Index: java/main/src/test/java/com/framsticks/core/ObjectInstanceTest.java
===================================================================
--- java/main/src/test/java/com/framsticks/core/ObjectInstanceTest.java	(revision 90)
+++ java/main/src/test/java/com/framsticks/core/ObjectInstanceTest.java	(revision 90)
@@ -0,0 +1,88 @@
+package com.framsticks.core;
+
+import java.util.ArrayList;
+
+import org.testng.annotations.BeforeClass;
+// import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import com.framsticks.model.Joint;
+import com.framsticks.model.Model;
+import com.framsticks.model.ModelBuilder;
+import com.framsticks.model.f0.Schema;
+import com.framsticks.model.f0.SchemaBuilder;
+import com.framsticks.test.TestConfiguration;
+import com.framsticks.util.dispatching.Dispatching;
+import com.framsticks.util.dispatching.Monitor;
+import com.framsticks.util.dispatching.RunAt;
+import com.framsticks.params.AccessInterface;
+import com.framsticks.params.ReflectionAccess;
+import com.framsticks.params.types.FloatParam;
+
+import static org.fest.assertions.Assertions.*;
+
+@Test
+public class ObjectInstanceTest extends TestConfiguration {
+
+	private Model model;
+	private Schema schema;
+	private ObjectInstance instance;
+	private Monitor monitor;
+
+	@BeforeClass
+	public void setUp() {
+		schema = new SchemaBuilder().stream(Schema.getDefaultDefinitionAsStream()).finish();
+		assertThat(schema.getFramsClasses().size()).isEqualTo(5);
+		assertThat(schema.getNeuroClasses().size()).isEqualTo(21);
+	}
+
+	@Test
+	public void loadModel() {
+		model = new ModelBuilder().schema(schema).stream(ObjectInstanceTest.class.getResourceAsStream("/parsers/f0_example.txt")).finish();
+
+		assertThat(model.getJoints().size()).isEqualTo(2);
+	}
+
+
+	@Test(dependsOnMethods = "loadModel", timeOut = 2000)
+	public void startInstance() {
+		instance = new ObjectInstance();
+		instance.getRegistry().takeAllFrom(schema.getRegistry());
+
+		instance.setRootObject(model);
+
+		monitor = new Monitor(instance);
+		monitor.use();
+
+		assertThat(Dispatching.get(instance, new Dispatching.Query<String>() {
+				@Override
+				public String get() {
+					return instance.getRootObject(Model.class).getParts().get(2).info;
+				}
+			})).isEqualTo("bla");
+
+		assertDispatch(instance, new RunAt<Instance>() {
+			@Override
+			public void run() {
+				assertThat(instance.getRootObject(Model.class).getNeuroDefinitions().get(2).details).isEqualTo("G");
+
+				Path path = instance.getPath("/");
+				assertThat(path.isResolved());
+				AccessInterface access = instance.bindAccess(path);
+				assertThat(access.get("se", Double.class)).isEqualTo(1.0);
+
+				assertThat(instance.bindAccess("/parts/2").getFramsClass().getParamEntry("m", FloatParam.class).getDef(Double.class)).isEqualTo(1.0);
+				assertThat(instance.bindAccess("/parts/2").getFramsClass().getParamEntry("m", FloatParam.class).getMax(Double.class)).isEqualTo(999.0);
+				assertThat(instance.bindAccess("/parts/2")).isInstanceOf(ReflectionAccess.class);
+				assertThat(instance.getPath("/neurodefs").getTopObject()).isInstanceOf(ArrayList.class);
+				assertThat(instance.getPath("/joints/1").getTopObject()).isInstanceOf(Joint.class);
+				assertThat(instance.bindAccess("/parts/2").get("i", String.class)).isEqualTo("bla");
+			}
+		});
+	}
+
+	@Test(dependsOnMethods = "startInstance", timeOut = 2000)
+	public void stoptInstance() {
+		monitor.useFor(1.0).drop().join();
+	}
+}
Index: java/main/src/test/java/com/framsticks/gui/BrowserBaseTest.java
===================================================================
--- java/main/src/test/java/com/framsticks/gui/BrowserBaseTest.java	(revision 90)
+++ java/main/src/test/java/com/framsticks/gui/BrowserBaseTest.java	(revision 90)
@@ -0,0 +1,78 @@
+package com.framsticks.gui;
+
+import javax.swing.JFrame;
+
+import org.apache.log4j.Logger;
+import org.fest.swing.core.Robot;
+import org.fest.swing.edt.FailOnThreadViolationRepaintManager;
+import org.fest.swing.edt.GuiQuery;
+import org.fest.swing.fixture.FrameFixture;
+import org.fest.swing.fixture.JTreeFixture;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import com.framsticks.test.TestConfiguration;
+import com.framsticks.util.dispatching.Monitor;
+
+import static org.fest.assertions.Assertions.assertThat;
+import static org.fest.swing.edt.GuiActionRunner.executeInEDT;
+import static org.fest.swing.core.BasicRobot.robotWithNewAwtHierarchy;
+import org.fest.swing.edt.GuiActionRunner;
+
+@Test
+public abstract class BrowserBaseTest extends TestConfiguration {
+
+	private static final Logger log = Logger.getLogger(BrowserTest.class);
+
+	protected Monitor monitor;
+	protected Browser browser;
+	protected static Robot robot;
+	protected FrameFixture frame;
+	protected JTreeFixture tree;
+
+	static {
+		FailOnThreadViolationRepaintManager.install();
+		assertThat(executeInEDT()).isTrue();
+
+		robot = robotWithNewAwtHierarchy();
+	}
+
+	@BeforeClass(timeOut = 5000)
+	public void setUp() {
+
+		configureBrowser();
+
+		monitor = new Monitor(browser);
+
+		monitor.use();
+
+		frame = new FrameFixture(robot,
+				GuiActionRunner.execute(new GuiQuery<JFrame>() {
+					@Override
+					protected JFrame executeInEDT() throws Throwable {
+						return browser.getMainFrame().getSwing();
+					}
+				}));
+
+		tree = frame.tree("tree");
+		log.debug("frame fixture done");
+	}
+
+	protected abstract void configureBrowser();
+
+	protected void clickAndExpandPath(String path) {
+		tree.clickPath(path).expandPath(path);
+		robot.waitForIdle();
+	}
+
+	protected void waitForIdle() {
+		robot.waitForIdle();
+	}
+
+	@AfterClass(timeOut = 5000)
+	public void tearDown() {
+		monitor.drop().join();
+	}
+
+}
Index: java/main/src/test/java/com/framsticks/gui/BrowserTest.java
===================================================================
--- java/main/src/test/java/com/framsticks/gui/BrowserTest.java	(revision 88)
+++ java/main/src/test/java/com/framsticks/gui/BrowserTest.java	(revision 90)
@@ -1,75 +1,37 @@
 package com.framsticks.gui;
 
