- add Spring
authorymh <ymh.work@gmail.com>
Tue, 06 Nov 2012 13:23:19 +0100
changeset 45 37c9a17c3284
parent 43 90f6937c417e
child 46 7e132e2a48ca
- add Spring - add unit test
.classpath
.settings/org.eclipse.wst.common.component
client/js/models.js
server/pom.xml
server/src/main/java/org/iri_research/renkan/RenkanException.java
server/src/main/java/org/iri_research/renkan/coweb/RenkanSessionModerator.java
server/src/main/java/org/iri_research/renkan/coweb/SpringConfigurer.java
server/src/main/java/org/iri_research/renkan/coweb/event/AbstractSyncEventManager.java
server/src/main/java/org/iri_research/renkan/coweb/event/ISyncEventManager.java
server/src/main/java/org/iri_research/renkan/coweb/event/ProjectSyncEventManager.java
server/src/main/java/org/iri_research/renkan/coweb/server/RenkanCometdServlet.java
server/src/main/java/org/iri_research/renkan/db/MongoConnectionManager.java
server/src/main/java/org/iri_research/renkan/models/AbstractRenkanModel.java
server/src/main/java/org/iri_research/renkan/models/IRenkanModel.java
server/src/main/java/org/iri_research/renkan/models/Node.java
server/src/main/java/org/iri_research/renkan/models/Project.java
server/src/main/java/org/iri_research/renkan/models/Relation.java
server/src/main/java/org/iri_research/renkan/repositories/IRenkanRepository.java
server/src/main/java/org/iri_research/renkan/repositories/NodesRepository.java
server/src/main/java/org/iri_research/renkan/repositories/ProjectsRepository.java
server/src/main/java/org/iri_research/renkan/repositories/ProjectsRepositoryCustom.java
server/src/main/java/org/iri_research/renkan/repositories/ProjectsRepositoryImpl.java
server/src/main/java/org/iri_research/renkan/repositories/RelationsRepository.java
server/src/main/java/org/iri_research/renkan/repositories/RenkanRepository.java
server/src/main/java/org/iri_research/renkan/repositories/RenkanRepositoryException.java
server/src/main/java/org/iri_research/renkan/repositories/RenkanRepositoryFactory.java
server/src/main/java/org/iri_research/renkan/repositories/RenkanRepositoryFactoryBean.java
server/src/main/java/org/iri_research/renkan/rest/ProjectsResource.java
server/src/main/resources/_firebug/LICENSE
server/src/main/resources/_firebug/errorIcon.png
server/src/main/resources/_firebug/firebug.css
server/src/main/resources/_firebug/firebug.js
server/src/main/resources/_firebug/firebug.js.uncompressed.js
server/src/main/resources/_firebug/infoIcon.png
server/src/main/resources/_firebug/tab_lft_norm.png
server/src/main/resources/_firebug/tab_lft_over.png
server/src/main/resources/_firebug/tab_rgt_norm.png
server/src/main/resources/_firebug/tab_rgt_over.png
server/src/main/resources/_firebug/warningIcon.png
server/src/main/resources/log4j.xml
server/src/main/web-resources/_firebug/LICENSE
server/src/main/web-resources/_firebug/errorIcon.png
server/src/main/web-resources/_firebug/firebug.css
server/src/main/web-resources/_firebug/firebug.js
server/src/main/web-resources/_firebug/firebug.js.uncompressed.js
server/src/main/web-resources/_firebug/infoIcon.png
server/src/main/web-resources/_firebug/tab_lft_norm.png
server/src/main/web-resources/_firebug/tab_lft_over.png
server/src/main/web-resources/_firebug/tab_rgt_norm.png
server/src/main/web-resources/_firebug/tab_rgt_over.png
server/src/main/web-resources/_firebug/warningIcon.png
server/src/main/webapp/WEB-INF/applicationContext.xml
server/src/main/webapp/WEB-INF/mongo-config.xml
server/src/main/webapp/WEB-INF/web.xml
server/src/main/webapp/css/style.css
server/src/main/webapp/favicon.ico
server/src/main/webapp/js/config.js
server/src/main/webapp/js/corenkan.js
server/src/main/webapp/js/main_coweb.js
server/src/main/webapp/js/main_test_models.js
server/src/main/webapp/js/models.js
server/src/main/webapp/model-test.html
server/src/test/java/org/iri_research/renkan/test/repositories/ProjectsRepositoryTest.java
server/src/test/resources/log4j.xml
server/src/test/resources/org/iri_research/renkan/test/repositories/mongo-config.xml
server/src/test/resources/org/iri_research/renkan/test/repositories/repositories-context.xml
server/target/.keepme
--- a/.classpath	Tue Nov 13 11:46:39 2012 +0100
+++ b/.classpath	Tue Nov 06 13:23:19 2012 +0100
@@ -1,6 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <classpath>
 	<classpathentry kind="src" path="server/src/main/java"/>
+	<classpathentry kind="src" path="server/src/test/java"/>
 	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6">
 		<attributes>
 			<attribute name="owner.project.facets" value="java"/>
@@ -11,15 +12,29 @@
 	<classpathentry kind="var" path="M2_REPO/org/opencoweb/coweb-bots/0.8.3/coweb-bots-0.8.3.jar"/>
 	<classpathentry kind="var" path="M2_REPO/org/opencoweb/coweb-server/0.8.3/coweb-server-0.8.3.jar"/>
 	<classpathentry kind="var" path="M2_REPO/org/opencoweb/coweb-operationengine/0.8.3/coweb-operationengine-0.8.3.jar"/>
-	<classpathentry kind="var" path="M2_REPO/org/cometd/java/cometd-java-server/2.4.0/cometd-java-server-2.4.0.jar"/>
-	<classpathentry kind="var" path="M2_REPO/org/cometd/java/bayeux-api/2.4.0/bayeux-api-2.4.0.jar"/>
-	<classpathentry kind="var" path="M2_REPO/org/cometd/java/cometd-java-common/2.4.0/cometd-java-common-2.4.0.jar"/>
-	<classpathentry kind="var" path="M2_REPO/org/eclipse/jetty/jetty-util/7.6.0.v20120127/jetty-util-7.6.0.v20120127.jar"/>
-	<classpathentry kind="var" path="M2_REPO/org/slf4j/slf4j-api/1.6.4/slf4j-api-1.6.4.jar"/>
-	<classpathentry kind="var" path="M2_REPO/org/eclipse/jetty/jetty-continuation/7.6.0.v20120127/jetty-continuation-7.6.0.v20120127.jar"/>
-	<classpathentry kind="var" path="M2_REPO/org/eclipse/jetty/jetty-jmx/7.6.0.v20120127/jetty-jmx-7.6.0.v20120127.jar"/>
-	<classpathentry kind="var" path="M2_REPO/com/sun/jersey/jersey-server/1.13/jersey-server-1.13.jar"/>
-	<classpathentry kind="var" path="M2_REPO/com/sun/jersey/jersey-core/1.13/jersey-core-1.13.jar"/>
-	<classpathentry kind="var" path="M2_REPO/org/mongodb/mongo-java-driver/2.8.0/mongo-java-driver-2.8.0.jar"/>
+	<classpathentry kind="var" path="M2_REPO/org/cometd/java/bayeux-api/2.5.0/bayeux-api-2.5.0.jar"/>
+	<classpathentry kind="var" path="M2_REPO/org/cometd/java/cometd-java-common/2.5.0/cometd-java-common-2.5.0.jar"/>
+	<classpathentry kind="var" path="M2_REPO/org/eclipse/jetty/jetty-util/7.6.7.v20120910/jetty-util-7.6.7.v20120910.jar"/>
+	<classpathentry kind="var" path="M2_REPO/org/slf4j/slf4j-api/1.6.6/slf4j-api-1.6.6.jar"/>
+	<classpathentry kind="var" path="M2_REPO/org/eclipse/jetty/jetty-continuation/7.6.7.v20120910/jetty-continuation-7.6.7.v20120910.jar"/>
+	<classpathentry kind="var" path="M2_REPO/org/eclipse/jetty/jetty-jmx/7.6.7.v20120910/jetty-jmx-7.6.7.v20120910.jar"/>
+	<classpathentry kind="var" path="M2_REPO/com/sun/jersey/jersey-server/1.14/jersey-server-1.14.jar"/>
+	<classpathentry kind="var" path="M2_REPO/com/sun/jersey/jersey-core/1.14/jersey-core-1.14.jar"/>
+	<classpathentry kind="var" path="M2_REPO/org/mongodb/mongo-java-driver/2.9.0/mongo-java-driver-2.9.0.jar"/>
+	<classpathentry kind="var" path="M2_REPO/org/springframework/spring-context/3.1.2.RELEASE/spring-context-3.1.2.RELEASE.jar"/>
+	<classpathentry kind="var" path="M2_REPO"/>
+	<classpathentry kind="var" path="M2_REPO/org/springframework/spring-beans/3.1.2.RELEASE/spring-beans-3.1.2.RELEASE.jar"/>
+	<classpathentry kind="var" path="M2_REPO/javax/persistence/persistence-api/1.0.2/persistence-api-1.0.2.jar"/>
+	<classpathentry kind="var" path="M2_REPO/org/springframework/data/spring-data-mongodb/1.1.0.RELEASE/spring-data-mongodb-1.1.0.RELEASE.jar"/>
+	<classpathentry kind="var" path="M2_REPO/org/springframework/data/spring-data-commons-core/1.4.0.RELEASE/spring-data-commons-core-1.4.0.RELEASE.jar"/>
+	<classpathentry kind="var" path="M2_REPO/org/springframework/data/spring-data-jpa/1.2.0.RELEASE/spring-data-jpa-1.2.0.RELEASE.jar"/>
+	<classpathentry kind="var" path="M2_REPO/javax/inject/javax.inject/1/javax.inject-1.jar"/>
+	<classpathentry kind="var" path="M2_REPO/org/cometd/java/cometd-java-annotations/2.5.0/cometd-java-annotations-2.5.0.jar"/>
+	<classpathentry kind="var" path="M2_REPO/org/cometd/java/cometd-java-server/2.5.0/cometd-java-server-2.5.0.jar"/>
+	<classpathentry kind="var" path="M2_REPO/javax/servlet/servlet-api/2.5/servlet-api-2.5.jar"/>
+	<classpathentry kind="var" path="M2_REPO/org/springframework/spring-core/3.1.2.RELEASE/spring-core-3.1.2.RELEASE.jar"/>
+	<classpathentry kind="var" path="M2_REPO/org/springframework/spring-web/3.0.0.RC3/spring-web-3.0.0.RC3.jar"/>
+	<classpathentry kind="var" path="M2_REPO/junit/junit/4.10/junit-4.10.jar"/>
+	<classpathentry kind="var" path="M2_REPO/org/springframework/spring-test/3.1.2.RELEASE/spring-test-3.1.2.RELEASE.jar"/>
 	<classpathentry kind="output" path="server/target/classes"/>
 </classpath>
--- a/.settings/org.eclipse.wst.common.component	Tue Nov 13 11:46:39 2012 +0100
+++ b/.settings/org.eclipse.wst.common.component	Tue Nov 06 13:23:19 2012 +0100
@@ -1,8 +1,8 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project-modules id="moduleCoreId" project-version="1.5.0">
+<?xml version="1.0" encoding="UTF-8"?><project-modules id="moduleCoreId" project-version="1.5.0">
     <wb-module deploy-name="renkan">
         <wb-resource deploy-path="/" source-path="/server/src/main/webapp"/>
         <wb-resource deploy-path="/WEB-INF/classes" source-path="/server/src/main/java"/>
+        <wb-resource deploy-path="/WEB-INF/classes" source-path="/server/src/test/java"/>
         <property name="java-output-path" value="/server/target/classes"/>
         <property name="context-root" value="renkan"/>
     </wb-module>
--- a/client/js/models.js	Tue Nov 13 11:46:39 2012 +0100
+++ b/client/js/models.js	Tue Nov 06 13:23:19 2012 +0100
@@ -88,7 +88,7 @@
                 description: this.get("description"),
                 position: this.get("position"),
                 image: this.get("image"),
-                created_by: this.get("created_by").get("_id")
+                created_by: this.get("created_by") ? this.get("created_by").get("_id") : null
             };
         },
     });
@@ -126,9 +126,9 @@
                 title: this.get("title"),
                 uri: this.get("uri"),
                 description: this.get("description"),
-                from: this.get("from").get("_id"),
-                to: this.get("to").get("_id"),
-                created_by: this.get("created_by").get("_id"),
+                from: this.get("from") ? this.get("from").get("_id") : null,
+                to: this.get("to") ? this.get("to").get("_id") : null,
+                created_by: this.get("created_by") ? this.get("created_by").get("_id") : null
             };
         },
     });
--- a/server/pom.xml	Tue Nov 13 11:46:39 2012 +0100
+++ b/server/pom.xml	Tue Nov 06 13:23:19 2012 +0100
@@ -8,7 +8,10 @@
     <packaging>war</packaging>
 
     <properties>
-        <coweb-version>0.8.3</coweb-version>
+        <coweb-version>0.8.3.1</coweb-version>
+        <jersey-version>1.14</jersey-version>
+        <spring-version>3.1.2.RELEASE</spring-version>
+        <junit.version>4.10</junit.version>
         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
     </properties>
 
@@ -52,6 +55,16 @@
                             </excludes>
                             <targetPath>lib</targetPath>
                         </overlay>
+                        <overlay>
+                            <groupId>org.opencoweb.cowebx</groupId>
+                            <artifactId>cowebx-widgets-dojo</artifactId>
+                            <type>war</type>
+                            <excludes>
+                                <exclude>META-INF/**</exclude>
+                                <exclude>WEB-INF/**</exclude>
+                            </excludes>
+                            <targetPath>lib/cowebx/dojo</targetPath>
+                        </overlay>
                     </overlays>
                    <webResources>
                        <resource>
@@ -61,13 +74,42 @@
                                <exclude>**/data</exclude>
                            </excludes>
                        </resource>
+                       <resource>
+                           <directory>src/main/web-resources</directory>
+                       </resource>                       
                    </webResources>
                 </configuration>
             </plugin>
         </plugins>
     </build>
-
+    <repositories>
+        <repository>
+            <id>spring-maven-release</id>
+            <name>Spring Maven Release Repository</name>
+            <url>http://maven.springframework.org/release</url>
+        </repository>
+        <repository>
+            <id>spring-maven-milestone</id>
+            <name>Spring Maven MILESTONE Repository</name>
+            <url>http://maven.springframework.org/milestone</url>
+        </repository>
+    </repositories>
     <dependencies>
+        <dependency>  
+            <groupId>javax.inject</groupId>  
+            <artifactId>javax.inject</artifactId>  
+            <version>1</version>  
+        </dependency>
+        <dependency>
+            <groupId>javax.servlet</groupId>
+            <artifactId>servlet-api</artifactId>
+            <version>2.5</version>
+        </dependency>
+        <dependency>
+            <groupId>org.cometd.java</groupId>
+            <artifactId>cometd-java-annotations</artifactId>
+            <version>2.5.0</version>
+        </dependency>  
         <dependency>
             <groupId>org.opencoweb</groupId>
             <artifactId>coweb-bots</artifactId>
@@ -85,25 +127,91 @@
             <type>war</type>
         </dependency>
         <dependency>
+            <groupId>org.opencoweb.cowebx</groupId>
+            <artifactId>cowebx-widgets-dojo</artifactId>
+            <version>${coweb-version}</version>
+            <type>war</type>
+        </dependency>
+        <dependency>
         	<groupId>com.sun.jersey</groupId>
         	<artifactId>jersey-server</artifactId>
-        	<version>1.13</version>
+        	<version>${jersey-version}</version>
         </dependency>
         <dependency>
-            <groupId>com.sun.jersey</groupId>
-            <artifactId>jersey-servlet</artifactId>
-            <version>1.13</version>
+            <groupId>com.sun.jersey.contribs</groupId>
+            <artifactId>jersey-spring</artifactId>
+            <version>${jersey-version}</version>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.springframework</groupId>
+                    <artifactId>spring-context</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.springframework</groupId>
+                    <artifactId>spring-beans</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.springframework</groupId>
+                    <artifactId>spring-core</artifactId>
+                </exclusion>
+            </exclusions>
         </dependency>
         <dependency>
             <groupId>org.mongodb</groupId>
             <artifactId>mongo-java-driver</artifactId>
-            <version>2.8.0</version>
+            <version>2.9.0</version>
         </dependency>
         <dependency> 
             <groupId>org.slf4j</groupId>
             <artifactId>slf4j-log4j12</artifactId>
             <version>1.6.6</version>
         </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-core</artifactId>