-import javax.swing.JFrame;
+import static org.fest.assertions.Assertions.assertThat;
+import static org.fest.swing.edt.GuiActionRunner.execute;
+
 
 import org.apache.log4j.Logger;
-import org.fest.swing.edt.FailOnThreadViolationRepaintManager;
-import org.fest.swing.edt.GuiActionRunner;
-import org.fest.swing.edt.GuiQuery;
 import org.fest.swing.edt.GuiTask;
-import org.fest.swing.fixture.FrameFixture;
-import org.fest.swing.fixture.JTreeFixture;
-// import static org.fest.swing.edt.GuiActionRunner.*;
-import org.testng.annotations.*;
+import org.testng.annotations.Test;
 
+import com.framsticks.model.ModelPackage;
 import com.framsticks.remote.RemoteInstance;
-import com.framsticks.test.TestConfiguration;
-import com.framsticks.util.dispatching.Dispatching;
-import com.framsticks.util.dispatching.JoinableMonitor;
-// import com.framsticks.util.dispatching.Dispatching;
 
-import static org.fest.assertions.Assertions.*;
-import static org.fest.swing.core.BasicRobot.robotWithNewAwtHierarchy;
-import static org.fest.swing.edt.GuiActionRunner.*;
-import org.fest.swing.core.Robot;
+public class BrowserTest extends BrowserBaseTest {
 
-public class BrowserTest extends TestConfiguration {
 	private static final Logger log = Logger.getLogger(BrowserTest.class);
 
-	JoinableMonitor monitor;
-	Browser browser;
-	Robot robot;
-	FrameFixture frame;
+	RemoteInstance localhost;
 
-	@BeforeClass
-	public void setUp() {
-		FailOnThreadViolationRepaintManager.install();
-		assertThat(executeInEDT()).isTrue();
+	@Override
+	protected void configureBrowser() {
+		browser = new Browser();
 
-		robot = robotWithNewAwtHierarchy();
-
-		browser = new Browser();
-		monitor = new JoinableMonitor(browser);
-
-		RemoteInstance localhost = new RemoteInstance();
+		localhost = new RemoteInstance();
 		localhost.setName("localhost");
 		localhost.setAddress("localhost:9009");
+		localhost.usePackage(new ModelPackage());
 
 		browser.addInstance(localhost);
 
-		monitor.use();
-		// robot.waitForIdle();
-		frame = new FrameFixture(robot,
-				GuiActionRunner.execute(new GuiQuery<JFrame>() {
-					@Override
-					protected JFrame executeInEDT() throws Throwable {
-						return browser.getMainFrame().getSwing();
-					}
-				}));
-
-		log.info("frame fixture done");
-		// frame.show();
-		// log.info("frame fixture shown");
 	}
 
-	public void clickAndExpandPath(JTreeFixture tree, String path) {
-		tree.clickPath(path).expandPath(path);
-		robot.waitForIdle();
-	}
-
-	@Test
+	@Test(timeOut = 10000)
 	public void testShow() {
 		log.info("testing");
-		JTreeFixture tree = frame.tree("tree");
 		tree.clickRow(0).expandRow(0);
 		robot.waitForIdle();
@@ -81,54 +43,14 @@
 			@Override
 			protected void executeInEDT() throws Throwable {
-				assertThat(frame.panel("o Simulator").component().isVisible())
-						.isTrue();
+				assertThat(frame.panel("Simulator").component().isVisible()).isTrue();
 			}
 		});
 
-		clickAndExpandPath(tree, "localhost/simulator/genepools");
-		clickAndExpandPath(tree, "localhost/simulator/genepools/groups");
-		clickAndExpandPath(tree, "localhost/simulator/genepools/groups/Genotypes");
+		clickAndExpandPath("localhost/simulator/genepools");
+		clickAndExpandPath("localhost/simulator/genepools/groups");
+		clickAndExpandPath("localhost/simulator/genepools/groups/Genotypes");
+	}
 
 
 
-
-
-
-		// tree.clickPath("localhost/simulator/genepools/groups/Genotypes/genotypes");
-		// robot.waitForIdle();
-		// sleep(2);
-		// tree.expandPath("localhost/simulator/genepools/groups/Genotypes/genotypes");
-
-		// tree.expandRow(tree.component().getLeadSelectionRow() + 1);
-		// robot.waitForIdle();
-
-		// sleep(2);
-	}
-
-
-	@AfterClass
-	public void tearDown() {
-		log.info("before close");
-
-		monitor.drop();
-
-		Dispatching.joinAbsolutely(browser);
-		// frame.cleanUp();
-		// log.info("before close");
-		// browser.interrupt();
-
-		// try {
-		// 	// frame.close();
-		// } catch (Throwable t) {
-		// 	log.error("caught ", t);
-		// }
-		// log.info("after close");
-		// // frame.close();
-		// // frame.cleanUp();
-
-
-
-		// Dispatching.join(browser);
-	}
-
 }
Index: java/main/src/test/java/com/framsticks/gui/ObjectInstanceBrowserTest.java
===================================================================
--- java/main/src/test/java/com/framsticks/gui/ObjectInstanceBrowserTest.java	(revision 90)
+++ java/main/src/test/java/com/framsticks/gui/ObjectInstanceBrowserTest.java	(revision 90)
@@ -0,0 +1,52 @@
+package com.framsticks.gui;
+
+import static org.fest.assertions.Assertions.assertThat;
+
+import org.testng.annotations.Test;
+
+import com.framsticks.core.Instance;
+import com.framsticks.core.ObjectInstance;
+import com.framsticks.model.Model;
+import com.framsticks.params.types.FloatParam;
+import com.framsticks.parsers.XmlLoader;
+import com.framsticks.util.dispatching.RunAt;
+
+@Test
+public class ObjectInstanceBrowserTest extends BrowserBaseTest {
+
+	ObjectInstance instance;
+
+	@Override
+	protected void configureBrowser() {
+		browser = new XmlLoader().load(Browser.class, getClass().getResourceAsStream("/configs/ObjectInstanceBrowserTest.xml"));
+
+		assertThat(browser.getInstances().size()).isEqualTo(1);
+		assertThat(browser.getInstances().get("model")).isInstanceOf(ObjectInstance.class);
+
+		instance = (ObjectInstance) browser.getInstances().get("model");
+	}
+
+	@Test(timeOut = 10000)
+	public void testShow() {
+		assertDispatch(instance, new RunAt<Instance>() {
+			@Override
+			public void run() {
+				assertThat(instance.getRootObject()).isInstanceOf(Model.class);
+			}
+		});
+
+		clickAndExpandPath("model");
+		clickAndExpandPath("model/parts");
+		clickAndExpandPath("model/parts/2");
+
+		assertDispatch(instance, new RunAt<Instance>() {
+			@Override
+			public void run() {
+				assertThat(instance.bindAccess("/parts/2").getFramsClass().getParamEntry("m", FloatParam.class).getMax(Double.class)).isEqualTo(999.0);
+			}
+		});
+
+	}
+
+
+}
Index: java/main/src/test/java/com/framsticks/gui/ProcedureBrowserTest.java
===================================================================
--- java/main/src/test/java/com/framsticks/gui/ProcedureBrowserTest.java	(revision 90)
+++ java/main/src/test/java/com/framsticks/gui/ProcedureBrowserTest.java	(revision 90)
@@ -0,0 +1,93 @@
+
+package com.framsticks.gui;
+
+import static org.fest.assertions.Assertions.assertThat;
+
+import org.fest.swing.fixture.JPanelFixture;
+import org.testng.annotations.Test;
+
+import com.framsticks.core.Instance;
+import com.framsticks.core.ObjectInstance;
+import com.framsticks.params.AccessInterface;
+import com.framsticks.params.FramsClass;
+import com.framsticks.params.ReflectionAccess;
+import com.framsticks.params.types.StringParam;
+import com.framsticks.parsers.XmlLoader;
+import com.framsticks.test.TestClass;
+import com.framsticks.util.dispatching.RunAt;
+
+@Test
+public class ProcedureBrowserTest extends BrowserBaseTest {
+
+	ObjectInstance instance;
+
+	@Override
+	protected void configureBrowser() {
+		browser = new XmlLoader().load(Browser.class, getClass().getResourceAsStream("/configs/ProcedureBrowserTest.xml"));
+
+		assertThat(browser.getInstances().size()).isEqualTo(1);
+		assertThat(browser.getInstances().get("test")).isInstanceOf(ObjectInstance.class);
+
+		instance = (ObjectInstance) browser.getInstances().get("test");
+	}
+
+	@Test(timeOut = 10000)
+	public void testShow() {
+		assertDispatch(instance, new RunAt<Instance>() {
+			@Override
+			public void run() {
+				assertThat(instance.getRootObject()).isInstanceOf(TestClass.class);
+			}
+		});
+
+		clickAndExpandPath("test");
+
+		assertDispatch(instance, new RunAt<Instance>() {
+			@Override
+			public void run() {
+				assertThat(instance.bindAccess("/").getFramsClass().getParam("history")).isInstanceOf(StringParam.class);
+			}
+		});
+
+		// monitor.useFor(4.0);
+
+		assertDispatch(instance, new RunAt<Instance>() {
+			@Override
+			public void run() {
+				AccessInterface access = instance.bindAccess("/");
+				assertThat(access).isInstanceOf(ReflectionAccess.class);
+				FramsClass framsClass = access.getFramsClass();
+				assertThat(framsClass.getParamCount()).isEqualTo(4);
+				assertThat(framsClass.getParam(0).getId()).isEqualTo("name");
+				assertThat(framsClass.getParam(1).getId()).isEqualTo("history");
+				assertThat(framsClass.getParam(2).getId()).isEqualTo("appendHistory");
+				assertThat(framsClass.getParam(3).getId()).isEqualTo("resetHistory");
+
+				assertThat(access.get("history", String.class)).isEqualTo("");
+			}
+		});
+
+		// frame.panel("TestClass");
+		JPanelFixture appendHistory = frame.panel("TestClass").panel("appendHistory");
+		appendHistory.panel("arg0").textBox("value").enterText("argument");
+		appendHistory.button("call").click();
+		waitForIdle();
+
+		assertDispatch(instance, new RunAt<Instance>() {
+			@Override
+			public void run() {
+				assertThat(instance.bindAccess("/").get("history", String.class)).isEqualTo("argument|");
+			}
+		});
+
+		frame.panel("TestClass").panel("resetHistory").button("call").click();
+		waitForIdle();
+
+		assertDispatch(instance, new RunAt<Instance>() {
+			@Override
+			public void run() {
+				assertThat(instance.bindAccess("/").get("history", String.class)).isEqualTo("");
+			}
+		});
+	}
+}
Index: java/main/src/test/java/com/framsticks/model/ModelPackageTest.java
===================================================================
--- java/main/src/test/java/com/framsticks/model/ModelPackageTest.java	(revision 90)
+++ java/main/src/test/java/com/framsticks/model/ModelPackageTest.java	(revision 90)
@@ -0,0 +1,66 @@
+package com.framsticks.model;
+
+import java.io.InputStream;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import com.framsticks.params.FramsClass;
+import com.framsticks.params.ReflectionAccess;
+import com.framsticks.params.SourceInterface;
+import com.framsticks.params.ValueParam;
+import com.framsticks.parsers.FileSource;
+import com.framsticks.parsers.Loaders;
+import com.framsticks.test.TestConfiguration;
+
+import static org.fest.assertions.Assertions.*;
+
+@Test
+public class ModelPackageTest extends TestConfiguration {
+
+	@Test(dataProvider = "classesList")
+	public void testFramsClass(Class<?> javaClass, String name, int paramCount, Object[][] paramsTests) throws InstantiationException, IllegalAccessException {
+		// log.info("testing " + name + " " + javaClass + " " + Package.class.getResource(filename));
+		String filename = "/info/" + name + ".info";
+		InputStream stream = ModelPackage.class.getResourceAsStream(filename);
+		assertThat(stream).describedAs("stream " + filename).isNotNull();
+
+		SourceInterface source = new FileSource(stream, filename);
+
+		assertThat(source.isClosed()).isFalse();
+		FramsClass framsClass = Loaders.loadFramsClass(source);
+		assertThat(framsClass).isNotNull();
+
+		assertThat(framsClass.getParamCount()).isEqualTo(paramCount);
+		ReflectionAccess access = new ReflectionAccess(javaClass, framsClass);
+		Object object = javaClass.newInstance();
+		access.select(object);
+
+		if (paramsTests != null) {
+			for (Object[] args : paramsTests) {
+				String paramName = (String )args[0];
+				Object defaultValue = args[1];
+
+				ValueParam param = framsClass.getParamEntry(paramName, ValueParam.class);
+				assertThat(param.getDef(Object.class)).isEqualTo(defaultValue);
+
+			}
+		}
+	}
+
+	@DataProvider
+	public Object[][] classesList() {
+		return new Object[][] {
+			{ MechPart.class, "MechPart", 20 , null},
+			{ Joint.class, "Joint", 16 , null},
+			{ MechJoint.class, "MechJoint", 10 , null},
+			{ Neuro.class, "Neuro", 21, null},
+			{ NeuroDefinition.class, "NeuroDef", 9, null},
+			{ Part.class, "Part", 18, new Object[][] {{"m", 1.0}}},
+			// { Model.class, "Model", null},
+			{ Creature.class, "Creature", 64, null},
+			{ Genotype.class, "Genotype", 37, null},
+			{ World.class, "World", 10, null}
+		};
+	}
+}
Index: java/main/src/test/java/com/framsticks/model/PackageTest.java
===================================================================
--- java/main/src/test/java/com/framsticks/model/PackageTest.java	(revision 88)
+++ 	(revision )
@@ -1,54 +1,0 @@
-package com.framsticks.model;
-
-import java.io.InputStream;
-
-import org.testng.annotations.DataProvider;
-import org.testng.annotations.Test;
-
-import com.framsticks.params.FramsClass;
-import com.framsticks.params.ReflectionAccess;
-import com.framsticks.params.SourceInterface;
-import com.framsticks.parsers.FileSource;
-import com.framsticks.parsers.Loaders;
-import com.framsticks.test.TestConfiguration;
-
-import static org.fest.assertions.Assertions.*;
-
-@Test
-public class PackageTest extends TestConfiguration {
-
-	@Test(dataProvider = "classesList")
-	public void testFramsClass(Class<?> javaClass, String name, int paramCount) throws InstantiationException, IllegalAccessException {
-		// log.info("testing " + name + " " + javaClass + " " + Package.class.getResource(filename));
-		String filename = "/info/" + name + ".info";
-		InputStream stream = Package.class.getResourceAsStream(filename);
-		assertThat(stream).describedAs("stream " + filename).isNotNull();
-
-		SourceInterface source = new FileSource(stream, filename);
-
-		assertThat(source.isClosed()).isFalse();
-		FramsClass framsClass = Loaders.loadFramsClass(source);
-		assertThat(framsClass).isNotNull();
-
-		assertThat(framsClass.getParamCount()).isEqualTo(paramCount);
-		ReflectionAccess access = new ReflectionAccess(javaClass, framsClass);
-		Object object = javaClass.newInstance();
-		access.select(object);
-	}
-
-	@DataProvider
-	public Object[][] classesList() {
-		return new Object[][] {
-			{ MechPart.class, "MechPart", 20 },
-			{ Joint.class, "Joint", 16 },
-			{ MechJoint.class, "MechJoint", 10 },
-			{ Neuro.class, "Neuro", 21},
-			{ NeuroDef.class, "NeuroDef", 9},
-			{ Part.class, "Part", 18},
-			// { Model.class, "Model" },
-			{ Creature.class, "Creature", 64 },
-			{ Genotype.class, "Genotype", 37 },
-			{ World.class, "World", 10 }
-		};
-	}
-}
Index: java/main/src/test/java/com/framsticks/model/f0/SchemaTest.java
===================================================================
--- java/main/src/test/java/com/framsticks/model/f0/SchemaTest.java	(revision 88)
+++ java/main/src/test/java/com/framsticks/model/f0/SchemaTest.java	(revision 90)
@@ -3,4 +3,5 @@
 import org.testng.annotations.*;
 