+            <version>${spring-version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-context</artifactId>
+            <version>${spring-version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-web</artifactId>
+            <version>${spring-version}</version>
+        </dependency>        
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-test</artifactId>
+            <version>${spring-version}</version>
+        </dependency>        
+        <dependency>
+            <groupId>org.springframework.data</groupId>
+            <artifactId>spring-data-commons-core</artifactId>
+            <version>1.4.0.RELEASE</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.data</groupId>
+            <artifactId>spring-data-jpa</artifactId>
+            <version>1.2.0.RELEASE</version>
+        </dependency> 
+        <dependency>
+            <groupId>org.springframework.data</groupId>
+            <artifactId>spring-data-mongodb</artifactId>
+            <version>1.1.0.RELEASE</version>
+        </dependency>
+        <dependency>
+            <groupId>javax.persistence</groupId>
+            <artifactId>persistence-api</artifactId>  
+            <version>1.0.2</version>
+        </dependency>
+        <dependency>                          
+            <groupId>junit</groupId>           
+            <artifactId>junit</artifactId>     
+            <version>${junit.version}</version>
+            <scope>test</scope>                
+        </dependency>         
     </dependencies>
     <organization>
     	<name>IRI</name>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/main/java/org/iri_research/renkan/RenkanException.java	Tue Nov 06 13:23:19 2012 +0100
@@ -0,0 +1,25 @@
+package org.iri_research.renkan;
+
+public class RenkanException extends Exception {
+
+	/**
+	 * 
+	 */
+	private static final long serialVersionUID = -6952770322990047437L;
+
+	public RenkanException() {
+	}
+
+	public RenkanException(String message) {
+		super(message);
+	}
+
+	public RenkanException(Throwable exc) {
+		super(exc);
+	}
+
+	public RenkanException(String message, Throwable exc) {
+		super(message, exc);
+	}
+
+}
--- a/server/src/main/java/org/iri_research/renkan/coweb/RenkanSessionModerator.java	Tue Nov 13 11:46:39 2012 +0100
+++ b/server/src/main/java/org/iri_research/renkan/coweb/RenkanSessionModerator.java	Tue Nov 06 13:23:19 2012 +0100
@@ -1,20 +1,72 @@
 package org.iri_research.renkan.coweb;
 
+//import java.util.HashMap;
 import java.util.Map;
 
+import javax.inject.Named;
+
 import org.coweb.DefaultSessionModerator;
+import org.iri_research.renkan.coweb.event.ISyncEventManager;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.springframework.context.ApplicationContext;
+//import javax.inject.Inject;
 
+@Named
 public class RenkanSessionModerator extends DefaultSessionModerator {
 	
-	private final Logger logger = LoggerFactory.getLogger(RenkanSessionModerator.class); 
-	
+	private final Logger logger = LoggerFactory.getLogger(RenkanSessionModerator.class);
+		
+	@SuppressWarnings("unchecked")
 	@Override
 	public boolean onSync(Map<String, Object> data) {
+				
+		this.logger.debug("Debugging onSync : " + data.toString());
+		this.logger.debug("Debugging onSync channel: " + data.get("channel"));
+		this.logger.debug("Debugging onSync type: " + data.get("type"));
+		this.logger.debug("Debugging onSync site: " + data.get("site"));
+		this.logger.debug("Debugging onSync value: " + data.get("value"));
+		this.logger.debug("Debugging onSync position: " + data.get("position"));
+				
+		Map<String, Object> values = null;
+		if(data.containsKey("value") && data.get("value") != null) {
+			values = ((Map<String, Object>) data.get("value"));
+		}
 		
-		this.logger.debug("Debugging onSync : "  + data.toString());
-		return super.onSync(data);
+		if(values == null) {
+			this.logger.warn("onSync : no values in message.");
+			return super.onSync(data);		
+		}
+		
+		String sync_type = (String) values.get("type");
+		if(sync_type == null || sync_type.length() == 0) {
+			this.logger.warn("onSync : no type in value of message.");
+			return super.onSync(data);
+		}
+		
+		//String className = String.format("org.iri_research.renkan.coweb.event.%sSyncEventManager", sync_type.substring(0, 1).toUpperCase()+sync_type.substring(1));
+		String beanName = String.format("%sSyncEventManager", sync_type.toLowerCase());
+		boolean resDispatch = false; 
+		
+		try {
+			
+			ApplicationContext context = SpringConfigurer.getInstance().getApplicationContext();
+			ISyncEventManager eventManager = (ISyncEventManager)context.getBean(beanName);
+			logger.debug("Debugging on Sync : dispatch to " + beanName);
+			resDispatch = eventManager.dispatchEvent(data);
+		}
+		catch(Throwable e) {
+			this.logger.error(String.format("onSync EventManagerClass %s not found : error : %s", sync_type, e.getMessage()));
+		}
+		/*catch (ClassNotFoundException e) {
+			this.logger.error(String.format("onSync EventManagerClass %s not found : ClassNotFoundException : %s", sync_type, e.getMessage()));
+		} catch (InstantiationException e) {
+			this.logger.error(String.format("onSync EventManagerClass %s not found : InstantiationException : %s", sync_type, e.getMessage()));
+		} catch (IllegalAccessException e) {
+			this.logger.error(String.format("onSync EventManagerClass %s not found : IllegalAccessException : %s", sync_type, e.getMessage()));
+		}*/
+		
+		return super.onSync(data) && resDispatch;
 	}
 
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/main/java/org/iri_research/renkan/coweb/SpringConfigurer.java	Tue Nov 06 13:23:19 2012 +0100
@@ -0,0 +1,106 @@
+package org.iri_research.renkan.coweb;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.annotation.PostConstruct;
+import javax.inject.Inject;
+import javax.servlet.ServletContext;
+
+import org.cometd.annotation.ServerAnnotationProcessor;
+import org.cometd.bayeux.server.BayeuxServer;
+import org.cometd.server.BayeuxServerImpl;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.config.DestructionAwareBeanPostProcessor;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+import org.springframework.context.annotation.Bean;
+import org.springframework.web.context.ServletContextAware;
+
+//@Component
+//@Scope("prototype")
+public class SpringConfigurer implements DestructionAwareBeanPostProcessor, ServletContextAware, ApplicationContextAware
+{
+	
+    private BayeuxServer bayeuxServer;
+    private ServerAnnotationProcessor processor;
+    private final Logger logger = LoggerFactory.getLogger(SpringConfigurer.class);
+    private ApplicationContext context;
+    
+    private static volatile SpringConfigurer instance = null;
+        
+    private SpringConfigurer() 
+    {
+    	this.logger.debug("Buiding SpringCond=figurer");    	
+    }
+    
+    public static SpringConfigurer getInstance() {
+    	if (instance == null) {
+    		synchronized (SpringConfigurer.class) {
+				if(instance == null) {
+					instance = new SpringConfigurer();
+				}
+			}
+    	}
+    	return instance;
+    }
+
+    @Inject
+    private void setBayeuxServer(BayeuxServer bayeuxServer)
+    {
+        this.bayeuxServer = bayeuxServer;
+    }
+
+    @PostConstruct
+    private void init()
+    {
+        this.processor = new ServerAnnotationProcessor(bayeuxServer);
+    }
+
+    public Object postProcessBeforeInitialization(Object bean, String name) throws BeansException
+    {
+        processor.processDependencies(bean);
+        processor.processConfigurations(bean);
+        processor.processCallbacks(bean);
+        return bean;
+    }
+
+    public Object postProcessAfterInitialization(Object bean, String name) throws BeansException
+    {
+        return bean;
+    }
+
+    public void postProcessBeforeDestruction(Object bean, String name) throws BeansException
+    {
+        processor.deprocessCallbacks(bean);
+    }
+
+    @Bean(initMethod = "start", destroyMethod = "stop")
+    public BayeuxServer bayeuxServer()
+    {
+        BayeuxServerImpl bean = new BayeuxServerImpl();
+        Map<String, Object> options = new HashMap<String, Object>();
+        options.put(BayeuxServerImpl.LOG_LEVEL, "3");
+        options.put("timeout", "1500");
+        bean.setOptions(options);
+        return bean;
+    }
+
+    public void setServletContext(ServletContext servletContext)
+    {
+        servletContext.setAttribute(BayeuxServer.ATTRIBUTE, bayeuxServer);
+    }
+
+	@Override
+	@Inject
+	public void setApplicationContext(ApplicationContext context)
+			throws BeansException {
+		this.context = context;
+	}
+	
+	public ApplicationContext getApplicationContext() {
+		return this.context;
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/main/java/org/iri_research/renkan/coweb/event/AbstractSyncEventManager.java	Tue Nov 06 13:23:19 2012 +0100
@@ -0,0 +1,47 @@
+package org.iri_research.renkan.coweb.event;
+
+import java.util.Map;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+public abstract class AbstractSyncEventManager implements ISyncEventManager {
+
+	private final Logger logger = LoggerFactory.getLogger(AbstractSyncEventManager.class);
+	
+	@Override
+	public boolean dispatchEvent(Map<String, Object> data) {
+
+		String eventType = (String) data.get("type");
+		
+		if("null".equalsIgnoreCase(eventType)) {
+			return this.nullOperation(data);
+		}
+		else if ("update".equalsIgnoreCase(eventType)) {
+			return this.update(data);
+		}
+		else if ("insert".equalsIgnoreCase(eventType)) {
+			return this.insert(data);
+		}
+		else if("delete".equalsIgnoreCase(eventType)) {
+			return this.delete(data);
+		}
+		
+		logger.warn(String.format("dispatchEvent : eventType unknown %s", eventType));
+		return false;
+	}
+
+	@Override
+	public abstract boolean update(Map<String, Object> data);
+
+	@Override
+	public abstract boolean insert(Map<String, Object> data);
+
+	@Override
+	public abstract boolean delete(Map<String, Object> data);
+
+	@Override
+	public abstract boolean nullOperation(Map<String, Object> data);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/main/java/org/iri_research/renkan/coweb/event/ISyncEventManager.java	Tue Nov 06 13:23:19 2012 +0100
@@ -0,0 +1,14 @@
+package org.iri_research.renkan.coweb.event;
+
+import java.util.Map;
+
+public interface ISyncEventManager {
+	
+	public boolean dispatchEvent(Map<String, Object> data);
+
+	public boolean update(Map<String, Object> data);
+	public boolean insert(Map<String, Object> data);
+	public boolean delete(Map<String, Object> data);
+	public boolean nullOperation(Map<String, Object> data);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/main/java/org/iri_research/renkan/coweb/event/ProjectSyncEventManager.java	Tue Nov 06 13:23:19 2012 +0100
@@ -0,0 +1,118 @@
+/**
+ * 
+ */
+package org.iri_research.renkan.coweb.event;
+
+import java.util.Map;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+
+import org.coweb.CowebException;
+import org.iri_research.renkan.repositories.ProjectsRepository;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.mongodb.BasicDBObject;
+import com.mongodb.DBCollection;
+import com.mongodb.DBObject;
+import com.mongodb.WriteResult;
+
+/**
+ * @author ymh
+ *
+ */
+@Named
+public class ProjectSyncEventManager extends AbstractSyncEventManager {
+
+	private final Logger logger = LoggerFactory.getLogger(ProjectSyncEventManager.class);
+	
+	@Inject
+	private ProjectsRepository projectsRepository;
+	
+	private DBCollection getCollection() {		
+		return this.projectsRepository.getCollection();
+	}
+	
+	/* Update a project
+	 * @see org.iri_research.renkan.coweb.event.AbstractSyncEventManager#update(java.util.Map)
+	 */
+	@Override
+	public boolean update(Map<String, Object> data) {
+		
+		this.logger.debug("ProjectSyncEventManager: update project");
+		
+		@SuppressWarnings("unchecked")
+		Map<String, Object> values = (Map<String, Object>) data.get("value");
+		String project_id = (String) values.get("id");
+		
+		// get project
+		this.logger.debug(String.format("update project %s", project_id));
+		try {
+			this.logger.debug(String.format("rev Counter %d", projectsRepository.getRevCounter(project_id)));
+		}
+		catch(Exception e){
+			this.logger.error("Bad rev counter",e);
+		}
+		
+		DBCollection projectCollection = this.getCollection();
+		DBObject project = projectCollection.findOne(project_id);
+		
+		if (null == project) {
+			throw new CowebException("Project not found", String.format("Project %s not found", project_id));
+		}
+		
+		boolean project_changed = false;
+		// update project
+		for (String fieldname : values.keySet()) {
+			if(!"id".equalsIgnoreCase(fieldname) && project.containsField(fieldname))
+			{
+				Object new_value = values.get(fieldname);
+				Object old_value = project.get(fieldname);
+				if((new_value == null && old_value != null) || (new_value != null && !new_value.equals(old_value))) {
+					project.put(fieldname, new_value);
+					project_changed = true;
+				}
+			}
+		}
+		
+		if(project_changed) {
+			project.put("_id", project_id);
+			WriteResult res = projectCollection.update(new BasicDBObject("_id", project_id), project, true, false);
+			
+			if(!res.getLastError().ok()) {
+				throw new CowebException(String.format("Error when writing project %s", project_id), res.getLastError().getErrorMessage()); 
+			}
+
+		}
+		return false;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.iri_research.renkan.coweb.event.AbstractSyncEventManager#insert(java.util.Map)
+	 */
+	@Override
+	public boolean insert(Map<String, Object> data) {
+		// do nothing
+		return false;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.iri_research.renkan.coweb.event.AbstractSyncEventManager#delete(java.util.Map)
+	 */
+	@Override
+	public boolean delete(Map<String, Object> data) {
+		// do nothing
+		return false;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.iri_research.renkan.coweb.event.AbstractSyncEventManager#nullOperation(java.util.Map)
+	 */
+	@Override
+	public boolean nullOperation(Map<String, Object> data) {
+		// do nothing
+		return false;
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/main/java/org/iri_research/renkan/coweb/server/RenkanCometdServlet.java	Tue Nov 06 13:23:19 2012 +0100
@@ -0,0 +1,28 @@
+package org.iri_research.renkan.coweb.server;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+
+import org.cometd.bayeux.server.BayeuxServer;
+import org.cometd.server.BayeuxServerImpl;
+import org.cometd.server.CometdServlet;
+
+@Named
+public class RenkanCometdServlet extends CometdServlet {
+
+	/**
+	 * 
+	 */
+	private static final long serialVersionUID = -5362140618261972254L;
+	
+	@Inject
+	private BayeuxServer _bayeux;
+	
+	@Override
+	protected BayeuxServerImpl newBayeuxServer()
+    {
+        return (BayeuxServerImpl)_bayeux;
+    }
+
+
+}
--- a/server/src/main/java/org/iri_research/renkan/db/MongoConnectionManager.java	Tue Nov 13 11:46:39 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,51 +0,0 @@
-/**
- * 
- */
-package org.iri_research.renkan.db;
-
-import java.net.UnknownHostException;
-
-import com.mongodb.DB;
-import com.mongodb.Mongo;
-import com.mongodb.MongoException;
-
-/**
- * This singleton class manage the mongo connection.
- * This class is thread safe
- * The singleton class is implemented following this example : http://en.wikipedia.org/wiki/Singleton_pattern#The_solution_of_Bill_Pugh
- * @author ymh
- *
- */
-public class MongoConnectionManager {
-
-	//TODO: add application parameters
-	public static final String HOST = "127.0.0.1";
-	public static final int PORT = 27017;
-	public static final String NAME = "renkan";
-	
-	private Mongo mongo = null;
-	private DB db = null;
-	
-	public DB getDb() throws UnknownHostException, MongoException {
-		if(null == this.db) {
-			this.mongo = new Mongo(HOST, PORT);
-			this.db = this.mongo.getDB(NAME);
-		}
-		return db;
-	}
-
-	// Private constructor suppresses generation
-	//  of a (public) default constructor
-	private MongoConnectionManager() {}
-	
-	private static class SingletonHolder {
-		public static final MongoConnectionManager INSTANCE = new MongoConnectionManager();
-	}
-	
-	public static MongoConnectionManager getInstance() {
-		return SingletonHolder.INSTANCE;
-	}
-	
-	
-	
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/main/java/org/iri_research/renkan/models/AbstractRenkanModel.java	Tue Nov 06 13:23:19 2012 +0100
@@ -0,0 +1,44 @@
+package org.iri_research.renkan.models;
+
+import java.io.Serializable;
+
+
+public abstract class AbstractRenkanModel<ID extends Serializable> implements IRenkanModel<ID> {
+	
+	public AbstractRenkanModel(ID id, String title, String description, String uri) {
+		super();
+		this.id = id;
+		this.title = title;
+		this.description = description;
+		this.uri = uri;
+	}
+	
+	protected AbstractRenkanModel() {		
+	}
+
+	protected ID id;
+	protected String title;
+	protected String description;
+	protected String uri;
+	
+	@Override
+	public String getTitle() {
+		return this.title;
+	}
+
+	@Override
+	public String getDescription() {
+		return this.description;
+	}
+
+	@Override
+	public String getUri() {
+		return this.uri;
+	}
+	
+	@Override
+	public ID getId() {
+		return this.id;
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/main/java/org/iri_research/renkan/models/IRenkanModel.java	Tue Nov 06 13:23:19 2012 +0100
@@ -0,0 +1,13 @@
+package org.iri_research.renkan.models;
+
+import java.io.Serializable;
+
+
+public interface IRenkanModel<ID extends Serializable> {
+	
+	public ID getId(); 
+	public String getTitle();
+	public String getDescription();
+	public String getUri();
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/main/java/org/iri_research/renkan/models/Node.java	Tue Nov 06 13:23:19 2012 +0100
@@ -0,0 +1,19 @@
+package org.iri_research.renkan.models;
+
+import org.springframework.data.mongodb.core.mapping.DBRef;
+import org.springframework.data.mongodb.core.mapping.Document;
+
+@Document(collection="nodes")
+public class Node extends AbstractRenkanModel<String> {
+
+
+	public Node(String id, String title, String description, String uri, Project project) {
+		super(id, title, description, uri);
+		
+		this.project = project;
+	}	
+	
+	@DBRef
+	private Project project = null;	
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/main/java/org/iri_research/renkan/models/Project.java	Tue Nov 06 13:23:19 2012 +0100
@@ -0,0 +1,33 @@
+package org.iri_research.renkan.models;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.data.mongodb.core.mapping.Document;
+
+@Document(collection="projects")
+public class Project extends AbstractRenkanModel<String> {
+	
+	@SuppressWarnings("unused")
+	private static Logger logger = LoggerFactory.getLogger(Project.class); 
+			
+	private int revCounter = 1;
+	
+	public Project(String id, String title, String description, String uri,
+			int revCounter) {
+		super(id,title, description, uri);
+		this.revCounter = revCounter;
+	}
+
+	public Project(String id, String title, String description, String uri) {
+		this(id,title, description, uri, 1);
+	}
+	
+	@SuppressWarnings("unused")
+	private Project() {		
+	}
+	
+	public int getRevCounter() {
+		return revCounter;
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/main/java/org/iri_research/renkan/models/Relation.java	Tue Nov 06 13:23:19 2012 +0100
@@ -0,0 +1,22 @@
+package org.iri_research.renkan.models;
+
+import org.springframework.data.mongodb.core.mapping.DBRef;
+import org.springframework.data.mongodb.core.mapping.Document;
+
+
+@Document(collection="relations")
+public class Relation extends AbstractRenkanModel<String> {
+
+	@DBRef
+	private Node srcNode;
+	
+	@DBRef
+	private Node tgtNode;
+
+	public Relation(String id, String title, String description, String uri, Node srcNode, Node tgtNode) {
+		super(id,title, description, uri);
+		this.srcNode = srcNode;
+		this.tgtNode = tgtNode;				
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/main/java/org/iri_research/renkan/repositories/IRenkanRepository.java	Tue Nov 06 13:23:19 2012 +0100
@@ -0,0 +1,13 @@
+package org.iri_research.renkan.repositories;
+
+import java.io.Serializable;
+
+import org.springframework.data.repository.CrudRepository;
+
+import com.mongodb.DBCollection;
+
+public interface IRenkanRepository<T, ID extends Serializable> extends
+		CrudRepository<T, ID> {
+
+	public DBCollection getCollection();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/main/java/org/iri_research/renkan/repositories/NodesRepository.java	Tue Nov 06 13:23:19 2012 +0100
@@ -0,0 +1,8 @@
+package org.iri_research.renkan.repositories;
+
+import org.iri_research.renkan.models.Node;
+import org.springframework.data.repository.CrudRepository;
+
+public interface NodesRepository extends CrudRepository<Node, String> {
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/main/java/org/iri_research/renkan/repositories/ProjectsRepository.java	Tue Nov 06 13:23:19 2012 +0100
@@ -0,0 +1,7 @@
+package org.iri_research.renkan.repositories;
+
+import org.iri_research.renkan.models.Project;
+
+public interface ProjectsRepository extends IRenkanRepository<Project, String>, ProjectsRepositoryCustom {
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/main/java/org/iri_research/renkan/repositories/ProjectsRepositoryCustom.java	Tue Nov 06 13:23:19 2012 +0100
@@ -0,0 +1,5 @@
+package org.iri_research.renkan.repositories;
+
+public interface ProjectsRepositoryCustom {
+	public int getRevCounter(String projectId);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/main/java/org/iri_research/renkan/repositories/ProjectsRepositoryImpl.java	Tue Nov 06 13:23:19 2012 +0100
@@ -0,0 +1,27 @@
+package org.iri_research.renkan.repositories;
+
+import org.iri_research.renkan.models.Project;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.mongodb.core.MongoTemplate;
+import org.springframework.stereotype.Component;
+import static org.springframework.data.mongodb.core.query.Query.query;
+import static org.springframework.data.mongodb.core.query.Criteria.where;
+import org.springframework.data.mongodb.core.query.Update;
+
+@Component
+public class ProjectsRepositoryImpl implements ProjectsRepositoryCustom {	
+	
+	@Autowired
+	private MongoTemplate mongoTemplate;
+	
+	@Override
+	public int getRevCounter(String projectId)  {		
+		Project p = this.mongoTemplate.findAndModify(query(where("id").is(projectId)), new Update().inc("revCounter", 1), Project.class);
+		
+		if(p == null) {
+			return -1;
+		}
+		return p.getRevCounter();
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/main/java/org/iri_research/renkan/repositories/RelationsRepository.java	Tue Nov 06 13:23:19 2012 +0100
@@ -0,0 +1,8 @@
+package org.iri_research.renkan.repositories;
+
+import org.iri_research.renkan.models.Relation;
+import org.springframework.data.repository.CrudRepository;
+
+public interface RelationsRepository extends CrudRepository<Relation, String> {
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/main/java/org/iri_research/renkan/repositories/RenkanRepository.java	Tue Nov 06 13:23:19 2012 +0100
@@ -0,0 +1,23 @@
+package org.iri_research.renkan.repositories;
+
+import java.io.Serializable;
+
+import org.springframework.data.mongodb.core.MongoOperations;
+import org.springframework.data.mongodb.repository.query.MongoEntityInformation;
+import org.springframework.data.mongodb.repository.support.SimpleMongoRepository;
+
+import com.mongodb.DBCollection;
+
+public class RenkanRepository<T, ID extends Serializable> extends SimpleMongoRepository<T, ID> implements
+		IRenkanRepository<T, ID> {
+
+	public RenkanRepository(MongoEntityInformation<T,ID> metadata,
+			MongoOperations mongoOperations) {
+		super(metadata, mongoOperations);
+	}
+
+	@Override
+	public DBCollection getCollection() {		
+		return this.getMongoOperations().getCollection(this.getEntityInformation().getCollectionName());
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/main/java/org/iri_research/renkan/repositories/RenkanRepositoryException.java	Tue Nov 06 13:23:19 2012 +0100
@@ -0,0 +1,11 @@
+package org.iri_research.renkan.repositories;
+
+public class RenkanRepositoryException extends Exception {
+
+	private static final long serialVersionUID = -7433823426870169568L;
+	
+	public RenkanRepositoryException(String message) {
+		super(message);
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/main/java/org/iri_research/renkan/repositories/RenkanRepositoryFactory.java	Tue Nov 06 13:23:19 2012 +0100
@@ -0,0 +1,50 @@
+package org.iri_research.renkan.repositories;
+
+import java.io.Serializable;
+
+import org.springframework.data.mongodb.core.MongoOperations;
+import org.springframework.data.mongodb.repository.query.MongoEntityInformation;
+import org.springframework.data.mongodb.repository.support.MongoRepositoryFactory;
+import org.springframework.data.mongodb.repository.support.SimpleMongoRepository;
+import org.springframework.data.repository.core.RepositoryMetadata;
+
+public class RenkanRepositoryFactory extends MongoRepositoryFactory {
+
+	private MongoOperations mongoOperations;
+	public RenkanRepositoryFactory(MongoOperations mongoOperations) {
+		super(mongoOperations);
+		this.mongoOperations = mongoOperations;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * @see org.springframework.data.repository.core.support.RepositoryFactorySupport#getTargetRepository(org.springframework.data.repository.core.RepositoryMetadata)
+	 */
+	@Override
+	@SuppressWarnings({ "rawtypes", "unchecked" })
+	protected Object getTargetRepository(RepositoryMetadata metadata) {
+		
+		Object res = super.getTargetRepository(metadata);
+				
+		if(SimpleMongoRepository.class.equals(res.getClass())) {
+			MongoEntityInformation<?, Serializable> entityInformation = this.getEntityInformation(metadata.getDomainType());			
+			return new RenkanRepository(entityInformation, this.mongoOperations);
+		}
+		else {
+			return res;
+		}
+
+	}
+	
+	@Override
+	protected Class<?> getRepositoryBaseClass(RepositoryMetadata metadata) {
+		Class<?> res = super.getRepositoryBaseClass(metadata);
+		if(SimpleMongoRepository.class.equals(res)) {
+			return RenkanRepository.class;
+		}
+		else {
+			return res;
+		}
+	}
+	
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/main/java/org/iri_research/renkan/repositories/RenkanRepositoryFactoryBean.java	Tue Nov 06 13:23:19 2012 +0100
@@ -0,0 +1,17 @@
+package org.iri_research.renkan.repositories;
+
+import java.io.Serializable;
+
+import org.springframework.data.mongodb.core.MongoOperations;
+import org.springframework.data.mongodb.repository.support.MongoRepositoryFactoryBean;
+import org.springframework.data.repository.Repository;
+import org.springframework.data.repository.core.support.RepositoryFactorySupport;
+
+public class RenkanRepositoryFactoryBean<T extends Repository<S,ID>,S,ID extends Serializable> extends MongoRepositoryFactoryBean<T,S,ID> {
+	
+	@Override
+	protected RepositoryFactorySupport getFactoryInstance(MongoOperations operations) {
+		return new RenkanRepositoryFactory(operations);
+	}
+	
+}
\ No newline at end of file
--- a/server/src/main/java/org/iri_research/renkan/rest/ProjectsResource.java	Tue Nov 13 11:46:39 2012 +0100
+++ b/server/src/main/java/org/iri_research/renkan/rest/ProjectsResource.java	Tue Nov 06 13:23:19 2012 +0100
@@ -1,9 +1,11 @@
 package org.iri_research.renkan.rest;
 
-import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.List;
 import java.util.UUID;
 
 import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
 import javax.ws.rs.GET;
 import javax.ws.rs.POST;
 import javax.ws.rs.PUT;
@@ -17,43 +19,36 @@
 import javax.ws.rs.core.Response.Status;
 import javax.ws.rs.core.UriInfo;
 
-import org.iri_research.renkan.db.MongoConnectionManager;
+import org.iri_research.renkan.repositories.ProjectsRepository;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
 
 import com.mongodb.BasicDBObject;
-import com.mongodb.DB;
 import com.mongodb.DBCollection;
+import com.mongodb.DBCursor;
 import com.mongodb.DBObject;
-import com.mongodb.MongoException;
 import com.mongodb.WriteResult;
 import com.mongodb.util.JSON;
 import com.sun.jersey.spi.resource.Singleton;
 
+
 @Singleton
 @Path("projects")
+@Component
 public class ProjectsResource {
 	
-	private Logger logger = LoggerFactory.getLogger(ProjectsResource.class); 
+	private Logger logger = LoggerFactory.getLogger(ProjectsResource.class);
+	
+	@Autowired
+	private ProjectsRepository projectRepository;
 	
 	@Context
 	private UriInfo uriInfo;
-	
-	private DB getDb() {
-		DB db = null;
-		try {
-			db = MongoConnectionManager.getInstance().getDb();
-		} catch (UnknownHostException e) {
-			throw new WebApplicationException(e, Status.INTERNAL_SERVER_ERROR);
-		} catch (MongoException e) {
-			throw new WebApplicationException(e, Status.INTERNAL_SERVER_ERROR);
-		}
-		return db;
-	}
-	
+		
 	private DBCollection getCollection() {		
-		DB db = this.getDb();
-		return db.getCollection("projects");
+		return projectRepository.getCollection();
 	}
 
 	@GET
@@ -62,7 +57,7 @@
 	public String getProject(@PathParam("id") String projectId) {
 		
 		this.logger.debug("GetProject : id " + projectId);
-		
+				
 		DBCollection projectCollection = this.getCollection();
 		DBObject project = projectCollection.findOne(projectId);
 		
@@ -70,121 +65,32 @@
 			throw new WebApplicationException(Status.NOT_FOUND);
 		}
 		
-		return project.toString();
-				
-		/*return "{" +
-    "\"title\": \"Test Graph\"," +
-    "\"creation_date\": \"2012-07-25T11:00:00.0Z\"," +
-    "\"users\": [" +
-    "{" +
-    "\"id\": \"u-cybunk\"," +
-    "\"title\": \"Samuel\"," +
-    "\"uri\": \"http://twitter.com/cybunk\"," +
-    "\"color\": \"#e00000\"" +
-    "}," +
-    "{" +
-    "\"id\": \"u-raphv\"," +
-    "\"title\": \"Raphael\"," +
-    "\"uri\": \"http://twitter.com/raphv\"," +
-    "\"color\": \"#00a000\"" +
-    "}" +
-    "]," +
-    "\"nodes\": [" +
-    "{" +
-    "\"id\": \"n-001\"," +
-    "\"title\": \"連環 (Renkan)\"," +
-    "\"uri\": \"http://ja.wikipedia.org/wiki/%E7%99%BE%E5%AD%A6%E9%80%A3%E7%92%B0\"," +
-    "\"created_by\": \"u-cybunk\"," +
-    "\"position\": {" +
-        "\"x\": 0," +
-        "\"y\": 0" +
-    "}" +
-    "}," +
-    "{" +
-    "\"id\": \"n-002\"," +
-    "\"title\": \"Savoir\"," +
-    "\"uri\": \"http://fr.wikipedia.org/wiki/Savoir\"," +
-    "\"created_by\": \"u-raphv\"," +
-    "\"position\": {" +
-        "\"x\": 200," +
-        "\"y\": 50" +
-    "}" +
-    "}," +
-    "{" +
-    "\"id\": \"n-003\"," +
-    "\"title\": \"Connaissance\","+
-    "\"uri\": \"http://fr.wikipedia.org/wiki/Connaissance\","+
-    "\"created_by\": \"u-raphv\","+
-    "\"position\": {"+
-        "\"x\": 300,"+
-            "\"y\": -50"+
-        "}"+
-    "},"+
-    "{"+
-        "\"id\": \"n-004\","+
-        "\"title\": \"graphe\","+
-        "\"uri\": \"http://fr.wikipedia.org/wiki/Th%C3%A9orie_des_graphes\","+
-        "\"created_by\": \"u-cybunk\","+
-        "\"position\": {"+
-            "\"x\": -200,"+
-            "\"y\": 0"+
-        "}"+
-    "},"+
-    "{"+
-        "\"id\": \"n-005\","+
-        "\"title\": \"nœud\","+
-        "\"uri\": \"http://fr.wikipedia.org/wiki/Th%C3%A9orie_des_graphes\","+
-        "\"created_by\": \"u-cybunk\","+
-        "\"position\": {"+
-            "\"x\": -350,"+
-            "\"y\": 100"+
-        "}"+
-    "},"+
-    "{"+
-        "\"id\": \"n-006\","+
-        "\"title\": \"lien\","+
-        "\"uri\": \"http://fr.wikipedia.org/wiki/Th%C3%A9orie_des_graphes\","+
-        "\"created_by\": \"u-cybunk\","+
-        "\"position\": {"+
-            "\"x\": -300,"+
-            "\"y\": -100"+
-        "}"+
-    "}"+
-    "],"+
-    "\"edges\": ["+
-    "{"+
-        "\"id\": \"e-001\","+
-        "\"from\": \"n-001\","+
-        "\"to\": \"n-002\","+
-        "\"created_by\": \"u-raphv\""+
-    "},"+
-    "{"+
-        "\"id\": \"e-002\","+
-        "\"from\": \"n-002\","+
-        "\"to\": \"n-003\","+
-        "\"created_by\": \"u-raphv\""+
-    "},"+
-    "{"+
-        "\"id\": \"e-003\","+
-        "\"from\": \"n-001\","+
-        "\"to\": \"n-004\","+
-        "\"created_by\": \"u-cybunk\""+
-    "},"+
-    "{"+
-        "\"id\": \"e-004\","+
-        "\"from\": \"n-004\","+
-        "\"to\": \"n-005\","+
-        "\"created_by\": \"u-cybunk\""+
-    "},"+
-    "{"+
-        "\"id\": \"e-005\","+
-        "\"from\": \"n-004\","+
-        "\"to\": \"n-006\","+
-        "\"created_by\": \"u-cybunk\""+
-    "}"+
-    "]"+
-    "}";*/
+		return project.toString();				
 	}
+	
+	@DELETE
+	@Path("{id : [a-zA-Z\\-0-9]+}")
+	@Produces(MediaType.TEXT_PLAIN + ";charset=utf-8")
+	public Response deleteProject(@PathParam("id") String projectId) {
+		
+		this.logger.debug("DeleteProject : id " + projectId);
+		DBCollection projectCollection = this.getCollection();
+		BasicDBObject filter = new BasicDBObject("_id", projectId);
+		WriteResult res = projectCollection.remove(filter);
+		
+		if(res.getLastError().ok()) {
+			if(res.getN() == 0) {
+				return Response.noContent().build();
+			}
+			else {
+				return Response.ok(this.uriInfo.getAbsolutePathBuilder().segment(projectId).build().toString() + " deleted").build();
+			}
+		}
+		else {
+			throw new WebApplicationException(Response.status(Status.BAD_REQUEST).entity(res.getError()).build());
+		}
+	}
+
 
 	/**
 	 * test: curl -i -X PUT -H 'Content-Type: application/json' -d @test-data.json  http://localhost:8080/renkan/rest/projects/12eff140-e65c-11e1-aff1-0800200c9a66
@@ -193,20 +99,66 @@
 	 */
 	@PUT
 	@Path("{id : [a-zA-Z\\-0-9]+}")
-	@Consumes(MediaType.APPLICATION_JSON)
+	@Consumes(MediaType.APPLICATION_JSON + ";charset=utf-8")
 	public Response putProject(@PathParam("id") String projectId, String projectContent) {
 		
 		return this.createOrUpdateProject(projectId, projectContent);		
 	}
 
 	@POST
-	@Consumes(MediaType.APPLICATION_JSON)
+	@Consumes(MediaType.APPLICATION_JSON + ";charset=utf-8")
 	public Response postProject(String projectContent) {
 		
 		return this.createOrUpdateProject(null, projectContent);
 		
 	}
 	
+	@GET
+	@Produces(MediaType.APPLICATION_JSON + ";charset=utf-8")
+	public String getProjectList() {
+		
+		DBCollection projectCollection = this.getCollection();
+		BasicDBObject keys = new BasicDBObject();
+		keys.put("description", 1);
+		keys.put("title", 1);
+		keys.put("uri", 1);
+		DBCursor cursor = projectCollection.find(new BasicDBObject(), keys);
+		
+		List<DBObject> res = new ArrayList<DBObject>();
+				
+		try {
+			while(cursor.hasNext()) {
+				DBObject obj = cursor.next();
+				DBObject links = new BasicDBObject();
+				
+				DBObject linkdef = new BasicDBObject();
+				linkdef.put("href", this.uriInfo.getAbsolutePathBuilder().path(obj.get("_id").toString()).build().toString());
+				linkdef.put("method", "get");
+				linkdef.put("produces", MediaType.APPLICATION_JSON + ";charset=utf-8");				
+				links.put("view", linkdef);
+				
+				linkdef = new BasicDBObject();
+				linkdef.put("href", this.uriInfo.getAbsolutePathBuilder().path(obj.get("_id").toString()).build().toString());
+				linkdef.put("method", "put");
+				linkdef.put("consumes", MediaType.APPLICATION_JSON + ";charset=utf-8");				
+				links.put("update", linkdef);
+
+				linkdef = new BasicDBObject();
+				linkdef.put("href", this.uriInfo.getAbsolutePathBuilder().path(obj.get("_id").toString()).build().toString());
+				linkdef.put("method", "delete");
+				links.put("delete", linkdef);				
+				
+				obj.put("__links",  links);
+				res.add(obj);
+			}
+		}
+		finally {
+			cursor.close();
+		}
+		
+		return JSON.serialize(res);
+	}
+	
 	private Response createOrUpdateProject(String projectId, String projectContent) {
 		
 		if(null == projectContent || projectContent.isEmpty()) {
--- a/server/src/main/resources/_firebug/LICENSE	Tue Nov 13 11:46:39 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,37 +0,0 @@
-License Disclaimer:
-
-All contents of this directory are Copyright (c) the Dojo Foundation, with the
-following exceptions:
--------------------------------------------------------------------------------
-
-firebug.html, firebug.js, errIcon.png, infoIcon.png, warningIcon.png:
-	* Copyright (c) 2006-2007, Joe Hewitt, All rights reserved.
-	  Distributed under the terms of the BSD License (see below)
-
--------------------------------------------------------------------------------
-
-Copyright (c) 2006-2007, Joe Hewitt
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-  * Redistributions of source code must retain the above copyright notice, this
-	list of conditions and the following disclaimer.
-  * Redistributions in binary form must reproduce the above copyright notice,
-	this list of conditions and the following disclaimer in the documentation
-	and/or other materials provided with the distribution.
-  * Neither the name of the Dojo Foundation nor the names of its contributors
-	may be used to endorse or promote products derived from this software
-	without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
-FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Binary file server/src/main/resources/_firebug/errorIcon.png has changed
--- a/server/src/main/resources/_firebug/firebug.css	Tue Nov 13 11:46:39 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,208 +0,0 @@
-.firebug {
-	margin: 0;
-	background:#fff;
-	font-family: Lucida Grande, Tahoma, sans-serif;
-	font-size: 11px;
-	overflow: hidden;
-	border: 1px solid black;
-	position: relative;
-}
-.firebug a {
-	text-decoration: none;
-}
-.firebug a:hover {
-	text-decoration: underline;
-}
-.firebug a:visited{
-	color:#0000FF;
-}
-.firebug #firebugToolbar {
-	height: 18px;
-	line-height:18px;
-	border-top: 1px solid ThreeDHighlight;
-	border-bottom: 1px solid ThreeDShadow;
-	padding: 2px 6px;
-	
-	background:#f0f0f0;
-}
-.firebug #firebugLog, .firebug #objectLog {
-	overflow: auto;
-	position: absolute;
-	left: 0;
-	width: 100%;
-}
-#objectLog{
-	overflow:scroll;
-	height:258px;
-}
-.firebug #firebugCommandLine {
-	position: absolute;
-	bottom: 0;
-	left: 0;
-	width: 100%;
-	height: 18px;
-	border: none;
-	border-top: 1px solid ThreeDShadow;
-}
-.firebug .logRow {
-	position: relative;
-	border-bottom: 1px solid #D7D7D7;
-	padding: 2px 4px 1px 6px;
-	background-color: #FFFFFF;
-}
-.firebug .logRow-command {
-	font-family: Monaco, monospace;
-	color: blue;
-}
-.firebug .objectBox-null {
-	padding: 0 2px;
-	border: 1px solid #666666;
-	background-color: #888888;
-	color: #FFFFFF;
-}
-.firebug .objectBox-string {
-	font-family: Monaco, monospace;
-	color: red;
-	white-space: pre;
-}
-.firebug .objectBox-number {
-	color: #000088;
-}
-.firebug .objectBox-function {
-	font-family: Monaco, monospace;
-	color: DarkGreen;
-}
-.firebug .objectBox-object {
-	color: DarkGreen;
-	font-weight: bold;
-}
-.firebug .logRow-info,
-.firebug .logRow-error,
-.firebug .logRow-warning
- {
-	background: #00FFFF no-repeat 2px 2px;
-	padding-left: 20px;
-	padding-bottom: 3px;
-}
-.firebug .logRow-info {
-	background: #FFF url(infoIcon.png) no-repeat 2px 2px;
-	padding-left: 20px;
-	padding-bottom: 3px;
-}
-.firebug .logRow-warning {
-	
-	background: #00FFFF url(warningIcon.png) no-repeat 2px 2px;
-	padding-left: 20px;
-	padding-bottom: 3px;
-}
-.firebug .logRow-error {
-	background: LightYellow url(errorIcon.png) no-repeat 2px 2px;
-	padding-left: 20px;
-	padding-bottom: 3px;
-}
-.firebug .errorMessage {
-	vertical-align: top;
-	color: #FF0000;
-}
-.firebug .objectBox-sourceLink {
-	position: absolute;
-	right: 4px;
-	top: 2px;
-	padding-left: 8px;
-	font-family: Lucida Grande, sans-serif;
-	font-weight: bold;
-	color: #0000FF;
-}
-.firebug .logRow-group {
-	background: #EEEEEE;
-	border-bottom: none;
-}
-.firebug .logGroup {
-	background: #EEEEEE;
-}
-.firebug .logGroupBox {
-	margin-left: 24px;
-	border-top: 1px solid #D7D7D7;
-	border-left: 1px solid #D7D7D7;
-}
-.firebug .selectorTag,
-.firebug .selectorId,
-.firebug .selectorClass {
-	font-family: Monaco, monospace;
-	font-weight: normal;
-}
-.firebug .selectorTag {
-	color: #0000FF;
-}
-.firebug .selectorId {
-	color: DarkBlue;
-}
-.firebug .selectorClass {
-	color: red;
-}
-.firebug .objectBox-element {
-	font-family: Monaco, monospace;
-	color: #000088;
-}
-.firebug .nodeChildren {
-	margin-left: 16px;
-}
-.firebug .nodeTag {
-	color: blue;
-}
-.firebug .nodeValue {
-	color: #FF0000;
-	font-weight: normal;
-}
-.firebug .nodeText,
-.firebug .nodeComment {
-	margin: 0 2px;
-	vertical-align: top;
-}
-.firebug .nodeText {
-	color: #333333;
-}
-.firebug .nodeComment {
-	color: DarkGreen;
-}
-.firebug .propertyNameCell {
-	vertical-align: top;
-}
-.firebug .propertyName {
-	font-weight: bold;
-}
-#firebugToolbar ul.tabs{
-	margin:0 !important;
-	padding:0;
-}
-#firebugToolbar ul.tabs li{
-	list-style:none;
-	background:transparent url(tab_lft_norm.png) no-repeat left;
-	line-height:18px;
-	float:left;
-	margin-left:5px;
-}
-#firebugToolbar ul.tabs li.right{
-	float:right;
-	margin-right:5px;
-	margin-left:0;
-}
-#firebugToolbar ul.tabs li.gap{
-	margin-left:20px;
-}
-#firebugToolbar .tabs a{
-	text-decoration:none;
-	background:transparent url(tab_rgt_norm.png) no-repeat right;
-	line-height:18px;
-	padding:3px 9px 4px 0px;
-	margin-left:9px;
-	color:#333333;
-}
-#firebugToolbar .tabs li:hover{
-	background:transparent url(tab_lft_over.png) no-repeat left;
-}
-#firebugToolbar .tabs a:hover{
-	text-decoration:none;
-	background:transparent url(tab_rgt_over.png) no-repeat right;
-	color:#FFFFFF;
-}
--- a/server/src/main/resources/_firebug/firebug.js	Tue Nov 13 11:46:39 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,898 +0,0 @@
-/*
-	Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved.
-	Available via Academic Free License >= 2.1 OR the modified BSD license.
-	see: http://dojotoolkit.org/license for details
-*/
-
-//>>built
-define("dojo/_firebug/firebug",["../_base/kernel","require","../_base/html","../sniff","../_base/array","../_base/lang","../_base/event","../_base/unload"],function(_1,_2,_3,_4){
-var _5=(/Trident/.test(window.navigator.userAgent));
-if(_5){
-var _6=["log","info","debug","warn","error"];
-for(var i=0;i<_6.length;i++){
-var m=_6[i];
-if(!console[m]||console[m]._fake){
-continue;
-}
-var n="_"+_6[i];
-console[n]=console[m];
-console[m]=(function(){
-var _7=n;
-return function(){
-console[_7](Array.prototype.join.call(arguments," "));
-};
-})();
-}
-try{
-console.clear();
-}
-catch(e){
-}
-}
-if(_4("ff")||_4("chrome")||_4("safari")||_5||window.firebug||(typeof console!="undefined"&&console.firebug)||_1.config.useCustomLogger||_4("air")){
-return;
-}
-try{
-if(window!=window.parent){
-if(window.parent["console"]){
-window.console=window.parent.console;
-}
-return;
-}
-}
-catch(e){
-}
-var _8=document;
-var _9=window;
-var _a=0;
-var _b=null;
-var _c=null;
-var _d=null;
-var _e=null;
-var _f=null;
-var _10=null;
-var _11=false;
-var _12=[];
-var _13=[];
-var _14={};
-var _15={};
-var _16=null;
-var _17;
-var _18;
-var _19=false;
-var _1a=null;
-var _1b=document.createElement("div");
-var _1c;
-var _1d;
-window.console={_connects:[],log:function(){
-_1e(arguments,"");
-},debug:function(){
-_1e(arguments,"debug");
-},info:function(){
-_1e(arguments,"info");
-},warn:function(){
-_1e(arguments,"warning");
-},error:function(){
-_1e(arguments,"error");
-},assert:function(_1f,_20){
-if(!_1f){
-var _21=[];
-for(var i=1;i<arguments.length;++i){
-_21.push(arguments[i]);
-}
-_1e(_21.length?_21:["Assertion Failure"],"error");
-throw _20?_20:"Assertion Failure";
-}
-},dir:function(obj){
-var str=_22(obj);
-str=str.replace(/\n/g,"<br />");
-str=str.replace(/\t/g,"&nbsp;&nbsp;&nbsp;&nbsp;");
-_23([str],"dir");
-},dirxml:function(_24){
-var _25=[];
-_26(_24,_25);
-_23(_25,"dirxml");
-},group:function(){
-_23(arguments,"group",_27);
-},groupEnd:function(){
-_23(arguments,"",_28);
-},time:function(_29){
-_14[_29]=new Date().getTime();
-},timeEnd:function(_2a){
-if(_2a in _14){
-var _2b=(new Date()).getTime()-_14[_2a];
-_1e([_2a+":",_2b+"ms"]);
-delete _14[_2a];
-}
-},count:function(_2c){
-if(!_15[_2c]){
-_15[_2c]=0;
-}
-_15[_2c]++;
-_1e([_2c+": "+_15[_2c]]);
-},trace:function(_2d){
-var _2e=_2d||3;
-var f=console.trace.caller;
-for(var i=0;i<_2e;i++){
-var _2f=f.toString();
-var _30=[];
-for(var a=0;a<f.arguments.length;a++){
-_30.push(f.arguments[a]);
-}
-if(f.arguments.length){
-}else{
-}
-f=f.caller;
-}
-},profile:function(){
-this.warn(["profile() not supported."]);
-},profileEnd:function(){
-},clear:function(){
-if(_c){
-while(_c.childNodes.length){
-_1.destroy(_c.firstChild);
-}
-}
-_1.forEach(this._connects,_1.disconnect);
-},open:function(){
-_31(true);
-},close:function(){
-if(_11){
-_31();
-}
-},_restoreBorder:function(){
-if(_1c){
-_1c.style.border=_1d;
-}
-},openDomInspector:function(){
-_19=true;
-_c.style.display="none";
-_16.style.display="block";
-_d.style.display="none";
-document.body.style.cursor="pointer";
-_17=_1.connect(document,"mousemove",function(evt){
-if(!_19){
-return;
-}
-if(!_1a){
-_1a=setTimeout(function(){
-_1a=null;
-},50);
-}else{
-return;
-}
-var _32=evt.target;
-if(_32&&(_1c!==_32)){
-var _33=true;
-console._restoreBorder();
-var _34=[];
-_26(_32,_34);
-_16.innerHTML=_34.join("");
-_1c=_32;
-_1d=_1c.style.border;
-_1c.style.border="#0000FF 1px solid";
-}
-});
-setTimeout(function(){
-_18=_1.connect(document,"click",function(evt){
-document.body.style.cursor="";
-_19=!_19;
-_1.disconnect(_18);
-});
-},30);
-},_closeDomInspector:function(){
-document.body.style.cursor="";
-_1.disconnect(_17);
-_1.disconnect(_18);
-_19=false;
-console._restoreBorder();
-},openConsole:function(){
-_c.style.display="block";
-_16.style.display="none";
-_d.style.display="none";
-console._closeDomInspector();
-},openObjectInspector:function(){
-_c.style.display="none";
-_16.style.display="none";
-_d.style.display="block";
-console._closeDomInspector();
-},recss:function(){
-var i,a,s;
-a=document.getElementsByTagName("link");
-for(i=0;i<a.length;i++){
-s=a[i];
-if(s.rel.toLowerCase().indexOf("stylesheet")>=0&&s.href){
-var h=s.href.replace(/(&|%5C?)forceReload=\d+/,"");
-s.href=h+(h.indexOf("?")>=0?"&":"?")+"forceReload="+new Date().valueOf();
-}
-}
-}};
-function _31(_35){
-_11=_35||!_11;
-if(_b){
-_b.style.display=_11?"block":"none";
-}
-};
-function _36(){
-_31(true);
-if(_f){
-_f.focus();
-}
-};
-function _37(x,y,w,h){
-var win=window.open("","_firebug","status=0,menubar=0,resizable=1,top="+y+",left="+x+",width="+w+",height="+h+",scrollbars=1,addressbar=0");
-if(!win){
-var msg="Firebug Lite could not open a pop-up window, most likely because of a blocker.\n"+"Either enable pop-ups for this domain, or change the djConfig to popup=false.";
-alert(msg);
-}
-_38(win);
-var _39=win.document;
-var _3a="<html style=\"height:100%;\"><head><title>Firebug Lite</title></head>\n"+"<body bgColor=\"#ccc\" style=\"height:97%;\" onresize=\"opener.onFirebugResize()\">\n"+"<div id=\"fb\"></div>"+"</body></html>";
-_39.write(_3a);
-_39.close();
-return win;
-};
-function _38(wn){
-var d=new Date();
-d.setTime(d.getTime()+(60*24*60*60*1000));
-d=d.toUTCString();
-var dc=wn.document,_3b;
-if(wn.innerWidth){
-_3b=function(){
-return {w:wn.innerWidth,h:wn.innerHeight};
-};
-}else{
-if(dc.documentElement&&dc.documentElement.clientWidth){
-_3b=function(){
-return {w:dc.documentElement.clientWidth,h:dc.documentElement.clientHeight};
-};
-}else{
-if(dc.body){
-_3b=function(){
-return {w:dc.body.clientWidth,h:dc.body.clientHeight};
-};
-}
-}
-}
-window.onFirebugResize=function(){
-_49(_3b().h);
-clearInterval(wn._firebugWin_resize);
-wn._firebugWin_resize=setTimeout(function(){
-var x=wn.screenLeft,y=wn.screenTop,w=wn.outerWidth||wn.document.body.offsetWidth,h=wn.outerHeight||wn.document.body.offsetHeight;
-document.cookie="_firebugPosition="+[x,y,w,h].join(",")+"; expires="+d+"; path=/";
-},5000);
-};
-};
-function _3c(){
-if(_b){
-return;
-}
-_31(true);
-if(_1.config.popup){
-var _3d="100%";
-var _3e=document.cookie.match(/(?:^|; )_firebugPosition=([^;]*)/);
-var p=_3e?_3e[1].split(","):[2,2,320,480];
-_9=_37(p[0],p[1],p[2],p[3]);
-_8=_9.document;
-_1.config.debugContainerId="fb";
-_9.console=window.console;
-_9.dojo=window.dojo;
-}else{
-_8=document;
-_3d=(_1.config.debugHeight||300)+"px";
-}
-var _3f=_8.createElement("link");
-_3f.href=_2.toUrl("./firebug.css");
-_3f.rel="stylesheet";
-_3f.type="text/css";
-var _40=_8.getElementsByTagName("head");
-if(_40){
-_40=_40[0];
-}
-if(!_40){
-_40=_8.getElementsByTagName("html")[0];
-}
-if(_4("ie")){
-window.setTimeout(function(){
-_40.appendChild(_3f);
-},0);
-}else{
-_40.appendChild(_3f);
-}
-if(_1.config.debugContainerId){
-_b=_8.getElementById(_1.config.debugContainerId);
-}
-if(!_b){
-_b=_8.createElement("div");
-_8.body.appendChild(_b);
-}
-_b.className+=" firebug";
-_b.id="firebug";
-_b.style.height=_3d;
-_b.style.display=(_11?"block":"none");
-var _41=function(_42,_43,_44,_45){
-return "<li class=\""+_45+"\"><a href=\"javascript:void(0);\" onclick=\"console."+_44+"(); return false;\" title=\""+_43+"\">"+_42+"</a></li>";
-};
-_b.innerHTML="<div id=\"firebugToolbar\">"+"  <ul id=\"fireBugTabs\" class=\"tabs\">"+_41("Clear","Remove All Console Logs","clear","")+_41("ReCSS","Refresh CSS without reloading page","recss","")+_41("Console","Show Console Logs","openConsole","gap")+_41("DOM","Show DOM Inspector","openDomInspector","")+_41("Object","Show Object Inspector","openObjectInspector","")+((_1.config.popup)?"":_41("Close","Close the console","close","gap"))+"\t</ul>"+"</div>"+"<input type=\"text\" id=\"firebugCommandLine\" />"+"<div id=\"firebugLog\"></div>"+"<div id=\"objectLog\" style=\"display:none;\">Click on an object in the Log display</div>"+"<div id=\"domInspect\" style=\"display:none;\">Hover over HTML elements in the main page. Click to hold selection.</div>";
-_10=_8.getElementById("firebugToolbar");
-_f=_8.getElementById("firebugCommandLine");
-_46(_f,"keydown",_47);
-_46(_8,_4("ie")||_4("safari")?"keydown":"keypress",_48);
-_c=_8.getElementById("firebugLog");
-_d=_8.getElementById("objectLog");
-_16=_8.getElementById("domInspect");
-_e=_8.getElementById("fireBugTabs");
-_49();
-_4a();
-};
-_1.addOnLoad(_3c);
-function _4b(){
-_8=null;
-if(_9.console){
-_9.console.clear();
-}
-_9=null;
-_b=null;
-_c=null;
-_d=null;
-_16=null;
-_f=null;
-_12=[];
-_13=[];
-_14={};
-};
-function _4c(){
-var _4d=_f.value;
-_f.value="";
-_23([">  ",_4d],"command");
-var _4e;
-try{
-_4e=eval(_4d);
-}
-catch(e){
-}
-};
-function _49(h){
-var _4f=25;
-var _50=h?h-(_4f+_f.offsetHeight+25+(h*0.01))+"px":(_b.offsetHeight-_4f-_f.offsetHeight)+"px";
-_c.style.top=_4f+"px";
-_c.style.height=_50;
-_d.style.height=_50;
-_d.style.top=_4f+"px";
-_16.style.height=_50;
-_16.style.top=_4f+"px";
-_f.style.bottom=0;
-_1.addOnWindowUnload(_4b);
-};
-function _23(_51,_52,_53){
-if(_c){
-_54(_51,_52,_53);
-}else{
-_12.push([_51,_52,_53]);
-}
-};
-function _4a(){
-var _55=_12;
-_12=[];
-for(var i=0;i<_55.length;++i){
-_54(_55[i][0],_55[i][1],_55[i][2]);
-}
-};
-function _54(_56,_57,_58){
-var _59=_c.scrollTop+_c.offsetHeight>=_c.scrollHeight;
-_58=_58||_5a;
-_58(_56,_57);
-if(_59){
-_c.scrollTop=_c.scrollHeight-_c.offsetHeight;
-}
-};
-function _5b(row){
-var _5c=_13.length?_13[_13.length-1]:_c;
-_5c.appendChild(row);
-};
-function _5a(_5d,_5e){
-var row=_c.ownerDocument.createElement("div");
-row.className="logRow"+(_5e?" logRow-"+_5e:"");
-row.innerHTML=_5d.join("");
-_5b(row);
-};
-function _27(_5f,_60){
-_1e(_5f,_60);
-var _61=_c.ownerDocument.createElement("div");
-_61.className="logGroupBox";
-_5b(_61);
-_13.push(_61);
-};
-function _28(){
-_13.pop();
-};
-function _1e(_62,_63){
-var _64=[];
-var _65=_62[0];
-var _66=0;
-if(typeof (_65)!="string"){
-_65="";
-_66=-1;
-}
-var _67=_68(_65);
-for(var i=0;i<_67.length;++i){
-var _69=_67[i];
-if(_69&&typeof _69=="object"){
-_69.appender(_62[++_66],_64);
-}else{
-_6a(_69,_64);
-}
-}
-var ids=[];
-var obs=[];
-for(i=_66+1;i<_62.length;++i){
-_6a(" ",_64);
-var _6b=_62[i];
-if(_6b===undefined||_6b===null){
-_6c(_6b,_64);
-}else{
-if(typeof (_6b)=="string"){
-_6a(_6b,_64);
-}else{
-if(_6b instanceof Date){
-_6a(_6b.toString(),_64);
-}else{
-if(_6b.nodeType==9){
-_6a("[ XmlDoc ]",_64);
-}else{
-var id="_a"+_a++;
-ids.push(id);
-obs.push(_6b);
-var str="<a id=\""+id+"\" href=\"javascript:void(0);\">"+_6d(_6b)+"</a>";
-_6e(str,_64);
-}
-}
-}
-}
-}
-_23(_64,_63);
-for(i=0;i<ids.length;i++){
-var btn=_8.getElementById(ids[i]);
-if(!btn){
-continue;
-}
-btn.obj=obs[i];
-_9.console._connects.push(_1.connect(btn,"onclick",function(){
-console.openObjectInspector();
-try{
-_22(this.obj);
-}
-catch(e){
-this.obj=e;
-}
-_d.innerHTML="<pre>"+_22(this.obj)+"</pre>";
-}));
-}
-};
-function _68(_6f){
-var _70=[];
-var reg=/((^%|[^\\]%)(\d+)?(\.)([a-zA-Z]))|((^%|[^\\]%)([a-zA-Z]))/;
-var _71={s:_6a,d:_72,i:_72,f:_73};
-for(var m=reg.exec(_6f);m;m=reg.exec(_6f)){
-var _74=m[8]?m[8]:m[5];
-var _75=_74 in _71?_71[_74]:_76;
-var _77=m[3]?parseInt(m[3]):(m[4]=="."?-1:0);
-_70.push(_6f.substr(0,m[0][0]=="%"?m.index:m.index+1));
-_70.push({appender:_75,precision:_77});
-_6f=_6f.substr(m.index+m[0].length);
-}
-_70.push(_6f);
-return _70;
-};
-function _78(_79){
-function _7a(ch){
-switch(ch){
-case "<":
-return "&lt;";
-case ">":
-return "&gt;";
-case "&":
-return "&amp;";
-case "'":
-return "&#39;";
-case "\"":
-return "&quot;";
-}
-return "?";
-};
-return String(_79).replace(/[<>&"']/g,_7a);
-};
-function _7b(_7c){
-try{
-return _7c+"";
-}
-catch(e){
-return null;
-}
-};
-function _6e(_7d,_7e){
-_7e.push(_7b(_7d));
-};
-function _6a(_7f,_80){
-_80.push(_78(_7b(_7f)));
-};
-function _6c(_81,_82){
-_82.push("<span class=\"objectBox-null\">",_78(_7b(_81)),"</span>");
-};
-function _83(_84,_85){
-_85.push("<span class=\"objectBox-string\">&quot;",_78(_7b(_84)),"&quot;</span>");
-};
-function _72(_86,_87){
-_87.push("<span class=\"objectBox-number\">",_78(_7b(_86)),"</span>");
-};
-function _73(_88,_89){
-_89.push("<span class=\"objectBox-number\">",_78(_7b(_88)),"</span>");
-};
-function _8a(_8b,_8c){
-_8c.push("<span class=\"objectBox-function\">",_6d(_8b),"</span>");
-};
-function _76(_8d,_8e){
-try{
-if(_8d===undefined){
-_6c("undefined",_8e);
-}else{
-if(_8d===null){
-_6c("null",_8e);
-}else{
-if(typeof _8d=="string"){
-_83(_8d,_8e);
-}else{
-if(typeof _8d=="number"){
-_72(_8d,_8e);
-}else{
-if(typeof _8d=="function"){
-_8a(_8d,_8e);
-}else{
-if(_8d.nodeType==1){
-_8f(_8d,_8e);
-}else{
-if(typeof _8d=="object"){
-_90(_8d,_8e);
-}else{
-_6a(_8d,_8e);
-}
-}
-}
-}
-}
-}
-}
-}
-catch(e){
-}
-};
-function _90(_91,_92){
-var _93=_7b(_91);
-var _94=/\[object (.*?)\]/;
-var m=_94.exec(_93);
-_92.push("<span class=\"objectBox-object\">",m?m[1]:_93,"</span>");
-};
-function _8f(_95,_96){
-_96.push("<span class=\"objectBox-selector\">");
-_96.push("<span class=\"selectorTag\">",_78(_95.nodeName.toLowerCase()),"</span>");
-if(_95.id){
-_96.push("<span class=\"selectorId\">#",_78(_95.id),"</span>");
-}
-if(_95.className){
-_96.push("<span class=\"selectorClass\">.",_78(_95.className),"</span>");
-}
-_96.push("</span>");
-};
-function _26(_97,_98){
-if(_97.nodeType==1){
-_98.push("<div class=\"objectBox-element\">","&lt;<span class=\"nodeTag\">",_97.nodeName.toLowerCase(),"</span>");
-for(var i=0;i<_97.attributes.length;++i){
-var _99=_97.attributes[i];
-if(!_99.specified){
-continue;
-}
-_98.push("&nbsp;<span class=\"nodeName\">",_99.nodeName.toLowerCase(),"</span>=&quot;<span class=\"nodeValue\">",_78(_99.nodeValue),"</span>&quot;");
-}
-if(_97.firstChild){
-_98.push("&gt;</div><div class=\"nodeChildren\">");
-for(var _9a=_97.firstChild;_9a;_9a=_9a.nextSibling){
-_26(_9a,_98);
-}
-_98.push("</div><div class=\"objectBox-element\">&lt;/<span class=\"nodeTag\">",_97.nodeName.toLowerCase(),"&gt;</span></div>");
-}else{
-_98.push("/&gt;</div>");
-}
-}else{
-if(_97.nodeType==3){
-_98.push("<div class=\"nodeText\">",_78(_97.nodeValue),"</div>");
-}
-}
-};
-function _46(_9b,_9c,_9d){
-if(document.all){
-_9b.attachEvent("on"+_9c,_9d);
-}else{
-_9b.addEventListener(_9c,_9d,false);
-}
-};
-function _9e(_9f,_a0,_a1){
-if(document.all){
-_9f.detachEvent("on"+_a0,_a1);
-}else{
-_9f.removeEventListener(_a0,_a1,false);
-}
-};
-function _a2(_a3){
-if(document.all){
-_a3.cancelBubble=true;
-}else{
-_a3.stopPropagation();
-}
-};
-function _a4(msg,_a5,_a6){
-var _a7=_a5.lastIndexOf("/");
-var _a8=_a7==-1?_a5:_a5.substr(_a7+1);
-var _a9=["<span class=\"errorMessage\">",msg,"</span>","<div class=\"objectBox-sourceLink\">",_a8," (line ",_a6,")</div>"];
-_23(_a9,"error");
-};
-var _aa=new Date().getTime();
-function _48(_ab){
-var _ac=(new Date()).getTime();
-if(_ac>_aa+200){
-_ab=_1.fixEvent(_ab);
-var _ad=_1.keys;
-var ekc=_ab.keyCode;
-_aa=_ac;
-if(ekc==_ad.F12){
-_31();
-}else{
-if((ekc==_ad.NUMPAD_ENTER||ekc==76)&&_ab.shiftKey&&(_ab.metaKey||_ab.ctrlKey)){
-_36();
-}else{
-return;
-}
-}
-_a2(_ab);
-}
-};
-function _47(e){
-var dk=_1.keys;
-if(e.keyCode==13&&_f.value){
-_ae(_f.value);
-_4c();
-}else{
-if(e.keyCode==27){
-_f.value="";
-}else{
-if(e.keyCode==dk.UP_ARROW||e.charCode==dk.UP_ARROW){
-_af("older");
-}else{
-if(e.keyCode==dk.DOWN_ARROW||e.charCode==dk.DOWN_ARROW){
-_af("newer");
-}else{
-if(e.keyCode==dk.HOME||e.charCode==dk.HOME){
-_b0=1;
-_af("older");
-}else{
-if(e.keyCode==dk.END||e.charCode==dk.END){
-_b0=999999;
-_af("newer");
-}
-}
-}
-}
-}
-}
-};
-var _b0=-1;
-var _b1=null;
-function _ae(_b2){
-var _b3=_b4("firebug_history");
-_b3=(_b3)?_1.fromJson(_b3):[];
-var pos=_1.indexOf(_b3,_b2);
-if(pos!=-1){
-_b3.splice(pos,1);
-}
-_b3.push(_b2);
-_b4("firebug_history",_1.toJson(_b3),30);
-while(_b3.length&&!_b4("firebug_history")){
-_b3.shift();
-_b4("firebug_history",_1.toJson(_b3),30);
-}
-_b1=null;
-_b0=-1;
-};
-function _af(_b5){
-var _b6=_b4("firebug_history");
-_b6=(_b6)?_1.fromJson(_b6):[];
-if(!_b6.length){
-return;
-}
-if(_b1===null){
-_b1=_f.value;
-}
-if(_b0==-1){
-_b0=_b6.length;
-}
-if(_b5=="older"){
---_b0;
-if(_b0<0){
-_b0=0;
-}
-}else{
-if(_b5=="newer"){
-++_b0;
-if(_b0>_b6.length){
-_b0=_b6.length;
-}
-}
-}
-if(_b0==_b6.length){
-_f.value=_b1;
-_b1=null;
-}else{
-_f.value=_b6[_b0];
-}
-};
-function _b4(_b7,_b8){
-var c=document.cookie;
-if(arguments.length==1){
-var _b9=c.match(new RegExp("(?:^|; )"+_b7+"=([^;]*)"));
-return _b9?decodeURIComponent(_b9[1]):undefined;
-}else{
-var d=new Date();
-d.setMonth(d.getMonth()+1);
-document.cookie=_b7+"="+encodeURIComponent(_b8)+((d.toUtcString)?"; expires="+d.toUTCString():"");
-}
-};
-function _ba(it){
-return it&&it instanceof Array||typeof it=="array";
-};
-function _bb(o){
-var cnt=0;
-for(var nm in o){
-cnt++;
-}
-return cnt;
-};
-function _22(o,i,txt,_bc){
-var ind=" \t";
-txt=txt||"";
-i=i||ind;
-_bc=_bc||[];
-var _bd;
-if(o&&o.nodeType==1){
-var _be=[];
-_26(o,_be);
-return _be.join("");
-}
-var br=",\n",cnt=0,_bf=_bb(o);
-if(o instanceof Date){
-return i+o.toString()+br;
-}
-looking:
-for(var nm in o){
-cnt++;
-if(cnt==_bf){
-br="\n";
-}
-if(o[nm]===window||o[nm]===document){
-}else{
-if(o[nm]===null){
-txt+=i+nm+" : NULL"+br;
-}else{
-if(o[nm]&&o[nm].nodeType){
-if(o[nm].nodeType==1){
-}else{
-if(o[nm].nodeType==3){
-txt+=i+nm+" : [ TextNode "+o[nm].data+" ]"+br;
-}
-}
-}else{
-if(typeof o[nm]=="object"&&(o[nm] instanceof String||o[nm] instanceof Number||o[nm] instanceof Boolean)){
-txt+=i+nm+" : "+o[nm]+","+br;
-}else{
-if(o[nm] instanceof Date){
-txt+=i+nm+" : "+o[nm].toString()+br;
-}else{
-if(typeof (o[nm])=="object"&&o[nm]){
-for(var j=0,_c0;_c0=_bc[j];j++){
-if(o[nm]===_c0){
-txt+=i+nm+" : RECURSION"+br;
-continue looking;
-}
-}
-_bc.push(o[nm]);
-_bd=(_ba(o[nm]))?["[","]"]:["{","}"];
-txt+=i+nm+" : "+_bd[0]+"\n";
-txt+=_22(o[nm],i+ind,"",_bc);
-txt+=i+_bd[1]+br;
-}else{
-if(typeof o[nm]=="undefined"){
-txt+=i+nm+" : undefined"+br;
-}else{
-if(nm=="toString"&&typeof o[nm]=="function"){
-var _c1=o[nm]();
-if(typeof _c1=="string"&&_c1.match(/function ?(.*?)\(/)){
-_c1=_78(_6d(o[nm]));
-}
-txt+=i+nm+" : "+_c1+br;
-}else{
-txt+=i+nm+" : "+_78(_6d(o[nm]))+br;
-}
-}
-}
-}
-}
-}
-}
-}
-}
-return txt;
-};
-function _6d(obj){
-var _c2=(obj instanceof Error);
-if(obj.nodeType==1){
-return _78("< "+obj.tagName.toLowerCase()+" id=\""+obj.id+"\" />");
-}
-if(obj.nodeType==3){
-return _78("[TextNode: \""+obj.nodeValue+"\"]");
-}
-var nm=(obj&&(obj.id||obj.name||obj.ObjectID||obj.widgetId));
-if(!_c2&&nm){
-return "{"+nm+"}";
-}
-var _c3=2;
-var _c4=4;
-var cnt=0;
-if(_c2){
-nm="[ Error: "+(obj.message||obj.description||obj)+" ]";
-}else{
-if(_ba(obj)){
-nm="["+obj.slice(0,_c4).join(",");
-if(obj.length>_c4){
-nm+=" ... ("+obj.length+" items)";
-}
-nm+="]";
-}else{
-if(typeof obj=="function"){
-nm=obj+"";
-var reg=/function\s*([^\(]*)(\([^\)]*\))[^\{]*\{/;
-var m=reg.exec(nm);
-if(m){
-if(!m[1]){
-m[1]="function";
-}
-nm=m[1]+m[2];
-}else{
-nm="function()";
-}
-}else{
-if(typeof obj!="object"||typeof obj=="string"){
-nm=obj+"";
-}else{
-nm="{";
-for(var i in obj){
-cnt++;
-if(cnt>_c3){
-break;
-}
-nm+=i+":"+_78(obj[i])+"  ";
-}
-nm+="}";
-}
-}
-}
-}
-return nm;
-};
-_46(document,_4("ie")||_4("safari")?"keydown":"keypress",_48);
-if((document.documentElement.getAttribute("debug")=="true")||(_1.config.isDebug)){
-_31(true);
-}
-_1.addOnWindowUnload(function(){
-_9e(document,_4("ie")||_4("safari")?"keydown":"keypress",_48);
-window.onFirebugResize=null;
-window.console=null;
-});
-});
--- a/server/src/main/resources/_firebug/firebug.js.uncompressed.js	Tue Nov 13 11:46:39 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1191 +0,0 @@
-define("dojo/_firebug/firebug", [
-	"../_base/kernel",
-	"require",
-	"../_base/html",
-	"../sniff",
-	"../_base/array",
-	"../_base/lang",
-	"../_base/event",
-	"../_base/unload"], function(dojo, require, html, has){
-
-	// module:
-	//		dojo/_firebug/firebug
-	// summary:
-	//		Firebug Lite, the baby brother to Joe Hewitt's Firebug for Mozilla Firefox
-	// description:
-	//		Opens a console for logging, debugging, and error messages.
-	//		Contains partial functionality to Firebug. See function list below.
-	//
-	//		NOTE:
-	//		Firebug is a Firefox extension created by Joe Hewitt (see license). You do not need Dojo to run Firebug.
-	//		Firebug Lite is included in Dojo by permission from Joe Hewitt
-	//		If you are new to Firebug, or used to the Dojo 0.4 dojo.debug, you can learn Firebug
-	//		functionality by reading the function comments below or visiting http://www.getfirebug.com/docs.html
-	//
-	//		NOTE:
-	//		To test Firebug Lite in Firefox:
-	//
-	//		- FF2: set "console = null" before loading dojo and set djConfig.isDebug=true
-	//		- FF3: disable Firebug and set djConfig.isDebug=true
-	//
-	// example:
-	//		Supports inline objects in object inspector window (only simple trace of dom nodes, however)
-	//	|	console.log("my object", {foo:"bar"})
-	// example:
-	//		Option for console to open in popup window
-	//	|	var djConfig = {isDebug: true, popup:true };
-	// example:
-	//		Option for console height (ignored for popup)
-	//	|	var djConfig = {isDebug: true, debugHeight:100 }
-
-
-	var isNewIE = (/Trident/.test(window.navigator.userAgent));
-	if(isNewIE){
-		// Fixing IE's console
-		// IE doesn't insert space between arguments. How annoying.
-		var calls = ["log", "info", "debug", "warn", "error"];
-		for(var i=0;i<calls.length;i++){
-			var m = calls[i];
-			if(!console[m] ||console[m]._fake){
-				// IE9 doesn't have console.debug method, a fake one is added later
-				continue;
-			}
-			var n = "_"+calls[i];
-			console[n] = console[m];
-			console[m] = (function(){
-				var type = n;
-				return function(){
-					console[type](Array.prototype.join.call(arguments, " "));
-				};
-			})();
-		}
-		// clear the console on load. This is more than a convenience - too many logs crashes it.
-		// If closed it throws an error
-		try{ console.clear(); }catch(e){}
-	}
-
-	if(
-		has("ff") ||								// Firefox has Firebug
-		has("chrome") ||							// Chrome 3+ has a console
-		has("safari") ||							// Safari 4 has a console
-		isNewIE ||									// Has the new IE console
-		window.firebug ||							// Testing for mozilla firebug lite
-		(typeof console != "undefined" && console.firebug) || //The firebug console
-		dojo.config.useCustomLogger ||				// Allow custom loggers
-		has("air")									// isDebug triggers AIRInsector, not Firebug
-	){
-		return;
-	}
-
-	// don't build firebug in iframes
-	try{
-		if(window != window.parent){
-			// but if we've got a parent logger, connect to it
-			if(window.parent["console"]){
-				window.console = window.parent.console;
-			}
-			return;
-		}
-	}catch(e){/*squelch*/}
-
-	// ***************************************************************************
-	// Placing these variables before the functions that use them to avoid a
-	// shrinksafe bug where variable renaming does not happen correctly otherwise.
-
-	// most of the objects in this script are run anonomously
-	var _firebugDoc = document;
-	var _firebugWin = window;
-	var __consoleAnchorId__ = 0;
-
-	var consoleFrame = null;
-	var consoleBody = null;
-	var consoleObjectInspector = null;
-	var fireBugTabs = null;
-	var commandLine = null;
-	var consoleToolbar = null;
-
-	var frameVisible = false;
-	var messageQueue = [];
-	var groupStack = [];
-	var timeMap = {};
-	var countMap = {};
-
-	var consoleDomInspector = null;
-	var _inspectionMoveConnection;
-	var _inspectionClickConnection;
-	var _inspectionEnabled = false;
-	var _inspectionTimer = null;
-	var _inspectTempNode = document.createElement("div");
-
-
-	var _inspectCurrentNode;
-	var _restoreBorderStyle;
-
-	// ***************************************************************************
-
-	window.console = {
-		_connects: [],
-		log: function(){
-			// summary:
-			//		Sends arguments to console.
-			logFormatted(arguments, "");
-		},
-
-		debug: function(){
-			// summary:
-			//		Sends arguments to console. Missing finctionality to show script line of trace.
-			logFormatted(arguments, "debug");
-		},
-
-		info: function(){
-			// summary:
-			//		Sends arguments to console, highlighted with (I) icon.
-			logFormatted(arguments, "info");
-		},
-
-		warn: function(){
-			// summary:
-			//		Sends warning arguments to console, highlighted with (!) icon and blue style.
-			logFormatted(arguments, "warning");
-		},
-
-		error: function(){
-			// summary:
-			//		Sends error arguments (object) to console, highlighted with (X) icon and yellow style
-			//		NEW: error object now displays in object inspector
-			logFormatted(arguments, "error");
-		},
-
-		assert: function(truth, message){
-			// summary:
-			//		Tests for true. Throws exception if false.
-			if(!truth){
-				var args = [];
-				for(var i = 1; i < arguments.length; ++i){
-					args.push(arguments[i]);
-				}
-
-				logFormatted(args.length ? args : ["Assertion Failure"], "error");
-				throw message ? message : "Assertion Failure";
-			}
-		},
-
-		dir: function(obj){
-			var str = printObject( obj );
-			str = str.replace(/\n/g, "<br />");
-			str = str.replace(/\t/g, "&nbsp;&nbsp;&nbsp;&nbsp;");
-			logRow([str], "dir");
-		},
-
-		dirxml: function(node){
-			var html = [];
-			appendNode(node, html);
-			logRow(html, "dirxml");
-		},
-
-		group: function(){
-			// summary:
-			//		collects log messages into a group, starting with this call and ending with
-			//		groupEnd(). Missing collapse functionality
-			logRow(arguments, "group", pushGroup);
-		},
-
-		groupEnd: function(){
-			// summary:
-			//		Closes group. See above
-			logRow(arguments, "", popGroup);
-		},
-
-		time: function(name){
-			// summary:
-			//		Starts timers assigned to name given in argument. Timer stops and displays on timeEnd(title);
-			// example:
-			//	|	console.time("load");
-			//	|	console.time("myFunction");
-			//	|	console.timeEnd("load");
-			//	|	console.timeEnd("myFunction");
-			timeMap[name] = new Date().getTime();
-		},
-
-		timeEnd: function(name){
-			// summary:
-			//		See above.
-			if(name in timeMap){
-				var delta = (new Date()).getTime() - timeMap[name];
-				logFormatted([name+ ":", delta+"ms"]);
-				delete timeMap[name];
-			}
-		},
-
-		count: function(name){
-			// summary:
-			//		Not supported
-			if(!countMap[name]) countMap[name] = 0;
-			countMap[name]++;
-			logFormatted([name+": "+countMap[name]]);
-		},
-
-		trace: function(_value){
-			var stackAmt = _value || 3;
-			var f = console.trace.caller; //function that called trace
-			console.log(">>> console.trace(stack)");
-			for(var i=0;i<stackAmt;i++){
-				var func = f.toString();
-				var args=[];
-				for (var a = 0; a < f.arguments.length; a++){
-					args.push(f.arguments[a]);
-				}
-				if(f.arguments.length){
-					console.dir({"function":func, "arguments":args});
-				}else{
-					console.dir({"function":func});
-				}
-
-				f = f.caller;
-			}
-		},
-
-		profile: function(){
-			// summary:
-			//		Not supported
-			this.warn(["profile() not supported."]);
-		},
-
-		profileEnd: function(){ },
-
-		clear: function(){
-			// summary:
-			//		Clears message console. Do not call this directly
-			if(consoleBody){
-				while(consoleBody.childNodes.length){
-					dojo.destroy(consoleBody.firstChild);
-				}
-			}
-			dojo.forEach(this._connects,dojo.disconnect);
-		},
-
-		open: function(){
-			// summary:
-			//		Opens message console. Do not call this directly
-			toggleConsole(true);
-		},
-
-		close: function(){
-			// summary:
-			//		Closes message console. Do not call this directly
-			if(frameVisible){
-				toggleConsole();
-			}
-		},
-		_restoreBorder: function(){
-			if(_inspectCurrentNode){
-				_inspectCurrentNode.style.border = _restoreBorderStyle;
-			}
-		},
-		openDomInspector: function(){
-			_inspectionEnabled = true;
-			consoleBody.style.display = "none";
-			consoleDomInspector.style.display = "block";
-			consoleObjectInspector.style.display = "none";
-			document.body.style.cursor = "pointer";
-			_inspectionMoveConnection = dojo.connect(document, "mousemove", function(evt){
-				if(!_inspectionEnabled){ return; }
-				if(!_inspectionTimer){
-					_inspectionTimer = setTimeout(function(){ _inspectionTimer = null; }, 50);
-				}else{
-					return;
-				}
-				var node = evt.target;
-				if(node && (_inspectCurrentNode !== node)){
-					var parent = true;
-
-					console._restoreBorder();
-					var html = [];
-					appendNode(node, html);
-					consoleDomInspector.innerHTML = html.join("");
-
-					_inspectCurrentNode = node;
-					_restoreBorderStyle = _inspectCurrentNode.style.border;
-					_inspectCurrentNode.style.border = "#0000FF 1px solid";
-				}
-			});
-			setTimeout(function(){
-				_inspectionClickConnection = dojo.connect(document, "click", function(evt){
-					document.body.style.cursor = "";
-					_inspectionEnabled = !_inspectionEnabled;
-					dojo.disconnect(_inspectionClickConnection);
-					// console._restoreBorder();
-				});
-			}, 30);
-		},
-		_closeDomInspector: function(){
-			document.body.style.cursor = "";
-			dojo.disconnect(_inspectionMoveConnection);
-			dojo.disconnect(_inspectionClickConnection);
-			_inspectionEnabled = false;
-			console._restoreBorder();
-		},
-		openConsole:function(){
-			// summary:
-			//		Closes object inspector and opens message console. Do not call this directly
-			consoleBody.style.display = "block";
-			consoleDomInspector.style.display = "none";
-			consoleObjectInspector.style.display = "none";
-			console._closeDomInspector();
-		},
-		openObjectInspector:function(){
-			consoleBody.style.display = "none";
-			consoleDomInspector.style.display = "none";
-			consoleObjectInspector.style.display = "block";
-			console._closeDomInspector();
-		},
-		recss: function(){
-			// this is placed in dojo since the console is most likely
-			// in another window and dojo is easilly accessible
-			var i,a,s;a=document.getElementsByTagName('link');
-			for(i=0;i<a.length;i++){
-				s=a[i];
-				if(s.rel.toLowerCase().indexOf('stylesheet')>=0&&s.href){
-					var h=s.href.replace(/(&|%5C?)forceReload=\d+/,'');
-					s.href=h+(h.indexOf('?')>=0?'&':'?')+'forceReload='+new Date().valueOf();
-				}
-			}
-		}
-	};
-
-	// ***************************************************************************
-
-	function toggleConsole(forceOpen){
-		frameVisible = forceOpen || !frameVisible;
-		if(consoleFrame){
-			consoleFrame.style.display = frameVisible ? "block" : "none";
-		}
-	}
-
-	function focusCommandLine(){
-		toggleConsole(true);
-		if(commandLine){
-			commandLine.focus();
-		}
-	}
-
-	function openWin(x,y,w,h){
-		var win = window.open("","_firebug","status=0,menubar=0,resizable=1,top="+y+",left="+x+",width="+w+",height="+h+",scrollbars=1,addressbar=0");
-		if(!win){
-			var msg = "Firebug Lite could not open a pop-up window, most likely because of a blocker.\n" +
-				"Either enable pop-ups for this domain, or change the djConfig to popup=false.";
-			alert(msg);
-		}
-		createResizeHandler(win);
-		var newDoc=win.document;
-		//Safari needs an HTML height
-		var HTMLstring=	'<html style="height:100%;"><head><title>Firebug Lite</title></head>\n' +
-					'<body bgColor="#ccc" style="height:97%;" onresize="opener.onFirebugResize()">\n' +
-					'<div id="fb"></div>' +
-					'</body></html>';
-
-		newDoc.write(HTMLstring);
-		newDoc.close();
-		return win;
-	}
-
-	function createResizeHandler(wn){
-		// summary:
-		//		Creates handle for onresize window. Called from script in popup's body tag (so that it will work with IE).
-		//
-
-		var d = new Date();
-			d.setTime(d.getTime()+(60*24*60*60*1000)); // 60 days
-			d = d.toUTCString();
-
-			var dc = wn.document,
-				getViewport;
-
-			if (wn.innerWidth){
-				getViewport = function(){
-					return{w:wn.innerWidth, h:wn.innerHeight};
-				};
-			}else if (dc.documentElement && dc.documentElement.clientWidth){
-				getViewport = function(){
-					return{w:dc.documentElement.clientWidth, h:dc.documentElement.clientHeight};
-				};
-			}else if (dc.body){
-				getViewport = function(){
-					return{w:dc.body.clientWidth, h:dc.body.clientHeight};
-				};
-			}
-
-
-		window.onFirebugResize = function(){
-
-			//resize the height of the console log body
-			layout(getViewport().h);
-
-			clearInterval(wn._firebugWin_resize);
-			wn._firebugWin_resize = setTimeout(function(){
-				var x = wn.screenLeft,
-					y = wn.screenTop,
-					w = wn.outerWidth  || wn.document.body.offsetWidth,
-					h = wn.outerHeight || wn.document.body.offsetHeight;
-
-				document.cookie = "_firebugPosition=" + [x,y,w,h].join(",") + "; expires="+d+"; path=/";
-
-			 }, 5000); //can't capture window.onMove - long timeout gives better chance of capturing a resize, then the move
-
-		};
-	}
-
-
-	/*****************************************************************************/
-
-
-	function createFrame(){
-		if(consoleFrame){
-			return;
-		}
-		toggleConsole(true);
-		if(dojo.config.popup){
-			var containerHeight = "100%";
-			var cookieMatch = document.cookie.match(/(?:^|; )_firebugPosition=([^;]*)/);
-			var p = cookieMatch ? cookieMatch[1].split(",") : [2,2,320,480];
-
-			_firebugWin = openWin(p[0],p[1],p[2],p[3]);	// global
-			_firebugDoc = _firebugWin.document;			// global
-
-			dojo.config.debugContainerId = 'fb';
-
-			// connecting popup
-			_firebugWin.console = window.console;
-			_firebugWin.dojo = window.dojo;
-		}else{
-			_firebugDoc = document;
-			containerHeight = (dojo.config.debugHeight || 300) + "px";
-		}
-
-		var styleElement = _firebugDoc.createElement("link");
-		styleElement.href = require.toUrl("./firebug.css");
-		styleElement.rel = "stylesheet";
-		styleElement.type = "text/css";
-		var styleParent = _firebugDoc.getElementsByTagName("head");
-		if(styleParent){
-			styleParent = styleParent[0];
-		}
-		if(!styleParent){
-			styleParent = _firebugDoc.getElementsByTagName("html")[0];
-		}
-		if(has("ie")){
-			window.setTimeout(function(){ styleParent.appendChild(styleElement); }, 0);
-		}else{
-			styleParent.appendChild(styleElement);
-		}
-
-		if(dojo.config.debugContainerId){
-			consoleFrame = _firebugDoc.getElementById(dojo.config.debugContainerId);
-		}
-		if(!consoleFrame){
-			consoleFrame = _firebugDoc.createElement("div");
-			_firebugDoc.body.appendChild(consoleFrame);
-		}
-		consoleFrame.className += " firebug";
-		consoleFrame.id = "firebug";
-		consoleFrame.style.height = containerHeight;
-		consoleFrame.style.display = (frameVisible ? "block" : "none");
-
-		var buildLink = function(label, title, method, _class){
-			return '<li class="'+_class+'"><a href="javascript:void(0);" onclick="console.'+ method +'(); return false;" title="'+title+'">'+label+'</a></li>';
-		};
-		consoleFrame.innerHTML =
-			  '<div id="firebugToolbar">'
-			+ '  <ul id="fireBugTabs" class="tabs">'
-
-			+ buildLink("Clear", "Remove All Console Logs", "clear", "")
-			+ buildLink("ReCSS", "Refresh CSS without reloading page", "recss", "")
-
-			+ buildLink("Console", "Show Console Logs", "openConsole", "gap")
-			+ buildLink("DOM", "Show DOM Inspector", "openDomInspector", "")
-			+ buildLink("Object", "Show Object Inspector", "openObjectInspector", "")
-			+ ((dojo.config.popup) ? "" : buildLink("Close", "Close the console", "close", "gap"))
-
-			+ '	</ul>'
-			+ '</div>'
-			+ '<input type="text" id="firebugCommandLine" />'
-			+ '<div id="firebugLog"></div>'
-			+ '<div id="objectLog" style="display:none;">Click on an object in the Log display</div>'
-			+ '<div id="domInspect" style="display:none;">Hover over HTML elements in the main page. Click to hold selection.</div>';
-
-
-		consoleToolbar = _firebugDoc.getElementById("firebugToolbar");
-
-		commandLine = _firebugDoc.getElementById("firebugCommandLine");
-		addEvent(commandLine, "keydown", onCommandLineKeyDown);
-
-		addEvent(_firebugDoc, has("ie") || has("safari") ? "keydown" : "keypress", onKeyDown);
-
-		consoleBody = _firebugDoc.getElementById("firebugLog");
-		consoleObjectInspector = _firebugDoc.getElementById("objectLog");
-		consoleDomInspector = _firebugDoc.getElementById("domInspect");
-		fireBugTabs = _firebugDoc.getElementById("fireBugTabs");
-		layout();
-		flush();
-	}
-
-	dojo.addOnLoad(createFrame);
-
-	function clearFrame(){
-		_firebugDoc = null;
-
-		if(_firebugWin.console){
-			_firebugWin.console.clear();
-		}
-		_firebugWin = null;
-		consoleFrame = null;
-		consoleBody = null;
-		consoleObjectInspector = null;
-		consoleDomInspector = null;
-		commandLine = null;
-		messageQueue = [];
-		groupStack = [];
-		timeMap = {};
-	}
-
-
-	function evalCommandLine(){
-		var text = commandLine.value;
-		commandLine.value = "";
-
-		logRow([">  ", text], "command");
-
-		var value;
-		try{
-			value = eval(text);
-		}catch(e){
-			console.debug(e); // put exception on the console
-		}
-
-		console.log(value);
-	}
-
-	function layout(h){
-		var tHeight = 25; //consoleToolbar.offsetHeight; // tab style not ready on load - throws off layout
-		var height = h ?
-			h  - (tHeight + commandLine.offsetHeight +25 + (h*.01)) + "px" :
-			(consoleFrame.offsetHeight - tHeight - commandLine.offsetHeight) + "px";
-
-		consoleBody.style.top = tHeight + "px";
-		consoleBody.style.height = height;
-		consoleObjectInspector.style.height = height;
-		consoleObjectInspector.style.top = tHeight + "px";
-		consoleDomInspector.style.height = height;
-		consoleDomInspector.style.top = tHeight + "px";
-		commandLine.style.bottom = 0;
-
-		dojo.addOnWindowUnload(clearFrame);
-	}
-
-	function logRow(message, className, handler){
-		if(consoleBody){
-			writeMessage(message, className, handler);
-		}else{
-			messageQueue.push([message, className, handler]);
-		}
-	}
-
-	function flush(){
-		var queue = messageQueue;
-		messageQueue = [];
-
-		for(var i = 0; i < queue.length; ++i){
-			writeMessage(queue[i][0], queue[i][1], queue[i][2]);
-		}
-	}
-
-	function writeMessage(message, className, handler){
-		var isScrolledToBottom =
-			consoleBody.scrollTop + consoleBody.offsetHeight >= consoleBody.scrollHeight;
-
-		handler = handler||writeRow;
-
-		handler(message, className);
-
-		if(isScrolledToBottom){
-			consoleBody.scrollTop = consoleBody.scrollHeight - consoleBody.offsetHeight;
-		}
-	}
-
-	function appendRow(row){
-		var container = groupStack.length ? groupStack[groupStack.length-1] : consoleBody;
-		container.appendChild(row);
-	}
-
-	function writeRow(message, className){
-		var row = consoleBody.ownerDocument.createElement("div");
-		row.className = "logRow" + (className ? " logRow-"+className : "");
-		row.innerHTML = message.join("");
-		appendRow(row);
-	}
-
-	function pushGroup(message, className){
-		logFormatted(message, className);
-
-		//var groupRow = consoleBody.ownerDocument.createElement("div");
-		//groupRow.className = "logGroup";
-		var groupRowBox = consoleBody.ownerDocument.createElement("div");
-		groupRowBox.className = "logGroupBox";
-		//groupRow.appendChild(groupRowBox);
-		appendRow(groupRowBox);
-		groupStack.push(groupRowBox);
-	}
-
-	function popGroup(){
-		groupStack.pop();
-	}
-
-	// ***************************************************************************
-
-	function logFormatted(objects, className){
-		var html = [];
-
-		var format = objects[0];
-		var objIndex = 0;
-
-		if(typeof(format) != "string"){
-			format = "";
-			objIndex = -1;
-		}
-
-		var parts = parseFormat(format);
-
-		for(var i = 0; i < parts.length; ++i){
-			var part = parts[i];
-			if(part && typeof part == "object"){
-				part.appender(objects[++objIndex], html);
-			}else{
-				appendText(part, html);
-			}
-		}
-
-
-		var ids = [];
-		var obs = [];
-		for(i = objIndex+1; i < objects.length; ++i){
-			appendText(" ", html);
-
-			var object = objects[i];
-			if(object === undefined || object === null ){
-				appendNull(object, html);
-
-			}else if(typeof(object) == "string"){
-				appendText(object, html);
-
-			}else if(object instanceof Date){
-				appendText(object.toString(), html);
-
-			}else if(object.nodeType == 9){
-				appendText("[ XmlDoc ]", html);
-
-			}else{
-				// Create link for object inspector
-				// need to create an ID for this link, since it is currently text
-				var id = "_a" + __consoleAnchorId__++;
-				ids.push(id);
-				// need to save the object, so the arrays line up
-				obs.push(object);
-				var str = '<a id="'+id+'" href="javascript:void(0);">'+getObjectAbbr(object)+'</a>';
-
-				appendLink( str , html);
-			}
-		}
-
-		logRow(html, className);
-
-		// Now that the row is inserted in the DOM, loop through all of the links that were just created
-		for(i=0; i<ids.length; i++){
-			var btn = _firebugDoc.getElementById(ids[i]);
-			if(!btn){ continue; }
-
-			// store the object in the dom btn for reference later
-			// avoid parsing these objects unless necessary
-			btn.obj = obs[i];
-
-			_firebugWin.console._connects.push(dojo.connect(btn, "onclick", function(){
-
-				console.openObjectInspector();
-
-				try{
-					printObject(this.obj);
-				}catch(e){
-					this.obj = e;
-				}
-				consoleObjectInspector.innerHTML = "<pre>" + printObject( this.obj ) + "</pre>";
-			}));
-		}
-	}
-
-	function parseFormat(format){
-		var parts = [];
-
-		var reg = /((^%|[^\\]%)(\d+)?(\.)([a-zA-Z]))|((^%|[^\\]%)([a-zA-Z]))/;
-		var appenderMap = {s: appendText, d: appendInteger, i: appendInteger, f: appendFloat};
-
-		for(var m = reg.exec(format); m; m = reg.exec(format)){
-			var type = m[8] ? m[8] : m[5];
-			var appender = type in appenderMap ? appenderMap[type] : appendObject;
-			var precision = m[3] ? parseInt(m[3]) : (m[4] == "." ? -1 : 0);
-
-			parts.push(format.substr(0, m[0][0] == "%" ? m.index : m.index+1));
-			parts.push({appender: appender, precision: precision});
-
-			format = format.substr(m.index+m[0].length);
-		}
-
-		parts.push(format);
-
-		return parts;
-	}
-
-	function escapeHTML(value){
-		function replaceChars(ch){
-			switch(ch){
-				case "<":
-					return "&lt;";
-				case ">":
-					return "&gt;";
-				case "&":
-					return "&amp;";
-				case "'":
-					return "&#39;";
-				case '"':
-					return "&quot;";
-			}
-			return "?";
-		}
-		return String(value).replace(/[<>&"']/g, replaceChars);
-	}
-
-	function objectToString(object){
-		try{
-			return object+"";
-		}catch(e){
-			return null;
-		}
-	}
-
-	// ***************************************************************************
-	function appendLink(object, html){
-		// needed for object links - no HTML escaping
-		html.push( objectToString(object) );
-	}
-
-	function appendText(object, html){
-		html.push(escapeHTML(objectToString(object)));
-	}
-
-	function appendNull(object, html){
-		html.push('<span class="objectBox-null">', escapeHTML(objectToString(object)), '</span>');
-	}
-
-	function appendString(object, html){
-		html.push('<span class="objectBox-string">&quot;', escapeHTML(objectToString(object)),
-			'&quot;</span>');
-	}
-
-	function appendInteger(object, html){
-		html.push('<span class="objectBox-number">', escapeHTML(objectToString(object)), '</span>');
-	}
-
-	function appendFloat(object, html){
-		html.push('<span class="objectBox-number">', escapeHTML(objectToString(object)), '</span>');
-	}
-
-	function appendFunction(object, html){
-		html.push('<span class="objectBox-function">', getObjectAbbr(object), '</span>');
-	}
-
-	function appendObject(object, html){
-		try{
-			if(object === undefined){
-				appendNull("undefined", html);
-			}else if(object === null){
-				appendNull("null", html);
-			}else if(typeof object == "string"){
-				appendString(object, html);
-			}else if(typeof object == "number"){
-				appendInteger(object, html);
-			}else if(typeof object == "function"){
-				appendFunction(object, html);
-			}else if(object.nodeType == 1){
-				appendSelector(object, html);
-			}else if(typeof object == "object"){
-				appendObjectFormatted(object, html);
-			}else{
-				appendText(object, html);
-			}
-		}catch(e){
-			/* squelch */
-		}
-	}
-
-	function appendObjectFormatted(object, html){
-		var text = objectToString(object);
-		var reObject = /\[object (.*?)\]/;
-
-		var m = reObject.exec(text);
-		html.push('<span class="objectBox-object">', m ? m[1] : text, '</span>');
-	}
-
-	function appendSelector(object, html){
-		html.push('<span class="objectBox-selector">');
-
-		html.push('<span class="selectorTag">', escapeHTML(object.nodeName.toLowerCase()), '</span>');
-		if(object.id){
-			html.push('<span class="selectorId">#', escapeHTML(object.id), '</span>');
-		}
-		if(object.className){
-			html.push('<span class="selectorClass">.', escapeHTML(object.className), '</span>');
-		}
-
-		html.push('</span>');
-	}
-
-	function appendNode(node, html){
-		if(node.nodeType == 1){
-			html.push(
-				'<div class="objectBox-element">',
-					'&lt;<span class="nodeTag">', node.nodeName.toLowerCase(), '</span>');
-
-			for(var i = 0; i < node.attributes.length; ++i){
-				var attr = node.attributes[i];
-				if(!attr.specified){ continue; }
-
-				html.push('&nbsp;<span class="nodeName">', attr.nodeName.toLowerCase(),
-					'</span>=&quot;<span class="nodeValue">', escapeHTML(attr.nodeValue),
-					'</span>&quot;');
-			}
-
-			if(node.firstChild){
-				html.push('&gt;</div><div class="nodeChildren">');
-
-				for(var child = node.firstChild; child; child = child.nextSibling){
-					appendNode(child, html);
-				}
-
-				html.push('</div><div class="objectBox-element">&lt;/<span class="nodeTag">',
-					node.nodeName.toLowerCase(), '&gt;</span></div>');
-			}else{
-				html.push('/&gt;</div>');
-			}
-		}else if (node.nodeType == 3){
-			html.push('<div class="nodeText">', escapeHTML(node.nodeValue),
-				'</div>');
-		}
-	}
-
-	// ***************************************************************************
-
-	function addEvent(object, name, handler){
-		if(document.all){
-			object.attachEvent("on"+name, handler);
-		}else{
-			object.addEventListener(name, handler, false);
-		}
-	}
-
-	function removeEvent(object, name, handler){
-		if(document.all){
-			object.detachEvent("on"+name, handler);
-		}else{
-			object.removeEventListener(name, handler, false);
-		}
-	}
-
-	function cancelEvent(event){
-		if(document.all){
-			event.cancelBubble = true;
-		}else{
-			event.stopPropagation();
-		}
-	}
-
-	function onError(msg, href, lineNo){
-		var lastSlash = href.lastIndexOf("/");
-		var fileName = lastSlash == -1 ? href : href.substr(lastSlash+1);
-
-		var html = [
-			'<span class="errorMessage">', msg, '</span>',
-			'<div class="objectBox-sourceLink">', fileName, ' (line ', lineNo, ')</div>'
-		];
-
-		logRow(html, "error");
-	}
-
-
-	//After converting to div instead of iframe, now getting two keydowns right away in IE 6.
-	//Make sure there is a little bit of delay.
-	var onKeyDownTime = new Date().getTime();
-
-	function onKeyDown(event){
-		var timestamp = (new Date()).getTime();
-		if(timestamp > onKeyDownTime + 200){
-			event = dojo.fixEvent(event);
-			var keys = dojo.keys;
-			var ekc = event.keyCode;
-			onKeyDownTime = timestamp;
-			if(ekc == keys.F12){
-				toggleConsole();
-			}else if(
-				(ekc == keys.NUMPAD_ENTER || ekc == 76) &&
-				event.shiftKey &&
-				(event.metaKey || event.ctrlKey)
-			){
-				focusCommandLine();
-			}else{
-				return;
-			}
-			cancelEvent(event);
-		}
-	}
-
-	function onCommandLineKeyDown(e){
-		var dk = dojo.keys;
-		if(e.keyCode == 13 && commandLine.value){
-			addToHistory(commandLine.value);
-			evalCommandLine();
-		}else if(e.keyCode == 27){
-			commandLine.value = "";
-		}else if(e.keyCode == dk.UP_ARROW || e.charCode == dk.UP_ARROW){
-			navigateHistory("older");
-		}else if(e.keyCode == dk.DOWN_ARROW || e.charCode == dk.DOWN_ARROW){
-			navigateHistory("newer");
-		}else if(e.keyCode == dk.HOME || e.charCode == dk.HOME){
-			historyPosition = 1;
-			navigateHistory("older");
-		}else if(e.keyCode == dk.END || e.charCode == dk.END){
-			historyPosition = 999999;
-			navigateHistory("newer");
-		}
-	}
-
-	var historyPosition = -1;
-	var historyCommandLine = null;
-
-	function addToHistory(value){
-		var history = cookie("firebug_history");
-		history = (history) ? dojo.fromJson(history) : [];
-		var pos = dojo.indexOf(history, value);
-		if (pos != -1){
-			history.splice(pos, 1);
-		}
-		history.push(value);
-		cookie("firebug_history", dojo.toJson(history), 30);
-		while(history.length && !cookie("firebug_history")){
-			history.shift();
-			cookie("firebug_history", dojo.toJson(history), 30);
-		}
-		historyCommandLine = null;
-		historyPosition = -1;
-	}
-
-	function navigateHistory(direction){
-		var history = cookie("firebug_history");
-		history = (history) ? dojo.fromJson(history) : [];
-		if(!history.length){
-			return;
-		}
-
-		if(historyCommandLine === null){
-			historyCommandLine = commandLine.value;
-		}
-
-		if(historyPosition == -1){
-			historyPosition = history.length;
-		}
-
-		if(direction == "older"){
-			--historyPosition;
-			if(historyPosition < 0){
-				historyPosition = 0;
-			}
-		}else if(direction == "newer"){
-			++historyPosition;
-			if(historyPosition > history.length){
-				historyPosition = history.length;
-			}
-		}
-
-		if(historyPosition == history.length){
-			commandLine.value = historyCommandLine;
-			historyCommandLine = null;
-		}else{
-			commandLine.value = history[historyPosition];
-		}
-	}
-
-	function cookie(name, value){
-		var c = document.cookie;
-		if(arguments.length == 1){
-			var matches = c.match(new RegExp("(?:^|; )" + name + "=([^;]*)"));
-			return matches ? decodeURIComponent(matches[1]) : undefined; // String or undefined
-		}else{
-			var d = new Date();
-			d.setMonth(d.getMonth()+1);
-			document.cookie = name + "=" + encodeURIComponent(value) + ((d.toUtcString) ? "; expires=" + d.toUTCString() : "");
-		}
-	}
-
-	function isArray(it){
-		return it && it instanceof Array || typeof it == "array";
-	}
-
-	//***************************************************************************************************
-	// Print Object Helpers
-	function objectLength(o){
-		var cnt = 0;
-		for(var nm in o){
-			cnt++;
-		}
-		return cnt;
-	}
-
-	function printObject(o, i, txt, used){
-		// Recursively trace object, indenting to represent depth for display in object inspector
-		var ind = " \t";
-		txt = txt || "";
-		i = i || ind;
-		used = used || [];
-		var opnCls;
-
-		if(o && o.nodeType == 1){
-			var html = [];
-			appendNode(o, html);
-			return html.join("");
-		}
-
-		var br=",\n", cnt = 0, length = objectLength(o);
-
-		if(o instanceof Date){
-			return i + o.toString() + br;
-		}
-		looking:
-		for(var nm in o){
-			cnt++;
-			if(cnt==length){br = "\n";}
-			if(o[nm] === window || o[nm] === document){
-				// do nothing
-			}else if(o[nm] === null){
-				txt += i+nm + " : NULL" + br;
-			}else if(o[nm] && o[nm].nodeType){
-				if(o[nm].nodeType == 1){
-					//txt += i+nm + " : < "+o[nm].tagName+" id=\""+ o[nm].id+"\" />" + br;
-				}else if(o[nm].nodeType == 3){
-					txt += i+nm + " : [ TextNode "+o[nm].data + " ]" + br;
-				}
-
-			}else if(typeof o[nm] == "object" && (o[nm] instanceof String || o[nm] instanceof Number || o[nm] instanceof Boolean)){
-				txt += i+nm + " : " + o[nm] + "," + br;
-
-			}else if(o[nm] instanceof Date){
-				txt += i+nm + " : " + o[nm].toString() + br;
-
-			}else if(typeof(o[nm]) == "object" && o[nm]){
-				for(var j = 0, seen; seen = used[j]; j++){
-					if(o[nm] === seen){
-						txt += i+nm + " : RECURSION" + br;
-						continue looking;
-					}
-				}
-				used.push(o[nm]);
-
-				opnCls = (isArray(o[nm]))?["[","]"]:["{","}"];
-				txt += i+nm +" : " + opnCls[0] + "\n";//non-standard break, (no comma)
-				txt += printObject(o[nm], i+ind, "", used);
-				txt += i + opnCls[1] + br;
-
-			}else if(typeof o[nm] == "undefined"){
-				txt += i+nm + " : undefined" + br;
-			}else if(nm == "toString" && typeof o[nm] == "function"){
-				var toString = o[nm]();
-				if(typeof toString == "string" && toString.match(/function ?(.*?)\(/)){
-					toString = escapeHTML(getObjectAbbr(o[nm]));
-				}
-				txt += i+nm +" : " + toString + br;
-			}else{
-				txt += i+nm +" : "+ escapeHTML(getObjectAbbr(o[nm])) + br;
-			}
-		}
-		return txt;
-	}
-
-	function getObjectAbbr(obj){
-		// Gets an abbreviation of an object for display in log
-		// X items in object, including id
-		// X items in an array
-		// TODO: Firebug Sr. actually goes by char count
-		var isError = (obj instanceof Error);
-		if(obj.nodeType == 1){
-			return escapeHTML('< '+obj.tagName.toLowerCase()+' id=\"'+ obj.id+ '\" />');
-		}
-		if(obj.nodeType == 3){
-			return escapeHTML('[TextNode: "'+obj.nodeValue+'"]');
-		}
-		var nm = (obj && (obj.id || obj.name || obj.ObjectID || obj.widgetId));
-		if(!isError && nm){ return "{"+nm+"}";	}
-
-		var obCnt = 2;
-		var arCnt = 4;
-		var cnt = 0;
-
-		if(isError){
-			nm = "[ Error: "+(obj.message || obj.description || obj)+" ]";
-		}else if(isArray(obj)){
-			nm = "[" + obj.slice(0,arCnt).join(",");
-			if(obj.length > arCnt){
-				nm += " ... ("+obj.length+" items)";
-			}
-			nm += "]";
-		}else if(typeof obj == "function"){
-			nm = obj + "";
-			var reg = /function\s*([^\(]*)(\([^\)]*\))[^\{]*\{/;
-			var m = reg.exec(nm);
-			if(m){
-				if(!m[1]){
-					m[1] = "function";
-				}
-				nm = m[1] + m[2];
-			}else{
-				nm = "function()";
-			}
-		}else if(typeof obj != "object" || typeof obj == "string"){
-			nm = obj + "";
-		}else{
-			nm = "{";
-			for(var i in obj){
-				cnt++;
-				if(cnt > obCnt){ break; }
-				nm += i+":"+escapeHTML(obj[i])+"  ";
-			}
-			nm+="}";
-		}
-
-		return nm;
-	}
-
-	//*************************************************************************************
-
-	//window.onerror = onError;
-
-	addEvent(document, has("ie") || has("safari") ? "keydown" : "keypress", onKeyDown);
-
-	if(	(document.documentElement.getAttribute("debug") == "true")||
-		(dojo.config.isDebug)
-	){
-		toggleConsole(true);
-	}
-
-	dojo.addOnWindowUnload(function(){
-		// Erase the globals and event handlers I created, to prevent spurious leak warnings
-		removeEvent(document, has("ie") || has("safari") ? "keydown" : "keypress", onKeyDown);
-		window.onFirebugResize = null;
-		window.console = null;
-	});
-
-});
Binary file server/src/main/resources/_firebug/infoIcon.png has changed
Binary file server/src/main/resources/_firebug/tab_lft_norm.png has changed
Binary file server/src/main/resources/_firebug/tab_lft_over.png has changed
Binary file server/src/main/resources/_firebug/tab_rgt_norm.png has changed
Binary file server/src/main/resources/_firebug/tab_rgt_over.png has changed
Binary file server/src/main/resources/_firebug/warningIcon.png has changed
--- a/server/src/main/resources/log4j.xml	Tue Nov 13 11:46:39 2012 +0100
+++ b/server/src/main/resources/log4j.xml	Tue Nov 06 13:23:19 2012 +0100
@@ -5,15 +5,40 @@
   <appender name="console" class="org.apache.log4j.ConsoleAppender"> 
     <param name="Target" value="System.out"/> 
     <layout class="org.apache.log4j.PatternLayout"> 
-      <param name="ConversionPattern" value="%-5p %c{1} - %m%n"/> 
+      <param name="ConversionPattern" value="%d{ABSOLUTE} %5p %t %c{2}:%L - %m%n"/> 
     </layout> 
-  </appender> 
+  </appender>
   <logger name="org.iri_research.renkan">
     <level value="DEBUG" />
   </logger>
+  <logger name="org.eclipse.jetty.util.log">
+    <level value="INFO" />
+  </logger>
+  <logger name="org.springframework.beans.factory">
+      <level value="DEBUG" />
+  </logger>
   <root> 
     <priority value ="WARN" /> 
     <appender-ref ref="console" /> 
   </root>
+ <!--
+log4j.rootCategory=INFO, stdout
+
+log4j.appender.stdout=org.springframework.data.document.mongodb.log4j.MongoLog4jAppender
+log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
+log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - <%m>%n
+log4j.appender.stdout.host = localhost 
+log4j.appender.stdout.port = 27017
+log4j.appender.stdout.database = logs
+log4j.appender.stdout.collectionPattern = %X{year}%X{month}
+log4j.appender.stdout.applicationId = my.application
+log4j.appender.stdout.warnOrHigherWriteConcern = FSYNC_SAFE
+
+log4j.category.org.apache.activemq=ERROR
+log4j.category.org.springframework.batch=DEBUG
+log4j.category.org.springframework.data.document.mongodb=DEBUG
+log4j.category.org.springframework.transaction=INFO
+-->
   
-</log4j:configuration>
\ No newline at end of file
+</log4j:configuration>
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/main/web-resources/_firebug/LICENSE	Tue Nov 06 13:23:19 2012 +0100
@@ -0,0 +1,37 @@
+License Disclaimer:
+
+All contents of this directory are Copyright (c) the Dojo Foundation, with the
+following exceptions:
+-------------------------------------------------------------------------------
+
+firebug.html, firebug.js, errIcon.png, infoIcon.png, warningIcon.png:
+	* Copyright (c) 2006-2007, Joe Hewitt, All rights reserved.
+	  Distributed under the terms of the BSD License (see below)
+
+-------------------------------------------------------------------------------
+
+Copyright (c) 2006-2007, Joe Hewitt
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+  * Redistributions of source code must retain the above copyright notice, this
+	list of conditions and the following disclaimer.
+  * Redistributions in binary form must reproduce the above copyright notice,
+	this list of conditions and the following disclaimer in the documentation
+	and/or other materials provided with the distribution.
+  * Neither the name of the Dojo Foundation nor the names of its contributors
+	may be used to endorse or promote products derived from this software
+	without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Binary file server/src/main/web-resources/_firebug/errorIcon.png has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/main/web-resources/_firebug/firebug.css	Tue Nov 06 13:23:19 2012 +0100
@@ -0,0 +1,208 @@
+.firebug {
+	margin: 0;
+	background:#fff;
+	font-family: Lucida Grande, Tahoma, sans-serif;
+	font-size: 11px;
+	overflow: hidden;
+	border: 1px solid black;
+	position: relative;
+}
+.firebug a {
+	text-decoration: none;
+}
+.firebug a:hover {
+	text-decoration: underline;
+}
+.firebug a:visited{
+	color:#0000FF;
+}
+.firebug #firebugToolbar {
+	height: 18px;
+	line-height:18px;
+	border-top: 1px solid ThreeDHighlight;
+	border-bottom: 1px solid ThreeDShadow;
+	padding: 2px 6px;
+	
+	background:#f0f0f0;
+}
+.firebug #firebugLog, .firebug #objectLog {
+	overflow: auto;
+	position: absolute;
+	left: 0;
+	width: 100%;
+}
+#objectLog{
+	overflow:scroll;
+	height:258px;
+}
+.firebug #firebugCommandLine {
+	position: absolute;
+	bottom: 0;
+	left: 0;
+	width: 100%;
+	height: 18px;
+	border: none;
+	border-top: 1px solid ThreeDShadow;
+}
+.firebug .logRow {
+	position: relative;
+	border-bottom: 1px solid #D7D7D7;
+	padding: 2px 4px 1px 6px;
+	background-color: #FFFFFF;
+}
+.firebug .logRow-command {
+	font-family: Monaco, monospace;
+	color: blue;
+}
+.firebug .objectBox-null {
+	padding: 0 2px;
+	border: 1px solid #666666;
+	background-color: #888888;
+	color: #FFFFFF;
+}
+.firebug .objectBox-string {
+	font-family: Monaco, monospace;
+	color: red;
+	white-space: pre;
+}
+.firebug .objectBox-number {
+	color: #000088;
+}
+.firebug .objectBox-function {
+	font-family: Monaco, monospace;
+	color: DarkGreen;
+}
+.firebug .objectBox-object {
+	color: DarkGreen;
+	font-weight: bold;
+}
+.firebug .logRow-info,
+.firebug .logRow-error,
+.firebug .logRow-warning
+ {
+	background: #00FFFF no-repeat 2px 2px;
+	padding-left: 20px;
+	padding-bottom: 3px;
+}
+.firebug .logRow-info {
+	background: #FFF url(infoIcon.png) no-repeat 2px 2px;
+	padding-left: 20px;
+	padding-bottom: 3px;
+}
+.firebug .logRow-warning {
+	
+	background: #00FFFF url(warningIcon.png) no-repeat 2px 2px;
+	padding-left: 20px;
+	padding-bottom: 3px;
+}
+.firebug .logRow-error {
+	background: LightYellow url(errorIcon.png) no-repeat 2px 2px;
+	padding-left: 20px;
+	padding-bottom: 3px;
+}
+.firebug .errorMessage {
+	vertical-align: top;
+	color: #FF0000;
+}
+.firebug .objectBox-sourceLink {
+	position: absolute;
+	right: 4px;
+	top: 2px;
+	padding-left: 8px;
+	font-family: Lucida Grande, sans-serif;
+	font-weight: bold;
+	color: #0000FF;
+}
+.firebug .logRow-group {
+	background: #EEEEEE;
+	border-bottom: none;
+}
+.firebug .logGroup {
+	background: #EEEEEE;
+}
+.firebug .logGroupBox {
+	margin-left: 24px;
+	border-top: 1px solid #D7D7D7;
+	border-left: 1px solid #D7D7D7;
+}
+.firebug .selectorTag,
+.firebug .selectorId,
+.firebug .selectorClass {
+	font-family: Monaco, monospace;
+	font-weight: normal;
+}
+.firebug .selectorTag {
+	color: #0000FF;
+}
+.firebug .selectorId {
+	color: DarkBlue;
+}
+.firebug .selectorClass {
+	color: red;
+}
+.firebug .objectBox-element {
+	font-family: Monaco, monospace;
+	color: #000088;
+}
+.firebug .nodeChildren {
+	margin-left: 16px;
+}
+.firebug .nodeTag {
+	color: blue;
+}
+.firebug .nodeValue {
+	color: #FF0000;
+	font-weight: normal;
+}
+.firebug .nodeText,
+.firebug .nodeComment {
+	margin: 0 2px;
+	vertical-align: top;
+}
+.firebug .nodeText {
+	color: #333333;
+}
+.firebug .nodeComment {
+	color: DarkGreen;
+}
+.firebug .propertyNameCell {
+	vertical-align: top;
+}
+.firebug .propertyName {
+	font-weight: bold;
+}
+#firebugToolbar ul.tabs{
+	margin:0 !important;
+	padding:0;
+}
+#firebugToolbar ul.tabs li{
+	list-style:none;
+	background:transparent url(tab_lft_norm.png) no-repeat left;
+	line-height:18px;
+	float:left;
+	margin-left:5px;
+}
+#firebugToolbar ul.tabs li.right{
+	float:right;
+	margin-right:5px;
+	margin-left:0;
+}
+#firebugToolbar ul.tabs li.gap{
+	margin-left:20px;
+}
+#firebugToolbar .tabs a{
+	text-decoration:none;
+	background:transparent url(tab_rgt_norm.png) no-repeat right;
+	line-height:18px;
+	padding:3px 9px 4px 0px;
+	margin-left:9px;
+	color:#333333;
+}
+#firebugToolbar .tabs li:hover{
+	background:transparent url(tab_lft_over.png) no-repeat left;
+}
+#firebugToolbar .tabs a:hover{
+	text-decoration:none;
+	background:transparent url(tab_rgt_over.png) no-repeat right;
+	color:#FFFFFF;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/main/web-resources/_firebug/firebug.js	Tue Nov 06 13:23:19 2012 +0100
@@ -0,0 +1,898 @@
+/*
+	Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved.
+	Available via Academic Free License >= 2.1 OR the modified BSD license.
+	see: http://dojotoolkit.org/license for details
+*/
+
+//>>built
+define("dojo/_firebug/firebug",["../_base/kernel","require","../_base/html","../sniff","../_base/array","../_base/lang","../_base/event","../_base/unload"],function(_1,_2,_3,_4){
+var _5=(/Trident/.test(window.navigator.userAgent));
+if(_5){
+var _6=["log","info","debug","warn","error"];
+for(var i=0;i<_6.length;i++){
+var m=_6[i];
+if(!console[m]||console[m]._fake){
+continue;
+}
+var n="_"+_6[i];
+console[n]=console[m];
+console[m]=(function(){
+var _7=n;
+return function(){
+console[_7](Array.prototype.join.call(arguments," "));
+};
+})();
+}
+try{
+console.clear();
+}
+catch(e){
+}
+}
+if(_4("ff")||_4("chrome")||_4("safari")||_5||window.firebug||(typeof console!="undefined"&&console.firebug)||_1.config.useCustomLogger||_4("air")){
+return;
+}
+try{
+if(window!=window.parent){
+if(window.parent["console"]){
+window.console=window.parent.console;
+}
+return;
+}
+}
+catch(e){
+}
+var _8=document;
+var _9=window;
+var _a=0;
+var _b=null;
+var _c=null;
+var _d=null;
+var _e=null;
+var _f=null;
+var _10=null;
+var _11=false;
+var _12=[];
+var _13=[];
+var _14={};
+var _15={};
+var _16=null;
+var _17;
+var _18;
+var _19=false;
+var _1a=null;
+var _1b=document.createElement("div");
+var _1c;
+var _1d;
+window.console={_connects:[],log:function(){
+_1e(arguments,"");
+},debug:function(){
+_1e(arguments,"debug");
+},info:function(){
+_1e(arguments,"info");
+},warn:function(){
+_1e(arguments,"warning");
+},error:function(){
+_1e(arguments,"error");
+},assert:function(_1f,_20){
+if(!_1f){
+var _21=[];
+for(var i=1;i<arguments.length;++i){
+_21.push(arguments[i]);
+}
+_1e(_21.length?_21:["Assertion Failure"],"error");
+throw _20?_20:"Assertion Failure";
+}
+},dir:function(obj){
+var str=_22(obj);
+str=str.replace(/\n/g,"<br />");
+str=str.replace(/\t/g,"&nbsp;&nbsp;&nbsp;&nbsp;");
+_23([str],"dir");
+},dirxml:function(_24){
+var _25=[];
+_26(_24,_25);
+_23(_25,"dirxml");
+},group:function(){
+_23(arguments,"group",_27);
+},groupEnd:function(){
+_23(arguments,"",_28);
+},time:function(_29){
+_14[_29]=new Date().getTime();
+},timeEnd:function(_2a){
+if(_2a in _14){
+var _2b=(new Date()).getTime()-_14[_2a];
+_1e([_2a+":",_2b+"ms"]);
+delete _14[_2a];
+}
+},count:function(_2c){
+if(!_15[_2c]){
+_15[_2c]=0;
+}
+_15[_2c]++;
+_1e([_2c+": "+_15[_2c]]);
+},trace:function(_2d){
+var _2e=_2d||3;
+var f=console.trace.caller;
+for(var i=0;i<_2e;i++){
+var _2f=f.toString();
+var _30=[];
+for(var a=0;a<f.arguments.length;a++){
+_30.push(f.arguments[a]);
+}
+if(f.arguments.length){
+}else{
+}
+f=f.caller;
+}
+},profile:function(){
+this.warn(["profile() not supported."]);
+},profileEnd:function(){
+},clear:function(){
+if(_c){
+while(_c.childNodes.length){
+_1.destroy(_c.firstChild);
+}
+}
+_1.forEach(this._connects,_1.disconnect);
+},open:function(){
+_31(true);
+},close:function(){
+if(_11){
+_31();
+}
+},_restoreBorder:function(){
+if(_1c){
+_1c.style.border=_1d;
+}
+},openDomInspector:function(){
+_19=true;
+_c.style.display="none";
+_16.style.display="block";
+_d.style.display="none";
+document.body.style.cursor="pointer";
+_17=_1.connect(document,"mousemove",function(evt){
+if(!_19){
+return;
+}
+if(!_1a){
+_1a=setTimeout(function(){
+_1a=null;
+},50);
+}else{
+return;
+}
+var _32=evt.target;
+if(_32&&(_1c!==_32)){
+var _33=true;
+console._restoreBorder();
+var _34=[];
+_26(_32,_34);
+_16.innerHTML=_34.join("");
+_1c=_32;
+_1d=_1c.style.border;
+_1c.style.border="#0000FF 1px solid";
+}
+});
+setTimeout(function(){
+_18=_1.connect(document,"click",function(evt){
+document.body.style.cursor="";
+_19=!_19;
+_1.disconnect(_18);
+});
+},30);
+},_closeDomInspector:function(){
+document.body.style.cursor="";
+_1.disconnect(_17);
+_1.disconnect(_18);
+_19=false;
+console._restoreBorder();
+},openConsole:function(){
+_c.style.display="block";
+_16.style.display="none";
+_d.style.display="none";
+console._closeDomInspector();
+},openObjectInspector:function(){
+_c.style.display="none";
+_16.style.display="none";
+_d.style.display="block";
+console._closeDomInspector();
+},recss:function(){
+var i,a,s;
+a=document.getElementsByTagName("link");
+for(i=0;i<a.length;i++){
+s=a[i];
+if(s.rel.toLowerCase().indexOf("stylesheet")>=0&&s.href){
+var h=s.href.replace(/(&|%5C?)forceReload=\d+/,"");
+s.href=h+(h.indexOf("?")>=0?"&":"?")+"forceReload="+new Date().valueOf();
+}
+}
+}};
+function _31(_35){
+_11=_35||!_11;
+if(_b){
+_b.style.display=_11?"block":"none";
+}
+};
+function _36(){
+_31(true);
+if(_f){
+_f.focus();
+}
+};
+function _37(x,y,w,h){
+var win=window.open("","_firebug","status=0,menubar=0,resizable=1,top="+y+",left="+x+",width="+w+",height="+h+",scrollbars=1,addressbar=0");
+if(!win){
+var msg="Firebug Lite could not open a pop-up window, most likely because of a blocker.\n"+"Either enable pop-ups for this domain, or change the djConfig to popup=false.";
+alert(msg);
+}
+_38(win);
+var _39=win.document;
+var _3a="<html style=\"height:100%;\"><head><title>Firebug Lite</title></head>\n"+"<body bgColor=\"#ccc\" style=\"height:97%;\" onresize=\"opener.onFirebugResize()\">\n"+"<div id=\"fb\"></div>"+"</body></html>";
+_39.write(_3a);
+_39.close();
+return win;
+};
+function _38(wn){
+var d=new Date();
+d.setTime(d.getTime()+(60*24*60*60*1000));
+d=d.toUTCString();
+var dc=wn.document,_3b;
+if(wn.innerWidth){
+_3b=function(){
+return {w:wn.innerWidth,h:wn.innerHeight};
+};
+}else{
+if(dc.documentElement&&dc.documentElement.clientWidth){
+_3b=function(){
+return {w:dc.documentElement.clientWidth,h:dc.documentElement.clientHeight};
+};
+}else{
+if(dc.body){
+_3b=function(){
+return {w:dc.body.clientWidth,h:dc.body.clientHeight};
+};
+}
+}
+}
+window.onFirebugResize=function(){
+_49(_3b().h);
+clearInterval(wn._firebugWin_resize);
+wn._firebugWin_resize=setTimeout(function(){
+var x=wn.screenLeft,y=wn.screenTop,w=wn.outerWidth||wn.document.body.offsetWidth,h=wn.outerHeight||wn.document.body.offsetHeight;
+document.cookie="_firebugPosition="+[x,y,w,h].join(",")+"; expires="+d+"; path=/";
+},5000);
+};
+};
+function _3c(){
+if(_b){
+return;
+}
+_31(true);
+if(_1.config.popup){
+var _3d="100%";
+var _3e=document.cookie.match(/(?:^|; )_firebugPosition=([^;]*)/);
+var p=_3e?_3e[1].split(","):[2,2,320,480];
+_9=_37(p[0],p[1],p[2],p[3]);
+_8=_9.document;
+_1.config.debugContainerId="fb";
+_9.console=window.console;
+_9.dojo=window.dojo;
+}else{
+_8=document;
+_3d=(_1.config.debugHeight||300)+"px";
+}
+var _3f=_8.createElement("link");
+_3f.href=_2.toUrl("./firebug.css");
+_3f.rel="stylesheet";
+_3f.type="text/css";
+var _40=_8.getElementsByTagName("head");
+if(_40){
+_40=_40[0];
+}
+if(!_40){
+_40=_8.getElementsByTagName("html")[0];
+}
+if(_4("ie")){
+window.setTimeout(function(){
+_40.appendChild(_3f);
+},0);
+}else{
+_40.appendChild(_3f);
+}
+if(_1.config.debugContainerId){
+_b=_8.getElementById(_1.config.debugContainerId);
+}
+if(!_b){
+_b=_8.createElement("div");
+_8.body.appendChild(_b);
+}
+_b.className+=" firebug";
+_b.id="firebug";
+_b.style.height=_3d;
+_b.style.display=(_11?"block":"none");
+var _41=function(_42,_43,_44,_45){
+return "<li class=\""+_45+"\"><a href=\"javascript:void(0);\" onclick=\"console."+_44+"(); return false;\" title=\""+_43+"\">"+_42+"</a></li>";
+};
+_b.innerHTML="<div id=\"firebugToolbar\">"+"  <ul id=\"fireBugTabs\" class=\"tabs\">"+_41("Clear","Remove All Console Logs","clear","")+_41("ReCSS","Refresh CSS without reloading page","recss","")+_41("Console","Show Console Logs","openConsole","gap")+_41("DOM","Show DOM Inspector","openDomInspector","")+_41("Object","Show Object Inspector","openObjectInspector","")+((_1.config.popup)?"":_41("Close","Close the console","close","gap"))+"\t</ul>"+"</div>"+"<input type=\"text\" id=\"firebugCommandLine\" />"+"<div id=\"firebugLog\"></div>"+"<div id=\"objectLog\" style=\"display:none;\">Click on an object in the Log display</div>"+"<div id=\"domInspect\" style=\"display:none;\">Hover over HTML elements in the main page. Click to hold selection.</div>";
+_10=_8.getElementById("firebugToolbar");
+_f=_8.getElementById("firebugCommandLine");
+_46(_f,"keydown",_47);
+_46(_8,_4("ie")||_4("safari")?"keydown":"keypress",_48);
+_c=_8.getElementById("firebugLog");
+_d=_8.getElementById("objectLog");
+_16=_8.getElementById("domInspect");
+_e=_8.getElementById("fireBugTabs");
+_49();
+_4a();
+};
+_1.addOnLoad(_3c);
+function _4b(){
+_8=null;
+if(_9.console){
+_9.console.clear();
+}
+_9=null;
+_b=null;
+_c=null;
+_d=null;
+_16=null;
+_f=null;
+_12=[];
+_13=[];
+_14={};
+};
+function _4c(){
+var _4d=_f.value;
+_f.value="";
+_23([">  ",_4d],"command");
+var _4e;
+try{
+_4e=eval(_4d);
+}
+catch(e){
+}
+};
+function _49(h){
+var _4f=25;
+var _50=h?h-(_4f+_f.offsetHeight+25+(h*0.01))+"px":(_b.offsetHeight-_4f-_f.offsetHeight)+"px";
+_c.style.top=_4f+"px";
+_c.style.height=_50;
+_d.style.height=_50;
+_d.style.top=_4f+"px";
+_16.style.height=_50;
+_16.style.top=_4f+"px";
+_f.style.bottom=0;
+_1.addOnWindowUnload(_4b);
+};
+function _23(_51,_52,_53){
+if(_c){
+_54(_51,_52,_53);
+}else{
+_12.push([_51,_52,_53]);
+}
+};
+function _4a(){
+var _55=_12;
+_12=[];
+for(var i=0;i<_55.length;++i){
+_54(_55[i][0],_55[i][1],_55[i][2]);
+}
+};
+function _54(_56,_57,_58){
+var _59=_c.scrollTop+_c.offsetHeight>=_c.scrollHeight;
+_58=_58||_5a;
+_58(_56,_57);
+if(_59){
+_c.scrollTop=_c.scrollHeight-_c.offsetHeight;
+}
+};
+function _5b(row){
+var _5c=_13.length?_13[_13.length-1]:_c;
+_5c.appendChild(row);
+};
+function _5a(_5d,_5e){
+var row=_c.ownerDocument.createElement("div");
+row.className="logRow"+(_5e?" logRow-"+_5e:"");
+row.innerHTML=_5d.join("");
+_5b(row);
+};
+function _27(_5f,_60){
+_1e(_5f,_60);
+var _61=_c.ownerDocument.createElement("div");
+_61.className="logGroupBox";
+_5b(_61);
+_13.push(_61);
+};
+function _28(){
+_13.pop();
+};
+function _1e(_62,_63){
+var _64=[];
+var _65=_62[0];
+var _66=0;
+if(typeof (_65)!="string"){
+_65="";
+_66=-1;
+}
+var _67=_68(_65);
+for(var i=0;i<_67.length;++i){
+var _69=_67[i];
+if(_69&&typeof _69=="object"){
+_69.appender(_62[++_66],_64);
+}else{
+_6a(_69,_64);
+}
+}
+var ids=[];
+var obs=[];
+for(i=_66+1;i<_62.length;++i){
+_6a(" ",_64);
+var _6b=_62[i];
+if(_6b===undefined||_6b===null){
+_6c(_6b,_64);
+}else{
+if(typeof (_6b)=="string"){
+_6a(_6b,_64);
+}else{
+if(_6b instanceof Date){
+_6a(_6b.toString(),_64);
+}else{
+if(_6b.nodeType==9){
+_6a("[ XmlDoc ]",_64);
+}else{
+var id="_a"+_a++;
+ids.push(id);
+obs.push(_6b);
+var str="<a id=\""+id+"\" href=\"javascript:void(0);\">"+_6d(_6b)+"</a>";
+_6e(str,_64);
+}
+}
+}
+}
+}
+_23(_64,_63);
+for(i=0;i<ids.length;i++){
+var btn=_8.getElementById(ids[i]);
+if(!btn){
+continue;
+}
+btn.obj=obs[i];
+_9.console._connects.push(_1.connect(btn,"onclick",function(){
+console.openObjectInspector();
+try{
+_22(this.obj);
+}
+catch(e){
+this.obj=e;
+}
+_d.innerHTML="<pre>"+_22(this.obj)+"</pre>";
+}));
+}
+};
+function _68(_6f){
+var _70=[];
+var reg=/((^%|[^\\]%)(\d+)?(\.)([a-zA-Z]))|((^%|[^\\]%)([a-zA-Z]))/;
+var _71={s:_6a,d:_72,i:_72,f:_73};
+for(var m=reg.exec(_6f);m;m=reg.exec(_6f)){
+var _74=m[8]?m[8]:m[5];
+var _75=_74 in _71?_71[_74]:_76;
+var _77=m[3]?parseInt(m[3]):(m[4]=="."?-1:0);
+_70.push(_6f.substr(0,m[0][0]=="%"?m.index:m.index+1));
+_70.push({appender:_75,precision:_77});
+_6f=_6f.substr(m.index+m[0].length);
+}
+_70.push(_6f);
+return _70;
+};
+function _78(_79){
+function _7a(ch){
+switch(ch){
+case "<":
+return "&lt;";
+case ">":
+return "&gt;";
+case "&":
+return "&amp;";
+case "'":
+return "&#39;";
+case "\"":
+return "&quot;";
+}
+return "?";
+};
+return String(_79).replace(/[<>&"']/g,_7a);
+};
+function _7b(_7c){
+try{
+return _7c+"";
+}
+catch(e){
+return null;
+}
+};
+function _6e(_7d,_7e){
+_7e.push(_7b(_7d));
+};
+function _6a(_7f,_80){
+_80.push(_78(_7b(_7f)));
+};
+function _6c(_81,_82){
+_82.push("<span class=\"objectBox-null\">",_78(_7b(_81)),"</span>");
+};
+function _83(_84,_85){
+_85.push("<span class=\"objectBox-string\">&quot;",_78(_7b(_84)),"&quot;</span>");
+};
+function _72(_86,_87){
+_87.push("<span class=\"objectBox-number\">",_78(_7b(_86)),"</span>");
+};
+function _73(_88,_89){
+_89.push("<span class=\"objectBox-number\">",_78(_7b(_88)),"</span>");
+};
+function _8a(_8b,_8c){
+_8c.push("<span class=\"objectBox-function\">",_6d(_8b),"</span>");
+};
+function _76(_8d,_8e){
+try{
+if(_8d===undefined){
+_6c("undefined",_8e);
+}else{
+if(_8d===null){
+_6c("null",_8e);
+}else{
+if(typeof _8d=="string"){
+_83(_8d,_8e);
+}else{
+if(typeof _8d=="number"){
+_72(_8d,_8e);
+}else{
+if(typeof _8d=="function"){
+_8a(_8d,_8e);
+}else{
+if(_8d.nodeType==1){
+_8f(_8d,_8e);
+}else{
+if(typeof _8d=="object"){
+_90(_8d,_8e);
+}else{
+_6a(_8d,_8e);
+}
+}
+}
+}
+}
+}
+}
+}
+catch(e){
+}
+};
+function _90(_91,_92){
+var _93=_7b(_91);
+var _94=/\[object (.*?)\]/;
+var m=_94.exec(_93);
+_92.push("<span class=\"objectBox-object\">",m?m[1]:_93,"</span>");
+};
+function _8f(_95,_96){
+_96.push("<span class=\"objectBox-selector\">");
+_96.push("<span class=\"selectorTag\">",_78(_95.nodeName.toLowerCase()),"</span>");
+if(_95.id){
+_96.push("<span class=\"selectorId\">#",_78(_95.id),"</span>");
+}
+if(_95.className){
+_96.push("<span class=\"selectorClass\">.",_78(_95.className),"</span>");
+}
+_96.push("</span>");
+};
+function _26(_97,_98){
+if(_97.nodeType==1){
+_98.push("<div class=\"objectBox-element\">","&lt;<span class=\"nodeTag\">",_97.nodeName.toLowerCase(),"</span>");
+for(var i=0;i<_97.attributes.length;++i){
+var _99=_97.attributes[i];
+if(!_99.specified){
+continue;
+}
+_98.push("&nbsp;<span class=\"nodeName\">",_99.nodeName.toLowerCase(),"</span>=&quot;<span class=\"nodeValue\">",_78(_99.nodeValue),"</span>&quot;");
+}
+if(_97.firstChild){
+_98.push("&gt;</div><div class=\"nodeChildren\">");
+for(var _9a=_97.firstChild;_9a;_9a=_9a.nextSibling){
+_26(_9a,_98);
+}
+_98.push("</div><div class=\"objectBox-element\">&lt;/<span class=\"nodeTag\">",_97.nodeName.toLowerCase(),"&gt;</span></div>");
+}else{
+_98.push("/&gt;</div>");
+}
+}else{
+if(_97.nodeType==3){
+_98.push("<div class=\"nodeText\">",_78(_97.nodeValue),"</div>");
+}
+}
+};
+function _46(_9b,_9c,_9d){
+if(document.all){
+_9b.attachEvent("on"+_9c,_9d);
+}else{
+_9b.addEventListener(_9c,_9d,false);
+}
+};
+function _9e(_9f,_a0,_a1){
+if(document.all){
+_9f.detachEvent("on"+_a0,_a1);
+}else{
+_9f.removeEventListener(_a0,_a1,false);
+}
+};
+function _a2(_a3){
+if(document.all){
+_a3.cancelBubble=true;
+}else{
+_a3.stopPropagation();
+}
+};
+function _a4(msg,_a5,_a6){
+var _a7=_a5.lastIndexOf("/");
+var _a8=_a7==-1?_a5:_a5.substr(_a7+1);
+var _a9=["<span class=\"errorMessage\">",msg,"</span>","<div class=\"objectBox-sourceLink\">",_a8," (line ",_a6,")</div>"];
+_23(_a9,"error");
+};
+var _aa=new Date().getTime();
+function _48(_ab){
+var _ac=(new Date()).getTime();
+if(_ac>_aa+200){
+_ab=_1.fixEvent(_ab);
+var _ad=_1.keys;
+var ekc=_ab.keyCode;
+_aa=_ac;
+if(ekc==_ad.F12){
+_31();
+}else{
+if((ekc==_ad.NUMPAD_ENTER||ekc==76)&&_ab.shiftKey&&(_ab.metaKey||_ab.ctrlKey)){
+_36();
+}else{
+return;
+}
+}
+_a2(_ab);
+}
+};
+function _47(e){
+var dk=_1.keys;
+if(e.keyCode==13&&_f.value){
+_ae(_f.value);
+_4c();
+}else{
+if(e.keyCode==27){
+_f.value="";
+}else{
+if(e.keyCode==dk.UP_ARROW||e.charCode==dk.UP_ARROW){
+_af("older");
+}else{
+if(e.keyCode==dk.DOWN_ARROW||e.charCode==dk.DOWN_ARROW){
+_af("newer");
+}else{
+if(e.keyCode==dk.HOME||e.charCode==dk.HOME){
+_b0=1;
+_af("older");
+}else{
+if(e.keyCode==dk.END||e.charCode==dk.END){
+_b0=999999;
+_af("newer");
+}
+}
+}
+}
+}
+}
+};
+var _b0=-1;
+var _b1=null;
+function _ae(_b2){
+var _b3=_b4("firebug_history");
+_b3=(_b3)?_1.fromJson(_b3):[];
+var pos=_1.indexOf(_b3,_b2);
+if(pos!=-1){
+_b3.splice(pos,1);
+}
+_b3.push(_b2);
+_b4("firebug_history",_1.toJson(_b3),30);
+while(_b3.length&&!_b4("firebug_history")){
+_b3.shift();
+_b4("firebug_history",_1.toJson(_b3),30);
+}
+_b1=null;
+_b0=-1;
+};
+function _af(_b5){
+var _b6=_b4("firebug_history");
+_b6=(_b6)?_1.fromJson(_b6):[];
+if(!_b6.length){
+return;
+}
+if(_b1===null){
+_b1=_f.value;
+}
+if(_b0==-1){
+_b0=_b6.length;
+}
+if(_b5=="older"){
+--_b0;
+if(_b0<0){
+_b0=0;
+}
+}else{
+if(_b5=="newer"){
+++_b0;
+if(_b0>_b6.length){
+_b0=_b6.length;
+}
+}
+}
+if(_b0==_b6.length){
+_f.value=_b1;
+_b1=null;
+}else{
+_f.value=_b6[_b0];
+}
+};
+function _b4(_b7,_b8){
+var c=document.cookie;
+if(arguments.length==1){
+var _b9=c.match(new RegExp("(?:^|; )"+_b7+"=([^;]*)"));
+return _b9?decodeURIComponent(_b9[1]):undefined;
+}else{
+var d=new Date();
+d.setMonth(d.getMonth()+1);
+document.cookie=_b7+"="+encodeURIComponent(_b8)+((d.toUtcString)?"; expires="+d.toUTCString():"");
+}
+};
+function _ba(it){
+return it&&it instanceof Array||typeof it=="array";
+};
+function _bb(o){
+var cnt=0;
+for(var nm in o){
+cnt++;
+}
+return cnt;
+};
+function _22(o,i,txt,_bc){
+var ind=" \t";
+txt=txt||"";
+i=i||ind;
+_bc=_bc||[];
+var _bd;
+if(o&&o.nodeType==1){
+var _be=[];
+_26(o,_be);
+return _be.join("");
+}
+var br=",\n",cnt=0,_bf=_bb(o);
+if(o instanceof Date){
+return i+o.toString()+br;
+}
+looking:
+for(var nm in o){
+cnt++;
+if(cnt==_bf){
+br="\n";
+}
+if(o[nm]===window||o[nm]===document){
+}else{
+if(o[nm]===null){
+txt+=i+nm+" : NULL"+br;
+}else{
+if(o[nm]&&o[nm].nodeType){
+if(o[nm].nodeType==1){
+}else{
+if(o[nm].nodeType==3){
+txt+=i+nm+" : [ TextNode "+o[nm].data+" ]"+br;
+}
+}
+}else{
+if(typeof o[nm]=="object"&&(o[nm] instanceof String||o[nm] instanceof Number||o[nm] instanceof Boolean)){
+txt+=i+nm+" : "+o[nm]+","+br;
+}else{
+if(o[nm] instanceof Date){
+txt+=i+nm+" : "+o[nm].toString()+br;
+}else{
+if(typeof (o[nm])=="object"&&o[nm]){
+for(var j=0,_c0;_c0=_bc[j];j++){
+if(o[nm]===_c0){
+txt+=i+nm+" : RECURSION"+br;
+continue looking;
+}
+}
+_bc.push(o[nm]);
+_bd=(_ba(o[nm]))?["[","]"]:["{","}"];
+txt+=i+nm+" : "+_bd[0]+"\n";
+txt+=_22(o[nm],i+ind,"",_bc);
+txt+=i+_bd[1]+br;
+}else{
+if(typeof o[nm]=="undefined"){
+txt+=i+nm+" : undefined"+br;
+}else{
+if(nm=="toString"&&typeof o[nm]=="function"){
+var _c1=o[nm]();
+if(typeof _c1=="string"&&_c1.match(/function ?(.*?)\(/)){
+_c1=_78(_6d(o[nm]));
+}
+txt+=i+nm+" : "+_c1+br;
+}else{
+txt+=i+nm+" : "+_78(_6d(o[nm]))+br;
+}
+}
+}
+}
+}
+}
+}
+}
+}
+return txt;
+};
+function _6d(obj){
+var _c2=(obj instanceof Error);
+if(obj.nodeType==1){
+return _78("< "+obj.tagName.toLowerCase()+" id=\""+obj.id+"\" />");
+}
+if(obj.nodeType==3){
+return _78("[TextNode: \""+obj.nodeValue+"\"]");
+}
+var nm=(obj&&(obj.id||obj.name||obj.ObjectID||obj.widgetId));
+if(!_c2&&nm){
+return "{"+nm+"}";
+}
+var _c3=2;
+var _c4=4;
+var cnt=0;
+if(_c2){
+nm="[ Error: "+(obj.message||obj.description||obj)+" ]";
+}else{
+if(_ba(obj)){
+nm="["+obj.slice(0,_c4).join(",");
+if(obj.length>_c4){
+nm+=" ... ("+obj.length+" items)";
+}
+nm+="]";
+}else{
+if(typeof obj=="function"){
+nm=obj+"";
+var reg=/function\s*([^\(]*)(\([^\)]*\))[^\{]*\{/;
+var m=reg.exec(nm);
+if(m){
+if(!m[1]){
+m[1]="function";
+}
+nm=m[1]+m[2];
+}else{
+nm="function()";
+}
+}else{
+if(typeof obj!="object"||typeof obj=="string"){
+nm=obj+"";
+}else{
+nm="{";
+for(var i in obj){
+cnt++;
+if(cnt>_c3){
+break;
+}
+nm+=i+":"+_78(obj[i])+"  ";
+}
+nm+="}";
+}
+}
+}
+}
+return nm;
+};
+_46(document,_4("ie")||_4("safari")?"keydown":"keypress",_48);
+if((document.documentElement.getAttribute("debug")=="true")||(_1.config.isDebug)){
+_31(true);
+}
+_1.addOnWindowUnload(function(){
+_9e(document,_4("ie")||_4("safari")?"keydown":"keypress",_48);
+window.onFirebugResize=null;
+window.console=null;
+});
+});
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/main/web-resources/_firebug/firebug.js.uncompressed.js	Tue Nov 06 13:23:19 2012 +0100
@@ -0,0 +1,1191 @@
+define("dojo/_firebug/firebug", [
+	"../_base/kernel",
+	"require",
+	"../_base/html",
+	"../sniff",
+	"../_base/array",
+	"../_base/lang",
+	"../_base/event",
+	"../_base/unload"], function(dojo, require, html, has){
+
+	// module:
+	//		dojo/_firebug/firebug
+	// summary:
+	//		Firebug Lite, the baby brother to Joe Hewitt's Firebug for Mozilla Firefox
+	// description:
+	//		Opens a console for logging, debugging, and error messages.
+	//		Contains partial functionality to Firebug. See function list below.
+	//
+	//		NOTE:
+	//		Firebug is a Firefox extension created by Joe Hewitt (see license). You do not need Dojo to run Firebug.
+	//		Firebug Lite is included in Dojo by permission from Joe Hewitt
+	//		If you are new to Firebug, or used to the Dojo 0.4 dojo.debug, you can learn Firebug
+	//		functionality by reading the function comments below or visiting http://www.getfirebug.com/docs.html
+	//
+	//		NOTE:
+	//		To test Firebug Lite in Firefox:
+	//
+	//		- FF2: set "console = null" before loading dojo and set djConfig.isDebug=true
+	//		- FF3: disable Firebug and set djConfig.isDebug=true
+	//
+	// example:
+	//		Supports inline objects in object inspector window (only simple trace of dom nodes, however)
+	//	|	console.log("my object", {foo:"bar"})
+	// example:
+	//		Option for console to open in popup window
+	//	|	var djConfig = {isDebug: true, popup:true };
+	// example:
+	//		Option for console height (ignored for popup)
+	//	|	var djConfig = {isDebug: true, debugHeight:100 }
+
+
+	var isNewIE = (/Trident/.test(window.navigator.userAgent));
+	if(isNewIE){
+		// Fixing IE's console
+		// IE doesn't insert space between arguments. How annoying.
+		var calls = ["log", "info", "debug", "warn", "error"];
+		for(var i=0;i<calls.length;i++){
+			var m = calls[i];
+			if(!console[m] ||console[m]._fake){
+				// IE9 doesn't have console.debug method, a fake one is added later
+				continue;
+			}
+			var n = "_"+calls[i];
+			console[n] = console[m];
+			console[m] = (function(){
+				var type = n;
+				return function(){
+					console[type](Array.prototype.join.call(arguments, " "));
+				};
+			})();
+		}
+		// clear the console on load. This is more than a convenience - too many logs crashes it.
+		// If closed it throws an error
+		try{ console.clear(); }catch(e){}
+	}
+
+	if(
+		has("ff") ||								// Firefox has Firebug
+		has("chrome") ||							// Chrome 3+ has a console
+		has("safari") ||							// Safari 4 has a console
+		isNewIE ||									// Has the new IE console
+		window.firebug ||							// Testing for mozilla firebug lite
+		(typeof console != "undefined" && console.firebug) || //The firebug console
+		dojo.config.useCustomLogger ||				// Allow custom loggers
+		has("air")									// isDebug triggers AIRInsector, not Firebug
+	){
+		return;
+	}
+
+	// don't build firebug in iframes
+	try{
+		if(window != window.parent){
+			// but if we've got a parent logger, connect to it
+			if(window.parent["console"]){
+				window.console = window.parent.console;
+			}
+			return;
+		}
+	}catch(e){/*squelch*/}
+
+	// ***************************************************************************
+	// Placing these variables before the functions that use them to avoid a
+	// shrinksafe bug where variable renaming does not happen correctly otherwise.
+
+	// most of the objects in this script are run anonomously
+	var _firebugDoc = document;
+	var _firebugWin = window;
+	var __consoleAnchorId__ = 0;
+
+	var consoleFrame = null;
+	var consoleBody = null;
+	var consoleObjectInspector = null;
+	var fireBugTabs = null;
+	var commandLine = null;
+	var consoleToolbar = null;
+
+	var frameVisible = false;
+	var messageQueue = [];
+	var groupStack = [];
+	var timeMap = {};
+	var countMap = {};
+
+	var consoleDomInspector = null;
+	var _inspectionMoveConnection;
+	var _inspectionClickConnection;
+	var _inspectionEnabled = false;
+	var _inspectionTimer = null;
+	var _inspectTempNode = document.createElement("div");
+
+
+	var _inspectCurrentNode;
+	var _restoreBorderStyle;
+
+	// ***************************************************************************
+
+	window.console = {
+		_connects: [],
+		log: function(){
+			// summary:
+			//		Sends arguments to console.
+			logFormatted(arguments, "");
+		},
+
+		debug: function(){
+			// summary:
+			//		Sends arguments to console. Missing finctionality to show script line of trace.
+			logFormatted(arguments, "debug");
+		},
+
+		info: function(){
+			// summary:
+			//		Sends arguments to console, highlighted with (I) icon.
+			logFormatted(arguments, "info");
+		},
+
+		warn: function(){
+			// summary:
+			//		Sends warning arguments to console, highlighted with (!) icon and blue style.
+			logFormatted(arguments, "warning");
+		},
+
+		error: function(){
+			// summary:
+			//		Sends error arguments (object) to console, highlighted with (X) icon and yellow style
+			//		NEW: error object now displays in object inspector
+			logFormatted(arguments, "error");
+		},
+
+		assert: function(truth, message){
+			// summary:
+			//		Tests for true. Throws exception if false.
+			if(!truth){
+				var args = [];
+				for(var i = 1; i < arguments.length; ++i){
+					args.push(arguments[i]);
+				}
+
+				logFormatted(args.length ? args : ["Assertion Failure"], "error");
+				throw message ? message : "Assertion Failure";
+			}
+		},
+
+		dir: function(obj){
+			var str = printObject( obj );
+			str = str.replace(/\n/g, "<br />");
+			str = str.replace(/\t/g, "&nbsp;&nbsp;&nbsp;&nbsp;");
+			logRow([str], "dir");
+		},
+
+		dirxml: function(node){
+			var html = [];
+			appendNode(node, html);
+			logRow(html, "dirxml");
+		},
+
+		group: function(){
+			// summary:
+			//		collects log messages into a group, starting with this call and ending with
+			//		groupEnd(). Missing collapse functionality
+			logRow(arguments, "group", pushGroup);
+		},
+
+		groupEnd: function(){
+			// summary:
+			//		Closes group. See above
+			logRow(arguments, "", popGroup);
+		},
+
+		time: function(name){
+			// summary:
+			//		Starts timers assigned to name given in argument. Timer stops and displays on timeEnd(title);
+			// example:
+			//	|	console.time("load");
+			//	|	console.time("myFunction");
+			//	|	console.timeEnd("load");
+			//	|	console.timeEnd("myFunction");
+			timeMap[name] = new Date().getTime();
+		},
+
+		timeEnd: function(name){
+			// summary:
+			//		See above.
+			if(name in timeMap){
+				var delta = (new Date()).getTime() - timeMap[name];
+				logFormatted([name+ ":", delta+"ms"]);
+				delete timeMap[name];
+			}
+		},
+
+		count: function(name){
+			// summary:
+			//		Not supported
+			if(!countMap[name]) countMap[name] = 0;
+			countMap[name]++;
+			logFormatted([name+": "+countMap[name]]);
+		},
+
+		trace: function(_value){
+			var stackAmt = _value || 3;
+			var f = console.trace.caller; //function that called trace
+			console.log(">>> console.trace(stack)");
+			for(var i=0;i<stackAmt;i++){
+				var func = f.toString();
+				var args=[];
+				for (var a = 0; a < f.arguments.length; a++){
+					args.push(f.arguments[a]);
+				}
+				if(f.arguments.length){
+					console.dir({"function":func, "arguments":args});
+				}else{
+					console.dir({"function":func});
+				}
+
+				f = f.caller;
+			}
+		},
+
+		profile: function(){
+			// summary:
+			//		Not supported
+			this.warn(["profile() not supported."]);
+		},
+
+		profileEnd: function(){ },
+
+		clear: function(){
+			// summary:
+			//		Clears message console. Do not call this directly
+			if(consoleBody){
+				while(consoleBody.childNodes.length){
+					dojo.destroy(consoleBody.firstChild);
+				}
+			}
+			dojo.forEach(this._connects,dojo.disconnect);
+		},
+
+		open: function(){
+			// summary:
+			//		Opens message console. Do not call this directly
+			toggleConsole(true);
+		},
+
+		close: function(){
+			// summary:
+			//		Closes message console. Do not call this directly
+			if(frameVisible){
+				toggleConsole();
+			}
+		},
+		_restoreBorder: function(){
+			if(_inspectCurrentNode){
+				_inspectCurrentNode.style.border = _restoreBorderStyle;
+			}
+		},
+		openDomInspector: function(){
+			_inspectionEnabled = true;
+			consoleBody.style.display = "none";
+			consoleDomInspector.style.display = "block";
+			consoleObjectInspector.style.display = "none";
+			document.body.style.cursor = "pointer";
+			_inspectionMoveConnection = dojo.connect(document, "mousemove", function(evt){
+				if(!_inspectionEnabled){ return; }
+				if(!_inspectionTimer){
+					_inspectionTimer = setTimeout(function(){ _inspectionTimer = null; }, 50);
+				}else{
+					return;
+				}
+				var node = evt.target;
+				if(node && (_inspectCurrentNode !== node)){
+					var parent = true;
+
+					console._restoreBorder();
+					var html = [];
+					appendNode(node, html);
+					consoleDomInspector.innerHTML = html.join("");
+
+					_inspectCurrentNode = node;
+					_restoreBorderStyle = _inspectCurrentNode.style.border;
+					_inspectCurrentNode.style.border = "#0000FF 1px solid";
+				}
+			});
+			setTimeout(function(){
+				_inspectionClickConnection = dojo.connect(document, "click", function(evt){
+					document.body.style.cursor = "";
+					_inspectionEnabled = !_inspectionEnabled;
+					dojo.disconnect(_inspectionClickConnection);
+					// console._restoreBorder();
+				});
+			}, 30);
+		},
+		_closeDomInspector: function(){
+			document.body.style.cursor = "";
+			dojo.disconnect(_inspectionMoveConnection);
+			dojo.disconnect(_inspectionClickConnection);
+			_inspectionEnabled = false;
+			console._restoreBorder();
+		},
+		openConsole:function(){
+			// summary:
+			//		Closes object inspector and opens message console. Do not call this directly
+			consoleBody.style.display = "block";
+			consoleDomInspector.style.display = "none";
+			consoleObjectInspector.style.display = "none";
+			console._closeDomInspector();
+		},
+		openObjectInspector:function(){
+			consoleBody.style.display = "none";
+			consoleDomInspector.style.display = "none";
+			consoleObjectInspector.style.display = "block";
+			console._closeDomInspector();
+		},
+		recss: function(){
+			// this is placed in dojo since the console is most likely
+			// in another window and dojo is easilly accessible
+			var i,a,s;a=document.getElementsByTagName('link');
+			for(i=0;i<a.length;i++){
+				s=a[i];
+				if(s.rel.toLowerCase().indexOf('stylesheet')>=0&&s.href){
+					var h=s.href.replace(/(&|%5C?)forceReload=\d+/,'');
+					s.href=h+(h.indexOf('?')>=0?'&':'?')+'forceReload='+new Date().valueOf();
+				}
+			}
+		}
+	};
+
+	// ***************************************************************************
+
+	function toggleConsole(forceOpen){
+		frameVisible = forceOpen || !frameVisible;
+		if(consoleFrame){
+			consoleFrame.style.display = frameVisible ? "block" : "none";
+		}
+	}
+
+	function focusCommandLine(){
+		toggleConsole(true);
+		if(commandLine){
+			commandLine.focus();
+		}
+	}
+
+	function openWin(x,y,w,h){
+		var win = window.open("","_firebug","status=0,menubar=0,resizable=1,top="+y+",left="+x+",width="+w+",height="+h+",scrollbars=1,addressbar=0");
+		if(!win){
+			var msg = "Firebug Lite could not open a pop-up window, most likely because of a blocker.\n" +
+				"Either enable pop-ups for this domain, or change the djConfig to popup=false.";
+			alert(msg);
+		}
+		createResizeHandler(win);
+		var newDoc=win.document;
+		//Safari needs an HTML height
+		var HTMLstring=	'<html style="height:100%;"><head><title>Firebug Lite</title></head>\n' +
+					'<body bgColor="#ccc" style="height:97%;" onresize="opener.onFirebugResize()">\n' +
+					'<div id="fb"></div>' +
+					'</body></html>';
+
+		newDoc.write(HTMLstring);
+		newDoc.close();
+		return win;
+	}
+
+	function createResizeHandler(wn){
+		// summary:
+		//		Creates handle for onresize window. Called from script in popup's body tag (so that it will work with IE).
+		//
+
+		var d = new Date();
+			d.setTime(d.getTime()+(60*24*60*60*1000)); // 60 days
+			d = d.toUTCString();
+
+			var dc = wn.document,
+				getViewport;
+
+			if (wn.innerWidth){
+				getViewport = function(){
+					return{w:wn.innerWidth, h:wn.innerHeight};
+				};
+			}else if (dc.documentElement && dc.documentElement.clientWidth){
+				getViewport = function(){
+					return{w:dc.documentElement.clientWidth, h:dc.documentElement.clientHeight};
+				};
+			}else if (dc.body){
+				getViewport = function(){
+					return{w:dc.body.clientWidth, h:dc.body.clientHeight};
+				};
+			}
+
+
+		window.onFirebugResize = function(){
+
+			//resize the height of the console log body
+			layout(getViewport().h);
+
+			clearInterval(wn._firebugWin_resize);
+			wn._firebugWin_resize = setTimeout(function(){
+				var x = wn.screenLeft,
+					y = wn.screenTop,
+					w = wn.outerWidth  || wn.document.body.offsetWidth,
+					h = wn.outerHeight || wn.document.body.offsetHeight;
+
+				document.cookie = "_firebugPosition=" + [x,y,w,h].join(",") + "; expires="+d+"; path=/";
+
+			 }, 5000); //can't capture window.onMove - long timeout gives better chance of capturing a resize, then the move
+
+		};
+	}
+
+
+	/*****************************************************************************/
+
+
+	function createFrame(){
+		if(consoleFrame){
+			return;
+		}
+		toggleConsole(true);
+		if(dojo.config.popup){
+			var containerHeight = "100%";
+			var cookieMatch = document.cookie.match(/(?:^|; )_firebugPosition=([^;]*)/);
+			var p = cookieMatch ? cookieMatch[1].split(",") : [2,2,320,480];
+
+			_firebugWin = openWin(p[0],p[1],p[2],p[3]);	// global
+			_firebugDoc = _firebugWin.document;			// global
+
+			dojo.config.debugContainerId = 'fb';
+
+			// connecting popup
+			_firebugWin.console = window.console;
+			_firebugWin.dojo = window.dojo;
+		}else{
+			_firebugDoc = document;
+			containerHeight = (dojo.config.debugHeight || 300) + "px";
+		}
+
+		var styleElement = _firebugDoc.createElement("link");
+		styleElement.href = require.toUrl("./firebug.css");
+		styleElement.rel = "stylesheet";
+		styleElement.type = "text/css";
+		var styleParent = _firebugDoc.getElementsByTagName("head");
+		if(styleParent){
+			styleParent = styleParent[0];
+		}
+		if(!styleParent){
+			styleParent = _firebugDoc.getElementsByTagName("html")[0];
+		}
+		if(has("ie")){
+			window.setTimeout(function(){ styleParent.appendChild(styleElement); }, 0);
+		}else{
+			styleParent.appendChild(styleElement);
+		}
+
+		if(dojo.config.debugContainerId){
+			consoleFrame = _firebugDoc.getElementById(dojo.config.debugContainerId);
+		}
+		if(!consoleFrame){
+			consoleFrame = _firebugDoc.createElement("div");
+			_firebugDoc.body.appendChild(consoleFrame);
+		}
+		consoleFrame.className += " firebug";
+		consoleFrame.id = "firebug";
+		consoleFrame.style.height = containerHeight;
+		consoleFrame.style.display = (frameVisible ? "block" : "none");
+
+		var buildLink = function(label, title, method, _class){
+			return '<li class="'+_class+'"><a href="javascript:void(0);" onclick="console.'+ method +'(); return false;" title="'+title+'">'+label+'</a></li>';
+		};
+		consoleFrame.innerHTML =
+			  '<div id="firebugToolbar">'
+			+ '  <ul id="fireBugTabs" class="tabs">'
+
+			+ buildLink("Clear", "Remove All Console Logs", "clear", "")
+			+ buildLink("ReCSS", "Refresh CSS without reloading page", "recss", "")
+
+			+ buildLink("Console", "Show Console Logs", "openConsole", "gap")
+			+ buildLink("DOM", "Show DOM Inspector", "openDomInspector", "")
+			+ buildLink("Object", "Show Object Inspector", "openObjectInspector", "")
+			+ ((dojo.config.popup) ? "" : buildLink("Close", "Close the console", "close", "gap"))
+
+			+ '	</ul>'
+			+ '</div>'
+			+ '<input type="text" id="firebugCommandLine" />'
+			+ '<div id="firebugLog"></div>'
+			+ '<div id="objectLog" style="display:none;">Click on an object in the Log display</div>'
+			+ '<div id="domInspect" style="display:none;">Hover over HTML elements in the main page. Click to hold selection.</div>';
+
+
+		consoleToolbar = _firebugDoc.getElementById("firebugToolbar");
+
+		commandLine = _firebugDoc.getElementById("firebugCommandLine");
+		addEvent(commandLine, "keydown", onCommandLineKeyDown);
+
+		addEvent(_firebugDoc, has("ie") || has("safari") ? "keydown" : "keypress", onKeyDown);
+
+		consoleBody = _firebugDoc.getElementById("firebugLog");
+		consoleObjectInspector = _firebugDoc.getElementById("objectLog");
+		consoleDomInspector = _firebugDoc.getElementById("domInspect");
+		fireBugTabs = _firebugDoc.getElementById("fireBugTabs");
+		layout();
+		flush();
+	}
+
+	dojo.addOnLoad(createFrame);
+
+	function clearFrame(){
+		_firebugDoc = null;
+
+		if(_firebugWin.console){
+			_firebugWin.console.clear();
+		}
+		_firebugWin = null;
+		consoleFrame = null;
+		consoleBody = null;
+		consoleObjectInspector = null;
+		consoleDomInspector = null;
+		commandLine = null;
+		messageQueue = [];
+		groupStack = [];
+		timeMap = {};
+	}
+
+
+	function evalCommandLine(){
+		var text = commandLine.value;
+		commandLine.value = "";
+
+		logRow([">  ", text], "command");
+
+		var value;
+		try{
+			value = eval(text);
+		}catch(e){
+			console.debug(e); // put exception on the console
+		}
+
+		console.log(value);
+	}
+
+	function layout(h){
+		var tHeight = 25; //consoleToolbar.offsetHeight; // tab style not ready on load - throws off layout
+		var height = h ?
+			h  - (tHeight + commandLine.offsetHeight +25 + (h*.01)) + "px" :
+			(consoleFrame.offsetHeight - tHeight - commandLine.offsetHeight) + "px";
+
+		consoleBody.style.top = tHeight + "px";
+		consoleBody.style.height = height;
+		consoleObjectInspector.style.height = height;
+		consoleObjectInspector.style.top = tHeight + "px";
+		consoleDomInspector.style.height = height;
+		consoleDomInspector.style.top = tHeight + "px";
+		commandLine.style.bottom = 0;
+
+		dojo.addOnWindowUnload(clearFrame);
+	}
+
+	function logRow(message, className, handler){
+		if(consoleBody){
+			writeMessage(message, className, handler);
+		}else{
+			messageQueue.push([message, className, handler]);
+		}
+	}
+
+	function flush(){
+		var queue = messageQueue;
+		messageQueue = [];
+
+		for(var i = 0; i < queue.length; ++i){
+			writeMessage(queue[i][0], queue[i][1], queue[i][2]);
+		}
+	}
+
+	function writeMessage(message, className, handler){
+		var isScrolledToBottom =
+			consoleBody.scrollTop + consoleBody.offsetHeight >= consoleBody.scrollHeight;
+
+		handler = handler||writeRow;
+
+		handler(message, className);
+
+		if(isScrolledToBottom){
+			consoleBody.scrollTop = consoleBody.scrollHeight - consoleBody.offsetHeight;
+		}
+	}
+
+	function appendRow(row){
+		var container = groupStack.length ? groupStack[groupStack.length-1] : consoleBody;
+		container.appendChild(row);
+	}
+
+	function writeRow(message, className){
+		var row = consoleBody.ownerDocument.createElement("div");
+		row.className = "logRow" + (className ? " logRow-"+className : "");
+		row.innerHTML = message.join("");
+		appendRow(row);
+	}
+
+	function pushGroup(message, className){
+		logFormatted(message, className);
+
+		//var groupRow = consoleBody.ownerDocument.createElement("div");
+		//groupRow.className = "logGroup";
+		var groupRowBox = consoleBody.ownerDocument.createElement("div");
+		groupRowBox.className = "logGroupBox";
+		//groupRow.appendChild(groupRowBox);
+		appendRow(groupRowBox);
+		groupStack.push(groupRowBox);
+	}
+
+	function popGroup(){
+		groupStack.pop();
+	}
+
+	// ***************************************************************************
+
+	function logFormatted(objects, className){
+		var html = [];
+
+		var format = objects[0];
+		var objIndex = 0;
+
+		if(typeof(format) != "string"){
+			format = "";
+			objIndex = -1;
+		}
+
+		var parts = parseFormat(format);
+
+		for(var i = 0; i < parts.length; ++i){
+			var part = parts[i];
+			if(part && typeof part == "object"){
+				part.appender(objects[++objIndex], html);
+			}else{
+				appendText(part, html);
+			}
+		}
+
+
+		var ids = [];
+		var obs = [];
+		for(i = objIndex+1; i < objects.length; ++i){
+			appendText(" ", html);
+
+			var object = objects[i];
+			if(object === undefined || object === null ){
+				appendNull(object, html);
+
+			}else if(typeof(object) == "string"){
+				appendText(object, html);
+
+			}else if(object instanceof Date){
+				appendText(object.toString(), html);
+
+			}else if(object.nodeType == 9){
+				appendText("[ XmlDoc ]", html);
+
+			}else{
+				// Create link for object inspector
+				// need to create an ID for this link, since it is currently text
+				var id = "_a" + __consoleAnchorId__++;
+				ids.push(id);
+				// need to save the object, so the arrays line up
+				obs.push(object);
+				var str = '<a id="'+id+'" href="javascript:void(0);">'+getObjectAbbr(object)+'</a>';
+
+				appendLink( str , html);
+			}
+		}
+
+		logRow(html, className);
+
+		// Now that the row is inserted in the DOM, loop through all of the links that were just created
+		for(i=0; i<ids.length; i++){
+			var btn = _firebugDoc.getElementById(ids[i]);
+			if(!btn){ continue; }
+
+			// store the object in the dom btn for reference later
+			// avoid parsing these objects unless necessary
+			btn.obj = obs[i];
+
+			_firebugWin.console._connects.push(dojo.connect(btn, "onclick", function(){
+
+				console.openObjectInspector();
+
+				try{
+					printObject(this.obj);
+				}catch(e){
+					this.obj = e;
+				}
+				consoleObjectInspector.innerHTML = "<pre>" + printObject( this.obj ) + "</pre>";
+			}));
+		}
+	}
+
+	function parseFormat(format){
+		var parts = [];
+
+		var reg = /((^%|[^\\]%)(\d+)?(\.)([a-zA-Z]))|((^%|[^\\]%)([a-zA-Z]))/;
+		var appenderMap = {s: appendText, d: appendInteger, i: appendInteger, f: appendFloat};
+
+		for(var m = reg.exec(format); m; m = reg.exec(format)){
+			var type = m[8] ? m[8] : m[5];
+			var appender = type in appenderMap ? appenderMap[type] : appendObject;
+			var precision = m[3] ? parseInt(m[3]) : (m[4] == "." ? -1 : 0);
+
+			parts.push(format.substr(0, m[0][0] == "%" ? m.index : m.index+1));
+			parts.push({appender: appender, precision: precision});
+
+			format = format.substr(m.index+m[0].length);
+		}
+
+		parts.push(format);
+
+		return parts;
+	}
+
+	function escapeHTML(value){
+		function replaceChars(ch){
+			switch(ch){
+				case "<":
+					return "&lt;";
+				case ">":
+					return "&gt;";
+				case "&":
+					return "&amp;";
+				case "'":
+					return "&#39;";
+				case '"':
+					return "&quot;";
+			}
+			return "?";
+		}
+		return String(value).replace(/[<>&"']/g, replaceChars);
+	}
+
+	function objectToString(object){
+		try{
+			return object+"";
+		}catch(e){
+			return null;
+		}
+	}
+
+	// ***************************************************************************
+	function appendLink(object, html){
+		// needed for object links - no HTML escaping
+		html.push( objectToString(object) );
+	}
+
+	function appendText(object, html){
+		html.push(escapeHTML(objectToString(object)));
+	}
+
+	function appendNull(object, html){
+		html.push('<span class="objectBox-null">', escapeHTML(objectToString(object)), '</span>');
+	}
+
+	function appendString(object, html){
+		html.push('<span class="objectBox-string">&quot;', escapeHTML(objectToString(object)),
+			'&quot;</span>');
+	}
+
+	function appendInteger(object, html){
+		html.push('<span class="objectBox-number">', escapeHTML(objectToString(object)), '</span>');
+	}
+
+	function appendFloat(object, html){
+		html.push('<span class="objectBox-number">', escapeHTML(objectToString(object)), '</span>');
+	}
+
+	function appendFunction(object, html){
+		html.push('<span class="objectBox-function">', getObjectAbbr(object), '</span>');
+	}
+
+	function appendObject(object, html){
+		try{
+			if(object === undefined){
+				appendNull("undefined", html);
+			}else if(object === null){
+				appendNull("null", html);
+			}else if(typeof object == "string"){
+				appendString(object, html);
+			}else if(typeof object == "number"){
+				appendInteger(object, html);
+			}else if(typeof object == "function"){
+				appendFunction(object, html);
+			}else if(object.nodeType == 1){
+				appendSelector(object, html);
+			}else if(typeof object == "object"){
+				appendObjectFormatted(object, html);
+			}else{
+				appendText(object, html);
+			}
+		}catch(e){
+			/* squelch */
+		}
+	}
+
+	function appendObjectFormatted(object, html){
+		var text = objectToString(object);
+		var reObject = /\[object (.*?)\]/;
+
+		var m = reObject.exec(text);
+		html.push('<span class="objectBox-object">', m ? m[1] : text, '</span>');
+	}
+
+	function appendSelector(object, html){
+		html.push('<span class="objectBox-selector">');
+
+		html.push('<span class="selectorTag">', escapeHTML(object.nodeName.toLowerCase()), '</span>');
+		if(object.id){
+			html.push('<span class="selectorId">#', escapeHTML(object.id), '</span>');
+		}
+		if(object.className){
+			html.push('<span class="selectorClass">.', escapeHTML(object.className), '</span>');
+		}
+
+		html.push('</span>');
+	}
+
+	function appendNode(node, html){
+		if(node.nodeType == 1){
+			html.push(
+				'<div class="objectBox-element">',
+					'&lt;<span class="nodeTag">', node.nodeName.toLowerCase(), '</span>');
+
+			for(var i = 0; i < node.attributes.length; ++i){
+				var attr = node.attributes[i];
+				if(!attr.specified){ continue; }
+
+				html.push('&nbsp;<span class="nodeName">', attr.nodeName.toLowerCase(),
+					'</span>=&quot;<span class="nodeValue">', escapeHTML(attr.nodeValue),
+					'</span>&quot;');
+			}
+
+			if(node.firstChild){
+				html.push('&gt;</div><div class="nodeChildren">');
+
+				for(var child = node.firstChild; child; child = child.nextSibling){
+					appendNode(child, html);
+				}
+
+				html.push('</div><div class="objectBox-element">&lt;/<span class="nodeTag">',
+					node.nodeName.toLowerCase(), '&gt;</span></div>');
+			}else{
+				html.push('/&gt;</div>');
+			}
+		}else if (node.nodeType == 3){
+			html.push('<div class="nodeText">', escapeHTML(node.nodeValue),
+				'</div>');
+		}
+	}
+
+	// ***************************************************************************
+
+	function addEvent(object, name, handler){
+		if(document.all){
+			object.attachEvent("on"+name, handler);
+		}else{
+			object.addEventListener(name, handler, false);
+		}
+	}
+
+	function removeEvent(object, name, handler){
+		if(document.all){
+			object.detachEvent("on"+name, handler);
+		}else{
+			object.removeEventListener(name, handler, false);
+		}
+	}
+
+	function cancelEvent(event){
+		if(document.all){
+			event.cancelBubble = true;
+		}else{
+			event.stopPropagation();
+		}
+	}
+
+	function onError(msg, href, lineNo){
+		var lastSlash = href.lastIndexOf("/");
+		var fileName = lastSlash == -1 ? href : href.substr(lastSlash+1);
+
+		var html = [
+			'<span class="errorMessage">', msg, '</span>',
+			'<div class="objectBox-sourceLink">', fileName, ' (line ', lineNo, ')</div>'
+		];
+
+		logRow(html, "error");
+	}
+
+
+	//After converting to div instead of iframe, now getting two keydowns right away in IE 6.
+	//Make sure there is a little bit of delay.
+	var onKeyDownTime = new Date().getTime();
+
+	function onKeyDown(event){
+		var timestamp = (new Date()).getTime();
+		if(timestamp > onKeyDownTime + 200){
+			event = dojo.fixEvent(event);
+			var keys = dojo.keys;
+			var ekc = event.keyCode;
+			onKeyDownTime = timestamp;
+			if(ekc == keys.F12){
+				toggleConsole();
+			}else if(
+				(ekc == keys.NUMPAD_ENTER || ekc == 76) &&
+				event.shiftKey &&
+				(event.metaKey || event.ctrlKey)
+			){
+				focusCommandLine();
+			}else{
+				return;
+			}
+			cancelEvent(event);
+		}
+	}
+
+	function onCommandLineKeyDown(e){
+		var dk = dojo.keys;
+		if(e.keyCode == 13 && commandLine.value){
+			addToHistory(commandLine.value);
+			evalCommandLine();
+		}else if(e.keyCode == 27){
+			commandLine.value = "";
+		}else if(e.keyCode == dk.UP_ARROW || e.charCode == dk.UP_ARROW){
+			navigateHistory("older");
+		}else if(e.keyCode == dk.DOWN_ARROW || e.charCode == dk.DOWN_ARROW){
+			navigateHistory("newer");
+		}else if(e.keyCode == dk.HOME || e.charCode == dk.HOME){
+			historyPosition = 1;
+			navigateHistory("older");
+		}else if(e.keyCode == dk.END || e.charCode == dk.END){
+			historyPosition = 999999;
+			navigateHistory("newer");
+		}
+	}
+
+	var historyPosition = -1;
+	var historyCommandLine = null;
+
+	function addToHistory(value){
+		var history = cookie("firebug_history");
+		history = (history) ? dojo.fromJson(history) : [];
+		var pos = dojo.indexOf(history, value);
+		if (pos != -1){
+			history.splice(pos, 1);
+		}
+		history.push(value);
+		cookie("firebug_history", dojo.toJson(history), 30);
+		while(history.length && !cookie("firebug_history")){
+			history.shift();
+			cookie("firebug_history", dojo.toJson(history), 30);
+		}
+		historyCommandLine = null;
+		historyPosition = -1;
+	}
+
+	function navigateHistory(direction){
+		var history = cookie("firebug_history");
+		history = (history) ? dojo.fromJson(history) : [];
+		if(!history.length){
+			return;
+		}
+
+		if(historyCommandLine === null){
+			historyCommandLine = commandLine.value;
+		}
+
+		if(historyPosition == -1){
+			historyPosition = history.length;
+		}
+
+		if(direction == "older"){
+			--historyPosition;
+			if(historyPosition < 0){
+				historyPosition = 0;
+			}
+		}else if(direction == "newer"){
+			++historyPosition;
+			if(historyPosition > history.length){
+				historyPosition = history.length;
+			}
+		}
+
+		if(historyPosition == history.length){
+			commandLine.value = historyCommandLine;
+			historyCommandLine = null;
+		}else{
+			commandLine.value = history[historyPosition];
+		}
+	}
+
+	function cookie(name, value){
+		var c = document.cookie;
+		if(arguments.length == 1){
+			var matches = c.match(new RegExp("(?:^|; )" + name + "=([^;]*)"));
+			return matches ? decodeURIComponent(matches[1]) : undefined; // String or undefined
+		}else{
+			var d = new Date();
+			d.setMonth(d.getMonth()+1);
+			document.cookie = name + "=" + encodeURIComponent(value) + ((d.toUtcString) ? "; expires=" + d.toUTCString() : "");
+		}
+	}
+
+	function isArray(it){
+		return it && it instanceof Array || typeof it == "array";
+	}
+
+	//***************************************************************************************************
+	// Print Object Helpers
+	function objectLength(o){
+		var cnt = 0;
+		for(var nm in o){
+			cnt++;
+		}
+		return cnt;
+	}
+
+	function printObject(o, i, txt, used){
+		// Recursively trace object, indenting to represent depth for display in object inspector
+		var ind = " \t";
+		txt = txt || "";
+		i = i || ind;
+		used = used || [];
+		var opnCls;
+
+		if(o && o.nodeType == 1){
+			var html = [];
+			appendNode(o, html);
+			return html.join("");
+		}
+
+		var br=",\n", cnt = 0, length = objectLength(o);
+
+		if(o instanceof Date){
+			return i + o.toString() + br;
+		}
+		looking:
+		for(var nm in o){
+			cnt++;
+			if(cnt==length){br = "\n";}
+			if(o[nm] === window || o[nm] === document){
+				// do nothing
+			}else if(o[nm] === null){
+				txt += i+nm + " : NULL" + br;
+			}else if(o[nm] && o[nm].nodeType){
+				if(o[nm].nodeType == 1){
+					//txt += i+nm + " : < "+o[nm].tagName+" id=\""+ o[nm].id+"\" />" + br;
+				}else if(o[nm].nodeType == 3){
+					txt += i+nm + " : [ TextNode "+o[nm].data + " ]" + br;
+				}
+
+			}else if(typeof o[nm] == "object" && (o[nm] instanceof String || o[nm] instanceof Number || o[nm] instanceof Boolean)){
+				txt += i+nm + " : " + o[nm] + "," + br;
+
+			}else if(o[nm] instanceof Date){
+				txt += i+nm + " : " + o[nm].toString() + br;
+
+			}else if(typeof(o[nm]) == "object" && o[nm]){
+				for(var j = 0, seen; seen = used[j]; j++){
+					if(o[nm] === seen){
+						txt += i+nm + " : RECURSION" + br;
+						continue looking;
+					}
+				}
+				used.push(o[nm]);
+
+				opnCls = (isArray(o[nm]))?["[","]"]:["{","}"];
+				txt += i+nm +" : " + opnCls[0] + "\n";//non-standard break, (no comma)
+				txt += printObject(o[nm], i+ind, "", used);
+				txt += i + opnCls[1] + br;
+
+			}else if(typeof o[nm] == "undefined"){
+				txt += i+nm + " : undefined" + br;
+			}else if(nm == "toString" && typeof o[nm] == "function"){
+				var toString = o[nm]();
+				if(typeof toString == "string" && toString.match(/function ?(.*?)\(/)){
+					toString = escapeHTML(getObjectAbbr(o[nm]));
+				}
+				txt += i+nm +" : " + toString + br;
+			}else{
+				txt += i+nm +" : "+ escapeHTML(getObjectAbbr(o[nm])) + br;
+			}
+		}
+		return txt;
+	}
+
+	function getObjectAbbr(obj){
+		// Gets an abbreviation of an object for display in log
+		// X items in object, including id
+		// X items in an array
+		// TODO: Firebug Sr. actually goes by char count
+		var isError = (obj instanceof Error);
+		if(obj.nodeType == 1){
+			return escapeHTML('< '+obj.tagName.toLowerCase()+' id=\"'+ obj.id+ '\" />');
+		}
+		if(obj.nodeType == 3){
+			return escapeHTML('[TextNode: "'+obj.nodeValue+'"]');
+		}
+		var nm = (obj && (obj.id || obj.name || obj.ObjectID || obj.widgetId));
+		if(!isError && nm){ return "{"+nm+"}";	}
+
+		var obCnt = 2;
+		var arCnt = 4;
+		var cnt = 0;
+
+		if(isError){
+			nm = "[ Error: "+(obj.message || obj.description || obj)+" ]";
+		}else if(isArray(obj)){
+			nm = "[" + obj.slice(0,arCnt).join(",");
+			if(obj.length > arCnt){
+				nm += " ... ("+obj.length+" items)";
+			}
+			nm += "]";
+		}else if(typeof obj == "function"){
+			nm = obj + "";
+			var reg = /function\s*([^\(]*)(\([^\)]*\))[^\{]*\{/;
+			var m = reg.exec(nm);
+			if(m){
+				if(!m[1]){
+					m[1] = "function";
+				}
+				nm = m[1] + m[2];
+			}else{
+				nm = "function()";
+			}
+		}else if(typeof obj != "object" || typeof obj == "string"){
+			nm = obj + "";
+		}else{
+			nm = "{";
+			for(var i in obj){
+				cnt++;
+				if(cnt > obCnt){ break; }
+				nm += i+":"+escapeHTML(obj[i])+"  ";
+			}
+			nm+="}";
+		}
+
+		return nm;
+	}
+
+	//*************************************************************************************
+
+	//window.onerror = onError;
+
+	addEvent(document, has("ie") || has("safari") ? "keydown" : "keypress", onKeyDown);
+
+	if(	(document.documentElement.getAttribute("debug") == "true")||
+		(dojo.config.isDebug)
+	){
+		toggleConsole(true);
+	}
+
+	dojo.addOnWindowUnload(function(){
+		// Erase the globals and event handlers I created, to prevent spurious leak warnings
+		removeEvent(document, has("ie") || has("safari") ? "keydown" : "keypress", onKeyDown);
+		window.onFirebugResize = null;
+		window.console = null;
+	});
+
+});
Binary file server/src/main/web-resources/_firebug/infoIcon.png has changed
Binary file server/src/main/web-resources/_firebug/tab_lft_norm.png has changed
Binary file server/src/main/web-resources/_firebug/tab_lft_over.png has changed
Binary file server/src/main/web-resources/_firebug/tab_rgt_norm.png has changed
Binary file server/src/main/web-resources/_firebug/tab_rgt_over.png has changed
Binary file server/src/main/web-resources/_firebug/warningIcon.png has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/main/webapp/WEB-INF/applicationContext.xml	Tue Nov 06 13:23:19 2012 +0100
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
+	xmlns:context="http://www.springframework.org/schema/context"
+	xsi:schemaLocation="http://www.springframework.org/schema/beans 
+	   		http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
+	   		http://www.springframework.org/schema/context
+	   		http://www.springframework.org/schema/context/spring-context-3.0.xsd">
+	
+	<!-- Activates various annotations to be detected in bean classes -->
+	<context:annotation-config />
+	
+	<!-- Configures the annotation-driven Spring MVC Controller programming model.
+	Note that, with Spring 3.0, this tag works in Servlet MVC only!  -->
+
+    <!-- Loads MongoDB configuraton -->
+    <import resource="mongo-config.xml"/>
+
+    <!--bean id="bayeuxServer" class="org.cometd.server.BayeuxServerImpl" init-method="start" destroy-method="stop">
+        <property name="options">
+            <map>
+                <entry key="logLevel" value="3" />
+                <entry key="timeout" value="15000" />
+            </map>
+        </property>  
+    </bean-->
+    <bean id="springConfigurer"
+        class="org.iri_research.renkan.coweb.SpringConfigurer"
+        factory-method="getInstance" />
+	
+    <!-- Scans the classpath for annotated components that will be auto-registered as Spring beans.
+     For example @Controller and @Service. Make sure to set the correct base-package-->
+    <context:component-scan base-package="org.iri_research.renkan.rest" />
+    <context:component-scan base-package="org.iri_research.renkan.coweb" />
+
+</beans>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/main/webapp/WEB-INF/mongo-config.xml	Tue Nov 06 13:23:19 2012 +0100
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
+	xmlns:p="http://www.springframework.org/schema/p" 
+    xmlns:mongo="http://www.springframework.org/schema/data/mongo"
+    xmlns:context="http://www.springframework.org/schema/context"
+    xmlns:jpa="http://www.springframework.org/schema/data/jpa"
+	xsi:schemaLocation="http://www.springframework.org/schema/beans 
+	   		http://www.springframework.org/schema/beans/spring-beans.xsd
+   			http://www.springframework.org/schema/data/mongo
+    		http://www.springframework.org/schema/data/mongo/spring-mongo.xsd
+    		http://www.springframework.org/schema/context
+            http://www.springframework.org/schema/context/spring-context.xsd
+            http://www.springframework.org/schema/data/jpa
+            http://www.springframework.org/schema/data/jpa/spring-jpa.xsd">	
+	<!-- Default bean name is 'mongo' -->
+	<mongo:mongo host="localhost" port="27017"/>
+		
+	<!-- Offers convenience methods and automatic mapping between MongoDB JSON documents and your domain classes. -->
+  	<bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
+  	    <constructor-arg ref="mongo"/>
+  		<constructor-arg value="renkan"/>
+  		<property name="writeResultChecking" value="EXCEPTION"/>
+  	</bean>
+  	
+  	<mongo:repositories base-package="org.iri_research.renkan" factory-class="org.iri_research.renkan.repositories.RenkanRepositoryFactoryBean" />
+  	  	
+</beans>
--- a/server/src/main/webapp/WEB-INF/web.xml	Tue Nov 13 11:46:39 2012 +0100
+++ b/server/src/main/webapp/WEB-INF/web.xml	Tue Nov 06 13:23:19 2012 +0100
@@ -1,8 +1,24 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">
+<web-app 
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
+    xmlns="http://java.sun.com/xml/ns/javaee"
+    xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
+    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
+    version="2.5">
+  <listener>  
+      <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>  
+  </listener>
+  <listener>  
+        <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>  
+  </listener>  
+  <context-param>  
+    <param-name>contextConfigLocation</param-name>  
+    <param-value>/WEB-INF/applicationContext.xml</param-value>  
+  </context-param>
   <servlet>
     <servlet-name>cometd</servlet-name>
-    <servlet-class>org.cometd.server.CometdServlet</servlet-class>
+    <!--servlet-class>org.cometd.server.CometdServlet</servlet-class-->
+    <servlet-class>org.iri_research.renkan.coweb.server.RenkanCometdServlet</servlet-class>
     <init-param>
       <param-name>logLevel</param-name>
       <param-value>0</param-value>
@@ -36,7 +52,7 @@
   </servlet-mapping>
   <servlet>
     <servlet-name>rest Servlet</servlet-name>
-    <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
+    <servlet-class>com.sun.jersey.spi.spring.container.servlet.SpringServlet</servlet-class>
     <init-param>
       <param-name>com.sun.jersey.config.property.packages</param-name>
       <param-value>org.iri_research.renkan.rest</param-value>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/main/webapp/css/style.css	Tue Nov 06 13:23:19 2012 +0100
@@ -0,0 +1,130 @@
+/* =============================================================================
+   HTML5 Boilerplate CSS: h5bp.com/css
+   ========================================================================== */
+
+article, aside, details, figcaption, figure, footer, header, hgroup, nav, section { display: block; }
+audio, canvas, video { display: inline-block; *display: inline; *zoom: 1; }
+audio:not([controls]) { display: none; }
+[hidden] { display: none; }
+
+html { font-size: 100%; -webkit-text-size-adjust: 100%; -ms-text-size-adjust: 100%; }
+html, button, input, select, textarea { font-family: sans-serif; color: #222; }
+body { margin: 0; font-size: 1em; line-height: 1.4; }
+
+::-moz-selection { background: #fe57a1; color: #fff; text-shadow: none; }
+::selection { background: #fe57a1; color: #fff; text-shadow: none; }
+
+a { color: #00e; }
+a:visited { color: #551a8b; }
+a:hover { color: #06e; }
+a:focus { outline: thin dotted; }
+a:hover, a:active { outline: 0; }
+
+abbr[title] { border-bottom: 1px dotted; }
+b, strong { font-weight: bold; }
+blockquote { margin: 1em 40px; }
+dfn { font-style: italic; }
+hr { display: block; height: 1px; border: 0; border-top: 1px solid #ccc; margin: 1em 0; padding: 0; }
+ins { background: #ff9; color: #000; text-decoration: none; }
+mark { background: #ff0; color: #000; font-style: italic; font-weight: bold; }
+pre, code, kbd, samp { font-family: monospace, serif; _font-family: 'courier new', monospace; font-size: 1em; }
+pre { white-space: pre; white-space: pre-wrap; word-wrap: break-word; }
+q { quotes: none; }
+q:before, q:after { content: ""; content: none; }
+small { font-size: 85%; }
+
+sub, sup { font-size: 75%; line-height: 0; position: relative; vertical-align: baseline; }
+sup { top: -0.5em; }
+sub { bottom: -0.25em; }
+
+ul, ol { margin: 1em 0; padding: 0 0 0 40px; }
+dd { margin: 0 0 0 40px; }
+nav ul, nav ol { list-style: none; list-style-image: none; margin: 0; padding: 0; }
+
+img { border: 0; -ms-interpolation-mode: bicubic; vertical-align: middle; }
+
+svg:not(:root) { overflow: hidden; }
+
+figure { margin: 0; }
+
+form { margin: 0; }
+fieldset { border: 0; margin: 0; padding: 0; }
+label { cursor: pointer; }
+legend { border: 0; *margin-left: -7px; padding: 0; white-space: normal; }
+button, input, select, textarea { font-size: 100%; margin: 0; vertical-align: baseline; *vertical-align: middle; }
+button, input { line-height: normal; }
+button, input[type="button"], input[type="reset"], input[type="submit"] { cursor: pointer; -webkit-appearance: button; *overflow: visible; }
+button[disabled], input[disabled] { cursor: default; }
+input[type="checkbox"], input[type="radio"] { box-sizing: border-box; padding: 0; *width: 13px; *height: 13px; }
+input[type="search"] { -webkit-appearance: textfield; -moz-box-sizing: content-box; -webkit-box-sizing: content-box; box-sizing: content-box; }
+input[type="search"]::-webkit-search-decoration, input[type="search"]::-webkit-search-cancel-button { -webkit-appearance: none; }
+button::-moz-focus-inner, input::-moz-focus-inner { border: 0; padding: 0; }
+textarea { overflow: auto; vertical-align: top; resize: vertical; }
+input:valid, textarea:valid {  }
+input:invalid, textarea:invalid { background-color: #f0dddd; }
+
+table { border-collapse: collapse; border-spacing: 0; }
+td { vertical-align: top; }
+
+.chromeframe { margin: 0.2em 0; background: #ccc; color: black; padding: 0.2em 0; }
+
+
+
+/* ===== Primary Styles ========================================================
+   Author:
+   ========================================================================== */
+.templates { display: none; }
+
+.project_desc_label { font-weight: bold; }
+
+#project_display {
+    background: #9cbc2c;
+    -moz-border-radius: 5px;
+    -webkit-border-radius: 5px;
+    border-radius: 5px;
+    padding: 20px;
+    width: 400px;
+}
+
+
+
+/* =============================================================================
+   Media Queries
+   ========================================================================== */
+
+@media only screen and (min-width: 35em) {
+	/* Style adjustments for viewports that meet the condition */
+}
+
+/* =============================================================================
+   Non-Semantic Helper Classes
+   ========================================================================== */
+
+.ir { display: block; border: 0; text-indent: -999em; overflow: hidden; background-color: transparent; background-repeat: no-repeat; text-align: left; direction: ltr; *line-height: 0; }
+.ir br { display: none; }
+.hidden { display: none !important; visibility: hidden; }
+.visuallyhidden { border: 0; clip: rect(0 0 0 0); height: 1px; margin: -1px; overflow: hidden; padding: 0; position: absolute; width: 1px; }
+.visuallyhidden.focusable:active, .visuallyhidden.focusable:focus { clip: auto; height: auto; margin: 0; overflow: visible; position: static; width: auto; }
+.invisible { visibility: hidden; }
+.clearfix:before, .clearfix:after { content: ""; display: table; }
+.clearfix:after { clear: both; }
+.clearfix { *zoom: 1; }
+
+/* =============================================================================
+   Print Styles
+   ========================================================================== */
+ 
+@media print {
+  * { background: transparent !important; color: black !important; box-shadow:none !important; text-shadow: none !important; filter:none !important; -ms-filter: none !important; } /* Black prints faster: h5bp.com/s */
+  a, a:visited { text-decoration: underline; }
+  a[href]:after { content: " (" attr(href) ")"; }
+  abbr[title]:after { content: " (" attr(title) ")"; }
+  .ir a:after, a[href^="javascript:"]:after, a[href^="#"]:after { content: ""; }  /* Don't show links for images, or javascript/internal links */
+  pre, blockquote { border: 1px solid #999; page-break-inside: avoid; }
+  thead { display: table-header-group; } /* h5bp.com/t */
+  tr, img { page-break-inside: avoid; }
+  img { max-width: 100% !important; }
+  @page { margin: 0.5cm; }
+  p, h2, h3 { orphans: 3; widows: 3; }
+  h2, h3 { page-break-after: avoid; }
+}
Binary file server/src/main/webapp/favicon.ico has changed
--- a/server/src/main/webapp/js/config.js	Tue Nov 13 11:46:39 2012 +0100
+++ b/server/src/main/webapp/js/config.js	Tue Nov 06 13:23:19 2012 +0100
@@ -10,21 +10,22 @@
 	paths : {
 	   coweb : 'lib/coweb',
 	   cowebx: 'lib/cowebx',
-	   org : 'lib/org'
+	   org : 'lib/org',
+	   corenkan: 'js/corenkan',
 	},
-/*	packages:[{
+	/*packages:[{
 		name: 'dojo',
-		location:'http://vhost1629.developer.ihost.com/dojotoolkit/1.7.0/dojo',
+		location:'lib/dojo',
 		main:'main'
 	},
 	{
 		name: 'dijit',
-		location:'http://vhost1629.developer.ihost.com/dojotoolkit/1.7.0/dijit',
+		location:'lib/dijit',
 		main:'main'
 	},
 	{
 		name: 'dojox',
-		location:'http://vhost1629.developer.ihost.com/dojotoolkit/1.7.0/dojox',
+		location:'lib/dojox',
 		main:'main'
 	}]*/
 };
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/main/webapp/js/corenkan.js	Tue Nov 06 13:23:19 2012 +0100
@@ -0,0 +1,116 @@
+define([
+    "dojo",
+    "coweb/main",
+], function(dojo, coweb) {
+
+    var CoRenkanApp = function() {
+    };
+
+    var proto = CoRenkanApp.prototype;
+
+    proto.init = function() {
+    	console.log("ready callback");
+    	
+    	//this.initCollab();
+    	
+    	var sess = coweb.initSession();
+    	sess.onStatusChange = function(status) {
+    	    console.log(status);
+    	};
+    	sess.prepare();
+    	this.project = null;
+                
+    };
+    
+    proto.initCollab = function(id) {    	
+    	this.collab = coweb.initCollab({id : id});
+    	this.collab.subscribeSync("project", this, "onRemoteProjectChange");    	
+    };
+    
+    function prepareValues(obj,c) {
+		values = {};
+		for(var fieldname in c.changes) {
+			if(c.changes[fieldname]) {
+				values[fieldname] = obj.get(fieldname);
+			}    			
+		}
+		return values;
+    }
+    
+    proto.setProject = function(project) {
+    	
+    	var projectFields = ["title", "description", "uri"];
+    	var that = this;
+    	for(var fieldIndex in projectFields) {
+    		(function(fi){
+	    		var field = projectFields[fi];
+	        	project.bind("change:"+field, function(obj, c) {
+	        		console.log(c);
+	        		values = {
+	        		    id: obj.id,
+	        		    type: "project"
+	        		};
+	        		values[field] = c;
+	        		that.collab.sendSync("project", values);
+	        	});
+    		})(fieldIndex);
+    	}
+    	this.project = project;
+    	this.initCollab(project.id);
+    };
+    
+    
+    /**
+     * Called when a remote data store changes in some manner. Dispatches to
+     * local methods for insert, update, delete handling.
+     * TODO: manage project list change on server
+     * @param args Cooperative web event
+     */
+    proto.onRemoteProjectChange = function(args) {    	
+    	console.log(args);
+    	if (args.type === "update") {
+            this.onRemoteProjectUpdate(args.value, args.position);
+    	}
+        /*if (args.type === "insert") {
+            this.onRemoteInsert(value, args.position);
+        } else if (args.type === "update") {
+            this.onRemoteUpdate(value, args.position);
+        } else if (args.type === "delete") {
+            this.onRemoteDelete(args.position);
+        }*/
+    };
+    
+    /**
+     * Called when a project attribute changes value in a remote data store.
+     * Updates the attribute value of the item with the same id in the local
+     * data store.
+     *
+     * @param value Item data sent by remote data store
+     * @param position Which item to update.
+     */
+    proto.onRemoteProjectUpdate = function(values, position) {
+    	var project_id = values['id'];
+    	if(typeof(project_id) === "undefined") {
+    		return;
+		}
+    	
+    	if(this.project != null && project_id == this.project.id) {
+    		for(var fieldname in values) {
+    			if(fieldname != "id" && fieldname != "type") {
+    				this.project.set(fieldname, values[fieldname]);
+    			}
+    		}
+    	}
+    	
+    };
+        
+    var app = new CoRenkanApp();
+    dojo.ready(function() {
+        app.init();
+    });
+    
+    
+    return {
+    	app: app
+    };
+});
\ No newline at end of file
--- a/server/src/main/webapp/js/main_coweb.js	Tue Nov 13 11:46:39 2012 +0100
+++ b/server/src/main/webapp/js/main_coweb.js	Tue Nov 06 13:23:19 2012 +0100
@@ -9,16 +9,16 @@
     adminUrl : './admin'
 };
 
+//require(['corenkan']);
+
 require({moduleUrl : 'lib'},
-        ['coweb/main','dojo'],
-function(coweb, dojo) {
+        ['coweb/main','dojo', 'corenkan'],
+function(coweb, dojo, corenkan) {
     // do application setup here
     
-    dojo.ready(function() {
-        // on page load, prepare, join, and update in a session
-        var sess = coweb.initSession();
-        sess.prepare();
-        this.collab = coweb.initCollab({id:'renkan'});
+	dojo.ready(function() {
+        //this.collab = corenkan.app.collab;
     });
+    
 });
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/main/webapp/js/main_test_models.js	Tue Nov 06 13:23:19 2012 +0100
@@ -0,0 +1,305 @@
+(function() {
+	
+	var root = this;
+		
+	var Backbone = root.Backbone;
+	
+	var Rkns = root.Rkns = {};
+
+	root.ModelView = Backbone.View.extend({
+		
+		events : {
+			"click .show_form" : "show_form",
+			"click .remove_button" : "remove_click",
+		},
+		
+		initialize: function(options) {
+			_.bindAll(this);
+			this.template = _.template(options.template);
+			this.model.bind("change", this.render);
+			this.form_view = options.form_view;
+			this.form_el = options.form_el;
+			if(typeof options.getJSON === "function") {
+				this.getJSON = options.getJSON;
+			}
+		},
+		render: function() {
+			$(this.el).html(this.template(this.getJSON()));
+			return this;
+		},
+		show_form: function(evt) {
+			if(typeof this.form_view !== "undefined") {
+				this.form_view.render();
+				$(this.form_el).empty();
+				$(this.form_el).append(this.form_view.el);
+			}
+		},
+		getJSON : function() {
+			return this.model.toJSON();			
+		},
+		remove_click : function(evt) {
+			var obj_id = $(evt.currentTarget).attr("value");
+			if(typeof this.model.collection !== "undefined") {
+				this.model.collection.remove(this.model);
+			}
+		},
+
+	});
+	
+	root.ColView = Backbone.View.extend({
+		initialize: function(options) {
+			
+			_.bindAll(this);
+			this.element = options.element;
+			this.element_form = options.element_form;
+			this.element_form_el = options.element_form_el;
+			this.rendered = false;
+			
+			var that = this;
+			this.element_views = [];
+			
+			this.collection.each(function(elt) { 
+				this.add(elt); 
+			});
+			
+			this.collection.bind('add', this.add);
+			this.collection.bind('remove', this.remove);
+		},
+		
+		render : function() {
+			this.rendered = true;
+			var that = this;
+			this.$el.empty();
+			_(this.element_views).each(function(dvs){
+				that.$el.append(dvs.disp.render().el);				
+			});
+			
+			return this;
+		},
+		
+		add : function(elt) {
+			
+			var fv_args = _.extend({}, this.element_form, {model: elt});			
+			var fv = new FormView(fv_args);
+			
+			var dv_args = _.extend({}, this.element, {model: elt, tagName: 'li', form_view: fv, form_el: this.element_form_el});			
+			var dv = new ModelView(dv_args);
+			
+			this.element_views.push({disp:dv, form:fv});
+			
+			if(this.rendered) {
+				this.$el.append(dv.render().el);
+			}
+		},
+			
+		
+		remove : function(elt) {
+			var viewsToRemove = _(this.element_views).select(function(cvs) { return cvs.disp.model === elt; })[0];
+			this.element_views = _(this.element_views).without(viewsToRemove);
+			
+			if(this.rendered) {
+				viewsToRemove.disp.$el.remove();
+				viewsToRemove.form.$el.remove();
+			}
+		},
+		
+		remove_click : function(evt) {
+			var obj_id = $(evt.currentTarget).attr("value");
+			this.collection.remove(this.collection.get(obj_id));
+		}
+		
+	});
+	
+	root.FormView = Backbone.View.extend({
+		events : {
+			"change .form_field": "changed"
+		},
+		initialize: function(options) {
+			_.bindAll(this);
+			this.template = _.template(options.template);
+			this.model.bind("change", this.render);
+			if(typeof options.getJSON === "function") {
+				this.getJSON = options.getJSON;
+			}
+		},
+		render: function() {
+			this.$el.html(this.template(this.getJSON()));
+			return this;
+		},
+		changed: function(evt) {
+			var value = $(evt.currentTarget).val();
+			var field_name = $(evt.currentTarget).attr("name");
+			if(this.model.get(field_name) != value) {
+				this.model.set(field_name, value);
+			}
+		},
+		getJSON : function() {
+			return this.model.toJSON(); 
+		}
+	});
+	
+	
+	root.SelectCurrentUserView = Backbone.View.extend({
+		initialize: function(options) {
+			_.bindAll(this);
+			this.rendered = false;
+			
+			this.child_view_constructor = options.child_view_constructor;
+			this.child_tag_name = options.child_tag_name;
+			
+			this.children_views = [];
+			this.collection.each(this.add);
+			
+			this.collection.bind('add', this.add);
+			this.collection.bind('remove', this.remove);
+		},
+		add: function(elt) {
+			var child_view = new this.child_view_constructor({
+				model: elt,
+				tagName : this.child_tag_name
+			});
+			this.children_views.push(child_view);
+			
+			if (this.rendered) {
+				this.$el.append(child_view.render().el);
+			}
+		},
+		remove: function(elt) {
+			var view_to_remove = _(this.children_views).select(function(cv) { return cv.model === elt; })[0];
+			this.children_views = _(this.children_views).without(view_to_remove);
+			if (this.rendered) {
+				view_to_remove.$el.remove();
+			}
+		},
+		render: function() {
+			this.rendered = true;
+			var that = this;
+			
+			this.$el.empty().html("<option value=\"\">Unknown</option>");
+			
+			_(this.children_views).each(function(cv){
+				that.$el.append(cv.render().el);
+			});
+			
+			return this;
+		}
+		
+	});
+	
+	root.SelectUserView = Backbone.View.extend({
+		initialize: function(options) {
+			_.bindAll(this);
+			this.model.bind("change", this.render);
+		},		
+		render: function() {
+			this.$el.val(this.model.id).text(this.model.get("title"));
+			return this;
+		}
+	});
+	
+	root.CurrentUserView = Backbone.View.extend({
+		initialize : function() {
+			this._select_view = new SelectCurrentUserView({
+				el : this.el,
+				collection : this.model.get("users"),
+				child_view_constructor: SelectUserView,
+				child_tag_name: "option",
+			});
+		},
+		render: function() {
+			this.$el.empty();
+			this._select_view.render();
+			return this;
+		}
+		
+	});
+	
+	
+	root.BasicListView = Backbone.View.extend({
+		
+		initialize: function(options) {
+			_.bindAll(this);
+			
+			this.element_view_constructor = options.element_view_constructor;
+			if(typeof options.template !== "undefined") {
+				this.template = _.template(options.template);
+			}
+			
+			this.rendered = false;
+			this.element_views = [];
+			this.collection.each(this.add);
+			
+			this.collection.bind('add', this.add);
+			this.collection.bind('remove', this.remove);
+			this.collection.bind('reset', this.reset);
+			this.collection.bind('destroy', this.destroy);
+		},
+	
+		render: function() {
+			this.rendered = true;
+			var that = this;
+			this.$el.empty();
+			if(typeof this.template !== "undefined") {
+				var data = {};
+				if(typeof this.model !== "undefined") {
+					data = this.$el.model.toJSON();
+				}
+				this.$el.html(this.template(data));
+			}
+			_(this.element_views).each(function(dvs){
+				that.$el.append(dvs.render().el);
+			});
+
+			return this;
+		},
+		
+		add: function(elt) {
+			var element_view = new this.element_view_constructor({model: elt});
+			this.element_views.push(element_view);
+			if(this.rendered) {
+				this.$el.append(element_view.render().el);
+			}
+		},
+		
+		remove: function(elt) {
+			var element_view = _(this.element_views).select(function(cv) {return cv.model === elt;})[0];
+			this.element_views = _(this.element_views).without(element_view);
+			if(this.rendered) {
+				element_view.$el.remove();
+			}
+			
+		},
+
+		reset: function() {
+			_(this.element_views).each(function(cv) {
+				cv.$el.remove();
+			});
+			this.element_views = [];
+			this.collection.each(this.add);	
+		}
+	
+	});
+	
+	
+	root.BasicModelView = Backbone.View.extend({
+				
+		initialize: function(options) {
+			_.bindAll(this);
+			if(typeof options.template !== "undefined") {
+				this.template = _.template(options.template);
+			}
+			if(typeof options.getJSON === "function") {
+				this.getJSON = options.getJSON;
+			}
+			this.model.bind("change", this.render);
+		},
+		render: function() {
+			$(this.el).html(this.template(this.getJSON()));
+			return this;
+		},
+		getJSON : function() {
+			return this.model.toJSON();			
+		}
+	});
+	
+}).call(this);
--- a/server/src/main/webapp/js/models.js	Tue Nov 13 11:46:39 2012 +0100
+++ b/server/src/main/webapp/js/models.js	Tue Nov 06 13:23:19 2012 +0100
@@ -21,7 +21,7 @@
 		constructor: function(options) {
 			
 			if (typeof options !== "undefined") {
-	            options._id = options.id || Models.getUID(this);
+	            options._id = options._id || options.id || Models.getUID(this);
 	            options.title = options.title || "(untitled " + this.type + ")";
 	            options.description = options.description || "";
 	            options.uri = options.uri || "";
@@ -65,10 +65,14 @@
 		relations: [{
 			type: Backbone.HasOne,
 			key: "created_by",
-			relatedModel: User
+			relatedModel: User,
+			reverseRelation : {
+				includeInJSON: '_id'
+			}
 		}],
 		prepare: function(options) {
 			project = options.project;
+			delete options["project"];
 			this.addReference(options, "created_by", project.get("users"), options.created_by, project.current_user);
 			options.description = options.description || "";			
 			return options;
@@ -83,7 +87,10 @@
 		  {
 			type: Backbone.HasOne,
 			key: "created_by",
-			relatedModel: User
+			relatedModel: User,
+			reverseRelation : {
+				includeInJSON: '_id'
+			}
 		  },
 		  {
 		    type: Backbone.HasOne,
@@ -98,6 +105,7 @@
 		],
 		prepare: function(options) {
 			project = options.project;
+			delete options.project;
 			this.addReference(options, "created_by", options.created_by, project.get("users"), project.current_user);
 			this.addReference(options, "from", options.from, project.get("nodes"));
 			this.addReference(options, "to", options.to, project.get("nodes"));
@@ -108,6 +116,7 @@
 	// PROJECT
 	var Project = Models.Project = root.Rkns.Models.Project = RenkanModel.extend({
 		type: "project",
+		current_user : null,
 		relations: [
 		  {
 		    type: Backbone.HasMany,
@@ -140,6 +149,9 @@
 		addNode: function(_props) {
 			_props.project = this;
 			this.get("nodes").push(_props);
+		},
+		addUser: function(_props) {
+			this.get("users").push(_props);
 		}
 	});
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/main/webapp/model-test.html	Tue Nov 06 13:23:19 2012 +0100
@@ -0,0 +1,340 @@
+<!doctype html>
+<html class="no-js" lang="en">
+<head>
+    <meta charset="utf-8">
+    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
+
+    <title>Test Model Renkan</title>
+    <meta name="description" content="">
+    <meta name="author" content="">
+
+    <meta name="viewport" content="width=device-width">
+
+    <link rel="stylesheet" href="css/style.css">
+    
+    <script type="text/javascript" src="js/config.js"></script>
+    <script type="text/javascript" src="js/dojo.js" data-dojo-config="isDebug: true, parseOnLoad: true"></script>
+    <script src="lib/jquery.min.js"></script>
+    <script src="lib/underscore-min.js"></script>
+    <script src="js/backbone.js"></script>
+    <script src="js/backbone-relational.js"></script>
+    <script src="js/main_test_models.js"></script>
+    <script src="js/models.js"></script>
+    <script type="text/javascript" src="js/config.js"></script>
+    <script data-main="main" src="js/main_coweb.js"></script>
+    <script type="text/javascript">
+    
+    function set_project(project) {
+    	
+    	require(["dojo/dom", "dojo/on", "corenkan"], function(dom, on, corenkan) {
+
+    		var template_html = dom.byId("project_disp_template").innerHTML;
+            var el = dom.byId("project_display");
+    
+            
+            var project_form_view = new FormView({el: dom.byId("form_display"), model: project, template: dom.byId("project_form_template").innerHTML});
+            
+            project_view = new ModelView({
+                el:el,
+                model: project,
+                template: template_html,
+                form_view: project_form_view,
+                form_el : dom.byId("form_display_div")
+            });
+            
+            var user_list_view = new ColView({
+                el: dom.byId("users_list_base"),
+                collection: project.get("users"),
+                element: {
+                    template: dom.byId("user_disp_template").innerHTML
+                },
+                element_form: {
+                    tagName: "div",
+                    attributes: {
+                        id:"form_display",
+                    },
+                    template: dom.byId("user_form_template").innerHTML
+                },
+                element_form_el : dom.byId("form_display_div")
+            });
+    
+            var node_list_view = new ColView({
+                el: dom.byId("nodes_list_base"),
+                collection: project.get("nodes"),
+                element: {
+                    template: dom.byId("node_disp_template").innerHTML
+                },
+                element_form: {
+                    tagName: "div",
+                    attributes: {
+                        id:"form_display",
+                    },
+                    template: dom.byId("node_form_template").innerHTML  
+                },
+                element_form_el : dom.byId("form_display_div") 
+            });
+            
+            var current_user_view = new CurrentUserView({
+                el: dom.byId("users_select"),
+                model: project
+            })
+            
+            project_view.render();
+            user_list_view.render();
+            node_list_view.render();
+            current_user_view.render();
+            
+            on(dom.byId("add_user"), "click", function() {
+                project.get("users").push(new Rkns.Models.User({}));
+            });
+            on(dom.byId("add_node"), "click", function() {
+                project.get("nodes").push(new Rkns.Models.Node({project: project}));
+            });
+            
+            on(dom.byId("users_select"), "change", function(evt) {
+                var val = evt.currentTarget.value;
+                var current_user = null;
+                if(typeof val !== "undefined" && val != "") {               
+                    current_user = project.get("users").get(val);
+                }
+                
+                if(current_user != null) {
+                    project.current_user = current_user;
+                    dom.byId("current_user").innerHTML = current_user.get("title");
+                }
+                else {
+                    project.current_user = null;
+                    dom.byId("current_user").innerHTML = "";
+                }
+                 
+            });
+            
+            project.get("users").on("change", function(evt) {
+                if(project.current_user == null) {
+                    dom.byId("current_user").innerHTML = "";
+                }
+                else if(evt.id == project.current_user.id) {
+                    dom.byId("current_user").innerHTML = project.current_user.get("title");
+                }
+            });
+            
+            project.get("users").on("remove", function(evt) {
+                if(typeof project.current_user === "undefined" || project.current_user == null || evt.id == project.current_user.id) {
+                    dom.byId("current_user").innerHTML = "";
+                }
+            });
+    
+            corenkan.app.setProject(project);
+        });
+    }
+    
+    function load_project(project_id) {
+    	var project = null;
+    	
+   		if(project_id) {
+   		    project = new Rkns.Models.Project({_id: project_id});
+   		}
+   		else {
+   			project = new Rkns.Models.Project({});
+   		}
+   		project.urlRoot = "rest/projects";
+   		
+   		if(project_id) {
+   			project.fetch({
+   				success: function(project, resp) {
+   				    set_project(project);    					
+   				}
+   			});
+   		}
+   		else {
+   			set_project(project);
+   		}
+    		    	
+    	return project;
+    }
+    
+    var current_project = null;
+    
+    require(["dojo/dom", "dojo/on", "dojo/domReady!"], function(dom, on) {
+    	    	
+    	var project_list_item_view = BasicModelView.extend({template: _.template(dom.byId("project_list_item_template").innerHTML), tagName: "li"});
+
+        var project_list_col = new (Backbone.Collection.extend({model: Rkns.Models.Project.extend({idAttribute:'_id', urlRoot:'rest/projects'})}))();
+        project_list_col.url = "rest/projects";
+        project_list_col.on("all", function(){
+        	if(!project_list_view) {
+        		return;
+        	}
+            _(project_list_view.element_views).each(function(ev){
+                if(ev.model.id === current_project.id) {
+                    $(".project_load_button",ev.el).attr('disabled','disabled');
+                    $(".project_delete_button",ev.el).attr('disabled','disabled');
+                }
+                else {
+                    $(".project_load_button",ev.el).removeAttr('disabled');
+                    $(".project_delete_button",ev.el).removeAttr('disabled');
+                }
+            });        	
+        });
+
+        var project_list_view = null; 
+        
+        project_list_col.fetch({
+        	success:function(collection, response) {
+        		project_list_view = new (BasicListView.extend({events: {
+                    "click .project_load_button" : function(evt) {
+                    	var proj_id = $(evt.target).val();
+                    	if(current_project && current_project.id == proj_id) {
+                    		return;
+                    	}
+                        current_project = load_project($(evt.target).val());
+                        project_list_col.trigger("sync");
+                    },
+                    "click .project_delete_button": function(evt) {                    	
+                    	var delete_id = $(evt.target).val();
+                    	if(!current_project || delete_id != current_project.id) { 
+                      	    _(project_list_col.where({_id: delete_id})).each(function(proj) {
+                      	        proj.destroy();
+                      	    });
+                    	}
+                    }
+                }}))({collection: collection, element_view_constructor: project_list_item_view, el: dom.byId("project_list")});
+                project_list_view.render();
+        	} 
+        });
+        
+        on(dom.byId("project_save_button"), "click", function(evt){
+        	if(current_project) {
+           	    current_project.save({}, {success: function(model, response) {
+           		    if(project_list_view != null) {
+           			    project_list_col.fetch({
+           	                success:function(collection, response) {
+           	                    project_list_view.render();
+           	                } 
+           	            });
+           		    }        		
+           	    }});
+        	}
+        });
+        
+        on(dom.byId("new_project_button"), "click", function(evt) {
+        	current_project = load_project();        	
+        });
+                
+    });
+    </script>
+</head>
+<body>
+<header>
+</header>
+
+<div>
+<div class="project_current_user"><span class="project_label project_user_label">User: </span><span id="current_user"></span></div>
+<select id="users_select">
+    <option value="">None</option>
+</select>
+</div>
+
+<button type="button" id="new_project_button">New Project</button>
+
+<div id="project_list_div">
+<ul id="project_list">
+</ul>
+</div>
+
+<div role="main" id="project_display">
+</div>
+<button type="button" id="project_save_button" value="save">Save</button>
+
+<div id="users_list_div">
+    <button id="add_user">Add user</button>
+    <ul id="users_list_base">
+    </ul>    
+</div>
+
+<div id="nodes_list_div">
+    <button id="add_node">Add node</button>
+    <ul id="nodes_list_base">
+    </ul>
+</div>
+
+
+<div id="form_display_div">
+</div>
+
+<footer>
+</footer>
+
+<script type="text/template" id="current_user_template">
+</script>
+
+<script type="text/template" id="project_disp_template">
+    <div class="show_form">
+    <h2 class="project_title">Project <%= _id %>: <%= title %></h2>
+    <div class="project_desc"><span class="project_label project_desc_label">Desc: </span><%= description %></div>
+    <div class="project_uri"><span class="project_label project_uri_label">Uri: </span><%= uri %></div>
+    </div>
+</script>
+<script type="text/template" id="project_form_template">
+    <table class="project_form">
+        <thead>
+            <tr><th>Field</th><th>Value</th></tr>
+        </thead>
+        <tbody>
+            <tr><td>Title:</td><td><input type="text" name="title" id="project_form_title" class="form_field" value="<%= title %>"></input></td></tr>
+            <tr><td>Uri :</td><td><input type="text" name="uri" id="project_form_text" class="form_field" value="<%= uri %>"></input></td></tr>
+            <tr><td>Desc :</td><td><textarea name="description" id="project_form_description" class="form_field"><%= description %></textarea></td></tr>            
+        </tbody>
+    </table>
+</script>
+<script type="text/template" id="user_disp_template">
+    <div class="show_form">
+    <h2 class="user_title">User <%= _id %>: <%= title %></h2>
+    <div class="user_desc"><span class="user_label user_desc_label">Desc: </span><%= description %></div>
+    <div class="user_uri"><span class="user_label user_uri_label">Uri: </span><%= uri %></div>
+    <div class="user_color"><span class="user_label user_color_label">Color: </span><%= color %></div>
+    </div>
+    <button type="button" class="remove_button" value="<%= _id %>">Remove<button>
+</script>
+<script type="text/template" id="user_form_template">
+    <table class="user_form">
+        <thead>
+            <tr><th>Field</th><th>Value</th></tr>
+        </thead>
+        <tbody>
+            <tr><td>Title:</td><td><input type="text" name="title" class="form_field" value="<%= title %>"></input></td></tr>
+            <tr><td>Uri :</td><td><input type="text" name="uri" class="form_field" value="<%= uri %>"></input></td></tr>
+            <tr><td>Color :</td><td><input type="text" name="color" class="form_field" value="<%= color %>"></input></td></tr>
+            <tr><td>Desc :</td><td><textarea name="description" class="form_field"><%= description %></textarea></td></tr>
+        </tbody>
+    </table>
+</script>
+<script type="text/template" id="node_disp_template">
+    <div class="show_form">
+    <h2 class="user_title">Node <%= _id %>: <%= title %></h2>
+    <div class="user_desc"><span class="user_label user_desc_label">Desc: </span><%= description %></div>
+    <div class="user_uri"><span class="user_label user_uri_label">Uri: </span><%= uri %></div>
+    <div class="user_creator"><span class="user_label user_uri_label">Creator: </span><%= created_by.title %></div>
+    </div>
+    <button type="button" class="remove_button" value="<%= _id %>">Remove<button>
+</script>
+<script type="text/template" id="node_form_template">
+    <table class="node_form">
+        <thead>
+            <tr><th>Field</th><th>Value</th></tr>
+        </thead>
+        <tbody>
+            <tr><td>Node title:</td><td><input type="text" name="title" class="form_field" value="<%= title %>"></input></td></tr>
+            <tr><td>Node uri :</td><td><input type="text" name="uri" class="form_field" value="<%= uri %>"></input></td></tr>
+            <tr><td>Node creator :</td><td><input type="text" name="created_by" class="form_field" value="<%= created_by.title %>" readonly="readonly"></input></td></tr>
+            <tr><td>Node desc :</td><td><textarea name="description" class="form_field"><%= description %></textarea></td></tr>
+        </tbody>
+    </table>
+</script>
+<script type="text/template" id="project_list_item_template">
+    <span class="title"><%= title %></span>&nbsp;<button type="button" class="project_load_button" value="<%= _id %>">Load</button><button type="button" class="project_delete_button" value="<%= _id %>">Delete</button>
+</script>
+
+
+</body>
+</html>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/test/java/org/iri_research/renkan/test/repositories/ProjectsRepositoryTest.java	Tue Nov 06 13:23:19 2012 +0100
@@ -0,0 +1,112 @@
+package org.iri_research.renkan.test.repositories;
+
+
+import java.sql.Array;
+import java.util.ArrayList;
+
+import org.iri_research.renkan.models.Project;
+import org.iri_research.renkan.repositories.ProjectsRepository;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration("repositories-context.xml")
+public class ProjectsRepositoryTest {
+
+	private Logger logger = LoggerFactory.getLogger(ProjectsRepositoryTest.class);
+	
+	@Autowired
+	private ProjectsRepository projectRepository;
+	
+	private ArrayList<Project> testProjects = new ArrayList<Project>();
+	
+	public ProjectsRepositoryTest() {
+	}
+	
+	@Before
+	public void setup() {
+		
+		logger.debug("Setup");		
+		ArrayList<Project> pl = new ArrayList<Project>();
+		pl.add(new Project(null, "test1", "desc1", "http://localhost:8080/rest/projects/id1"));
+		pl.add(new Project(null, "test2", "desc2", "http://localhost:8080/rest/projects/id2"));
+		logger.debug("Setup : new Project ");
+		for(Project p: projectRepository.save(pl)) {
+			this.testProjects.add(p);
+		}
+	}
+	
+	@After
+	public void teardown() {
+		logger.debug("Teardown");
+		projectRepository.deleteAll();
+	}
+	
+	@Test
+	public void testInitialRevCounter() {
+		
+		Project p = projectRepository.findOne(this.testProjects.get(0).getId());
+		
+		Assert.assertEquals("Initial rev counter should be 1", 1, p.getRevCounter());
+	}
+	
+	@Test
+	public void testIncrementRevCounter() {
+		
+		int revCounter = projectRepository.getRevCounter(this.testProjects.get(0).getId());
+		Assert.assertEquals("After 1 call rev counter should be 1", 1, revCounter);
+		revCounter = projectRepository.getRevCounter(this.testProjects.get(0).getId());
+		Assert.assertEquals("After 2 calls rev counter should be 2", 2, revCounter);
+
+		for(int i=0; i<10; i++) {
+			revCounter = projectRepository.getRevCounter(this.testProjects.get(0).getId());
+		}
+		
+		Assert.assertEquals("After 10 more calls rev counter should be 12", 12, revCounter);
+		
+		Project p = projectRepository.findOne(this.testProjects.get(0).getId());
+		
+		Assert.assertEquals("next rev counter should be 13", 13, p.getRevCounter());
+		
+		p = projectRepository.findOne(this.testProjects.get(1).getId());
+		
+		Assert.assertEquals("other project next rev counter should be 1", 1, p.getRevCounter());
+		
+	}
+	
+	
+	@Test
+	public void testIncrementNonExisting() {
+		
+		int revCounter = projectRepository.getRevCounter("aaaa");
+		Assert.assertEquals("Rev counter non existing == -1", -1, revCounter);
+		
+	}
+	
+	@Test
+	public void testIncrementNull() {
+		
+		int revCounter = projectRepository.getRevCounter(null);
+		Assert.assertEquals("Rev counter null == -1", -1, revCounter);
+		
+	}
+
+	@Test
+	public void testIncrementEmpty() {
+		
+		int revCounter = projectRepository.getRevCounter("");
+		Assert.assertEquals("Rev counter empty == -1", -1, revCounter);
+		
+	}
+	
+	
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/test/resources/log4j.xml	Tue Nov 06 13:23:19 2012 +0100
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
+
+<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
+  <appender name="console" class="org.apache.log4j.ConsoleAppender"> 
+    <param name="Target" value="System.out"/> 
+    <layout class="org.apache.log4j.PatternLayout"> 
+      <param name="ConversionPattern" value="%d{ABSOLUTE} %5p %t %c{2}:%L - %m%n"/> 
+    </layout> 
+  </appender>
+  <logger name="org.iri_research.renkan">
+    <level value="DEBUG" />
+  </logger>
+  <logger name="org.eclipse.jetty.util.log">
+    <level value="INFO" />
+  </logger>
+  <logger name="org.springframework.test">
+      <level value="DEBUG" />
+  </logger>
+  <root> 
+    <priority value ="WARN" /> 
+    <appender-ref ref="console" /> 
+  </root>
+ <!--
+log4j.rootCategory=INFO, stdout
+
+log4j.appender.stdout=org.springframework.data.document.mongodb.log4j.MongoLog4jAppender
+log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
+log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - <%m>%n
+log4j.appender.stdout.host = localhost 
+log4j.appender.stdout.port = 27017
+log4j.appender.stdout.database = logs
+log4j.appender.stdout.collectionPattern = %X{year}%X{month}
+log4j.appender.stdout.applicationId = my.application
+log4j.appender.stdout.warnOrHigherWriteConcern = FSYNC_SAFE
+
+log4j.category.org.apache.activemq=ERROR
+log4j.category.org.springframework.batch=DEBUG
+log4j.category.org.springframework.data.document.mongodb=DEBUG
+log4j.category.org.springframework.transaction=INFO
+-->
+  
+</log4j:configuration>
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/test/resources/org/iri_research/renkan/test/repositories/mongo-config.xml	Tue Nov 06 13:23:19 2012 +0100
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
+	xmlns:p="http://www.springframework.org/schema/p" 
+    xmlns:mongo="http://www.springframework.org/schema/data/mongo"
+    xmlns:context="http://www.springframework.org/schema/context"
+    xmlns:jpa="http://www.springframework.org/schema/data/jpa"
+	xsi:schemaLocation="http://www.springframework.org/schema/beans 
+	   		http://www.springframework.org/schema/beans/spring-beans.xsd
+   			http://www.springframework.org/schema/data/mongo
+    		http://www.springframework.org/schema/data/mongo/spring-mongo.xsd
+    		http://www.springframework.org/schema/context
+            http://www.springframework.org/schema/context/spring-context.xsd
+            http://www.springframework.org/schema/data/jpa
+            http://www.springframework.org/schema/data/jpa/spring-jpa.xsd">	
+	<!-- Default bean name is 'mongo' -->
+	<mongo:mongo host="localhost" port="27017"/>
+		
+	<!-- Offers convenience methods and automatic mapping between MongoDB JSON documents and your domain classes. -->
+  	<bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
+  	    <constructor-arg ref="mongo"/>
+  		<constructor-arg value="renkan_test"/>
+  		<property name="writeResultChecking" value="EXCEPTION"/>
+  	</bean>
+  	
+  	<mongo:repositories base-package="org.iri_research.renkan" factory-class="org.iri_research.renkan.repositories.RenkanRepositoryFactoryBean" />
+  	  	
+</beans>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/test/resources/org/iri_research/renkan/test/repositories/repositories-context.xml	Tue Nov 06 13:23:19 2012 +0100
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
+    xmlns:context="http://www.springframework.org/schema/context"
+    xsi:schemaLocation="http://www.springframework.org/schema/beans 
+            http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
+            http://www.springframework.org/schema/context
+            http://www.springframework.org/schema/context/spring-context-3.0.xsd">
+    
+    <!-- Activates various annotations to be detected in bean classes -->
+    <context:annotation-config />
+    
+    <!-- Configures the annotation-driven Spring MVC Controller programming model.
+    Note that, with Spring 3.0, this tag works in Servlet MVC only!  -->
+
+    <!-- Loads MongoDB configuraton -->
+    <import resource="mongo-config.xml"/>
+
+    <!--bean id="bayeuxServer" class="org.cometd.server.BayeuxServerImpl" init-method="start" destroy-method="stop">
+        <property name="options">
+            <map>
+                <entry key="logLevel" value="3" />
+                <entry key="timeout" value="15000" />
+            </map>
+        </property>  
+    </bean-->
+    <bean id="springConfigurer"
+        class="org.iri_research.renkan.coweb.SpringConfigurer"
+        factory-method="getInstance" />
+    
+    <!-- Scans the classpath for annotated components that will be auto-registered as Spring beans.
+     For example @Controller and @Service. Make sure to set the correct base-package-->
+    <context:component-scan base-package="org.iri_research.renkan.rest" />
+    <context:component-scan base-package="org.iri_research.renkan.coweb" />
+
+</beans>
\ No newline at end of file