+import com.framsticks.params.FramsClass;
 import com.framsticks.params.types.FloatParam;
 import com.framsticks.test.TestConfiguration;
@@ -15,5 +16,5 @@
 	@Test
 	public void loadSchemaWithXmlLoader() {
-		Schema schema = Schema.load(Schema.getDefaultDefinitionAsStream());
+		Schema schema = new SchemaBuilder().stream(Schema.getDefaultDefinitionAsStream()).finish();
 		assertThat(schema.getFramsClasses().size()).isEqualTo(5);
 		assertThat(schema.getNeuroClasses().size()).isEqualTo(21);
@@ -23,5 +24,11 @@
 		assertThat(schema.getNeuroClass("VEye").getParamEntry("p", FloatParam.class).getMax(Double.class)).isEqualTo(10.0, delta(0.0));
 
-		assertThat(schema.getFramsClass("p").getParamEntry("as", FloatParam.class).getDef(Double.class)).isEqualTo(0.25, delta(0.0));
+		FramsClass partClass = schema.getFramsClass("p");
+		assertThat(partClass).isNotNull();
+		assertThat(partClass.getParamEntry("as", FloatParam.class).getDef(Double.class)).isEqualTo(0.25, delta(0.0));
+		assertThat(partClass.getGroupCount()).isEqualTo(3);
+		assertThat(partClass.getGroup(1).getName()).isEqualTo("Other properties");
+		assertThat(partClass.getGroup(1).getCount()).isEqualTo(7);
+		assertThat(partClass.getGroup(1).getParam(2)).isEqualTo(partClass.getParam("dn"));
 	}
 
Index: java/main/src/test/java/com/framsticks/params/FramsClassBuilderTest.java
===================================================================
--- java/main/src/test/java/com/framsticks/params/FramsClassBuilderTest.java	(revision 90)
+++ java/main/src/test/java/com/framsticks/params/FramsClassBuilderTest.java	(revision 90)
@@ -0,0 +1,63 @@
+package com.framsticks.params;
+
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import com.framsticks.params.types.ProcedureParam;
+import com.framsticks.params.types.StringParam;
+import com.framsticks.test.TestClass;
+import com.framsticks.test.TestConfiguration;
+import static org.fest.assertions.Assertions.*;
+
+@Test
+public class FramsClassBuilderTest extends TestConfiguration {
+
+	FramsClass framsClass;
+	ReflectionAccess access;
+	TestClass test;
+
+
+	@BeforeClass
+	public void setUp() {
+		test = new TestClass();
+		test.setName("test");
+		test.appendHistory("first");
+		framsClass = FramsClass.build().forClass(TestClass.class);
+	}
+
+	@Test
+	public void checkProcedureParams() {
+		assertThat(framsClass.getParamCount()).isEqualTo(4);
+
+		assertThat(framsClass.getParam("name")).isInstanceOf(StringParam.class);
+		assertThat(framsClass.getParam("history")).isInstanceOf(StringParam.class);
+
+		assertThat(framsClass.getParam("appendHistory")).isInstanceOf(ProcedureParam.class);
+		assertThat(framsClass.getParam("resetHistory")).isInstanceOf(ProcedureParam.class);
+		ProcedureParam appendHistory = framsClass.getParamEntry("appendHistory", ProcedureParam.class);
+		assertThat(appendHistory.getArgumentsType().size()).isEqualTo(1);
+		assertThat(appendHistory.getArgumentsType().get(0).getId()).isEqualTo("arg0");
+	}
+
+	@Test(dependsOnMethods = "checkProcedureParams")
+	public void callProcedures() {
+		access = new ReflectionAccess(TestClass.class, framsClass);
+
+		access.select(test);
+
+		assertThat(access.get("history", String.class)).isEqualTo("first|");
+		Object result = access.call("appendHistory", new Object[] {"second"});
+
+		assertThat(result).isInstanceOf(Integer.class);
+		assertThat(result).isEqualTo(13);
+		assertThat(access.get("history", String.class)).isEqualTo("first|second|");
+
+		result = access.call("resetHistory", null);
+		assertThat(result).isNull();
+
+		assertThat(access.get("history", String.class)).isEqualTo("");
+
+	}
+
+}
Index: java/main/src/test/java/com/framsticks/parsers/F0ParserTest.java
===================================================================
--- java/main/src/test/java/com/framsticks/parsers/F0ParserTest.java	(revision 88)
+++ java/main/src/test/java/com/framsticks/parsers/F0ParserTest.java	(revision 90)
@@ -4,6 +4,6 @@
 
 import com.framsticks.model.*;
-import com.framsticks.model.Package;
 import com.framsticks.model.f0.Schema;
+import com.framsticks.model.f0.SchemaBuilder;
 import com.framsticks.params.*;
 import com.framsticks.params.types.FloatParam;
@@ -25,14 +25,25 @@
 	private Schema schema;
 	private List<AccessInterface> accesses;
-	private List<Object> objects;
+	private List<ModelComponent> components;
 	private Model model;
 
 	@BeforeClass
 	public void setUp() throws Exception {
-		schema = Schema.load(Schema.getDefaultDefinitionAsStream());
-		Package.register(schema.getRegistry());
+		schema = new SchemaBuilder().stream(Schema.getDefaultDefinitionAsStream()).finish();
 	}
 
 	@Test
+	public void checkFramsClasses() {
+		FramsClass modelClass = schema.getRegistry().getFramsClass("Model");
+		assertThat(modelClass).isNotNull();
+		assertThat(modelClass.getParam("se")).isInstanceOf(FloatParam.class);
+		// assertThat(modelClass.getParam("energ0")).isInstanceOf(FloatParam.class);
+		assertThat(modelClass.getParam("Vstyle")).isInstanceOf(StringParam.class);
+		assertThat(modelClass.getParamCount()).isEqualTo(6);
+		// assertThat();
+
+	}
+
+	@Test(dependsOnMethods = "checkFramsClasses")
 	public void primitiveParam() {
 		FramsClass joint = schema.getFramsClass("j");
@@ -43,15 +54,15 @@
 		assertThat(dx.getMin(Double.class)).isEqualTo(-2.0, delta(0.0));
 
-		assertThat(schema.getRegistry().getInfoFromCache("n").getParamEntry("d", StringParam.class).getDef(String.class)).isEqualTo("N");
+		assertThat(schema.getRegistry().getFramsClass("n").getParamEntry("d", StringParam.class).getDef(String.class)).isEqualTo("N");
 	}
 
-	@Test
+	@Test(dependsOnMethods = "primitiveParam")
 	public void readF0() throws IOException, ParseException {
 		assertThat(schema.getFramsClass("p")).isInstanceOf(FramsClass.class);
-		assertThat(schema.getRegistry().getInfoFromCache("p").getParamEntry("as", FloatParam.class).getDef(Double.class)).isEqualTo(0.25, delta(0.0));
+		assertThat(schema.getRegistry().getFramsClass("p").getParamEntry("as", FloatParam.class).getDef(Double.class)).isEqualTo(0.25, delta(0.0));
 
 		accesses = new F0Parser(schema, F0ParserTest.class.getResourceAsStream("/parsers/f0_example.txt")).parse();
 
-		assertThat(accesses.size()).isEqualTo(12);
+		assertThat(accesses.size()).isEqualTo(19);
 		assertThat(accesses.get(0).getSelected()).isInstanceOf(Model.class);
 		assertThat(accesses.get(5).get("i", String.class)).isEqualTo("1,2,3,\"dsadsa,,,,");
@@ -62,31 +73,37 @@
 	@Test(dependsOnMethods = {"readF0"})
 	public void stripAccessInterface() {
-		objects = Util.stripAccessInterface(accesses);
+		components = Util.stripAccessInterface(accesses, ModelComponent.class);
 
-		assertThat(objects.get(1)).isInstanceOf(Part.class);
-		assertThat(objects.get(4)).isInstanceOf(Joint.class);
-		assertThat(objects.get(6)).isInstanceOf(NeuroDef.class);
+		assertThat(components.get(1)).isInstanceOf(Part.class);
+		assertThat(components.get(4)).isInstanceOf(Joint.class);
+		assertThat(components.get(6)).isInstanceOf(NeuroDefinition.class);
+		assertThat(components.get(12)).isInstanceOf(NeuroConnection.class);
 	}
 
 	@Test(dependsOnMethods = {"stripAccessInterface"})
 	public void buildModel() {
-		model = Model.build(objects);
+		model = new ModelBuilder().addComponents(components).finish();
 
 		assertThat(model.getParts().size()).isEqualTo(3);
-		assertThat(model.getNeuroDefs().size()).isEqualTo(6);
+		assertThat(model.getNeuroDefinitions().size()).isEqualTo(6);
 		assertThat(model.getJoints().size()).isEqualTo(2);
-
-		assertThat(model.getJoints().get(0).part1).isEqualTo(0);
-		assertThat(model.getJoints().get(0).part2).isEqualTo(1);
-		assertThat(model.getNeuroDefs().size()).isEqualTo(6);
-		assertThat(model.getNeuroDefs().get(0).part).isEqualTo(1);
-		assertThat(model.getNeuroDefs().get(0).joint).isEqualTo(-1);
-		assertThat(model.getNeuroDefs().get(1).details).isEqualTo("|:p=0.25,r=1");
-		assertThat(model.getNeuroDefs().get(3).details).isEqualTo("N");
-		assertThat(model.getNeuroDefs().get(4).part).isEqualTo(-1);
+		assertThat(model.getNeuroConnections().size()).isEqualTo(7);
 
 		assertThat(model.getParts().get(1).getPosition().x).isEqualTo(2.0, delta(0.0));
 		assertThat(model.getParts().get(2).getPosition().sub(new Point3d(2.27236, -0.0792596, -0.958924)).length()).isLessThan(0.0001);
 		assertThat(model.getParts().get(2).getOrientation().y.sub(new Point3d(0.870277, -0.404792, 0.280644)).length()).isLessThan(0.0001);
+
+		assertThat(model.getJoints().get(0).part1).isEqualTo(0);
+		assertThat(model.getJoints().get(0).part2).isEqualTo(1);
+
+		assertThat(model.getNeuroDefinitions().get(0).part).isEqualTo(1);
+		assertThat(model.getNeuroDefinitions().get(0).joint).isEqualTo(-1);
+		assertThat(model.getNeuroDefinitions().get(1).details).isEqualTo("|:p=0.25,r=1");
+		assertThat(model.getNeuroDefinitions().get(3).details).isEqualTo("N");
+		assertThat(model.getNeuroDefinitions().get(4).part).isEqualTo(-1);
+
+		assertThat(model.getNeuroConnections().get(2).connectedNeuro).isEqualTo(0);
+		assertThat(model.getNeuroConnections().get(5).weight).isEqualTo(5.6, delta(0.0));
+
 	}
 
@@ -94,5 +111,4 @@
 	public void print() throws Exception {
 		ListSink sink = new ListSink();
-
 
 		new F0Writer(schema, model, sink).write();
@@ -110,4 +126,11 @@
 			"n:j=0,d=@:p=0.25",
 			"n:p=1,d=Nu",
+			"c:0,2",
+			"c:0,2,5.4",
+			"c:1,0",
+			"c:2,0,3.4",
+			"c:0,1,4.5",
+			"c:1,0,5.6",
+			"c:2,1",
 			"m:"
 		);
Index: java/main/src/test/java/com/framsticks/running/ExternalProcessTest.java
===================================================================
--- java/main/src/test/java/com/framsticks/running/ExternalProcessTest.java	(revision 88)
+++ java/main/src/test/java/com/framsticks/running/ExternalProcessTest.java	(revision 90)
@@ -10,5 +10,5 @@
 
 import com.framsticks.test.TestConfiguration;
-import com.framsticks.util.dispatching.JoinableMonitor;
+import com.framsticks.util.dispatching.Monitor;
 
 import static org.fest.assertions.Assertions.*;
@@ -17,5 +17,5 @@
 public class ExternalProcessTest extends TestConfiguration {
 
-	@Test
+	@Test(timeOut = 1000)
 	public void runBash() throws InterruptedException {
 		final ExternalProcess process = new ExternalProcess();
@@ -31,5 +31,5 @@
 			}
 		});
-		JoinableMonitor monitor = new JoinableMonitor(process);
+		Monitor monitor = new Monitor(process);
 		monitor.use();
 
Index: java/main/src/test/java/com/framsticks/running/FramsServerTest.java
===================================================================
--- java/main/src/test/java/com/framsticks/running/FramsServerTest.java	(revision 88)
+++ java/main/src/test/java/com/framsticks/running/FramsServerTest.java	(revision 90)
@@ -4,6 +4,6 @@
 
 import com.framsticks.core.Framsticks;
-import com.framsticks.remote.RemoteInstance;
 import com.framsticks.test.TestConfiguration;
+import com.framsticks.util.dispatching.Monitor;
 
 import static org.fest.assertions.Assertions.*;
@@ -12,11 +12,21 @@
 public class FramsServerTest extends TestConfiguration {
 
-	@Test
+	@Test(timeOut = 3000)
 	public void runServer() {
 		Framsticks framsticks = Framsticks.loadConfiguration(FramsServerTest.class.getResourceAsStream("/configs/FramsServerTest.xml"));
 
-		assertThat(framsticks.getObservables().size()).isEqualTo(2);
+		assertThat(framsticks.getObservables().size()).isEqualTo(1);
 		assertThat(framsticks.getObservables().get("frams")).isInstanceOf(FramsServer.class);
-		assertThat(framsticks.getObservables().get("remote")).isInstanceOf(RemoteInstance.class);
+		// assertThat(framsticks.getObservables().get("remote")).isInstanceOf(RemoteInstance.class);
+
+		new Monitor(framsticks).use().useFor(1.0).drop().join();
+
+		// monitor.use();
+
+		// Dispatching.sleep(1000);
+
+		// // monitor.waitFor();
+		// monitor.drop();
+		// monitor.join();
 
 		// framsticks.start();
Index: java/main/src/test/java/com/framsticks/test/TestClass.java
===================================================================
--- java/main/src/test/java/com/framsticks/test/TestClass.java	(revision 90)
+++ java/main/src/test/java/com/framsticks/test/TestClass.java	(revision 90)
@@ -0,0 +1,56 @@
+package com.framsticks.test;
+
+import com.framsticks.params.annotations.FramsClassAnnotation;
+import com.framsticks.params.annotations.ParamAnnotation;
+import com.framsticks.params.types.ProcedureParam;
+
+@FramsClassAnnotation(order = {"name", "history", "appendHistory", "resetHistory"})
+public class TestClass {
+
+	protected String name = "test";
+	protected String history = "";
+
+	/**
+	 * @return the name
+	 */
+	@ParamAnnotation
+	public String getName() {
+		return name;
+	}
+
+	/**
+	 * @param name the name to set
+	 */
+	@ParamAnnotation
+	public void setName(String name) {
+		this.name = name;
+	}
+
+	/**
+	 * @return the history
+	 */
+	@ParamAnnotation
+	public String getHistory() {
+		return history;
+	}
+
+	/**
+	 * @param history the history to set
+	 */
+	@ParamAnnotation
+	public void setHistory(String history) {
+		this.history = history;
+	}
+
+	@ParamAnnotation(paramType = ProcedureParam.class)
+	public int appendHistory(String line) {
+		history = history + line + "|";
+		return history.length();
+	}
+
+	@ParamAnnotation(paramType = ProcedureParam.class)
+	public void resetHistory() {
+		history = "";
+	}
+
+}
Index: java/main/src/test/java/com/framsticks/test/TestConfiguration.java
===================================================================
--- java/main/src/test/java/com/framsticks/test/TestConfiguration.java	(revision 88)
+++ java/main/src/test/java/com/framsticks/test/TestConfiguration.java	(revision 90)
@@ -1,3 +1,6 @@
 package com.framsticks.test;
+
+import java.util.LinkedList;
+import java.util.List;
 
 import org.apache.log4j.Logger;
@@ -5,8 +8,10 @@
 import org.testng.annotations.*;
 
+import com.framsticks.util.dispatching.Dispatcher;
+import com.framsticks.util.dispatching.RunAt;
+
 public class TestConfiguration {
 
-	private static final Logger log =
-		Logger.getLogger(TestConfiguration.class);
+	private static final Logger log = Logger.getLogger(TestConfiguration.class);
 
 	@BeforeClass
@@ -16,3 +21,70 @@
 	}
 
+	private final List<AsyncAssert<?>> asyncAssertions = new LinkedList<AsyncAssert<?>>();
+
+	public class AsyncAssert<C> extends RunAt<C> {
+		final RunAt<? extends C> runnable;
+		boolean done = false;
+		AssertionError assertion;
+
+		/**
+		 * @param runnable
+		 */
+		public AsyncAssert(RunAt<? extends C> runnable) {
+			this.runnable = runnable;
+		}
+
+		@Override
+		public void run() {
+			try {
+				runnable.run();
+			} catch (AssertionError e) {
+				assertion = e;
+			}
+			synchronized (this) {
+				done = true;
+				this.notifyAll();
+			}
+		}
+	}
+
+	public <C> void assertDispatch(Dispatcher<C> dispatcher, RunAt<? extends C> runnable) {
+		AsyncAssert<C> assertion = new AsyncAssert<C>(runnable);
+		synchronized (asyncAssertions) {
+			asyncAssertions.add(assertion);
+		}
+		dispatcher.dispatch(assertion);
+	}
+
+	@BeforeMethod
+	public void clearAsyncAsserts() {
+		synchronized (asyncAssertions) {
+			asyncAssertions.clear();
+		}
+	}
+
+	@AfterMethod(timeOut = 5000)
+	public void waitForAsyncAsserts() {
+		while (true) {
+			AsyncAssert<?> assertion;
+			synchronized (asyncAssertions) {
+				if (asyncAssertions.isEmpty()) {
+					return;
+				}
+				assertion = asyncAssertions.get(0);
+				asyncAssertions.remove(0);
+			}
+			synchronized (assertion) {
+				while (!assertion.done) {
+					try {
+						assertion.wait();
+					} catch (InterruptedException ignored) {
+					}
+				}
+				if (assertion.assertion != null) {
+					throw assertion.assertion;
+				}
+			}
+		}
+	}
 }
Index: java/main/src/test/resources/configs/FramsServerTest.xml
===================================================================
--- java/main/src/test/resources/configs/FramsServerTest.xml	(revision 88)
+++ java/main/src/test/resources/configs/FramsServerTest.xml	(revision 90)
@@ -3,5 +3,8 @@
 	<import class="com.framsticks.running.FramsServer" />
 	<import class="com.framsticks.remote.RemoteInstance" />
-	<FramsServer name="frams" port="9008" />
-	<RemoteInstance name="remote" address="localhost:9008" />
+	<import class="com.framsticks.running.LoggingOutputListener" />
+	<FramsServer name="frams" port="9008">
+		<LoggingOutputListener />
+	</FramsServer>
+	<!-- <RemoteInstance name="remote" address="localhost:9008" /> -->
 </Framsticks>
Index: java/main/src/test/resources/configs/ObjectInstanceBrowserTest.xml
===================================================================
--- java/main/src/test/resources/configs/ObjectInstanceBrowserTest.xml	(revision 90)
+++ java/main/src/test/resources/configs/ObjectInstanceBrowserTest.xml	(revision 90)
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Browser>
+	<import class="com.framsticks.model.ModelBuilder" />
+	<import class="com.framsticks.core.ObjectInstance" />
+	<import class="com.framsticks.model.ModelPackage" />
+	<ObjectInstance name="model">
+		<ModelBuilder resource="/examples/f0_example.txt" />
+	</ObjectInstance>
+</Browser>
Index: java/main/src/test/resources/configs/ProcedureBrowserTest.xml
===================================================================
--- java/main/src/test/resources/configs/ProcedureBrowserTest.xml	(revision 90)
+++ java/main/src/test/resources/configs/ProcedureBrowserTest.xml	(revision 90)
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Browser>
+	<import class="com.framsticks.core.ObjectInstance" />
+	<import class="com.framsticks.test.TestClass" />
+	<ObjectInstance name="test">
+		<TestClass />
+	</ObjectInstance>
+</Browser>
Index: java/main/src/test/resources/info/Part.info
===================================================================
--- java/main/src/test/resources/info/Part.info	(revision 88)
+++ java/main/src/test/resources/info/Part.info	(revision 90)
@@ -3,109 +3,98 @@
 
 prop:
+id:x
 name:position.x
-id:x
 type:f
 flags:1024
 
 prop:
+id:y
 name:position.y
-id:y
 type:f
 flags:1024
 
 prop:
+id:z
 name:position.z
-id:z
 type:f
 flags:1024
 
 prop:
+id:m
 name:mass
-id:m
-type:f
-flags:0
+type:f 0.1 999.0 1.0
 
 prop:
+id:s
 name:size
-id:s
-type:f
-flags:0
+type:f 0.1 10.0 1.0
 
 prop:
+id:dn
 name:density
-id:dn
-type:f
-flags:0
+type:f 0.2 5.0 1.0
 
 prop:
+id:fr
 name:friction
-id:fr
-type:f
-flags:0
+type:f 0.0 4.0 0.4
 
 prop:
+id:ing
 name:ingestion
-id:ing
-type:f
-flags:0
+type:f 0.0 1.0 0.25
 
 prop:
+id:as
 name:assimilation
-id:as
-type:f
-flags:0
+type:f 0.0 1.0 0.25
 
 prop:
+id:rx
 name:rot.x
-id:rx
 type:f
-flags:0
 
 prop:
+id:ry
 name:rot.y
-id:ry
 type:f
 flags:1024
 
 prop:
+id:rz
 name:rot.z
-id:rz
 type:f
 flags:1024
 
 prop:
+id:i
 name:info
-id:i
 type:s
-flags:0
 
 prop:
+id:Vstyle
 name:vis_style
-id:Vstyle
-type:s
-flags:0
+type:s 0 -1 part
 
 prop:
+id:vs
 name:visual thickness
-id:vs
-type:f
-flags:0
+type:f 0.05 0.7 0.3
 
 prop:
+id:vr
 name:red component
-id:vr
-type:f
-flags:0
+type:f 0.0 1.0 0.5
 
 prop:
+id:vg
 name:green component
-id:vg
-type:f
+type:f 0.0 1.0 0.5
 flags:1024
 
 prop:
+id:vb
 name:blue component
-id:vb
-type:f
+type:f 0.0 1.0 0.5
 flags:1024
 
Index: java/main/src/test/resources/log4j.properties
===================================================================
--- java/main/src/test/resources/log4j.properties	(revision 88)
+++ java/main/src/test/resources/log4j.properties	(revision 90)
@@ -27,6 +27,8 @@
 
 log4j.logger.com.framsticks=INFO
-# log4j.logger.com.framsticks.util.dispatching.JoinableMonitor=DEBUG
-# log4j.logger.com.framsticks.util.dispatching.Dispatching=DEBUG
+# log4j.logger.com.framsticks.parsers.F0Writer=TRACE
+# log4j.logger.com.framsticks.core.ObjectInstance=DEBUG
+# log4j.logger.com.framsticks.core.Instance=DEBUG
+# log4j.logger.com.framsticks.running=DEBUG
 # log4j.logger.com.framsticks.parsers.XmlLoader=DEBUG
 # log4j.logger.com.framsticks.parsers.MultiParamLoader=TRACE
Index: java/main/src/test/resources/parsers/f0_example.txt
===================================================================
--- java/main/src/test/resources/parsers/f0_example.txt	(revision 88)
+++ java/main/src/test/resources/parsers/f0_example.txt	(revision 90)
@@ -12,9 +12,9 @@
 n:j=0,d=@:p=0.25
 n:p=1,d=Nu
-#c:0,2
-#c:0,2,5.4
-#c:1,0
-#c:2,0,3.4
-#c:0,1,4.5
-#c:1,0,5.6
-#c:2,1
+c:0,2
+c:0,2,5.4
+c:1,0
+c:2,0,3.4
+c:0,1,4.5
+c:1,0,5.6
+c:2,1
