Index: java/main/src/main/java/com/framsticks/communication/ClientConnection.java
===================================================================
--- java/main/src/main/java/com/framsticks/communication/ClientConnection.java	(revision 79)
+++ java/main/src/main/java/com/framsticks/communication/ClientConnection.java	(revision 84)
@@ -8,10 +8,12 @@
 import com.framsticks.params.ListSource;
 import com.framsticks.util.*;
+import com.framsticks.util.dispatching.AtOnceDispatcher;
+import com.framsticks.util.dispatching.Dispatcher;
+import com.framsticks.util.dispatching.Dispatching;
+import com.framsticks.util.lang.Pair;
+import com.framsticks.util.lang.Strings;
 import org.apache.log4j.Logger;
 
-import java.io.BufferedReader;
 import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.PrintWriter;
 import java.net.Socket;
 import java.net.SocketException;
@@ -25,367 +27,368 @@
 public class ClientConnection extends Connection {
 
-    private final static Logger LOGGER = Logger.getLogger(ClientConnection.class);
-
-    protected final Map<String, Subscription> subscriptions = new HashMap<String, Subscription>();
-
-    public String getAddress() {
-        return address;
-    }
-
-    public void connect(StateFunctor connectedFunctor) {
-        try {
-            LOGGER.info("connecting to " + address);
-
-            socket = new Socket(hostName, port);
-
-            socket.setSoTimeout(500);
-
-            LOGGER.info("connected to " + hostName + ":" + port);
-            connected = true;
-
-            runThreads();
-
-            connectedFunctor.call(null);
-        } catch (SocketException e) {
-            LOGGER.error("failed to connect: " + e);
-            connectedFunctor.call(e);
-        } catch (IOException e) {
-            LOGGER.error("buffer creation failure");
-            connectedFunctor.call(e);
-            close();
-        }
-    }
-
-    private static abstract class InboundMessage {
-        protected String currentFilePath;
-        protected List<String> currentFileContent;
-        protected final List<File> files = new ArrayList<File>();
-
-        public abstract void eof();
-
-        protected void initCurrentFile(String path) {
-            currentFileContent = new LinkedList<String>();
-            currentFilePath = path;
-        }
-        protected void finishCurrentFile() {
-            if (currentFileContent == null) {
-                return;
-            }
-            files.add(new File(currentFilePath, new ListSource(currentFileContent)));
-            currentFilePath = null;
-            currentFileContent= null;
-        }
-
-        public abstract void startFile(String path);
-
-        public void addLine(String line) {
-            assert line != null;
-            assert currentFileContent != null;
-            currentFileContent.add(line.substring(0, line.length() - 1));
-        }
-
-        public List<File> getFiles() {
-            return files;
-        }
-    }
-
-    private static class EventFire extends InboundMessage {
-        public final Subscription subscription;
-
-        private EventFire(Subscription subscription) {
-            this.subscription = subscription;
-        }
-
-        public void startFile(String path) {
-            assert path == null;
-            initCurrentFile(null);
-        }
-
-        @Override
-        public void eof() {
-            finishCurrentFile();
-            Dispatching.invokeLaterOrNow(subscription.getDispatcher(), new Runnable() {
-                @Override
-                public void run() {
-                    subscription.getEventCallback().call(getFiles());
-                }
-            });
-        }
-    }
-
-    private static class SentQuery extends InboundMessage {
-        Request request;
-        ResponseCallback callback;
-        Dispatcher dispatcher;
-
-        public void startFile(String path) {
-            finishCurrentFile();
-            if (path == null) {
-                assert request instanceof ApplicationRequest;
-                path = ((ApplicationRequest)request).getPath();
-            }
-            initCurrentFile(path);
-        }
-
-        public void eof() {
-            finishCurrentFile();
-            //no-operation
-        }
-
-        @Override
-        public String toString() {
-            return request.toString();
-        }
-    }
-    private Map<Integer, SentQuery> queryMap = new HashMap<Integer, SentQuery>();
-
-
-    protected final String address;
-    protected final String hostName;
-    protected final int port;
-
-    private static Pattern addressPattern = Pattern.compile("^([^:]*)(:([0-9]+))?$");
-
-    public ClientConnection(String address) {
-        assert address != null;
-        this.address = address;
-        Matcher matcher = addressPattern.matcher(address);
-        if (!matcher.matches()) {
-            LOGGER.fatal("invalid address: " + address);
-            hostName = null;
-            port = 0;
-            return;
-        }
-        hostName = matcher.group(1);
-        port = matcher.group(3) != null ? Integer.parseInt(matcher.group(3)) : 9009;
-    }
-
-    private SentQuery currentlySentQuery;
-
-    public void send(Request request, ResponseCallback callback) {
-        send(request, AtOnceDispatcher.instance, callback);
-    }
-
-    public void send(Request request, Dispatcher dispatcher, ResponseCallback callback) {
-
-        if (!isConnected()) {
-            LOGGER.fatal("not connected");
-            return;
-        }
-        final SentQuery sentQuery = new SentQuery();
-        sentQuery.request = request;
-        sentQuery.callback = callback;
-        sentQuery.dispatcher = dispatcher;
-
-        senderThread.invokeLater(new Runnable(){
-            @Override
-            public void run() {
-                synchronized (ClientConnection.this) {
-
-                    while (!(requestIdEnabled || currentlySentQuery == null)) {
-                        try {
-                            ClientConnection.this.wait();
-                        } catch (InterruptedException ignored) {
-                            break;
-                        }
-                    }
-                }
-                Integer id = stashQuery(sentQuery);
-                String command = sentQuery.request.getCommand();
-                StringBuilder message = new StringBuilder();
-                message.append(command);
-                if (id != null) {
-                    message.append(" ").append(id);
-                }
-                sentQuery.request.construct(message);
-                String out = message.toString();
-
-                output.println(out);
-                LOGGER.debug("sending query: " + out);
-
-            }
-        });
-        /*
-        synchronized (this) {
-            LOGGER.debug("queueing query: " + query);
-            queryQueue.offer(sentQuery);
-            notifyAll();
-        }
-        */
-    }
-
-
-    @Override
-    public String toString() {
-        return address;
-    }
-
-    public void subscribe(final String path, final SubscriptionCallback callback) {
-        send(new RegistrationRequest().setPath(path), new ResponseCallback() {
-            @Override
-            public void process(Response response) {
-                if (!response.getOk()) {
-                    LOGGER.error("failed to register on event: " + path);
-                    callback.subscribed(null);
-                    return;
-                }
-                assert response.getFiles().isEmpty();
-                Subscription subscription = new Subscription(ClientConnection.this, path, response.getComment());
-                LOGGER.debug("registered on event: " + subscription);
-                synchronized (subscriptions) {
-                    subscriptions.put(subscription.getRegisteredPath(), subscription);
-                }
-                subscription.setEventCallback(callback.subscribed(subscription));
-                if (subscription.getEventCallback() == null) {
-                    LOGGER.info("subscription for " + path + " aborted");
-                    subscription.unsubscribe(new LoggingStateCallback(LOGGER, "abort subscription"));
-                }
-            }
-        });
-    }
-
-    public void negotiateProtocolVersion(StateFunctor stateFunctor) {
-        protocolVersion = -1;
-        sendQueryVersion(1, stateFunctor);
-    }
-
-    public void sendQueryVersion(final int version, final StateFunctor stateFunctor) {
-        send(new VersionRequest().version(version), new StateCallback() {
-            @Override
-            public void call(Exception e) {
-                if (e != null) {
-                    LOGGER.fatal("failed to upgrade protocol to version: " + version);
-                    return;
-                }
-                protocolVersion = version;
-                if (version < 4) {
-                    /** it is an implicit loop here*/
-                    sendQueryVersion(version + 1, stateFunctor);
-                    return;
-                }
-                send(new UseRequest().feature("request_id"), new StateCallback() {
-                    @Override
-                    public void call(Exception e) {
-                        requestIdEnabled = e == null;
-                        /*
-                        synchronized (ClientConnection.this) {
-                            ClientConnection.this.notifyAll();
-                        }
-                        */
-                        if (!requestIdEnabled) {
-                            LOGGER.fatal("protocol negotiation failed");
-                            stateFunctor.call(new Exception("protocol negotiation failed", e));
-                            return;
-                        }
-                        stateFunctor.call(null);
-                    }
-                });
-
-            }
-        });
-    }
-
-
-    private synchronized SentQuery fetchQuery(Integer id, boolean remove) {
-        if (id == null) {
-            if (requestIdEnabled) {
-                return null;
-            }
-            SentQuery result = currentlySentQuery;
-            if (remove) {
-                currentlySentQuery = null;
-                notifyAll();
-            }
-            return result;
-        }
-        if (queryMap.containsKey(id)) {
-            SentQuery result = queryMap.get(id);
-            if (remove) {
-                queryMap.remove(id);
-            }
-            return result;
-        }
-        return null;
-    }
-
-    private int nextQueryId = 0;
-
-    private Integer stashQuery(SentQuery sentQuery) {
-        if (!requestIdEnabled) {
-            currentlySentQuery = sentQuery;
-            return null;
-        }
-        queryMap.put(nextQueryId, sentQuery);
-        return nextQueryId++;
-    }
-
-    protected void processMessage(InboundMessage inboundMessage) throws Exception {
-        if (inboundMessage == null) {
-            LOGGER.error("failed to use any inbound message");
-            return;
-        }
-
-        String line;
-        while (!(line = getLine()).startsWith("eof")) {
-            inboundMessage.addLine(line);
-        }
-        inboundMessage.eof();
-    }
-
-    protected void processEvent(String rest) throws Exception {
-        Matcher matcher = eventPattern.matcher(rest);
-        if (!matcher.matches()) {
-            LOGGER.error("invalid event line: " + rest);
-            return;
-        }
-        Subscription subscription = subscriptions.get(matcher.group(1));
-        if (subscription == null) {
-            LOGGER.error("non subscribed event: " + matcher.group(1));
-            return;
-        }
-        EventFire event = new EventFire(subscription);
-        event.startFile(null);
-        processMessage(event);
-    }
-
-
-    protected void processMessageStartingWith(String line) throws Exception {
-        Pair<String, String> command = Strings.splitIntoPair(line, ' ', "\n");
-        if (command.first.equals("event")) {
-            processEvent(command.second);
-            return;
-        }
-        Pair<Integer, String> rest = parseRest(command.second);
-
-        if (command.first.equals("file")) {
-            SentQuery sentQuery = fetchQuery(rest.first, false);
-            sentQuery.startFile(rest.second);
-            processMessage(sentQuery);
-            return;
-        }
-
-        SentQuery sentQuery = fetchQuery(rest.first, true);
-        if (sentQuery == null) {
-            return;
-        }
-        LOGGER.debug("parsing response for request " + sentQuery);
-
-        final Response response = new Response(command.first.equals("ok"), rest.second, sentQuery.getFiles());
-        final ResponseCallback callback = sentQuery.callback;
-
-        Dispatching.invokeLaterOrNow(sentQuery.dispatcher, new Runnable() {
-            @Override
-            public void run() {
-                callback.process(response);
-            }
-        });
-    }
-
-    @Override
-    protected void receiverThreadRoutine() throws Exception {
-        while (connected) {
-            processMessageStartingWith(getLine());
-        }
-    }
+	private final static Logger log = Logger.getLogger(ClientConnection.class);
+
+	protected final Map<String, Subscription> subscriptions = new HashMap<String, Subscription>();
+
+	public String getAddress() {
+		return address;
+	}
+
+	public void connect(StateFunctor connectedFunctor) {
+		try {
+			log.info("connecting to " + address);
+
+			socket = new Socket(hostName, port);
+
+			socket.setSoTimeout(500);
+
+			log.info("connected to " + hostName + ":" + port);
+			connected = true;
+
+			runThreads();
+
+			connectedFunctor.call(null);
+		} catch (SocketException e) {
+			log.error("failed to connect: " + e);
+			connectedFunctor.call(e);
+		} catch (IOException e) {
+			log.error("buffer creation failure");
+			connectedFunctor.call(e);
+			close();
+		}
+	}
+
+	private static abstract class InboundMessage {
+		protected String currentFilePath;
+		protected List<String> currentFileContent;
+		protected final List<File> files = new ArrayList<File>();
+
+		public abstract void eof();
+
+		protected void initCurrentFile(String path) {
+			currentFileContent = new LinkedList<String>();
+			currentFilePath = path;
+		}
+		protected void finishCurrentFile() {
+			if (currentFileContent == null) {
+				return;
+			}
+			files.add(new File(currentFilePath, new ListSource(currentFileContent)));
+			currentFilePath = null;
+			currentFileContent= null;
+		}
+
+		public abstract void startFile(String path);
+
+		public void addLine(String line) {
+			assert line != null;
+			assert currentFileContent != null;
+			currentFileContent.add(line.substring(0, line.length() - 1));
+		}
+
+		public List<File> getFiles() {
+			return files;
+		}
+	}
+
+	private static class EventFire extends InboundMessage {
+		public final Subscription subscription;
+
+		private EventFire(Subscription subscription) {
+			this.subscription = subscription;
+		}
+
+		public void startFile(String path) {
+			assert path == null;
+			initCurrentFile(null);
+		}
+
+		@Override
+		public void eof() {
+			finishCurrentFile();
+			Dispatching.invokeLaterOrNow(subscription.getDispatcher(), new Runnable() {
+				@Override
+				public void run() {
+					subscription.getEventCallback().call(getFiles());
+				}
+			});
+		}
+	}
+
+	private static class SentQuery extends InboundMessage {
+		Request request;
+		ResponseCallback callback;
+		Dispatcher dispatcher;
+
+		public void startFile(String path) {
+			finishCurrentFile();
+			if (path == null) {
+				assert request instanceof ApplicationRequest;
+				path = ((ApplicationRequest)request).getPath();
+			}
+			initCurrentFile(path);
+		}
+
+		public void eof() {
+			finishCurrentFile();
+			//no-operation
+		}
+
+		@Override
+		public String toString() {
+			return request.toString();
+		}
+	}
+	private Map<Integer, SentQuery> queryMap = new HashMap<Integer, SentQuery>();
+
+
+	protected final String address;
+	protected final String hostName;
+	protected final int port;
+
+	private static Pattern addressPattern = Pattern.compile("^([^:]*)(:([0-9]+))?$");
+
+	public ClientConnection(String address) {
+		assert address != null;
+		this.address = address;
+		Matcher matcher = addressPattern.matcher(address);
+		if (!matcher.matches()) {
+			log.fatal("invalid address: " + address);
+			hostName = null;
+			port = 0;
+			return;
+		}
+		hostName = matcher.group(1);
+		port = matcher.group(3) != null ? Integer.parseInt(matcher.group(3)) : 9009;
+	}
+
+	private SentQuery currentlySentQuery;
+
+	public void send(Request request, ResponseCallback callback) {
+		send(request, AtOnceDispatcher.instance, callback);
+	}
+
+	public void send(Request request, Dispatcher dispatcher, ResponseCallback callback) {
+
+		if (!isConnected()) {
+			log.fatal("not connected");
+			return;
+		}
+		final SentQuery sentQuery = new SentQuery();
+		sentQuery.request = request;
+		sentQuery.callback = callback;
+		sentQuery.dispatcher = dispatcher;
+
+		senderThread.invokeLater(new Runnable(){
+			@Override
+			public void run() {
+				synchronized (ClientConnection.this) {
+
+					while (!(requestIdEnabled || currentlySentQuery == null)) {
+						try {
+							ClientConnection.this.wait();
+						} catch (InterruptedException ignored) {
+							break;
+						}
+					}
+				}
+				Integer id = stashQuery(sentQuery);
+				String command = sentQuery.request.getCommand();
+				StringBuilder message = new StringBuilder();
+				message.append(command);
+				if (id != null) {
+					message.append(" ").append(id);
+				}
+				sentQuery.request.construct(message);
+				String out = message.toString();
+
+				output.println(out);
+				log.debug("sending query: " + out);
+
+			}
+		});
+		/*
+		synchronized (this) {
+			log.debug("queueing query: " + query);
+			queryQueue.offer(sentQuery);
+			notifyAll();
+		}
+		*/
+	}
+
+
+	@Override
+	public String toString() {
+		return address;
+	}
+
+	public void subscribe(final String path, final SubscriptionCallback callback) {
+		send(new RegistrationRequest().setPath(path), new ResponseCallback() {
+			@Override
+			public void process(Response response) {
+				if (!response.getOk()) {
+					log.error("failed to register on event: " + path);
+					callback.subscribed(null);
+					return;
+				}
+				assert response.getFiles().isEmpty();
+				Subscription subscription = new Subscription(ClientConnection.this, path, response.getComment());
+				log.debug("registered on event: " + subscription);
+				synchronized (subscriptions) {
+					subscriptions.put(subscription.getRegisteredPath(), subscription);
+				}
+				subscription.setEventCallback(callback.subscribed(subscription));
+				if (subscription.getEventCallback() == null) {
+					log.info("subscription for " + path + " aborted");
+					subscription.unsubscribe(new LoggingStateCallback(log, "abort subscription"));
+				}
+			}
+		});
+	}
+
+	public void negotiateProtocolVersion(StateFunctor stateFunctor) {
+		protocolVersion = -1;
+		sendQueryVersion(1, stateFunctor);
+	}
+
+	public void sendQueryVersion(final int version, final StateFunctor stateFunctor) {
+		send(new VersionRequest().version(version), new StateCallback() {
+			@Override
+			public void call(Exception e) {
+				if (e != null) {
+					log.fatal("failed to upgrade protocol to version: " + version);
+					return;
+				}
+				protocolVersion = version;
+				if (version < 4) {
+					/** it is an implicit loop here*/
+					sendQueryVersion(version + 1, stateFunctor);
+					return;
+				}
+				send(new UseRequest().feature("request_id"), new StateCallback() {
+					@Override
+					public void call(Exception e) {
+						requestIdEnabled = e == null;
+						/*
+						synchronized (ClientConnection.this) {
+							ClientConnection.this.notifyAll();
+						}
+						*/
+						if (!requestIdEnabled) {
+							log.fatal("protocol negotiation failed");
+							stateFunctor.call(new Exception("protocol negotiation failed", e));
+							return;
+						}
+						stateFunctor.call(null);
+					}
+				});
+
+			}
+		});
+	}
+
+
+	private synchronized SentQuery fetchQuery(Integer id, boolean remove) {
+		if (id == null) {
+			if (requestIdEnabled) {
+				return null;
+			}
+			SentQuery result = currentlySentQuery;
+			if (remove) {
+				currentlySentQuery = null;
+				notifyAll();
+			}
+			return result;
+		}
+		if (queryMap.containsKey(id)) {
+			SentQuery result = queryMap.get(id);
+			if (remove) {
+				queryMap.remove(id);
+			}
+			return result;
+		}
+		return null;
+	}
+
+	private int nextQueryId = 0;
+
+	private Integer stashQuery(SentQuery sentQuery) {
+		if (!requestIdEnabled) {
+			currentlySentQuery = sentQuery;
+			return null;
+		}
+		queryMap.put(nextQueryId, sentQuery);
+		return nextQueryId++;
+	}
+
+	protected void processMessage(InboundMessage inboundMessage) throws Exception {
+		if (inboundMessage == null) {
+			log.error("failed to use any inbound message");
+			return;
+		}
+
+		String line;
+		while (!(line = getLine()).startsWith("eof")) {
+			// log.debug("line: " + line);
+			inboundMessage.addLine(line);
+		}
+		inboundMessage.eof();
+	}
+
+	protected void processEvent(String rest) throws Exception {
+		Matcher matcher = eventPattern.matcher(rest);
+		if (!matcher.matches()) {
+			log.error("invalid event line: " + rest);
+			return;
+		}
+		Subscription subscription = subscriptions.get(matcher.group(1));
+		if (subscription == null) {
+			log.error("non subscribed event: " + matcher.group(1));
+			return;
+		}
+		EventFire event = new EventFire(subscription);
+		event.startFile(null);
+		processMessage(event);
+	}
+
+
+	protected void processMessageStartingWith(String line) throws Exception {
+		Pair<String, String> command = Strings.splitIntoPair(line, ' ', "\n");
+		if (command.first.equals("event")) {
+			processEvent(command.second);
+			return;
+		}
+		Pair<Integer, String> rest = parseRest(command.second);
+
+		if (command.first.equals("file")) {
+			SentQuery sentQuery = fetchQuery(rest.first, false);
+			sentQuery.startFile(rest.second);
+			processMessage(sentQuery);
+			return;
+		}
+
+		SentQuery sentQuery = fetchQuery(rest.first, true);
+		if (sentQuery == null) {
+			return;
+		}
+		log.debug("parsing response for request " + sentQuery);
+
+		final Response response = new Response(command.first.equals("ok"), rest.second, sentQuery.getFiles());
+		final ResponseCallback callback = sentQuery.callback;
+
+		Dispatching.invokeLaterOrNow(sentQuery.dispatcher, new Runnable() {
+			@Override
+			public void run() {
+				callback.process(response);
+			}
+		});
+	}
+
+	@Override
+	protected void receiverThreadRoutine() throws Exception {
+		while (connected) {
+			processMessageStartingWith(getLine());
+		}
+	}
 
 }
Index: java/main/src/main/java/com/framsticks/communication/Connection.java
===================================================================
--- java/main/src/main/java/com/framsticks/communication/Connection.java	(revision 79)
+++ java/main/src/main/java/com/framsticks/communication/Connection.java	(revision 84)
@@ -1,5 +1,5 @@
 package com.framsticks.communication;
 
-import com.framsticks.util.Pair;
+import com.framsticks.util.lang.Pair;
 import org.apache.log4j.Logger;
 import java.io.BufferedReader;
@@ -15,5 +15,5 @@
 public abstract class Connection {
 
-	protected final static Logger LOGGER = Logger.getLogger(Connection.class);
+	protected final static Logger log = Logger.getLogger(Connection.class);
 
 	protected PrintWriter output = null;
@@ -28,5 +28,5 @@
 	protected int protocolVersion = -1;
 
-	protected final com.framsticks.util.Thread senderThread = new com.framsticks.util.Thread();
+	protected final com.framsticks.util.dispatching.Thread senderThread = new com.framsticks.util.dispatching.Thread();
 	protected Thread receiverThread;
 
@@ -40,6 +40,6 @@
 			connected = false;
 
-            senderThread.interrupt();
-            senderThread.join();
+			senderThread.interrupt();
+			senderThread.join();
 			if (receiverThread != null) {
 				receiverThread.interrupt();
@@ -64,7 +64,7 @@
 			}
 
-			LOGGER.info("connection closed");
+			log.info("connection closed");
 		} catch (Exception e) {
-			LOGGER.error(e);
+			log.error(e);
 		}
 
@@ -77,80 +77,80 @@
 
 
-    protected final Pair<Integer, String> parseRest(String rest) {
-        Matcher matcher = (requestIdEnabled ? requestIdEnabledPattern : requestIDisabledPattern).matcher(rest);
-        if (!matcher.matches()) {
-            LOGGER.fatal("unmatched first line of input: " + rest);
-            return null;
-        }
-        return new Pair<Integer, String>(requestIdEnabled ? Integer.parseInt(matcher.group(1)) : null, matcher.group(requestIdEnabled ? 2 : 1));
-    }
+	protected final Pair<Integer, String> parseRest(String rest) {
+		Matcher matcher = (requestIdEnabled ? requestIdEnabledPattern : requestIDisabledPattern).matcher(rest);
+		if (!matcher.matches()) {
+			log.fatal("unmatched first line of input: " + rest);
+			return null;
+		}
+		return new Pair<Integer, String>(requestIdEnabled ? Integer.parseInt(matcher.group(1)) : null, matcher.group(requestIdEnabled ? 2 : 1));
+	}
 
-    static final int BUFFER_LENGTH = 1024;
+	static final int BUFFER_LENGTH = 1024;
 
-    int readChars = 0;
-    int iterator = 0;
-    int bufferStart = 0;
-    char[] readBuffer = new char[BUFFER_LENGTH];
+	int readChars = 0;
+	int iterator = 0;
+	int bufferStart = 0;
+	char[] readBuffer = new char[BUFFER_LENGTH];
 
-    protected String getLine() throws Exception {
-        StringBuilder lineBuffer = new StringBuilder();
-        while (!Thread.interrupted()) {
-            while (iterator < readChars) {
-                if (readBuffer[iterator] != '\n') {
-                    ++iterator;
-                    continue;
-                }
-                lineBuffer.append(readBuffer, bufferStart, iterator - bufferStart + 1);
-                ++iterator;
-                bufferStart = iterator;
-                return lineBuffer.toString();
-            }
-            lineBuffer.append(readBuffer, bufferStart, readChars - bufferStart);
+	protected String getLine() throws Exception {
+		StringBuilder lineBuffer = new StringBuilder();
+		while (!Thread.interrupted()) {
+			while (iterator < readChars) {
+				if (readBuffer[iterator] != '\n') {
+					++iterator;
+					continue;
+				}
+				lineBuffer.append(readBuffer, bufferStart, iterator - bufferStart + 1);
+				++iterator;
+				bufferStart = iterator;
+				return lineBuffer.toString();
+			}
+			lineBuffer.append(readBuffer, bufferStart, readChars - bufferStart);
 
-            readChars = 0;
-            while (readChars == 0) {
-                try {
-                    readChars = input.read(readBuffer);
-                } catch (SocketTimeoutException ignored) {
-                    //timeout - continue
-                }
-            }
-            iterator = 0;
-            bufferStart = 0;
-        }
-        throw new InterruptedException();
-    }
+			readChars = 0;
+			while (readChars == 0) {
+				try {
+					readChars = input.read(readBuffer);
+				} catch (SocketTimeoutException ignored) {
+					//timeout - continue
+				}
+			}
+			iterator = 0;
+			bufferStart = 0;
+		}
+		throw new InterruptedException();
+	}
 
-    protected abstract void receiverThreadRoutine() throws Exception;
+	protected abstract void receiverThreadRoutine() throws Exception;
 
-    protected void runThreads() {
-        try {
-            output = new PrintWriter(socket.getOutputStream(), true);
-            input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
-        } catch (IOException e) {
-            LOGGER.error("buffer creation failure");
-            close();
-            return;
-        }
+	protected void runThreads() {
+		try {
+			output = new PrintWriter(socket.getOutputStream(), true);
+			input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
+		} catch (IOException e) {
+			log.error("buffer creation failure");
+			close();
+			return;
+		}
 
-        senderThread.setName(this + "-sender");
-        receiverThread = new Thread(new Runnable() {
-            @Override
-            public void run() {
-                try {
-                    receiverThreadRoutine();
-                } catch (InterruptedException ignored) {
-                    LOGGER.debug("receiver thread interrupted");
-                } catch (Exception e) {
-                    LOGGER.error("error: " + e);
-                    close();
-                }
-            }
-        });
-        receiverThread.setName(this + "-receiver");
+		senderThread.setName(this + "-sender");
+		receiverThread = new Thread(new Runnable() {
+			@Override
+			public void run() {
+				try {
+					receiverThreadRoutine();
+				} catch (InterruptedException ignored) {
+					log.debug("receiver thread interrupted");
+				} catch (Exception e) {
+					log.error("error: " + e);
+					close();
+				}
+			}
+		});
+		receiverThread.setName(this + "-receiver");
 
-        senderThread.start();
-        receiverThread.start();
-    }
+		senderThread.start();
+		receiverThread.start();
+	}
 
 
Index: java/main/src/main/java/com/framsticks/communication/EventCallback.java
===================================================================
--- java/main/src/main/java/com/framsticks/communication/EventCallback.java	(revision 79)
+++ java/main/src/main/java/com/framsticks/communication/EventCallback.java	(revision 84)
@@ -1,5 +1,3 @@
 package com.framsticks.communication;
-
-import com.framsticks.params.SourceInterface;
 
 import java.util.List;
Index: java/main/src/main/java/com/framsticks/communication/Request.java
===================================================================
--- java/main/src/main/java/com/framsticks/communication/Request.java	(revision 79)
+++ java/main/src/main/java/com/framsticks/communication/Request.java	(revision 84)
@@ -2,8 +2,4 @@
 
 import com.framsticks.communication.queries.*;
-
-import java.util.Collection;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
 
 /**
@@ -12,5 +8,5 @@
 public abstract class Request {
 
-    public static void quoteValue(StringBuilder builder, String value) {
+	public static void quoteValue(StringBuilder builder, String value) {
 		String quote = ((value.indexOf(' ') > 0) || (value.length() == 0) ? "\"" : "");
 		builder.append(quote).append(value).append(quote);
@@ -19,5 +15,5 @@
 	public abstract String getCommand();
 
-    protected abstract StringBuilder construct(StringBuilder buffer);
+	protected abstract StringBuilder construct(StringBuilder buffer);
 	//private static Pattern queryPattern = Pattern.compile("^(\\S+)\\s+(\\S+)(?:\\s+(\\S+))?$");
 
@@ -35,21 +31,21 @@
 			return new CallRequest();
 		}
-        if (type.equals("reg")) {
-            return new RegistrationRequest();
-        }
-        if (type.equals("use")) {
-            return new UseRequest();
-        }
-        if (type.equals("version")) {
-            return new VersionRequest();
-        }
-        return null;
+		if (type.equals("reg")) {
+			return new RegistrationRequest();
+		}
+		if (type.equals("use")) {
+			return new UseRequest();
+		}
+		if (type.equals("version")) {
+			return new VersionRequest();
+		}
+		return null;
 	}
 
-    public abstract void parseRest(String rest);
+	public abstract void parseRest(String rest);
 
-    @Override
-    public String toString() {
-        return construct(new StringBuilder().append(getCommand())).toString();
-    }
+	@Override
+	public String toString() {
+		return construct(new StringBuilder().append(getCommand())).toString();
+	}
 }
Index: java/main/src/main/java/com/framsticks/communication/ResponseCallback.java
===================================================================
--- java/main/src/main/java/com/framsticks/communication/ResponseCallback.java	(revision 79)
+++ java/main/src/main/java/com/framsticks/communication/ResponseCallback.java	(revision 84)
@@ -1,7 +1,3 @@
 package com.framsticks.communication;
-
-import com.framsticks.params.SourceInterface;
-
-import java.util.List;
 
 /**
Index: java/main/src/main/java/com/framsticks/communication/ServerConnection.java
===================================================================
--- java/main/src/main/java/com/framsticks/communication/ServerConnection.java	(revision 79)
+++ java/main/src/main/java/com/framsticks/communication/ServerConnection.java	(revision 84)
@@ -3,12 +3,8 @@
 import com.framsticks.communication.queries.*;
 import com.framsticks.params.SourceInterface;
-import com.framsticks.util.Pair;
-import com.framsticks.util.Strings;
+import com.framsticks.util.lang.Pair;
+import com.framsticks.util.lang.Strings;
 import org.apache.log4j.Logger;
 
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.PrintWriter;
 import java.net.Socket;
 
@@ -18,114 +14,114 @@
 public class ServerConnection extends Connection {
 
-    private final static Logger LOGGER = Logger.getLogger(ServerConnection.class);
+	private final static Logger log = Logger.getLogger(ServerConnection.class);
 
-    RequestHandler requestHandler;
+	RequestHandler requestHandler;
 
-    public ServerConnection(Socket socket, RequestHandler requestHandler) {
-        this.socket = socket;
-        this.requestHandler = requestHandler;
-        connected = true;
+	public ServerConnection(Socket socket, RequestHandler requestHandler) {
+		this.socket = socket;
+		this.requestHandler = requestHandler;
+		connected = true;
 
-    }
+	}
 
-    public void start() {
+	public void start() {
 
 
-        runThreads();
-    }
+		runThreads();
+	}
 
-    @Override
-    public String toString() {
-        return socket.getInetAddress().getHostAddress();
-    }
+	@Override
+	public String toString() {
+		return socket.getInetAddress().getHostAddress();
+	}
 
-    @Override
-    protected void receiverThreadRoutine() throws Exception {
-        while (connected) {
-            processNextRequest();
-        }
-    }
+	@Override
+	protected void receiverThreadRoutine() throws Exception {
+		while (connected) {
+			processNextRequest();
+		}
+	}
 
-    protected void handleRequest(Request request, ResponseCallback responseCallback) {
-        if (request instanceof ApplicationRequest) {
-            requestHandler.handle((ApplicationRequest)request, responseCallback);
-            return;
-        }
-        if (request instanceof ProtocolRequest) {
-            if (request instanceof VersionRequest) {
-                responseCallback.process(new Response(true, null, null));
-                return;
-            }
-            if (request instanceof UseRequest) {
-                String feature = ((UseRequest)request).getFeature();
-                if (feature.equals("request_id")) {
-                    requestIdEnabled = true;
-                    responseCallback.process(new Response(true, null, null));
-                    return;
-                }
-                responseCallback.process(new Response(false, "\"unknown feature: " + feature + "\"", null));
-                return;
-            }
+	protected void handleRequest(Request request, ResponseCallback responseCallback) {
+		if (request instanceof ApplicationRequest) {
+			requestHandler.handle((ApplicationRequest)request, responseCallback);
+			return;
+		}
+		if (request instanceof ProtocolRequest) {
+			if (request instanceof VersionRequest) {
+				responseCallback.process(new Response(true, null, null));
+				return;
+			}
+			if (request instanceof UseRequest) {
+				String feature = ((UseRequest)request).getFeature();
+				if (feature.equals("request_id")) {
+					requestIdEnabled = true;
+					responseCallback.process(new Response(true, null, null));
+					return;
+				}
+				responseCallback.process(new Response(false, "\"unknown feature: " + feature + "\"", null));
+				return;
+			}
 
-        }
-        LOGGER.error("unhandled request: " + request);
-        responseCallback.process(new Response(false, "unhandled", null));
-    }
+		}
+		log.error("unhandled request: " + request);
+		responseCallback.process(new Response(false, "unhandled", null));
+	}
 
-    protected final void respond(final Response response, final Integer id) {
-        senderThread.invokeLater(new Runnable() {
-            @Override
-            public void run() {
-                String outId = id != null ? " " + id : "";
-                if (response.getFiles() != null) {
-                    for (File f : response.getFiles()) {
-                        output.print("file" + outId/* + " " + f.getPath()*/ + "\n");
-                        SourceInterface content = f.getContent();
-                        String line;
-                        while ((line = content.readLine()) != null) {
-                            output.print(line);
-                            output.print('\n');
-                        }
-                        output.print("eof\n");
-                    }
-                }
-                output.print(response.getOk() ? "ok" : "error");
-                output.print(outId);
-                if (Strings.notEmpty(response.getComment())) {
-                    output.print(' ');
-                    output.print(response.getComment());
-                }
-                output.print('\n');
-                output.flush();
-            }
-        });
+	protected final void respond(final Response response, final Integer id) {
+		senderThread.invokeLater(new Runnable() {
+			@Override
+			public void run() {
+				String outId = id != null ? " " + id : "";
+				if (response.getFiles() != null) {
+					for (File f : response.getFiles()) {
+						output.print("file" + outId/* + " " + f.getPath()*/ + "\n");
+						SourceInterface content = f.getContent();
+						String line;
+						while ((line = content.readLine()) != null) {
+							output.print(line);
+							output.print('\n');
+						}
+						output.print("eof\n");
+					}
+				}
+				output.print(response.getOk() ? "ok" : "error");
+				output.print(outId);
+				if (Strings.notEmpty(response.getComment())) {
+					output.print(' ');
+					output.print(response.getComment());
+				}
+				output.print('\n');
+				output.flush();
+			}
+		});
 
-    }
+	}
 
-    protected void processNextRequest() throws Exception {
-        String line = getLine();
-        Pair<String, String> command = Strings.splitIntoPair(line, ' ', "\n");
-        final Pair<Integer, String> rest = parseRest(command.second);
-        if (rest == null) {
-            respond(new Response(false, "\"invalid input\"", null), null);
-            return;
-        }
+	protected void processNextRequest() throws Exception {
+		String line = getLine();
+		Pair<String, String> command = Strings.splitIntoPair(line, ' ', "\n");
+		final Pair<Integer, String> rest = parseRest(command.second);
+		if (rest == null) {
+			respond(new Response(false, "\"invalid input\"", null), null);
+			return;
+		}
 
-        final Request request = Request.createRequestByTypeString(command.first);
-        if (request == null) {
-            respond(new Response(false, "\"invalid input\"", null), null);
-            return;
-        }
-        request.parseRest(rest.second);
-        if (LOGGER.isTraceEnabled()) {
-            LOGGER.trace("read request: " + request);
-        }
+		final Request request = Request.createRequestByTypeString(command.first);
+		if (request == null) {
+			respond(new Response(false, "\"invalid input\"", null), null);
+			return;
+		}
+		request.parseRest(rest.second);
+		if (log.isTraceEnabled()) {
+			log.trace("read request: " + request);
+		}
 
-        handleRequest(request, new ResponseCallback() {
-            @Override
-            public void process(Response response) {
-                respond(response, rest.first);
-            }
-        });
-    }
+		handleRequest(request, new ResponseCallback() {
+			@Override
+			public void process(Response response) {
+				respond(response, rest.first);
+			}
+		});
+	}
 }
Index: java/main/src/main/java/com/framsticks/communication/Subscription.java
===================================================================
--- java/main/src/main/java/com/framsticks/communication/Subscription.java	(revision 79)
+++ java/main/src/main/java/com/framsticks/communication/Subscription.java	(revision 84)
@@ -2,6 +2,6 @@
 
 import com.framsticks.communication.queries.RegistrationRequest;
-import com.framsticks.util.AtOnceDispatcher;
-import com.framsticks.util.Dispatcher;
+import com.framsticks.util.dispatching.AtOnceDispatcher;
+import com.framsticks.util.dispatching.Dispatcher;
 import com.framsticks.util.StateFunctor;
 import org.apache.log4j.Logger;
@@ -13,5 +13,5 @@
 public class Subscription {
 
-    private final static Logger LOGGER = Logger.getLogger(Subscription.class);
+    private final static Logger log = Logger.getLogger(Subscription.class);
 
     private final ClientConnection connection;
@@ -51,10 +51,10 @@
             public void process(Response response) {
                 if (!response.getOk()) {
-                    LOGGER.error("failed to unsunscribe " + this + ": " + response.getComment());
+                    log.error("failed to unsunscribe " + this + ": " + response.getComment());
                     stateFunctor.call(new Exception(response.getComment()));
                     return;
                 }
                 assert response.hasFiles();
-                LOGGER.debug("unsunscribed " + this);
+                log.debug("unsunscribed " + this);
                 stateFunctor.call(null);
             }
Index: java/main/src/main/java/com/framsticks/communication/queries/ApplicationRequest.java
===================================================================
--- java/main/src/main/java/com/framsticks/communication/queries/ApplicationRequest.java	(revision 79)
+++ java/main/src/main/java/com/framsticks/communication/queries/ApplicationRequest.java	(revision 84)
@@ -2,4 +2,5 @@
 
 import com.framsticks.communication.Request;
+import com.framsticks.util.lang.Delimeted;
 
 import java.util.Collection;
@@ -10,51 +11,44 @@
 public abstract class ApplicationRequest extends Request {
 
-    protected String path;
-    protected String fields;
+	protected String path;
+	protected String fields;
 
-    public ApplicationRequest setPath(String path) {
-        assert path != null;
-        this.path = path;
-        return this;
-    }
+	public ApplicationRequest setPath(String path) {
+		assert path != null;
+		this.path = path;
+		return this;
+	}
 
-    public ApplicationRequest setField(String field) {
-        this.fields = field;
-        return this;
-    }
+	public ApplicationRequest setField(String field) {
+		this.fields = field;
+		return this;
+	}
 
-    public ApplicationRequest setFields(Collection<String> fields) {
-        StringBuilder fieldString = new StringBuilder();
-        boolean notFirst = false;
-        for (String field : fields) {
-            if (notFirst) {
-                fieldString.append(",");
-
-            } else {
-                notFirst = true;
-            }
-            fieldString.append(field);
-        }
-        return setField(fieldString.toString());
-    }
+	public ApplicationRequest setFields(Collection<String> fields) {
+		Delimeted d = new Delimeted(",", "");
+		for (String f : fields) {
+			d.append(f);
+		}
+		return setField(d.build());
+	}
 
 
-    public String getPath() {
-        return path;
-    }
+	public String getPath() {
+		return path;
+	}
 
-    @Override
-    protected StringBuilder construct(StringBuilder buffer) {
-        buffer.append(' ').append(path);
-        if (fields != null) {
-            buffer.append(' ').append(fields);
-        }
-        return buffer;
-    }
+	@Override
+	protected StringBuilder construct(StringBuilder buffer) {
+		buffer.append(' ').append(path);
+		if (fields != null) {
+			buffer.append(' ').append(fields);
+		}
+		return buffer;
+	}
 
-    @Override
-    public void parseRest(String rest) {
-        path = rest;
-    }
+	@Override
+	public void parseRest(String rest) {
+		path = rest;
+	}
 
 }
Index: java/main/src/main/java/com/framsticks/communication/queries/CallRequest.java
===================================================================
--- java/main/src/main/java/com/framsticks/communication/queries/CallRequest.java	(revision 79)
+++ java/main/src/main/java/com/framsticks/communication/queries/CallRequest.java	(revision 84)
@@ -9,7 +9,7 @@
  */
 public class CallRequest extends ApplicationRequest {
+
 	protected String arguments;
 	protected String method;
-
 
 	public CallRequest setArguments(String arguments) {
@@ -21,7 +21,6 @@
 		StringBuilder buffer = new StringBuilder();
 		for (String a : arguments) {
-			String arg = a.trim();
 			buffer.append(" ");
-			Request.quoteValue(buffer, arg);
+			Request.quoteValue(buffer, a.trim());
 		}
 		return this.setArguments(buffer.toString());
@@ -42,5 +41,5 @@
 			buffer.append(arguments);
 		}
-        return buffer;
+		return buffer;
 	}
 
Index: java/main/src/main/java/com/framsticks/communication/queries/GetRequest.java
===================================================================
--- java/main/src/main/java/com/framsticks/communication/queries/GetRequest.java	(revision 79)
+++ java/main/src/main/java/com/framsticks/communication/queries/GetRequest.java	(revision 84)
@@ -1,5 +1,3 @@
 package com.framsticks.communication.queries;
-
-import com.framsticks.communication.Request;
 
 /**
Index: java/main/src/main/java/com/framsticks/communication/queries/InfoRequest.java
===================================================================
--- java/main/src/main/java/com/framsticks/communication/queries/InfoRequest.java	(revision 79)
+++ java/main/src/main/java/com/framsticks/communication/queries/InfoRequest.java	(revision 84)
@@ -1,5 +1,3 @@
 package com.framsticks.communication.queries;
-
-import com.framsticks.communication.Request;
 
 /**
Index: java/main/src/main/java/com/framsticks/communication/queries/RegistrationRequest.java
===================================================================
--- java/main/src/main/java/com/framsticks/communication/queries/RegistrationRequest.java	(revision 79)
+++ java/main/src/main/java/com/framsticks/communication/queries/RegistrationRequest.java	(revision 84)
@@ -1,5 +1,3 @@
 package com.framsticks.communication.queries;
-
-import com.framsticks.communication.Request;
 
 /**
@@ -17,11 +15,11 @@
 	}
 
-    @Override
+	@Override
 	protected StringBuilder construct(StringBuilder buffer) {
-        super.construct(buffer);
+		super.construct(buffer);
 		if (!register) {
 			buffer.append(" remove");
 		}
-        return buffer;
+		return buffer;
 	}
 
Index: java/main/src/main/java/com/framsticks/communication/queries/SetRequest.java
===================================================================
--- java/main/src/main/java/com/framsticks/communication/queries/SetRequest.java	(revision 79)
+++ java/main/src/main/java/com/framsticks/communication/queries/SetRequest.java	(revision 84)
@@ -1,5 +1,3 @@
 package com.framsticks.communication.queries;
-
-import com.framsticks.communication.Request;
 
 /**
@@ -23,5 +21,5 @@
 			buffer.append(" \"").append(value).append("\"");
 		}
-        return buffer;
+		return buffer;
 	}
 	@Override
Index: java/main/src/main/java/com/framsticks/communication/queries/UseRequest.java
===================================================================
--- java/main/src/main/java/com/framsticks/communication/queries/UseRequest.java	(revision 79)
+++ java/main/src/main/java/com/framsticks/communication/queries/UseRequest.java	(revision 84)
@@ -1,5 +1,3 @@
 package com.framsticks.communication.queries;
-
-import com.framsticks.communication.Request;
 
 /**
@@ -14,21 +12,21 @@
 	}
 
-    @Override
+	@Override
 	public String getCommand() {
 		return "use";
 	}
 
-    @Override
+	@Override
 	protected StringBuilder construct(StringBuilder buffer) {
 		return buffer.append(' ').append(feature);
 	}
 
-    @Override
-    public void parseRest(String rest) {
-        feature = rest;
-    }
+	@Override
+	public void parseRest(String rest) {
+		feature = rest;
+	}
 
-    public final String getFeature() {
-        return feature;
-    }
+	public final String getFeature() {
+		return feature;
+	}
 }
Index: java/main/src/main/java/com/framsticks/communication/queries/VersionRequest.java
===================================================================
--- java/main/src/main/java/com/framsticks/communication/queries/VersionRequest.java	(revision 79)
+++ java/main/src/main/java/com/framsticks/communication/queries/VersionRequest.java	(revision 84)
@@ -1,7 +1,5 @@
 package com.framsticks.communication.queries;
 
-import com.framsticks.communication.Request;
-import com.framsticks.util.Numbers;
-import com.sun.j3d.loaders.ParsingErrorException;
+import com.framsticks.util.lang.Numbers;
 
 /**
@@ -19,16 +17,16 @@
 	}
 
-    @Override
+	@Override
 	public String getCommand() {
 		return "version";
 	}
 
-    @Override
-    public void parseRest(String rest) {
-        version = Numbers.parse(rest, Integer.class);
-    }
+	@Override
+	public void parseRest(String rest) {
+		version = Numbers.parse(rest, Integer.class);
+	}
 
-    @Override
-    protected StringBuilder construct(StringBuilder buffer) {
+	@Override
+	protected StringBuilder construct(StringBuilder buffer) {
 		return buffer.append(' ').append(version);
 	}
Index: java/main/src/main/java/com/framsticks/communication/util/LoggingStateCallback.java
===================================================================
--- java/main/src/main/java/com/framsticks/communication/util/LoggingStateCallback.java	(revision 79)
+++ java/main/src/main/java/com/framsticks/communication/util/LoggingStateCallback.java	(revision 84)
@@ -3,5 +3,4 @@
 import com.framsticks.communication.StateCallback;
 import org.apache.log4j.Logger;
-import org.apache.log4j.Priority;
 
 /**
Index: java/main/src/main/java/com/framsticks/core/Entity.java
===================================================================
--- java/main/src/main/java/com/framsticks/core/Entity.java	(revision 79)
+++ java/main/src/main/java/com/framsticks/core/Entity.java	(revision 84)
@@ -1,6 +1,9 @@
 package com.framsticks.core;
 
-import com.framsticks.util.*;
-import com.framsticks.util.Thread;
+import com.framsticks.params.FramsClass;
+import com.framsticks.util.dispatching.Thread;
+import com.framsticks.util.dispatching.Dispatcher;
+
+import org.apache.commons.configuration.Configuration;
 import org.apache.log4j.Logger;
 
@@ -8,53 +11,93 @@
  * @author Piotr Sniegowski
  */
-public abstract class Entity extends Parameters implements Dispatcher {
+public abstract class Entity implements Dispatcher {
 
-    private final static Logger LOGGER = Logger.getLogger(Entity.class.getName());
+	private final static Logger log = Logger.getLogger(Entity.class.getName());
 
-    public Entity(Parameters parameters) {
-        super(parameters);
-        if (dispatcher == null) {
-            dispatcher = new Thread(name);
-        }
-    }
+	protected String name = "entity";
+	protected EntityOwner owner;
+	protected Dispatcher dispatcher;
 
-    @Override
-    public final boolean isActive() {
-        return dispatcher.isActive();
-    }
+	public Entity() {
+	}
 
-    @Override
-    public final void invokeLater(Runnable runnable) {
-        dispatcher.invokeLater(runnable);
-    }
+	public final String getName() {
+		return name;
+	}
 
-    protected void run() {
-        assert isActive();
-        LOGGER.info("running: " + this);
-    }
+	/**
+	 * @param name the name to set
+	 */
+	public final void setName(String name) {
+		this.name = name;
+		if (dispatcher instanceof Thread) {
+			((Thread) dispatcher).setName(name);
+		}
+	}
 
-    public final void configurePublic() throws Exception {
-        configure();
-    }
+	/**
+	 * @return the owner
+	 */
+	public EntityOwner getOwner() {
+		return owner;
+	}
 
-    protected void configure() throws Exception {
+	/**
+	 * @param owner the owner to set
+	 */
+	public void setOwner(EntityOwner owner) {
+		this.owner = owner;
+	}
 
-    }
+	@Override
+	public final boolean isActive() {
+		return dispatcher == null || dispatcher.isActive();
+	}
 
-    public Dispatcher getDispatcher() {
-        return dispatcher;
-    }
+	@Override
+	public final void invokeLater(Runnable runnable) {
+		assert dispatcher != null;
+		dispatcher.invokeLater(runnable);
+	}
 
-    public final void start() {
-        invokeLater(new Runnable() {
-            @Override
-            public void run() {
-                Entity.this.run();
-            }
-        });
-    }
+	public Dispatcher createDefaultDispatcher() {
+		return new Thread(name);
+	}
+
+	protected void run() {
+		assert isActive();
+		log.info("running: " + this);
+	}
+
+
+	public void configure(Configuration config) {
+	}
+
+	public Dispatcher getDispatcher() {
+		return dispatcher;
+	}
+
+	/**
+	 * @param dispatcher the dispatcher to set
+	 */
+	public void setDispatcher(Dispatcher dispatcher) {
+		this.dispatcher = dispatcher;
+	}
+
+	public final void start() {
+		if (dispatcher == null) {
+			log.debug("no dispatcher set for " + this + ", creating default one");
+			setDispatcher(createDefaultDispatcher());
+		}
+		invokeLater(new Runnable() {
+			@Override
+			public void run() {
+				Entity.this.run();
+			}
+		});
+	}
 
 	public final void done() {
-		LOGGER.info("stopping entity");
+		log.info("stopping entity");
 		if (owner != null) {
 			owner.onDone();
@@ -62,4 +105,6 @@
 	}
 
-
+	public static void constructFramsClass(FramsClass.Constructor constructor) {
+		constructor.method("getName");
+	}
 }
Index: java/main/src/main/java/com/framsticks/core/Instance.java
===================================================================
--- java/main/src/main/java/com/framsticks/core/Instance.java	(revision 79)
+++ java/main/src/main/java/com/framsticks/core/Instance.java	(revision 84)
@@ -3,5 +3,4 @@
 import com.framsticks.communication.*;
 import com.framsticks.params.*;
-import com.framsticks.params.types.CompositeParam;
 import com.framsticks.params.types.ObjectParam;
 import com.framsticks.parsers.Loaders;
@@ -9,4 +8,7 @@
 import com.framsticks.util.*;
 import com.framsticks.util.UnsupportedOperationException;
+import com.framsticks.util.dispatching.Dispatching;
+import com.framsticks.util.dispatching.Future;
+import com.framsticks.util.lang.Casting;
 import org.apache.log4j.Logger;
 
@@ -18,28 +20,22 @@
 public abstract class Instance extends Entity {
 
-	private static final Logger LOGGER = Logger.getLogger(Instance.class.getName());
-
-
-    protected Node root;
-
-    public Set<InstanceListener> listeners = new HashSet<InstanceListener>();
-
-    public Instance(Parameters parameters) {
-        super(parameters);
-        root = new Node((CompositeParam)new ParamBuilder().setName("Instance").setId(name).setType("o").build(), null);
-	}
-
-    @Override
-    protected void run() {
-        super.run();
+	private static final Logger log = Logger.getLogger(Instance.class.getName());
+
+
+	protected Node root;
+
+	public Set<InstanceListener> listeners = new HashSet<InstanceListener>();
+
+	public Instance() {
+	}
+
+	@Override
+	protected void run() {
+		super.run();
+		root = new Node((CompositeParam)new ParamBuilder().setName("Instance").setId(name).setType("o").build(), null);
 		com.framsticks.model.Package.register(registry);
-    }
-
-    @Override
-    protected void configure() throws Exception {
-        super.configure();
-    }
-
-    protected void fetchInfo(Path path, Future<FramsClass> future) {
+	}
+
+	protected void fetchInfo(Path path, Future<FramsClass> future) {
 		future.result(null, new UnsupportedOperationException());
 	}
@@ -61,13 +57,13 @@
 	}
 
-    public void fetchValue(Path path, Param param, StateFunctor stateFunctor) {
+	public void fetchValue(Path path, Param param, StateFunctor stateFunctor) {
 		stateFunctor.call(null);
 	}
 
-    public void fetchValues(Path path, StateFunctor stateFunctor) {
+	public void fetchValues(Path path, StateFunctor stateFunctor) {
 		stateFunctor.call(null);
 	}
 
-    protected void tryRegisterOnChangeEvents(Path path) {
+	protected void tryRegisterOnChangeEvents(Path path) {
 
 	}
@@ -83,52 +79,59 @@
 	}
 
-    protected void fireRun(Exception e) {
-        for (InstanceListener l : this.listeners) {
-            l.onRun(e);
-        }
-    }
-
-    protected void fireStop(Exception e) {
-        for (InstanceListener l : this.listeners) {
-            l.onStop(e);
-        }
-    }
-
-    public void addListener(final InstanceListener listener) {
-        assert Dispatching.isThreadSafe();
-        Dispatching.invokeLaterOrNow(this, new Runnable() {
-            @Override
-            public void run() {
-                listeners.add(listener);
-            }
-        });
-    }
-
-    public void removeListener(final InstanceListener listener) {
-        assert Dispatching.isThreadSafe();
-        Dispatching.invokeLaterOrNow(this, new Runnable() {
-            @Override
-            public void run() {
-                listeners.remove(listener);
-            }
-        });
-    }
-
-
-    protected void fireListChange(Path path, ListChange change) {
-        assert isActive();
-        for (InstanceListener l : this.listeners) {
+	protected void fireRun(Exception e) {
+		for (InstanceListener l : this.listeners) {
+			l.onRun(e);
+		}
+	}
+
+	protected void fireStop(Exception e) {
+		for (InstanceListener l : this.listeners) {
+			l.onStop(e);
+		}
+	}
+
+	public void addListener(final InstanceListener listener) {
+		assert Dispatching.isThreadSafe();
+		Dispatching.invokeLaterOrNow(this, new Runnable() {
+			@Override
+			public void run() {
+				listeners.add(listener);
+			}
+		});
+	}
+
+	public void removeListener(final InstanceListener listener) {
+		assert Dispatching.isThreadSafe();
+		Dispatching.invokeLaterOrNow(this, new Runnable() {
+			@Override
+			public void run() {
+				listeners.remove(listener);
+			}
+		});
+	}
+
+
+	protected void fireListChange(Path path, ListChange change) {
+		assert isActive();
+		for (InstanceListener l : this.listeners) {
 			l.onListChange(path, change);
 		}
 	}
 
-
-    public final FramsClass getInfoFromCache(Path path) {
-        return getInfoFromCache(path.getTop().getParam().getContainedTypeName());
-    }
-
-
-    public FramsClass getInfoFromCache(String id) {
-        assert isActive();
+	protected void fireFetch(Path path) {
+		assert isActive();
+		for (InstanceListener l : this.listeners) {
+			l.onFetch(path);
+		}
+	}
+
+
+	public final FramsClass getInfoFromCache(Path path) {
+		return getInfoFromCache(path.getTop().getParam().getContainedTypeName());
+	}
+
+
+	public FramsClass getInfoFromCache(String id) {
+		assert isActive();
 		return registry.getInfoFromCache(id);
 	}
@@ -137,211 +140,213 @@
 
 	public AccessInterface createAccess(String name) {
-        assert isActive();
-        if (name == null) {
+		assert isActive();
+		return registry.createAccess(name);
+	}
+
+
+	// TODO: make ValueParam
+	public <T> T get(Node node, Param childParam, Class<T> type) {
+		return bindAccess(node).get((ValueParam) childParam, type);
+	}
+
+	public void findInfo(final Path path, final Future<FramsClass> future) {
+		assert isActive();
+		final String name = path.getTop().getParam().getContainedTypeName();
+		final FramsClass framsClass = getInfoFromCache(name);
+		if (framsClass != null) {
+			log.trace("info for " + name + " found in cache");
+			future.result(framsClass, null);
+			return;
+		}
+		fetchInfo(path, future);
+	}
+
+	public final AccessInterface bindAccess(Node node) {
+		assert node.getObject() != null;
+		AccessInterface access = registry.prepareAccess(node.getParam());
+		if (access == null) {
+			log.error("missing access for: " + node.getParam());
 			return null;
 		}
-		FramsClass framsClass = getInfoFromCache(name);
-		if (framsClass == null) {
-			return null;
-		}
-
-		return registry.createAccess(name, framsClass);
-	}
-
-	public static AccessInterface wrapAccessWithListIfNeeded(CompositeParam param, AccessInterface access) {
-        if (access == null) {
-			return null;
-		}
-        return param.prepareAccessInterface(access);
-	}
-
-    public AccessInterface prepareAccess(CompositeParam param) {
-        return wrapAccessWithListIfNeeded(param, createAccess(param.getContainedTypeName()));
-    }
-
-    public <T> T get(Node node, Param childParam, Class<T> type) {
-        return bindAccess(node).get(childParam, type);
-    }
-
-    public void findInfo(final Path path, final Future<FramsClass> future) {
-        assert isActive();
-        final String name = path.getTop().getParam().getContainedTypeName();
-        final FramsClass framsClass = getInfoFromCache(name);
-        if (framsClass != null) {
-            LOGGER.trace("info for " + name + " found in cache");
-            future.result(framsClass, null);
-            return;
-        }
-        fetchInfo(path, future);
-    }
-
-    public final AccessInterface bindAccess(Node node) {
-        assert node.getObject() != null;
-        AccessInterface access = prepareAccess(node.getParam());
-        if (access == null) {
-			LOGGER.error("missing access for: " + node.getParam());
-            return null;
-        }
-        access.select(node.getObject());
-        return access;
-    }
-
-    public final <T> T getParam(Path path, String id, Class<T> type) {
-        return Casting.tryCast(type, prepareAccess(path.getTop().getParam()).getParam(id));
-    }
-
-    public final AccessInterface bindAccess(Path path) {
-        assert path.isResolved();
-        return bindAccess(path.getTop());
-    }
-
-    public void resolve(final String targetPath, final Future<Path> future) {
-        assert isActive();
-        final Path path = new Path(this, targetPath);
-        resolve(path, new Future<Path>() {
-            @Override
-            public void result(Path result, Exception e) {
-                assert isActive();
-                if (e != null) {
-                    future.result(path, e);
-                    return;
-                }
-                if (path.isResolved(targetPath)) {
-                    future.result(path, null);
-                    return;
-                }
-                if (path.isResolved()) {
-                    future.result(path, new Exception("testing"));
-                    return;
-                }
-                resolve(targetPath, future);
-            }
-        });
-    }
-
-    public void resolveAndFetch(final String targetPath, final Future<Path> future) {
-        assert isActive();
-        resolve(targetPath, new Future<Path>() {
-            @Override
-            public void result(final Path path, Exception e) {
-                if (e != null) {
-                    future.result(path, e);
-                    return;
-                }
-                assert path.isResolved(targetPath);
-                fetchValues(path, new StateFunctor() {
-                    @Override
-                    public void call(Exception e) {
-                        future.result(path, e);
-                    }
-                });
-            }
-        });
-    }
-
-    public Path createIfNeeded(String path) {
-        Path p;
-        while (!(p = new Path(this, path)).isResolved(path)) {
-            create(p);
-        }
-        return p;
-    }
-
-    public Path create(Path path) {
-        assert isActive();
-        assert !path.isResolved();
-        Path resolved = path.findResolution();
-        if (!resolved.isResolved()) {
-            LOGGER.debug("creating: " + path);
-            AccessInterface access = prepareAccess(path.getTop().getParam());
-            assert access != null;
-            Object child = access.createAccessee();
-            assert child != null;
-            if (path.size() == 1) {
-                root = new Node(root.getParam(), child);
-            } else {
-                bindAccess(path.getUnder()).set(path.getTop().getParam(), child);
-            }
-            resolved = path.appendResolution(child);
-        }
-        tryRegisterOnChangeEvents(resolved);
-        return resolved;
-    }
-
-
-
-
-    public FramsClass processFetchedInfo(File file) {
-        assert isActive();
-        FramsClass framsClass = Loaders.loadFramsClass(file.getContent());
-        if ("/".equals(file.getPath())) {
-            if (root.getParam().getContainedTypeName() == null) {
-                root = new Node((CompositeParam)new ParamBuilder().setName("Instance").setId(name).setType("o " + framsClass.getId()).build(), root.getObject());
-            }
-        }
-        registry.putInfoIntoCache(framsClass);
-        return framsClass;
-    }
-
-    public void processFetchedValues(Path path, List<File> files) {
-        assert isActive();
-        assert files.size() == 1;
-        assert path.isTheSame(files.get(0).getPath());
-        Node node = path.getTop();
-        MultiParamLoader loader = new MultiParamLoader();
-        loader.setNewSource(files.get(0).getContent());
-        loader.addBreakCondition(MultiParamLoader.Status.AfterObject);
-
-        try {
-            if (node.getParam() instanceof ObjectParam) {
-                loader.addAccessInterface(bindAccess(node));
-                loader.go();
-    //            for (NodeListener l : listeners) {
-    //                l.onChange(this);
-    //            }
-                return;
-            }
-
-            ListAccess listAccess = ((ListAccess)bindAccess(node));
-            assert listAccess != null;
-            listAccess.clearValues();
-
-            AccessInterface elementAccess = listAccess.getElementAccess();
-            loader.addAccessInterface(elementAccess);
-            MultiParamLoader.Status status;
-            while ((status = loader.go()) != MultiParamLoader.Status.Finished) {
-                if (status == MultiParamLoader.Status.AfterObject) {
-                    AccessInterface accessInterface = loader.getLastAccessInterface();
-
-                    String id = listAccess.computeIdentifierFor(accessInterface.getSelected());
-                    Param param = new ParamBuilder().setType("o " + accessInterface.getId()).setId(id).build();
-                    Object child = accessInterface.getSelected();
-                    accessInterface.select(null);
-                    assert child != null;
-                    bindAccess(node).set(param, child);
-                }
-            }
-    //        for (NodeListener l : listeners) {
-    //            l.onChange(this);
-    //        }
-        } catch (Exception e) {
-            LOGGER.error("exception occurred while loading: " + e);
-        }
-
-    }
-
-    public static Iterator<String> splitPath(String path) {
-        List<String> list = new LinkedList<String>();
-        for (String s : path.split("/")) {
-            if (!s.isEmpty()) {
-                list.add(s);
-            }
-        }
-        return list.iterator();
-    }
+		access.select(node.getObject());
+		return access;
+	}
+
+	public final <T> T getParam(Path path, String id, Class<T> type) {
+		return Casting.tryCast(type, registry.prepareAccess(path.getTop().getParam()).getParam(id));
+	}
+
+	public final AccessInterface bindAccess(Path path) {
+		assert path.isResolved();
+		return bindAccess(path.getTop());
+	}
+
+	public void resolve(final String targetPath, final Future<Path> future) {
+		assert isActive();
+		final Path path = getPath(targetPath);
+		resolve(path, new Future<Path>() {
+			@Override
+			public void result(Path result, Exception e) {
+				assert isActive();
+				if (e != null) {
+					future.result(path, e);
+					return;
+				}
+				if (path.isResolved(targetPath)) {
+					future.result(path, null);
+					return;
+				}
+				if (path.isResolved()) {
+					future.result(path, new Exception("testing"));
+					return;
+				}
+				resolve(targetPath, future);
+			}
+		});
+	}
+
+	public void resolveAndFetch(final String targetPath, final Future<Path> future) {
+		assert isActive();
+		resolve(targetPath, new Future<Path>() {
+			@Override
+			public void result(final Path path, Exception e) {
+				if (e != null) {
+					future.result(path, e);
+					return;
+				}
+				assert path.isResolved(targetPath);
+				fetchValues(path, new StateFunctor() {
+					@Override
+					public void call(Exception e) {
+						future.result(path, e);
+					}
+				});
+			}
+		});
+	}
+
+	public Path createIfNeeded(String path) {
+		Path p;
+		while (!(p = getPath(path)).isResolved(path)) {
+			create(p);
+		}
+		return p;
+	}
+
+	public Path createIfNeeded(Path path) {
+		assert isActive();
+		if (path.isResolved()) {
+			return path;
+		}
+		return create(path);
+	}
+
+	public Path create(Path path) {
+		assert isActive();
+		assert !path.isResolved();
+		Path resolved = path.tryFindResolution();
+		if (!resolved.isResolved()) {
+			log.debug("creating: " + path);
+			AccessInterface access = registry.prepareAccess(path.getTop().getParam());
+			assert access != null;
+			Object child = access.createAccessee();
+			assert child != null;
+			if (path.size() == 1) {
+				root = new Node(root.getParam(), child);
+			} else {
+				bindAccess(path.getUnder()).set(path.getTop().getParam(), child);
+			}
+			resolved = path.appendResolution(child);
+		}
+		tryRegisterOnChangeEvents(resolved);
+		return resolved;
+	}
+
+
+
+
+	public FramsClass processFetchedInfo(File file) {
+		assert isActive();
+		FramsClass framsClass = Loaders.loadFramsClass(file.getContent());
+		if ("/".equals(file.getPath())) {
+			if (root.getParam().getContainedTypeName() == null) {
+				root = new Node((CompositeParam)new ParamBuilder().setName("Instance").setId(name).setType("o " + framsClass.getId()).build(), root.getObject());
+			}
+		}
+		registry.putInfoIntoCache(framsClass);
+		return framsClass;
+	}
+
+	public void processFetchedValues(Path path, List<File> files) {
+		assert isActive();
+		assert files.size() == 1;
+		assert path.isTheSame(files.get(0).getPath());
+		Node node = path.getTop();
+		MultiParamLoader loader = new MultiParamLoader();
+		loader.setNewSource(files.get(0).getContent());
+		loader.addBreakCondition(MultiParamLoader.Status.AfterObject);
+
+		try {
+			if (node.getParam() instanceof ObjectParam) {
+				loader.addAccessInterface(bindAccess(node));
+				loader.go();
+				fireFetch(path);
+	//            for (NodeListener l : listeners) {
+	//                l.onChange(this);
+	//            }
+				return;
+			}
+
+			ListAccess listAccess = ((ListAccess)bindAccess(node));
+			assert listAccess != null;
+			listAccess.clearValues();
+
+			AccessInterface elementAccess = listAccess.getElementAccess();
+			loader.addAccessInterface(elementAccess);
+			MultiParamLoader.Status status;
+			while ((status = loader.go()) != MultiParamLoader.Status.Finished) {
+				if (status == MultiParamLoader.Status.AfterObject) {
+					AccessInterface accessInterface = loader.getLastAccessInterface();
+
+					String id = listAccess.computeIdentifierFor(accessInterface.getSelected());
+					Param param = new ParamBuilder().setType("o " + accessInterface.getId()).setId(id).build();
+					Object child = accessInterface.getSelected();
+					accessInterface.select(null);
+					assert child != null;
+					bindAccess(node).set((ValueParam) param, child);
+				}
+			}
+
+			fireFetch(path);
+	//        for (NodeListener l : listeners) {
+	//            l.onChange(this);
+	//        }
+		} catch (Exception e) {
+			log.error("exception occurred while loading: " + e);
+		}
+
+	}
+
+	public static Iterator<String> splitPath(String path) {
+		List<String> list = new LinkedList<String>();
+		for (String s : path.split("/")) {
+			if (!s.isEmpty()) {
+				list.add(s);
+			}
+		}
+		return list.iterator();
+	}
 
 	public Registry getRegistry() {
 		return registry;
 	}
+
+	public Path getPath(String textual) {
+		return new Path(this, textual);
+	}
+
+	public Path getRootPath() {
+		return getPath("/");
+	}
 }
 
Index: java/main/src/main/java/com/framsticks/core/InstanceListener.java
===================================================================
--- java/main/src/main/java/com/framsticks/core/InstanceListener.java	(revision 79)
+++ java/main/src/main/java/com/framsticks/core/InstanceListener.java	(revision 84)
@@ -5,6 +5,7 @@
  */
 public interface InstanceListener {
-    public void onListChange(Path path, ListChange change);
-    public void onRun(Exception e);
-    public void onStop(Exception e);
+	public void onListChange(Path path, ListChange change);
+	public void onFetch(Path path);
+	public void onRun(Exception e);
+	public void onStop(Exception e);
 }
Index: java/main/src/main/java/com/framsticks/core/ListChange.java
===================================================================
--- java/main/src/main/java/com/framsticks/core/ListChange.java	(revision 79)
+++ java/main/src/main/java/com/framsticks/core/ListChange.java	(revision 84)
@@ -2,12 +2,10 @@
 
 import com.framsticks.params.FramsClass;
-import com.framsticks.params.ListSource;
 import com.framsticks.params.ParamBuilder;
 import com.framsticks.params.types.DecimalParam;
 import com.framsticks.params.types.EnumParam;
 import com.framsticks.params.types.StringParam;
-import com.framsticks.util.Strings;
+import com.framsticks.util.lang.Strings;
 
-import java.util.ArrayList;
 import java.util.Arrays;
 
@@ -17,28 +15,28 @@
 public class ListChange {
 
-    public Action getAction() {
-        return action;
-    }
+	public Action getAction() {
+		return action;
+	}
 
-    public Integer getPosition() {
-        return position;
-    }
+	public Integer getPosition() {
+		return position;
+	}
 
-    public String getIdentifier() {
-        return identifier;
-    }
+	public String getIdentifier() {
+		return identifier;
+	}
 
-    public static enum Action {
-        Add,
-        Remove,
-        Modify
-    }
+	public static enum Action {
+		Add,
+		Remove,
+		Modify
+	}
 
-    private Action action;
-    private Integer position;
-    private String identifier;
+	private Action action;
+	private Integer position;
+	private String identifier;
 
-    public Integer getType() { return action.ordinal(); }
-    public void setType(Integer type) { action = Action.values()[type]; }
+	public Integer getType() { return action.ordinal(); }
+	public void setType(Integer type) { action = Action.values()[type]; }
 
 	public Integer getPos() { return position; }
@@ -48,26 +46,21 @@
 	public void setId(String id) { identifier = id; }
 
-    public String getBestIdentifier() {
-        if (Strings.notEmpty(identifier)) {
-            return identifier;
-        }
-        return position.toString();
-    }
+	public String getBestIdentifier() {
+		if (Strings.notEmpty(identifier)) {
+			return identifier;
+		}
+		return position.toString();
+	}
 
-    public static FramsClass getFramsClass() {
+	public static FramsClass getFramsClass() {
+		return new FramsClass("ListChange", "ListChange", null)
+				.append(new ParamBuilder().setId("type").setName("type").setType(new EnumParam(Arrays.asList("Add", "Remove", "Modify"))).build())
+				.append(new ParamBuilder().setId("id").setName("identifier").setType(StringParam.class).build())
+				.append(new ParamBuilder().setId("pos").setName("position").setType(DecimalParam.class).build());
+	}
 
-        ArrayList<String> actions = new ArrayList<String>();
-        actions.add("Add");
-        actions.add("Remove");
-        actions.add("Modify");
-        return new FramsClass("ListChange", "ListChange", null)
-                .append(new ParamBuilder().setId("type").setName("type").setType(new EnumParam(actions)).build())
-                .append(new ParamBuilder().setId("id").setName("identifier").setType(StringParam.class).build())
-                .append(new ParamBuilder().setId("pos").setName("position").setType(DecimalParam.class).build());
-    }
-
-    @Override
-    public String toString() {
-        return action + " " + identifier + " " + position;
-    }
+	@Override
+	public String toString() {
+		return action + " " + identifier + " " + position;
+	}
 }
Index: java/main/src/main/java/com/framsticks/core/LocalInstance.java
===================================================================
--- java/main/src/main/java/com/framsticks/core/LocalInstance.java	(revision 79)
+++ java/main/src/main/java/com/framsticks/core/LocalInstance.java	(revision 84)
@@ -2,8 +2,7 @@
 
 import com.framsticks.hosting.InstanceClient;
-import com.framsticks.params.AccessInterface;
-import com.framsticks.params.Param;
-import com.framsticks.util.*;
-import com.framsticks.util.Thread;
+import com.framsticks.util.dispatching.Thread;
+
+import org.apache.commons.configuration.Configuration;
 import org.apache.log4j.Logger;
 
@@ -21,79 +20,72 @@
 public abstract class LocalInstance extends Instance {
 
-    private static final Logger LOGGER = Logger.getLogger(LocalInstance.class.getName());
+	private static final Logger log = Logger.getLogger(LocalInstance.class.getName());
 
-    public LocalInstance(Parameters parameters) {
-        super(parameters);
+	public LocalInstance() {
 
-        Integer accept = config.getInteger("accept", null);
-        if (accept != null) {
-            try {
-                acceptSocket = new ServerSocket();
-                acceptSocket.setReuseAddress(true);
-                acceptThread = new Thread(name + "-accept");
-                tryBind(accept);
-            } catch (IOException e) {
-                LOGGER.fatal("failed to create accept socket: " + e);
-            }
-        }
-    }
+	}
 
-    @Override
-    protected void run() {
-        super.run();
-    }
+	@Override
+	public void configure(Configuration config) {
+		Integer accept = config.getInteger("accept", null);
+		if (accept != null) {
+			try {
+				acceptSocket = new ServerSocket();
+				acceptSocket.setReuseAddress(true);
+				acceptThread = new Thread(name + "-accept");
+				tryBind(accept);
+			} catch (IOException e) {
+				log.fatal("failed to create accept socket: " + e);
+			}
+		}
+	}
 
-    @Override
-    protected void configure() throws Exception {
-        super.configure();
-    }
+	protected final Set<InstanceClient> clients = new HashSet<InstanceClient>();
+	ServerSocket acceptSocket;
+	Thread acceptThread;
 
-    protected final Set<InstanceClient> clients = new HashSet<InstanceClient>();
-    ServerSocket acceptSocket;
-    Thread acceptThread;
+	protected void acceptNext() {
+		acceptThread.invokeLater(new Runnable() {
+			@Override
+			public void run() {
+				try {
+					final Socket socket = acceptSocket.accept();
+					assert socket != null;
+					log.debug("accepted socket: " + socket.getInetAddress().getHostAddress());
+					invokeLater(new Runnable() {
+						@Override
+						public void run() {
+							InstanceClient client = new InstanceClient(LocalInstance.this, socket);
+							clients.add(client);
+							log.info("client connected: " + client);
+						}
+					});
+				} catch (IOException e) {
+					log.error("failed to accept socket: " + e);
+				}
+				acceptNext();
+			}
+		});
+	}
 
-    protected void acceptNext() {
-        acceptThread.invokeLater(new Runnable() {
-            @Override
-            public void run() {
-                try {
-                    final Socket socket = acceptSocket.accept();
-                    assert socket != null;
-                    LOGGER.debug("accepted socket: " + socket.getInetAddress().getHostAddress());
-                    invokeLater(new Runnable() {
-                        @Override
-                        public void run() {
-                            InstanceClient client = new InstanceClient(LocalInstance.this, socket);
-                            clients.add(client);
-                            LOGGER.info("client connected: " + client);
-                        }
-                    });
-                } catch (IOException e) {
-                    LOGGER.error("failed to accept socket: " + e);
-                }
-                acceptNext();
-            }
-        });
-    }
-
-    public void tryBind(final Integer accept) {
-        acceptThread.invokeLater(new Runnable() {
-            @Override
-            public void run() {
-                try {
-                    acceptSocket.bind(new InetSocketAddress(accept));
-                    LOGGER.debug("started accepting on port " + accept);
-                    acceptNext();
-                } catch (IOException e) {
-                    LOGGER.fatal("failed to accept on port " + accept + ": " + e);
-                }
-                try {
-                    java.lang.Thread.sleep(1000);
-                } catch (InterruptedException ignored) {
-                }
-                tryBind(accept);
-            }
-        });
-    }
+	public void tryBind(final Integer accept) {
+		acceptThread.invokeLater(new Runnable() {
+			@Override
+			public void run() {
+				try {
+					acceptSocket.bind(new InetSocketAddress(accept));
+					log.debug("started accepting on port " + accept);
+					acceptNext();
+				} catch (IOException e) {
+					log.fatal("failed to accept on port " + accept + ": " + e);
+				}
+				try {
+					java.lang.Thread.sleep(1000);
+				} catch (InterruptedException ignored) {
+				}
+				tryBind(accept);
+			}
+		});
+	}
 
 }
Index: java/main/src/main/java/com/framsticks/core/Node.java
===================================================================
--- java/main/src/main/java/com/framsticks/core/Node.java	(revision 79)
+++ java/main/src/main/java/com/framsticks/core/Node.java	(revision 84)
@@ -1,8 +1,5 @@
 package com.framsticks.core;
 
-import com.framsticks.params.types.CompositeParam;
-
-import java.util.HashMap;
-import java.util.Map;
+import com.framsticks.params.CompositeParam;
 
 /**
Index: java/main/src/main/java/com/framsticks/core/Parameters.java
===================================================================
--- java/main/src/main/java/com/framsticks/core/Parameters.java	(revision 79)
+++ 	(revision )
@@ -1,43 +1,0 @@
-package com.framsticks.core;
-
-import com.framsticks.params.FramsClass;
-import com.framsticks.util.Dispatcher;
-import org.apache.commons.configuration.Configuration;
-
-/**
- * @author Piotr Sniegowski
- */
-public class Parameters {
-    protected Configuration config;
-    protected String name;
-    protected Dispatcher dispatcher;
-	protected EntityOwner owner;
-
-
-
-    public Parameters(Configuration config, String name, Dispatcher dispatcher, EntityOwner owner) {
-        this.config = config;
-        this.name = name;
-        this.dispatcher = dispatcher;
-		this.owner = owner;
-    }
-
-    public Parameters(Parameters parameters) {
-        config = parameters.config;
-        name = parameters.name;
-        dispatcher = parameters.dispatcher;
-		owner = parameters.owner;
-    }
-
-    public final Configuration getConfig() {
-        return config;
-    }
-
-    public final String getName() {
-        return name;
-    }
-
-    public static void constructFramsClass(FramsClass.Constructor constructor) {
-        constructor.method("getName");
-    }
-}
Index: java/main/src/main/java/com/framsticks/core/Path.java
===================================================================
--- java/main/src/main/java/com/framsticks/core/Path.java	(revision 79)
+++ java/main/src/main/java/com/framsticks/core/Path.java	(revision 84)
@@ -2,11 +2,12 @@
 
 import com.framsticks.params.AccessInterface;
+import com.framsticks.params.CompositeParam;
 import com.framsticks.params.Param;
-import com.framsticks.params.types.CompositeParam;
-import com.framsticks.util.Dispatching;
-import org.apache.log4j.Logger;
-
+import com.framsticks.util.dispatching.Dispatching;
 import java.util.Iterator;
 import java.util.LinkedList;
+import java.util.List;
+
+import org.apache.commons.collections.ListUtils;
 
 /**
@@ -14,155 +15,190 @@
  */
 public class Path {
-    private final static Logger LOGGER = Logger.getLogger(Path.class.getName());
-
-    final LinkedList<Node> nodes = new LinkedList<Node>();
-    String textual;
-    Instance instance;
-
-    protected Object getKnownChild(AccessInterface access, CompositeParam param) {
-        Object child = access.get(param, Object.class);
-        if (child == null) {
-            return null;
-        }
-        return (instance.prepareAccess(param) != null) ? child : null;
-    }
-
-    public Path(Instance instance, String textual) {
-        assert instance.isActive();
-        this.instance = instance;
-        StringBuilder b = new StringBuilder();
-        nodes.add(instance.root);
-        Node current = instance.root;
-        Iterator<String> i = Instance.splitPath(textual);
-        while (i.hasNext() && current.getObject() != null) {
-            AccessInterface access = instance.prepareAccess(current.getParam());
-            if (access == null) {
-                break;
-            }
-            String e = i.next();
-            Param p = access.getParam(e);
-            if (!(p instanceof CompositeParam)) {
-                //entries.add(new Entry());
-                break;
-            }
-            CompositeParam c = (CompositeParam)p;
-            b.append("/").append(e);
-            access.select(current.getObject());
-            current = new Node(c, getKnownChild(access, c));
-            nodes.add(current);
-        }
-        this.textual = (size() == 1) ? "/" : b.toString();
-    }
-
-    protected Path() {
-
-    }
-
-    public Path appendNode(Node node) {
-        assert isResolved();
-        Path result = new Path();
-        result.textual = textual + ((size() == 1) ? "" : "/") + node.getParam().getId();
-        result.instance = instance;
-        result.nodes.addAll(nodes);
-        result.nodes.add(node);
-        return result;
-    }
-
-    public Path appendParam(CompositeParam param) {
-        assert isResolved();
-        return appendNode(new Node(param, null));
-    }
-
-    public Path appendResolution(Object object) {
-        assert !isResolved();
-        Path result = new Path();
-        result.textual = textual;
-        result.instance = instance;
-        result.nodes.addAll(nodes);
-        result.nodes.add(new Node(result.nodes.pollLast().getParam(), object));
-        return result;
-    }
-
-    public final Object getTopObject() {
-        return getTop().getObject();
-    }
-
-    public final Node getTop() {
-        return nodes.getLast();
-    }
-
-    public final Node getUnder() {
-        assert nodes.size() >= 2;
-        return nodes.get(nodes.size() - 2);
-    }
-
-    public final String getTextual() {
-        return textual;
-    }
-
-    public String toString() {
-        return instance + textual + (!isResolved() ? "!" : "");
-    }
-
-    public final int size() {
-        assert Dispatching.isThreadSafe();
-        return nodes.size();
-    }
-
-    public final boolean isResolved() {
-        assert Dispatching.isThreadSafe();
-        return getTop().getObject() != null;
-    }
-
-    public final boolean isResolved(String textual) {
-        assert Dispatching.isThreadSafe();
-        return isTheSame(textual) && isResolved();
-    }
-
-    public final boolean isTheSame(String textual) {
-        assert Dispatching.isThreadSafe();
-        return this.textual.equals(textual);
-    }
-
-    public final Instance getInstance() {
-        assert Dispatching.isThreadSafe();
-        return instance;
-    }
-
-    public Path findResolution() {
-        assert instance.isActive();
-        assert !isResolved();
-        if (size() == 1) {
+	// private final static Logger log = Logger.getLogger(Path.class.getName());
+
+	final LinkedList<Node> nodes = new LinkedList<Node>();
+	String textual;
+	Instance instance;
+
+	protected Object getKnownChild(AccessInterface access, CompositeParam param) {
+		Object child = access.get(param, Object.class);
+		if (child == null) {
+			return null;
+		}
+		return (instance.registry.prepareAccess(param) != null) ? child : null;
+	}
+
+	// public Path constructPath(Instance instance, String textual) {
+	//	assert instance.isActive();
+
+	// }
+
+	Path(Instance instance, String textual) {
+		assert instance.isActive();
+		this.instance = instance;
+
+		nodes.add(instance.root);
+		Node current = instance.root;
+
+		StringBuilder b = new StringBuilder();
+		Iterator<String> i = Instance.splitPath(textual);
+		while (i.hasNext() && current.getObject() != null) {
+			AccessInterface access = instance.registry.prepareAccess(current.getParam());
+			if (access == null) {
+				break;
+			}
+			String e = i.next();
+			Param p = access.getParam(e);
+			if (!(p instanceof CompositeParam)) {
+				//entries.add(new Entry());
+				break;
+			}
+			CompositeParam c = (CompositeParam)p;
+			b.append("/").append(e);
+			access.select(current.getObject());
+			current = new Node(c, getKnownChild(access, c));
+			nodes.add(current);
+		}
+		this.textual = (size() == 1) ? "/" : b.toString();
+	}
+
+	public Path(Instance instance, List<Node> nodes, Node node) {
+		this.instance = instance;
+		StringBuilder b = new StringBuilder();
+		boolean add = false;
+		for (Node n : nodes) {
+			this.nodes.add(n);
+			if (add) {
+				b.append("/").append(n.getParam().getId());
+			}
+			add = true;
+			if (n == node) {
+				break;
+			}
+		}
+		this.textual = (size() == 1) ? "/" : b.toString();
+	}
+
+	protected Path() {
+
+	}
+
+	public Path appendNode(Node node) {
+		assert isResolved();
+		Path result = new Path();
+		result.textual = textual + ((size() == 1) ? "" : "/") + node.getParam().getId();
+		result.instance = instance;
+		result.nodes.addAll(nodes);
+		result.nodes.add(node);
+		return result;
+	}
+
+	public Path appendParam(CompositeParam param) {
+		assert isResolved();
+		return appendNode(new Node(param, null));
+	}
+
+	public Path appendResolution(Object object) {
+		assert !isResolved();
+		Path result = new Path();
+		result.textual = textual;
+		result.instance = instance;
+		result.nodes.addAll(nodes);
+		result.nodes.add(new Node(result.nodes.pollLast().getParam(), object));
+		return result;
+	}
+
+	public final Object getTopObject() {
+		return getTop().getObject();
+	}
+
+	public final Node getTop() {
+		return nodes.getLast();
+	}
+
+	public final Node getUnder() {
+		assert nodes.size() >= 2;
+		return nodes.get(nodes.size() - 2);
+	}
+
+	public final String getTextual() {
+		return textual;
+	}
+
+	public String toString() {
+		return instance + textual + (!isResolved() ? "!" : "");
+	}
+
+	public final int size() {
+		assert Dispatching.isThreadSafe();
+		return nodes.size();
+	}
+
+	public final boolean isResolved() {
+		assert Dispatching.isThreadSafe();
+		return getTop().getObject() != null;
+	}
+
+	public final boolean isResolved(String textual) {
+		assert Dispatching.isThreadSafe();
+		return isTheSame(textual) && isResolved();
+	}
+
+	public final boolean isTheSame(String textual) {
+		assert Dispatching.isThreadSafe();
+		return this.textual.equals(textual);
+	}
+
+	public final Instance getInstance() {
+		assert Dispatching.isThreadSafe();
+		return instance;
+	}
+
+
+	/** Attach resolution at end, if available.
+	 *
+	 * @return Modified path, if resolution was available, this otherwise.
+	 */
+	public Path tryFindResolution() {
+		assert instance.isActive();
+		assert !isResolved();
+		if (size() == 1) {
 			return new Path(instance, "/");//appendResolution(instance.root.object);
-        }
-        Object child = getKnownChild(instance.bindAccess(getUnder()), getTop().getParam());
-        if (child == null) {
-            return this;
-        }
-        return appendResolution(child);
-    }
-
-    public boolean matches(Path p) {
-        assert Dispatching.isThreadSafe();
-        assert instance == p.instance;
-        Iterator<Node> a = nodes.iterator();
-        Iterator<Node> b = p.nodes.iterator();
-        while (a.hasNext() && b.hasNext()) {
-            Node an = a.next();
-            Node bn = b.next();
-            if (an.object != bn.object) {
-                return false;
-            }
-        }
-        return a.hasNext() == b.hasNext();
-    }
-
-    public String getLastElement() {
-        return getTop().getParam().getId();
-    }
-
-    public final boolean isOwner(Instance instance) {
-        return this.instance == instance;
-    }
+		}
+		Object child = getKnownChild(instance.bindAccess(getUnder()), getTop().getParam());
+		if (child == null) {
+			return this;
+		}
+		return appendResolution(child);
+	}
+
+	public boolean matches(Path p) {
+		assert Dispatching.isThreadSafe();
+		assert instance == p.instance;
+		Iterator<Node> a = nodes.iterator();
+		Iterator<Node> b = p.nodes.iterator();
+		while (a.hasNext() && b.hasNext()) {
+			Node an = a.next();
+			Node bn = b.next();
+			if (an.object != bn.object) {
+				return false;
+			}
+		}
+		return a.hasNext() == b.hasNext();
+	}
+
+	public String getLastElement() {
+		return getTop().getParam().getId();
+	}
+
+	public final boolean isOwner(Instance instance) {
+		return this.instance == instance;
+	}
+
+	@SuppressWarnings("unchecked")
+	public
+	List<Node> getNodes() {
+		return ListUtils.unmodifiableList(nodes);
+	}
 }
 
Index: java/main/src/main/java/com/framsticks/core/Program.java
===================================================================
--- java/main/src/main/java/com/framsticks/core/Program.java	(revision 79)
+++ java/main/src/main/java/com/framsticks/core/Program.java	(revision 84)
@@ -1,11 +1,10 @@
 package com.framsticks.core;
 
-import com.framsticks.util.Pair;
-import com.framsticks.util.Strings;
+import com.framsticks.util.lang.IterableIterator;
+import com.framsticks.util.lang.Pair;
+import com.framsticks.util.lang.Strings;
 import org.apache.commons.configuration.*;
 import org.apache.log4j.Logger;
 import org.apache.log4j.PropertyConfigurator;
-//import sun.misc.Signal;
-//import sun.misc.SignalHandler;
 
 import java.lang.reflect.Constructor;
@@ -15,112 +14,99 @@
  * @author Piotr Sniegowski
  */
-public class Program extends com.framsticks.util.Thread {
+public class Program extends com.framsticks.util.dispatching.Thread {
 
-    private final static Logger LOGGER = Logger.getLogger(Program.class.getName());
+	private final static Logger log = Logger.getLogger(Program.class.getName());
 
-/*
-    protected SignalHandler signalHandler = new SignalHandler() {
-        @Override
-        public void handle(Signal signal) {
-            LOGGER.info("caught " + signal);
-            Runtime.getRuntime().exit(0);
-        }
-    };
-*/
+	protected Entity entity;
 
-    protected Entity entity;
+	Configuration config;
 
-    Configuration config;
+	public Program(String name) {
+		super(name, java.lang.Thread.currentThread());
+	}
 
+	public static Entity configureEntity(Configuration config) {
+		String typeName = config.getString("class");
+		log.info("configuring instance " + typeName);
+		try {
+			Class<?> type = Class.forName(typeName);
+			Constructor<?> constructor = type.getConstructor();
+			Entity entity = (Entity) constructor.newInstance();
+			return entity;
+		} catch (Exception e) {
+			log.error("failed to instantiate: " + e);
+		}
+		return null;
+	}
 
-    public Program(String name) {
-        super(name, java.lang.Thread.currentThread());
-//        Signal.handle(new Signal("INT"), signalHandler);
-//        Signal.handle(new Signal("TERM"), signalHandler);
-    }
+	protected static void resolve(Configuration config, String prefix) {
+		for (String p : new IterableIterator<String>(prefix == null ? config.getKeys() : config.getKeys(prefix))) {
+			if (p.endsWith(".mount")) {
+				String source = config.getString(p);
+				log.info("mounting " + source + " at " + p);
+				config.clearProperty(p);
+				Configuration mount = config.subset(source);
+				for (String mk : new IterableIterator<String>(mount.getKeys())) {
+					config.addProperty(p.substring(0, p.length() - 6) + "."	+ mk, mount.getProperty(mk));
+				}
+			}
+		}
+	}
 
-    public static Entity configureEntity(Parameters parameters) {
-        String typeName = parameters.getConfig().getString("class");
-        LOGGER.info("configuring instance " + typeName);
-        try {
-            Class type = Class.forName(typeName);
-            Constructor constructor = type.getConstructor(Parameters.class);
-            return (Entity) constructor.newInstance(parameters);
-        } catch (Exception e) {
-            LOGGER.error("failed to instantiate: " + e);
-        }
-        return null;
-    }
-
-    protected static void resolve(Configuration config, String prefix) {
-
-        Iterator i = prefix == null ? config.getKeys() : config.getKeys(prefix);
-        while (i.hasNext()) {
-            String p = (String) i.next();
-            if (p.endsWith(".mount")) {
-                String source = config.getString(p);
-                LOGGER.info("mounting " + source + " at " + p);
-                config.clearProperty(p);
-                Configuration mount = config.subset(source);
-                Iterator mi = mount.getKeys();
-                while (mi.hasNext()) {
-                    String mk = (String) mi.next();
-                    config.addProperty(p.substring(0, p.length() - 6) + "." + mk, mount.getProperty(mk));
-                }
-            }
-        }
-    }
-
-    public void run(String[] args) {
+	public void run(String[] args) {
 
 		PropertyConfigurator.configure(getClass().getResource("/configs/log4j.properties"));
-		LOGGER.debug("started in " + System.getProperty("user.dir"));
-        try {
+		log.debug("started in " + System.getProperty("user.dir"));
+		try {
 			config = new PropertiesConfiguration(getClass().getResource("/configs/framsticks.properties"));
 
-            for (String a : args) {
-                Pair<String, String> p = Strings.splitIntoPair(a, '=', "true");
-                config.setProperty(p.first, p.second);
-            }
+			for (String a : args) {
+				Pair<String, String> p = Strings.splitIntoPair(a, '=', "true");
+				config.setProperty(p.first, p.second);
+			}
 
-            resolve(config, null);
+			resolve(config, null);
 
-            Iterator i = config.getKeys();
-            while (i.hasNext()) {
-                String p = (String) i.next();
-                LOGGER.debug(p + " = " + config.getProperty(p));
-            }
+			Iterator<?> i = config.getKeys();
+			while (i.hasNext()) {
+				String p = (String) i.next();
+				log.debug(p + " = " + config.getProperty(p));
+			}
 
-        } catch (ConfigurationException e) {
-            System.err.print("failed to parse configuration:" + e);
-            return;
-        }
+		} catch (ConfigurationException e) {
+			System.err.print("failed to parse configuration:" + e);
+			return;
+		}
+		Configuration entityConfig = config.subset("com.framsticks.entity");
 
-        entity = configureEntity(new Parameters(config.subset("com.framsticks.entity"), "main", null, new EntityOwner() {
+		entity = configureEntity(entityConfig);
+		entity.setOwner(new EntityOwner() {
 			@Override
 			public void onDone() {
-				LOGGER.info("exiting");
+				log.info("exiting");
 				Runtime.getRuntime().exit(0);
 			}
-		}));
+		});
+		entity.setName("main");
 		try {
-	        entity.configurePublic();
+			entity.configure(entityConfig);
 		} catch (Exception e) {
-			LOGGER.fatal("exception caught during configuration: " + e);
+			log.fatal("exception caught during configuration: " + e);
 		}
-        LOGGER.info("all entities were configured");
-        entity.start();
-    }
+		log.info("all entities were configured");
+		entity.start();
+	}
 
-    public static void main(final String[] args) {
-        final Program program = new Program("program");
-        program.invokeLater(new Runnable() {
-            @Override
-            public void run() {
-                program.run(args);
-            }
-        });
-        program.routine();
-    }
+	public static void main(final String[] args) {
+
+		final Program program = new Program("program");
+		program.invokeLater(new Runnable() {
+			@Override
+			public void run() {
+				program.run(args);
+			}
+		});
+		program.routine();
+	}
 
 }
Index: java/main/src/main/java/com/framsticks/diagnostics/Diagnostics.java
===================================================================
--- java/main/src/main/java/com/framsticks/diagnostics/Diagnostics.java	(revision 79)
+++ java/main/src/main/java/com/framsticks/diagnostics/Diagnostics.java	(revision 84)
@@ -1,5 +1,6 @@
 package com.framsticks.diagnostics;
 
-import com.framsticks.core.Parameters;
+import org.apache.commons.configuration.Configuration;
+
 import com.framsticks.observers.Endpoint;
 import com.framsticks.observers.Observer;
@@ -10,27 +11,25 @@
 public class Diagnostics extends Observer {
 
-    final Integer dumpsInterval;
-    final String dumpsPath;
-    final String dumpsFormat;
+	Integer dumpsInterval;
+	String dumpsPath;
+	String dumpsFormat;
 
 
-    public Diagnostics(Parameters parameters) {
-        super(parameters);
-        dumpsInterval = config.getInteger("dumps.interval", null);
-        dumpsPath = config.getString("dumps.path", null);
-        dumpsFormat = config.getString("dumps.format", null);
-    }
+	public Diagnostics() {
+	}
 
-    @Override
-    protected void configure() throws Exception {
-
-        super.configure();
-    }
+	@Override
+	public void configure(Configuration config) {
+		super.configure(config);
+		dumpsInterval = config.getInteger("dumps.interval", null);
+		dumpsPath = config.getString("dumps.path", null);
+		dumpsFormat = config.getString("dumps.format", null);
+	}
 
 
-    @Override
-    protected Endpoint createEndpoint() {
-        return new DiagnosticsEndpoint();
-    }
+	@Override
+	protected Endpoint createEndpoint() {
+		return new DiagnosticsEndpoint();
+	}
 
 
Index: java/main/src/main/java/com/framsticks/diagnostics/DiagnosticsEndpoint.java
===================================================================
--- java/main/src/main/java/com/framsticks/diagnostics/DiagnosticsEndpoint.java	(revision 79)
+++ java/main/src/main/java/com/framsticks/diagnostics/DiagnosticsEndpoint.java	(revision 84)
@@ -1,8 +1,7 @@
 package com.framsticks.diagnostics;
 
-import com.framsticks.core.Path;
+import com.framsticks.dumping.PrintWriterSink;
 import com.framsticks.dumping.SaveStream;
 import com.framsticks.observers.Endpoint;
-import com.framsticks.dumping.PrintStreamSink;
 import com.framsticks.remote.RecursiveFetcher;
 import com.framsticks.util.Logging;
@@ -13,5 +12,5 @@
 import java.io.File;
 import java.io.IOException;
-import java.io.PrintStream;
+import java.io.PrintWriter;
 import java.text.SimpleDateFormat;
 import java.util.Date;
@@ -22,64 +21,64 @@
 public class DiagnosticsEndpoint extends Endpoint {
 
-    private final static Logger LOGGER = Logger.getLogger(DiagnosticsEndpoint.class.getName());
+	private final static Logger log = Logger.getLogger(DiagnosticsEndpoint.class.getName());
 
 
-    public DiagnosticsEndpoint() {
-        super();
-    }
+	public DiagnosticsEndpoint() {
+		super();
+	}
 
-    @Override
-    public Diagnostics getObserver() {
-        return (Diagnostics)observer;
-    }
+	@Override
+	public Diagnostics getObserver() {
+		return (Diagnostics)observer;
+	}
 
 
-    @Override
-    protected void configure() {
-        super.configure();
+	@Override
+	public void start() {
+		super.start();
 
-        if (getObserver().dumpsInterval != null) {
-            new PeriodicTask(instance, getObserver().dumpsInterval * 1000) {
-                @Override
-                public void run() {
+		if (getObserver().dumpsInterval != null) {
+			new PeriodicTask(instance, getObserver().dumpsInterval * 1000) {
+				@Override
+				public void run() {
 
-                    LOGGER.info("starting periodic dump");
-                    new RecursiveFetcher(instance, new Path(instance, "/"), new StateFunctor() {
-                        @Override
-                        public void call(Exception e) {
-                            if (Logging.log(LOGGER, "recursively fetch", instance, e)) {
-                                again();
-                                return;
-                            }
-                            LOGGER.info("instance resolved, saving");
-                            try {
-                                final String fileName = getObserver().dumpsPath + "/" + instance + "_" + new SimpleDateFormat(getObserver().dumpsFormat).format(new Date()) + ".param";
-                                File file = new File(fileName);
-                                new SaveStream(new PrintStreamSink(new PrintStream(file)), instance, new Path(instance, "/"), new StateFunctor() {
-                                    @Override
-                                    public void call(Exception e) {
-                                        Logging.log(LOGGER, "periodic dump in " + fileName + " of", DiagnosticsEndpoint.this.instance, e);
-                                        again();
-                                    }
-                                });
-                            } catch (IOException ex) {
-                                LOGGER.info("failed to initiate dump: " + ex);
-                                again();
-                            }
+					log.info("starting periodic dump");
+					new RecursiveFetcher(instance, instance.getRootPath(), new StateFunctor() {
+						@Override
+						public void call(Exception e) {
+							if (Logging.log(log, "recursively fetch", instance, e)) {
+								again();
+								return;
+							}
+							log.info("instance resolved, saving");
+							try {
+								final String fileName = getObserver().dumpsPath + "/" + instance + "_" + new SimpleDateFormat(getObserver().dumpsFormat).format(new Date()) + ".param";
+								File file = new File(fileName);
+								new SaveStream(new PrintWriterSink(new PrintWriter(file)), instance, instance.getRootPath(), new StateFunctor() {
+									@Override
+									public void call(Exception e) {
+										Logging.log(log, "periodic dump in " + fileName + " of", DiagnosticsEndpoint.this.instance, e);
+										again();
+									}
+								});
+							} catch (IOException ex) {
+								log.info("failed to initiate dump: " + ex);
+								again();
+							}
 
-                        }
-                    });
+						}
+					});
 
 
-                }
-            };
-        }
-    }
+				}
+			};
+		}
+	}
 
-    /*
-    @Override
-    public void onChange(Path path) {
-        super.onChange(path);    //To change body of overridden methods use File | Settings | File Templates.
-    }
-    */
+	/*
+	@Override
+	public void onChange(Path path) {
+		super.onChange(path);    //To change body of overridden methods use File | Settings | File Templates.
+	}
+	*/
 }
Index: java/main/src/main/java/com/framsticks/dumping/FileInstance.java
===================================================================
--- java/main/src/main/java/com/framsticks/dumping/FileInstance.java	(revision 79)
+++ java/main/src/main/java/com/framsticks/dumping/FileInstance.java	(revision 84)
@@ -2,10 +2,9 @@
 
 import com.framsticks.core.LocalInstance;
-import com.framsticks.core.Parameters;
 import com.framsticks.core.Path;
-import com.framsticks.params.FramsClass;
 import com.framsticks.core.Instance;
-import com.framsticks.util.*;
-import com.framsticks.util.UnsupportedOperationException;
+import com.framsticks.util.dispatching.Future;
+
+import org.apache.commons.configuration.Configuration;
 import org.apache.log4j.Logger;
 
@@ -20,41 +19,45 @@
 public class FileInstance extends LocalInstance {
 
-    private static final Logger LOGGER = Logger.getLogger(Instance.class.getName());
-    protected final File file;
+	private static final Logger log = Logger.getLogger(Instance.class.getName());
+	protected File file;
 
-    public FileInstance(Parameters parameters) {
-        super(parameters);
-        file = new File(config.getString("filename"));
-    }
+	public FileInstance() {
+	}
 
-    @Override
-    public void run() {
-        assert isActive();
-        super.run();
-        try {
-            FileReader fileReader = new FileReader(file);
-            LoadStream stream = new LoadStream(new Path(this, "/"), new BufferedReader(fileReader), this, new Future<Path>() {
-                @Override
-                public void result(Path result, Exception e) {
-                    if (e != null) {
-                        LOGGER.error("failed to load file instance " + FileInstance.this + ": " + e);
-                        fireRun(e);
-                        return;
-                    }
-                    LOGGER.info("loaded file instance " + FileInstance.this);
-                    fireRun(null);
-                }
-            });
-            stream.load();
-        } catch (IOException e) {
-            LOGGER.error("io failure: " + e);
-            fireRun(e);
-        }
-    }
+	@Override
+	public void configure(Configuration config) {
+		super.configure(config);
+		file = new File(config.getString("filename"));
+	}
 
-    @Override
-    public String toString() {
-        return "file@" + file.getName();
-    }
+	@Override
+	public void run() {
+		assert isActive();
+		super.run();
+		try {
+			FileReader fileReader = new FileReader(file);
+			LoadStream stream = new LoadStream(this.getRootPath(), new BufferedReader(fileReader), this, new Future<Path>() {
+				@Override
+				public void result(Path result, Exception e) {
+					if (e != null) {
+						log.error("failed to load file instance " + FileInstance.this + ": " + e);
+						fireRun(e);
+						return;
+					}
+					log.info("loaded file instance " + FileInstance.this);
+					fireRun(null);
+				}
+			});
+			stream.load();
+		} catch (IOException e) {
+			log.error("io failure: " + e);
+			fireRun(e);
+		}
+	}
+
+	@Override
+	public String toString() {
+		return "file@" + file.getName();
+	}
 
 
Index: java/main/src/main/java/com/framsticks/dumping/LoadStream.java
===================================================================
--- java/main/src/main/java/com/framsticks/dumping/LoadStream.java	(revision 79)
+++ java/main/src/main/java/com/framsticks/dumping/LoadStream.java	(revision 84)
@@ -6,4 +6,7 @@
 import com.framsticks.core.Instance;
 import com.framsticks.util.*;
+import com.framsticks.util.dispatching.Future;
+import com.framsticks.util.lang.Pair;
+import com.framsticks.util.lang.Strings;
 import org.apache.log4j.Logger;
 
@@ -18,71 +21,71 @@
 public class LoadStream {
 
-    private final static Logger LOGGER = Logger.getLogger(LoadStream.class.getName());
+	private final static Logger log = Logger.getLogger(LoadStream.class.getName());
 
-    protected final Instance instance;
-    protected final Path mountPath;
-    protected final BufferedReader stream;
-    protected final Future<Path> future;
-    protected final Stopwatch stopwatch = new Stopwatch();
+	protected final Instance instance;
+	protected final Path mountPath;
+	protected final BufferedReader stream;
+	protected final Future<Path> future;
+	protected final Stopwatch stopwatch = new Stopwatch();
 
 
-    public LoadStream(Path mountPath, BufferedReader stream, Instance instance, Future<Path> future) {
-        this.instance = instance;
-        this.mountPath = mountPath;
-        this.stream = stream;
-        this.future = future;
-    }
+	public LoadStream(Path mountPath, BufferedReader stream, Instance instance, Future<Path> future) {
+		this.instance = instance;
+		this.mountPath = mountPath;
+		this.stream = stream;
+		this.future = future;
+	}
 
-    public void load() {
-        try {
-            String line;
-            Pair<String, String> query = null;
-            List<File> files = null;
-            List<String> content = null;
-            //File file;
-            while ((line = stream.readLine()) != null) {
-                if (query == null) {
-                    query = Strings.splitIntoPair(line, ' ', "\n");
-                    files = new LinkedList<File>();
-                    LOGGER.trace("loading " + line);
-                    continue;
-                }
-                if (content == null) {
-                    if (line.equals("file")) {
-                        content = new LinkedList<String>();
-                        continue;
-                    }
-                    if (line.equals("ok")) {
-                        if (query.first.equals("get")) {
-                            Path path = instance.createIfNeeded(query.second);
-                            instance.processFetchedValues(path, files);
-                        } else if (query.first.equals("info")) {
-                            assert files.size() == 1;
-                            instance.processFetchedInfo(files.get(0));
-                        } else {
-                            assert false;
-                        }
-                        query = null;
-                        files = null;
-                        continue;
-                    }
-                    assert false;
-                    continue;
-                }
-                if (line.equals("eof")) {
-                    files.add(new File(query.second, new ListSource(content)));
-                    content = null;
-                    continue;
-                }
-                content.add(line);
-            }
-        } catch (IOException e) {
-            LOGGER.error("failed to load: " + e);
-            future.result(null, e);
-            return;
-        }
-        LOGGER.info("loaded in: " + stopwatch);
-        future.result(new Path(instance, mountPath.getTextual()), null);
-    }
+	public void load() {
+		try {
+			String line;
+			Pair<String, String> query = null;
+			List<File> files = null;
+			List<String> content = null;
+			//File file;
+			while ((line = stream.readLine()) != null) {
+				if (query == null) {
+					query = Strings.splitIntoPair(line, ' ', "\n");
+					files = new LinkedList<File>();
+					log.trace("loading " + line);
+					continue;
+				}
+				if (content == null) {
+					if (line.equals("file")) {
+						content = new LinkedList<String>();
+						continue;
+					}
+					if (line.equals("ok")) {
+						if (query.first.equals("get")) {
+							Path path = instance.createIfNeeded(query.second);
+							instance.processFetchedValues(path, files);
+						} else if (query.first.equals("info")) {
+							assert files.size() == 1;
+							instance.processFetchedInfo(files.get(0));
+						} else {
+							assert false;
+						}
+						query = null;
+						files = null;
+						continue;
+					}
+					assert false;
+					continue;
+				}
+				if (line.equals("eof")) {
+					files.add(new File(query.second, new ListSource(content)));
+					content = null;
+					continue;
+				}
+				content.add(line);
+			}
+		} catch (IOException e) {
+			log.error("failed to load: " + e);
+			future.result(null, e);
+			return;
+		}
+		log.info("loaded in: " + stopwatch);
+		future.result(instance.getPath(mountPath.getTextual()), null);
+	}
 
 
Index: java/main/src/main/java/com/framsticks/dumping/PrintStreamSink.java
===================================================================
--- java/main/src/main/java/com/framsticks/dumping/PrintStreamSink.java	(revision 79)
+++ 	(revision )
@@ -1,38 +1,0 @@
-package com.framsticks.dumping;
-
-import com.framsticks.params.SinkInterface;
-
-import java.io.PrintStream;
-
-/**
- * @author Piotr Sniegowski
- */
-public class PrintStreamSink implements SinkInterface {
-
-    protected final PrintStream stream;
-
-    public PrintStreamSink(PrintStream stream) {
-        this.stream = stream;
-    }
-
-    @Override
-    public PrintStreamSink print(String str) {
-        stream.print(str);
-        return this;
-    }
-
-    @Override
-    public PrintStreamSink print(Object obj) {
-        stream.print(obj);
-        return this;
-    }
-
-    @Override
-    public void breakLine() {
-        stream.print('\n');
-    }
-
-    @Override
-    public void close() {
-    }
-}
Index: java/main/src/main/java/com/framsticks/dumping/PrintWriterSink.java
===================================================================
--- java/main/src/main/java/com/framsticks/dumping/PrintWriterSink.java	(revision 84)
+++ java/main/src/main/java/com/framsticks/dumping/PrintWriterSink.java	(revision 84)
@@ -0,0 +1,38 @@
+package com.framsticks.dumping;
+
+import com.framsticks.params.SinkInterface;
+
+import java.io.PrintWriter;
+
+/**
+ * @author Piotr Sniegowski
+ */
+public class PrintWriterSink implements SinkInterface {
+
+    protected final PrintWriter stream;
+
+    public PrintWriterSink(PrintWriter stream) {
+        this.stream = stream;
+    }
+
+    @Override
+    public PrintWriterSink print(String str) {
+        stream.print(str);
+        return this;
+    }
+
+    @Override
+    public PrintWriterSink print(Object obj) {
+        stream.print(obj);
+        return this;
+    }
+
+    @Override
+    public void breakLine() {
+        stream.print('\n');
+    }
+
+    @Override
+    public void close() {
+    }
+}
Index: java/main/src/main/java/com/framsticks/dumping/SaveStream.java
===================================================================
--- java/main/src/main/java/com/framsticks/dumping/SaveStream.java	(revision 79)
+++ java/main/src/main/java/com/framsticks/dumping/SaveStream.java	(revision 84)
@@ -4,16 +4,17 @@
 import com.framsticks.core.Path;
 import com.framsticks.params.AccessInterface;
+import com.framsticks.params.CompositeParam;
 import com.framsticks.params.FramsClass;
 import com.framsticks.params.ListAccess;
-import com.framsticks.params.Param;
-import com.framsticks.params.types.CompositeParam;
 import com.framsticks.params.SinkInterface;
 import com.framsticks.parsers.Savers;
 import com.framsticks.core.Instance;
 import com.framsticks.util.*;
+import com.framsticks.util.dispatching.Dispatching;
 import org.apache.log4j.Logger;
 
 import java.util.HashSet;
 import java.util.Set;
+import static com.framsticks.util.lang.Containers.filterInstanceof;
 
 /**
@@ -22,21 +23,21 @@
 public class SaveStream {
 
-    private final static Logger LOGGER = Logger.getLogger(SaveStream.class.getName());
+	private final static Logger log = Logger.getLogger(SaveStream.class.getName());
 
-    protected final SinkInterface sink;
-    protected final Instance instance;
-    protected final StateFunctor stateFunctor;
-    protected final Stopwatch stopwatch = new Stopwatch();
-    protected final Set<FramsClass> storedInfo = new HashSet<FramsClass>();
+	protected final SinkInterface sink;
+	protected final Instance instance;
+	protected final StateFunctor stateFunctor;
+	protected final Stopwatch stopwatch = new Stopwatch();
+	protected final Set<FramsClass> storedInfo = new HashSet<FramsClass>();
 
-    private int dispatched = 0;
+	private int dispatched = 0;
 
-    public SaveStream(SinkInterface sink, Instance instance, Path root, StateFunctor stateFunctor) {
-        assert Dispatching.isThreadSafe();
-        this.sink = sink;
-        this.instance = instance;
-        this.stateFunctor = stateFunctor;
+	public SaveStream(SinkInterface sink, Instance instance, Path root, StateFunctor stateFunctor) {
+		assert Dispatching.isThreadSafe();
+		this.sink = sink;
+		this.instance = instance;
+		this.stateFunctor = stateFunctor;
 		dispatchWrite(root);
-    }
+	}
 
 	protected void dispatchWrite(final Path path) {
@@ -50,49 +51,46 @@
 	}
 
-    protected void finished() {
-        assert instance.isActive();
-        LOGGER.info("stored in " + stopwatch);
-        stateFunctor.call(null);
-    }
+	protected void finished() {
+		assert instance.isActive();
+		log.info("stored in " + stopwatch);
+		stateFunctor.call(null);
+	}
 
-    public void write(final Path path) {
-        assert instance.isActive();
-        if (!path.isResolved()) {
-            LOGGER.debug("path " + path + " is not resolved - skipping");
-        } else {
-            AccessInterface access = instance.bindAccess(path);
+	public void write(final Path path) {
+		assert instance.isActive();
+		if (!path.isResolved()) {
+			log.debug("path " + path + " is not resolved - skipping");
+		} else {
+			AccessInterface access = instance.bindAccess(path);
 			assert access != null;
-            FramsClass framsClass = access.getFramsClass();
-            assert framsClass != null;
-            if (!storedInfo.contains(framsClass)) {
-                storedInfo.add(framsClass);
-                sink.print("info ").print(path.getTextual()).breakLine();
-                sink.print("file").breakLine();
-                Savers.saveFramsClass(sink, framsClass);
-                sink.print("eof").breakLine();
-                sink.print("ok").breakLine();
-            }
-            if (!(access instanceof ListAccess)) {
-                sink.print("get ").print(path.getTextual()).breakLine();
-                sink.print("file").breakLine();
-                //stream.print("#" + access.getSelected().getClass().getCanonicalName() + "\n");
-                access.save(sink);
-                sink.print("eof").breakLine();
-                sink.print("ok").breakLine();
-            }
-            for (Param p : access.getParams()) {
-                if (p instanceof CompositeParam) {
-                    CompositeParam childParam = (CompositeParam)p;
-                    final Path childPath = path.appendNode(new Node(childParam, access.get(childParam, Object.class)));
-                    if (childPath.isResolved() && instance.getInfoFromCache(childPath) != null) {
-						dispatchWrite(childPath);
-                    }
-                }
-            }
-        }
-        --dispatched;
-        if (dispatched == 0) {
-            finished();
-        }
-    }
+			FramsClass framsClass = access.getFramsClass();
+			assert framsClass != null;
+			if (!storedInfo.contains(framsClass)) {
+				storedInfo.add(framsClass);
+				sink.print("info ").print(path.getTextual()).breakLine();
+				sink.print("file").breakLine();
+				Savers.saveFramsClass(sink, framsClass);
+				sink.print("eof").breakLine();
+				sink.print("ok").breakLine();
+			}
+			if (!(access instanceof ListAccess)) {
+				sink.print("get ").print(path.getTextual()).breakLine();
+				sink.print("file").breakLine();
+				//stream.print("#" + access.getSelected().getClass().getCanonicalName() + "\n");
+				access.save(sink);
+				sink.print("eof").breakLine();
+				sink.print("ok").breakLine();
+			}
+			for (CompositeParam p : filterInstanceof(access.getParams(), CompositeParam.class)) {
+				final Path childPath = path.appendNode(new Node(p, access.get(p, Object.class)));
+				if (childPath.isResolved() && instance.getInfoFromCache(childPath) != null) {
+					dispatchWrite(childPath);
+				}
+			}
+		}
+		--dispatched;
+		if (dispatched == 0) {
+			finished();
+		}
+	}
 }
Index: java/main/src/main/java/com/framsticks/examples/GenotypeBrowser.java
===================================================================
--- java/main/src/main/java/com/framsticks/examples/GenotypeBrowser.java	(revision 79)
+++ java/main/src/main/java/com/framsticks/examples/GenotypeBrowser.java	(revision 84)
@@ -3,14 +3,17 @@
 import com.framsticks.core.Instance;
 import com.framsticks.core.Node;
-import com.framsticks.core.Parameters;
-import com.framsticks.core.Path;
+import com.framsticks.dumping.PrintWriterSink;
 import com.framsticks.model.*;
 import com.framsticks.model.Package;
 import com.framsticks.params.*;
-import com.framsticks.params.types.CompositeParam;
 import com.framsticks.parsers.F0Parser;
+import com.framsticks.parsers.F0Writer;
 import com.framsticks.parsers.Schema;
+
+import org.apache.commons.configuration.Configuration;
 import org.apache.log4j.Logger;
 
+import java.io.PrintWriter;
+import java.io.StringWriter;
 import java.util.List;
 
@@ -20,17 +23,20 @@
 public class GenotypeBrowser extends Instance {
 
-	private static final Logger LOGGER = Logger.getLogger(Instance.class.getName());
+	private static final Logger log = Logger
+			.getLogger(Instance.class.getName());
 	protected Schema schema;
 
-
-	public GenotypeBrowser(Parameters parameters) {
-		super(parameters);
-		LOGGER.info("model builder created");
+	public GenotypeBrowser() {
+		log.info("model builder created");
 	}
 
 	@Override
-	protected void configure() throws Exception {
-		super.configure();
-		schema = new Schema(Schema.getDefaultDefinitionAsStream());
+	public void configure(Configuration config) {
+		super.configure(config);
+		try {
+			schema = new Schema(Schema.getDefaultDefinitionAsStream());
+		} catch (Exception e) {
+			log.error("failed to load schema: " + e);
+		}
 		this.registry = schema.getRegistry();
 		Package.register(this.getRegistry());
@@ -38,4 +44,5 @@
 		registry.putInfoIntoCache(new FramsClass("ModelBuilderRoot", "ModelBuilderRoot", null)
 				.append(new ParamBuilder().setType("o Model").setId("model").setName("model").build())
+				.append(new ParamBuilder().setType("s 1").setId("genotype").setName("genotype").build())
 		);
 		root = new Node((CompositeParam)new ParamBuilder().setType("o ModelBuilderRoot").setId(name).setName("Instance").build(), PropertiesAccess.createPropertiesMap());
@@ -51,10 +58,14 @@
 			Model model = Model.build(objects);
 
-			AccessInterface rootAccess = bindAccess(new Path(this, "/"));
+			AccessInterface rootAccess = bindAccess(this.getRootPath());
 
 			rootAccess.set("model", model);
 
+			StringWriter w = new StringWriter();
+			new F0Writer(schema, model, new PrintWriterSink(new PrintWriter(w))).write();
+			rootAccess.set("genotype", w.getBuffer().toString());
+
 		} catch (Exception e) {
-			LOGGER.error("exception caught: " + e);
+			log.error("exception caught: " + e);
 		}
 		//done();
Index: java/main/src/main/java/com/framsticks/gui/Browser.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/Browser.java	(revision 79)
+++ java/main/src/main/java/com/framsticks/gui/Browser.java	(revision 84)
@@ -4,9 +4,18 @@
 import com.framsticks.observers.Endpoint;
 import com.framsticks.observers.Observer;
-import com.framsticks.util.Dispatcher;
+import com.framsticks.util.Logging;
+import com.framsticks.util.dispatching.Dispatcher;
+import com.framsticks.util.dispatching.Future;
+
+import org.apache.commons.configuration.Configuration;
+import org.apache.commons.lang.ArrayUtils;
 import org.apache.log4j.Logger;
 
 import javax.swing.*;
+
+import java.awt.Dimension;
+import java.util.ArrayList;
 import java.util.HashSet;
+import java.util.List;
 import java.util.Set;
 
@@ -16,110 +25,188 @@
 public class Browser extends Observer implements Dispatcher {
 
-    private static final Logger LOGGER = Logger.getLogger(Browser.class.getName());
-
-    protected final Set<Frame> frames = new HashSet<Frame>();
-    protected MainFrame mainFrame;
-
-    public void addFrame(Frame frame) {
-        frames.add(frame);
-    }
-
-	public Browser(Parameters parameters) {
-        super(parameters);
-        dispatcher = SwingDispatcher.instance;
-        invokeLater(new Runnable() {
-            @Override
-            public void run() {
-                assert isActive();
-
-            }
-        });
+	private static final Logger log = Logger.getLogger(Browser.class.getName());
+
+	protected final Set<Frame> frames = new HashSet<Frame>();
+	protected MainFrame mainFrame;
+	public List<PanelProvider> panelProviders = new ArrayList<PanelProvider>();
+	protected Dimension defaultFrameDimension;
+
+	public void addFrame(Frame frame) {
+		frames.add(frame);
+	}
+
+	public Browser() {
+		JPopupMenu.setDefaultLightWeightPopupEnabled(false);
+		addPanelProvider(new StandardPanelProvider());
+	}
+
+	@Override
+	public void configure(Configuration config) {
+		super.configure(config);
+
+		defaultFrameDimension = new Dimension(config.getInteger("size.width", 1000), config.getInteger("size.height", 500));
+
+		for (String name : config.getStringArray("panel_providers")) {
+			try {
+				Class<?> c = Class.forName(name);
+				if (ArrayUtils.indexOf(c.getInterfaces(), PanelProvider.class) == -1) {
+					continue;
+				}
+				PanelProvider p = (PanelProvider)c.newInstance();
+				addPanelProvider(p);
+			} catch (Exception e) {
+				log.error("failed to load PanelProvider " + name + ": " + e);
+			}
+		}
+
+		// for (final String path : config.getStringArray("resolve_paths")) {
+		//	invokeLater()
+		//	autoResolvePath(path, new Future<Path>() {
+		//		@Override
+		//		public void result(Path p, Exception e) {
+		//			Logging.log(log, "auto resolve path", path, e);
+		//		}
+		//	});
+		// }
+	}
+
+	public void addPanelProvider(PanelProvider panelProvider) {
+		log.debug("added panel provider of type: " + panelProvider.getClass().getCanonicalName());
+		panelProviders.add(panelProvider);
+	}
+
+	public void autoResolvePath(final String path, final Future<Path> future) {
+		final Instance i = endpoints.get("localhost").getInstance();
+		i.invokeLater(new Runnable() {
+			@Override
+			public void run() {
+				i.resolveAndFetch(path, new Future<Path>() {
+					@Override
+					public void result(final Path p, Exception e) {
+						Logging.log(log, "auto resolve path", path, e);
+						if (future != null) {
+							future.result(p, e);
+						}
+						if (e == null) {
+							mainFrame.invokeLater(new Runnable() {
+								@Override
+								public void run() {
+									mainFrame.goTo(p);
+								}
+							});
+						}
+					}
+				});
+			}
+		});
 	}
 
 	public void clear() {
-        assert isActive();
-        for (Frame f : frames) {
-            f.clear();
-        }
-	}
-
-    @Override
-    protected void configure() throws Exception {
-        super.configure();
-    }
-
-
-    @Override
-    public void run() {
-        super.run();
-
-        try {
-            UIManager.setLookAndFeel("com.sun.java.swing.plaf.gtk.GTKLookAndFeel");
-        } catch (Exception ex) {
-            LOGGER.warn("failed loading Look&Feel: ", ex);
-        }
-        javax.swing.JFrame.setDefaultLookAndFeelDecorated(true);
-
-        mainFrame = new MainFrame(Browser.this);
-        addFrame(mainFrame);
-
-        for (Frame f : frames) {
-            f.configure();
-        }
-
-        for (final Endpoint e : getEndpoints().values()) {
-            e.invokeLater(new Runnable() {
-                @Override
-                public void run() {
-                    final Path p = new Path(e.getInstance(), "/");
-                    invokeLater(new Runnable() {
-                        @Override
-                        public void run() {
-                            mainFrame.addRootPath((BrowserEndpoint) e, p);
-                        }
-                    });
-                }
-            });
-
-        }
-
-        for (Frame f : frames) {
-            f.setVisible(true);
-        }
-    }
-
-    public void createTreeNodeForChild(final Path path) {
-        assert !isActive();
-        //assert instance.isActive();
+		assert isActive();
+		for (Frame f : frames) {
+			f.clear();
+		}
+	}
+
+	@Override
+	public void run() {
+		super.run();
+
+		assert isActive();
+
+		try {
+			boolean found = false;
+			// for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
+			//	log.info("look and feel available: " + info.getName());
+			//	if ("Nimbus".equals(info.getName())) {
+			//		UIManager.setLookAndFeel(info.getClassName());
+			//		found = true;
+			//		break;
+			//	}
+			// }
+			if (!found) {
+				UIManager.setLookAndFeel("com.sun.java.swing.plaf.gtk.GTKLookAndFeel");
+			}
+		} catch (Exception ex) {
+			log.warn("failed loading Look&Feel: ", ex);
+		}
+
+		javax.swing.JFrame.setDefaultLookAndFeelDecorated(true);
+
+		mainFrame = new MainFrame(Browser.this);
+		addFrame(mainFrame);
+
+		for (Frame f : frames) {
+			f.configure();
+		}
+
+		for (final Endpoint e : getEndpoints().values()) {
+			e.invokeLater(new Runnable() {
+				@Override
+				public void run() {
+					final Path p = e.getInstance().getRootPath();
+					invokeLater(new Runnable() {
+						@Override
+						public void run() {
+							mainFrame.addRootPath((BrowserEndpoint) e, p);
+						}
+					});
+				}
+			});
+		}
+
+		for (Frame f : frames) {
+			f.setVisible(true);
+		}
+
+		// autoResolvePath("/simulator/genepools/groups/0", null);
+		// autoResolvePath("/", null);
+	}
+
+	public void createTreeNodeForChild(final Path path) {
+		assert !isActive();
+		//assert instance.isActive();
 
 
 /*
-        final TreeNode parentTreeNode = (TreeNode) child.getParent().getUserObject();
-        if (parentTreeNode == null) {
-            Dispatching.invokeDispatch(this, manager, new Runnable() {
-                @Override
-                public void run() {
-                    createTreeNodeForChild(child);
-                }
-            });
-            return;
-        }
-        LOGGER.debug(child.getClass().getSimpleName() + " created: " + child);
-
-
-        invokeLater(new Runnable() {
-            @Override
-            public void run() {
-                parentTreeNode.getOrCreateChildTreeNodeFor(child);
-            }
-        });
+		final TreeNode parentTreeNode = (TreeNode) child.getParent().getUserObject();
+		if (parentTreeNode == null) {
+			Dispatching.invokeDispatch(this, manager, new Runnable() {
+				@Override
+				public void run() {
+					createTreeNodeForChild(child);
+				}
+			});
+			return;
+		}
+		log.debug(child.getClass().getSimpleName() + " created: " + child);
+
+
+		invokeLater(new Runnable() {
+			@Override
+			public void run() {
+				parentTreeNode.getOrCreateChildTreeNodeFor(child);
+			}
+		});
 */
 	}
 
 
-    @Override
-    protected Endpoint createEndpoint() {
-        return new BrowserEndpoint();
-    }
+	@Override
+	protected Endpoint createEndpoint() {
+		return new BrowserEndpoint();
+	}
+
+	@Override
+	public Dispatcher createDefaultDispatcher() {
+		return SwingDispatcher.instance;
+	}
+
+	/**
+	 * @return the mainFrame
+	 */
+	public MainFrame getMainFrame() {
+		return mainFrame;
+	}
 
 }
Index: java/main/src/main/java/com/framsticks/gui/BrowserEndpoint.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/BrowserEndpoint.java	(revision 79)
+++ java/main/src/main/java/com/framsticks/gui/BrowserEndpoint.java	(revision 84)
@@ -9,4 +9,5 @@
 
     public BrowserEndpoint() {
+    	
     }
 
Index: java/main/src/main/java/com/framsticks/gui/EmptyPanel.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/EmptyPanel.java	(revision 84)
+++ java/main/src/main/java/com/framsticks/gui/EmptyPanel.java	(revision 84)
@@ -0,0 +1,23 @@
+package com.framsticks.gui;
+
+import com.framsticks.params.AccessInterface;
+
+/**
+ * Author: Piotr Śniegowski
+ */
+@SuppressWarnings("serial")
+public class EmptyPanel extends Panel {
+
+	public EmptyPanel(Parameters parameters) {
+		super(parameters);
+	}
+
+	@Override
+	public void pullValuesFromLocalToUser(AccessInterface access) {
+	}
+
+	@Override
+	public String getTitle() {
+		return "Empty";
+	}
+}
Index: java/main/src/main/java/com/framsticks/gui/EndpointAtFrame.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/EndpointAtFrame.java	(revision 79)
+++ java/main/src/main/java/com/framsticks/gui/EndpointAtFrame.java	(revision 84)
@@ -1,42 +1,176 @@
 package com.framsticks.gui;
 
-import java.util.HashMap;
-import java.util.Map;
+import org.apache.log4j.Logger;
+
+import com.framsticks.core.Instance;
+import com.framsticks.core.InstanceListener;
+import com.framsticks.core.ListChange;
+import com.framsticks.core.Node;
+import com.framsticks.core.Path;
+import com.framsticks.params.CompositeParam;
+import com.framsticks.params.FramsClass;
+
+import java.util.*;
+
+import javax.swing.tree.TreePath;
 
 /**
  * @author Piotr Sniegowski
  */
-public class EndpointAtFrame {
-    protected final BrowserEndpoint endpoint;
-    protected final Frame frame;
-    protected final Map<String, Panel> knownPanels = new HashMap<String, Panel>();
+public class EndpointAtFrame implements InstanceListener {
 
-    public EndpointAtFrame(BrowserEndpoint endpoint, Frame frame) {
-        this.endpoint = endpoint;
-        this.frame = frame;
-    }
+	private static final Logger log = Logger.getLogger(EndpointAtFrame.class);
 
+	protected final BrowserEndpoint endpoint;
+	protected final Frame frame;
+	protected final Instance instance;
+	protected final Map<String, Panel> knownPanels = new HashMap<String, Panel>();
+	protected TreeNode rootTreeNode;
 
-    public BrowserEndpoint getEndpoint() {
-        return endpoint;
-    }
+	public EndpointAtFrame(BrowserEndpoint endpoint, Frame frame) {
+		this.endpoint = endpoint;
+		this.frame = frame;
+		this.instance = endpoint.getInstance();
+	}
 
-    public Frame getFrame() {
-        return frame;
-    }
+	public BrowserEndpoint getEndpoint() {
+		return endpoint;
+	}
 
-    public void registerPanel(Panel panel) {
-        assert frame.isActive();
-        knownPanels.put(panel.getClassName(), panel);
-        frame.cardPanel.add(panel, panel.getFullName());
-    }
+	public Frame getFrame() {
+		return frame;
+	}
 
-    public Panel findPanel(String className) {
-        assert frame.isActive();
-        return (knownPanels.containsKey(className) ? knownPanels.get(className) : null);
-    }
+	public void registerPanel(Panel panel) {
+	}
 
-    public final String getName() {
-        return endpoint.getName();
-    }
+	public Panel findPanel(String accessId) {
+		assert frame.isActive();
+		return (knownPanels.containsKey(accessId) ? knownPanels.get(accessId) : null);
+	}
+
+	public final String getName() {
+		return endpoint.getName();
+	}
+
+	public Panel preparePanel(CompositeParam param, FramsClass framsClass) {
+		assert frame.isActive();
+		Panel panel = preparePanelImpl(param, framsClass);
+		assert panel != null;
+		String accessId = param.computeAccessId();
+		panel.uniqueName = accessId + "@" + endpoint.getName();
+		knownPanels.put(accessId, panel);
+		frame.cardPanel.add(panel, panel.uniqueName);
+		log.debug("prepared panel for " + panel);
+		return panel;
+	}
+
+	protected Panel preparePanelImpl(CompositeParam param, FramsClass framsClass) {
+		assert frame.isActive();
+		List<Panel> panels = new ArrayList<Panel>();
+
+		Panel.Parameters parameters = new Panel.Parameters(this, param,
+				framsClass);
+		for (PanelProvider pp : frame.browser.panelProviders) {
+			Panel p = pp.providePanel(parameters);
+			if (p != null) {
+				panels.add(p);
+			}
+		}
+
+		if (panels.isEmpty()) {
+			return new EmptyPanel(parameters);
+		}
+		if (panels.size() == 1) {
+			return panels.get(0);
+		}
+		return new MultiPanel(parameters, panels);
+
+	}
+
+	@Override
+	public void onListChange(Path path, ListChange change) {
+
+	}
+
+	public TreePath getTreePath(Path path, boolean create) {
+		assert frame.isActive();
+		TreeNode t = rootTreeNode;
+		TreePath result = new TreePath(frame.rootNode).pathByAddingChild(rootTreeNode);
+		List<Node> nodes = path.getNodes();
+		Iterator<Node> i = nodes.iterator();
+		i.next();
+		// Node first = i.next();
+
+		// if (!t.path.isResolved()) {
+		// 	t.path = new Path(path.getInstance(), nodes, first);
+		// }
+		while (i.hasNext()) {
+			Node n = i.next();
+			TreeNode r = null;
+			for (TreeNode c : t.childrenIterable()) {
+				if (c.paramId.equals(n.getParam().getId())) {
+					r = c;
+					break;
+				}
+			}
+			if (r == null) {
+				log.debug("missing " + n.getParam().getId() + " in " + t);
+				if (!create) {
+					return result;
+				}
+				Path p = new Path(path.getInstance(), nodes, n);
+				log.debug("forced resolution: creating treenode for " + p);
+				TreeNode childNode = new TreeNode(EndpointAtFrame.this, p);
+
+				frame.addNode(childNode, t);
+				// frame.treeModel.reload();
+				// t.add(childNode);
+				// frame.treeModel.nodeStructureChanged(t);
+
+				r = childNode;
+			} else {
+				// if (!r.path.isResolved()) {
+				// 	r.path = new Path(path.getInstance(), nodes, n);
+				// }
+			}
+			result = result.pathByAddingChild(r);
+			t = r;
+		}
+		return result;
+	}
+
+	@Override
+	public void onFetch(final Path path) {
+		assert instance.isActive();
+		log.trace("fetched " + path);
+
+		frame.invokeLater(new Runnable() {
+			@Override
+			public void run() {
+
+				TreePath treePath = getTreePath(path, true);
+				assert treePath.getPathCount() == path.size() + 1;
+
+				final TreeNode result = (TreeNode) treePath.getLastPathComponent();
+				// log.trace("found " + result + " == " + path);
+				instance.invokeLater(new Runnable() {
+					@Override
+					public void run() {
+						result.reactForFetchResult(path, null);
+					}
+				});
+			}
+		});
+	}
+
+	@Override
+	public void onRun(Exception e) {
+
+	}
+
+	@Override
+	public void onStop(Exception e) {
+
+	}
 }
Index: java/main/src/main/java/com/framsticks/gui/Frame.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/Frame.java	(revision 79)
+++ java/main/src/main/java/com/framsticks/gui/Frame.java	(revision 84)
@@ -1,20 +1,22 @@
 package com.framsticks.gui;
 
-import com.framsticks.core.Node;
+import com.framsticks.core.Instance;
 import com.framsticks.core.Path;
 import com.framsticks.gui.view.*;
 import com.framsticks.gui.view.TreeCellRenderer;
-import com.framsticks.util.Dispatcher;
+import com.framsticks.util.dispatching.Dispatcher;
+import com.framsticks.util.swing.KeyboardModifier;
 import org.apache.log4j.Logger;
 
 import javax.swing.*;
+import javax.swing.event.TreeModelEvent;
+import javax.swing.event.TreeModelListener;
 import javax.swing.event.TreeSelectionEvent;
 import javax.swing.event.TreeSelectionListener;
 import javax.swing.tree.*;
+
 import java.awt.*;
 import java.awt.datatransfer.StringSelection;
-import java.awt.event.ActionEvent;
-import java.awt.event.MouseAdapter;
-import java.awt.event.MouseEvent;
+import java.awt.event.*;
 import java.util.HashMap;
 import java.util.Map;
@@ -23,265 +25,319 @@
  * @author Piotr Sniegowski
  */
+@SuppressWarnings("serial")
 public class Frame extends JFrame implements Dispatcher {
 
-    private static final Logger LOGGER = Logger.getLogger(Frame.class.getName());
-
-    protected final Browser browser;
-
-    protected final Dimension screenDimension = Toolkit.getDefaultToolkit().getScreenSize();
-
-
-    final protected CardLayout cardPanelLayout = new CardLayout();
-    protected final JPanel cardPanel = new JPanel();
-
-    protected JScrollPane treeScrollPane;
-    protected JTree tree;
-    protected DefaultTreeModel treeModel;
-    protected javax.swing.tree.MutableTreeNode rootNode;
-    //final Instance instance;
-    protected JPanel treePanel;
-    protected  JPopupMenu treePopupMenu;
-    protected JMenuItem treePopupMenuHeader;
-
-    TreeNode currentlyPoppedTreeNode;
-    protected JLabel statusBar;
-    protected JPanel mainPanel;
-    protected JPanel leftPanel;
-    protected JPanel normalWorkPanel;
-    protected CardLayout mainPanelLayout;
-
-    protected final Map<BrowserEndpoint, EndpointAtFrame> endpoints = new HashMap<BrowserEndpoint, EndpointAtFrame>();
-
-    public Frame(String title, Browser browser) {
+	private static final Logger log = Logger.getLogger(Frame.class.getName());
+
+	protected final Browser browser;
+
+	protected final Dimension screenDimension = Toolkit.getDefaultToolkit()
+			.getScreenSize();
+
+	final protected CardLayout cardPanelLayout = new CardLayout();
+	protected final JPanel cardPanel = new JPanel();
+
+	protected JScrollPane treeScrollPane;
+	protected JTree tree;
+	protected DefaultTreeModel treeModel;
+	protected javax.swing.tree.MutableTreeNode rootNode;
+	//final Instance instance;
+	protected JPanel treePanel;
+	protected JPopupMenu treePopupMenu;
+	protected JMenuItem treePopupMenuHeader;
+
+	TreeNode currentlyPoppedTreeNode;
+	protected JLabel statusBar;
+	protected JPanel mainPanel;
+	protected JPanel leftPanel;
+	protected JPanel normalWorkPanel;
+	protected CardLayout mainPanelLayout;
+
+	protected JMenuBar menuBar;
+	protected JMenu fileMenu;
+	protected JMenu editMenu;
+	protected JMenu viewMenu;
+	protected JMenu windowMenu;
+	protected JMenu helpMenu;
+
+	protected final Map<BrowserEndpoint, EndpointAtFrame> endpoints = new HashMap<BrowserEndpoint, EndpointAtFrame>();
+	protected final Map<Instance, EndpointAtFrame> endpointsByInstance = new HashMap<Instance, EndpointAtFrame>();
+
+	public Frame(String title, Browser browser) {
 		super(title);
-        this.browser = browser;
-    }
-
-    public void configure() {
-
-        Container contentPane = this.getContentPane();
-        contentPane.setLayout(new BorderLayout());
-
-        treePopupMenu = new JPopupMenu("title");
-        treePopupMenu.setName("popup");
-        treePopupMenuHeader = new JMenuItem();
-        treePopupMenuHeader.setForeground(Color.BLUE);
-        treePopupMenu.add(treePopupMenuHeader);
-        treePopupMenu.addSeparator();
-        //TODO: add to favourites
-        //TODO: remove from favourites
-        //TODO: open in new window as root
-        //TODO: refresh
-        //TODO: open in console
-
-        treePopupMenu.add(new JMenuItem("Refresh"));
-        treePopupMenu.add(new JMenuItem("Open in new frame as root"));
-		addNodeActionToTreePopupMenu("Copy path to clipboard", new NodeAction() {
-			@Override
-			public void actionPerformed(TreeNode treeNode) {
-				Path path = treeNode.getInstancePath();
-				StringSelection selection = new StringSelection(path.toString());
-				getToolkit().getSystemClipboard().setContents(selection, selection);
-			}
-		});
-        //this.add(createMenuItem("Add to favourites", null));
-        //this.add(createMenuItem("Remove from favourites", null));
-
-        treePanel = new JPanel();
-        treePanel.setLayout(new BorderLayout());
-
-        treeModel = new DefaultTreeModel(null);
-
-        tree = new JTree(treeModel);
-        tree.setRootVisible(false);
-        ToolTipManager.sharedInstance().registerComponent(tree);
-
-        tree.addTreeSelectionListener(new TreeSelectionListener() {
-            @Override
-            public void valueChanged(TreeSelectionEvent e) {
-                chooseTreeNode(e.getNewLeadSelectionPath());
-            }
-        });
-
-        tree.setExpandsSelectedPaths(true);
-        tree.setEditable(false);
-        tree.setDoubleBuffered(true);
-        tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
-        tree.setShowsRootHandles(true);
-        tree.setRowHeight(26);
-        tree.setDoubleBuffered(true);
-        tree.addMouseListener(new MouseAdapter() {
-            @Override
-            public void mousePressed(MouseEvent e) {
-                assert isActive();
-                showPopup(e);
-            }
-
-            @Override
-            public void mouseReleased(MouseEvent e) {
-                assert isActive();
-                showPopup(e);
-            }
-        });
-        tree.setCellRenderer(new TreeCellRenderer());
-
-        treeScrollPane = new JScrollPane(tree);
-        treeScrollPane.setBorder(BorderFactory.createEmptyBorder());
-
-        treePanel.add(treeScrollPane);
-
-        rootNode = new DefaultMutableTreeNode();
-        treeModel.setRoot(rootNode);
-
-        normalWorkPanel = new JPanel();
-        normalWorkPanel.setLayout(new BorderLayout());
-
-        mainPanel = new JPanel();
-        mainPanelLayout = new CardLayout();
-        mainPanel.setLayout(mainPanelLayout);
-        mainPanel.add(normalWorkPanel, "browser");
-
-        contentPane.add(createMenu(), BorderLayout.NORTH);
-        contentPane.add(mainPanel, BorderLayout.CENTER);
-        contentPane.add(statusBar, BorderLayout.SOUTH);
-
-        leftPanel = new JPanel();
-        leftPanel.setLayout(new BorderLayout());
-        JPanel leftTopPanel = createLeftTopPanel();
-        if (leftTopPanel != null) {
-            leftPanel.add(leftTopPanel, BorderLayout.PAGE_START);
-        }
-        leftPanel.add(treePanel, BorderLayout.CENTER);
-        leftPanel.setBackground(Color.WHITE);
-        leftPanel.setForeground(Color.WHITE);
-
-        JSplitPane split = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, leftPanel, cardPanel);
-        split.setPreferredSize(new Dimension(this.browser.getConfig().getInteger("size.width", 1000), this.browser.getConfig().getInteger("size.height", 500)));
-        split.setMaximumSize(screenDimension);
-        split.setOneTouchExpandable(true);
-        split.setDividerLocation(250);
-        split.setDividerSize(5);
-
-        normalWorkPanel.add(split);
-
-        //this.setVisible(true);
-        mainPanelLayout.show(mainPanel, "browser");
-
-        cardPanel.setLayout(cardPanelLayout);
+		/** this is done to remove the current value label from above the slider,
+		 * because it cannot put to work properly with floating-point value sliders,
+		 * nor it can be removed in normal way through JSlider methods  */
+		UIManager.put("Slider.paintValue", false);
+		this.browser = browser;
+		log.debug("creating " + this);
+	}
+
+	public void configure() {
+
+		Container contentPane = this.getContentPane();
+		contentPane.setLayout(new BorderLayout());
+
+		treePopupMenu = new JPopupMenu("title");
+		treePopupMenu.setName("popup");
+		treePopupMenuHeader = new JMenuItem();
+		treePopupMenuHeader.setForeground(Color.BLUE);
+		treePopupMenu.add(treePopupMenuHeader);
+		treePopupMenu.addSeparator();
+		//TODO: add to favourites
+		//TODO: remove from favourites
+		//TODO: open in new window as root
+		//TODO: refresh
+		//TODO: open in console
+
+		treePopupMenu.add(new JMenuItem("Refresh"));
+		treePopupMenu.add(new JMenuItem("Open in new frame as root"));
+		addNodeActionToTreePopupMenu("Copy path to clipboard",
+				new NodeAction() {
+					@Override
+					public void actionPerformed(TreeNode treeNode) {
+						Path path = treeNode.getInstancePath();
+						StringSelection selection = new StringSelection(path
+								.toString());
+						getToolkit().getSystemClipboard().setContents(
+								selection, selection);
+					}
+				});
+		//this.add(createMenuItem("Add to favourites", null));
+		//this.add(createMenuItem("Remove from favourites", null));
+
+		treePanel = new JPanel();
+		treePanel.setLayout(new BorderLayout());
+
+		treeModel = new DefaultTreeModel(null);
+		treeModel.addTreeModelListener(new TreeModelListener() {
+
+			@Override
+			public void treeNodesChanged(TreeModelEvent arg0) {
+				log.trace("treeNodesChanged: " + arg0);
+			}
+
+			@Override
+			public void treeNodesInserted(TreeModelEvent arg0) {
+				// log.trace("treeNodesInserted: " + arg0);
+			}
+
+			@Override
+			public void treeNodesRemoved(TreeModelEvent arg0) {
+				log.trace("treeNodesRemoved: " + arg0);
+			}
+
+			@Override
+			public void treeStructureChanged(TreeModelEvent arg0) {
+				log.trace("treeStructureChanged: " + arg0);
+			}
+		});
+
+		tree = new JTree(treeModel);
+		tree.setName("tree");
+		tree.setRootVisible(false);
+		tree.setExpandsSelectedPaths(true);
+		tree.setSelectionModel(new DefaultTreeSelectionModel());
+		ToolTipManager.sharedInstance().registerComponent(tree);
+
+		tree.addTreeSelectionListener(new TreeSelectionListener() {
+			@Override
+			public void valueChanged(TreeSelectionEvent e) {
+				chooseTreeNode(e.getNewLeadSelectionPath());
+			}
+		});
+
+		tree.setExpandsSelectedPaths(true);
+		tree.setEditable(false);
+		tree.setDoubleBuffered(true);
+		tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
+		tree.setShowsRootHandles(true);
+		tree.setRowHeight(26);
+		tree.setDoubleBuffered(true);
+		tree.addMouseListener(new MouseAdapter() {
+			@Override
+			public void mousePressed(MouseEvent e) {
+				assert isActive();
+				showPopup(e);
+			}
+
+			@Override
+			public void mouseReleased(MouseEvent e) {
+				assert isActive();
+				showPopup(e);
+			}
+		});
+
+		new KeyboardModifier(tree, JComponent.WHEN_FOCUSED)
+			.join(KeyStroke.getKeyStroke('h'), KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0))
+			.join(KeyStroke.getKeyStroke('j'), KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0))
+			.join(KeyStroke.getKeyStroke('k'), KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0))
+			.join(KeyStroke.getKeyStroke('l'), KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0))
+			;
+
+		tree.setCellRenderer(new TreeCellRenderer());
+
+		treeScrollPane = new JScrollPane(tree);
+		treeScrollPane.setBorder(BorderFactory.createEmptyBorder());
+
+		treePanel.add(treeScrollPane);
+
+		rootNode = new DefaultMutableTreeNode();
+		rootNode.setUserObject("root");
+		treeModel.setRoot(rootNode);
+
+		normalWorkPanel = new JPanel();
+		normalWorkPanel.setLayout(new BorderLayout());
+		normalWorkPanel.setName("browser");
+
+		mainPanel = new JPanel();
+		mainPanel.setName("main");
+		mainPanelLayout = new CardLayout();
+		mainPanel.setLayout(mainPanelLayout);
+		mainPanel.add(normalWorkPanel, "browser");
+
+		menuBar = new JMenuBar();
+
+		fileMenu = menuBar.add(new JMenu("File"));
+		editMenu = menuBar.add(new JMenu("Edit"));
+		viewMenu = menuBar.add(new JMenu("View"));
+		windowMenu = menuBar.add(new JMenu("Window"));
+		helpMenu = menuBar.add(new JMenu("Help"));
+
+		contentPane.add(menuBar, BorderLayout.NORTH);
+		contentPane.add(mainPanel, BorderLayout.CENTER);
+		contentPane.add(statusBar, BorderLayout.SOUTH);
+
+		leftPanel = new JPanel();
+		leftPanel.setLayout(new BorderLayout());
+		//leftPanel.add(new ViewerTest(), BorderLayout.PAGE_START);
+//        JPanel leftTopPanel = createLeftTopPanel();
+//        if (leftTopPanel != null) {
+//            leftPanel.add(leftTopPanel, BorderLayout.PAGE_START);
+//        }
+		leftPanel.add(treePanel, BorderLayout.CENTER);
+		leftPanel.setBackground(Color.WHITE);
+		leftPanel.setForeground(Color.WHITE);
+
+		cardPanel.setName("card");
+		JSplitPane split = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, leftPanel, cardPanel);
+		split.setPreferredSize(browser.defaultFrameDimension);
+		split.setMaximumSize(screenDimension);
+		split.setOneTouchExpandable(true);
+		split.setDividerLocation(250);
+		split.setDividerSize(5);
+		split.setName("split");
+
+		normalWorkPanel.add(split);
+
+		//this.setVisible(true);
+		mainPanelLayout.show(mainPanel, "browser");
+
+		cardPanel.setLayout(cardPanelLayout);
 
 		this.pack();
 		tree.requestFocusInWindow();
 
-    }
-
-    protected JMenuBar createMenu() {
-        return new JMenuBar();
-    }
-
-    protected JPanel createLeftTopPanel() {
-        return null;
-    }
-
-    public void repaintTree() {
-        //LOGGER.debug("repainting");
-        //tree.repaint();
-    }
-
-    public EndpointAtFrame getOrCreateEndpointAtFrame(BrowserEndpoint endpoint) {
-        assert isActive();
-        if (endpoints.containsKey(endpoint)) {
-            return endpoints.get(endpoint);
-        }
-        EndpointAtFrame e = new EndpointAtFrame(endpoint, this);
-        endpoints.put(endpoint, e);
-        return e;
-    }
-
-    public void addRootPath(BrowserEndpoint endpoint, Path path) {
-        assert isActive();
-        TreeNode node = new TreeNode(this, getOrCreateEndpointAtFrame(endpoint), path);
-        treeModel.insertNodeInto(node, rootNode, rootNode.getChildCount());
-        tree.expandPath(new TreePath(rootNode));
-    }
-
-    @Override
-    public boolean isActive() {
-        return SwingDispatcher.instance.isActive();
-    }
-
-    @Override
-    public void invokeLater(Runnable runnable) {
-        SwingDispatcher.instance.invokeLater(runnable);
-    }
-
-    public Action addActionToTreePopupMenu(Action action) {
-        assert isActive();
-        treePopupMenu.add(action);
-        return action;
-    }
-
-    public Action addNodeActionToTreePopupMenu(String title, final NodeAction nodeAction) {
-        assert isActive();
-        return addActionToTreePopupMenu(new AbstractAction(title) {
-            @Override
-            public void actionPerformed(ActionEvent e) {
-                TreeNode treeNode = getCurrentlyPoppedTreeNode();
-                if (treeNode == null) {
-                    return;
-                }
-                nodeAction.actionPerformed(treeNode);
-            }
-        });
-    }
-
-
-    public void showPanel(Panel panel) {
-        assert isActive();
-        assert panel != null;
-        cardPanelLayout.show(cardPanel, panel.getFullName());
-    }
-
-    private void showPopup(MouseEvent e) {
-        assert isActive();
-        if (!e.isPopupTrigger()) {
-            return;
-        }
-        currentlyPoppedTreeNode = findTreeNodeByTreePath(tree.getPathForLocation(e.getX(), e.getY()));
-        if (currentlyPoppedTreeNode == null) {
-            return;
-        }
-        treePopupMenu.show(e.getComponent(), e.getX(), e.getY());
-        //currentlyPoppedPanel.getNode().getFramsClass().getName()
-        //treePopupMenuHeader.setText(currentlyPoppedTreeNode.getNode().getPath());
-    }
-
-    public TreeNode getCurrentlyPoppedTreeNode() {
-        assert isActive();
-        return currentlyPoppedTreeNode;
-    }
-
-
-    public void clear() {
-        treeModel.setRoot(null);
-        cardPanel.removeAll();
-        cardPanel.updateUI();
-        tree.setEnabled(false);
-    }
-
-
-    public void markNodeChanged(MutableTreeNode treeNode, TreePath path) {
-        assert isActive();
-        treeModel.nodeStructureChanged(treeNode);
-        tree.setSelectionPath(path);
-        tree.repaint();
-    }
-
-    public TreePath startChange() {
-        return tree.getSelectionPath();
-    }
-
-
-    public void selectTreeNode(final TreeNode treeNode) {
-        assert isActive();
+		log.debug("frame configured");
+
+	}
+
+	protected JPanel createLeftTopPanel() {
+		return null;
+	}
+
+	public void addRootPath(BrowserEndpoint endpoint, Path path) {
+		assert isActive();
+		assert !endpoints.containsKey(endpoint);
+
+		EndpointAtFrame e = new EndpointAtFrame(endpoint, this);
+		endpoint.getInstance().addListener(e);
+		endpoints.put(endpoint, e);
+		endpointsByInstance.put(endpoint.getInstance(), e);
+		TreeNode node = new TreeNode(e, path);
+		e.rootTreeNode = node;
+		treeModel.insertNodeInto(node, rootNode, rootNode.getChildCount());
+		tree.expandPath(new TreePath(rootNode));
+	}
+
+	@Override
+	public boolean isActive() {
+		return SwingDispatcher.instance.isActive();
+	}
+
+	@Override
+	public void invokeLater(Runnable runnable) {
+		SwingDispatcher.instance.invokeLater(runnable);
+	}
+
+	public Action addActionToTreePopupMenu(Action action) {
+		assert isActive();
+		treePopupMenu.add(action);
+		return action;
+	}
+
+	public Action addNodeActionToTreePopupMenu(String title, final NodeAction nodeAction) {
+		assert isActive();
+		return addActionToTreePopupMenu(new AbstractAction(title) {
+			@Override
+			public void actionPerformed(ActionEvent e) {
+				TreeNode treeNode = getCurrentlyPoppedTreeNode();
+				if (treeNode == null) {
+					return;
+				}
+				nodeAction.actionPerformed(treeNode);
+			}
+		});
+	}
+
+	public void showPanel(Panel panel) {
+		assert isActive();
+		assert panel != null;
+		cardPanelLayout.show(cardPanel, panel.getUniqueName());
+	}
+
+
+	private void showPopup(MouseEvent e) {
+		assert isActive();
+		if (!e.isPopupTrigger()) {
+			return;
+		}
+		currentlyPoppedTreeNode = findTreeNodeByTreePath(tree.getPathForLocation(e.getX(), e.getY()));
+		if (currentlyPoppedTreeNode == null) {
+			return;
+		}
+		treePopupMenu.show(e.getComponent(), e.getX(), e.getY());
+		//currentlyPoppedPanel.getNode().getFramsClass().getName()
+		//treePopupMenuHeader.setText(currentlyPoppedTreeNode.getNode().getPath());
+	}
+
+	public TreeNode getCurrentlyPoppedTreeNode() {
+		assert isActive();
+		return currentlyPoppedTreeNode;
+	}
+
+
+	public void clear() {
+		treeModel.setRoot(null);
+		cardPanel.removeAll();
+		cardPanel.updateUI();
+		tree.setEnabled(false);
+	}
+
+	public Runnable startChange(final DefaultMutableTreeNode node) {
+		assert isActive();
+		final TreePath selection = tree.getSelectionPath();
+		return new Runnable() {
+			@Override
+			public void run() {
+				assert isActive();
+				treeModel.nodeChanged(node);
+				tree.setSelectionPath(selection);
+			}
+		};
+	}
+
+	public void selectTreeNode(final TreeNode treeNode) {
+		assert isActive();
 /*		final Panel panel = treeNode.getOrCreatePanel();
 		if (panel == null) {
@@ -291,28 +347,53 @@
 		treeNode.updateData();
 		showPanel(panel);*/
-    }
-
-    public TreeNode findTreeNodeByTreePath(TreePath treePath) {
-        assert isActive();
-        if (treePath == null) {
-            return null;
-        }
-        if (!(treePath.getLastPathComponent() instanceof TreeNode)) {
-            return null;
-        }
-        return (TreeNode)treePath.getLastPathComponent();
-    }
-
-
-
-    public void chooseTreeNode(TreePath treePath) {
-        assert isActive();
-        final TreeNode treeNode = findTreeNodeByTreePath(treePath);
-        if (treeNode == null) {
-            return;
-        }
-        treeNode.select();
-    }
-
+	}
+
+	public TreeNode findTreeNodeByTreePath(TreePath treePath) {
+		assert isActive();
+		if (treePath == null) {
+			return null;
+		}
+		if (!(treePath.getLastPathComponent() instanceof TreeNode)) {
+			return null;
+		}
+		return (TreeNode)treePath.getLastPathComponent();
+	}
+
+	public void chooseTreeNode(TreePath treePath) {
+		assert isActive();
+		final TreeNode treeNode = findTreeNodeByTreePath(treePath);
+		if (treeNode == null) {
+			return;
+		}
+		treeNode.select();
+	}
+
+	public void goTo(Path path) {
+		assert isActive();
+		final TreePath treePath = endpointsByInstance.get(path.getInstance()).getTreePath(path, false);
+		log.info("go to path: " + path + "(" + treePath + ")");
+		invokeLater(new Runnable() {
+			@Override
+			public void run() {
+				tree.setSelectionPath(treePath);
+				tree.makeVisible(treePath);
+				assert tree.isVisible(treePath);
+			}
+
+		});
+	}
+
+
+	public void addNode(TreeNode child, DefaultMutableTreeNode parent) {
+		assert isActive();
+		Runnable r = startChange(parent);
+		treeModel.insertNodeInto(child, parent, parent.getChildCount());
+		r.run();
+	}
+
+	@Override
+	public String toString() {
+		return getTitle() + "@" + browser.getName();
+	}
 
 }
Index: java/main/src/main/java/com/framsticks/gui/Gui.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/Gui.java	(revision 84)
+++ java/main/src/main/java/com/framsticks/gui/Gui.java	(revision 84)
@@ -0,0 +1,127 @@
+package com.framsticks.gui;
+
+import java.awt.Dimension;
+import java.util.Collection;
+import java.util.Map;
+
+import javax.swing.Box;
+import javax.swing.BoxLayout;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+
+import org.apache.log4j.Logger;
+
+import com.framsticks.gui.controls.CheckBoxControl;
+import com.framsticks.gui.controls.Control;
+import com.framsticks.gui.controls.EnumControl;
+import com.framsticks.gui.controls.EventControl;
+import com.framsticks.gui.controls.ProcedureControl;
+import com.framsticks.gui.controls.SliderControl;
+import com.framsticks.gui.controls.TextAreaControl;
+import com.framsticks.gui.controls.TextFieldControl;
+import com.framsticks.params.CompositeParam;
+import com.framsticks.params.Param;
+import com.framsticks.params.PrimitiveParam;
+import com.framsticks.params.types.BinaryParam;
+import com.framsticks.params.types.BooleanParam;
+import com.framsticks.params.types.ColorParam;
+import com.framsticks.params.types.DecimalParam;
+import com.framsticks.params.types.EnumParam;
+import com.framsticks.params.types.EventParam;
+import com.framsticks.params.types.FloatParam;
+import com.framsticks.params.types.ProcedureParam;
+import com.framsticks.params.types.StringParam;
+import com.framsticks.params.types.UniversalParam;
+import com.framsticks.util.lang.Strings;
+
+public final class Gui {
+
+	private static final Logger log = Logger.getLogger(Gui.class.getName());
+
+	private Gui() {
+	}
+
+	public static Control createComponentForText(PrimitiveParam valueParam) {
+		if (valueParam.getMin(Object.class) != null) {
+			return new TextAreaControl(valueParam);
+		}
+		return new TextFieldControl(valueParam);
+	}
+
+	public static Control createSuitable(Param param) {
+
+		if (param instanceof EnumParam) {
+			return new EnumControl((EnumParam) param);
+		}
+		if (param instanceof BooleanParam) {
+			return new CheckBoxControl((BooleanParam) param);
+		}
+		if (param instanceof DecimalParam) {
+			DecimalParam decimalParam = (DecimalParam)param;
+			if (decimalParam.getMin(Integer.class) != null && decimalParam.getMax(Integer.class) != null) {
+				return new SliderControl(decimalParam);
+			}
+			return createComponentForText(decimalParam);
+		}
+		if (param instanceof FloatParam) {
+			FloatParam floatParam = (FloatParam)param;
+			if (floatParam.getMin(Double.class) != null && floatParam.getMax(Double.class) != null) {
+				return new SliderControl(floatParam);
+			}
+			return createComponentForText(floatParam);
+		}
+		if (param instanceof StringParam) {
+			return createComponentForText((StringParam)param);
+		}
+		if (param instanceof ProcedureParam) {
+			return new ProcedureControl((ProcedureParam)param);
+		}
+		if (param instanceof BinaryParam) {
+			return createComponentForText((BinaryParam)param);
+		}
+		if (param instanceof ColorParam) {
+			return createComponentForText((ColorParam) param);
+		}
+		if (param instanceof UniversalParam) {
+			return new TextAreaControl((UniversalParam)param);
+		}
+		if (param instanceof EventParam) {
+			return new EventControl((EventParam)param);
+		}
+		return null;
+	}
+
+	public static void fillWithControls(JPanel panel, Collection<Param> params, Map<Param, Control> components) {
+		for (Param param : params) {
+			if (param.isUserHidden()) {
+				continue;
+			}
+			assert !(param instanceof CompositeParam);
+			Control control = Gui.createSuitable(param);
+			if (control == null) {
+				log.error("component for param " + param + " of type " + param.getClass().getSimpleName() + " was not added");
+				continue;
+			}
+			log.debug("add component for " + param);
+			JPanel line = new JPanel();
+			line.setLayout(new BoxLayout(line, BoxLayout.LINE_AXIS));
+			line.setAlignmentX(JPanel.LEFT_ALIGNMENT);
+			JLabel label = new JLabel(Strings.notEmpty(param.getName()) ? param.getName() : "? (" + param.getId() + ")");
+			label.setToolTipText(control.getToolTipText());
+			label.setHorizontalAlignment(JLabel.RIGHT);
+			Dimension labelSize = new Dimension(150, 30);
+			label.setMaximumSize(labelSize);
+			label.setMinimumSize(labelSize);
+			label.setPreferredSize(labelSize);
+			line.add(label);
+			line.add(Box.createRigidArea(new Dimension(8, 0)));
+			line.add(control);
+			line.revalidate();
+			panel.add(line);
+			panel.add(Box.createRigidArea(new Dimension(0, 8)));
+			//component.setAlignmentX(LEFT_ALIGNMENT);
+			components.put(param, control);
+		}
+
+	}
+}
Index: java/main/src/main/java/com/framsticks/gui/ImageProvider.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/ImageProvider.java	(revision 79)
+++ java/main/src/main/java/com/framsticks/gui/ImageProvider.java	(revision 84)
@@ -7,5 +7,4 @@
 
 import javax.swing.*;
-import java.net.URL;
 import java.util.HashMap;
 import java.util.LinkedHashMap;
@@ -16,5 +15,5 @@
 public class ImageProvider {
 
-    private final static Logger LOGGER = Logger.getLogger(ImageProvider.class.getName());
+    private final static Logger log = Logger.getLogger(ImageProvider.class.getName());
 
 
@@ -87,5 +86,5 @@
             return icon;
 		} catch (Exception ignored) {
-            LOGGER.error("failed to read icon: " + resourceName);
+            log.error("failed to read icon: " + resourceName);
 		}
 		return null;
Index: java/main/src/main/java/com/framsticks/gui/ListPanel.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/ListPanel.java	(revision 79)
+++ java/main/src/main/java/com/framsticks/gui/ListPanel.java	(revision 84)
@@ -12,13 +12,13 @@
  */
 @SuppressWarnings("serial")
-public class ListPanel extends Panel {
+public class ListPanel extends ModifiablePanel {
 
-	private static final Logger LOGGER = Logger.getLogger(ListPanel.class.getName());
+	private static final Logger log = Logger.getLogger(ListPanel.class.getName());
 
 	final protected TableModel tableModel = new TableModel();
 	final protected JTable table = new JTable(tableModel);
 
-	public ListPanel(EndpointAtFrame endpoint) {
-		super(endpoint, "list");
+	public ListPanel(Parameters parameters) {
+		super(parameters);
 
 		table.getTableHeader().setReorderingAllowed(false);
@@ -29,8 +29,10 @@
 		contentPanel.add(table);
 
-        /*
+		log.debug("created");
+
+		/*
 		AccessInterface elementAccess = ((ListAccess)access).getElementAccess();
 		if (elementAccess == null) {
-			LOGGER.error("no type class");
+			log.error("no type class");
 			return;
 		}
@@ -50,5 +52,5 @@
 		}
 		tableModel.addRow(list.toArray());
-        */
+		*/
 		/*
 		JMenuBar menuBar = new JMenuBar();
@@ -105,6 +107,11 @@
 
 	@Override
-	public void refreshComponents(AccessInterface access) {
+	public void pullValuesFromLocalToUser(AccessInterface access) {
 
 	}
+
+	@Override
+	public String getTitle() {
+		return "List";
+	}
 }
Index: java/main/src/main/java/com/framsticks/gui/MainFrame.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/MainFrame.java	(revision 79)
+++ java/main/src/main/java/com/framsticks/gui/MainFrame.java	(revision 84)
@@ -1,7 +1,6 @@
 package com.framsticks.gui;
 
-import com.framsticks.gui.components.Control;
-import com.framsticks.gui.view.*;
 import com.framsticks.gui.windows.console.ConsoleFrame;
+import com.framsticks.util.swing.MenuConstructor;
 import org.apache.log4j.Logger;
 
@@ -11,4 +10,5 @@
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
+import java.awt.event.KeyEvent;
 import java.awt.event.WindowAdapter;
 import java.awt.event.WindowEvent;
@@ -17,7 +17,8 @@
  * Application Main Frame.
  */
+@SuppressWarnings("serial")
 public class MainFrame extends Frame {
 
-	private final static Logger LOGGER = Logger.getLogger(MainFrame.class.getName());
+	private final static Logger log = Logger.getLogger(MainFrame.class.getName());
 
 	JButton start, stop, step;
@@ -28,96 +29,128 @@
 	public MainFrame(final Browser browser) {
 		super("Framsticks Network Client", browser);
-		LOGGER.debug("creating main frame");
+		log.debug("creating main frame");
 
 		statusBar = new JLabel("not connected");
-
-
-	}
+	}
+
 
 	@Override
 	public void configure() {
 		super.configure();
+
+		new MenuConstructor(fileMenu)
+			.add(null, new AbstractAction("Console") {
+				@Override
+				public void actionPerformed(ActionEvent actionEvent) {
+					showConsoleFrame();
+				}
+			})
+			.add(KeyStroke.getKeyStroke(KeyEvent.VK_G, ActionEvent.CTRL_MASK), new AbstractAction("Goto") {
+				@Override
+				public void actionPerformed(ActionEvent actionEvent) {
+					browser.autoResolvePath("/simulator/genepools/groups/0", null);
+					// browser.autoResolvePath("/simulator/populations/groups/0", null;
+					// browser.autoResolvePath("/simulator/genepools/groups/0/genotypes", null);
+					// browser.autoResolvePath("/simulator/populations/groups", null);
+				}
+			})
+			.add(null, new AbstractAction("Disconnect") {
+				@Override
+				public void actionPerformed(ActionEvent actionEvent) {
+					disconnect();
+				}
+			})
+			.add(null, new AbstractAction("Quit") {
+				@Override
+				public void actionPerformed(ActionEvent actionEvent) {
+				}
+			})
+			;
+
 		setFrameProperties();
 	}
 
-	private void onConnectionEstablished() {
-        assert isActive();
-
-        addNodeActionToTreePopupMenu("Open in console", new NodeAction() {
-            @Override
-            public void actionPerformed(TreeNode treeNode) {
-                assert isActive();
-                //showConsoleFrame().setCommandLine("info " + treeNode.getNode().getPath());
-            }
-        });
-
-
-
-/*
-        browser.addNodeActionToTreePopupMenu("Resolve recursively", new NodeAction() {
-            @Override
-            public void actionPerformed(TreeNode treeNode) {
-                final Child child = treeNode.getChild();
-                //server.invokeLater(new Runnable() {
-                    @Override
-                    public void run() {
-                        resolveRecursively(child);
-                    }
-                });
-            }
-        });
-*/
-
-        addNodeActionToTreePopupMenu("Store in file", new NodeAction() {
-            @Override
-            public void actionPerformed(final TreeNode treeNode) {
-
-/*
-                final Node node = treeNode.getNode();
-                server.invokeLater(new Runnable() {
-                    @Override
-                    public void run() {
-                        try {
-                            LOGGER.info("storing");
-                            //File file = new File();
-                            PrintStream file = new PrintStream("/home/piotr/Desktop/test.param");
-                            StoreStream stream = new StoreStream(file, server.getManager());
-                            stream.store(node);
-
-                        } catch (FileNotFoundException e) {
-                            e.printStackTrace();
-                        }
-                    }
-                });
-*/
-            }
-        });
-
-/*
-        arguments.forEach("resolve", new UnaryFunctor<Boolean, String>() {
-            @Override
-            public Boolean call(final String s) {
-                server.getManager().resolvePath(s, new StateFunctor() {
-                    @Override
-                    public void call(Exception e) {
-                        if (e != null) {
-                            LOGGER.error("failed to resolve: " + s);
-                            return;
-                        }
-                        LOGGER.info("succeeded to resolve: " + s);
-
-                    }
-                });
-                return true;
-            }
-        });
-*/
-
-        /*
-        arguments.forEach("console", new UnaryFunctor<Boolean, String>() {
+	// private void onConnectionEstablished() {
+		// assert isActive();
+
+		// addNodeActionToTreePopupMenu("Open in console", new NodeAction() {
+			// @Override
+			// public void actionPerformed(TreeNode treeNode) {
+				// assert isActive();
+			// }
+		// });
+
+
+
+
+	// 	// browser.addNodeActionToTreePopupMenu("Resolve recursively", new NodeAction() {
+	// 	// 	@Override
+	// 	// 	public void actionPerformed(TreeNode treeNode) {
+	// 	// 		final Child child = treeNode.getChild();
+	// 	// 		//server.invokeLater(new Runnable() {
+	// 		// 		@Override
+	// 		// 		public void run() {
+	// 		// 			resolveRecursively(child);
+	// 		// 		}
+	// 		// 	});
+	// 	// }
+	// 	// });
+
+
+		// // addNodeActionToTreePopupMenu("Store in file", new NodeAction() {
+		// //     @Override
+		// //     public void actionPerformed(final TreeNode treeNode) {
+		// //         // final Node node = treeNode.getNode();
+		// //         // server.invokeLater(new Runnable() {
+		// //         //     @Override
+		// //         //     public void run() {
+		// //         //         try {
+		// //         //             log.info("storing");
+		// //         //             //File file = new File();
+		// //         //             StoreStream stream = new StoreStream(file, server.getManager());
+		// //         //             stream.store(node);
+		// //         //         } catch (FileNotFoundException e) {
+		// //         //             e.printStackTrace();
+		// //         //         }
+		// //         //     }
+		// //         // });
+		// //     }
+		// // });
+
+
+	// 	// arguments.forEach("resolve", new UnaryFunctor<Boolean, String>() {
+	// 	// 	@Override
+	// 	// 	public Boolean call(final String s) {
+	// 	// 		server.getManager().resolvePath(s, new StateFunctor() {
+	// 	// 			@Override
+	// 	// 			public void call(Exception e) {
+	// 	// 				if (e != null) {
+	// 	// 					log.error("failed to resolve: " + s);
+	// 	// 					return;
+	// 	// 				}
+	// 	// 				log.info("succeeded to resolve: " + s);
+	// 	// 			}
+	// 	// 		});
+	// 	// 		return true;
+	// 	// 	}
+	// 	// });
+
+
+	// 	// arguments.forEach("console", new UnaryFunctor<Boolean, String>() {
+	// 	// 	@Override
+	// 	// 	public Boolean call(String s) {
+	// 	// 		showConsoleFrame().setCommandLine(s);
+	// 	// 		return true;
+	// 	// 	}
+	// 	// });
+	// }
+
+	public void setSimulationRunning(final boolean run) {
+		assert isActive();
+		/*
+		remoteInstance.invokeLater(new Runnable() {
 			@Override
-			public Boolean call(String s) {
-				showConsoleFrame().setCommandLine(s);
-				return true;
+			public void run() {
+				remoteInstance.setRunning(run);
 			}
 		});
@@ -125,23 +158,11 @@
 	}
 
-	public void setSimulationRunning(final boolean run) {
-        assert isActive();
-        /*
-        remoteInstance.invokeLater(new Runnable() {
-            @Override
-            public void run() {
-                remoteInstance.setRunning(run);
-            }
-        });
-        */
-	}
-
 	/**
 	 * Creates panel with start, step, stop buttons.
 	 */
-    @Override
+	@Override
 	protected JPanel createLeftTopPanel() {
-        assert isActive();
-        Dimension buttonDimension = new Dimension(45, 45);
+		assert isActive();
+		Dimension buttonDimension = new Dimension(45, 45);
 
 		JPanel panel = new JPanel();
@@ -161,5 +182,5 @@
 
 		step = new JButton(ImageProvider.loadImage(ImageProvider.SIM_STEP));
-        /*
+		/*
 		step.addActionListener(new ActionListener() {
 
@@ -212,6 +233,6 @@
 	 */
 	private void setFrameProperties() {
-        assert isActive();
-        setMinimumSize(this.getPreferredSize());
+		assert isActive();
+		setMinimumSize(this.getPreferredSize());
 		setSize(this.getPreferredSize());
 		setMaximumSize(screenDimension);
@@ -224,7 +245,7 @@
 		addWindowListener(new WindowAdapter() {
 			public void windowClosing(WindowEvent e) {
-                assert isActive();
-                /*
-                if (connection != null) {
+				assert isActive();
+				/*
+				if (connection != null) {
 					connection.close();
 				}
@@ -237,58 +258,11 @@
 
 	public ConsoleFrame showConsoleFrame() {
-        assert isActive();
-        /*
-        ConsoleFrame consoleFrame = new ConsoleFrame(connection);
+		assert isActive();
+		/*
+		ConsoleFrame consoleFrame = new ConsoleFrame(connection);
 		consoleFrame.show(MainFrame.this);
 		return consoleFrame;
 		*/
-        return null;
-	}
-
-	/**
-	 * Creates menu bar.
-	 *
-	 * @return JMenuBar Menu bar.
-	 */
-    @Override
-	protected JMenuBar createMenu() {
-        assert isActive();
-        final JMenuBar menuBar = new JMenuBar();
-		final JMenu menu = new JMenu("Main");
-
-		final JMenuItem consoleItem = new JMenuItem("Console");
-		consoleItem.addActionListener(new ActionListener() {
-
-			public void actionPerformed(ActionEvent e) {
-				showConsoleFrame();
-			}
-
-		});
-
-        /*
-		final JMenuItem serverLogItem = new JMenuItem("Sever Log");
-		serverLogItem.addActionListener(new ActionListener() {
-
-			public void actionPerformed(ActionEvent e) {
-				serverLogFrame.show(MainFrame.this);
-			}
-
-		});
-		*/
-
-		final JMenuItem disconnectItem = new JMenuItem("Disconnect");
-		disconnectItem.addActionListener(new ActionListener() {
-
-			public void actionPerformed(ActionEvent e) {
-				disconnect();
-			}
-		});
-
-		/** @todo do something proper with UI on close */
-		menu.add(consoleItem);
-		//menu.add(serverLogItem);
-		menu.add(disconnectItem);
-		menuBar.add(menu);
-		return menuBar;
+		return null;
 	}
 
@@ -297,6 +271,6 @@
 	 */
 	private void disconnect() {
-        assert isActive();
-        //remoteInstance.disconnect();
+		assert isActive();
+		//remoteInstance.disconnect();
 		browser.clear();
 		onWindowClosing();
@@ -308,11 +282,11 @@
 	 */
 	private void onWindowClosing() {
-        assert isActive();
+		assert isActive();
 
 	}
 
 	public void setRunningButtons(boolean running) {
-        assert isActive();
-        step.setEnabled(!running);
+		assert isActive();
+		step.setEnabled(!running);
 		stop.setEnabled(running);
 		start.setEnabled(!running);
Index: java/main/src/main/java/com/framsticks/gui/ModifiablePanel.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/ModifiablePanel.java	(revision 84)
+++ java/main/src/main/java/com/framsticks/gui/ModifiablePanel.java	(revision 84)
@@ -0,0 +1,72 @@
+package com.framsticks.gui;
+
+import org.apache.log4j.Logger;
+
+import javax.swing.*;
+import java.awt.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+/**
+ * @author Piotr Sniegowski
+ */
+@SuppressWarnings("serial")
+public abstract class ModifiablePanel extends Panel {
+
+	private static final Logger log = Logger.getLogger(ModifiablePanel.class.getName());
+
+	/**
+	 * Pane to which components will be added.
+	 */
+	protected JPanel contentPanel;
+
+	final protected JLabel label;
+	final protected JButton applyButton;
+
+	public ModifiablePanel(Panel.Parameters parameters) {
+		super(parameters);
+		log.debug("create panel for type: " + className);
+
+
+		contentPanel = new JPanel();
+		contentPanel.setLayout(new BoxLayout(contentPanel, BoxLayout.PAGE_AXIS));
+		JScrollPane scroll = new JScrollPane(contentPanel);
+		//scroll.setBorder(BorderFactory.createEtchedBorder());
+
+		JPanel pageEndPanel = new JPanel();
+		pageEndPanel.setLayout(new BoxLayout(pageEndPanel, BoxLayout.X_AXIS));
+		pageEndPanel.add(Box.createHorizontalGlue());
+
+		applyButton = new JButton("Apply");
+		applyButton.addActionListener(new ActionListener() {
+			public void actionPerformed(ActionEvent e) {
+				applyChanges();
+			}
+		});
+		pageEndPanel.add(applyButton);
+
+		pageEndPanel.add(Box.createHorizontalStrut(10));
+		pageEndPanel.setPreferredSize(new Dimension(0, 30));
+
+		label = new JLabel();
+		JPanel centerPanel = new JPanel();
+		centerPanel.setLayout(new BorderLayout());
+		centerPanel.add(Box.createHorizontalStrut(10), BorderLayout.LINE_START);
+		centerPanel.add(Box.createHorizontalStrut(10), BorderLayout.LINE_END);
+		centerPanel.add(label, BorderLayout.PAGE_START);
+		centerPanel.add(scroll, BorderLayout.CENTER);
+		centerPanel.add(pageEndPanel, BorderLayout.PAGE_END);
+
+		this.setLayout(new BorderLayout());
+		this.add(centerPanel, BorderLayout.CENTER);
+		//this.add(new ViewerTest(), BorderLayout.PAGE_END);
+	}
+
+	@Override
+	public void setCurrentTreeNode(TreeNode node) {
+		super.setCurrentTreeNode(node);
+	}
+
+	protected abstract void applyChanges();
+
+}
Index: java/main/src/main/java/com/framsticks/gui/MultiPanel.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/MultiPanel.java	(revision 84)
+++ java/main/src/main/java/com/framsticks/gui/MultiPanel.java	(revision 84)
@@ -0,0 +1,54 @@
+package com.framsticks.gui;
+
+import com.framsticks.params.AccessInterface;
+
+import javax.swing.*;
+import java.awt.*;
+import java.util.List;
+
+/**
+ * Author: Piotr Śniegowski
+ */
+@SuppressWarnings("serial")
+public class MultiPanel extends Panel {
+
+	protected final List<Panel> panels;
+	protected final JTabbedPane tabbedPane;
+
+
+	public MultiPanel(Panel.Parameters parameters, List<Panel> panels) {
+		super(parameters);
+		this.panels = panels;
+		tabbedPane = new JTabbedPane();
+
+		for (Panel p : panels) {
+			assert p.getClassName().equals(getClassName());
+			assert p.getEndpointAtFrame() == getEndpointAtFrame();
+			tabbedPane.add(p.getTitle(), p);
+		}
+
+		this.setLayout(new BorderLayout());
+		this.add(tabbedPane, BorderLayout.CENTER);
+
+	}
+
+	@Override
+	public void pullValuesFromLocalToUser(AccessInterface access) {
+		for (Panel p : panels) {
+			p.pullValuesFromLocalToUser(access);
+		}
+	}
+
+	@Override
+	public String getTitle() {
+		return className;
+	}
+
+	@Override
+	public void setCurrentTreeNode(TreeNode currentTreeNode) {
+		super.setCurrentTreeNode(currentTreeNode);
+		for (Panel p : panels) {
+			p.setCurrentTreeNode(currentTreeNode);
+		}
+	}
+}
Index: java/main/src/main/java/com/framsticks/gui/ObjectPanel.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/ObjectPanel.java	(revision 79)
+++ java/main/src/main/java/com/framsticks/gui/ObjectPanel.java	(revision 84)
@@ -1,85 +1,45 @@
 package com.framsticks.gui;
 
-import com.framsticks.gui.components.Control;
-import com.framsticks.gui.components.ValueControl;
-import com.framsticks.gui.components.ValueControlListener;
+import com.framsticks.gui.controls.Control;
+import com.framsticks.gui.controls.ValueControl;
+import com.framsticks.gui.controls.ValueControlListener;
 import com.framsticks.params.AccessInterface;
-import com.framsticks.params.types.CompositeParam;
 import com.framsticks.params.Param;
-import com.framsticks.util.Strings;
+import com.framsticks.params.ValueParam;
+
 import org.apache.log4j.Logger;
 
 import javax.swing.*;
-import java.awt.*;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.Map;
-import java.util.List;
+import static com.framsticks.util.lang.Containers.filterInstanceof;
 
 @SuppressWarnings("serial")
-public class ObjectPanel extends com.framsticks.gui.Panel {
+public class ObjectPanel extends ModifiablePanel {
 
-	private static final Logger LOGGER = Logger.getLogger(ObjectPanel.class.getName());
+	private static final Logger log = Logger.getLogger(ObjectPanel.class.getName());
 
 	final protected Map<Param, Control> components = new HashMap<Param, Control>();
-	final protected Map<Param, ValueControl> valueComponents = new HashMap<Param, ValueControl>();
+	final protected Map<ValueParam, ValueControl> valueControls = new HashMap<ValueParam, ValueControl>();
 
-	public static void fillWithComponents(JPanel panel, Collection<Param> params, Map<Param, Control> components) {
-		for (Param param : params) {
-			if (param.isUserHidden()) {
-				continue;
-			}
-			assert !(param instanceof CompositeParam);
-			Control control = Control.createSuitable(param);
-			if (control != null) {
-				LOGGER.debug("add component for " + param);
-				JPanel line = new JPanel();
-				line.setLayout(new BoxLayout(line, BoxLayout.LINE_AXIS));
-				line.setAlignmentX(LEFT_ALIGNMENT);
-				JLabel label = new JLabel(Strings.notEmpty(param.getName()) ? param.getName() : "? (" + param.getId() + ")");
-				label.setToolTipText(label.getText());
-				label.setHorizontalAlignment(JLabel.RIGHT);
-				Dimension labelSize = new Dimension(150, 30);
-				label.setMaximumSize(labelSize);
-				label.setMinimumSize(labelSize);
-				label.setPreferredSize(labelSize);
-				line.add(label);
-				line.add(Box.createRigidArea(new Dimension(8, 0)));
-				line.add(control);
-				line.revalidate();
-				panel.add(line);
-				panel.add(Box.createRigidArea(new Dimension(0, 8)));
-				//component.setAlignmentX(LEFT_ALIGNMENT);
-				components.put(param, control);
-				continue;
-			}
-			LOGGER.error("component for param " + param + " of type " + param.getClass().getSimpleName() + " was not added");
-		}
+	public ObjectPanel(Panel.Parameters parameters, Collection<Param> params) {
+		super(parameters);
 
-	}
+		Gui.fillWithControls(contentPanel, params, components);
 
-	public ObjectPanel(EndpointAtFrame endpoint, String className, List<Param> params) {
-		super(endpoint, className);
-
-		fillWithComponents(contentPanel, params, components);
-
-		for (Map.Entry<Param, Control> e : components.entrySet()) {
-			Control control = e.getValue();
-			Param param = e.getKey();
-			if (control instanceof ValueControl) {
-				final ValueControl valueComponent = (ValueControl) control;
-				valueComponents.put(param, valueComponent);
-				valueComponent.setListener(new ValueControlListener() {
-					@Override
-					public boolean onChange(Object newValue) {
-						if (currentTreeNode == null) {
-							return true;
-						}
-						boolean result = currentTreeNode.changeValue(valueComponent, newValue);
-						refreshControlButtons();
-						return result;
+		for (final ValueControl c : filterInstanceof(components.values(), ValueControl.class)) {
+			valueControls.put(c.getParam(), c);
+			c.setListener(new ValueControlListener() {
+				@Override
+				public boolean onChange(Object newValue) {
+					if (currentTreeNode == null) {
+						return true;
 					}
-				});
-			}
+					boolean result = currentTreeNode.changeValue(c, newValue);
+					refreshControlButtons();
+					return result;
+				}
+			});
 		}
 		contentPanel.add(Box.createVerticalGlue());
@@ -91,65 +51,71 @@
 		assert frame.isActive();
 		assert currentTreeNode != null;
-		currentTreeNode.applyChanges();
+		currentTreeNode.pushLocalChanges();
 	}
 
 	protected void refreshControlButtons() {
 		assert frame.isActive();
-		applyButton.setEnabled(currentTreeNode.changedValues != null);
+		applyButton.setEnabled(currentTreeNode.localChanges != null);
+	}
+
+	protected static void fillControlsWithValues(Map<ValueControl, Object> map) {
 	}
 
 	@Override
-	public void refreshComponents(AccessInterface access) {
-        assert currentTreeNode.path.getInstance().isActive();
-        assert currentTreeNode != null;
-        LOGGER.debug("refreshing components");
+	public void pullValuesFromLocalToUser(AccessInterface access) {
+		assert currentTreeNode != null;
+		assert currentTreeNode.path.getInstance().isActive();
+		log.debug("refreshing components");
 
-        final Map<ValueControl, Object> values = new HashMap<ValueControl, Object>();
-        for (ValueControl vc : valueComponents.values()) {
-            Object value = access.get(vc.getParam().getId(), Object.class);
-            values.put(vc, value);
-        }
+		final Map<ValueControl, Object> values = new HashMap<ValueControl, Object>();
+		for (Map.Entry<ValueParam, ValueControl> e : valueControls.entrySet()) {
+			values.put(e.getValue(), access.get(e.getKey().getId(), Object.class));
+		}
 
-        frame.invokeLater(new Runnable() {
-            @Override
-            public void run() {
-                for (Map.Entry<ValueControl, Object> e : values.entrySet()) {
-                    e.getKey().setValue(e.getValue());
-                }
-				if (currentTreeNode.changedValues != null) {
-					for (Map.Entry<ValueControl, Object> e : currentTreeNode.changedValues.entrySet()) {
-						e.getKey().setValue(e.getValue());
+		frame.invokeLater(new Runnable() {
+			@Override
+			public void run() {
+				if (currentTreeNode.localChanges != null) {
+					for (Map.Entry<ValueControl, Object> e : currentTreeNode.localChanges.entrySet()) {
+						values.put(e.getKey(), e.getValue());
 					}
 				}
+				for (Map.Entry<ValueControl, Object> e : values.entrySet()) {
+					e.getKey().pushValueToUserInterface(e.getValue());
+				}
 				refreshControlButtons();
-                ObjectPanel.this.revalidate();
-            }
-        });
+				ObjectPanel.this.revalidate();
+			}
+		});
 
 	}
 
+	@Override
+	public String getTitle() {
+		return "Properties";
+	}
 
 
-/*	public void updateValue() {
-		//assert panel.getFrame().isActive();
+	// public void updateValue() {
+	// 	//assert panel.getFrame().isActive();
 
-        final Node n = panel.getCurrentNode();
-        panel.getBrowser().getManager().invokeLater(new Runnable() {
-            @Override
-            public void run() {
-                Object v = n.getAccess().get(param, Object.class);
-                if (v == null) {
-                    v = param.getDef(Object.class);
-                }
-                final Object fv = v;
-                panel.getBrowser().invokeLater(new Runnable() {
-                    @Override
-                    public void run() {
-                        setValueImpl(fv);
-                    }
-                });
-            }
-        });
-	}*/
+	// 	final Node n = panel.getCurrentNode();
+	// 	panel.getBrowser().getManager().invokeLater(new Runnable() {
+	// 		@Override
+	// 		public void run() {
+	// 			Object v = n.getAccess().get(param, Object.class);
+	// 			if (v == null) {
+	// 				v = param.getDef(Object.class);
+	// 			}
+	// 			final Object fv = v;
+	// 			panel.getBrowser().invokeLater(new Runnable() {
+	// 				@Override
+	// 				public void run() {
+	// 					setValueImpl(fv);
+	// 				}
+	// 			});
+	// 		}
+	// 	});
+	// }
 
 }
Index: java/main/src/main/java/com/framsticks/gui/Panel.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/Panel.java	(revision 79)
+++ java/main/src/main/java/com/framsticks/gui/Panel.java	(revision 84)
@@ -2,77 +2,49 @@
 
 import com.framsticks.params.AccessInterface;
-import org.apache.log4j.Logger;
+import com.framsticks.params.CompositeParam;
+import com.framsticks.params.FramsClass;
+// import org.apache.log4j.Logger;
 
 import javax.swing.*;
-import java.awt.*;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
 
 /**
- * @author Piotr Sniegowski
+ * Author: Piotr Śniegowski
  */
+@SuppressWarnings("serial")
 public abstract class Panel extends JPanel {
 
-	private static final Logger LOGGER = Logger.getLogger(Panel.class.getName());
+	public static class Parameters {
+		public final EndpointAtFrame endpoint;
+		public final CompositeParam param;
+		public final FramsClass framsClass;
 
-	/**
-	 * Pane to which components will be added.
-	 */
-	protected JPanel contentPanel;
+		public Parameters(EndpointAtFrame endpoint, CompositeParam param, FramsClass framsClass) {
+			this.endpoint = endpoint;
+			this.param = param;
+			this.framsClass = framsClass;
+		}
+	}
+
+	// private static final Logger log = Logger.getLogger(Panel.class.getName());
 
 	protected TreeNode currentTreeNode;
-    protected EndpointAtFrame endpoint;
-    protected final Frame frame;
+	protected final EndpointAtFrame endpoint;
+	protected final Frame frame;
 	protected final String className;
-	final protected JLabel label;
-	final protected JButton applyButton;
+	protected final FramsClass framsClass;
+	protected final CompositeParam param;
+	protected String uniqueName = "?";
 
-	public Panel(EndpointAtFrame endpoint, String className) {
-        this.endpoint = endpoint;
-		this.frame = endpoint.getFrame();
-		this.className = className;
-		LOGGER.debug("create panel for type: " + className);
-
-        endpoint.registerPanel(this);
-
-		contentPanel = new JPanel();
-		contentPanel.setLayout(new BoxLayout(contentPanel, BoxLayout.PAGE_AXIS));
-		JScrollPane scroll = new JScrollPane(contentPanel);
-		//scroll.setBorder(BorderFactory.createEtchedBorder());
-
-		JPanel pageEndPanel = new JPanel();
-		pageEndPanel.setLayout(new BoxLayout(pageEndPanel, BoxLayout.X_AXIS));
-		pageEndPanel.add(Box.createHorizontalGlue());
-
-		applyButton = new JButton("Apply");
-		applyButton.addActionListener(new ActionListener() {
-			public void actionPerformed(ActionEvent e) {
-				applyChanges();
-			}
-		});
-		pageEndPanel.add(applyButton);
-
-		pageEndPanel.add(Box.createHorizontalStrut(10));
-		pageEndPanel.setPreferredSize(new Dimension(0, 30));
-
-		label = new JLabel();
-		JPanel centerPanel = new JPanel();
-		centerPanel.setLayout(new BorderLayout());
-		centerPanel.add(Box.createHorizontalStrut(10), BorderLayout.LINE_START);
-		centerPanel.add(Box.createHorizontalStrut(10), BorderLayout.LINE_END);
-		centerPanel.add(label, BorderLayout.PAGE_START);
-		centerPanel.add(scroll, BorderLayout.CENTER);
-		centerPanel.add(pageEndPanel, BorderLayout.PAGE_END);
-
-		this.setLayout(new BorderLayout());
-		this.add(centerPanel, BorderLayout.CENTER);
-
-
+	public Panel(Parameters parameters) {
+		this.endpoint = parameters.endpoint;
+		this.frame = parameters.endpoint.getFrame();
+		this.framsClass = parameters.framsClass;
+		this.param = parameters.param;
+		this.className = parameters.param.getContainedTypeName();
+		this.setName(parameters.param.getFramsTypeName());
 	}
 
-	public void setCurrentTreeNode(TreeNode node) {
-		currentTreeNode = node;
-		//label.setText(node.getNode().getPath());
-		//this.revalidate();
+	public void setCurrentTreeNode(TreeNode currentTreeNode) {
+		this.currentTreeNode = currentTreeNode;
 	}
 
@@ -81,24 +53,28 @@
 	}
 
-	protected abstract void applyChanges();
-	public abstract void refreshComponents(AccessInterface access);
+	public final Frame getFrame() {
+		return frame;
+	}
+
+	public final EndpointAtFrame getEndpointAtFrame() {
+		return endpoint;
+	}
+
+
+	public final String getClassName() {
+		return className;
+	}
+
+	public abstract void pullValuesFromLocalToUser(AccessInterface access);
 
 	@Override
 	public String toString() {
-		return currentTreeNode == null ? "?" : currentTreeNode.toString();
+		return uniqueName;
 	}
 
-    public final Frame getFrame() {
-        return frame;
-    }
+	public final String getUniqueName() {
+		return uniqueName;
+	}
 
-
-    public final String getClassName() {
-        return className;
-    }
-
-    public final String getFullName() {
-        return className + "@" + endpoint.getName();
-    }
-
+	public abstract String getTitle();
 }
Index: java/main/src/main/java/com/framsticks/gui/PanelProvider.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/PanelProvider.java	(revision 84)
+++ java/main/src/main/java/com/framsticks/gui/PanelProvider.java	(revision 84)
@@ -0,0 +1,9 @@
+package com.framsticks.gui;
+
+
+/**
+ * Author: Piotr Śniegowski
+ */
+public interface PanelProvider {
+	public Panel providePanel(Panel.Parameters parameters);
+}
Index: java/main/src/main/java/com/framsticks/gui/StandardPanelProvider.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/StandardPanelProvider.java	(revision 84)
+++ java/main/src/main/java/com/framsticks/gui/StandardPanelProvider.java	(revision 84)
@@ -0,0 +1,28 @@
+package com.framsticks.gui;
+
+import com.framsticks.params.CompositeParam;
+import com.framsticks.params.types.ObjectParam;
+
+
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.collections.functors.InstanceofPredicate;
+import org.apache.commons.collections.functors.NotPredicate;
+
+
+/**
+ * Author: Piotr Śniegowski
+ */
+public class StandardPanelProvider implements PanelProvider {
+
+	@SuppressWarnings("unchecked")
+	@Override
+	public Panel providePanel(Panel.Parameters parameters) {
+		if (parameters.param instanceof ObjectParam) {
+			return new ObjectPanel(parameters, CollectionUtils.select(parameters.framsClass.getParamEntries(), new NotPredicate(new InstanceofPredicate(CompositeParam.class))));
+		}
+//		if (param instanceof ListParam) {
+//			return new ListPanel(endpoint);
+//		}
+		return null;
+	}
+}
Index: java/main/src/main/java/com/framsticks/gui/SwingDispatcher.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/SwingDispatcher.java	(revision 79)
+++ java/main/src/main/java/com/framsticks/gui/SwingDispatcher.java	(revision 84)
@@ -1,9 +1,8 @@
 package com.framsticks.gui;
 
-import com.framsticks.util.Dispatcher;
-import com.framsticks.util.Task;
+import com.framsticks.util.dispatching.Dispatcher;
+import com.framsticks.util.dispatching.Task;
 
 import javax.swing.*;
-import java.awt.*;
 
 /**
@@ -12,25 +11,25 @@
 public class SwingDispatcher implements Dispatcher {
 
-    public static final SwingDispatcher instance = new SwingDispatcher();
+	public static final SwingDispatcher instance = new SwingDispatcher();
 
-    public SwingDispatcher() {
-        invokeLater(new Runnable() {
-            @Override
-            public void run() {
-                Thread.currentThread().setName("gui");
-            }
-        });
-    }
+	public SwingDispatcher() {
+		invokeLater(new Runnable() {
+			@Override
+			public void run() {
+				Thread.currentThread().setName("gui");
+			}
+		});
+	}
 
-    @Override
-    public final boolean isActive() {
-        return SwingUtilities.isEventDispatchThread();
-    }
+	@Override
+	public final boolean isActive() {
+		return SwingUtilities.isEventDispatchThread();
+	}
 
-    @Override
-    public final void invokeLater(Runnable runnable) {
-        assert !(runnable instanceof Task);
-        SwingUtilities.invokeLater(runnable);
-    }
+	@Override
+	public final void invokeLater(Runnable runnable) {
+		assert !(runnable instanceof Task);
+		SwingUtilities.invokeLater(runnable);
+	}
 
 }
Index: java/main/src/main/java/com/framsticks/gui/TreeNode.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/TreeNode.java	(revision 79)
+++ java/main/src/main/java/com/framsticks/gui/TreeNode.java	(revision 84)
@@ -5,12 +5,14 @@
 import com.framsticks.core.ListChange;
 import com.framsticks.core.Path;
-import com.framsticks.gui.components.ValueControl;
+import com.framsticks.gui.controls.ValueControl;
 import com.framsticks.gui.view.TreeCellRenderer;
 import com.framsticks.params.AccessInterface;
-import com.framsticks.params.Param;
+import com.framsticks.params.CompositeParam;
+import com.framsticks.params.FramsClass;
 import com.framsticks.params.types.*;
 import com.framsticks.remote.*;
-import com.framsticks.util.Casting;
-import com.framsticks.util.Future;
+import com.framsticks.util.lang.Casting;
+import com.framsticks.util.swing.TooltipConstructor;
+import com.framsticks.util.dispatching.Future;
 import com.framsticks.util.Logging;
 import com.framsticks.util.StateFunctor;
@@ -18,482 +20,468 @@
 
 import javax.swing.tree.DefaultMutableTreeNode;
-import javax.swing.tree.TreePath;
 import java.util.HashMap;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
+import static com.framsticks.util.lang.Containers.filterInstanceof;
+import com.framsticks.util.swing.TreeNodeUtils;
 
 /**
  * @author Piotr Sniegowski
  */
+@SuppressWarnings("serial")
 public class TreeNode extends DefaultMutableTreeNode implements NodeListener {
 
-	private static final Logger LOGGER = Logger.getLogger(TreeNode.class.getName());
+	private static final Logger log = Logger.getLogger(TreeNode.class.getName());
 
 	Panel panel;
 
 	final protected Frame frame;
-    final protected EndpointAtFrame endpoint;
-
-    final protected Map<EventParam, Subscription> userSubscriptions = new HashMap<EventParam, Subscription>();
-	protected Map<ValueControl, Object> changedValues = null;
-    protected String tooltip;
-    protected String name;
-    protected String iconName;
-    protected Path path;
-
-
-    public TreeNode(Frame frame, EndpointAtFrame endpoint, final Path path) {
-        assert frame.isActive();
-        this.frame = frame;
-		LOGGER.debug("creating treenode for: " + path);
-        this.path = path;
-        this.endpoint = endpoint;
-
-        name = path.getTop().getParam().getId();
-        iconName = TreeCellRenderer.findIconName(name, path.getTextual());
-        tooltip = "?";
-        path.getInstance().invokeLater(new Runnable() {
-            @Override
-            public void run() {
-                updateDescriptions(path);
-            }
-        });
-	}
-
-    public void fetch(final Path p) {
-        assert p.getInstance().isActive();
-        LOGGER.debug("fetching: " + p);
-        p.getInstance().fetchValues(p, new StateFunctor() {
-            @Override
-            public void call(Exception e) {
-                assert p.getInstance().isActive();
-                if (Logging.log(LOGGER, "fetch", TreeNode.this, e)) {
-                    frame.invokeLater(new Runnable() {
-                        @Override
-                        public void run() {
-                            LOGGER.debug("removing node from tree: " + p);
-                            TreeNode.this.removeFromParent();
-                            frame.repaintTree();
-                        }
-                    });
-                    return;
-                }
-                updateChildren(p);
-                frame.invokeLater(new Runnable() {
-                    @Override
-                    public void run() {
-                        //TODO maybe this should be called from some better place
-                        useOrCreatePanel();
-                    }
-                });
-
-            }
-        });
-    }
-
-    protected void postUpdatePath(final Path newPath) {
-        assert !frame.isActive();
-        /** TODO those two actions could be merged into single closure */
-        frame.invokeLater(new Runnable() {
-            @Override
-            public void run() {
-                updatePath(newPath);
-            }
-        });
-        updateDescriptions(newPath);
-    }
-
-    protected void updatePath(Path newPath) {
-        assert frame.isActive();
-        if (!path.isResolved()) {
-            path = newPath;
-			LOGGER.debug("updated treenode's path: " + path);
-            return;
-        }
-        if (path.matches(newPath)) {
-            return;
-        }
-        this.removeAllChildren();
-    }
-
-    /** Update children, by removing non existing and adding new ones.
-     */
-    protected void updateChildren(final Path p) {
-        assert p.getInstance().isActive();
-        LOGGER.debug("updating children of " + this);
-        AccessInterface access = p.getInstance().bindAccess(p.getTop());
+	final protected EndpointAtFrame endpoint;
+
+	final protected Map<EventParam, Subscription> userSubscriptions = new HashMap<EventParam, Subscription>();
+	protected Map<ValueControl, Object> localChanges = null;
+	protected String tooltip;
+	protected String name;
+	protected final String paramId;
+	protected String iconName;
+	protected Path path;
+
+	public TreeNode(EndpointAtFrame endpoint, final Path path) {
+		this.frame = endpoint.getFrame();
+		assert frame.isActive();
+		this.paramId = path.getLastElement();
+		this.name = this.paramId;
+		log.debug("creating treenode " + name + ": " + path);
+		this.path = path;
+		this.endpoint = endpoint;
+
+		iconName = TreeCellRenderer.findIconName(name, path.getTextual());
+		tooltip = "?";
+		path.getInstance().invokeLater(new Runnable() {
+			@Override
+			public void run() {
+				updateDescriptions(path);
+			}
+		});
+	}
+
+	public void fetch(final Path p) {
+		assert p.getInstance().isActive();
+		log.debug("fetching: " + p);
+		p.getInstance().fetchValues(p, new StateFunctor() {
+			@Override
+			public void call(Exception e) {
+				//TODO removing should stay here
+				// reactForFetchResult(p, e);
+			}
+		});
+	}
+
+	protected void reactForFetchResult(final Path p, Exception e) {
+		assert p.getInstance().isActive();
+		if (Logging.log(log, "fetch", TreeNode.this, e)) {
+			frame.invokeLater(new Runnable() {
+				@Override
+				public void run() {
+					log.debug("removing node from tree: " + p);
+					frame.treeModel.removeNodeFromParent(TreeNode.this);
+				}
+			});
+			return;
+		}
+		updateChildren(p);
+		frame.invokeLater(new Runnable() {
+			@Override
+			public void run() {
+				//TODO maybe this should be called from some better place
+				useOrCreatePanel();
+			}
+		});
+	}
+
+	protected void postUpdatePath(final Path newPath) {
+		assert !frame.isActive();
+		/** TODO those two actions could be merged into single closure */
+		frame.invokeLater(new Runnable() {
+			@Override
+			public void run() {
+				updatePath(newPath);
+			}
+		});
+		updateDescriptions(newPath);
+	}
+
+	protected void updatePath(Path newPath) {
+		assert frame.isActive();
+		if (!path.isResolved()) {
+			path = newPath;
+			log.debug("updated treenode's path: " + path);
+			return;
+		}
+		if (path.matches(newPath)) {
+			return;
+		}
+		log.debug("removing all children due to path update");
+		this.removeAllChildren();
+		frame.treeModel.nodeStructureChanged(this);
+	}
+
+	public Iterable<TreeNode> childrenIterable() {
+		return filterInstanceof(TreeNodeUtils.children(TreeNode.this, frame.treeModel), TreeNode.class);
+	}
+
+	/** Update children, by removing non existing and adding new ones.
+	 */
+	protected void updateChildren(final Path p) {
+		assert p.getInstance().isActive();
+		log.debug("updating children of " + this);
+		AccessInterface access = p.getInstance().bindAccess(p.getTop());
 		if (access == null) {
 			return;
 		}
-        final List<Path> childrenPaths = new LinkedList<Path>();
-        /**Prepare path for each child.*/
-        for (Param param : access.getParams()) {
-            if (!(param instanceof CompositeParam)) {
-                continue;
-            }
-            Path childPath = p.appendParam((CompositeParam)param);
-            childrenPaths.add(childPath);
-        }
-        /**If some child were found, update in frame context.*/
-        if (childrenPaths.size() > 0) {
-            frame.invokeLater(new Runnable() {
-                @Override
-                public void run() {
-                    TreePath treePath = frame.startChange();
-                    updatePath(p);
-                    Map<String, TreeNode> current = new HashMap<String, TreeNode>();
-                    for (int c = 0; c < TreeNode.this.getChildCount(); ++c) {
-                        TreeNode n = (TreeNode)TreeNode.this.getChildAt(c);
-                        current.put(n.path.getLastElement(), n);
-                    }
-                    for (final Path childPath : childrenPaths) {
-                        String e = childPath.getLastElement();
-                        if (current.containsKey(e)) {
-                            /*
-                            final TreeNode n = current.get(e);
-                            childPath.getInstance().invokeLater(new Runnable() {
-                                @Override
-                                public void run() {
-                                    n.updateChildren(childPath);
-                                }
-                            });
-                            */
-                            current.remove(e);
-                            continue;
-                        }
-                        TreeNode childNode = new TreeNode(frame, endpoint, childPath);
-                        TreeNode.this.add(childNode);
-                    }
-                    for (TreeNode n : current.values()) {
-                        TreeNode.this.remove(n);
-                    }
-                    frame.markNodeChanged(TreeNode.this, treePath);
-                    frame.repaintTree();
-                    LOGGER.debug("updated children of " + TreeNode.this);
-                }
-            });
-        } else {
-            LOGGER.debug("no children in " + TreeNode.this);
-        }
-    }
-
-    public void select() {
-        final Path p = path;
-
-        p.getInstance().invokeLater(new Runnable() {
-            @Override
-            public void run() {
-                final Path updated = (p.isResolved()) ? p : p.findResolution();
-                if (updated.isResolved()) {
-                    Logging.log(LOGGER, "update", updated, null);
-                    fetch(updated);
-                    postUpdatePath(updated);
-                    return;
-                }
-                p.getInstance().resolve(updated, new Future<Path>() {
-                    @Override
-                    public void result(final Path result, Exception e) {
-                        if (Logging.log(LOGGER, "resolve and select", TreeNode.this, e)) {
-                            return;
-                        }
-
-                        fetch(result);
-                        postUpdatePath(result);
-                    }
-                });
-            }
-        });
-
-    }
-
-    @Override
-    public String toString() {
-        return path.toString();
-    }
+		final List<Path> childrenPaths = new LinkedList<Path>();
+		/**Prepare path for each child.*/
+		for (CompositeParam param : filterInstanceof(access.getParams(), CompositeParam.class)) {
+			childrenPaths.add(p.appendParam(param).tryFindResolution());
+		}
+
+		/**If some child were found, update in frame context.*/
+		if (childrenPaths.size() > 0) {
+			frame.invokeLater(new Runnable() {
+				@Override
+				public void run() {
+					// TreePath treePath = frame.startChange();
+					updatePath(p);
+					Map<String, TreeNode> current = new HashMap<String, TreeNode>();
+					for (TreeNode n : childrenIterable()) {
+						current.put(n.path.getLastElement(), n);
+					}
+					assert current.size() == TreeNode.this.getChildCount();
+					assert TreeNode.this.getChildCount() == frame.treeModel.getChildCount(TreeNode.this);
+					log.trace("current " + TreeNode.this.getChildCount() + " children: " + current.values());
+					for (Path childPath : childrenPaths) {
+						String e = childPath.getLastElement();
+						if (current.containsKey(e)) {
+							current.remove(e);
+							continue;
+						}
+						log.debug("update: treenode for " + p);
+						TreeNode childNode = new TreeNode(endpoint, childPath);
+
+						frame.addNode(childNode, TreeNode.this);
+					}
+					for (TreeNode n : current.values()) {
+						frame.treeModel.removeNodeFromParent(n);
+					}
+					log.debug("updated children of " + TreeNode.this + ": " + TreeNode.this.getChildCount());
+				}
+			});
+		} else {
+			log.debug("no children in " + TreeNode.this);
+		}
+	}
+
+	public void select() {
+		final Path p = path;
+
+		p.getInstance().invokeLater(new Runnable() {
+			@Override
+			public void run() {
+				final Path updated = (p.isResolved()) ? p : p.tryFindResolution();
+				if (updated.isResolved()) {
+					Logging.log(log, "update", updated, null);
+					fetch(updated);
+					postUpdatePath(updated);
+					return;
+				}
+				p.getInstance().resolve(updated, new Future<Path>() {
+					@Override
+					public void result(final Path result, Exception e) {
+						if (Logging.log(log, "resolve and select", TreeNode.this, e)) {
+							return;
+						}
+
+						fetch(result);
+						postUpdatePath(result);
+					}
+				});
+			}
+		});
+
+	}
+
+	@Override
+	public String toString() {
+		return path.toString();
+	}
 
 	public final Panel getPanel() {
-        assert frame.isActive();
+		assert frame.isActive();
 		return panel;
 	}
 
-    protected void updateDescriptions(final Path p) {
-        assert p.getInstance().isActive();
-        if (!p.isResolved()) {
-            return;
-        }
-        AccessInterface access = p.getInstance().bindAccess(p);
+	protected void updateDescriptions(Path p) {
+		assert p.getInstance().isActive();
+
+		if (!p.isResolved()) {
+			return;
+		}
+		AccessInterface access = p.getInstance().bindAccess(p);
 		if (access == null) {
 			return;
 		}
-        StringBuilder t = new StringBuilder();
-        /** html formatting is used here, since tooltips in swing do not support simple \n line breaks */
-        t.append("<html>");
-        t.append("frams: ").append(access.getId()).append("<br/>");
-        t.append("java: ").append(p.getTopObject().getClass().getCanonicalName()).append("<br/>");
-        t.append("access: ").append(access.getClass().getSimpleName());
-        t.append("</html>");
-        final String tooltip = t.toString();
-
-        StringParam nameParam = Casting.tryCast(StringParam.class, access.getParam("name"));
-        final String name = (nameParam != null ? access.get(nameParam, String.class) : path.getTop().getParam().getId());
-
-        frame.invokeLater(new Runnable() {
-            @Override
-            public void run() {
-
-                TreeNode.this.tooltip = tooltip;
-                TreeNode.this.name = name;
-            }
-        });
-    }
+
+		final String tooltip = new TooltipConstructor()
+			.append("frams", access.getId())
+			.append("java", p.getTopObject().getClass().getCanonicalName())
+			.append("access", access.getClass().getSimpleName())
+			.append("name", name)
+			.append("id", paramId)
+			.append("object", Integer.toHexString(System.identityHashCode(this)))
+			.build()
+			;
+
+		StringParam nameParam = Casting.tryCast(StringParam.class, access.getParam("name"));
+		final String name = (nameParam != null ? access.get(nameParam, String.class) : path.getTop().getParam().getId());
+
+		frame.invokeLater(new Runnable() {
+			@Override
+			public void run() {
+				TreeNode.this.tooltip = tooltip;
+				TreeNode.this.name = name;
+
+				log.debug("updated descriptions for " + path + ": " + name);
+			}
+		});
+	}
 
 /*
 	public void updateData() {
-        assert browser.isActive();
+		assert browser.isActive();
 		final Node node = getNode();
-        browser.manager.invokeLater(new Runnable() {
-            @Override
-            public void run() {
-                node.fetchValues(new StateFunctor() {
-                    @Override
-                    public void call(Exception e) {
-                        if (e != null) {
-                            return;
-                        }
-                        browser.invokeLater(new Runnable() {
-                            @Override
-                            public void run() {
-                                assert browser.isActive();
-                                if (panel.getCurrentTreeNode() == TreeNode.this) {
-                                    panel.refreshComponents();
-                                }
-
-                                browser.tree.repaint();
-                                panel.refreshComponents();
-                            }
-                        });
-                    }
-                });
-            }
-        });
+		browser.manager.invokeLater(new Runnable() {
+			@Override
+			public void run() {
+				node.fetchValues(new StateFunctor() {
+					@Override
+					public void call(Exception e) {
+						if (e != null) {
+							return;
+						}
+						browser.invokeLater(new Runnable() {
+							@Override
+							public void run() {
+								assert browser.isActive();
+								if (panel.getCurrentTreeNode() == TreeNode.this) {
+									panel.refreshComponents();
+								}
+
+								browser.tree.repaint();
+								panel.refreshComponents();
+							}
+						});
+					}
+				});
+			}
+		});
 	}
 */
 
-    public void showPanel() {
-        assert frame.isActive();
-        assert panel != null;
-        frame.showPanel(panel);
-    }
-
-    public void fillPanelWithValues() {
-        assert frame.isActive();
-        final Path p = path;
-        assert p.isResolved();
-        assert panel != null;
-        panel.setCurrentTreeNode(this);
-        p.getInstance().invokeLater(new Runnable() {
-            @Override
-            public void run() {
-                AccessInterface access = p.getInstance().bindAccess(p);
-                panel.refreshComponents(access);
-
-                frame.invokeLater(new Runnable() {
-                    @Override
-                    public void run() {
-                        showPanel();
-                    }
-                });
-            }
-        });
-
-    }
+	public void showPanel() {
+		assert frame.isActive();
+		assert panel != null;
+		frame.showPanel(panel);
+	}
+
+	public void fillPanelWithValues() {
+		assert frame.isActive();
+		if (panel == null) {
+			return;
+		}
+		final Path p = path;
+		assert p.isResolved();
+		panel.setCurrentTreeNode(this);
+		p.getInstance().invokeLater(new Runnable() {
+			@Override
+			public void run() {
+				AccessInterface access = p.getInstance().bindAccess(p);
+				panel.pullValuesFromLocalToUser(access);
+
+				frame.invokeLater(new Runnable() {
+					@Override
+					public void run() {
+						showPanel();
+					}
+				});
+			}
+		});
+
+	}
 
 	public void useOrCreatePanel() {
-        assert frame.isActive();
+		assert frame.isActive();
 		if (panel != null) {
-            LOGGER.trace("panel is already attached: " + path);
-            fillPanelWithValues();
-			return;
-		}
-        if (!path.isResolved()) {
-            LOGGER.trace("path is not resolved: " + path);
-            return;
-        }
-
-        CompositeParam param = path.getTop().getParam();
-        panel = endpoint.findPanel(param.computeAccessId());
-        if (panel != null) {
-            LOGGER.debug("found prepared panel for: " + path);
-            fillPanelWithValues();
-            return;
-        }
-        final Path p = path;
-        LOGGER.debug("preparing panel: " + p);
-        p.getInstance().invokeLater(new Runnable() {
-            @Override
-            public void run() {
-                assert p.getInstance().isActive();
-                final CompositeParam param = p.getTop().getParam();
-                if (param instanceof ObjectParam) {
-                    AccessInterface access = p.getInstance().prepareAccess(param);
-                    final List<Param> params = new LinkedList<Param>();
-                    for (Param p : access.getParams()) {
-                        if (p instanceof CompositeParam) {
-                            continue;
-                        }
-                        params.add(p);
-                    }
-                    frame.invokeLater(new Runnable() {
-                        @Override
-                        public void run() {
-                            panel = new ObjectPanel(endpoint, param.getContainedTypeName(), params);
-                            fillPanelWithValues();
-                        }
-                    });
-                    return;
-                }
-                if (param instanceof ListParam) {
-					frame.invokeLater(new Runnable() {
-						@Override
-						public void run() {
-							panel = new ListPanel(endpoint);
-							fillPanelWithValues();
+			log.trace("panel is already attached: " + path);
+			fillPanelWithValues();
+			return;
+		}
+		if (!path.isResolved()) {
+			log.trace("path is not resolved: " + path);
+			return;
+		}
+
+		CompositeParam param = path.getTop().getParam();
+		panel = endpoint.findPanel(param.computeAccessId());
+		if (panel != null) {
+			log.debug("found prepared panel for: " + path);
+			fillPanelWithValues();
+			return;
+		}
+		final Path p = path;
+		log.debug("preparing panel: " + p);
+		p.getInstance().invokeLater(new Runnable() {
+			@Override
+			public void run() {
+				assert p.getInstance().isActive();
+				final CompositeParam param = p.getTop().getParam();
+				final FramsClass framsClass = p.getInstance().getInfoFromCache(param.getContainedTypeName());
+				frame.invokeLater(new Runnable() {
+					@Override
+					public void run() {
+						panel = endpoint.preparePanel(param, framsClass);
+						fillPanelWithValues();
+					}
+				});
+			}
+		});
+	}
+
+	public String getTooltip() {
+		assert frame.isActive();
+		return tooltip;
+	}
+
+
+
+
+	/*public void subscribe(final EventParam eventParam) {
+		assert browser.isActive();
+		if (hasSubscribed(eventParam)) {
+			log.error(eventParam + " is already subscribed for " + this);
+			return;
+		}
+		Node node = getNode();
+		node.getConnection().subscribe(node.getPath() + "/" + eventParam.getId(), new SubscriptionCallback() {
+			@Override
+			public EventCallback subscribed(final Subscription subscription) {
+				if (subscription == null) {
+					log.error("subscription failed");
+					return null;
+				}
+				if (hasSubscribed(eventParam)) {
+					//abort subscription
+					return null;
+				}
+				userSubscriptions.put(eventParam, subscription);
+				log.debug("subscription succeeded: " + subscription);
+				subscription.setDispatcher(browser);
+				return new EventCallback() {
+					@Override
+					public void call(SourceInterface content) {
+						assert browser.isActive();
+						log.info("event " + subscription + " occurred");
+					}
+				};
+			}
+		});
+
+	}*/
+
+	public boolean hasSubscribed(EventParam param) {
+		assert frame.isActive();
+		return userSubscriptions.containsKey(param);
+	}
+
+	public void unsubscribe(EventParam eventParam) {
+		assert frame.isActive();
+		if (!hasSubscribed(eventParam)) {
+			log.error("could not unsubscribe from " + eventParam);
+			return;
+		}
+		userSubscriptions.get(eventParam).unsubscribe(new LoggingStateCallback(log, "unsubscribed " + eventParam));
+		userSubscriptions.remove(eventParam);
+	}
+
+/*
+
+	@Override
+	public void onChildChange(final Child child, ListChange.Action action) {
+		assert browser.manager.isActive();
+
+		switch (action) {
+			case Remove: {
+				Dispatching.invokeDispatch(browser, browser.manager, new Runnable() {
+					@Override
+					public void run() {
+						assert browser.manager.isActive();
+						final TreeNode treeNode = (TreeNode) child.getUserObject();
+						if (treeNode == null) {
+							log.error("child " + child + " had no tree node attached");
+							return;
 						}
-					});
-					return;
-                    //return panel = new ListPanel(browser, access);
-                }
-                assert false;
-            }
-        });
-	}
-
-    public String getTooltip() {
-        assert frame.isActive();
-        return tooltip;
-    }
-
-
-
-
-    /*public void subscribe(final EventParam eventParam) {
-        assert browser.isActive();
-        if (hasSubscribed(eventParam)) {
-            LOGGER.error(eventParam + " is already subscribed for " + this);
-            return;
-        }
-        Node node = getNode();
-        node.getConnection().subscribe(node.getPath() + "/" + eventParam.getId(), new SubscriptionCallback() {
-            @Override
-            public EventCallback subscribed(final Subscription subscription) {
-                if (subscription == null) {
-                    LOGGER.error("subscription failed");
-                    return null;
-                }
-                if (hasSubscribed(eventParam)) {
-                    //abort subscription
-                    return null;
-                }
-                userSubscriptions.put(eventParam, subscription);
-                LOGGER.debug("subscription succeeded: " + subscription);
-                subscription.setDispatcher(browser);
-                return new EventCallback() {
-                    @Override
-                    public void call(SourceInterface content) {
-                        assert browser.isActive();
-                        LOGGER.info("event " + subscription + " occurred");
-                    }
-                };
-            }
-        });
-
-    }*/
-
-    public boolean hasSubscribed(EventParam param) {
-        assert frame.isActive();
-        return userSubscriptions.containsKey(param);
-    }
-
-    public void unsubscribe(EventParam eventParam) {
-        assert frame.isActive();
-        if (!hasSubscribed(eventParam)) {
-            LOGGER.error("could not unsubscribe from " + eventParam);
-            return;
-        }
-        userSubscriptions.get(eventParam).unsubscribe(new LoggingStateCallback(LOGGER, "unsubscribed " + eventParam));
-        userSubscriptions.remove(eventParam);
-    }
-
-/*
-
-    @Override
-    public void onChildChange(final Child child, ListChange.Action action) {
-        assert browser.manager.isActive();
-
-        switch (action) {
-            case Remove: {
-                Dispatching.invokeDispatch(browser, browser.manager, new Runnable() {
-                    @Override
-                    public void run() {
-                        assert browser.manager.isActive();
-                        final TreeNode treeNode = (TreeNode) child.getUserObject();
-                        if (treeNode == null) {
-                            LOGGER.error("child " + child + " had no tree node attached");
-                            return;
-                        }
-                        browser.invokeLater(new Runnable() {
-                            @Override
-                            public void run() {
-                                assert browser.isActive();
-                                TreePath path = browser.startChange();
-                                //assert treeNode.getParent() == TreeNode.this;
-                                if (treeNode.getParent() != null) {
-                                    browser.treeModel.removeNodeFromParent(treeNode);
-                                }
-                                //remove(treeNode);
-                                browser.markNodeChanged(TreeNode.this, path);
-                            }
-                        });
-                    }
-                });
-                break;
-            }
-        }
-
-    }
+						browser.invokeLater(new Runnable() {
+							@Override
+							public void run() {
+								assert browser.isActive();
+								TreePath path = browser.startChange();
+								//assert treeNode.getParent() == TreeNode.this;
+								if (treeNode.getParent() != null) {
+									browser.treeModel.removeNodeFromParent(treeNode);
+								}
+								//remove(treeNode);
+								browser.markNodeChanged(TreeNode.this, path);
+							}
+						});
+					}
+				});
+				break;
+			}
+		}
+
+	}
 */
 
-    public String getName() {
-        return name;
-    }
-
-    public String getIconName() {
-        return iconName;
-    }
-
-    @Override
-    public void onUpgrade(Path path) {
-    }
-
-    @Override
-    public void onChange(Path path) {
-    }
-
-    @Override
-    public void onChildChange(Path path, ListChange.Action action) {
-    }
-
-    public final Frame getFrame() {
-        return frame;
-    }
+	public String getName() {
+		return name;
+	}
+
+	public String getIconName() {
+		return iconName;
+	}
+
+	@Override
+	public void onUpgrade(Path path) {
+	}
+
+	@Override
+	public void onChange(Path path) {
+	}
+
+	@Override
+	public void onChildChange(Path path, ListChange.Action action) {
+	}
+
+	public final Frame getFrame() {
+		return frame;
+	}
 
 	public boolean changeValue(ValueControl component, Object newValue) {
-		LOGGER.debug("changing value of " + component + " to '" + newValue + "'");
-
-		if (changedValues == null) {
-			changedValues = new HashMap<ValueControl, Object>();
-		}
-		changedValues.put(component, newValue);
+		log.debug("changing value of " + component + " to '" + newValue + "'");
+
+		if (localChanges == null) {
+			localChanges = new HashMap<ValueControl, Object>();
+		}
+		localChanges.put(component, newValue);
 
 		return true;
@@ -505,11 +493,11 @@
 	}
 
-	public void applyChanges() {
-		assert frame.isActive();
-		if (changedValues == null) {
-			return;
-		}
-		final Map<ValueControl, Object> changes = changedValues;
-		changedValues = null;
+	public void pushLocalChanges() {
+		assert frame.isActive();
+		if (localChanges == null) {
+			return;
+		}
+		final Map<ValueControl, Object> changes = localChanges;
+		localChanges = null;
 		endpoint.getEndpoint().invokeLater(new Runnable() {
 			@Override
@@ -525,5 +513,5 @@
 								return;
 							}
-							LOGGER.debug("applied changes for: " + p);
+							log.debug("applied changes for: " + p);
 							frame.invokeLater(new Runnable() {
 								@Override
Index: java/main/src/main/java/com/framsticks/gui/controls/CheckBoxControl.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/controls/CheckBoxControl.java	(revision 84)
+++ java/main/src/main/java/com/framsticks/gui/controls/CheckBoxControl.java	(revision 84)
@@ -0,0 +1,54 @@
+package com.framsticks.gui.controls;
+
+import java.awt.Dimension;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+import javax.swing.JCheckBox;
+
+import org.apache.log4j.Logger;
+
+import com.framsticks.params.types.BooleanParam;
+
+@SuppressWarnings("serial")
+public class CheckBoxControl extends ValueControl {
+
+	private static final Logger log = Logger.getLogger(CheckBoxControl.class.getName());
+
+	protected final JCheckBox checkBox;
+
+	public CheckBoxControl(BooleanParam booleanParam) {
+		super(booleanParam);
+		checkBox = new JCheckBox();
+		checkBox.setEnabled(!isReadOnly());
+		checkBox.addActionListener(new ActionListener() {
+
+			@Override
+			public void actionPerformed(ActionEvent actionEvent) {
+				log.debug("change to: " + checkBox.isSelected());
+				notifyOfChange();
+			}
+		});
+		this.setMaximumSize(new Dimension(Integer.MAX_VALUE, Control.LINE_HEIGHT));
+		addAsOnlyChild(checkBox);
+	}
+
+	@Override
+	public void pushValueToUserInterfaceImpl(Object value) {
+		if (value == null) {
+			return;
+		}
+		checkBox.setSelected((Boolean) value);
+	}
+
+	@Override
+	public Object pullValueFromUserInterface() {
+		return checkBox.isSelected();
+	}
+
+	@Override
+	public BooleanParam getParam() {
+		return (BooleanParam) param;
+	}
+
+}
Index: java/main/src/main/java/com/framsticks/gui/controls/Control.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/controls/Control.java	(revision 84)
+++ java/main/src/main/java/com/framsticks/gui/controls/Control.java	(revision 84)
@@ -0,0 +1,45 @@
+package com.framsticks.gui.controls;
+
+import com.framsticks.params.Flags;
+import com.framsticks.params.Param;
+import javax.swing.*;
+import java.awt.*;
+
+/**
+ * Interface that each class that want to be component must implement.
+ */
+@SuppressWarnings("serial")
+public abstract class Control extends JPanel {
+
+	public static final int LINE_HEIGHT = 36;
+
+	// private static final Logger log = Logger.getLogger(Control.class.getName());
+
+	protected Frame frame;
+	protected final Param param;
+
+	public Control(Param param) {
+		this.param = param;
+
+		this.setEnabled(!param.hasFlag(Flags.READONLY));
+		// TODO: take care of textField exception: setEditable
+	}
+
+	public Param getParam() {
+		return param;
+	}
+
+	public void setFrame(Frame frame) {
+		this.frame = frame;
+	}
+
+	protected void addAsOnlyChild(JComponent component) {
+		this.setLayout(new BorderLayout());
+		this.add(component, BorderLayout.CENTER);
+	}
+
+	@Override
+	public String toString() {
+		return param.toString();
+	}
+}
Index: java/main/src/main/java/com/framsticks/gui/controls/ControlPopupListener.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/controls/ControlPopupListener.java	(revision 84)
+++ java/main/src/main/java/com/framsticks/gui/controls/ControlPopupListener.java	(revision 84)
@@ -0,0 +1,40 @@
+package com.framsticks.gui.controls;
+
+import javax.swing.*;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+
+/**
+ * Listener for component's JPopup menu.
+ */
+public class ControlPopupListener extends MouseAdapter {
+
+	private JPopupMenu popup;
+
+	public ControlPopupListener(JPopupMenu popup) {
+		this.popup = popup;
+	}
+
+	@Override
+	public void mousePressed(MouseEvent e) {
+		if (e.isPopupTrigger()) {
+			showPopup(e);
+		}
+	}
+
+	@Override
+	public void mouseReleased(MouseEvent e) {
+		if (e.isPopupTrigger()) {
+			showPopup(e);
+		}
+	}
+
+	/**
+	 * Shows popup menu if popup trigger fires.
+	 *
+	 * @param e MouseEvent on which popup menu will be showed.
+	 */
+	private void showPopup(MouseEvent e) {
+		popup.show(e.getComponent(), e.getX(), e.getY());
+	}
+}
Index: java/main/src/main/java/com/framsticks/gui/controls/EnumControl.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/controls/EnumControl.java	(revision 84)
+++ java/main/src/main/java/com/framsticks/gui/controls/EnumControl.java	(revision 84)
@@ -0,0 +1,63 @@
+package com.framsticks.gui.controls;
+
+import com.framsticks.params.types.EnumParam;
+import com.framsticks.util.lang.Numbers;
+import org.apache.log4j.Logger;
+
+import javax.swing.*;
+
+import java.awt.Dimension;
+import java.awt.event.ItemEvent;
+import java.awt.event.ItemListener;
+
+@SuppressWarnings("serial")
+public class EnumControl extends ValueControl {
+
+	protected final JComboBox list;
+
+	private static final Logger log = Logger.getLogger(EnumControl.class.getName());
+
+	public EnumControl(EnumParam enumParam) {
+		super(enumParam);
+
+		this.setMaximumSize(new Dimension(Integer.MAX_VALUE, LINE_HEIGHT));
+
+		list = new JComboBox();
+		for (String item : enumParam.getElements()) {
+			list.addItem(item);
+		}
+		list.setEditable(false);
+		list.setEnabled(!isReadOnly());
+		list.addItemListener(new ItemListener() {
+			@Override
+			public void itemStateChanged(ItemEvent itemEvent) {
+				notifyOfChange();
+			}
+		});
+		addAsOnlyChild(list);
+	}
+
+	@Override
+	public void pushValueToUserInterfaceImpl(Object value) {
+		Integer x = Numbers.cast(value, Integer.class);
+		if (x == null) {
+			return;
+		}
+		try {
+			list.setSelectedIndex(x - getParam().getMin(Integer.class));
+		} catch (IllegalArgumentException e) {
+			log.error("failed to set value");
+		}
+	}
+
+	@Override
+	public Object pullValueFromUserInterface() {
+		return list.getSelectedIndex();
+	}
+
+	@Override
+	public EnumParam getParam() {
+		return (EnumParam) param;
+	}
+
+}
Index: java/main/src/main/java/com/framsticks/gui/controls/EventControl.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/controls/EventControl.java	(revision 84)
+++ java/main/src/main/java/com/framsticks/gui/controls/EventControl.java	(revision 84)
@@ -0,0 +1,49 @@
+package com.framsticks.gui.controls;
+
+import java.awt.Dimension;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+import javax.swing.JButton;
+
+import com.framsticks.params.types.EventParam;
+
+/**
+ * @author Piotr Sniegowski
+ */
+@SuppressWarnings("serial")
+public class EventControl extends Control {
+	// private static final Logger log = Logger.getLogger(EventControl.class.getName());
+
+	protected final JButton button;
+	boolean subscribed = true;
+
+	public EventControl(final EventParam eventParam) {
+		super(eventParam);
+
+		button = new JButton("subscribe");
+		this.add(button);
+		this.setMaximumSize(new Dimension(Integer.MAX_VALUE, Control.LINE_HEIGHT));
+
+		button.addActionListener(new ActionListener() {
+			@Override
+			public void actionPerformed(ActionEvent e) {
+				if (subscribed) {
+					//panel.getCurrentTreeNode().unsubscribe(eventParam);
+				} else {
+					//panel.getCurrentTreeNode().subscribe(eventParam);
+				}
+			}
+		});
+
+	}
+
+	/*
+	@Override
+	public void refresh() {
+		subscribed = panel.getCurrentTreeNode().hasSubscribed((EventParam)param);
+		button.setText(subscribed ? "unsubscribe" : "subscribe");
+		this.revalidate();
+	}
+	*/
+}
Index: java/main/src/main/java/com/framsticks/gui/controls/ProcedureControl.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/controls/ProcedureControl.java	(revision 84)
+++ java/main/src/main/java/com/framsticks/gui/controls/ProcedureControl.java	(revision 84)
@@ -0,0 +1,65 @@
+package com.framsticks.gui.controls;
+
+import com.framsticks.gui.Gui;
+import com.framsticks.params.Param;
+import com.framsticks.params.types.ProcedureParam;
+
+import javax.swing.*;
+import javax.swing.border.BevelBorder;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.HashMap;
+import java.util.Map;
+
+@SuppressWarnings("serial")
+public class ProcedureControl extends Control {
+	// private static final Logger log = Logger.getLogger(Control.class.getName());
+
+	protected final JButton procedureButton;
+
+	final protected Map<Param, Control> components = new HashMap<Param, Control>();
+
+	public ProcedureControl(ProcedureParam procedureParam) {
+		super(procedureParam);
+
+		procedureButton = new JButton("Call");
+
+		this.setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
+
+		Gui.fillWithControls(this, procedureParam.getArgumentsType(), components);
+
+		if (components.size() != procedureParam.getArgumentsType().size()) {
+			procedureButton.setEnabled(false);
+		}
+		if (!components.isEmpty()) {
+			this.setBorder(new BevelBorder(BevelBorder.RAISED));
+		}
+
+		procedureButton.addActionListener(new ActionListener() {
+			@Override
+			public void actionPerformed(ActionEvent e) {
+
+/*
+				Node node = panel.getCurrentNode();
+				if (argumentWindow != null) {
+					argumentWindow.askForArguments();
+					return;
+				}
+				node.getConnection().send(new CallQuery().setMethod(param.getId()).setPath(node.getPath()).setCallback(new QueryCallback() {
+					@Override
+					public void call(boolean ok, String comment, SourceInterface content) {
+						if (!ok) {
+							log.error("failed to call method: " + param);
+							return;
+						}
+						log.debug("successful call of method: " + param);
+					}
+				}));
+*/
+			}
+		});
+		this.add(procedureButton);
+
+	}
+
+}
Index: java/main/src/main/java/com/framsticks/gui/controls/SliderControl.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/controls/SliderControl.java	(revision 84)
+++ java/main/src/main/java/com/framsticks/gui/controls/SliderControl.java	(revision 84)
@@ -0,0 +1,208 @@
+package com.framsticks.gui.controls;
+
+import java.awt.BorderLayout;
+import java.awt.Dimension;
+import java.util.Hashtable;
+
+import javax.swing.Box;
+import javax.swing.BoxLayout;
+import javax.swing.JComponent;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JSlider;
+import javax.swing.JTextField;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
+
+import org.apache.log4j.Logger;
+
+import com.framsticks.params.Flags;
+import com.framsticks.params.types.DecimalParam;
+import com.framsticks.params.types.FloatParam;
+import com.framsticks.params.types.NumberParam;
+import com.framsticks.util.lang.Numbers;
+import com.framsticks.util.swing.Layout;
+
+@SuppressWarnings("serial")
+public class SliderControl extends TextControl {
+
+	private static final Logger log = Logger.getLogger(SliderControl.class.getName());
+
+	protected final JSlider slider;
+
+	protected final JTextField text;
+
+	/**
+	 * Division factor used to implement float value slider.
+	 */
+	private final int div = 10;
+	private JComponent changing = null;
+
+	private Class<? extends Number> valueType;
+
+	public SliderControl(NumberParam<?> param) {
+		super(param);
+		text = new JTextField();
+
+		//TODO: that factor should be done as a constant
+		this.setMaximumSize(new Dimension(Integer.MAX_VALUE, (int)(LINE_HEIGHT * 1.2)));
+
+		// ComponentUI ui = UIManager.getUI(slider);
+		// assert ui instanceof SliderUI;
+		// SliderUI sui = (SliderUI) ui;
+		// slider.setUI(sui);
+
+		slider = new JSlider();
+
+		slider.setEnabled(!isReadOnly());
+		slider.setPaintLabels(false);
+		if (param instanceof DecimalParam) {
+			valueType = Integer.class;
+
+			int min = param.getMin(Integer.class);
+			int max = param.getMax(Integer.class);
+			slider.setMinimum(min);
+			slider.setMaximum(max);
+			if (param.getDef(Integer.class) != null) {
+				slider.setValue(param.getDef(Integer.class));
+			} else {
+				slider.setValue(min);
+			}
+			slider.setMajorTickSpacing((int) ((max - min) / 5));
+			slider.setMinorTickSpacing((int) ((max - min) / 10));
+		} else if (param instanceof FloatParam) {
+			valueType = Double.class;
+
+			double min = param.getMin(Double.class) * div;
+			slider.setMinimum((int) min);
+			double max = param.getMax(Double.class) * div;
+			double diff = max - min;
+			slider.setMaximum((int) max);
+
+			Hashtable<Integer, java.awt.Component> labels = new Hashtable<Integer, java.awt.Component>();
+			int ticks = 6;
+			for (int i = 0; i <= ticks; i++) {
+				double val = (diff / ticks) * i + min;
+				String label = String.format("%1$.1f", (val / 10)).replace(",",
+						".");
+				labels.put((int) val, new JLabel(label, JLabel.CENTER));
+			}
+			slider.setLabelTable(labels);
+			slider.setMajorTickSpacing((int) (diff / 5));
+			slider.setMinorTickSpacing((int) (diff / 10));
+			if (param.getDef(Double.class) != null) {
+				double defaultValue = param.getDef(Double.class) * div;
+				slider.setValue((int) defaultValue);
+			}
+		}
+		slider.setPaintLabels(true);
+		slider.setPaintTicks(true);
+
+		this.setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS));
+		this.setAlignmentX(Box.CENTER_ALIGNMENT);
+		this.setAlignmentY(Box.CENTER_ALIGNMENT);
+
+		JPanel sliderPanel = new JPanel();
+		sliderPanel.setLayout(new BoxLayout(sliderPanel, BoxLayout.LINE_AXIS));
+
+
+		Layout.fixComponentSize(text, new Dimension(90, Control.LINE_HEIGHT));
+		text.setHorizontalAlignment(JSlider.CENTER);
+
+		text.setEnabled(!param.hasFlag(Flags.READONLY));
+
+		slider.addChangeListener(new ChangeListener() {
+			@Override
+			public void stateChanged(ChangeEvent e) {
+				if (changing != null) {
+					return;
+				}
+				log.trace("changing " + getParam() + " with slider: " + slider.getValue());
+				changing = slider;
+				text.setText(convertFromSliderDomain(slider.getValue()).toString());
+				changing = null;
+			}
+		});
+
+		text.getDocument().addDocumentListener(createDocumentListener(new Runnable() {
+			@Override
+			public void run() {
+				if (changing != null) {
+					return;
+				}
+				log.trace("changing " + getParam() + " with text: " + text.getText());
+				changing = text;
+				Integer i = convertToSliderDomain(convertTextToNumber());
+				if (i != null) {
+					slider.setValue(i);
+				}
+				changing = null;
+				notifyOfChange();
+			}
+		}));
+
+		JPanel sVPanel = new JPanel();
+		sVPanel.setLayout(new BoxLayout(sVPanel, BoxLayout.LINE_AXIS));
+		sVPanel.add(text);
+		Layout.copyComponentDimensions(sVPanel, text);
+
+		JPanel sPanel = new JPanel();
+		sPanel.setLayout(new BoxLayout(sPanel, BoxLayout.LINE_AXIS));
+
+		sliderPanel.setLayout(new BorderLayout());
+		sliderPanel.add(slider, BorderLayout.CENTER);
+		sliderPanel.setMaximumSize(new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE));
+		sliderPanel.setMinimumSize(new Dimension(0, 60));
+
+		sPanel.add(sVPanel);
+		sPanel.add(sliderPanel);
+
+		this.add(sPanel);
+	}
+
+	@Override
+	public NumberParam<?> getParam() {
+		return (NumberParam<?>) param;
+	}
+
+	private Number convertFromSliderDomain(int value) {
+		if (param instanceof DecimalParam) {
+			return value;
+		}
+		if (param instanceof FloatParam) {
+			return (double) value / (double) div;
+		}
+		return null;
+	}
+
+	private Integer convertToSliderDomain(Number value) {
+		if (value == null) {
+			return null;
+		}
+		if (param instanceof DecimalParam) {
+			return (Integer) value;
+		}
+		if (param instanceof FloatParam) {
+			return (int) ((Double) value * div);
+		}
+		return null;
+	}
+
+	private Number convertTextToNumber() {
+		return Numbers.cast(text.getText(), valueType);
+	}
+
+	@Override
+	public void pushValueToUserInterfaceImpl(Object value) {
+		if (value == null) {
+			return;
+		}
+		text.setText(value.toString());
+	}
+
+	@Override
+	public Number pullValueFromUserInterface() {
+		return convertTextToNumber();
+	}
+
+}
Index: java/main/src/main/java/com/framsticks/gui/controls/TextAreaControl.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/controls/TextAreaControl.java	(revision 84)
+++ java/main/src/main/java/com/framsticks/gui/controls/TextAreaControl.java	(revision 84)
@@ -0,0 +1,50 @@
+package com.framsticks.gui.controls;
+
+import com.framsticks.params.PrimitiveParam;
+
+import javax.swing.*;
+import java.awt.*;
+
+@SuppressWarnings("serial")
+public class TextAreaControl extends TextControl {
+
+	// private static final Logger log = Logger.getLogger(TextAreaControl.class.getName());
+
+	protected JTextArea textArea;
+	protected JScrollPane textScrollPane;
+
+	public TextAreaControl(PrimitiveParam valueParam) {
+		super(valueParam);
+		textArea = new JTextArea();
+		textArea.setLineWrap(true);
+		textArea.setWrapStyleWord(true);
+		textArea.setEditable(!isReadOnly());
+		addDefaultDocumentListener(textArea);
+
+		textScrollPane = new JScrollPane(textArea);
+		this.setLayout(new BorderLayout());
+		this.add(textScrollPane, BorderLayout.CENTER);
+		this.setMaximumSize(new Dimension(Integer.MAX_VALUE, LINE_HEIGHT * 3));
+		textArea.setMaximumSize(new Dimension(Integer.MAX_VALUE, LINE_HEIGHT * 3));
+
+		this.revalidate();
+	}
+
+	@Override
+	public Dimension getPreferredSize() {
+		Dimension result = super.getPreferredSize();
+		return new Dimension(result.width, Math.min(result.height, this.getMaximumSize().height));
+	}
+
+	@Override
+	public void pushValueToUserInterfaceImpl(Object value) {
+		textArea.setText((String) value);
+		this.revalidate();
+	}
+
+	@Override
+	public Object pullValueFromUserInterface() {
+		return textArea.getText();
+	}
+
+}
Index: java/main/src/main/java/com/framsticks/gui/controls/TextControl.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/controls/TextControl.java	(revision 84)
+++ java/main/src/main/java/com/framsticks/gui/controls/TextControl.java	(revision 84)
@@ -0,0 +1,43 @@
+package com.framsticks.gui.controls;
+
+import javax.swing.event.DocumentEvent;
+import javax.swing.event.DocumentListener;
+import javax.swing.text.JTextComponent;
+
+import com.framsticks.params.PrimitiveParam;
+
+@SuppressWarnings("serial")
+public abstract class TextControl extends ValueControl {
+
+	public TextControl(PrimitiveParam valueParam) {
+		super(valueParam);
+	}
+
+	protected void addDefaultDocumentListener(JTextComponent text) {
+		text.getDocument().addDocumentListener(createDocumentListener(new Runnable() {
+			@Override
+			public void run() {
+				notifyOfChange();
+			}
+		}));
+	}
+
+	protected static DocumentListener createDocumentListener(final Runnable runnable) {
+		return new DocumentListener() {
+			@Override
+			public void insertUpdate(DocumentEvent documentEvent) {
+				runnable.run();
+			}
+
+			@Override
+			public void removeUpdate(DocumentEvent documentEvent) {
+				runnable.run();
+			}
+
+			@Override
+			public void changedUpdate(DocumentEvent documentEvent) {
+				runnable.run();
+			}
+		};
+	}
+}
Index: java/main/src/main/java/com/framsticks/gui/controls/TextFieldControl.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/controls/TextFieldControl.java	(revision 84)
+++ java/main/src/main/java/com/framsticks/gui/controls/TextFieldControl.java	(revision 84)
@@ -0,0 +1,49 @@
+package com.framsticks.gui.controls;
+
+import com.framsticks.params.PrimitiveParam;
+import com.framsticks.util.lang.Strings;
+
+import javax.swing.*;
+import java.awt.*;
+
+@SuppressWarnings("serial")
+public class TextFieldControl extends TextControl {
+
+
+	private static final Color CORRECT_COLOR = new Color(180, 255, 215);
+	private static final Color WRONG_COLOR = new Color(255, 180, 215);
+
+	protected final JTextField textField;
+
+	@Override
+	protected boolean notifyOfChange() {
+		boolean result = super.notifyOfChange();
+		textField.setBackground(result ? CORRECT_COLOR : WRONG_COLOR);
+		return result;
+	}
+
+	public TextFieldControl(PrimitiveParam valueParam) {
+		super(valueParam);
+		textField = new JTextField();
+
+		textField.setMinimumSize(new Dimension(0, Control.LINE_HEIGHT));
+		this.setMaximumSize(new Dimension(Integer.MAX_VALUE, Control.LINE_HEIGHT));
+
+		textField.setEditable(!isReadOnly());
+
+		addDefaultDocumentListener(textField);
+
+		addAsOnlyChild(textField);
+	}
+
+	@Override
+	public void pushValueToUserInterfaceImpl(Object text) {
+		textField.setText(Strings.toStringNullProof(text));
+	}
+
+	@Override
+	public Object pullValueFromUserInterface() {
+		return textField.getText();
+	}
+
+}
Index: java/main/src/main/java/com/framsticks/gui/controls/ValueControl.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/controls/ValueControl.java	(revision 84)
+++ java/main/src/main/java/com/framsticks/gui/controls/ValueControl.java	(revision 84)
@@ -0,0 +1,96 @@
+package com.framsticks.gui.controls;
+
+import org.apache.log4j.Logger;
+
+import com.framsticks.params.CastFailure;
+import com.framsticks.params.Flags;
+import com.framsticks.params.PrimitiveParam;
+import com.framsticks.params.ReassignResult;
+import com.framsticks.util.swing.TooltipConstructor;
+
+/**
+ * @author Piotr Sniegowski
+ */
+@SuppressWarnings("serial")
+public abstract class ValueControl extends Control {
+	private static final Logger log =
+		Logger.getLogger(ValueControl.class);
+
+	/**
+	 *
+	 */
+	protected ValueControlListener listener;
+
+	public ValueControl(PrimitiveParam primitiveParam) {
+		super(primitiveParam);
+
+		this.setToolTipText(new TooltipConstructor()
+			.append("name", primitiveParam.getName())
+			.append("id", primitiveParam.getId())
+			.append("help", primitiveParam.getHelp())
+			.append("def", primitiveParam.getDef(Object.class))
+			.append("min", primitiveParam.getMin(Object.class))
+			.append("max", primitiveParam.getMax(Object.class))
+			.append("flags", Flags.write(primitiveParam.getFlags(), null))
+			.append("group", primitiveParam.getGroup())
+			.append("extra", primitiveParam.getExtra())
+			.build())
+			;
+	}
+
+	@Override
+	public PrimitiveParam getParam() {
+		return (PrimitiveParam) param;
+	}
+
+	protected abstract void pushValueToUserInterfaceImpl(Object value);
+
+	/** I consider this an ugly solution, but I was unable to find proper
+	 * action listeners for underlying swing controls, that would only fire
+	 * on user change and on programmatic change.
+	 */
+	protected boolean programmaticChange = false;
+
+	public void pushValueToUserInterface(Object value) {
+		programmaticChange = true;
+		pushValueToUserInterfaceImpl(value);
+		programmaticChange = false;
+	}
+
+	public abstract Object pullValueFromUserInterface();
+
+	public void setListener(ValueControlListener listener) {
+		this.listener = listener;
+	}
+
+	protected Object filterValueThroughConstraints(Object candidate) {
+		Object oldValue = pullValueFromUserInterface();
+		try {
+			ReassignResult<?> res = getParam().reassign(candidate, oldValue);
+			if (res.getFlags() != 0) {
+				log.warn("filter of param " + param + " failed: " + Flags.write(res.getFlags(), "0"));
+			}
+			return res.getValue();
+		} catch (CastFailure e) {
+			log.error("cast failure when setting param " + param + " to value " + candidate + ": " + e);
+		}
+		return oldValue;
+	}
+
+	protected boolean notifyOfChange() {
+		if (!programmaticChange) {
+			if (listener == null) {
+				return true;
+			}
+			return listener.onChange(filterValueThroughConstraints(pullValueFromUserInterface()));
+		}
+		return true;
+	}
+
+	public final boolean isReadOnly() {
+		return (param.getFlags() & Flags.READONLY) != 0;
+	}
+
+
+
+}
Index: java/main/src/main/java/com/framsticks/gui/controls/ValueControlListener.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/controls/ValueControlListener.java	(revision 84)
+++ java/main/src/main/java/com/framsticks/gui/controls/ValueControlListener.java	(revision 84)
@@ -0,0 +1,8 @@
+package com.framsticks.gui.controls;
+
+/**
+ * @author Piotr Sniegowski
+ */
+public interface ValueControlListener {
+	public boolean onChange(Object newValue);
+}
Index: java/main/src/main/java/com/framsticks/gui/view/ColumnMenuItem.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/view/ColumnMenuItem.java	(revision 79)
+++ java/main/src/main/java/com/framsticks/gui/view/ColumnMenuItem.java	(revision 84)
@@ -46,5 +46,5 @@
 		this.addItemListener(new ItemListener() {
 			public void itemStateChanged(ItemEvent e) {
-				if (e.getStateChange() == e.SELECTED) {
+				if (e.getStateChange() == ItemEvent.SELECTED) {
 					columnManager.addColumn(ColumnMenuItem.this.columnName,
 							ColumnMenuItem.this.columnId,
Index: java/main/src/main/java/com/framsticks/gui/view/TreeCellRenderer.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/view/TreeCellRenderer.java	(revision 79)
+++ java/main/src/main/java/com/framsticks/gui/view/TreeCellRenderer.java	(revision 84)
@@ -6,4 +6,7 @@
 import javax.swing.*;
 import javax.swing.tree.DefaultTreeCellRenderer;
+
+import org.apache.log4j.Logger;
+
 import java.awt.*;
 
@@ -13,15 +16,18 @@
 @SuppressWarnings("serial")
 public class TreeCellRenderer extends DefaultTreeCellRenderer {
+	private static final Logger log =
+		Logger.getLogger(TreeCellRenderer.class);
 
-    public TreeCellRenderer() {
-        setOpenIcon(null);
-        setClosedIcon(null);
-        setLeafIcon(null);
-    }
+
+	public TreeCellRenderer() {
+		setOpenIcon(null);
+		setClosedIcon(null);
+		setLeafIcon(null);
+	}
 
 	@Override
 	public Component getTreeCellRendererComponent(JTree tree, Object value,
-	                                              boolean sel, boolean expanded, boolean leaf, int row,
-	                                              boolean hasFocus) {
+			boolean sel, boolean expanded, boolean leaf, int row,
+			boolean hasFocus) {
 
 		//super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf,
@@ -31,21 +37,23 @@
 		}
 		if (!(value instanceof TreeNode)) {
-            setIcon(ImageProvider.loadImage(ImageProvider.SERVER));
-            setText("framsticks");
+			setIcon(ImageProvider.loadImage(ImageProvider.SERVER));
+			setText("framsticks");
 			return this;
 		}
 		TreeNode treeNode = (TreeNode)value;
-        assert treeNode.getFrame().isActive();
-        setToolTipText(treeNode.getTooltip());
-        setIcon(ImageProvider.loadImage(treeNode.getIconName()));
-        setText(treeNode.getName());
+		assert treeNode.getFrame().isActive();
+		setToolTipText(treeNode.getTooltip());
+		setIcon(ImageProvider.loadImage(treeNode.getIconName()));
+		setText(treeNode.getName());
 		return this;
 	}
 
 	public static String findIconName(String nodeName, String path) {
-        if (path == null || nodeName == null) {
-            return null;
-        }
-        if (path.equals("/")) {
+		if (nodeName == null || path == null) {
+			log.warn("given invalid parameters: " + nodeName + " " + path);
+			// return null;
+			return ImageProvider.SERVER;
+		}
+		if (path.equals("/")) {
 			return ImageProvider.SERVER;
 		}
@@ -133,5 +141,5 @@
 		return ImageProvider.SERVER;
 	}
-	
-	
+
+
 }
Index: java/main/src/main/java/com/framsticks/gui/windows/ServerLogFrame.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/windows/ServerLogFrame.java	(revision 79)
+++ java/main/src/main/java/com/framsticks/gui/windows/ServerLogFrame.java	(revision 84)
@@ -2,5 +2,4 @@
 
 import com.framsticks.gui.ImageProvider;
-import com.framsticks.gui.components.Control;
 import org.apache.log4j.Logger;
 
Index: java/main/src/main/java/com/framsticks/gui/windows/console/ConsoleFrame.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/windows/console/ConsoleFrame.java	(revision 79)
+++ java/main/src/main/java/com/framsticks/gui/windows/console/ConsoleFrame.java	(revision 84)
@@ -3,6 +3,6 @@
 import com.framsticks.communication.*;
 import com.framsticks.gui.ImageProvider;
-import com.framsticks.util.Pair;
-import com.framsticks.util.Strings;
+import com.framsticks.util.lang.Pair;
+import com.framsticks.util.lang.Strings;
 import org.apache.log4j.Logger;
 
@@ -19,19 +19,19 @@
 public class ConsoleFrame extends JFrame {
 
-	private static final Logger LOGGER = Logger.getLogger(ConsoleFrame.class.getName());
-
-	/**
-     * Painter coloring manager responses before display.
-     */
-    private final ConsolePainter consolePainter;
-
-    /**
-     * Text field for typing commands.
-     */
-    private final JTextField commandLine;
-	/**
-     * Reference to connection.
-     */
-    protected final ClientConnection connection;
+	private static final Logger log = Logger.getLogger(ConsoleFrame.class.getName());
+
+	/**
+	 * Painter coloring manager responses before display.
+	 */
+	private final ConsolePainter consolePainter;
+
+	/**
+	 * Text field for typing commands.
+	 */
+	private final JTextField commandLine;
+	/**
+	 * Reference to connection.
+	 */
+	protected final ClientConnection connection;
 
 	/**
@@ -52,76 +52,76 @@
 
 	/**
-     * Default constructor creates frame with console.
-     */
-    @SuppressWarnings("unchecked")
-    public ConsoleFrame(ClientConnection connection) {
-	    this.connection = connection;
-        this.setTitle("Console");
-        this.setLayout(new BorderLayout());
-        this.setSize(new Dimension(440, 400));
-        this.setMinimumSize(new Dimension(440, 400));
-        this.setIconImage(ImageProvider.loadImage(ImageProvider.LOGO).getImage());
-        JFrame.setDefaultLookAndFeelDecorated(true);
-
-	    JTextPane text = new JTextPane();
-        consolePainter = new ConsolePainter(text);
-
-        text.setEditable(false);
-        final JScrollPane scrollText = new JScrollPane(text);
-        scrollText.setBorder(BorderFactory.createEtchedBorder());
-
-        JPanel scrollPanel = new JPanel();
-        scrollPanel.setLayout(new BorderLayout());
-        scrollPanel.add(scrollText, BorderLayout.CENTER);
-        scrollPanel.setBorder(BorderFactory.createEmptyBorder(7, 7, 7, 7));
-
-        commandLine = new JTextField();
-
-        commandLine.addKeyListener(new KeyListener() {
-	        @Override
-	        public void keyTyped(KeyEvent e) {
-
-	        }
-
-	        @Override
-	        public void keyPressed(KeyEvent e) {
-		        onKeyPressed(e.getKeyCode());
-	        }
-
-	        @Override
-	        public void keyReleased(KeyEvent e) {
-	        }
-        });
-
-        commandLine.setFocusTraversalKeys(
-		        KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
-		        Collections.EMPTY_SET);
-
-        this.addWindowListener(new WindowAdapter() {
-            public void windowActivated(WindowEvent e) {
-                commandLine.requestFocusInWindow();
-            }
-        });
-
-	    JButton sendButton = new JButton("Send");
-        sendButton.addActionListener(new ActionListener() {
-
-	        public void actionPerformed(final ActionEvent e) {
-		        buttonSendAction();
-	        }
-
-        });
-
-        final Box cmdBox = new Box(BoxLayout.LINE_AXIS);
-        cmdBox.add(commandLine);
-        cmdBox.add(Box.createHorizontalStrut(10));
-        cmdBox.add(sendButton);
-        cmdBox.setBorder(BorderFactory.createEmptyBorder(0, 7, 7, 7));
-
-        this.getContentPane().add(scrollPanel, BorderLayout.CENTER);
-        this.getContentPane().add(cmdBox, BorderLayout.PAGE_END);
-        this.setVisible(false);
-
-    }
+	 * Default constructor creates frame with console.
+	 */
+	@SuppressWarnings("unchecked")
+	public ConsoleFrame(ClientConnection connection) {
+		this.connection = connection;
+		this.setTitle("Console");
+		this.setLayout(new BorderLayout());
+		this.setSize(new Dimension(440, 400));
+		this.setMinimumSize(new Dimension(440, 400));
+		this.setIconImage(ImageProvider.loadImage(ImageProvider.LOGO).getImage());
+		JFrame.setDefaultLookAndFeelDecorated(true);
+
+		JTextPane text = new JTextPane();
+		consolePainter = new ConsolePainter(text);
+
+		text.setEditable(false);
+		final JScrollPane scrollText = new JScrollPane(text);
+		scrollText.setBorder(BorderFactory.createEtchedBorder());
+
+		JPanel scrollPanel = new JPanel();
+		scrollPanel.setLayout(new BorderLayout());
+		scrollPanel.add(scrollText, BorderLayout.CENTER);
+		scrollPanel.setBorder(BorderFactory.createEmptyBorder(7, 7, 7, 7));
+
+		commandLine = new JTextField();
+
+		commandLine.addKeyListener(new KeyListener() {
+			@Override
+			public void keyTyped(KeyEvent e) {
+
+			}
+
+			@Override
+			public void keyPressed(KeyEvent e) {
+				onKeyPressed(e.getKeyCode());
+			}
+
+			@Override
+			public void keyReleased(KeyEvent e) {
+			}
+		});
+
+		commandLine.setFocusTraversalKeys(
+				KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
+				Collections.EMPTY_SET);
+
+		this.addWindowListener(new WindowAdapter() {
+			public void windowActivated(WindowEvent e) {
+				commandLine.requestFocusInWindow();
+			}
+		});
+
+		JButton sendButton = new JButton("Send");
+		sendButton.addActionListener(new ActionListener() {
+
+			public void actionPerformed(final ActionEvent e) {
+				buttonSendAction();
+			}
+
+		});
+
+		final Box cmdBox = new Box(BoxLayout.LINE_AXIS);
+		cmdBox.add(commandLine);
+		cmdBox.add(Box.createHorizontalStrut(10));
+		cmdBox.add(sendButton);
+		cmdBox.setBorder(BorderFactory.createEmptyBorder(0, 7, 7, 7));
+
+		this.getContentPane().add(scrollPanel, BorderLayout.CENTER);
+		this.getContentPane().add(cmdBox, BorderLayout.PAGE_END);
+		this.setVisible(false);
+
+	}
 
 	public void setCommandLine(String command) {
@@ -130,55 +130,55 @@
 
 
-    /**
-     * Shows console frame, sets location relative to parent.
-     *
-     * @param parent Frame relative to which console window will be localized.
-     */
-    public void show(JFrame parent) {
-        final Point parentLocation = parent.getLocation();
-        final Point location = new Point(parentLocation.x + 20, parentLocation.y + 20);
-        this.setLocation(location);
-        this.setVisible(true);
-    }
-
-    /**
-     * Adds query to console window.
-     *
-     * @param line Line of string query.
-     */
-    private void addQuery(String line) {
-        consolePainter.userMsg(line + "\n");
-    }
-
-
-    /**
-     * Sends message to manager and adds message to console frame.
-     */
-    public void buttonSendAction() {
-        if (!connection.isConnected()) {
-            JOptionPane.showMessageDialog(this, "missing connection to manager");
-            return;
-        }
-        String commandText = commandLine.getText();
-	    Pair<String, String> command = Strings.splitIntoPair(commandText, ' ', "\n");
-        Request request = Request.createRequestByTypeString(command.first);
-        if (request == null) {
-            LOGGER.warn("not a valid request: " + commandText);
-            return;
-        }
-        request.parseRest(command.second);
-
-	    addQuery(commandText);
-	    addSentMessage(commandText);
-	    commandLine.setText("");
-        connection.send(request, new ResponseCallback() {
-            @Override
-            public void process(Response response) {
-                for (File f : response.getFiles()) {
-                    consolePainter.paintMessage(f);
-                }
-            }
-        });
-    }
+	/**
+	 * Shows console frame, sets location relative to parent.
+	 *
+	 * @param parent Frame relative to which console window will be localized.
+	 */
+	public void show(JFrame parent) {
+		final Point parentLocation = parent.getLocation();
+		final Point location = new Point(parentLocation.x + 20, parentLocation.y + 20);
+		this.setLocation(location);
+		this.setVisible(true);
+	}
+
+	/**
+	 * Adds query to console window.
+	 *
+	 * @param line Line of string query.
+	 */
+	private void addQuery(String line) {
+		consolePainter.userMsg(line + "\n");
+	}
+
+
+	/**
+	 * Sends message to manager and adds message to console frame.
+	 */
+	public void buttonSendAction() {
+		if (!connection.isConnected()) {
+			JOptionPane.showMessageDialog(this, "missing connection to manager");
+			return;
+		}
+		String commandText = commandLine.getText();
+		Pair<String, String> command = Strings.splitIntoPair(commandText, ' ', "\n");
+		Request request = Request.createRequestByTypeString(command.first);
+		if (request == null) {
+			log.warn("not a valid request: " + commandText);
+			return;
+		}
+		request.parseRest(command.second);
+
+		addQuery(commandText);
+		addSentMessage(commandText);
+		commandLine.setText("");
+		connection.send(request, new ResponseCallback() {
+			@Override
+			public void process(Response response) {
+				for (File f : response.getFiles()) {
+					consolePainter.paintMessage(f);
+				}
+			}
+		});
+	}
 
 	private void onKeyPressed(int keyCode) {
Index: java/main/src/main/java/com/framsticks/gui/windows/console/ConsolePainter.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/windows/console/ConsolePainter.java	(revision 79)
+++ java/main/src/main/java/com/framsticks/gui/windows/console/ConsolePainter.java	(revision 84)
@@ -2,6 +2,5 @@
 
 import com.framsticks.communication.File;
-import com.framsticks.params.SourceInterface;
-import org.apache.log4j.Logger;
+// import org.apache.log4j.Logger;
 
 import java.awt.Color;
@@ -16,17 +15,17 @@
  */
 public class ConsolePainter {
-	private static final Logger LOGGER = Logger.getLogger(ConsolePainter.class.getName());
+	// private static final Logger log = Logger.getLogger(ConsolePainter.class.getName());
 
 	private Document doc;
 	private JTextPane textPane;
-	private Color c1 = new Color(192, 0, 0);
-	private Color c2 = new Color(84, 141, 212);
-	private Color c3 = new Color(118, 146, 60);
-	private Color c4 = new Color(0, 0, 128);
+	// private Color c1 = new Color(192, 0, 0);
+	// private Color c2 = new Color(84, 141, 212);
+	// private Color c3 = new Color(118, 146, 60);
+	// private Color c4 = new Color(0, 0, 128);
 	private SimpleLinePainter linePainter1;
 	private SimpleLinePainter linePainter2;
 	private final SimpleAttributeSet set = new SimpleAttributeSet();
 
-	
+
 	/**
 	 * Constructor sets reference to pane with text.
@@ -47,6 +46,6 @@
 
 		String line;
-		Boolean boldNextId = false;
-		Boolean doNotPaint = false;
+		// Boolean boldNextId = false;
+		// Boolean doNotPaint = false;
 
 		while ((line = file.getContent().readLine()) != null) {
@@ -113,5 +112,5 @@
 
 		scrollDown();
-		
+
 	}
 
@@ -166,16 +165,16 @@
 	 * @return First word in text line (with space char).
 	 */
-	private String firstWord(String line) {
-		String result;
-		int spaceIndex = line.indexOf(' ');
-
-		if (spaceIndex == -1) {
-			result = line;
-		} else {
-			result = line.substring(0, spaceIndex + 1);
-		}
-
-		return result;
-	}
+	// private String firstWord(String line) {
+	// 	String result;
+	// 	int spaceIndex = line.indexOf(' ');
+
+	// 	if (spaceIndex == -1) {
+	// 		result = line;
+	// 	} else {
+	// 		result = line.substring(0, spaceIndex + 1);
+	// 	}
+
+	// 	return result;
+	// }
 
 	/**
Index: java/main/src/main/java/com/framsticks/hosting/InstanceClient.java
===================================================================
--- java/main/src/main/java/com/framsticks/hosting/InstanceClient.java	(revision 79)
+++ java/main/src/main/java/com/framsticks/hosting/InstanceClient.java	(revision 84)
@@ -9,5 +9,5 @@
 import com.framsticks.parsers.Savers;
 import com.framsticks.core.LocalInstance;
-import com.framsticks.util.Future;
+import com.framsticks.util.dispatching.Future;
 
 import java.net.Socket;
@@ -21,74 +21,74 @@
 public class InstanceClient implements RequestHandler {
 
-    protected final LocalInstance instance;
-    protected final ServerConnection connection;
+	protected final LocalInstance instance;
+	protected final ServerConnection connection;
 
-    public InstanceClient(LocalInstance instance, Socket socket) {
-        this.instance = instance;
-        connection = new ServerConnection(socket, this);
-        connection.start();
-    }
+	public InstanceClient(LocalInstance instance, Socket socket) {
+		this.instance = instance;
+		connection = new ServerConnection(socket, this);
+		connection.start();
+	}
 
-    @Override
-    public String toString() {
-        return instance + "|" + connection.toString();
-    }
+	@Override
+	public String toString() {
+		return instance + "|" + connection.toString();
+	}
 
 
-    @Override
-    public void handle(final ApplicationRequest request, final ResponseCallback responseCallback) {
-        instance.invokeLater(new Runnable() {
-            @Override
-            public void run() {
-                final Path path = new Path(instance, request.getPath());
-                if (!path.isResolved(request.getPath())) {
-                    responseCallback.process(new Response(false, "\"invalid path\"", null));
-                    return;
-                }
-                if (request instanceof GetRequest) {
-                    instance.findInfo(path, new Future<FramsClass>() {
-                        @Override
-                        public void result(FramsClass result, Exception e) {
-                            if (result == null) {
-                                responseCallback.process(new Response(false, "\"failed to find info for access bind\"", null));
-                                return;
-                            }
-                            List<File> files = new LinkedList<File>();
-                            AccessInterface access = instance.bindAccess(path);
+	@Override
+	public void handle(final ApplicationRequest request, final ResponseCallback responseCallback) {
+		instance.invokeLater(new Runnable() {
+			@Override
+			public void run() {
+				final Path path = instance.getPath(request.getPath());
+				if (!path.isResolved(request.getPath())) {
+					responseCallback.process(new Response(false, "\"invalid path\"", null));
+					return;
+				}
+				if (request instanceof GetRequest) {
+					instance.findInfo(path, new Future<FramsClass>() {
+						@Override
+						public void result(FramsClass result, Exception e) {
+							if (result == null) {
+								responseCallback.process(new Response(false, "\"failed to find info for access bind\"", null));
+								return;
+							}
+							List<File> files = new LinkedList<File>();
+							AccessInterface access = instance.bindAccess(path);
 
-                            if (access == null) {
+							if (access == null) {
 
-                                responseCallback.process(new Response(false, "\"failed to bind access\"", null));
-                                return;
-                            }
-                            ListSink sink = new ListSink();
-                            access.save(sink);
-                            files.add(new File(path.getTextual(), new ListSource(sink.getOut())));
-                            responseCallback.process(new Response(true, "", files));
-                        }
-                    });
-                    return;
-                }
-                if (request instanceof InfoRequest) {
-                    instance.findInfo(path, new Future<FramsClass>() {
-                        @Override
-                        public void result(FramsClass result, Exception e) {
-                            if (result == null) {
-                                responseCallback.process(new Response(false, "\"info not found\"", null));
-                                return;
-                            }
-                            ListSink sink = new ListSink();
-                            Savers.saveFramsClass(sink, result);
-                            List<File> files = new ArrayList<File>();
-                            files.add(new File(path.getTextual(), new ListSource(sink.getOut())));
-                            responseCallback.process(new Response(true, null, files));
-                        }
-                    });
-                    return;
-                }
-                responseCallback.process(new Response(false, "invalid", null));
-            }
-        });
+								responseCallback.process(new Response(false, "\"failed to bind access\"", null));
+								return;
+							}
+							ListSink sink = new ListSink();
+							access.save(sink);
+							files.add(new File(path.getTextual(), new ListSource(sink.getOut())));
+							responseCallback.process(new Response(true, "", files));
+						}
+					});
+					return;
+				}
+				if (request instanceof InfoRequest) {
+					instance.findInfo(path, new Future<FramsClass>() {
+						@Override
+						public void result(FramsClass result, Exception e) {
+							if (result == null) {
+								responseCallback.process(new Response(false, "\"info not found\"", null));
+								return;
+							}
+							ListSink sink = new ListSink();
+							Savers.saveFramsClass(sink, result);
+							List<File> files = new ArrayList<File>();
+							files.add(new File(path.getTextual(), new ListSource(sink.getOut())));
+							responseCallback.process(new Response(true, null, files));
+						}
+					});
+					return;
+				}
+				responseCallback.process(new Response(false, "invalid", null));
+			}
+		});
 
-    }
+	}
 }
Index: java/main/src/main/java/com/framsticks/hosting/ServerInstance.java
===================================================================
--- java/main/src/main/java/com/framsticks/hosting/ServerInstance.java	(revision 79)
+++ java/main/src/main/java/com/framsticks/hosting/ServerInstance.java	(revision 84)
@@ -2,9 +2,11 @@
 
 import com.framsticks.core.*;
+import com.framsticks.params.CompositeParam;
 import com.framsticks.params.FramsClass;
 import com.framsticks.params.ParamBuilder;
-import com.framsticks.params.types.CompositeParam;
 import com.framsticks.core.LocalInstance;
-import com.framsticks.util.Future;
+import com.framsticks.util.dispatching.Future;
+
+import org.apache.commons.configuration.Configuration;
 import org.apache.log4j.Logger;
 
@@ -14,73 +16,73 @@
 public class ServerInstance extends LocalInstance {
 
-    private final static Logger LOGGER = Logger.getLogger(ServerInstance.class.getName());
+	private final static Logger log = Logger.getLogger(ServerInstance.class.getName());
 
-    Entity hosted;
+	Entity hosted;
 
-    public ServerInstance(Parameters parameters) {
-        super(parameters);
-    }
+	public ServerInstance() {
+	}
 
-    @Override
-    protected void run() {
-        super.run();
-        assert hosted != null;
-        hosted.start();
-    }
+	@Override
+	protected void run() {
+		super.run();
+		assert hosted != null;
+		hosted.start();
+	}
 
-    @Override
-    protected void configure() throws Exception {
-        super.configure();
+	@Override
+	public void configure(Configuration config) {
+		super.configure(config);
 
-        Parameters p = new Parameters(config.subset("hosted.entity"), "hosted", this, null);
-        hosted = Program.configureEntity(p);
-        if (hosted == null) {
-            LOGGER.fatal("failed to create hosted entity");
-            return;
-        }
-        hosted.configurePublic();
-        root = new Node((CompositeParam)new ParamBuilder().setName("root").setId("root").setType("o" + hosted.getClass().getCanonicalName()).build(), hosted);
-    }
+		Configuration hostedConfig = config.subset("hosted.entity");
+		hosted = Program.configureEntity(hostedConfig);
+		if (hosted == null) {
+			log.fatal("failed to create hosted entity");
+			return;
+		}
+		hosted.setName("hosted");
+		hosted.configure(hostedConfig);
+		root = new Node((CompositeParam)new ParamBuilder().setName("root").setId("root").setType("o" + hosted.getClass().getCanonicalName()).build(), hosted);
+	}
 
-    @Override
-    public FramsClass getInfoFromCache(String id) {
-        assert isActive();
-        if (id == null) {
-            return null;
-        }
+	@Override
+	public FramsClass getInfoFromCache(String id) {
+		assert isActive();
+		if (id == null) {
+			return null;
+		}
 		FramsClass cached = registry.getInfoFromCache(id);
-        if (cached != null) {
+		if (cached != null) {
 			return cached;
-        }
-        try {
-            Class nativeClass = Class.forName(id);
-            FramsClass framsClass = new FramsClass.Constructor(nativeClass, id).getResult();
+		}
+		try {
+			Class<?> nativeClass = Class.forName(id);
+			FramsClass framsClass = new FramsClass.Constructor(nativeClass, id).getResult();
 
-            registry.registerReflectedClass(null, id, nativeClass);
-            registry.putInfoIntoCache(framsClass);
-            return framsClass;
-        } catch (ClassNotFoundException ignored) {
-        }
+			registry.registerReflectedClass(null, id, nativeClass);
+			registry.putInfoIntoCache(framsClass);
+			return framsClass;
+		} catch (ClassNotFoundException ignored) {
+		}
 
-        return null;
-    }
+		return null;
+	}
 
-    @Override
-    protected void fetchInfo(Path path, Future<FramsClass> future) {
-        assert isActive();
+	@Override
+	protected void fetchInfo(Path path, Future<FramsClass> future) {
+		assert isActive();
 
-        FramsClass framsClass = getInfoFromCache(path.getTop().getObject().getClass().getCanonicalName());
-        if (framsClass == null) {
-            LOGGER.error("failed to create frams class for: " + path.getTop().getObject().getClass());
-            future.result(null, new Exception());
-            return;
-        }
-        future.result(framsClass, null);
+		FramsClass framsClass = getInfoFromCache(path.getTop().getObject().getClass().getCanonicalName());
+		if (framsClass == null) {
+			log.error("failed to create frams class for: " + path.getTop().getObject().getClass());
+			future.result(null, new Exception());
+			return;
+		}
+		future.result(framsClass, null);
 
-    }
+	}
 
-    @Override
-    protected void tryRegisterOnChangeEvents(Path path) {
-    }
+	@Override
+	protected void tryRegisterOnChangeEvents(Path path) {
+	}
 
 }
Index: java/main/src/main/java/com/framsticks/leftovers/FavouritesXMLFactory.java
===================================================================
--- java/main/src/main/java/com/framsticks/leftovers/FavouritesXMLFactory.java	(revision 79)
+++ java/main/src/main/java/com/framsticks/leftovers/FavouritesXMLFactory.java	(revision 84)
@@ -29,5 +29,5 @@
 	/**
 	 * Writes favourites nodes and fields list to XML file.
-	 * 
+	 *
 	 * @param path
 	 *            Path of XML file.
@@ -89,5 +89,5 @@
 	/**
 	 * Reads user favourites nodes and fields from XML file.
-	 * 
+	 *
 	 * @param filePath
 	 *            PAth to XML file.
@@ -117,5 +117,5 @@
 						if (itemDetails.item(0).getNodeName().equals(pathMark)
 								&& itemDetails.item(1).getNodeName().equals(nameMark)
-								&& (itemDetails.item(2).getNodeName().equals(fieldMark) 
+								&& (itemDetails.item(2).getNodeName().equals(fieldMark)
 										|| itemDetails.item(2).getNodeName().equals(typeMark))) {
 							path = itemDetails.item(0).getTextContent();
@@ -128,5 +128,5 @@
 							}else{
 								try {
-									int nodeTypeId = Integer.parseInt(itemDetails.item(2).getTextContent());
+									// int nodeTypeId = Integer.parseInt(itemDetails.item(2).getTextContent());
 									userNode = new UserFavourite(path, name, null);
 									result.put(path, userNode);
@@ -147,5 +147,5 @@
 	/**
 	 * Writes column configuration to XML file.
-	 * 
+	 *
 	 * @param path
 	 *            Path to XML file.
@@ -206,5 +206,5 @@
 	/**
 	 * Reads column configuration from XML file.
-	 * 
+	 *
 	 * @param path
 	 *            Path to XML file.
Index: java/main/src/main/java/com/framsticks/leftovers/f0/NeuroClass.java
===================================================================
--- java/main/src/main/java/com/framsticks/leftovers/f0/NeuroClass.java	(revision 79)
+++ java/main/src/main/java/com/framsticks/leftovers/f0/NeuroClass.java	(revision 84)
@@ -4,4 +4,5 @@
 
 import com.framsticks.params.FramsClass;
+import com.framsticks.params.Param;
 
 /**
@@ -14,20 +15,32 @@
 	*/
 
-	/** The symbol glymph. */
+	/**
+	 * The symbol glymph.
+	 */
 	private int[] symbolGlymph;
-	
-	/** The pref inputs. */
+
+	/**
+	 * The pref inputs.
+	 */
 	private int prefInputs;
-	
-	/** The pref output. */
+
+	/**
+	 * The pref output.
+	 */
 	private int prefOutput;
-	
-	/** The pref location. */
+
+	/**
+	 * The pref location.
+	 */
 	private int prefLocation;
-	
-	/** The param entry list. */
+
+	/**
+	 * The param entry list.
+	 */
 	private FramsClass framsClass;
-	
-	/** The visual hints. */
+
+	/**
+	 * The visual hints.
+	 */
 	private int visualHints;
 
@@ -53,14 +66,14 @@
 	 * Instantiates a new neuro class.
 	 *
-	 * @param framsClass the param entry list
-	 * @param prefInputs the pref inputs
-	 * @param prefOutput the pref output
+	 * @param framsClass   the param entry list
+	 * @param prefInputs   the pref inputs
+	 * @param prefOutput   the pref output
 	 * @param prefLocation the pref location
-	 * @param visualHints the visual hints
+	 * @param visualHints  the visual hints
 	 * @param symbolGlymph the symbol glymph
 	 */
 	public NeuroClass(FramsClass framsClass, int prefInputs,
-			int prefOutput, int prefLocation, int visualHints,
-			int[] symbolGlymph) {
+					  int prefOutput, int prefLocation, int visualHints,
+					  int[] symbolGlymph) {
 		super();
 		this.framsClass = framsClass;
@@ -113,8 +126,8 @@
 	 *
 	 * @return 0 if the object doesn't need any assignment to the body element.
-	 * 1 = it likes to be attached to the Part ( @see
-	 * Neuro::attachToPart() )
-	 * 2 = the object prefers to have the Joint ( @see
-	 * Neuro::attachToJoint() )
+	 *         1 = it likes to be attached to the Part ( @see
+	 *         Neuro::attachToPart() )
+	 *         2 = the object prefers to have the Joint ( @see
+	 *         Neuro::attachToJoint() )
 	 */
 	int getPreferredLocation() {
@@ -170,15 +183,18 @@
 	public String toString() {
 		StringBuilder sb = new StringBuilder();
-		sb.append("NeuroClass [getId=" + framsClass.getId() + ", getName="
-				+ framsClass.getName() + ", description="
-				+ framsClass.getDescription() + ", groups#="
-				+ framsClass.getGroupCount() + ", prefInputs=" + prefInputs
-				+ ", prefOutput=" + prefOutput + ", prefLocation="
-				+ prefLocation + ", visualHints=" + visualHints
-				+ ", symbolGlymph=" + Arrays.toString(symbolGlymph)
-				+ ", paramList={");
+		sb.append("NeuroClass [getId=").append(framsClass.getId())
+				.append(", getName=").append(framsClass.getName())
+				.append(", description=").append(framsClass.getDescription())
+				.append(", groups#=").append(framsClass.getGroupCount())
+				.append(", prefInputs=").append(prefInputs)
+				.append(", prefOutput=").append(prefOutput)
+				.append(", prefLocation=").append(prefLocation)
+				.append(", visualHints=").append(visualHints)
+				.append(", symbolGlymph=").append(Arrays.toString(symbolGlymph));
+
+		sb.append(", paramList={");
 		for (int i = 0; i < framsClass.getParamCount(); i++) {
 			sb.append("\n");
-			sb.append(framsClass.getParamEntry(i).toString());
+			sb.append(framsClass.getParamEntry(i, Param.class).toString());
 		}
 		sb.append("\n}]");
Index: java/main/src/main/java/com/framsticks/model/BaseJoint.java
===================================================================
--- java/main/src/main/java/com/framsticks/model/BaseJoint.java	(revision 79)
+++ java/main/src/main/java/com/framsticks/model/BaseJoint.java	(revision 84)
@@ -1,5 +1,5 @@
 package com.framsticks.model;
 
-import com.framsticks.util.Point3d;
+import com.framsticks.util.math.Point3d;
 
 /**
Index: java/main/src/main/java/com/framsticks/model/BasePart.java
===================================================================
--- java/main/src/main/java/com/framsticks/model/BasePart.java	(revision 79)
+++ java/main/src/main/java/com/framsticks/model/BasePart.java	(revision 84)
@@ -1,6 +1,6 @@
 package com.framsticks.model;
 
-import com.framsticks.util.Orientation;
-import com.framsticks.util.Point3d;
+import com.framsticks.util.math.Orientation;
+import com.framsticks.util.math.Point3d;
 
 /**
Index: java/main/src/main/java/com/framsticks/model/Creature.java
===================================================================
--- java/main/src/main/java/com/framsticks/model/Creature.java	(revision 79)
+++ java/main/src/main/java/com/framsticks/model/Creature.java	(revision 84)
@@ -2,6 +2,5 @@
 
 import com.framsticks.params.FramsClass;
-import com.framsticks.util.Orientation;
-import com.framsticks.util.Point3d;
+import com.framsticks.util.math.Point3d;
 
 import java.util.ArrayList;
Index: java/main/src/main/java/com/framsticks/model/Genotype.java
===================================================================
--- java/main/src/main/java/com/framsticks/model/Genotype.java	(revision 79)
+++ java/main/src/main/java/com/framsticks/model/Genotype.java	(revision 84)
@@ -2,8 +2,8 @@
 
 
-import org.apache.log4j.Logger;
+// import org.apache.log4j.Logger;
 
 public class Genotype extends Model {
-	private final static Logger LOGGER = Logger.getLogger(Genotype.class);
+	// private final static Logger log = Logger.getLogger(Genotype.class);
 
 	public String name;
Index: java/main/src/main/java/com/framsticks/model/Joint.java
===================================================================
--- java/main/src/main/java/com/framsticks/model/Joint.java	(revision 79)
+++ java/main/src/main/java/com/framsticks/model/Joint.java	(revision 84)
@@ -1,5 +1,3 @@
 package com.framsticks.model;
-
-import com.framsticks.util.Point3d;
 
 /**
Index: java/main/src/main/java/com/framsticks/model/MechJoint.java
===================================================================
--- java/main/src/main/java/com/framsticks/model/MechJoint.java	(revision 79)
+++ java/main/src/main/java/com/framsticks/model/MechJoint.java	(revision 84)
@@ -1,5 +1,3 @@
 package com.framsticks.model;
-
-import com.framsticks.util.Point3d;
 
 /**
Index: java/main/src/main/java/com/framsticks/model/MechPart.java
===================================================================
--- java/main/src/main/java/com/framsticks/model/MechPart.java	(revision 79)
+++ java/main/src/main/java/com/framsticks/model/MechPart.java	(revision 84)
@@ -1,6 +1,5 @@
 package com.framsticks.model;
 
-import com.framsticks.util.Orientation;
-import com.framsticks.util.Point3d;
+import com.framsticks.util.math.Point3d;
 
 /*
Index: java/main/src/main/java/com/framsticks/model/Model.java
===================================================================
--- java/main/src/main/java/com/framsticks/model/Model.java	(revision 79)
+++ java/main/src/main/java/com/framsticks/model/Model.java	(revision 84)
@@ -1,7 +1,8 @@
 package com.framsticks.model;
 
-import com.framsticks.util.Casting;
-import com.framsticks.util.Containers;
-import com.framsticks.util.Orientation;
+import com.framsticks.util.lang.Casting;
+import com.framsticks.util.lang.Containers;
+import com.framsticks.util.lang.IterableIterator;
+import com.framsticks.util.math.Orientation;
 import org.apache.log4j.Logger;
 
@@ -15,5 +16,5 @@
 public class Model {
 
-	private final static Logger LOGGER = Logger.getLogger(Model.class);
+	private final static Logger log = Logger.getLogger(Model.class);
 
 	public Double startingEnergy;
@@ -53,9 +54,8 @@
 		Model f0Genotype = Casting.tryCast(Model.class, i.next());
 		if (f0Genotype == null) {
-			LOGGER.fatal("first object is not a Model");
+			log.fatal("first object is not a Model");
 			return null;
 		}
-		while (i.hasNext()) {
-			Object object = i.next();
+		for (Object object : new IterableIterator<Object>(i)) {
 			if (object instanceof Joint) {
 				f0Genotype.joints.add((Joint)object);
@@ -70,5 +70,5 @@
 				continue;
 			}
-			LOGGER.error("invalid class: " + object.getClass().getCanonicalName());
+			log.error("invalid class: " + object.getClass().getCanonicalName());
 		}
 
Index: java/main/src/main/java/com/framsticks/model/Neuro.java
===================================================================
--- java/main/src/main/java/com/framsticks/model/Neuro.java	(revision 79)
+++ java/main/src/main/java/com/framsticks/model/Neuro.java	(revision 84)
@@ -1,5 +1,5 @@
 package com.framsticks.model;
 
-import com.framsticks.util.Point3d;
+import com.framsticks.util.math.Point3d;
 
 /**
Index: java/main/src/main/java/com/framsticks/model/Package.java
===================================================================
--- java/main/src/main/java/com/framsticks/model/Package.java	(revision 79)
+++ java/main/src/main/java/com/framsticks/model/Package.java	(revision 84)
@@ -1,8 +1,5 @@
 package com.framsticks.model;
 
-import com.framsticks.params.FramsClass;
 import com.framsticks.params.Registry;
-import com.framsticks.util.Orientation;
-import com.framsticks.util.Point3d;
 
 /**
Index: java/main/src/main/java/com/framsticks/model/Part.java
===================================================================
--- java/main/src/main/java/com/framsticks/model/Part.java	(revision 79)
+++ java/main/src/main/java/com/framsticks/model/Part.java	(revision 84)
@@ -2,5 +2,5 @@
 
 
-import com.framsticks.util.Point3d;
+import com.framsticks.util.math.Point3d;
 
 /**
Index: java/main/src/main/java/com/framsticks/observers/Endpoint.java
===================================================================
--- java/main/src/main/java/com/framsticks/observers/Endpoint.java	(revision 79)
+++ java/main/src/main/java/com/framsticks/observers/Endpoint.java	(revision 84)
@@ -5,7 +5,6 @@
 import com.framsticks.core.Path;
 import com.framsticks.params.FramsClass;
-import com.framsticks.portals.PortalEndpoint;
 import com.framsticks.core.ListChange;
-import com.framsticks.util.Dispatcher;
+import com.framsticks.util.dispatching.Dispatcher;
 import org.apache.log4j.Logger;
 
@@ -14,68 +13,73 @@
  */
 public class Endpoint implements Dispatcher, InstanceListener {
-    private final static Logger LOGGER = Logger.getLogger(PortalEndpoint.class.getName());
+	private final static Logger log = Logger.getLogger(Endpoint.class.getName());
 
-    protected Instance instance;
-    protected Observer observer;
-    protected String name;
+	protected Instance instance;
+	protected Observer observer;
+	protected String name;
 
-    public Endpoint() {
-    }
+	public Endpoint() {
+	}
 
-    public final void configurePublic(Observer observer, Instance instance, String name) {
-        assert instance != null;
-        this.name = name;
-        this.observer = observer;
-        this.instance = instance;
-        instance.addListener(this);
-        configure();
-    }
+	public final void configurePublic(Observer observer, Instance instance, String name) {
+		assert instance != null;
+		this.name = name;
+		this.observer = observer;
+		this.instance = instance;
+		instance.addListener(this);
+	}
 
-    protected void configure() {
+	public void start() {
+		instance.start();
+	}
 
-    }
+	@Override
+	public void onListChange(Path path, ListChange change) {
+		log.info("change " + change + " in " + path);
+	}
 
-    @Override
-    public void onListChange(Path path, ListChange change) {
-        LOGGER.info("change " + change + " in " + path);
-    }
+	@Override
+	public void onRun(Exception e) {
+	}
 
-    @Override
-    public void onRun(Exception e) {
-    }
+	@Override
+	public void onStop(Exception e) {
+	}
 
-    @Override
-    public void onStop(Exception e) {
-    }
+	@Override
+	public void onFetch(Path path) {
+		log.trace("fetched " + path);
+	}
 
-    @Override
-    public String toString() {
-        return instance.toString();
-    }
+	@Override
+	public String toString() {
+		return instance.toString();
+	}
 
-    public final Instance getInstance() {
-        return instance;
-    }
+	public final Instance getInstance() {
+		return instance;
+	}
 
-    @Override
-    public final boolean isActive() {
-        return instance.isActive();
-    }
+	@Override
+	public final boolean isActive() {
+		return instance.isActive();
+	}
 
-    @Override
-    public final void invokeLater(Runnable runnable) {
-        instance.invokeLater(runnable);
-    }
+	@Override
+	public final void invokeLater(Runnable runnable) {
+		instance.invokeLater(runnable);
+	}
 
-    public Observer getObserver() {
-        return observer;
-    }
+	public Observer getObserver() {
+		return observer;
+	}
 
-    public final String getName() {
-        return name;
-    }
+	public final String getName() {
+		return name;
+	}
 
-    public static void constructFramsClass(FramsClass.Constructor constructor) {
-        constructor.method("getName").method("getInstance");
-    }
+	public static void constructFramsClass(FramsClass.Constructor constructor) {
+		constructor.method("getName").method("getInstance");
+	}
+
 }
Index: java/main/src/main/java/com/framsticks/observers/Observer.java
===================================================================
--- java/main/src/main/java/com/framsticks/observers/Observer.java	(revision 79)
+++ java/main/src/main/java/com/framsticks/observers/Observer.java	(revision 84)
@@ -3,8 +3,7 @@
 import com.framsticks.core.Entity;
 import com.framsticks.core.Instance;
-import com.framsticks.core.Parameters;
 import com.framsticks.core.Program;
 import com.framsticks.params.FramsClass;
-import com.framsticks.util.Casting;
+import com.framsticks.util.lang.Casting;
 import org.apache.commons.configuration.Configuration;
 import org.apache.log4j.Logger;
@@ -17,56 +16,59 @@
 public abstract class Observer extends Entity {
 
-    private final static Logger LOGGER = Logger.getLogger(Observer.class.getName());
+	private final static Logger log = Logger.getLogger(Observer.class.getName());
 
-    public Observer(Parameters parameters) {
-        super(parameters);
-    }
+	public Observer() {
+	}
 
-    protected final Map<String, Endpoint> endpoints = new HashMap<String, Endpoint>();
+	protected final Map<String, Endpoint> endpoints = new HashMap<String, Endpoint>();
 
-    protected Endpoint createEndpoint() {
-        return new Endpoint();
-    }
+	protected Endpoint createEndpoint() {
+		return new Endpoint();
+	}
 
-    @Override
-    protected void configure() throws Exception {
-        super.configure();
-        for (String name : config.getStringArray("endpoints")) {
-            if (getEndpoints().containsKey(name)) {
-                LOGGER.fatal("observer already contains endpoint named: " + name);
-                continue;
-            }
-            Configuration c = config.subset("endpoints." + name);
-            Parameters p = new Parameters(c.subset("entity"), name, null, null);
-            Entity e = Program.configureEntity(p);
-            Instance i = Casting.tryCast(Instance.class, e);
-            if (i == null) {
-                LOGGER.error("failed to create instance: " + p);
-                continue;
-            }
-            i.configurePublic();
-            Endpoint endpoint = createEndpoint();
-            endpoint.configurePublic(this, i, name);
-            getEndpoints().put(name, endpoint);
-            LOGGER.info("instance " + i + " was added to " + Observer.this);
-        }
-    }
+	@Override
+	public void configure(Configuration config) {
+		super.configure(config);
+		for (String n : config.getStringArray("endpoints")) {
+			if (getEndpoints().containsKey(n)) {
+				log.fatal("observer already contains endpoint named: " + n);
+				continue;
+			}
+			Configuration instanceConfig = config.subset("endpoints." + n).subset("entity");
+			Instance i = Casting.tryCast(Instance.class, Program.configureEntity(instanceConfig));
+			if (i == null) {
+				log.error("failed to create instance: ");
+				continue;
+			}
+			i.setName(n);
+			i.configure(instanceConfig);
+			addEndpointForInstance(i);
+		}
+	}
 
-    @Override
-    protected void run() {
-        super.run();
-        for (Endpoint e : getEndpoints().values()) {
-            e.getInstance().start();
-        }
-    }
+	public Endpoint addEndpointForInstance(Instance instance) {
+		Endpoint endpoint = createEndpoint();
+		endpoint.configurePublic(this, instance, instance.getName());
+		getEndpoints().put(instance.getName(), endpoint);
+		log.info("instance " + instance + " was added to " + this + " as " + instance.getName());
+		return endpoint;
+	};
+
+	@Override
+	protected void run() {
+		super.run();
+		for (Endpoint e : getEndpoints().values()) {
+			e.start();
+		}
+	}
 
 
-    public Map<String, Endpoint> getEndpoints() {
-        return endpoints;
-    }
+	public Map<String, Endpoint> getEndpoints() {
+		return endpoints;
+	}
 
-    public static void constructFramsClass(FramsClass.Constructor constructor) {
-        constructor.method("getEndpoints");
-    }
+	public static void constructFramsClass(FramsClass.Constructor constructor) {
+		constructor.method("getEndpoints");
+	}
 
 
Index: java/main/src/main/java/com/framsticks/params/AccessInterface.java
===================================================================
--- java/main/src/main/java/com/framsticks/params/AccessInterface.java	(revision 79)
+++ java/main/src/main/java/com/framsticks/params/AccessInterface.java	(revision 84)
@@ -2,5 +2,4 @@
 
 import java.util.Collection;
-import java.util.List;
 
 
@@ -9,5 +8,5 @@
  * framsticks. In descriptions of methods names "property" and "parameter" are
  * synonyms.
- * 
+ *
  * @author Jarek Szymczak <name.surname@gmail.com> (please replace name and
  *         surname with my personal data)
@@ -20,16 +19,4 @@
 
 	String getId();
-
-
-    /*
-    	String getName();
-
-    * This method provides more verbose (but not strict) names of classes.
-     *
-     * e.g. for a list it will return l Type, and if name of FramsClass missing,
-     * it's id will be used
-     *
-    String getNiceName();
-    */
 
 	Param getGroupMember(int gi, int n);
@@ -44,5 +31,5 @@
 	<T> T get(String id, Class<T> type);
 
-	<T> T get(Param param, Class<T> type);
+	<T> T get(ValueParam param, Class<T> type);
 
 	<T> int set(int i, T value);
@@ -50,5 +37,5 @@
 	<T> int set(String id, T value);
 
-	<T> int set(Param param, T value);
+	<T> int set(ValueParam param, T value);
 
 	void setDefault(boolean numericOnly);
@@ -71,18 +58,9 @@
 
 	/**
-	 * Return as a single line String.
-	 * 
-	 * @param omitDefaultValues
-	 *            the omit default values
-	 * @return the string
-	 */
-	String save2(boolean omitDefaultValues);
-
-	/**
 	 * Removes all the properties values.
 	 */
 	void clearValues();
 
-	void select(Object object);
+	AccessInterface select(Object object);
 
 	Object getSelected();
@@ -90,9 +68,9 @@
 	AccessInterface cloneAccess();
 
-    Object createAccessee();
+	Object createAccessee();
 
-    Collection<Param> getParams();
+	Collection<Param> getParams();
 
-    FramsClass getFramsClass();
+	FramsClass getFramsClass();
 
 
Index: java/main/src/main/java/com/framsticks/params/ArrayListAccess.java
===================================================================
--- java/main/src/main/java/com/framsticks/params/ArrayListAccess.java	(revision 79)
+++ java/main/src/main/java/com/framsticks/params/ArrayListAccess.java	(revision 84)
@@ -1,5 +1,5 @@
 package com.framsticks.params;
 
-import com.framsticks.util.Numbers;
+import com.framsticks.util.lang.Numbers;
 
 import java.util.ArrayList;
@@ -13,111 +13,112 @@
 public class ArrayListAccess extends ListAccess {
 
-    List list;
+	List<Object> list;
 
+	public ArrayListAccess(AccessInterface elementAccess) {
+		super(elementAccess);
+	}
 
-    public ArrayListAccess(AccessInterface elementAccess) {
-        super(elementAccess);
-    }
+	@Override
+	public ArrayListAccess cloneAccess() {
+		return new ArrayListAccess(elementAccess.cloneAccess());
+	}
 
-    @Override
-    public ArrayListAccess cloneAccess() {
-        return new ArrayListAccess(elementAccess.cloneAccess());
-    }
+	@Override
+	public List<?> createAccessee() {
+		return new ArrayList<Object>();
+	}
 
-    @Override
-    public List createAccessee() {
-        return new ArrayList();
-    }
+	@Override
+	public Param getParam(int i) {
+		return new ParamBuilder().setId(Integer.toString(i)).setName(elementAccess.getId()).setType("o " + elementAccess.getId()).build();
+	}
 
-    @Override
-    public Param getParam(int i) {
-        return new ParamBuilder().setId(Integer.toString(i)).setName(elementAccess.getId()).setType("o " + elementAccess.getId()).build();
-    }
+	@Override
+	public Param getParam(String id) {
+		Integer i = Numbers.parse(id, Integer.class);
+		return (i == null ? null : getParam(i));
+	}
 
-    @Override
-    public Param getParam(String id) {
-        Integer i = Numbers.parse(id, Integer.class);
-        return (i == null ? null : getParam(i));
-    }
+	@Override
+	public String getId() {
+		return "l " + elementAccess.getId();
+	}
 
-    @Override
-    public String getId() {
-        return "l " + elementAccess.getId();
-    }
+	@Override
+	public int getParamCount() {
+		return list.size();
+	}
 
-    @Override
-    public int getParamCount() {
-        return list.size();
-    }
+	@Override
+	public <T> T get(int i, Class<T> type) {
+		if (i < list.size()) {
+			return type.cast(list.get(i));
+		}
+		return null;
+	}
 
-    @Override
-    public <T> T get(int i, Class<T> type) {
-        if (i < list.size()) {
-            return type.cast(list.get(i));
-        }
-        return null;
-    }
+	@Override
+	public <T> T get(String id, Class<T> type) {
+		return get(Integer.parseInt(id), type);
+	}
 
-    @Override
-    public <T> T get(String id, Class<T> type) {
-        return get(Integer.parseInt(id), type);
-    }
+	@Override
+	public <T> T get(ValueParam param, Class<T> type) {
+		return get(param.getId(), type);
+	}
 
-    @Override
-    public <T> T get(Param param, Class<T> type) {
-        return get(param.getId(), type);
-    }
+	@Override
+	public <T> int set(int i, T value) {
+		while (i >= list.size()) {
+			list.add(null);
+		}
+		list.set(i, value);
+		return 0;
+	}
 
-    @Override
-    public <T> int set(int i, T value) {
-        while (i >= list.size()) {
-            list.add(null);
-        }
-        list.set(i, value);
-        return 0;
-    }
+	@Override
+	public <T> int set(String id, T value) {
+		return set(Integer.parseInt(id), value);
+	}
 
-    @Override
-    public <T> int set(String id, T value) {
-        return set(Integer.parseInt(id), value);
-    }
+	@Override
+	public <T> int set(ValueParam param, T value) {
+		return set(param.getId(), value);
+	}
 
-    @Override
-    public <T> int set(Param param, T value) {
-        return set(param.getId(), value);
-    }
+	@Override
+	public void clearValues() {
+		list.clear();
+	}
 
-    @Override
-    public void clearValues() {
-        list.clear();
-    }
+	/** covariant */
+	@Override
+	public List<Object> getSelected() {
+		return list;
+	}
 
-    /** covariant */
-    @Override
-    public List getSelected() {
-        return list;
-    }
+	@SuppressWarnings("unchecked")
+	@Override
+	public ArrayListAccess select(Object object) {
+		list = (List<Object>) object;
+		return this;
+	}
 
-    @Override
-    public void select(Object object) {
-        list = (List)object;
-    }
+	@Override
+	public String computeIdentifierFor(Object selected) {
+		return Integer.toString(list.size());
+	}
 
-    @Override
-    public String computeIdentifierFor(Object selected) {
-        return Integer.toString(list.size());
-    }
-
-    @Override
-    public Collection<Param> getParams() {
-        List<Param> result = new LinkedList<Param>();
-        if (list == null) {
-            return result;
-        }
-        for (int i = 0; i < list.size(); ++i) {
-            result.add(getParam(i));
-        }
-        return result;
-    }
+	@Override
+	public Collection<Param> getParams() {
+		List<Param> result = new LinkedList<Param>();
+		if (list == null) {
+			return result;
+		}
+		for (int i = 0; i < list.size(); ++i) {
+			result.add(getParam(i));
+		}
+		return result;
+	}
 
 
Index: java/main/src/main/java/com/framsticks/params/CastFailure.java
===================================================================
--- java/main/src/main/java/com/framsticks/params/CastFailure.java	(revision 79)
+++ java/main/src/main/java/com/framsticks/params/CastFailure.java	(revision 84)
@@ -5,3 +5,9 @@
  */
 public class CastFailure extends Exception {
+
+	/**
+	 *
+	 */
+	private static final long serialVersionUID = 2117813329617553801L;
+
 }
Index: java/main/src/main/java/com/framsticks/params/CompositeParam.java
===================================================================
--- java/main/src/main/java/com/framsticks/params/CompositeParam.java	(revision 84)
+++ java/main/src/main/java/com/framsticks/params/CompositeParam.java	(revision 84)
@@ -0,0 +1,35 @@
+package com.framsticks.params;
+
+import com.framsticks.util.lang.Strings;
+
+/**
+ * @author Piotr Sniegowski
+ */
+public abstract class CompositeParam extends ValueParam {
+	protected final String containedTypeName;
+
+	public CompositeParam(String containedTypeName) {
+		this.containedTypeName = Strings.notEmpty(containedTypeName) ? containedTypeName : null;
+	}
+
+	public boolean isMatchingContainedName(String name) {
+		assert name != null;
+		if (containedTypeName == null) {
+			return true;
+		}
+		return name.equals(containedTypeName);
+	}
+
+	public String getContainedTypeName() {
+		return containedTypeName;
+	}
+
+	public abstract AccessInterface prepareAccessInterface(AccessInterface access);
+
+	public abstract String computeAccessId();
+
+	public <T> T getDef(Class<T> type) throws ClassCastException {
+		return null;
+	}
+
+}
Index: java/main/src/main/java/com/framsticks/params/Flags.java
===================================================================
--- java/main/src/main/java/com/framsticks/params/Flags.java	(revision 79)
+++ java/main/src/main/java/com/framsticks/params/Flags.java	(revision 84)
@@ -3,4 +3,6 @@
 import java.lang.reflect.Field;
 import org.apache.log4j.Logger;
+
+import com.framsticks.util.lang.Delimeted;
 
 /**
@@ -9,5 +11,5 @@
  *
  * Based on c++ defines located in: cpp/gdk/param.h
- * 
+ *
  * @author Jarek Szymczak <name.surname@gmail.com>
  * (please replace name and surname with my personal data)
@@ -17,6 +19,5 @@
 public final class Flags {
 
-	private final static Logger logger = Logger.getLogger(Flags.class.getName());
-
+	private final static Logger log = Logger.getLogger(Flags.class.getName());
 
 	public static final int READONLY = 1;
@@ -48,4 +49,23 @@
 	public static final int PSET_HITMAX = 8;
 
+	public static String write(int flags, String empty) {
+		Delimeted d = new Delimeted("+", empty);
+		try {
+			for (Field f : Flags.class.getDeclaredFields()) {
+				if (f.getType() != int.class) {
+					continue;
+				}
+				if ((flags & f.getInt(null)) != 0) {
+					d.append(f.getName());
+				}
+			}
+		} catch (IllegalArgumentException e) {
+			e.printStackTrace();
+		} catch (IllegalAccessException e) {
+			e.printStackTrace();
+		}
+		return d.build();
+	}
+
 	public static Integer read(String flags) {
 		Integer allFlags = 0;
@@ -59,12 +79,11 @@
 					allFlags |= Integer.parseInt(field.get(null).toString());
 				} catch (SecurityException e) {
-					logger.warn("security exception was thrown while trying to read flag ("
-							+ flag + ")");
+					log.warn("security exception was thrown while trying to read flag (" + flag + ")");
 				} catch (NoSuchFieldException e) {
-					logger.warn("selected flag is not known (" + flag + ")");
+					log.warn("selected flag is not known (" + flag + ")");
 				} catch (IllegalArgumentException e) {
-					logger.warn("selected flag is not known (" + flag + ")");
+					log.warn("selected flag is not known (" + flag + ")");
 				} catch (IllegalAccessException e) {
-					logger.warn("selected flag is not known (" + flag + ")");
+					log.warn("selected flag is not known (" + flag + ")");
 				}
 			}
Index: java/main/src/main/java/com/framsticks/params/FramsClass.java
===================================================================
--- java/main/src/main/java/com/framsticks/params/FramsClass.java	(revision 79)
+++ java/main/src/main/java/com/framsticks/params/FramsClass.java	(revision 84)
@@ -1,18 +1,14 @@
 package com.framsticks.params;
 
-import com.framsticks.params.types.CompositeParam;
-import com.framsticks.params.types.DecimalParam;
-import com.framsticks.params.types.FloatParam;
 import com.framsticks.params.types.StringParam;
 import com.framsticks.parsers.FileSource;
 import com.framsticks.parsers.Loaders;
-import com.framsticks.util.Casting;
+import com.framsticks.util.lang.Casting;
+
 import org.apache.log4j.Logger;
 
-import javax.lang.model.element.TypeElement;
 import java.io.InputStream;
 import java.lang.reflect.*;
 import java.util.*;
-import java.util.List;
 
 /**
@@ -30,9 +26,9 @@
 public final class FramsClass {
 
-    private final static Logger LOGGER = Logger.getLogger(FramsClass.class.getName());
-
-    /**
-      * The Class which represents group.
-      */
+	private final static Logger log = Logger.getLogger(FramsClass.class.getName());
+
+	/**
+	  * The Class which represents group.
+	  */
 
 	/** The offset of the parameter (applied for newly added parameter). */
@@ -75,5 +71,5 @@
 	/**
 	 * Adds new param entry.
-	 * 
+	 *
 	 * @param param
 	 *            the new param entry
@@ -113,5 +109,5 @@
 	/**
 	 * Gets the group member.
-	 * 
+	 *
 	 * @param gi
 	 *            the offset of group
@@ -123,5 +119,5 @@
 		if (gi < 0 || pi < 0 || gi >= groups.size()) {
 			return null;
-        }
+		}
 		Group group = groups.get(gi);
 		return (group != null ? group.getProperty(pi) : null);
@@ -130,5 +126,5 @@
 	/**
 	 * Gets the group getName.
-	 * 
+	 *
 	 * @param gi
 	 *            the offset of group
@@ -149,31 +145,31 @@
 	}
 
-    public String getNiceName() {
-        return name != null ? name : id;
-    }
+	public String getNiceName() {
+		return name != null ? name : id;
+	}
 
 	/**
 	 * Gets the param entry.
-	 * 
+	 *
 	 * @param i
 	 *            the offset of parameter
 	 * @return the param entry
 	 */
-	public Param getParamEntry(int i) {
+	public <T extends Param> T getParamEntry(int i, Class<T> type) {
 		if (i < 0 || i >= paramList.size()) {
 			return null;
 		}
-		return paramList.get(i);
+		return Casting.tryCast(type, paramList.get(i));
 	}
 
 	/**
 	 * Gets the param entry.
-	 * 
+	 *
 	 * @param id
 	 *            the getId of parameter
 	 * @return the param entry
 	 */
-	public Param getParamEntry(String id) {
-		return paramEntryMap.get(id);
+	public <T extends Param> T getParamEntry(String id, Class<T> type) {
+		return Casting.tryCast(type, paramEntryMap.get(id));
 	}
 
@@ -206,40 +202,40 @@
 	}
 
-    public static String getParamTypeForNativeType(Type type) {
-        if (type instanceof ParameterizedType) {
-            ParameterizedType p = (ParameterizedType) type;
-            Type rawType = p.getRawType();
-            if (rawType.equals(Map.class)) {
-                Type containedType = p.getActualTypeArguments()[1];
-                //TODO uid should be passed along during construction
-                if (containedType instanceof Class) {
-                    return "l " + ((Class) containedType).getCanonicalName() + " name";
-                }
-            }
+	public static String getParamTypeForNativeType(Type type) {
+		if (type instanceof ParameterizedType) {
+			ParameterizedType p = (ParameterizedType) type;
+			Type rawType = p.getRawType();
+			if (rawType.equals(Map.class)) {
+				Type containedType = p.getActualTypeArguments()[1];
+				//TODO uid should be passed along during construction
+				if (containedType instanceof Class) {
+					return "l " + ((Class<?>) containedType).getCanonicalName() + " name";
+				}
+			}
 			if (rawType.equals(List.class)) {
 				Type containedType = p.getActualTypeArguments()[0];
 				if (containedType instanceof Class) {
-					return "l " + ((Class) containedType).getCanonicalName();
-				}
-			}
-            return null;
-        }
-
-        if (type.equals(Integer.class)) {
-            return "d";
-        }
-        if (type.equals(String.class)) {
-            return "s";
-        }
-        if (type.equals(Double.class)) {
-            return "f";
-        }
-        if (type instanceof Class) {
-            return "o " + ((Class) type).getCanonicalName();
-        }
-        return null;
-    }
-
-    public static final String GENERATE_HELP_PREFIX = "automatically generated from: ";
+					return "l " + ((Class<?>) containedType).getCanonicalName();
+				}
+			}
+			return null;
+		}
+
+		if (type.equals(Integer.class)) {
+			return "d";
+		}
+		if (type.equals(String.class)) {
+			return "s";
+		}
+		if (type.equals(Double.class)) {
+			return "f";
+		}
+		if (type instanceof Class) {
+			return "o " + ((Class<?>) type).getCanonicalName();
+		}
+		return null;
+	}
+
+	public static final String GENERATE_HELP_PREFIX = "automatically generated from: ";
 
 	public static FramsClass readFromStream(InputStream stream) {
@@ -248,22 +244,23 @@
 
 	public static class Constructor {
-        protected final FramsClass result;
-        protected Class currentClass;
-        public Constructor(Class src, String name) {
-            result = new FramsClass(name, name, GENERATE_HELP_PREFIX + src.toString());
-            currentClass = src;
-            while (currentClass != null) {
-                try {
-                    currentClass.getMethod("constructFramsClass", Constructor.class).invoke(null, this);
-                } catch (Exception ignored) {
-                }
-                currentClass = currentClass.getSuperclass();
-            }
+		protected final FramsClass result;
+		protected Class<?> currentClass;
+
+		public Constructor(Class<?> src, String name) {
+			result = new FramsClass(name, name, GENERATE_HELP_PREFIX + src.toString());
 			currentClass = src;
-        }
-
-        public final FramsClass getResult() {
-            return result;
-        }
+			while (currentClass != null) {
+				try {
+					currentClass.getMethod("constructFramsClass", Constructor.class).invoke(null, this);
+				} catch (Exception ignored) {
+				}
+				currentClass = currentClass.getSuperclass();
+			}
+			currentClass = src;
+		}
+
+		public final FramsClass getResult() {
+			return result;
+		}
 
 		public Constructor allFields() {
@@ -274,50 +271,50 @@
 		}
 
-        public Constructor method(String name, Class<?> ... arguments) {
-            try {
-                Method method = currentClass.getMethod(name, arguments);
-                if (!Modifier.isPublic(method.getModifiers())) {
-                    return this;
-                }
-                String returnParamClass = getParamTypeForNativeType(method.getGenericReturnType());
-                if (returnParamClass == null) {
-                    return this;
-                }
-                Class[] args = method.getParameterTypes();
-                if (args.length == 0) {
-                    if (method.getName().startsWith("get")) {
-                        String fieldName = method.getName().substring(3, 4).toLowerCase() + method.getName().substring(4);
-                        Param param = new ParamBuilder().setType(returnParamClass).setName(fieldName).setId(fieldName).setHelp(GENERATE_HELP_PREFIX + method.toString()).build();
-                        assert param != null;
-                        result.append(param);
-                        return this;
-                    }
-                    return this;
-                }
-                return this;
-            } catch (NoSuchMethodException e) {
-                LOGGER.fatal("method " + name + " was not found in " + currentClass.toString());
-            }
-            return this;
-        }
-        public Constructor field(String name) {
-            try {
-                Field field = currentClass.getField(name);
-                if (!Modifier.isPublic(field.getModifiers())) {
-                    return this;
-                }
-                String paramClass = getParamTypeForNativeType(field.getGenericType());
-                if (paramClass == null) {
-                    return this;
-                }
-                Param param = new ParamBuilder().setType(paramClass).setName(field.getName()).setId(field.getName()).setHelp(GENERATE_HELP_PREFIX + field.toString()).build();
-                assert param != null;
-                result.append(param);
-                return this;
-            } catch (NoSuchFieldException e) {
-                LOGGER.fatal("field " + name + " was not found in " + currentClass.toString());
-            }
-            return this;
-        }
-    }
+		public Constructor method(String name, Class<?> ... arguments) {
+			try {
+				Method method = currentClass.getMethod(name, arguments);
+				if (!Modifier.isPublic(method.getModifiers())) {
+					return this;
+				}
+				String returnParamClass = getParamTypeForNativeType(method.getGenericReturnType());
+				if (returnParamClass == null) {
+					return this;
+				}
+				Class<?>[] args = method.getParameterTypes();
+				if (args.length == 0) {
+					if (method.getName().startsWith("get")) {
+						String fieldName = method.getName().substring(3, 4).toLowerCase() + method.getName().substring(4);
+						Param param = new ParamBuilder().setType(returnParamClass).setName(fieldName).setId(fieldName).setHelp(GENERATE_HELP_PREFIX + method.toString()).build();
+						assert param != null;
+						result.append(param);
+						return this;
+					}
+					return this;
+				}
+				return this;
+			} catch (NoSuchMethodException e) {
+				log.fatal("method " + name + " was not found in " + currentClass.toString());
+			}
+			return this;
+		}
+		public Constructor field(String name) {
+			try {
+				Field field = currentClass.getField(name);
+				if (!Modifier.isPublic(field.getModifiers())) {
+					return this;
+				}
+				String paramClass = getParamTypeForNativeType(field.getGenericType());
+				if (paramClass == null) {
+					return this;
+				}
+				Param param = new ParamBuilder().setType(paramClass).setName(field.getName()).setId(field.getName()).setHelp(GENERATE_HELP_PREFIX + field.toString()).build();
+				assert param != null;
+				result.append(param);
+				return this;
+			} catch (NoSuchFieldException e) {
+				log.fatal("field " + name + " was not found in " + currentClass.toString());
+			}
+			return this;
+		}
+	}
 }
Index: java/main/src/main/java/com/framsticks/params/ListAccess.java
===================================================================
--- java/main/src/main/java/com/framsticks/params/ListAccess.java	(revision 79)
+++ java/main/src/main/java/com/framsticks/params/ListAccess.java	(revision 84)
@@ -1,9 +1,7 @@
 package com.framsticks.params;
 
-import com.framsticks.core.Node;
-import com.framsticks.core.Path;
-import com.framsticks.params.types.CompositeParam;
 
-import java.util.List;
+
+import static com.framsticks.util.lang.Containers.filterInstanceof;
 
 /**
@@ -18,5 +16,5 @@
 	}
 
-    @Override
+	@Override
 	public Param getGroupMember(int gi, int n) {
 		return null;
@@ -52,23 +50,16 @@
 
 	@Override
-    public void save(SinkInterface sink) {
-        for (Param p : getParams()) {
-            assert p instanceof CompositeParam;
-            CompositeParam childParam = (CompositeParam)p;
-            Object child = get(childParam, Object.class);
-            //this is probably an assertion
-            assert child != null;
-            elementAccess.select(child);
-            elementAccess.save(sink);
-        }
-    }
+	public void save(SinkInterface sink) {
+		for (CompositeParam p : filterInstanceof(getParams(), CompositeParam.class)) {
+			Object child = get(p, Object.class);
+			//this is probably an assertion
+			assert child != null;
+			elementAccess.select(child);
+			elementAccess.save(sink);
+		}
+	}
 
 	@Override
 	public void load(SourceInterface stream) throws Exception {
-	}
-
-	@Override
-	public String save2(boolean omitDefaultValues) {
-		return null;
 	}
 
@@ -77,10 +68,10 @@
 	}
 
-    public abstract String computeIdentifierFor(Object selected);
+	public abstract String computeIdentifierFor(Object selected);
 
-    @Override
-    public final FramsClass getFramsClass() {
-        return elementAccess.getFramsClass();
-    }
+	@Override
+	public final FramsClass getFramsClass() {
+		return elementAccess.getFramsClass();
+	}
 
 }
Index: java/main/src/main/java/com/framsticks/params/ListSink.java
===================================================================
--- java/main/src/main/java/com/framsticks/params/ListSink.java	(revision 79)
+++ java/main/src/main/java/com/framsticks/params/ListSink.java	(revision 84)
@@ -8,40 +8,40 @@
  */
 public class ListSink implements SinkInterface {
-    protected final List<String> out;
-    protected StringBuilder lineBuilder = new StringBuilder();
+	protected final List<String> out;
+	protected StringBuilder lineBuilder = new StringBuilder();
 
-    public ListSink(List<String> out) {
-        this.out = out;
-    }
+	public ListSink(List<String> out) {
+		this.out = out;
+	}
 
-    public ListSink() {
-        this.out = new LinkedList<String>();
-    }
+	public ListSink() {
+		this.out = new LinkedList<String>();
+	}
 
-    public final List<String> getOut() {
-        return out;
-    }
+	public final List<String> getOut() {
+		return out;
+	}
 
 
-    @Override
-    public SinkInterface print(String str) {
-        lineBuilder.append(str);
-        return this;
-    }
+	@Override
+	public SinkInterface print(String str) {
+		lineBuilder.append(str);
+		return this;
+	}
 
-    @Override
-    public SinkInterface print(Object obj) {
-        lineBuilder.append(obj);
-        return this;
-    }
+	@Override
+	public SinkInterface print(Object obj) {
+		lineBuilder.append(obj);
+		return this;
+	}
 
-    @Override
-    public void breakLine() {
-        out.add(lineBuilder.toString());
-        lineBuilder = new StringBuilder();
-    }
+	@Override
+	public void breakLine() {
+		out.add(lineBuilder.toString());
+		lineBuilder = new StringBuilder();
+	}
 
-    @Override
-    public void close() {
-    }
+	@Override
+	public void close() {
+	}
 }
Index: java/main/src/main/java/com/framsticks/params/ListSource.java
===================================================================
--- java/main/src/main/java/com/framsticks/params/ListSource.java	(revision 79)
+++ java/main/src/main/java/com/framsticks/params/ListSource.java	(revision 84)
@@ -7,8 +7,8 @@
 
 	private Iterator<String> iterator = null;
-    private final List<String> source;
+    //private final List<String> source;
 
 	public ListSource(List<String> source) {
-        this.source = source;
+        //this.source = source;
         iterator = source.iterator();
 	}
Index: java/main/src/main/java/com/framsticks/params/Param.java
===================================================================
--- java/main/src/main/java/com/framsticks/params/Param.java	(revision 79)
+++ java/main/src/main/java/com/framsticks/params/Param.java	(revision 84)
@@ -3,7 +3,4 @@
 import com.framsticks.params.types.DecimalParam;
 import com.framsticks.params.types.StringParam;
-
-import java.util.HashMap;
-import java.util.Map;
 
 /**
@@ -42,27 +39,4 @@
 	protected Integer extra;
 
-	/** The minimum allowed value of parameter. */
-	protected Object min;
-
-	/** The maximum allowed value of parameter. */
-	protected Object max;
-
-	/** The default value of parameter. */
-	protected Object def;
-
-
-
-	/**
-	 * The defaults used for Integer, Double and String classes, if the default
-	 * value of parameter is not explicitly given.
-	 */
-	@SuppressWarnings("rawtypes")
-	private Map<Class, Object> defaults = new HashMap<Class, Object>();
-	// static initialization of defaults
-	{
-		defaults.put(String.class, "");
-		defaults.put(Integer.class, 0);
-		defaults.put(Double.class, 0.0);
-	}
 
 	public Param() {
@@ -94,5 +68,5 @@
 	}
 
-    public abstract String getType();
+	public abstract String getFramsTypeName();
 
 
@@ -101,51 +75,4 @@
 	}
 
-
-    private <T> T tryCastAndReturn(Object value, Class<T> type) {
-        if (value == null)
-            return null;
-        try {
-            return type.cast(value);
-        } catch (ClassCastException e) {
-            throw new ClassCastException("property \"" + name
-                    + "\" type is \"" + value.getClass().getName()
-                    + "\", not \"" + type.getName() + "\"");
-        }
-    }
-	/**
-	 * Gets the minimum value of parameter.
-	 *
-	 * @param <T> the generic getType which must be correctly specified by user
-	 * @param type the getType of variable, can be checked by
-	 * @return the minimum allowed value of parameter
-	 * @throws ClassCastException the class cast exception, thrown when given getType is incorrect
-	 */
-	public <T> T getMin(Class<T> type) {
-		return tryCastAndReturn(min, type);
-	}
-
-	/**
-	 * Gets the maximum value of parameter.
-	 *
-	 * @param <T> the generic getType which must be correctly specified by user
-	 * @param type the getType of variable, can be checked by {@link #getStorageType()}
-	 * @return the maximum allowed value of parameter
-	 * @throws ClassCastException the class cast exception, thrown when given getType is incorrect
-	 */
-	public <T> T getMax(Class<T> type) {
-		return tryCastAndReturn(max, type);
-	}
-
-	/**
-	 * Gets the default value of parameter.
-	 *
-	 * @param <T> the generic getType which must be correctly specified by user
-	 * @param type the getType of variable, can be checked by {@link #getStorageType()}
-	 * @return the default value of parameter
-	 * @throws ClassCastException the class cast exception, thrown when given getType is incorrect
-	 */
-	public <T> T getDef(Class<T> type) throws ClassCastException {
-		return tryCastAndReturn(def, type);
-	}
 
 	public Integer getExtra() {
@@ -166,9 +93,5 @@
 	}
 
-	public boolean isEmptyAvailable() {
-		return false;
-	}
-
-	public abstract Class getStorageType();
+	public abstract Class<?> getStorageType();
 
 	public boolean hasFlag(int flag) {
@@ -176,30 +99,16 @@
 	}
 
-	public Object reassign(Object newValue, Object oldValue) throws CastFailure {
-        if (newValue == null) {
-            if (isEmptyAvailable()) {
-                return null;
-            }
-            throw new CastFailure();
-        }
-        try {
-            return getStorageType().cast(newValue);
-        } catch (ClassCastException ignored) {
-            throw new CastFailure();
-        }
-    }
-
 	public boolean isUserHidden() {
 		return (flags & Flags.USERHIDDEN) != 0;
 	}
 
-    public static FramsClass getFramsClass() {
-        return new FramsClass("prop", "prop", null)
-                .append(new ParamBuilder().setId("name").setName("Name").setType(StringParam.class).build())
-                .append(new ParamBuilder().setId("id").setName("Id").setType(StringParam.class).build())
-                .append(new ParamBuilder().setId("type").setName("Type").setType(StringParam.class).build())
-                .append(new ParamBuilder().setId("help").setName("Help").setType(StringParam.class).build())
-                .append(new ParamBuilder().setId("flags").setName("Flags").setType(DecimalParam.class).build());
-    }
+	public static FramsClass getFramsClass() {
+		return new FramsClass("prop", "prop", null)
+				.append(new ParamBuilder().setId("name").setName("Name").setType(StringParam.class).build())
+				.append(new ParamBuilder().setId("id").setName("Id").setType(StringParam.class).build())
+				.append(new ParamBuilder().setId("type").setName("Type").setType(StringParam.class).build())
+				.append(new ParamBuilder().setId("help").setName("Help").setType(StringParam.class).build())
+				.append(new ParamBuilder().setId("flags").setName("Flags").setType(DecimalParam.class).build());
+	}
 
 }
Index: java/main/src/main/java/com/framsticks/params/ParamBuilder.java
===================================================================
--- java/main/src/main/java/com/framsticks/params/ParamBuilder.java	(revision 79)
+++ java/main/src/main/java/com/framsticks/params/ParamBuilder.java	(revision 84)
@@ -2,4 +2,6 @@
 
 import com.framsticks.params.types.*;
+import com.framsticks.util.lang.Numbers;
+
 import org.apache.log4j.Logger;
 
@@ -9,5 +11,5 @@
 /**
  * The class ParamBuilder helps building Param objects.
- * 
+ *
  * @author Mateusz Jarus <name.surname@gmail.com> (please replace name and
  *         surname with my personal data)
@@ -17,5 +19,5 @@
 
 public class ParamBuilder {
-	private final static Logger LOGGER = Logger.getLogger(ParamBuilder.class.getName());
+	private final static Logger log = Logger.getLogger(ParamBuilder.class.getName());
 
 	private static final String ID_FIELD = "id";
@@ -48,12 +50,12 @@
 
 	/** The getType of parameter. */
-	@SuppressWarnings("rawtypes")
-	private Class paramType;
+	private Class<? extends Param> paramType;
 
 	private Param param;
+	private PrimitiveParam primitiveParam;
 
 	/**
 	 * Build Param based on provided data.
-	 * 
+	 *
 	 * @return Param object
 	 * @throws Exception
@@ -61,5 +63,5 @@
 	 */
 	public Param build()  {
-        assert param != null;
+		assert param != null;
 		param.id = id;
 		param.name = name;
@@ -68,5 +70,4 @@
 		param.flags = flags;
 		param.internalId = internalId;
-
 		return param;
 	}
@@ -77,8 +78,16 @@
 	}
 
+	protected <T extends Param> ParamBuilder internalSetType(Class<? extends Param> type, T param) {
+		this.paramType = type;
+		this.param = param;
+		if (param instanceof PrimitiveParam) {
+			primitiveParam = (PrimitiveParam) param;
+		}
+		return this;
+	}
+
 	public <T extends Param> ParamBuilder setType(Class<T> type) {
-		this.paramType = type;
 		try {
-			this.param = (Param)paramType.newInstance();
+			return internalSetType(type, type.newInstance());
 		} catch (InstantiationException e) {
 			e.printStackTrace();
@@ -89,8 +98,6 @@
 	}
 
-	public <T extends Param> ParamBuilder setType(T type) {
-		this.paramType = type.getClass();
-		this.param = type;
-		return this;
+	public <T extends Param> ParamBuilder setType(T param) {
+		return internalSetType(param.getClass(), param);
 	}
 
@@ -116,7 +123,26 @@
 	}
 
+	protected <T extends Number> void parseMinMaxDefNumber(Class<T> type, String second, String third) {
+		if (primitiveParam == null) {
+			log.warn("param is not a primitive param");
+			return;
+		}
+		if (second != null) {
+			this.primitiveParam.min = Numbers.parse(second, type);
+			if (this.primitiveParam.min == null) {
+				log.warn("value of min attribute was invalid");
+			}
+		}
+		if (third != null) {
+			this.primitiveParam.max = Numbers.parse(third, type);
+			if (this.primitiveParam.max == null) {
+				log.warn("value of min attribute was invalid");
+			}
+		}
+	}
+
 	public ParamBuilder setType(String type) {
 
-		LOGGER.trace("parsing type: " + type);
+		log.trace("parsing type: " + type);
 
 		String[] typeSplitted = type.split(" ");
@@ -136,5 +162,5 @@
 					procedureParam.parseSignature(signature);
 				} catch (Exception e) {
-					LOGGER.error("invalid procedure signature '" + signature + "': " + e);
+					log.error("invalid procedure signature '" + signature + "': " + e);
 				}
 				setType(procedureParam);
@@ -148,5 +174,5 @@
 				} else {
 					if (first.length() >= 2) {
-						switch (first.charAt(1)) {
+				switch (first.charAt(1)) {
 							case 'b': {
 								setType(BinaryParam.class);
@@ -159,7 +185,7 @@
 						}
 					}
-                    if ("0".equals(second) && "1".equals(third)) {
-                        setType(BooleanParam.class);
-                    }
+					if ("0".equals(second) && "1".equals(third)) {
+						setType(BooleanParam.class);
+					}
 					if (param == null) {
 						setType(DecimalParam.class);
@@ -167,15 +193,5 @@
 				}
 				if (this.param instanceof DecimalParam) {
-					try {
-						if (second != null) {
-							this.param.min = Integer.parseInt(second);
-						}
-
-						if (third != null) {
-							this.param.max = Integer.parseInt(third);
-						}
-					} catch (NumberFormatException e) {
-						LOGGER.warn("value of min or max attribute should be an Integer");
-					}
+					parseMinMaxDefNumber(Integer.class, second, third);
 				}
 				break;
@@ -183,15 +199,5 @@
 			case 'f': {
 				setType(FloatParam.class);
-				try {
-					if (second != null) {
-						this.param.min = Double.parseDouble(second);
-					}
-
-					if (third != null) {
-						this.param.max = Double.parseDouble(third);
-					}
-				} catch (NumberFormatException ex) {
-					LOGGER.warn("Value of min or max attribute should be Double");
-				}
+				parseMinMaxDefNumber(Double.class, second, third);
 				break;
 			}
@@ -202,6 +208,6 @@
 			case 's': {
 				setType(StringParam.class);
-				this.param.min = second;
-				this.param.max = third;
+				setMin(second);
+				setMax(third);
 				break;
 			}
@@ -211,5 +217,4 @@
 			}
 			case 'l': {
-
 				setType(third != null ? new UniqueListParam(second, third) : new ArrayListParam(second));
 				break;
@@ -225,17 +230,35 @@
 	}
 
+	/**
+	 * @return the paramType
+	 */
+	public Class<? extends Param> getParamType() {
+		return paramType;
+	}
+
 	public <T> ParamBuilder setMin(T min) {
-		this.param.min = min;
+		if (primitiveParam != null) {
+			this.primitiveParam.min = min;
+		}
 		return this;
 	}
 
 	public <T> ParamBuilder setMax(T max) {
-		this.param.max = max;
+		if (primitiveParam != null) {
+			this.primitiveParam.max = max;
+		}
 		return this;
 	}
 
 	public <T> ParamBuilder setDef(T def) {
-		this.param.def = def;
-		return this;
+		if (def != null && primitiveParam != null) {
+			this.primitiveParam.def = def;
+		}
+		return this;
+	}
+
+	public Class<?> getStorageType() {
+		assert param != null;
+		return param.getStorageType();
 	}
 
@@ -244,5 +267,5 @@
 
 		if (paramEntryValues.length == 0) {
-			LOGGER.warn("field empty or wrong format (" + line
+			log.warn("field empty or wrong format (" + line
 					+ ") - omitting");
 			return null;
@@ -263,5 +286,5 @@
 			/** everything is ok, parameters have just finished*/
 		} catch (NumberFormatException ex) {
-			LOGGER.warn("wrong format of entry: " + line
+			log.warn("wrong format of entry: " + line
 					+ ", omitting");
 			return null;
Index: java/main/src/main/java/com/framsticks/params/PrimitiveParam.java
===================================================================
--- java/main/src/main/java/com/framsticks/params/PrimitiveParam.java	(revision 84)
+++ java/main/src/main/java/com/framsticks/params/PrimitiveParam.java	(revision 84)
@@ -0,0 +1,69 @@
+package com.framsticks.params;
+
+
+/**
+ * @author Piotr Sniegowski
+ */
+public abstract class PrimitiveParam extends ValueParam {
+
+	/** The minimum allowed value of parameter. */
+	protected Object min;
+
+	/** The maximum allowed value of parameter. */
+	protected Object max;
+
+	/** The default value of parameter. */
+	protected Object def;
+
+	public void save(SinkInterface sink, Object value) {
+		sink.print(value);
+	}
+
+	protected <T> T tryCastAndReturn(Object value, Class<T> type) {
+		if (value == null)
+			return null;
+		try {
+			return type.cast(value);
+		} catch (ClassCastException e) {
+			throw new ClassCastException("property \"" + name
+					+ "\" type is \"" + value.getClass().getName()
+					+ "\", not \"" + type.getName() + "\"");
+		}
+	}
+
+	/**
+	 * Gets the minimum value of parameter.
+	 *
+	 * @param <T> the generic getType which must be correctly specified by user
+	 * @param type the getType of variable, can be checked by
+	 * @return the minimum allowed value of parameter
+	 * @throws ClassCastException the class cast exception, thrown when given getType is incorrect
+	 */
+	public <T> T getMin(Class<T> type) {
+		return tryCastAndReturn(min, type);
+	}
+
+	/**
+	 * Gets the maximum value of parameter.
+	 *
+	 * @param <T> the generic getType which must be correctly specified by user
+	 * @param type the getType of variable, can be checked by {@link #getStorageType()}
+	 * @return the maximum allowed value of parameter
+	 * @throws ClassCastException the class cast exception, thrown when given getType is incorrect
+	 */
+	public <T> T getMax(Class<T> type) {
+		return tryCastAndReturn(max, type);
+	}
+
+	/**
+	 * Gets the default value of parameter.
+	 *
+	 * @param <T> the generic getType which must be correctly specified by user
+	 * @param type the getType of variable, can be checked by {@link #getStorageType()}
+	 * @return the default value of parameter
+	 * @throws ClassCastException the class cast exception, thrown when given getType is incorrect
+	 */
+	public <T> T getDef(Class<T> type) throws ClassCastException {
+		return tryCastAndReturn(def, type);
+	}
+}
Index: java/main/src/main/java/com/framsticks/params/PropertiesAccess.java
===================================================================
--- java/main/src/main/java/com/framsticks/params/PropertiesAccess.java	(revision 79)
+++ java/main/src/main/java/com/framsticks/params/PropertiesAccess.java	(revision 84)
@@ -1,12 +1,11 @@
 package com.framsticks.params;
 
-import java.util.ArrayList;
 import java.util.HashMap;
-import java.util.List;
 import java.util.Map;
+
 
 /**
  * The Class PropertiesAccess.
- * 
+ *
  * @author Jarek Szymczak <name.surname@gmail.com> (please replace name and
  *         surname with my personal data)
@@ -18,5 +17,5 @@
 	public Map<String, Object> properties;
 
-    @Override
+	@Override
 	public Map<String, Object> createAccessee() {
 		return PropertiesAccess.createPropertiesMap();
@@ -33,12 +32,12 @@
 	@Override
 	public void clearValues() {
-        assert properties != null;
-        properties.clear();
+		assert properties != null;
+		properties.clear();
 	}
 
 	@Override
-	public <T> T get(Param param, Class<T> type) {
-        assert properties != null;
-        assert param != null;
+	public <T> T get(ValueParam param, Class<T> type) {
+		assert properties != null;
+		assert param != null;
 		Object object = null;
 		try {
@@ -54,5 +53,6 @@
 	}
 
-	protected <T> void internalSet(Param param, T value) {
+	@Override
+	protected <T> void internalSet(ValueParam param, T value) {
 		properties.put(param.getId(), value);
 	}
@@ -63,11 +63,13 @@
 	 * correct exceptions might occurred while getting / setting the parameters
 	 * values
-	 * 
+	 *
 	 * @param object
 	 *            the properties with parameters values
 	 */
+	@SuppressWarnings("unchecked")
 	@Override
-	public void select(Object object) {
+	public PropertiesAccess select(Object object) {
 		this.properties = (Map<String, Object>)object;
+		return this;
 	}
 
@@ -81,6 +83,4 @@
 	public PropertiesAccess cloneAccess() {
 		return new PropertiesAccess(framsClass);
-		//properties = createProperties();
-		//return access;
 	}
 
Index: java/main/src/main/java/com/framsticks/params/ReassignResult.java
===================================================================
--- java/main/src/main/java/com/framsticks/params/ReassignResult.java	(revision 84)
+++ java/main/src/main/java/com/framsticks/params/ReassignResult.java	(revision 84)
@@ -0,0 +1,42 @@
+package com.framsticks.params;
+
+public class ReassignResult<T> {
+	protected final T value;
+	protected final int flags;
+
+	/**
+	 * @param value
+	 * @param state
+	 */
+	public ReassignResult(T value, int state) {
+		this.value = value;
+		this.flags = state;
+	}
+
+	/**
+	 * @param value
+	 */
+	public ReassignResult(T value) {
+		this.value = value;
+		this.flags = 0;
+	}
+
+	/**
+	 * @return the value
+	 */
+	public final T getValue() {
+		return value;
+	}
+
+	/**
+	 * @return the state
+	 */
+	public final int getFlags() {
+		return flags;
+	}
+
+	public static <T> ReassignResult<T> create(T value) {
+		return new ReassignResult<T>(value);
+	}
+
+}
Index: java/main/src/main/java/com/framsticks/params/ReflectionAccess.java
===================================================================
--- java/main/src/main/java/com/framsticks/params/ReflectionAccess.java	(revision 79)
+++ java/main/src/main/java/com/framsticks/params/ReflectionAccess.java	(revision 84)
@@ -4,14 +4,13 @@
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Modifier;
-import java.lang.reflect.Type;
-import java.util.List;
 
-import com.framsticks.params.types.ListParam;
 import org.apache.log4j.Logger;
+
+import com.framsticks.util.lang.Containers;
 
 
 /**
  * The Class ReflectionAccess. Stores data in provided object using reflection.
- * 
+ *
  * @author Mateusz Jarus <name.surname@gmail.com> (please replace name and
  *         surname with my personal data)
@@ -20,13 +19,11 @@
  */
 public class ReflectionAccess extends SimpleAbstractAccess {
-	private final static Logger LOGGER = Logger.getLogger(ReflectionAccess.class
-			.getName());
+	private final static Logger log = Logger.getLogger(ReflectionAccess.class.getName());
 
-
-    protected final Class reflectedClass;
+	protected final Class<?> reflectedClass;
 	private Object object;
 
-	public ReflectionAccess(Class reflectedClass, FramsClass framsClass) {
-        this.reflectedClass = reflectedClass;
+	public ReflectionAccess(Class<?> reflectedClass, FramsClass framsClass) {
+		this.reflectedClass = reflectedClass;
 		setFramsClass(framsClass);
 	}
@@ -37,5 +34,5 @@
 
 	@Override
-	public <T> T get(Param param, Class<T> type) {
+	public <T> T get(ValueParam param, Class<T> type) {
 		if (object == null) {
 			return null;
@@ -54,29 +51,29 @@
 			} catch (InvocationTargetException e) {
 				//e.printStackTrace();
-            }
+			}
 
 		} catch (IllegalAccessException ex) {
-			LOGGER.warn("illegal access error occurred while trying to access returnedObject");
+			log.warn("illegal access error occurred while trying to access returnedObject");
 			ex.printStackTrace();
-        } catch (ClassCastException ignored) {
+		} catch (ClassCastException ignored) {
 
-        }
+		}
 		return null;
 	}
 
 	@Override
-	protected <T> void internalSet(Param param, T value) {
+	protected <T> void internalSet(ValueParam param, T value) {
 		setValue(param, value);
 	}
 
-	private <T> void setValue(Param param, T value) {
+	private <T> void setValue(ValueParam param, T value) {
 		if (object == null) {
 			return;
-        }
+		}
 		try {
 			String id = param.getId();
 			try {
 				Field f = reflectedClass.getField(id);
-				Class t = f.getType();
+				Class<?> t = f.getType();
 				if (Modifier.isFinal(f.getModifiers())) {
 					return;
@@ -111,5 +108,5 @@
 
 		try {
-			for (Param p : framsClass.getParamEntries()) {
+			for (ValueParam p : Containers.filterInstanceof(framsClass.getParamEntries(), ValueParam.class)) {
 				setValue(p, p.getDef(Object.class));
 			}
@@ -121,12 +118,13 @@
 	/**
 	 * Sets the new object to operate on.
-	 * 
+	 *
 	 * @param object
 	 *            new object to operate on
 	 */
 	@Override
-	public void select(Object object) {
+	public ReflectionAccess select(Object object) {
 		assert object == null || reflectedClass.isInstance(object);
 		this.object = object;
+		return this;
 	}
 
@@ -159,15 +157,15 @@
 	}
 
-    @Override
-    public Object createAccessee() {
-        try {
-            return reflectedClass.newInstance();
-        } catch (InstantiationException e) {
-            e.printStackTrace();
-        } catch (IllegalAccessException e) {
-            e.printStackTrace();
-        }
-        LOGGER.fatal("failed to create reflected object of class " + reflectedClass.getCanonicalName() + " for frams type " + framsClass.getId());
-        return null;
-    }
+	@Override
+	public Object createAccessee() {
+		try {
+			return reflectedClass.newInstance();
+		} catch (InstantiationException e) {
+			e.printStackTrace();
+		} catch (IllegalAccessException e) {
+			e.printStackTrace();
+		}
+		log.fatal("failed to create reflected object of class " + reflectedClass.getCanonicalName() + " for frams type " + framsClass.getId());
+		return null;
+	}
 }
Index: java/main/src/main/java/com/framsticks/params/Registry.java
===================================================================
--- java/main/src/main/java/com/framsticks/params/Registry.java	(revision 79)
+++ java/main/src/main/java/com/framsticks/params/Registry.java	(revision 84)
@@ -10,7 +10,7 @@
  */
 public class Registry {
-	private static final Logger LOGGER = Logger.getLogger(Registry.class.getName());
+	private static final Logger log = Logger.getLogger(Registry.class.getName());
 
-	protected final Map<String, Class> reflectedClasses = new HashMap<String, Class>();
+	protected final Map<String, Class<?>> reflectedClasses = new HashMap<String, Class<?>>();
 	protected final Map<String, String> invertedReflectedClasses = new HashMap<String, String>();
 	protected final Map<String, FramsClass> infoCache = new HashMap<String, FramsClass>();
@@ -20,9 +20,10 @@
 			registerReflectedClass(name, id, Class.forName(className));
 		} catch (ClassNotFoundException e) {
-			LOGGER.fatal("class not found during registration: " + e);
+			log.fatal("class not found during registration: " + e);
 		}
 	}
 
-	public void registerReflectedClass(String name, String id, Class reflectedClass) {
+	public void registerReflectedClass(String name, String id,
+			Class<?> reflectedClass) {
 		if (name != null) {
 			reflectedClasses.put(name, reflectedClass);
@@ -43,8 +44,8 @@
 	public void putInfoIntoCache(FramsClass framsClass) {
 		if (infoCache.containsKey(framsClass.getId())) {
-			LOGGER.info("already cached " + framsClass);
+			log.info("already cached " + framsClass);
 			return;
 		}
-		LOGGER.debug("caching info for " + framsClass);
+		log.debug("caching info for " + framsClass);
 		infoCache.put(framsClass.getId(), framsClass);
 		infoCache.put(framsClass.getName(), framsClass);
@@ -63,3 +64,27 @@
 		return null;
 	}
+
+	public static AccessInterface wrapAccessWithListIfNeeded(CompositeParam param, AccessInterface access) {
+        if (access == null) {
+			return null;
+		}
+        return param.prepareAccessInterface(access);
+	}
+
+    public AccessInterface prepareAccess(CompositeParam param) {
+        return wrapAccessWithListIfNeeded(param, createAccess(param.getContainedTypeName()));
+    }
+
+	public AccessInterface createAccess(String name) {
+		if (name == null) {
+			return null;
+		}
+		FramsClass framsClass = getInfoFromCache(name);
+		if (framsClass == null) {
+			return null;
+		}
+
+		return createAccess(name, framsClass);
+	}
+
 }
Index: java/main/src/main/java/com/framsticks/params/SimpleAbstractAccess.java
===================================================================
--- java/main/src/main/java/com/framsticks/params/SimpleAbstractAccess.java	(revision 79)
+++ java/main/src/main/java/com/framsticks/params/SimpleAbstractAccess.java	(revision 84)
@@ -2,13 +2,9 @@
 
 import java.io.IOException;
-import java.text.DecimalFormat;
-import java.text.DecimalFormatSymbols;
-import java.util.ArrayList;
 import java.util.Collection;
-import java.util.List;
-
-import com.framsticks.params.types.*;
+
+import static com.framsticks.util.lang.Containers.filterInstanceof;
+
 import org.apache.log4j.Logger;
-import java.util.Locale;
 
 /**
@@ -26,9 +22,7 @@
 public abstract class SimpleAbstractAccess implements AccessInterface {
 
-	private final static Logger LOGGER = Logger.getLogger(SimpleAbstractAccess.class.getName());
-
-
-
-    @Override
+	private final static Logger log = Logger.getLogger(SimpleAbstractAccess.class.getName());
+
+	@Override
 	public final FramsClass getFramsClass() {
 		return framsClass;
@@ -38,5 +32,5 @@
 		this.framsClass = framsClass;
 	}
-    /**
+	/**
 	 * Simple String key, value class.
 	 */
@@ -64,5 +58,5 @@
 	}
 
-    @Override
+	@Override
 	public int getParamCount() {
 		return framsClass.getParamCount();
@@ -71,12 +65,11 @@
 	@Override
 	public Param getParam(int i) {
-		return framsClass.getParamEntry(i);
+		return framsClass.getParamEntry(i, Param.class);
 	}
 
 	@Override
 	public Param getParam(String id) {
-		return framsClass.getParamEntry(id);
-	}
-
+		return framsClass.getParamEntry(id, Param.class);
+	}
 
 	@Override
@@ -87,53 +80,59 @@
 	@Override
 	public <T> T get(int i, Class<T> type) {
-		return get(getParam(i), type);
+		Param p = getParam(i);
+		assert p instanceof ValueParam;
+		return get((ValueParam) p, type);
 	}
 
 	@Override
 	public <T> T get(String id, Class<T> type) {
-		return get(getParam(id), type);
-	}
-
+		Param p = getParam(id);
+		assert p instanceof ValueParam;
+		return get((ValueParam) p, type);
+	}
 
 	@Override
 	public <T> int set(String id, T value) {
-		return set(getParam(id), value);
+		Param p = getParam(id);
+		assert p instanceof ValueParam;
+		return set((ValueParam) p, value);
 	}
 
 	@Override
 	public <T> int set(int i, T value) {
-		return set(getParam(i), value);
-	}
-
-	@SuppressWarnings("unchecked")
-	@Override
-	public <T> int set(Param param, T value) {
+		Param p = getParam(i);
+		assert p instanceof ValueParam;
+		return set((ValueParam) p, value);
+	}
+
+	@Override
+	public <T> int set(ValueParam param, T value) {
 		int flags = 0;
+
 		//String id = param.getEffectiveId();
 		try {
-            Object oldValue = get(param, param.getStorageType());
-            Object casted = param.reassign(value, oldValue);
-            if (casted != oldValue) {
-                internalSet(param, casted);
-            }
-        } catch (CastFailure e) {
-            LOGGER.error("casting failure while set: ", e);
-
-        }
-        return flags;
-    }
-
-
-
+			Object oldValue = get(param, param.getStorageType());
+			ReassignResult<?> result = param.reassign(value, oldValue);
+			Object casted = result.getValue();
+			if (casted != oldValue) {
+				internalSet(param, casted);
+			}
+			flags = result.getFlags();
+		} catch (CastFailure e) {
+			log.error("casting failure while set: ", e);
+		}
+		return flags;
+	}
 
 	@Override
 	public void setDefault(boolean numericOnly) {
-		for (int i = 0; i < framsClass.getParamCount(); i++)
+		for (int i = 0; i < framsClass.getParamCount(); i++) {
 			setDefault(i, numericOnly);
+		}
 	}
 
 	@Override
 	public void setDefault(int i, boolean numericOnly) {
-		Param entry = framsClass.getParamEntry(i);
+		ValueParam entry = framsClass.getParamEntry(i, ValueParam.class);
 		if ((entry != null)	&& (!numericOnly || entry.isNumeric())) {
 			set(i, entry.getDef(entry.getStorageType()));
@@ -148,8 +147,10 @@
 	}
 
-	@SuppressWarnings("unchecked")
 	@Override
 	public void setMin(int i) {
-		Param entry = framsClass.getParamEntry(i);
+		PrimitiveParam entry = framsClass.getParamEntry(i, PrimitiveParam.class);
+		if (entry == null) {
+			return;
+		}
 		Object min = entry.getMin(entry.getStorageType());
 		if (min != null) {
@@ -165,8 +166,10 @@
 	}
 
-	@SuppressWarnings("unchecked")
 	@Override
 	public void setMax(int i) {
-		Param entry = framsClass.getParamEntry(i);
+		PrimitiveParam entry = framsClass.getParamEntry(i, PrimitiveParam.class);
+		if (entry == null) {
+			return;
+		}
 		Object max = entry.getMax(entry.getStorageType());
 		if (max != null) {
@@ -191,169 +194,99 @@
 	@Override
 	public void save(SinkInterface sink) {
-        assert framsClass != null;
-        sink.print(framsClass.getId()).print(":").breakLine();
-        for (Param p : framsClass.getParamEntries()) {
-            if (p instanceof ValueParam) {
-                Object value = get(p, Object.class);
-                if (value == null) {
-                    continue;
-                }
-                sink.print(p.getId()).print(":");
-                ((ValueParam)p).save(sink, value);
-                sink.breakLine();
-
-
-                //continue;
-            }
-            /*
-            if (p instanceof CompositeParam) {
-                if (!(p instanceof ListParam)) {
-                    continue;
-                }
-                Collection c = get(p, Collection.class);
-                if (c != null) {
-                    save(stream, p, c.size());
-                }
-            }
-            */
-
-        }
-        sink.breakLine();
-	}
-
-	@Override
-	public String save2(boolean omitDefaultValues) {
-		StringBuilder stringBuilder = new StringBuilder();
-		DecimalFormat df = new DecimalFormat("#.###", new DecimalFormatSymbols(
-				Locale.ENGLISH));
-		boolean canOmitName = false;
-		int n = 0;
-		for (int i = 0; i < framsClass.getParamCount(); i++) {
-			Object value = this.get(i, Object.class);
-			Object def = framsClass.getParamEntry(i).getDef(Object.class);
-			if (value != null && (!omitDefaultValues || !value.equals(def))) {
-				if ((n != i && !canOmitName)
-						|| (getParam(i).getFlags() & Flags.CANOMITNAME) == 0) {
-					stringBuilder.append(getParam(i).getId());
-					stringBuilder.append("=");
+		assert framsClass != null;
+		sink.print(framsClass.getId()).print(":").breakLine();
+		for (PrimitiveParam p : filterInstanceof(framsClass.getParamEntries(), PrimitiveParam.class)) {
+			Object value = get(p, Object.class);
+			if (value == null) {
+				continue;
+			}
+			sink.print(p.getId()).print(":");
+			p.save(sink, value);
+			sink.breakLine();
+		}
+		sink.breakLine();
+	}
+
+	private Entry readEntry(SourceInterface source)
+			throws IOException {
+
+		String line;
+		String key = null;
+		StringBuilder value = null;
+		while ((line = source.readLine()) != null)
+		{
+			if (key == null) {
+				int colonIndex = line.indexOf(':');
+				if (colonIndex == -1) {
+					return null;
 				}
-				n++;
-				canOmitName = true;
-				if (this.get(i, Object.class) instanceof String) {
-					String valueString = this.get(i, String.class);
-					valueString = valueString.replaceAll("\\\"", "\\\\\"");
-					valueString = valueString.contains(",") ? "\""
-							+ valueString + "\"" : valueString;
-					// if ("".equals(valueString.trim()))
-					// value = "\"\"";
-					stringBuilder.append(valueString);
-				} else if (this.get(i, Object.class) instanceof Double) {
-					stringBuilder.append(df.format(this.get(i, Double.class)));
-				} else
-					stringBuilder.append(this.get(i, Object.class));
-				stringBuilder.append(", ");
+				key = line.substring(0, colonIndex);
+				String inlineValue = line.substring(colonIndex + 1);
+
+
+				if (!inlineValue.startsWith("~")) {
+					return new Entry(key, inlineValue);
+				}
+				value = new StringBuilder();
+				value.append(inlineValue.substring(1));
+				continue;
+			}
+			if (value.length() != 0) {
+				value.append(System.getProperty("line.separator"));
+			}
+			if (line.contains("~")) {
+				value.append(line.substring(0, line.indexOf("~")));
+				return new Entry(key, value.toString());
+			}
+			value.append(line);
+			/*
+			if (line.contains("~")) {
+				String lastLine = line.substring(0, line.indexOf("~"));
+				if (lastLine.length() > 0) {
+					appendToValue(value, lastLine);
+				}
+				return new Entry(key, value.toString());
+			}
+			appendToValue(value, line);
+			*/
+		}
+		return null;
+	}
+
+	@Override
+	public void load(SourceInterface source) throws Exception {
+		//TODO not clearing values, because get from manager gives only fields, not children
+		//this.clearValues();
+
+		Entry entry;
+		while ((entry = readEntry(source)) != null) {
+			Param param = getParam(entry.key);
+			if (param == null) {
+				continue;
+			}
+			if (!(param instanceof ValueParam)) {
+				log.warn("param " + param + " is not a ValueParam");
+				continue;
+			}
+			if ((param.getFlags() & Flags.DONTLOAD) != 0) {
+				log.debug("DontLoad flag was set - not loading...");
 			} else {
-				canOmitName = false;
-			}
-		}
-
-		String params = "";
-		if (stringBuilder.length() > 1)
-			params = stringBuilder.substring(0, stringBuilder.length() - 2);
-
-		return getId() + ":" + params;
-	}
-
-    /*
-    private static void appendToValue(StringBuilder value, String line) {
-
-        if (value.length() != 0) {
-            value.append(System.getProperty("line.separator"));
-        }
-        value.append(line);
-    }
-    */
-
-    private Entry readEntry(SourceInterface source)
-            throws IOException {
-
-        String line;
-        String key = null;
-        StringBuilder value = null;
-        while ((line = source.readLine()) != null)
-        {
-            if (key == null) {
-                int colonIndex = line.indexOf(':');
-                if (colonIndex == -1) {
-                    return null;
-                }
-                key = line.substring(0, colonIndex);
-                String inlineValue = line.substring(colonIndex + 1);
-
-
-                if (!inlineValue.startsWith("~")) {
-                    return new Entry(key, inlineValue);
-                }
-                value = new StringBuilder();
-                value.append(inlineValue.substring(1));
-                continue;
-            }
-            if (value.length() != 0) {
-                value.append(System.getProperty("line.separator"));
-            }
-            if (line.contains("~")) {
-                value.append(line.substring(0, line.indexOf("~")));
-                return new Entry(key, value.toString());
-            }
-            value.append(line);
-            /*
-            if (line.contains("~")) {
-                String lastLine = line.substring(0, line.indexOf("~"));
-                if (lastLine.length() > 0) {
-                    appendToValue(value, lastLine);
-                }
-                return new Entry(key, value.toString());
-            }
-            appendToValue(value, line);
-            */
-        }
-        return null;
-    }
-
-    @Override
-    public void load(SourceInterface source) throws Exception {
-        //TODO not clearing values, because get from manager gives only fields, not children
-        //this.clearValues();
-
-        Entry entry;
-        while ((entry = readEntry(source)) != null) {
-            Param param = getParam(entry.key);
-            if (param == null) {
-                continue;
-            }
-            if ((param.getFlags() & Flags.DONTLOAD) != 0) {
-                LOGGER.debug("DontLoad flag was set - not loading...");
-            } else {
-                int retFlags = this.set(param, entry.value);
-                if ((retFlags & (Flags.PSET_HITMIN | Flags.PSET_HITMAX)) != 0) {
-                    String which = ((retFlags & Flags.PSET_HITMIN) != 0) ? "small"
-                            : "big";
-                    LOGGER.warn("value of key '" + entry.key
-                            + "' was too " + which + ", adjusted");
-                }
-            }
-        }
-    }
-
-
-
-	protected abstract <T> void internalSet(Param param, T value);
-
-    @Override
-    public Collection<Param> getParams() {
-        return framsClass.getParamEntries();
-    }
-
-    /*
+				int retFlags = this.set((ValueParam) param, entry.value);
+				if ((retFlags & (Flags.PSET_HITMIN | Flags.PSET_HITMAX)) != 0) {
+					String which = ((retFlags & Flags.PSET_HITMIN) != 0) ? "small" : "big";
+					log.warn("value of key '" + entry.key + "' was too " + which + ", adjusted");
+				}
+			}
+		}
+	}
+
+	protected abstract <T> void internalSet(ValueParam param, T value);
+
+	@Override
+	public Collection<Param> getParams() {
+		return framsClass.getParamEntries();
+	}
+
+	/*
 	protected <T extends Comparable<T>> int setAndCut(Param param, Object value, Class<T> type) {
 		int flags = 0;
Index: java/main/src/main/java/com/framsticks/params/UniqueListAccess.java
===================================================================
--- java/main/src/main/java/com/framsticks/params/UniqueListAccess.java	(revision 79)
+++ java/main/src/main/java/com/framsticks/params/UniqueListAccess.java	(revision 84)
@@ -1,6 +1,6 @@
 package com.framsticks.params;
 
-import com.framsticks.util.Casting;
-import com.framsticks.util.Numbers;
+import com.framsticks.util.lang.Casting;
+import com.framsticks.util.lang.Numbers;
 import org.apache.log4j.Logger;
 
@@ -12,181 +12,184 @@
 public class UniqueListAccess extends ListAccess {
 
-    private static final Logger LOGGER = Logger.getLogger(UniqueListAccess.class.getName());
+	private static final Logger log = Logger.getLogger(UniqueListAccess.class.getName());
 
-    Map<String, Object> map;
+	Map<String, Object> map;
 
-    final String uidName;
+	final String uidName;
 
-    public UniqueListAccess(AccessInterface elementAccess, String uidName) {
-        super(elementAccess);
-        this.uidName = uidName;
-    }
+	public UniqueListAccess(AccessInterface elementAccess, String uidName) {
+		super(elementAccess);
+		this.uidName = uidName;
+	}
 
-    @Override
-    public Map<String, Object> createAccessee() {
-        return new HashMap<String, Object>();
-    }
+	@Override
+	public Map<String, Object> createAccessee() {
+		return new HashMap<String, Object>();
+	}
 
-    @Override
-    public Param getParam(int i) {
-        LOGGER.error("accesing unique list through index");
-        assert false;
-        return null;
-        //LOGGER.error("accesing unique list through index");
-        //return null;
-        //return new ParamBuilder().setId(Integer.toString(i)).setName(elementAccess.getId()).setType("o " + elementAccess.getId()).build();
-    }
+	@Override
+	public Param getParam(int i) {
+		log.error("accesing unique list through index");
+		assert false;
+		return null;
+		//log.error("accesing unique list through index");
+		//return null;
+		//return new ParamBuilder().setId(Integer.toString(i)).setName(elementAccess.getId()).setType("o " + elementAccess.getId()).build();
+	}
 
-    @Override
-    public Param getParam(String id) {
-        Integer i = Numbers.parse(id, Integer.class);
-        if (i != null) {
-            return getParam(i);
-        }
-        return new ParamBuilder().setId(id).setName(elementAccess.getId()).setType("o " + elementAccess.getId()).build();
-    }
+	@Override
+	public Param getParam(String id) {
+		Integer i = Numbers.parse(id, Integer.class);
+		if (i != null) {
+			return getParam(i);
+		}
+		return new ParamBuilder().setId(id).setName(elementAccess.getId()).setType("o " + elementAccess.getId()).build();
+	}
 
-    @Override
-    public String getId() {
-        return "l " + elementAccess.getId() + " " + uidName;
-    }
+	@Override
+	public String getId() {
+		return "l " + elementAccess.getId() + " " + uidName;
+	}
 
-    @Override
-    public int getParamCount() {
-        return map.size();
-    }
+	@Override
+	public int getParamCount() {
+		return map.size();
+	}
 
-    @Override
-    public <T> T get(int i, Class<T> type) {
-        LOGGER.error("accesing unique list through index");
-        assert false;
-        return null;
-        //Object[] values = map.values().toArray();
-        //return Casting.tryCast(i < values.length ? values[i] : null, type);
-    }
+	@Override
+	public <T> T get(int i, Class<T> type) {
+		log.error("accesing unique list through index");
+		assert false;
+		return null;
+		//Object[] values = map.values().toArray();
+		//return Casting.tryCast(i < values.length ? values[i] : null, type);
+	}
 
-    @Override
-    public <T> T get(String id, Class<T> type) {
-        Integer i = Numbers.parse(id, Integer.class);
-        if (i != null) {
-            return get(i, type);
-        }
-        return Casting.tryCast(type, map.containsKey(id) ? map.get(id) : null);
-    }
+	@Override
+	public <T> T get(String id, Class<T> type) {
+		Integer i = Numbers.parse(id, Integer.class);
+		if (i != null) {
+			return get(i, type);
+		}
+		return Casting.tryCast(type, map.containsKey(id) ? map.get(id) : null);
+	}
 
-    @Override
-    public <T> T get(Param param, Class<T> type) {
-        return get(param.getId(), type);
-    }
+	@Override
+	public <T> T get(ValueParam param, Class<T> type) {
+		return get(param.getId(), type);
+	}
 
-    public String getUidOf(Object value) {
-        Object tmp = elementAccess.getSelected();
-        elementAccess.select(value);
-        String uid = elementAccess.get(uidName, String.class);
-        elementAccess.select(tmp);
-        if (uid == null) {
-            return null;
-        }
-        return uid;
-    }
+	public String getUidOf(Object value) {
+		Object tmp = elementAccess.getSelected();
+		elementAccess.select(value);
+		String uid = elementAccess.get(uidName, String.class);
+		elementAccess.select(tmp);
+		if (uid == null) {
+			return null;
+		}
+		return uid;
+	}
 
-    protected int setByUid(Object object, String uid) {
-        if (uid == null) {
-            uid = getUidOf(object);
-            if (uid == null) {
-                LOGGER.error("failed to set - missing uid");
-                return 0;
-            }
-        }
-        if (object == null) {
-            map.remove(uid);
-        } else {
-            map.put(uid, object);
-        }
-        return 0;
-    }
+	protected int setByUid(Object object, String uid) {
+		if (uid == null) {
+			uid = getUidOf(object);
+			if (uid == null) {
+				log.error("failed to set - missing uid");
+				return 0;
+			}
+		}
+		if (object == null) {
+			map.remove(uid);
+		} else {
+			map.put(uid, object);
+		}
+		return 0;
+	}
 
-    @Override
-    public <T> int set(int i, T value) {
-        LOGGER.error("accesing unique list through index");
-        //return setByUid(value, null);
-        return 0;
-    }
+	@Override
+	public <T> int set(int i, T value) {
+		log.error("accesing unique list through index");
+		//return setByUid(value, null);
+		return 0;
+	}
 
-    @Override
-    public <T> int set(String id, T value) {
-        Integer i = Numbers.parse(id, Integer.class);
-        if (i != null) {
-            return set(i, value);
-        }
-        if (value == null) {
-            return setByUid(null, id);
-        }
-        String uid = getUidOf(value);
-        if (uid != null && id != null) {
-            if (!id.equals(uid)) {
-                LOGGER.error("uid mismatch with set key");
-                return 0;
-            }
-            setByUid(value, uid);
-            return 0;
-        }
-        if (uid != null) {
-            setByUid(value, uid);
-            return 0;
-        }
-        if (id != null) {
-            setByUid(value, id);
-            return 0;
-        }
-        LOGGER.error("missing both uid and id - failed to set");
-        return 0;
-    }
+	@Override
+	public <T> int set(String id, T value) {
+		Integer i = Numbers.parse(id, Integer.class);
+		if (i != null) {
+			return set(i, value);
+		}
+		if (value == null) {
+			return setByUid(null, id);
+		}
+		String uid = getUidOf(value);
+		if (uid != null && id != null) {
+			if (!id.equals(uid)) {
+				log.error("uid mismatch with set key");
+				return 0;
+			}
+			setByUid(value, uid);
+			return 0;
+		}
+		if (uid != null) {
+			setByUid(value, uid);
+			return 0;
+		}
+		if (id != null) {
+			setByUid(value, id);
+			return 0;
+		}
+		log.error("missing both uid and id - failed to set");
+		return 0;
+	}
 
-    @Override
-    public <T> int set(Param param, T value) {
-        return set(param.getId(), value);
-    }
+	@Override
+	public <T> int set(ValueParam param, T value) {
+		return set(param.getId(), value);
+	}
 
-    @Override
-    public void clearValues() {
-        map.clear();
-    }
+	@Override
+	public void clearValues() {
+		map.clear();
+	}
 
-    @Override
-    public void select(Object object) {
-        map = (Map<String, Object>)object;
-    }
+	@SuppressWarnings("unchecked")
+	@Override
+	public UniqueListAccess select(Object object) {
+		assert (object instanceof Map);
+		map = (Map<String, Object>) object;
+		return this;
+	}
 
-    @Override
-    public Object getSelected() {
-        return map;
-    }
+	@Override
+	public Object getSelected() {
+		return map;
+	}
 
-    @Override
-    public UniqueListAccess cloneAccess() {
-        return new UniqueListAccess(elementAccess.cloneAccess(), uidName);
-    }
+	@Override
+	public UniqueListAccess cloneAccess() {
+		return new UniqueListAccess(elementAccess.cloneAccess(), uidName);
+	}
 
-    @Override
-    public String computeIdentifierFor(Object selected) {
-        String uid = getUidOf(selected);
-        if (uid == null) {
-            LOGGER.error("missing uid field");
-            return null;
-        }
-        return uid;
-    }
+	@Override
+	public String computeIdentifierFor(Object selected) {
+		String uid = getUidOf(selected);
+		if (uid == null) {
+			log.error("missing uid field");
+			return null;
+		}
+		return uid;
+	}
 
-    @Override
-    public Collection<Param> getParams() {
-        List<Param> result = new LinkedList<Param>();
-        if (map == null) {
-            return result;
-        }
-        for (String k : map.keySet()) {
-            result.add(getParam(k));
-        }
-        return result;
-    }
+	@Override
+	public Collection<Param> getParams() {
+		List<Param> result = new LinkedList<Param>();
+		if (map == null) {
+			return result;
+		}
+		for (String k : map.keySet()) {
+			result.add(getParam(k));
+		}
+		return result;
+	}
 }
Index: java/main/src/main/java/com/framsticks/params/Util.java
===================================================================
--- java/main/src/main/java/com/framsticks/params/Util.java	(revision 79)
+++ java/main/src/main/java/com/framsticks/params/Util.java	(revision 84)
@@ -4,17 +4,21 @@
 import java.util.List;
 
+import static com.framsticks.util.lang.Containers.filterInstanceof;
+
 /**
  * @author Piotr Sniegowski
  */
 public abstract class Util {
-    public static String readSourceToString(SourceInterface source) {
-        StringBuilder result = new StringBuilder();
-        String line;
-        while ((line = source.readLine()) != null) {
-            result.append(line).append(" ");
-        }
-        source.close();
-        return result.toString();
-    }
+
+	public static String readSourceToString(SourceInterface source) {
+		StringBuilder result = new StringBuilder();
+		String line;
+		while ((line = source.readLine()) != null) {
+			result.append(line).append(" ");
+		}
+		source.close();
+		return result.toString();
+	}
+
 	public static List<Object> stripAccessInterface(List<AccessInterface> accesses) {
 		List<Object> result = new ArrayList<Object>();
@@ -24,9 +28,10 @@
 		return result;
 	}
+
 	public static int copyParams(AccessInterface to, AccessInterface from) {
 		int copied = 0;
-		for (Param f : from.getParams()) {
+		for (ValueParam f : filterInstanceof(from.getParams(), ValueParam.class)) {
 			Param t = from.getParam(f.getId());
-			if (t == null) {
+			if (!(t instanceof ValueParam)) {
 				continue;
 			}
@@ -34,5 +39,5 @@
 				continue;
 			}
-			to.set(t, from.get(f, Object.class));
+			to.set((ValueParam) t, from.get(f, Object.class));
 			++copied;
 		}
Index: java/main/src/main/java/com/framsticks/params/ValueParam.java
===================================================================
--- java/main/src/main/java/com/framsticks/params/ValueParam.java	(revision 84)
+++ java/main/src/main/java/com/framsticks/params/ValueParam.java	(revision 84)
@@ -0,0 +1,15 @@
+package com.framsticks.params;
+
+
+/**
+ * @author Piotr Sniegowski
+ */
+public abstract class ValueParam extends Param {
+
+	public ReassignResult<?> reassign(Object newValue, Object oldValue) throws CastFailure {
+		throw new CastFailure();
+	}
+
+	public abstract <T> T getDef(Class<T> type) throws ClassCastException;
+
+}
Index: java/main/src/main/java/com/framsticks/params/types/ArrayListParam.java
===================================================================
--- java/main/src/main/java/com/framsticks/params/types/ArrayListParam.java	(revision 79)
+++ java/main/src/main/java/com/framsticks/params/types/ArrayListParam.java	(revision 84)
@@ -4,7 +4,8 @@
 import com.framsticks.params.ArrayListAccess;
 import com.framsticks.params.CastFailure;
-import com.framsticks.util.Casting;
-import com.framsticks.util.Containers;
-import com.framsticks.util.Numbers;
+import com.framsticks.params.ReassignResult;
+import com.framsticks.util.lang.Casting;
+import com.framsticks.util.lang.Containers;
+import com.framsticks.util.lang.Numbers;
 
 import java.util.ArrayList;
@@ -16,53 +17,53 @@
 public class ArrayListParam extends ListParam {
 
-    public ArrayListParam(String containedTypeName) {
-        super(containedTypeName);
-    }
+	public ArrayListParam(String containedTypeName) {
+		super(containedTypeName);
+	}
 
 
-    @Override
-    public Class getStorageType() {
-        return List.class;
-    }
+	@Override
+	public Class<?> getStorageType() {
+		return List.class;
+	}
 
-    @Override
-    public AccessInterface prepareAccessInterface(AccessInterface access) {
-        return new ArrayListAccess(access);
-    }
+	@Override
+	public AccessInterface prepareAccessInterface(AccessInterface access) {
+		return new ArrayListAccess(access);
+	}
 
-    @Override
-    public String computeAccessId() {
-        return "l " + containedTypeName;
-    }
+	@Override
+	public String computeAccessId() {
+		return "l " + containedTypeName;
+	}
 
-    @Override
-    public Object reassign(Object newValue, Object oldValue) throws CastFailure {
-        if (newValue == null) {
-            throw new CastFailure();
-        }
-        Integer size = Numbers.cast(newValue, Integer.class);
-        if (size != null) {
-            //return oldValue;
-            List list;
-            if (oldValue == null) {
-                list = new ArrayList();
-            } else {
-                list = Casting.tryCast(List.class, oldValue);
-                if (list == null) {
-                    throw new CastFailure();
-                }
-            }
-            Containers.resizeList(list, size);
-            return list;
-        }
-        if (oldValue != null) {
-            return oldValue;
-        }
-        return newValue;
-    }
+	@Override
+	public ReassignResult<List<?>> reassign(Object newValue, Object oldValue) throws CastFailure {
+		if (newValue == null) {
+			throw new CastFailure();
+		}
+		Integer size = Numbers.cast(newValue, Integer.class);
+		if (size != null) {
+			//return oldValue;
+			List<?> list;
+			if (oldValue == null) {
+				list = new ArrayList<Object>();
+			} else {
+				list = Casting.tryCast(List.class, oldValue);
+				if (list == null) {
+					throw new CastFailure();
+				}
+			}
+			Containers.resizeList(list, size);
+			return new ReassignResult<List<?>>(list);
+		}
+		if (oldValue != null) {
+			return new ReassignResult<List<?>>(Casting.throwCast(List.class, oldValue));
+		}
+		return new ReassignResult<List<?>>(Casting.throwCast(List.class, newValue));
+	}
 
-    @Override
-    public String getType() {
-        return "l " + getContainedTypeName();
-    }
+	@Override
+	public String getFramsTypeName() {
+		return "l " + getContainedTypeName();
+	}
 }
Index: java/main/src/main/java/com/framsticks/params/types/BinaryParam.java
===================================================================
--- java/main/src/main/java/com/framsticks/params/types/BinaryParam.java	(revision 79)
+++ java/main/src/main/java/com/framsticks/params/types/BinaryParam.java	(revision 84)
@@ -2,31 +2,37 @@
 
 import com.framsticks.params.CastFailure;
-import com.framsticks.util.Numbers;
+import com.framsticks.params.PrimitiveParam;
+import com.framsticks.params.ReassignResult;
+import com.framsticks.util.lang.Numbers;
 
 /**
  * @author Piotr Sniegowski
  */
-public class BinaryParam extends ValueParam {
+public class BinaryParam extends PrimitiveParam {
+
 	@Override
-	public Class getStorageType() {
+	public Class<?> getStorageType() {
 		return Integer.class;
 	}
 
-    @Override
-    public String getType() {
-        return "db";
-    }
+	@Override
+	public String getFramsTypeName() {
+		return "db";
+	}
 
-    @Override
-    public Object reassign(Object newValue, Object oldValue) throws CastFailure {
-        if (newValue instanceof String) {
-            Integer v = Numbers.parse((String) newValue, Integer.class);
-            if (v != null) {
-                return v;
-            }
-            throw new CastFailure();
-        }
-        return super.reassign(newValue, oldValue);
-    }
+	@Override
+	public ReassignResult<?> reassign(Object newValue, Object oldValue) throws CastFailure {
+		if (newValue instanceof String) {
+			Integer v = Numbers.parse((String) newValue, Integer.class);
+			if (v != null) {
+				return ReassignResult.create(v);
+			}
+			throw new CastFailure();
+		}
+		if (newValue instanceof Integer) {
+			return ReassignResult.create((Integer) newValue);
+		}
+		throw new CastFailure();
+	}
 
 }
Index: java/main/src/main/java/com/framsticks/params/types/BooleanParam.java
===================================================================
--- java/main/src/main/java/com/framsticks/params/types/BooleanParam.java	(revision 79)
+++ java/main/src/main/java/com/framsticks/params/types/BooleanParam.java	(revision 84)
@@ -2,46 +2,56 @@
 
 import com.framsticks.params.CastFailure;
+import com.framsticks.params.PrimitiveParam;
+import com.framsticks.params.ReassignResult;
 import com.framsticks.params.SinkInterface;
+import com.framsticks.util.lang.Numbers;
 
 /**
  * @author Piotr Sniegowski
  */
-public class BooleanParam extends DecimalParam {
-    @Override
-    public Class getStorageType() {
-        return Boolean.class;
-    }
+public class BooleanParam extends PrimitiveParam {
 
-    @Override
-    public Object reassign(Object newValue, Object oldValue) throws CastFailure {
+	public BooleanParam() {
+		def = false;
+	}
+
+	@Override
+	public Class<?> getStorageType() {
+		return Boolean.class;
+	}
+
+	@Override
+	public ReassignResult<Boolean> reassign(Object newValue, Object oldValue) throws CastFailure {
 		if (newValue instanceof Boolean) {
-			return newValue;
+			return ReassignResult.create((Boolean) newValue);
 		}
-        Object casted = super.reassign(newValue, oldValue);
-        if (casted instanceof Integer) {
-            Integer i = (Integer)casted;
-            if (i == 0) return false;
-            if (i == 1) return true;
-            throw new CastFailure();
-        }
-        /*
-        if (newValue instanceof String) {
-            if (newValue.equals("true")) return true;
-            if (newValue.equals("false")) return false;
-            throw new CastFailure();
-        }
-        */
-        throw new CastFailure();
-    }
+		if (newValue instanceof Integer) {
+			return ReassignResult.create(((Integer) newValue) != 0);
+		}
+		if (newValue instanceof String) {
+			if ("true".equals(newValue)) {
+				return ReassignResult.create(true);
+			}
+			if ("false".equals(newValue)) {
+				return ReassignResult.create(false);
+			}
+			Integer i = Numbers.cast(newValue, Integer.class);
+			if (i != null) {
+				return ReassignResult.create(i != 0);
+			}
+			throw new CastFailure();
+		}
+		throw new CastFailure();
+	}
 
-    @Override
-    public String getType() {
-        return "d 0 1";
-    }
+	@Override
+	public String getFramsTypeName() {
+		return "d 0 1";
+	}
 
-    @Override
-    public void save(SinkInterface sink, Object value) {
-        assert value instanceof Boolean;
-        sink.print(((Boolean)value) ? "1" : "0");
-    }
+	@Override
+	public void save(SinkInterface sink, Object value) {
+		assert value instanceof Boolean;
+		sink.print(((Boolean)value) ? "1" : "0");
+	}
 }
Index: java/main/src/main/java/com/framsticks/params/types/ColorParam.java
===================================================================
--- java/main/src/main/java/com/framsticks/params/types/ColorParam.java	(revision 79)
+++ java/main/src/main/java/com/framsticks/params/types/ColorParam.java	(revision 84)
@@ -1,19 +1,26 @@
 package com.framsticks.params.types;
+
+import com.framsticks.params.CastFailure;
+import com.framsticks.params.PrimitiveParam;
+import com.framsticks.params.ReassignResult;
 
 /**
  * @author Piotr Sniegowski
  */
-public class ColorParam extends ValueParam {
+public class ColorParam extends PrimitiveParam {
 
 	@Override
-	public Class getStorageType() {
-		return Void.class;
+	public Class<?> getStorageType() {
+		return Object.class;
 	}
 
-    @Override
-    public String getType() {
-        return "dc";
-    }
+	@Override
+	public String getFramsTypeName() {
+		return "dc";
+	}
 
+	public ReassignResult<Object> reassign(Object newValue, Object oldValue) throws CastFailure {
+		return ReassignResult.create(newValue);
+	}
 
 
Index: java/main/src/main/java/com/framsticks/params/types/CompositeParam.java
===================================================================
--- java/main/src/main/java/com/framsticks/params/types/CompositeParam.java	(revision 79)
+++ 	(revision )
@@ -1,33 +1,0 @@
-package com.framsticks.params.types;
-
-import com.framsticks.params.AccessInterface;
-import com.framsticks.params.Param;
-import com.framsticks.util.Strings;
-
-/**
- * @author Piotr Sniegowski
- */
-public abstract class CompositeParam extends Param {
-	protected final String containedTypeName;
-
-	public CompositeParam(String containedTypeName) {
-		this.containedTypeName = Strings.notEmpty(containedTypeName) ? containedTypeName : null;
-	}
-
-    public boolean isMatchingContainedName(String name) {
-        assert name != null;
-        if (containedTypeName == null) {
-            return true;
-        }
-        return name.equals(containedTypeName);
-    }
-
-	public String getContainedTypeName() {
-		return containedTypeName;
-	}
-
-    public abstract AccessInterface prepareAccessInterface(AccessInterface access);
-
-    public abstract String computeAccessId();
-
-}
Index: java/main/src/main/java/com/framsticks/params/types/DecimalParam.java
===================================================================
--- java/main/src/main/java/com/framsticks/params/types/DecimalParam.java	(revision 79)
+++ java/main/src/main/java/com/framsticks/params/types/DecimalParam.java	(revision 84)
@@ -2,39 +2,29 @@
 
 import com.framsticks.params.CastFailure;
-import com.framsticks.util.Numbers;
+import com.framsticks.params.ReassignResult;
 
 /**
  * @author Piotr Sniegowski
  */
-public class DecimalParam extends ValueParam {
+public class DecimalParam extends NumberParam<Integer> {
 
-	@Override
-	public boolean isNumeric() {
-		return true;
+	public DecimalParam() {
+		def = 0;
 	}
 
 	@Override
-	public Class getStorageType() {
+	public Class<?> getStorageType() {
 		return Integer.class;
 	}
 
+	@Override
+	public ReassignResult<Integer> reassign(Object newValue, Object oldValue) throws CastFailure {
+		return reassignNumber(newValue, oldValue, Integer.class);
+	}
 
-
-    @Override
-    public Object reassign(Object newValue, Object oldValue) throws CastFailure {
-        if (newValue instanceof String) {
-            Integer v = Numbers.parse((String)newValue, Integer.class);
-            if (v != null) {
-                return v;
-            }
-            throw new CastFailure();
-        }
-        return super.reassign(newValue, oldValue);
-    }
-
-    @Override
-    public String getType() {
-        return "d";
-    }
+	@Override
+	public String getFramsTypeName() {
+		return "d";
+	}
 
 
Index: java/main/src/main/java/com/framsticks/params/types/EnumParam.java
===================================================================
--- java/main/src/main/java/com/framsticks/params/types/EnumParam.java	(revision 79)
+++ java/main/src/main/java/com/framsticks/params/types/EnumParam.java	(revision 84)
@@ -1,5 +1,4 @@
 package com.framsticks.params.types;
 
-import java.util.ArrayList;
 import java.util.List;
 
@@ -9,5 +8,5 @@
 public class EnumParam extends DecimalParam {
 
-	ArrayList<String> enums;
+	List<String> enums;
 
 	/**
@@ -16,5 +15,5 @@
 	 * @param enums
 	 */
-	public EnumParam(ArrayList<String> enums) {
+	public EnumParam(List<String> enums) {
 		assert(enums != null);
 		this.enums = enums;
Index: java/main/src/main/java/com/framsticks/params/types/EventParam.java
===================================================================
--- java/main/src/main/java/com/framsticks/params/types/EventParam.java	(revision 79)
+++ java/main/src/main/java/com/framsticks/params/types/EventParam.java	(revision 84)
@@ -7,15 +7,13 @@
  */
 public class EventParam extends Param {
+
 	@Override
-	public Class getStorageType() {
+	public Class<?> getStorageType() {
 		return Void.class;
 	}
 
-    @Override
-    public String getType() {
-        return "e";
-    }
-
-
-
+	@Override
+	public String getFramsTypeName() {
+		return "e";
+	}
 }
Index: java/main/src/main/java/com/framsticks/params/types/FloatParam.java
===================================================================
--- java/main/src/main/java/com/framsticks/params/types/FloatParam.java	(revision 79)
+++ java/main/src/main/java/com/framsticks/params/types/FloatParam.java	(revision 84)
@@ -2,35 +2,29 @@
 
 import com.framsticks.params.CastFailure;
-import com.framsticks.util.Numbers;
+import com.framsticks.params.ReassignResult;
 
 /**
  * @author Piotr Sniegowski
  */
-public class FloatParam extends ValueParam {
+public class FloatParam extends NumberParam<Double> {
+
+	public FloatParam() {
+		def = 0.0;
+	}
+
 	@Override
-	public boolean isNumeric() {
-		return true;
-	}
-	@Override
-	public Class getStorageType() {
+	public Class<?> getStorageType() {
 		return Double.class;
 	}
 
 	@Override
-    public Object reassign(Object newValue, Object oldValue) throws CastFailure {
-        if (newValue instanceof String) {
-		    Double v = Numbers.parse((String)newValue, Double.class);
-            if (v != null) {
-                return v;
-            }
-            throw new CastFailure();
-        }
-        return super.reassign(newValue, oldValue);
+	public ReassignResult<Double> reassign(Object newValue, Object oldValue) throws CastFailure {
+		return reassignNumber(newValue, oldValue, Double.class);
 	}
 
-    @Override
-    public String getType() {
-        return "f";
-    }
+	@Override
+	public String getFramsTypeName() {
+		return "f";
+	}
 
 
Index: java/main/src/main/java/com/framsticks/params/types/ListParam.java
===================================================================
--- java/main/src/main/java/com/framsticks/params/types/ListParam.java	(revision 79)
+++ java/main/src/main/java/com/framsticks/params/types/ListParam.java	(revision 84)
@@ -1,10 +1,5 @@
 package com.framsticks.params.types;
 
-import com.framsticks.params.CastFailure;
-import com.framsticks.util.Casting;
-import com.framsticks.util.Containers;
-import com.framsticks.util.Numbers;
-
-import java.util.List;
+import com.framsticks.params.CompositeParam;
 
 /**
@@ -17,8 +12,3 @@
 	}
 
-
-
-
-
-
 }
Index: java/main/src/main/java/com/framsticks/params/types/NumberParam.java
===================================================================
--- java/main/src/main/java/com/framsticks/params/types/NumberParam.java	(revision 84)
+++ java/main/src/main/java/com/framsticks/params/types/NumberParam.java	(revision 84)
@@ -0,0 +1,38 @@
+package com.framsticks.params.types;
+
+import com.framsticks.params.CastFailure;
+import com.framsticks.params.Flags;
+import com.framsticks.params.PrimitiveParam;
+import com.framsticks.params.ReassignResult;
+import com.framsticks.util.lang.Casting;
+import com.framsticks.util.lang.Numbers;
+
+/**
+ * @author Piotr Sniegowski
+ */
+public abstract class NumberParam<T extends Number & Comparable<T>> extends PrimitiveParam {
+
+	@Override
+	public boolean isNumeric() {
+		return true;
+	}
+
+	protected ReassignResult<T> reassignNumber(Object newValue, Object oldValue, Class<T> type) throws CastFailure {
+		T v = null;
+		if (newValue instanceof String) {
+			v = Numbers.parse((String)newValue, type);
+		} else {
+			v = Casting.tryCast(type, newValue);
+		}
+		if (v == null) {
+			throw new CastFailure();
+		}
+		if (min != null && v.compareTo(getMin(type)) < 0) {
+			return new ReassignResult<T>(getMin(type), Flags.PSET_HITMIN);
+		}
+		if (max != null && v.compareTo(getMax(type)) > 0) {
+			return new ReassignResult<T>(getMax(type), Flags.PSET_HITMAX);
+		}
+		return ReassignResult.create(v);
+	}
+}
Index: java/main/src/main/java/com/framsticks/params/types/ObjectParam.java
===================================================================
--- java/main/src/main/java/com/framsticks/params/types/ObjectParam.java	(revision 79)
+++ java/main/src/main/java/com/framsticks/params/types/ObjectParam.java	(revision 84)
@@ -3,4 +3,6 @@
 import com.framsticks.params.AccessInterface;
 import com.framsticks.params.CastFailure;
+import com.framsticks.params.CompositeParam;
+import com.framsticks.params.ReassignResult;
 
 /**
@@ -13,36 +15,28 @@
 	}
 
-    @Override
-    public String computeAccessId() {
-        return containedTypeName;
-    }
+	@Override
+	public String computeAccessId() {
+		return containedTypeName;
+	}
 
-    @Override
-	public Class getStorageType() {
+	@Override
+	public Class<?> getStorageType() {
 		return Object.class;
 	}
 
 	@Override
-	public boolean isEmptyAvailable() {
-		return true;
+	public ReassignResult<Object> reassign(Object newValue, Object oldValue) throws CastFailure {
+		return ReassignResult.create(newValue);
 	}
 
 	@Override
-	public Object reassign(Object newValue, Object oldValue) throws CastFailure {
-		return newValue;
+	public AccessInterface prepareAccessInterface(AccessInterface access) {
+		return access;
 	}
 
-    @Override
-    public AccessInterface prepareAccessInterface(AccessInterface access) {
-        return access;
-    }
-
-    @Override
-    public String getType() {
-        return "o " + containedTypeName;
-    }
-
-
-
+	@Override
+	public String getFramsTypeName() {
+		return "o " + containedTypeName;
+	}
 
 }
Index: java/main/src/main/java/com/framsticks/params/types/ProcedureParam.java
===================================================================
--- java/main/src/main/java/com/framsticks/params/types/ProcedureParam.java	(revision 79)
+++ java/main/src/main/java/com/framsticks/params/types/ProcedureParam.java	(revision 84)
@@ -1,9 +1,7 @@
 package com.framsticks.params.types;
 
-import com.framsticks.params.CastFailure;
-import com.framsticks.params.FramsClass;
 import com.framsticks.params.Param;
 import com.framsticks.params.ParamBuilder;
-import com.framsticks.util.Strings;
+import com.framsticks.util.lang.Strings;
 
 import java.util.ArrayList;
@@ -58,5 +56,5 @@
 
 	@Override
-	public Class getStorageType() {
+	public Class<?> getStorageType() {
 		return Void.class;
 	}
@@ -70,13 +68,8 @@
 	}
 
-    @Override
-    public Object reassign(Object newValue, Object oldValue) throws CastFailure {
-        throw new CastFailure();
-    }
-
-    @Override
-    public String getType() {
-        return "p";
-    }
+	@Override
+	public String getFramsTypeName() {
+		return "p";
+	}
 
 }
Index: java/main/src/main/java/com/framsticks/params/types/StringParam.java
===================================================================
--- java/main/src/main/java/com/framsticks/params/types/StringParam.java	(revision 79)
+++ java/main/src/main/java/com/framsticks/params/types/StringParam.java	(revision 84)
@@ -2,4 +2,6 @@
 
 import com.framsticks.params.CastFailure;
+import com.framsticks.params.PrimitiveParam;
+import com.framsticks.params.ReassignResult;
 import com.framsticks.params.SinkInterface;
 
@@ -7,35 +9,34 @@
  * @author Piotr Sniegowski
  */
-public class StringParam extends ValueParam {
+public class StringParam extends PrimitiveParam {
 	@Override
-	public Class getStorageType() {
+	public Class<?> getStorageType() {
 		return String.class;
 	}
 
 	@Override
-	public boolean isEmptyAvailable() {
-		return true;
+	public ReassignResult<String> reassign(Object newValue, Object oldValue) throws CastFailure {
+		if (newValue == null) {
+			return new ReassignResult<String>(null);
+		}
+		if (newValue instanceof String) {
+			return ReassignResult.create((String) newValue);
+		}
+		return ReassignResult.create(newValue.toString());
+		// return super.reassign(newValue, oldValue);
 	}
 
-    @Override
-    public Object reassign(Object newValue, Object oldValue) throws CastFailure {
-        if (newValue instanceof String) {
-            return (String)newValue;
-        }
-        return super.reassign(newValue, oldValue);
-    }
+	@Override
+	public String getFramsTypeName() {
+		return "s";
+	}
 
-    @Override
-    public String getType() {
-        return "s";
-    }
+	private static final String SEPARATOR = System.getProperty("line.separator");
 
-    private static final String SEPARATOR = System.getProperty("line.separator");
-
-    @Override
-    public void save(SinkInterface sink, Object value) {
-        assert value instanceof String;
-        String s = (String)value;
-        sink.print((s.contains(SEPARATOR) ? (s = "~" + SEPARATOR + s + "~") : s));
-    }
+	@Override
+	public void save(SinkInterface sink, Object value) {
+		assert value instanceof String;
+		String s = (String)value;
+		sink.print((s.contains(SEPARATOR) ? (s = "~" + SEPARATOR + s + "~") : s));
+	}
 }
Index: java/main/src/main/java/com/framsticks/params/types/UniqueListParam.java
===================================================================
--- java/main/src/main/java/com/framsticks/params/types/UniqueListParam.java	(revision 79)
+++ java/main/src/main/java/com/framsticks/params/types/UniqueListParam.java	(revision 84)
@@ -3,9 +3,9 @@
 import com.framsticks.params.AccessInterface;
 import com.framsticks.params.CastFailure;
+import com.framsticks.params.ReassignResult;
 import com.framsticks.params.UniqueListAccess;
-import com.framsticks.util.Numbers;
+import com.framsticks.util.lang.Numbers;
 
 import java.util.HashMap;
-import java.util.List;
 import java.util.Map;
 
@@ -15,53 +15,52 @@
 public class UniqueListParam extends ListParam {
 
-    final String uidName;
+	final String uidName;
 
-    public UniqueListParam(String containedTypeName, String uidName) {
-        super(containedTypeName);
-        this.uidName = uidName;
-    }
+	public UniqueListParam(String containedTypeName, String uidName) {
+		super(containedTypeName);
+		this.uidName = uidName;
+	}
 
-    @Override
-    public String computeAccessId() {
-        return "l " + containedTypeName + " " + uidName;
-    }
+	@Override
+	public String computeAccessId() {
+		return "l " + containedTypeName + " " + uidName;
+	}
 
 
-    @Override
-    public Class getStorageType() {
-        return Map.class;
-    }
+	@Override
+	public Class<?> getStorageType() {
+		return Map.class;
+	}
 
-    @Override
-    public AccessInterface prepareAccessInterface(AccessInterface access) {
-        return new UniqueListAccess(access, uidName);
-    }
+	@Override
+	public AccessInterface prepareAccessInterface(AccessInterface access) {
+		return new UniqueListAccess(access, uidName);
+	}
 
+	@Override
+	public ReassignResult<? extends Map<?,?>> reassign(Object newValue, Object oldValue) throws CastFailure {
+		if (newValue instanceof Map) {
+			return new ReassignResult<Map<?,?>>((Map<?,?>) newValue);
+		}
+		Integer size = Numbers.cast(newValue, Integer.class);
+		if (size != null) {
+			//return oldValue;
+			/*
+			the integer value should be ignored, because this may cause, that object is created before
+			information about it's elements is available, which would break resolution flow
+			*/
+			if (oldValue != null) {
+				return new ReassignResult<Map<?,?>>((Map<?,?>) oldValue);
+			}
+			return ReassignResult.create(new HashMap<Object, Object>());
+		}
 
-    @Override
-    public Object reassign(Object newValue, Object oldValue) throws CastFailure {
-        if (newValue instanceof Map) {
-            return newValue;
-        }
-        Integer size = Numbers.cast(newValue, Integer.class);
-        if (size != null) {
-            //return oldValue;
-            /*
-            the integer value should be ignored, because this may cause, that object is created before
-            information about it's elements is available, which would break resolution flow
-            */
-            if (oldValue != null) {
-                return oldValue;
-            }
-            return new HashMap();
-        }
+		throw new CastFailure();
+	}
 
-        throw new CastFailure();
-    }
-
-    @Override
-    public String getType() {
-        return "l " + containedTypeName + " " + uidName;
-    }
+	@Override
+	public String getFramsTypeName() {
+		return "l " + containedTypeName + " " + uidName;
+	}
 
 
Index: java/main/src/main/java/com/framsticks/params/types/UniversalParam.java
===================================================================
--- java/main/src/main/java/com/framsticks/params/types/UniversalParam.java	(revision 79)
+++ java/main/src/main/java/com/framsticks/params/types/UniversalParam.java	(revision 84)
@@ -2,25 +2,25 @@
 
 import com.framsticks.params.CastFailure;
-import com.framsticks.util.Numbers;
+import com.framsticks.params.PrimitiveParam;
+import com.framsticks.params.ReassignResult;
 
 /**
  * @author Piotr Sniegowski
  */
-public class UniversalParam extends ValueParam {
+public class UniversalParam extends PrimitiveParam {
 	@Override
-	public Class getStorageType() {
+	public Class<?> getStorageType() {
 		return Object.class;
 	}
 
 	@Override
-	public boolean isEmptyAvailable() {
-		return true;
+	public String getFramsTypeName() {
+		return "x";
 	}
 
-    @Override
-    public String getType() {
-        return "x";
-    }
-
+	@Override
+	public ReassignResult<Object> reassign(Object newValue, Object oldValue) throws CastFailure {
+		return ReassignResult.create(newValue);
+	}
 
 }
Index: java/main/src/main/java/com/framsticks/params/types/ValueParam.java
===================================================================
--- java/main/src/main/java/com/framsticks/params/types/ValueParam.java	(revision 79)
+++ 	(revision )
@@ -1,14 +1,0 @@
-package com.framsticks.params.types;
-
-import com.framsticks.params.Param;
-import com.framsticks.params.SinkInterface;
-
-/**
- * @author Piotr Sniegowski
- */
-public abstract class ValueParam extends Param {
-
-    public void save(SinkInterface sink, Object value) {
-        sink.print(value);
-    }
-}
Index: java/main/src/main/java/com/framsticks/parsers/F0Parser.java
===================================================================
--- java/main/src/main/java/com/framsticks/parsers/F0Parser.java	(revision 79)
+++ java/main/src/main/java/com/framsticks/parsers/F0Parser.java	(revision 84)
@@ -7,4 +7,5 @@
 import java.text.ParseException;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.List;
 
@@ -14,7 +15,9 @@
 import com.framsticks.params.Flags;
 import com.framsticks.params.Param;
-import com.framsticks.util.Exceptions;
-import com.framsticks.util.Pair;
-import com.framsticks.util.Strings;
+import com.framsticks.params.PrimitiveParam;
+import com.framsticks.util.lang.Containers;
+import com.framsticks.util.lang.Exceptions;
+import com.framsticks.util.lang.Pair;
+import com.framsticks.util.lang.Strings;
 import org.apache.log4j.Logger;
 
@@ -27,5 +30,5 @@
 public class F0Parser {
 
-	private final static Logger LOGGER = Logger.getLogger(F0Parser.class);
+	private final static Logger log = Logger.getLogger(F0Parser.class);
 
 	/** The schema proper for f0 representation. */
@@ -71,5 +74,5 @@
 	 * fields (bigger than maximum or smaller than minimum values) are
 	 * communicated by warnings and set to minimum / maximum value.
-	 * 
+	 *
 	 * @return the list
 	 * @throws IOException
@@ -91,5 +94,5 @@
 				if (lineNumber == 1) {
 					if (!"//0".equals(line)) {
-						LOGGER.warn("stream should begin with \"//0\" in the first line");
+						log.warn("stream should begin with \"//0\" in the first line");
 					} else {
 						continue;
@@ -122,5 +125,5 @@
 
 	private static void warn(int lineNumber, String message, Exception e) {
-		LOGGER.warn("in line " + lineNumber + " the following error occurred (" + message + "): " + e + "\n" + Exceptions.printStackTrace(e));
+		log.warn("in line " + lineNumber + " the following error occurred (" + message + "): " + e + "\n" + Exceptions.printStackTrace(e));
 	}
 
@@ -175,9 +178,10 @@
 		List<Exception> exceptions = new ArrayList<Exception>();
 
-		Param[] params = access.getParams().toArray(new Param[] {null});
+		Collection<Param> paramsC = access.getParams();
+		Param[] params = paramsC.toArray(new Param[] {null});
 		if (params.length == 0) {
 			return exceptions;
 		}
-		for (Param p : params) {
+		for (PrimitiveParam p : Containers.filterInstanceof(paramsC, PrimitiveParam.class)) {
 			Object def = p.getDef(Object.class);
 			if (def != null) {
@@ -210,14 +214,14 @@
 					currentParam = params[nextParamNumber];
 				}
-
 				if (currentParam != null) {
 					if (pair.value != null) {
-						int setFlag = access.set(currentParam, pair.value);
+						PrimitiveParam vp = (PrimitiveParam) currentParam;
+						int setFlag = access.set(vp, pair.value);
 						if ((setFlag & Flags.PSET_HITMIN) != 0) {
-							exceptions.add(createBoundaryHitException(access, currentParam, pair.value, Flags.PSET_HITMIN));
+							exceptions.add(createBoundaryHitException(access, vp, pair.value, Flags.PSET_HITMIN));
 						}
 
 						if ((setFlag & Flags.PSET_HITMAX) != 0) {
-							exceptions.add(createBoundaryHitException(access, currentParam, pair.value, Flags.PSET_HITMAX));
+							exceptions.add(createBoundaryHitException(access, vp, pair.value, Flags.PSET_HITMAX));
 						}
 
@@ -243,5 +247,5 @@
 	}
 
-	private static Exception createBoundaryHitException(AccessInterface access, Param param, String value, int flag) {
+	private static Exception createBoundaryHitException(AccessInterface access, PrimitiveParam param, String value, int flag) {
 		boolean minimum = (flag & Flags.PSET_HITMIN) != 0;
 		String boundary = (minimum ? param.getMin(Object.class) : param.getMax(Object.class)).toString();
Index: java/main/src/main/java/com/framsticks/parsers/F0Writer.java
===================================================================
--- java/main/src/main/java/com/framsticks/parsers/F0Writer.java	(revision 84)
+++ java/main/src/main/java/com/framsticks/parsers/F0Writer.java	(revision 84)
@@ -0,0 +1,86 @@
+package com.framsticks.parsers;
+
+import com.framsticks.model.Model;
+import com.framsticks.params.*;
+import com.framsticks.util.Misc;
+import com.framsticks.util.lang.Containers;
+import static com.framsticks.util.lang.Containers.filterInstanceof;
+
+/**
+ * Author: Piotr Śniegowski
+ */
+public class F0Writer {
+
+	protected final Schema schema;
+	protected final SinkInterface sink;
+	protected final Model model;
+	protected boolean omit = true;
+
+	public F0Writer(Schema schema, Model model, SinkInterface sink) {
+		this.schema = schema;
+		this.model = model;
+		this.sink = sink;
+	}
+
+	F0Writer omitDefaultValues(boolean omit) {
+		this.omit = omit;
+		return this;
+	}
+
+	protected void write(AccessInterface access) {
+		if (access instanceof ListAccess) {
+			// TODO
+			for (ValueParam p : Containers.filterInstanceof(access.getParams(), ValueParam.class)) {
+				write(schema.getRegistry().prepareAccess((CompositeParam) p).select(access.get(p, Object.class)));
+			}
+			return;
+		}
+		StringBuilder line = new StringBuilder();
+		line.append(access.getId()).append(":");
+		boolean placeComma = false;
+		boolean contiguous = true;
+
+		for (ValueParam param : filterInstanceof(access.getParams(), ValueParam.class)) {
+			if (param instanceof CompositeParam) {
+				AccessInterface a = schema.getRegistry().prepareAccess((CompositeParam)param);
+				a.select(access.get((ValueParam) param, Object.class));
+				write(a);
+				continue;
+			}
+			Object value = access.get(param, Object.class);
+			if ((param instanceof PrimitiveParam) && Misc.equals(value, ((PrimitiveParam) param).getDef(Object.class))) {
+				contiguous = false;
+				continue;
+			}
+			if (value == null) {
+				contiguous = false;
+				continue;
+			}
+
+			if (placeComma) {
+				line.append(",");
+			} else {
+				placeComma = true;
+			}
+
+			if ((!contiguous) || ((param.getFlags() & Flags.CANOMITNAME) == 0)) {
+				line.append(param.getId()).append("=");
+				contiguous = true;
+			}
+			String printed = value.toString().replace("\"", "\\\"");
+			if (printed.contains(",")) {
+				line.append("\"").append(printed).append("\"");
+			} else {
+				line.append(value);
+			}
+		}
+		sink.print(line).breakLine();
+	}
+	public void write() {
+		AccessInterface access = schema.getRegistry().createAccess("m");
+		access.select(model);
+		write(access);
+	}
+
+
+}
Index: java/main/src/main/java/com/framsticks/parsers/Loaders.java
===================================================================
--- java/main/src/main/java/com/framsticks/parsers/Loaders.java	(revision 79)
+++ java/main/src/main/java/com/framsticks/parsers/Loaders.java	(revision 84)
@@ -9,5 +9,5 @@
 public class Loaders {
 
-	private static final Logger LOGGER = Logger.getLogger(Loaders.class.getName());
+	private static final Logger log = Logger.getLogger(Loaders.class.getName());
 
 	public static FramsClass loadFramsClass(SourceInterface source) {
@@ -15,9 +15,9 @@
 		loader.setNewSource(source);
 
-        FramsClass result = new FramsClass();
+		FramsClass result = new FramsClass();
 
-        AccessInterface framsClassAccess = new ReflectionAccess(FramsClass.class, FramsClass.getFramsClass());
-        AccessInterface paramBuilderAccess = new ReflectionAccess(ParamBuilder.class, ParamBuilder.getFramsClass());
-        framsClassAccess.select(result);
+		AccessInterface framsClassAccess = new ReflectionAccess(FramsClass.class, FramsClass.getFramsClass());
+		AccessInterface paramBuilderAccess = new ReflectionAccess(ParamBuilder.class, ParamBuilder.getFramsClass());
+		framsClassAccess.select(result);
 		loader.addAccessInterface(framsClassAccess);
 		loader.addAccessInterface(paramBuilderAccess);
@@ -31,9 +31,9 @@
 
 					Object object = loader.returnObject();
-                    if (object instanceof FramsClass) {
-                        continue;
-                    }
-                    if (object instanceof ParamBuilder) {
-                        result.append(((ParamBuilder) object).build());
+					if (object instanceof FramsClass) {
+						continue;
+					}
+					if (object instanceof ParamBuilder) {
+						result.append(((ParamBuilder) object).build());
 					}
 				}
@@ -41,5 +41,5 @@
 			return result;
 		} catch (Exception e) {
-			LOGGER.error("an error occurred while loading class description: " + e + " before " + source.readLine());
+			log.error("an error occurred while loading class description: " + e + " before " + source.readLine());
 			e.printStackTrace();
 		}
Index: java/main/src/main/java/com/framsticks/parsers/Savers.java
===================================================================
--- java/main/src/main/java/com/framsticks/parsers/Savers.java	(revision 79)
+++ java/main/src/main/java/com/framsticks/parsers/Savers.java	(revision 84)
@@ -8,15 +8,15 @@
  */
 public class Savers {
-    public static void saveFramsClass(SinkInterface sink, FramsClass framsClass) {
+	public static void saveFramsClass(SinkInterface sink, FramsClass framsClass) {
 
-        AccessInterface framsClassAccess = new ReflectionAccess(FramsClass.class, FramsClass.getFramsClass());
-        AccessInterface paramAccess = new ReflectionAccess(Param.class, Param.getFramsClass());
-        framsClassAccess.select(framsClass);
-        framsClassAccess.save(sink);
-        for (Param p : framsClass.getParamEntries()) {
-            paramAccess.select(p);
-            paramAccess.save(sink);
-        }
-    }
+		AccessInterface framsClassAccess = new ReflectionAccess(FramsClass.class, FramsClass.getFramsClass());
+		AccessInterface paramAccess = new ReflectionAccess(Param.class, Param.getFramsClass());
+		framsClassAccess.select(framsClass);
+		framsClassAccess.save(sink);
+		for (Param p : framsClass.getParamEntries()) {
+			paramAccess.select(p);
+			paramAccess.save(sink);
+		}
+	}
 
 }
Index: java/main/src/main/java/com/framsticks/parsers/Schema.java
===================================================================
--- java/main/src/main/java/com/framsticks/parsers/Schema.java	(revision 79)
+++ java/main/src/main/java/com/framsticks/parsers/Schema.java	(revision 84)
@@ -1,6 +1,4 @@
 package com.framsticks.parsers;
 
-import java.io.File;
-import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStream;
@@ -8,10 +6,7 @@
 import java.util.HashMap;
 import java.util.Map;
-import java.util.Map.Entry;
 
 import com.framsticks.params.*;
-import com.framsticks.params.types.DecimalParam;
-import com.framsticks.params.types.FloatParam;
-import com.framsticks.params.types.StringParam;
+import com.framsticks.util.lang.Numbers;
 import org.apache.log4j.Logger;
 
@@ -224,4 +219,11 @@
 	}
 
+	private static <T extends Number> T extractAttribute(NamedNodeMap attributes, String name, Class<T> type) {
+		String value = getAttribute(attributes, name);
+		if (value == null) {
+			return null;
+		}
+		return Numbers.parse(value, type);
+	}
 	/**
 	 * It analyses the single property within the class
@@ -265,56 +267,22 @@
 		}
 
-		Map<String, String> minMaxDef = new HashMap<String, String>();
-
-		for (String key : new String[] { "MIN", "MAX", "DEF" }) {
-			String value = getAttribute(attributes, key);
-			if (value != null && !value.trim().equals(""))
-				minMaxDef.put(key, value);
-		}
-
 		ParamBuilder builder = new ParamBuilder();
 		builder.setId(id).setName(name).setHelp(description).setGroup(group).setFlags(flags);
 
+		builder.setType(type);
+
 		if ("d".equals(type)) {
-
-			Map<String, Integer> minMaxDefInt = new HashMap<String, Integer>();
-			for (Entry<String, String> entry : minMaxDef.entrySet()) {
-				try {
-					minMaxDefInt.put(entry.getKey(),
-							Integer.parseInt(entry.getValue()));
-				} catch (NumberFormatException e) {
-					logger.warn(entry.getKey() + " attribute in property \""
-							+ id + "\" getId in class \"" + classId
-							+ "\" should be an integer value");
-				}
-			}
-
-			builder.setType(DecimalParam.class);
-			builder.setMin(minMaxDefInt.get("MIN"));
-			builder.setMax(minMaxDefInt.get("MAX"));
-			builder.setDef(minMaxDefInt.get("DEF"));
-
+			builder.setMin(extractAttribute(attributes, "MIN", Integer.class));
+			builder.setMax(extractAttribute(attributes, "MAX", Integer.class));
+			builder.setDef(extractAttribute(attributes, "DEF", Integer.class));
 		} else if ("f".equals(type)) {
-
-			Map<String, Double> minMaxDefDouble = new HashMap<String, Double>();
-			for (Entry<String, String> entry : minMaxDef.entrySet()) {
-				try {
-					minMaxDefDouble.put(entry.getKey(),
-							Double.parseDouble(entry.getValue()));
-				} catch (NumberFormatException e) {
-					logger.warn(entry.getKey() + " attribute in property \""
-							+ id + "\" getId in class \"" + classId
-							+ "\" should be a double value");
-				}
-			}
-			builder.setType(FloatParam.class);
-			builder.setMin(minMaxDefDouble.get("MIN"));
-			builder.setMax(minMaxDefDouble.get("MAX"));
-			builder.setDef(minMaxDefDouble.get("DEF"));
-
-
+			builder.setMin(extractAttribute(attributes, "MIN", Double.class));
+			builder.setMax(extractAttribute(attributes, "MAX", Double.class));
+			builder.setDef(extractAttribute(attributes, "DEF", Double.class));
 		} else if ("s".equals(type)) {
-			builder.setType(StringParam.class);
-			builder.setDef(minMaxDef.get("DEF"));
+			builder.setMin(extractAttribute(attributes, "MIN", Integer.class));
+			builder.setMax(extractAttribute(attributes, "MAX", Integer.class));
+			builder.setDef(extractAttribute(attributes, "DEF", Integer.class));
+			builder.setDef(getAttribute(attributes, "DEF"));
 		} else {
 			builder.setType(type);
Index: java/main/src/main/java/com/framsticks/portals/Portal.java
===================================================================
--- java/main/src/main/java/com/framsticks/portals/Portal.java	(revision 79)
+++ java/main/src/main/java/com/framsticks/portals/Portal.java	(revision 84)
@@ -1,5 +1,4 @@
 package com.framsticks.portals;
 
-import com.framsticks.core.Parameters;
 import com.framsticks.observers.Observer;
 import com.framsticks.params.FramsClass;
@@ -13,43 +12,36 @@
 public class Portal extends Observer {
 
-    private final static Logger LOGGER = Logger.getLogger(Portal.class.getName());
+	private final static Logger log = Logger.getLogger(Portal.class.getName());
 
-    public Integer counter = 0;
+	public Integer counter = 0;
 
-    public Portal(Parameters parameters) {
-        super(parameters);
-    }
+	public Portal() {
+	}
 
-    @Override
-    public void run() {
-        super.run();
-        new PeriodicTask(this, 1000) {
+	@Override
+	public void run() {
+		super.run();
+		new PeriodicTask(this, 1000) {
 
-            @Override
-            public void run() {
-                ++counter;
-                LOGGER.debug("counter is now: " + counter);
-                again();
-            }
-        };
-    }
+			@Override
+			public void run() {
+				++counter;
+				log.debug("counter is now: " + counter);
+				again();
+			}
+		};
+	}
 
-    @Override
-    protected void configure() throws Exception {
-        super.configure();
-    }
+	@Override
+	protected PortalEndpoint createEndpoint() {
+		return new PortalEndpoint();
+	}
 
+	public Double getCounterSquared() {
+		return (double)(counter * counter);
+	}
 
-    @Override
-    protected PortalEndpoint createEndpoint() {
-        return new PortalEndpoint();
-    }
-
-    public Double getCounterSquared() {
-        return (double)(counter * counter);
-    }
-
-    public static void constructFramsClass(FramsClass.Constructor constructor) {
-        constructor.method("getCounterSquared").field("counter");
-    }
+	public static void constructFramsClass(FramsClass.Constructor constructor) {
+		constructor.method("getCounterSquared").field("counter");
+	}
 }
Index: java/main/src/main/java/com/framsticks/portals/PortalEndpoint.java
===================================================================
--- java/main/src/main/java/com/framsticks/portals/PortalEndpoint.java	(revision 79)
+++ java/main/src/main/java/com/framsticks/portals/PortalEndpoint.java	(revision 84)
@@ -3,6 +3,6 @@
 import com.framsticks.core.Path;
 import com.framsticks.observers.Endpoint;
-import com.framsticks.util.Dispatching;
-import com.framsticks.util.Future;
+import com.framsticks.util.dispatching.Dispatching;
+import com.framsticks.util.dispatching.Future;
 import com.framsticks.util.Logging;
 import org.apache.log4j.Logger;
@@ -13,5 +13,5 @@
 public class PortalEndpoint extends Endpoint {
 
-	private final static Logger LOGGER = Logger.getLogger(PortalEndpoint.class.getName());
+	private final static Logger log = Logger.getLogger(PortalEndpoint.class.getName());
 
 	public PortalEndpoint() {
@@ -39,5 +39,5 @@
                     @Override
                     public void result(Path result, Exception e) {
-                        Logging.log(LOGGER, "resolve", path, e);
+                        Logging.log(log, "resolve", path, e);
                     }
                 });
@@ -57,5 +57,5 @@
             @Override
             public void run() {
-                LOGGER.debug("change at " + path);
+                log.debug("change at " + path);
             }
         });
Index: java/main/src/main/java/com/framsticks/remote/RecursiveFetcher.java
===================================================================
--- java/main/src/main/java/com/framsticks/remote/RecursiveFetcher.java	(revision 79)
+++ java/main/src/main/java/com/framsticks/remote/RecursiveFetcher.java	(revision 84)
@@ -4,12 +4,12 @@
 import com.framsticks.core.Path;
 import com.framsticks.params.AccessInterface;
+import com.framsticks.params.CompositeParam;
 import com.framsticks.params.FramsClass;
-import com.framsticks.params.Param;
-import com.framsticks.params.types.CompositeParam;
 import com.framsticks.core.Instance;
-import com.framsticks.util.Future;
+import com.framsticks.util.dispatching.Future;
 import com.framsticks.util.StateFunctor;
 import com.framsticks.util.Stopwatch;
 import org.apache.log4j.Logger;
+import static com.framsticks.util.lang.Containers.filterInstanceof;
 
 /**
@@ -18,81 +18,78 @@
 public class RecursiveFetcher {
 
-    private final static Logger LOGGER = Logger.getLogger(RecursiveFetcher.class.getName());
+	private final static Logger log = Logger.getLogger(RecursiveFetcher.class.getName());
 
-    protected final Instance instance;
-    protected final StateFunctor stateFunctor;
-    protected int dispatched;
-    protected final Stopwatch stopwatch = new Stopwatch();
+	protected final Instance instance;
+	protected final StateFunctor stateFunctor;
+	protected int dispatched;
+	protected final Stopwatch stopwatch = new Stopwatch();
 
-    public RecursiveFetcher(Instance instance, final Path path, StateFunctor stateFunctor) {
-        this.instance = instance;
-        this.stateFunctor = stateFunctor;
-        dispatched = 1;
-        process(path);
-    }
+	public RecursiveFetcher(Instance instance, final Path path, StateFunctor stateFunctor) {
+		this.instance = instance;
+		this.stateFunctor = stateFunctor;
+		dispatched = 1;
+		process(path);
+	}
 
-    protected void finished() {
-        assert instance.isActive();
-        LOGGER.info("recursively fetched in " + stopwatch);
-        stateFunctor.call(null);
-    }
+	protected void finished() {
+		assert instance.isActive();
+		log.info("recursively fetched in " + stopwatch);
+		stateFunctor.call(null);
+	}
 
-    protected void process(final Path path) {
-        assert instance.isActive();
-        if (path == null || !path.isResolved()) {
-            LOGGER.warn("path " + path + " is not resolved - skipping");
-        } else {
-            AccessInterface access = instance.bindAccess(path);
-            FramsClass framsClass = access.getFramsClass();
-            assert framsClass != null;
-            for (Param p : access.getParams()) {
-                if (p instanceof CompositeParam) {
-                    CompositeParam childParam = (CompositeParam)p;
-                    Object child = access.get(childParam, Object.class);
-                    final Path childPath = path.appendNode(new Node(childParam, child));
-                    if (childPath.isResolved() && instance.getInfoFromCache(childPath) != null) {
-                        ++dispatched;
-                        instance.invokeLater(new Runnable() {
-                            @Override
-                            public void run() {
-                                fetch(childPath);
-                            }
-                        });
-                        continue;
-                    }
-                    ++dispatched;
-                    instance.resolve(childPath, new Future<Path>() {
-                        @Override
-                        public void result(Path result, Exception e) {
-                            assert instance.isActive();
-                            if (e != null) {
-                                LOGGER.error(e);
-                                return;
-                            }
-                            fetch(result);
-                        }
-                    });
-                }
-            }
-        }
-        --dispatched;
-        if (dispatched == 0) {
-            finished();
-        }
-    }
+	protected void process(final Path path) {
+		assert instance.isActive();
+		if (path == null || !path.isResolved()) {
+			log.warn("path " + path + " is not resolved - skipping");
+		} else {
+			AccessInterface access = instance.bindAccess(path);
+			FramsClass framsClass = access.getFramsClass();
+			assert framsClass != null;
+			for (CompositeParam p : filterInstanceof(access.getParams(), CompositeParam.class)) {
+				Object child = access.get(p, Object.class);
+				final Path childPath = path.appendNode(new Node(p, child));
+				if (childPath.isResolved() && instance.getInfoFromCache(childPath) != null) {
+					++dispatched;
+					instance.invokeLater(new Runnable() {
+						@Override
+						public void run() {
+							fetch(childPath);
+						}
+					});
+					continue;
+				}
+				++dispatched;
+				instance.resolve(childPath, new Future<Path>() {
+					@Override
+					public void result(Path result, Exception e) {
+						assert instance.isActive();
+						if (e != null) {
+							log.error(e);
+							return;
+						}
+						fetch(result);
+					}
+				});
+			}
+		}
+		--dispatched;
+		if (dispatched == 0) {
+			finished();
+		}
+	}
 
-    protected void fetch(final Path path) {
-        instance.fetchValues(path, new StateFunctor() {
-            @Override
-            public void call(Exception e) {
-                if (e != null) {
-                    LOGGER.error("failed to fetch values for " + path + ": " + e);
-                    process(null);
-                    return;
-                }
-                process(path);
-            }
-        });
-    }
+	protected void fetch(final Path path) {
+		instance.fetchValues(path, new StateFunctor() {
+			@Override
+			public void call(Exception e) {
+				if (e != null) {
+					log.error("failed to fetch values for " + path + ": " + e);
+					process(null);
+					return;
+				}
+				process(path);
+			}
+		});
+	}
 
 }
Index: java/main/src/main/java/com/framsticks/remote/RemoteInstance.java
===================================================================
--- java/main/src/main/java/com/framsticks/remote/RemoteInstance.java	(revision 79)
+++ java/main/src/main/java/com/framsticks/remote/RemoteInstance.java	(revision 84)
@@ -7,12 +7,16 @@
 import com.framsticks.communication.util.LoggingSubscriptionCallback;
 import com.framsticks.core.ListChange;
-import com.framsticks.core.Parameters;
 import com.framsticks.core.Path;
 import com.framsticks.params.*;
-import com.framsticks.params.types.CompositeParam;
 import com.framsticks.params.types.EventParam;
 import com.framsticks.parsers.MultiParamLoader;
 import com.framsticks.core.Instance;
 import com.framsticks.util.*;
+import com.framsticks.util.dispatching.Dispatching;
+import com.framsticks.util.dispatching.Future;
+import com.framsticks.util.lang.Casting;
+import com.framsticks.util.lang.Pair;
+
+import org.apache.commons.configuration.Configuration;
 import org.apache.log4j.Logger;
 
@@ -24,83 +28,83 @@
 public class RemoteInstance extends Instance {
 
-	private final static Logger LOGGER = Logger.getLogger(RemoteInstance.class.getName());
-
-    protected Path simulator;
-    protected final ClientConnection connection;
-
-    protected final Set<Pair<Path, Subscription>> subscriptions = new HashSet<Pair<Path, Subscription>>();
-
-    public Pair<Path, Subscription> getSubscription(Path path) {
-        for (Pair<Path, Subscription> s : subscriptions) {
-            if (s.first.matches(path)) {
-                return s;
-            }
-        }
-        return null;
-    }
-
-    @Override
-    public void run() {
-        assert isActive();
-        super.run();
-        connection.connect(new StateFunctor() {
+	private final static Logger log = Logger.getLogger(RemoteInstance.class.getName());
+
+	protected Path simulator;
+	protected ClientConnection connection;
+
+	protected final Set<Pair<Path, Subscription>> subscriptions = new HashSet<Pair<Path, Subscription>>();
+
+	public Pair<Path, Subscription> getSubscription(Path path) {
+		for (Pair<Path, Subscription> s : subscriptions) {
+			if (s.first.matches(path)) {
+				return s;
+			}
+		}
+		return null;
+	}
+
+	@Override
+	public void run() {
+		assert isActive();
+		super.run();
+		connection.connect(new StateFunctor() {
 			@Override
 			public void call(Exception e) {
-                if (e != null) {
-                    fireRun(e);
-                    return;
-                }
+				if (e != null) {
+					fireRun(e);
+					return;
+				}
 				connection.negotiateProtocolVersion(new StateFunctor() {
 					@Override
 					public void call(Exception e) {
 						if (e != null) {
-							LOGGER.fatal("unsupported protocol version!\n minimal version is: "
+							log.fatal("unsupported protocol version!\n minimal version is: "
 									+ "nmanager protocol is: "
 									+ connection.getProtocolVersion());
 							connection.close();
-                            fireRun(e);
+							fireRun(e);
 							return;
 						}
 
-                        invokeLater(new Runnable() {
-                            @Override
-                            public void run() {
-                                resolveAndFetch("/simulator", new Future<Path>() {
-                                    @Override
-                                    public void result(Path path, Exception e) {
-                                        if (e != null) {
-                                            LOGGER.fatal("failed to resolve simulator node");
-                                            fireRun(e);
-                                            return;
-                                        }
-                                        assert isActive();
-                                        simulator = path;
-                                        fireRun(null);
-                                        LOGGER.info("resolved simulator node");
-
-                                        EventParam param = getParam(simulator, "running_changed", EventParam.class);
-                                        assert param != null;
-                                        connection.subscribe(simulator.getTextual() + "/" + param.getId(), new LoggingSubscriptionCallback(LOGGER, "server running state change", new EventCallback() {
-                                            @Override
-                                            public void call(List<File> files) {
-                                                invokeLater(new Runnable() {
-                                                    @Override
-                                                    public void run() {
-                                                        updateSimulationRunning();
-                                                    }
-                                                });
-                                            }
-                                        }));
-                                        new PeriodicTask(RemoteInstance.this, 1000) {
-                                            @Override
-                                            public void run() {
-                                                updateSimulationRunning();
-                                                again();
-                                            }
-                                        };
-                                    }
-                                });
-                            }
-                        });
+						invokeLater(new Runnable() {
+							@Override
+							public void run() {
+								resolveAndFetch("/simulator", new Future<Path>() {
+									@Override
+									public void result(Path path, Exception e) {
+										if (e != null) {
+											log.fatal("failed to resolve simulator node");
+											fireRun(e);
+											return;
+										}
+										assert isActive();
+										simulator = path;
+										fireRun(null);
+										log.info("resolved simulator node");
+
+										EventParam param = getParam(simulator, "running_changed", EventParam.class);
+										assert param != null;
+										connection.subscribe(simulator.getTextual() + "/" + param.getId(), new LoggingSubscriptionCallback(log, "server running state change", new EventCallback() {
+											@Override
+											public void call(List<File> files) {
+												invokeLater(new Runnable() {
+													@Override
+													public void run() {
+														updateSimulationRunning();
+													}
+												});
+											}
+										}));
+										new PeriodicTask(RemoteInstance.this, 1000) {
+											@Override
+											public void run() {
+												updateSimulationRunning();
+												again();
+											}
+										};
+									}
+								});
+							}
+						});
 					}
 				});
@@ -109,18 +113,28 @@
 	}
 
-	public RemoteInstance(Parameters parameters) {
-        super(parameters);
-        connection = new ClientConnection(config.getString("address"));
-    }
+	public RemoteInstance() {
+	}
+
+
+	@Override
+	public void configure(Configuration config) {
+		super.configure(config);
+		connection = new ClientConnection(config.getString("address"));
+	}
+
+
+	public void setConnection(ClientConnection connection) {
+		this.connection = connection;
+	}
 
 	@Override
 	public String toString() {
-        assert Dispatching.isThreadSafe();
+		assert Dispatching.isThreadSafe();
 		return getConnection().getAddress();
 	}
 
 	public void setRunning(final boolean running) {
-        assert isActive();
-        //simulator.call(simulator.getParam(running ? "start" : "stop", ProcedureParam.class), new LoggingStateCallback(LOGGER, (running ? "starting" : "stopping") + " server"));
+		assert isActive();
+		//simulator.call(simulator.getParam(running ? "start" : "stop", ProcedureParam.class), new LoggingStateCallback(log, (running ? "starting" : "stopping") + " server"));
 	}
 
@@ -128,256 +142,256 @@
 
 	protected void updateSimulationRunning() {
-        assert isActive();
-        /*
-        fetchValue(simulator, getParam(simulator, "running", Param.class), new StateFunctor() {
-            @Override
-            public void call(Exception e) {
-                if (e != null) {
-                    LOGGER.fatal("failed to query simulator running status: " + e);
-                    return;
-                }
-
-                invokeLater(new Runnable() {
-                    @Override
-                    public void run() {
-                        boolean value = bindAccess(simulator).get("running", Boolean.class);
-                        LOGGER.trace("server running: " + value);
-                        simulationRunningListeners.call(value);
-                    }
-                });
-
-            }
-        });
-        */
+		assert isActive();
+		/*
+		fetchValue(simulator, getParam(simulator, "running", Param.class), new StateFunctor() {
+			@Override
+			public void call(Exception e) {
+				if (e != null) {
+					log.fatal("failed to query simulator running status: " + e);
+					return;
+				}
+
+				invokeLater(new Runnable() {
+					@Override
+					public void run() {
+						boolean value = bindAccess(simulator).get("running", Boolean.class);
+						log.trace("server running: " + value);
+						simulationRunningListeners.call(value);
+					}
+				});
+
+			}
+		});
+		*/
 	}
 
 	public void addRunningStateListener(UnaryFunctor<Boolean, Boolean> listener) {
-        assert isActive();
-        simulationRunningListeners.add(listener);
+		assert isActive();
+		simulationRunningListeners.add(listener);
 	}
 
 	public void disconnect() {
-        assert isActive();
-        if (connection.isConnected()) {
+		assert isActive();
+		if (connection.isConnected()) {
 			connection.close();
 		}
 	}
 
-    public final ClientConnection getConnection() {
-        return connection;
-    }
-
-    @Override
-    public void fetchValue(final Path path, final Param param, final StateFunctor stateFunctor) {
-        assert isActive();
-        assert param != null;
-        assert path.isResolved();
-        connection.send(new GetRequest().setField(param.getId()).setPath(path.getTextual()), this, new ResponseCallback() {
-            @Override
-            public void process(Response response) {
-                assert isActive();
-                if (!response.getOk()) {
-                    stateFunctor.call(new Exception(response.getComment()));
-                    return;
-                }
-                try {
-                    processFetchedValues(path, response.getFiles());
-                    stateFunctor.call(null);
-                } catch (Exception ex) {
-                    stateFunctor.call(ex);
-                }
-            }
-        });
-    }
-
-    protected final Map<String, Set<Future<FramsClass>>> infoRequests = new HashMap<String, Set<Future<FramsClass>>>();
-
-    protected void finishInfoRequest(String id, FramsClass result, Exception e) {
-        assert isActive();
-        Set<Future<FramsClass>> futures = infoRequests.get(id);
-        infoRequests.remove(id);
-        for (Future<FramsClass> f : futures) {
-            f.result(result, e);
-        }
-    }
-
-    @Override
-    protected void fetchInfo(final Path path, final Future<FramsClass> future) {
-
-        final String name = path.getTop().getParam().getContainedTypeName();
-
-        if (infoRequests.containsKey(name)) {
-            infoRequests.get(name).add(future);
-            return;
-        }
-
-        LOGGER.debug("issuing info request for " + name);
-        Set<Future<FramsClass>> futures = new HashSet<Future<FramsClass>>();
-        futures.add(future);
-        infoRequests.put(name, futures);
-
-        //TODO: if the info is in the cache, then don't communicate
-        connection.send(new InfoRequest().setPath(path.getTextual()), this, new ResponseCallback() {
-            @Override
-            public void process(Response response) {
-                assert isActive();
-                if (!response.getOk()) {
-                    finishInfoRequest(name, null, new Exception(response.getComment()));
-                    return;
-                }
-
-                assert response.getFiles().size() == 1;
-                assert path.isTheSame(response.getFiles().get(0).getPath());
-                FramsClass framsClass = processFetchedInfo(response.getFiles().get(0));
-
-                if (framsClass == null) {
-                    LOGGER.fatal("could not read class info");
-                    finishInfoRequest(name, null, new Exception("could not read class info"));
-                    return;
-                }
-                CompositeParam thisParam = path.getTop().getParam();
-                if (!thisParam.isMatchingContainedName(framsClass.getId())) {
-                    String mismatch = "class name mismatch: param=" + thisParam.getContainedTypeName() + " differs from fetched=" + framsClass.getId();
-                    LOGGER.error(mismatch);
-                    finishInfoRequest(name, null, new Exception(mismatch));
-                    return;
-                }
-                finishInfoRequest(name, framsClass, null);
-            }
-        });
-    }
-
-    @Override
-    public void fetchValues(final Path path, final StateFunctor stateFunctor) {
-        assert isActive();
-        assert path.getTop().getObject() != null;
-
-        LOGGER.trace("fetching values for " + path);
-        connection.send(new GetRequest().setPath(path.getTextual()), this, new ResponseCallback() {
-            @Override
-            public void process(Response response) {
-                assert isActive();
-                if (!response.getOk()) {
-                    stateFunctor.call(new Exception(response.getComment()));
-                    return;
-                }
-                try {
-                    processFetchedValues(path, response.getFiles());
-                    stateFunctor.call(null);
-                } catch (Exception ex) {
-                    LOGGER.error("an exception occurred while loading: " + ex);
-                    ex.printStackTrace();
-                    stateFunctor.call(ex);
-                }
-            }
-        });
-    }
-
-    @Override
-    public void resolve(final Path path, final Future<Path> future) {
-        assert isActive();
-        if (path.getTop().getObject() != null) {
-            if (getInfoFromCache(path) != null) {
-                future.result(path, null);
-                return;
-            }
-            findInfo(path, new Future<FramsClass>() {
-                @Override
-                public void result(FramsClass result, Exception e) {
-                    if (e != null) {
-                        future.result(null, e);
-                        return;
-                    }
-                    future.result(path, null);
-                }
-            });
-            return;
-        }
-        findInfo(path, new Future<FramsClass>() {
-            @Override
-            public void result(FramsClass result, Exception e) {
-                assert isActive();
-                if (e != null) {
-                    future.result(null, e);
-                    return;
-                }
-                assert path.getTop().getParam().isMatchingContainedName(result.getId());
-                Path p = (path.getTop().getParam().getContainedTypeName() != null ? path : new Path(path.getInstance(), path.getTextual()));
-                future.result(create(p), null);
-            }
-        });
-    }
-
-    @Override
-    protected void tryRegisterOnChangeEvents(final Path path) {
-        assert isActive();
-        AccessInterface access = bindAccess(path);
-        if (!(access instanceof ListAccess)) {
-            return;
-        }
-
-
-        assert path.size() >= 2;
-        FramsClass underFramsClass = getInfoFromCache(path.getUnder().getParam().getContainedTypeName());
-
-        EventParam changedEvent = Casting.tryCast(EventParam.class, underFramsClass.getParamEntry(path.getTop().getParam().getId() + "_changed"));
-        if (changedEvent == null) {
-            return;
-        }
-
-        if (getSubscription(path) != null) {
-            return;
-        }
-
-        final Pair<Path, Subscription> temporary = new Pair<Path, Subscription>(path, null);
-        subscriptions.add(temporary);
-
-        connection.subscribe(path.getTextual() + "_changed", new SubscriptionCallback() {
-            @Override
-            public EventCallback subscribed(final Subscription subscription) {
-                if (subscription == null) {
-                    LOGGER.error("failed to subscribe for change event for " + path);
-                    return null;
-                }
-                LOGGER.debug("subscribed for change event for " + path);
-                subscription.setDispatcher(RemoteInstance.this);
-                RemoteInstance.this.invokeLater(new Runnable() {
-                    @Override
-                    public void run() {
-                        subscriptions.remove(temporary);
-                        subscriptions.add(new Pair<Path, Subscription>(path, subscription));
-                    }
-                });
-                return new EventCallback() {
-                    @Override
-                    public void call(List<File> files) {
-                        assert isActive();
-                        assert files.size() == 1;
-                        MultiParamLoader loader = new MultiParamLoader();
-                        loader.setNewSource(files.get(0).getContent());
-                        loader.addBreakCondition(MultiParamLoader.Status.AfterObject);
-                        ReflectionAccess access = new ReflectionAccess(ListChange.class, ListChange.getFramsClass());
-                        loader.addAccessInterface(access);
-                        MultiParamLoader.Status status;
-                        try {
-                            while ((status = loader.go()) != MultiParamLoader.Status.Finished) {
-                                if (status == MultiParamLoader.Status.AfterObject) {
-                                    AccessInterface accessInterface = loader.getLastAccessInterface();
-                                    reactToChange(path, (ListChange) accessInterface.getSelected());
-                                }
-                            }
-                        } catch (Exception e) {
-                            e.printStackTrace();
-                        }
-                    }
-                };
-            }
-        });
-    }
-
-
-    protected void reactToChange(final Path path, final ListChange listChange) {
-        assert isActive();
-        LOGGER.debug("reacting to change " + listChange + " in " + path);
+	public final ClientConnection getConnection() {
+		return connection;
+	}
+
+	@Override
+	public void fetchValue(final Path path, final Param param, final StateFunctor stateFunctor) {
+		assert isActive();
+		assert param != null;
+		assert path.isResolved();
+		connection.send(new GetRequest().setField(param.getId()).setPath(path.getTextual()), this, new ResponseCallback() {
+			@Override
+			public void process(Response response) {
+				assert isActive();
+				if (!response.getOk()) {
+					stateFunctor.call(new Exception(response.getComment()));
+					return;
+				}
+				try {
+					processFetchedValues(path, response.getFiles());
+					stateFunctor.call(null);
+				} catch (Exception ex) {
+					stateFunctor.call(ex);
+				}
+			}
+		});
+	}
+
+	protected final Map<String, Set<Future<FramsClass>>> infoRequests = new HashMap<String, Set<Future<FramsClass>>>();
+
+	protected void finishInfoRequest(String id, FramsClass result, Exception e) {
+		assert isActive();
+		Set<Future<FramsClass>> futures = infoRequests.get(id);
+		infoRequests.remove(id);
+		for (Future<FramsClass> f : futures) {
+			f.result(result, e);
+		}
+	}
+
+	@Override
+	protected void fetchInfo(final Path path, final Future<FramsClass> future) {
+
+		final String name = path.getTop().getParam().getContainedTypeName();
+
+		if (infoRequests.containsKey(name)) {
+			infoRequests.get(name).add(future);
+			return;
+		}
+
+		log.debug("issuing info request for " + name);
+		Set<Future<FramsClass>> futures = new HashSet<Future<FramsClass>>();
+		futures.add(future);
+		infoRequests.put(name, futures);
+
+		//TODO: if the info is in the cache, then don't communicate
+		connection.send(new InfoRequest().setPath(path.getTextual()), this, new ResponseCallback() {
+			@Override
+			public void process(Response response) {
+				assert isActive();
+				if (!response.getOk()) {
+					finishInfoRequest(name, null, new Exception(response.getComment()));
+					return;
+				}
+
+				assert response.getFiles().size() == 1;
+				assert path.isTheSame(response.getFiles().get(0).getPath());
+				FramsClass framsClass = processFetchedInfo(response.getFiles().get(0));
+
+				if (framsClass == null) {
+					log.fatal("could not read class info");
+					finishInfoRequest(name, null, new Exception("could not read class info"));
+					return;
+				}
+				CompositeParam thisParam = path.getTop().getParam();
+				if (!thisParam.isMatchingContainedName(framsClass.getId())) {
+					String mismatch = "class name mismatch: param=" + thisParam.getContainedTypeName() + " differs from fetched=" + framsClass.getId();
+					log.error(mismatch);
+					finishInfoRequest(name, null, new Exception(mismatch));
+					return;
+				}
+				finishInfoRequest(name, framsClass, null);
+			}
+		});
+	}
+
+	@Override
+	public void fetchValues(final Path path, final StateFunctor stateFunctor) {
+		assert isActive();
+		assert path.getTop().getObject() != null;
+
+		log.trace("fetching values for " + path);
+		connection.send(new GetRequest().setPath(path.getTextual()), this, new ResponseCallback() {
+			@Override
+			public void process(Response response) {
+				assert isActive();
+				if (!response.getOk()) {
+					stateFunctor.call(new Exception(response.getComment()));
+					return;
+				}
+				try {
+					processFetchedValues(path, response.getFiles());
+					stateFunctor.call(null);
+				} catch (Exception ex) {
+					log.error("an exception occurred while loading: " + ex);
+					ex.printStackTrace();
+					stateFunctor.call(ex);
+				}
+			}
+		});
+	}
+
+	@Override
+	public void resolve(final Path path, final Future<Path> future) {
+		assert isActive();
+		if (path.getTop().getObject() != null) {
+			if (getInfoFromCache(path) != null) {
+				future.result(path, null);
+				return;
+			}
+			findInfo(path, new Future<FramsClass>() {
+				@Override
+				public void result(FramsClass result, Exception e) {
+					if (e != null) {
+						future.result(null, e);
+						return;
+					}
+					future.result(path, null);
+				}
+			});
+			return;
+		}
+		findInfo(path, new Future<FramsClass>() {
+			@Override
+			public void result(FramsClass result, Exception e) {
+				assert isActive();
+				if (e != null) {
+					future.result(null, e);
+					return;
+				}
+				assert path.getTop().getParam().isMatchingContainedName(result.getId());
+				Path p = (path.getTop().getParam().getContainedTypeName() != null ? path : path.tryFindResolution());
+				future.result(createIfNeeded(p), null);
+			}
+		});
+	}
+
+	@Override
+	protected void tryRegisterOnChangeEvents(final Path path) {
+		assert isActive();
+		AccessInterface access = bindAccess(path);
+		if (!(access instanceof ListAccess)) {
+			return;
+		}
+
+
+		assert path.size() >= 2;
+		FramsClass underFramsClass = getInfoFromCache(path.getUnder().getParam().getContainedTypeName());
+
+		EventParam changedEvent = underFramsClass.getParamEntry(path.getTop().getParam().getId() + "_changed", EventParam.class);
+		if (changedEvent == null) {
+			return;
+		}
+
+		if (getSubscription(path) != null) {
+			return;
+		}
+
+		final Pair<Path, Subscription> temporary = new Pair<Path, Subscription>(path, null);
+		subscriptions.add(temporary);
+
+		connection.subscribe(path.getTextual() + "_changed", new SubscriptionCallback() {
+			@Override
+			public EventCallback subscribed(final Subscription subscription) {
+				if (subscription == null) {
+					log.error("failed to subscribe for change event for " + path);
+					return null;
+				}
+				log.debug("subscribed for change event for " + path);
+				subscription.setDispatcher(RemoteInstance.this);
+				RemoteInstance.this.invokeLater(new Runnable() {
+					@Override
+					public void run() {
+						subscriptions.remove(temporary);
+						subscriptions.add(new Pair<Path, Subscription>(path, subscription));
+					}
+				});
+				return new EventCallback() {
+					@Override
+					public void call(List<File> files) {
+						assert isActive();
+						assert files.size() == 1;
+						MultiParamLoader loader = new MultiParamLoader();
+						loader.setNewSource(files.get(0).getContent());
+						loader.addBreakCondition(MultiParamLoader.Status.AfterObject);
+						ReflectionAccess access = new ReflectionAccess(ListChange.class, ListChange.getFramsClass());
+						loader.addAccessInterface(access);
+						MultiParamLoader.Status status;
+						try {
+							while ((status = loader.go()) != MultiParamLoader.Status.Finished) {
+								if (status == MultiParamLoader.Status.AfterObject) {
+									AccessInterface accessInterface = loader.getLastAccessInterface();
+									reactToChange(path, (ListChange) accessInterface.getSelected());
+								}
+							}
+						} catch (Exception e) {
+							e.printStackTrace();
+						}
+					}
+				};
+			}
+		});
+	}
+
+
+	protected void reactToChange(final Path path, final ListChange listChange) {
+		assert isActive();
+		log.debug("reacting to change " + listChange + " in " + path);
 		AccessInterface access = bindAccess(path);
 		assert access != null;
@@ -389,5 +403,5 @@
 				public void result(Path result, Exception e) {
 					if (e != null) {
-						LOGGER.error("failed to modify " + p + ": " + e);
+						log.error("failed to modify " + p + ": " + e);
 						return;
 					}
@@ -399,54 +413,55 @@
 
 
-        CompositeParam childParam = Casting.tryCast(CompositeParam.class, access.getParam(listChange.getBestIdentifier()));
-        assert childParam != null;
-        switch (listChange.getAction()) {
-            case Add: {
-                final String p = path.getTextual() + "/" + childParam.getId();
-                resolveAndFetch(p, new Future<Path>() {
-                    @Override
-                    public void result(Path result, Exception e) {
-                        if (e != null) {
-                            LOGGER.error("failed to add " + p + ": " + e);
-                            return;
-                        }
-                        LOGGER.debug("added: " + result);
-                        fireListChange(path, listChange);
-                    }
-                });
-                break;
-            }
-            case Remove: {
-                access.set(childParam, null);
-                fireListChange(path, listChange);
-                break;
-            }
-            case Modify: {
-                final String p = path.getTextual() + "/" + childParam.getId();
-                resolveAndFetch(p, new Future<Path>() {
-                    @Override
-                    public void result(Path result, Exception e) {
-                        if (e != null) {
-                            LOGGER.error("failed to modify " + p + ": " + e);
-                            return;
-                        }
-                        fireListChange(path, listChange);
-                    }
-                });
-                break;
-            }
-        }
-    }
-
+		CompositeParam childParam = Casting.tryCast(CompositeParam.class, access.getParam(listChange.getBestIdentifier()));
+		assert childParam != null;
+		switch (listChange.getAction()) {
+			case Add: {
+				final String p = path.getTextual() + "/" + childParam.getId();
+				resolveAndFetch(p, new Future<Path>() {
+					@Override
+					public void result(Path result, Exception e) {
+						if (e != null) {
+							log.error("failed to add " + p + ": " + e);
+							return;
+						}
+						log.debug("added: " + result);
+						fireListChange(path, listChange);
+					}
+				});
+				break;
+			}
+			case Remove: {
+				access.set(childParam, null);
+				fireListChange(path, listChange);
+				break;
+			}
+			case Modify: {
+				final String p = path.getTextual() + "/" + childParam.getId();
+				resolveAndFetch(p, new Future<Path>() {
+					@Override
+					public void result(Path result, Exception e) {
+						if (e != null) {
+							log.error("failed to modify " + p + ": " + e);
+							return;
+						}
+						fireListChange(path, listChange);
+					}
+				});
+				break;
+			}
+		}
+	}
+
+	//TODO ValueParam
 	@Override
 	public void storeValue(final Path path, final Param param, final Object value, final StateFunctor stateFunctor) {
 		assert isActive();
 
-		LOGGER.trace("storing value " + param + " for " + path);
+		log.trace("storing value " + param + " for " + path);
 		connection.send(new SetRequest().value(value.toString()).setField(param.getId()).setPath(path.getTextual()), this, new StateCallback() {
 			@Override
 			public void call(Exception e) {
 				if (e == null) {
-					bindAccess(path).set(param, value);
+					bindAccess(path).set((ValueParam) param, value);
 				}
 				stateFunctor.call(e);
Index: java/main/src/main/java/com/framsticks/util/AtOnceDispatcher.java
===================================================================
--- java/main/src/main/java/com/framsticks/util/AtOnceDispatcher.java	(revision 79)
+++ 	(revision )
@@ -1,19 +1,0 @@
-package com.framsticks.util;
-
-/**
- * @author Piotr Sniegowski
- */
-public class AtOnceDispatcher implements Dispatcher {
-
-    public static final AtOnceDispatcher instance = new AtOnceDispatcher();
-
-    @Override
-    public final boolean isActive() {
-        return true;
-    }
-
-    @Override
-    public final void invokeLater(Runnable runnable) {
-        runnable.run();
-    }
-}
Index: java/main/src/main/java/com/framsticks/util/Casting.java
===================================================================
--- java/main/src/main/java/com/framsticks/util/Casting.java	(revision 79)
+++ 	(revision )
@@ -1,34 +1,0 @@
-package com.framsticks.util;
-
-import com.framsticks.core.Entity;
-import com.framsticks.core.Instance;
-import org.apache.commons.configuration.HierarchicalConfiguration;
-
-/**
- * @author Piotr Sniegowski
- */
-public abstract class Casting {
-    public static <T> T tryCast(Class<T> class_, Object object) {
-        try {
-            return class_.cast(object);
-        } catch (ClassCastException ignored) {
-            return null;
-        }
-    }
-
-    public static <T> T assertCast(Class<T> class_, Object object) {
-        try {
-            return class_.cast(object);
-        } catch (ClassCastException ignored) {
-            assert false;
-            return null;
-        }
-    }
-
-    public static <T> T throwCast(Class<T> class_, Object object) {
-        if (object == null) {
-            throw new NullPointerException();
-        }
-        return class_.cast(object);
-    }
-}
Index: java/main/src/main/java/com/framsticks/util/Containers.java
===================================================================
--- java/main/src/main/java/com/framsticks/util/Containers.java	(revision 79)
+++ 	(revision )
@@ -1,17 +1,0 @@
-package com.framsticks.util;
-
-import java.util.List;
-
-/**
- * @author Piotr Sniegowski
- */
-public abstract class Containers {
-    public static void resizeList(List list, int size) {
-        while (list.size() < size) {
-            list.add(null);
-        }
-        while (list.size() > size) {
-            list.remove(list.size() - 1);
-        }
-    }
-}
Index: java/main/src/main/java/com/framsticks/util/Dispatcher.java
===================================================================
--- java/main/src/main/java/com/framsticks/util/Dispatcher.java	(revision 79)
+++ 	(revision )
@@ -1,9 +1,0 @@
-package com.framsticks.util;
-
-/**
- * @author Piotr Sniegowski
- */
-public interface Dispatcher {
-    public boolean isActive();
-    public void invokeLater(Runnable runnable);
-}
Index: java/main/src/main/java/com/framsticks/util/Dispatching.java
===================================================================
--- java/main/src/main/java/com/framsticks/util/Dispatching.java	(revision 79)
+++ 	(revision )
@@ -1,43 +1,0 @@
-package com.framsticks.util;
-
-/**
- * @author Piotr Sniegowski
- */
-public abstract class Dispatching {
-
-    public static boolean isThreadSafe() {
-        return true;
-    }
-
-    public static void invokeLaterOrNow(Dispatcher dispatcher, Runnable runnable) {
-        if (dispatcher.isActive()) {
-            runnable.run();
-            return;
-        }
-        dispatcher.invokeLater(runnable);
-    }
-
-    public static void dispatchOk(Dispatcher dispatcher, final StateFunctor stateFunctor) {
-        dispatcher.invokeLater(new Runnable() {
-            @Override
-            public void run() {
-                stateFunctor.call(null);
-            }
-        });
-    }
-
-    public static boolean assertInvokeLater(Dispatcher dispatcher, Runnable runnable) {
-        dispatcher.invokeLater(runnable);
-        return true;
-    }
-
-    public static void invokeDispatch(Dispatcher dispatcher, final Dispatcher finalDispatcher, final Runnable runnable) {
-        dispatcher.invokeLater(new Runnable() {
-            @Override
-            public void run() {
-                finalDispatcher.invokeLater(runnable);
-            }
-        });
-    }
-
-}
Index: java/main/src/main/java/com/framsticks/util/Exceptions.java
===================================================================
--- java/main/src/main/java/com/framsticks/util/Exceptions.java	(revision 79)
+++ 	(revision )
@@ -1,15 +1,0 @@
-package com.framsticks.util;
-
-import java.io.PrintWriter;
-import java.io.StringWriter;
-
-/**
- * Author: Piotr Śniegowski
- */
-public class Exceptions {
-	public static String printStackTrace(Throwable throwable) {
-		StringWriter w = new StringWriter();
-		throwable.printStackTrace(new PrintWriter(w));
-		return w.getBuffer().toString();
-	}
-}
Index: java/main/src/main/java/com/framsticks/util/Future.java
===================================================================
--- java/main/src/main/java/com/framsticks/util/Future.java	(revision 79)
+++ 	(revision )
@@ -1,8 +1,0 @@
-package com.framsticks.util;
-
-/**
- * @author Piotr Sniegowski
- */
-public interface Future <T> {
-    void result(T result, Exception e);
-}
Index: java/main/src/main/java/com/framsticks/util/Iterators.java
===================================================================
--- java/main/src/main/java/com/framsticks/util/Iterators.java	(revision 79)
+++ 	(revision )
@@ -1,22 +1,0 @@
-package com.framsticks.util;
-
-import java.util.Iterator;
-
-/**
- * @author Piotr Sniegowski
- */
-public class Iterators {
-	public static String resolve(Iterator iterator, String separator) {
-		StringBuilder b = new StringBuilder();
-		boolean following = false;
-		while (iterator.hasNext()) {
-			if (following) {
-				b.append(separator);
-			} else {
-				following = true;
-			}
-			b.append(iterator.next());
-		}
-		return b.toString();
-	}
-}
Index: java/main/src/main/java/com/framsticks/util/Layout.java
===================================================================
--- java/main/src/main/java/com/framsticks/util/Layout.java	(revision 79)
+++ 	(revision )
@@ -1,23 +1,0 @@
-package com.framsticks.util;
-
-
-import javax.swing.*;
-import java.awt.*;
-
-/**
- * @author Piotr Sniegowski
- */
-public class Layout {
-	public static void fixComponentSize(JComponent component, Dimension dimension) {
-		component.setPreferredSize(dimension);
-		component.setMaximumSize(dimension);
-		component.setMaximumSize(dimension);
-	}
-
-	public static void copyComponentDimensions(JComponent destination, JComponent source) {
-		destination.setPreferredSize(source.getPreferredSize());
-		destination.setMaximumSize(source.getMaximumSize());
-		destination.setMinimumSize(source.getMinimumSize());
-	}
-
-}
Index: java/main/src/main/java/com/framsticks/util/Misc.java
===================================================================
--- java/main/src/main/java/com/framsticks/util/Misc.java	(revision 84)
+++ java/main/src/main/java/com/framsticks/util/Misc.java	(revision 84)
@@ -0,0 +1,13 @@
+package com.framsticks.util;
+
+/**
+ * Author: Piotr Śniegowski
+ */
+public class Misc {
+	public static boolean equals(Object a, Object b) {
+		if (a != null) {
+			return (b != null && a.equals(b));
+		}
+		return b == null;
+	}
+}
Index: java/main/src/main/java/com/framsticks/util/Numbers.java
===================================================================
--- java/main/src/main/java/com/framsticks/util/Numbers.java	(revision 79)
+++ 	(revision )
@@ -1,44 +1,0 @@
-package com.framsticks.util;
-
-import java.lang.reflect.InvocationTargetException;
-
-/**
- * @author Piotr Sniegowski
- */
-public abstract class Numbers {
-	public static <T extends Number> T parse(String value, Class<T> type) {
-		if (!Strings.notEmpty(value)) {
-			return null;
-		}
-		try {
-			return (T)type.getMethod("valueOf", String.class).invoke(null, value);
-		} catch (IllegalAccessException e) {
-			e.printStackTrace();
-		} catch (InvocationTargetException e) {
-            if (e.getTargetException() instanceof NumberFormatException) {
-                return null;
-            }
-			e.printStackTrace();
-		} catch (NoSuchMethodException e) {
-			e.printStackTrace();
-		} catch (NumberFormatException ignored) {
-			return null;
-		}
-		return null;
-	}
-
-
-	public static <T extends Number> T cast(Object value, Class<T> type) {
-		if (value == null) {
-			return null;
-		}
-		if (value instanceof String) {
-			return parse((String)value, type);
-		}
-		if (value.getClass() == type) {
-			return type.cast(value);
-		}
-		return null;
-	}
-
-}
Index: java/main/src/main/java/com/framsticks/util/Orientation.java
===================================================================
--- java/main/src/main/java/com/framsticks/util/Orientation.java	(revision 79)
+++ 	(revision )
@@ -1,79 +1,0 @@
-package com.framsticks.util;
-
-/**
- * @author Piotr Sniegowski
- */
-public class Orientation {
-    public final Point3d x;
-    public final Point3d y;
-    public final Point3d z;
-
-	public Orientation(Point3d x, Point3d y, Point3d z) {
-		this.x = x;
-		this.y = y;
-		this.z = z;
-	}
-
-	public Orientation() {
-		x = new Point3d(1, 0, 0);
-		y = new Point3d(0, 1, 0);
-		z = new Point3d(0, 0, 1);
-	}
-
-	/** based on c++ void Orient::transform(Pt3D& target,const Pt3D &s) const */
-	public Point3d transform(Point3d source) {
-		Point3d.Builder b = new Point3d.Builder();
-		for (int i = 0; i < 3; ++i) {
-			double v = 0;
-			for (int j = 0; j < 3; ++j) {
-				v += source.get(j) * this.get(j).get(i);
-			}
-			b.set(i, v);
-		}
-		return b.build();
-	}
-
-	/** based on c++ void Orient::transform(Orient& target,const Orient& src) const */
-	public Orientation transform(Orientation source) {
-		return new Orientation(transform(source.x), transform(source.y), transform(source.z));
-	}
-
-	protected static Point3d rotate2D(double sin, double cos, Point3d p, int a0, int a1, int im) {
-		Point3d.Builder b = new Point3d.Builder();
-		b.set(a0, cos * p.get(a0) - sin * p.get(a1));
-		b.set(a1, sin * p.get(a0) + cos * p.get(a1));
-		b.set(im, p.get(im));
-		return b.build();
-	}
-
-	/** based on c++ Orient::rotate(const Pt3D &v) */
-	public Orientation rotate(Point3d v) {
-		Point3d[] p = new Point3d[] {x, y, z};
-
-		for (int i = 0; i < 3; ++i) {
-			double sin = Math.sin(v.get(i));
-			double cos = Math.cos(v.get(i));
-
-			for (int j = 0; j < 3; ++j) {
-				p[j] = rotate2D(sin, cos, p[j], i == 0 ? 1 : 0, i == 2 ? 1 : 2, i);
-			}
-		}
-		return new Orientation(p[0], p[1], p[2]);
-	}
-
-	final Point3d get(int i) {
-		switch (i) {
-			case 0: return x;
-			case 1: return y;
-			case 2: return z;
-		}
-		assert false;
-		return null;
-	}
-
-
-	@Override
-	public final String toString() {
-		return x + " | " + y + " | " + z;
-	}
-}
Index: java/main/src/main/java/com/framsticks/util/Pair.java
===================================================================
--- java/main/src/main/java/com/framsticks/util/Pair.java	(revision 79)
+++ 	(revision )
@@ -1,20 +1,0 @@
-package com.framsticks.util;
-
-/**
- * @author Piotr Sniegowski
- */
-public class Pair<T1, T2> {
-    public final T1 first;
-    public final T2 second;
-
-    public Pair(T1 first, T2 second) {
-        this.first = first;
-        this.second = second;
-    }
-
-    @Override
-    public String toString() {
-        return Strings.toStringNullProof(first) + " " + Strings.toStringNullProof(second);
-    }
-
-}
Index: java/main/src/main/java/com/framsticks/util/PeriodicTask.java
===================================================================
--- java/main/src/main/java/com/framsticks/util/PeriodicTask.java	(revision 79)
+++ java/main/src/main/java/com/framsticks/util/PeriodicTask.java	(revision 84)
@@ -1,3 +1,6 @@
 package com.framsticks.util;
+
+import com.framsticks.util.dispatching.Dispatcher;
+import com.framsticks.util.dispatching.Task;
 
 /**
Index: java/main/src/main/java/com/framsticks/util/Point3d.java
===================================================================
--- java/main/src/main/java/com/framsticks/util/Point3d.java	(revision 79)
+++ 	(revision )
@@ -1,67 +1,0 @@
-package com.framsticks.util;
-	
-/**
- * The simple class which represent point in 3d space.
- */
-public class Point3d
-{
-	public final double x;
-	public final double y;
-	public final double z;
-
-	public Point3d() {
-		x = 0.0;
-		y = 0.0;
-		z = 0.0;
-	}
-
-	public Point3d(double x, double y, double z) {
-		this.x = x;
-		this.y = y;
-		this.z = z;
-	}
-
-	public Point3d(Point3d p) {
-		x = p.x;
-		y = p.y;
-		z = p.z;
-	}
-
-	@Override
-	public final String toString() {
-		return x + " " + y + " " + z;
-	}
-
-	public final double get(int i) {
-		switch (i) {
-			case 0: return x;
-			case 1: return y;
-			case 2: return z;
-		}
-		assert false;
-		return 0;
-	}
-
-
-	public final Point3d add(Point3d p) {
-		return new Point3d(x + p.x, y + p.y, z + p.z);
-	}
-
-	public final Point3d sub(Point3d p) {
-		return new Point3d(x - p.x, y - p.y, z - p.z);
-	}
-
-	public final double length() {
-		return Math.sqrt(x * x + y * y + z * z);
-	}
-
-	public static class Builder {
-		double[] a = new double[3];
-
-		public Point3d build() { return new Point3d(a[0], a[1], a[2]); }
-
-		public final void set(int i, double v) {
-			a[i] = v;
-		}
-	}
-}
Index: java/main/src/main/java/com/framsticks/util/Strings.java
===================================================================
--- java/main/src/main/java/com/framsticks/util/Strings.java	(revision 79)
+++ 	(revision )
@@ -1,41 +1,0 @@
-package com.framsticks.util;
-
-/**
- * @author Piotr Sniegowski
- */
-public abstract class Strings {
-	public static String valueOf(Object o) {
-		if (o == null) {
-			return null;
-		}
-		return o.toString();
-	}
-
-	public static boolean notEmpty(String str) {
-		return str != null && !str.equals("");
-	}
-
-	public static String toStringNullProof(Object object) {
-		if (object == null) {
-			return "";
-		}
-		return object.toString();
-	}
-
-	public static String collapse(String s) {
-		if (s == null) {
-			return null;
-		}
-		s = s.trim();
-		return (s.equals("")) ? null : s;
-	}
-
-    public static Pair<String, String> splitIntoPair(String string, char separator, String second) {
-        int pos = string.indexOf(separator);
-        if (pos == -1) {
-            return new Pair<String, String>(string.substring(0, string.length() - 1), second);
-        } else {
-            return new Pair<String, String>(string.substring(0, pos), string.substring(pos + 1));
-        }
-    }
-}
Index: java/main/src/main/java/com/framsticks/util/Task.java
===================================================================
--- java/main/src/main/java/com/framsticks/util/Task.java	(revision 79)
+++ 	(revision )
@@ -1,22 +1,0 @@
-package com.framsticks.util;
-
-/**
- * @author Piotr Sniegowski
- */
-public abstract class Task implements Runnable {
-
-    protected final long moment;
-
-    public Task() {
-        moment = System.currentTimeMillis();
-    }
-
-    public Task(long moment) {
-        this.moment = moment;
-    }
-
-    public final long getMoment() {
-        return moment;
-    }
-
-}
Index: java/main/src/main/java/com/framsticks/util/Thread.java
===================================================================
--- java/main/src/main/java/com/framsticks/util/Thread.java	(revision 79)
+++ 	(revision )
@@ -1,137 +1,0 @@
-package com.framsticks.util;
-
-import org.apache.log4j.Logger;
-
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.ListIterator;
-import java.util.Queue;
-
-/**
- * @author Piotr Sniegowski
- */
-public class Thread implements Dispatcher {
-
-    private static final Logger LOGGER = Logger.getLogger(Thread.class.getName());
-
-    protected final java.lang.Thread thread;
-
-    private final LinkedList<Task> queue = new LinkedList<Task>();
-
-    public Thread() {
-        thread = new java.lang.Thread(new Runnable() {
-            @Override
-            public void run() {
-                Thread.this.routine();
-            }
-        });
-    }
-    public Thread(String s) {
-        this();
-        thread.setName(s);
-        thread.start();
-    }
-
-    public Thread(String s, java.lang.Thread thread) {
-        this.thread = thread;
-        thread.setName(s);
-    }
-
-    @Override
-    public final boolean isActive() {
-        return thread.equals(java.lang.Thread.currentThread());
-    }
-
-    protected void routine() {
-        while (!java.lang.Thread.interrupted()) {
-            Task task;
-            synchronized (queue) {
-                if (queue.isEmpty()) {
-                    try {
-                        queue.wait();
-                    } catch (InterruptedException ignored) {
-                        break;
-                    }
-                    continue;
-                }
-                task = queue.peekFirst();
-                assert task != null;
-                if (task.moment > System.currentTimeMillis()) {
-                    try {
-                        queue.wait(task.moment - System.currentTimeMillis());
-                    } catch (InterruptedException ignored) {
-                        continue;
-                    }
-                    continue;
-                }
-                queue.pollFirst();
-            }
-            try {
-                task.run();
-            } catch (Exception e) {
-                LOGGER.error("error in thread: " + e);
-                e.printStackTrace();
-            }
-        }
-    }
-
-    protected void enqueueTask(Task task) {
-        synchronized (queue) {
-            ListIterator<Task> i = queue.listIterator();
-            while (i.hasNext()) {
-                Task t = i.next();
-                if (t.getMoment() > task.getMoment()) {
-                    i.previous();
-                    i.add(task);
-                    task = null;
-                    break;
-                }
-            }
-            if (task != null) {
-                queue.add(task);
-            }
-
-            /*
-            Iterator<Task> j = queue.iterator();
-            Task prev = null;
-            while (j.hasNext()) {
-                Task next = j.next();
-                assert (prev == null) || prev.getMoment() <= next.getMoment();
-                prev = next;
-            }
-            */
-            queue.notify();
-        }
-    }
-
-    @Override
-    public void invokeLater(final Runnable runnable) {
-        if (!(runnable instanceof Task)) {
-            enqueueTask(new Task() {
-                @Override
-                public void run() {
-                    runnable.run();
-                }
-            });
-            return;
-        }
-        enqueueTask((Task)runnable);
-    }
-
-    public void interrupt() {
-        thread.interrupt();
-    }
-
-    public void join() throws InterruptedException {
-        thread.join();
-    }
-
-    public void start() {
-        thread.start();
-    }
-
-    public void setName(String name) {
-        thread.setName(name);
-
-    }
-}
Index: java/main/src/main/java/com/framsticks/util/UnsupportedOperationException.java
===================================================================
--- java/main/src/main/java/com/framsticks/util/UnsupportedOperationException.java	(revision 79)
+++ java/main/src/main/java/com/framsticks/util/UnsupportedOperationException.java	(revision 84)
@@ -6,3 +6,8 @@
 public class UnsupportedOperationException extends Exception {
 
+	/**
+	 *
+	 */
+	private static final long serialVersionUID = -8006030446614381094L;
+
 }
Index: java/main/src/main/java/com/framsticks/util/dispatching/AtOnceDispatcher.java
===================================================================
--- java/main/src/main/java/com/framsticks/util/dispatching/AtOnceDispatcher.java	(revision 84)
+++ java/main/src/main/java/com/framsticks/util/dispatching/AtOnceDispatcher.java	(revision 84)
@@ -0,0 +1,19 @@
+package com.framsticks.util.dispatching;
+
+/**
+ * @author Piotr Sniegowski
+ */
+public class AtOnceDispatcher implements Dispatcher {
+
+    public static final AtOnceDispatcher instance = new AtOnceDispatcher();
+
+    @Override
+    public final boolean isActive() {
+        return true;
+    }
+
+    @Override
+    public final void invokeLater(Runnable runnable) {
+        runnable.run();
+    }
+}
Index: java/main/src/main/java/com/framsticks/util/dispatching/Dispatcher.java
===================================================================
--- java/main/src/main/java/com/framsticks/util/dispatching/Dispatcher.java	(revision 84)
+++ java/main/src/main/java/com/framsticks/util/dispatching/Dispatcher.java	(revision 84)
@@ -0,0 +1,9 @@
+package com.framsticks.util.dispatching;
+
+/**
+ * @author Piotr Sniegowski
+ */
+public interface Dispatcher {
+    public boolean isActive();
+    public void invokeLater(Runnable runnable);
+}
Index: java/main/src/main/java/com/framsticks/util/dispatching/Dispatching.java
===================================================================
--- java/main/src/main/java/com/framsticks/util/dispatching/Dispatching.java	(revision 84)
+++ java/main/src/main/java/com/framsticks/util/dispatching/Dispatching.java	(revision 84)
@@ -0,0 +1,45 @@
+package com.framsticks.util.dispatching;
+
+import com.framsticks.util.StateFunctor;
+
+/**
+ * @author Piotr Sniegowski
+ */
+public abstract class Dispatching {
+
+    public static boolean isThreadSafe() {
+        return true;
+    }
+
+    public static void invokeLaterOrNow(Dispatcher dispatcher, Runnable runnable) {
+        if (dispatcher.isActive()) {
+            runnable.run();
+            return;
+        }
+        dispatcher.invokeLater(runnable);
+    }
+
+    public static void dispatchOk(Dispatcher dispatcher, final StateFunctor stateFunctor) {
+        dispatcher.invokeLater(new Runnable() {
+            @Override
+            public void run() {
+                stateFunctor.call(null);
+            }
+        });
+    }
+
+    public static boolean assertInvokeLater(Dispatcher dispatcher, Runnable runnable) {
+        dispatcher.invokeLater(runnable);
+        return true;
+    }
+
+    public static void invokeDispatch(Dispatcher dispatcher, final Dispatcher finalDispatcher, final Runnable runnable) {
+        dispatcher.invokeLater(new Runnable() {
+            @Override
+            public void run() {
+                finalDispatcher.invokeLater(runnable);
+            }
+        });
+    }
+
+}
Index: java/main/src/main/java/com/framsticks/util/dispatching/Future.java
===================================================================
--- java/main/src/main/java/com/framsticks/util/dispatching/Future.java	(revision 84)
+++ java/main/src/main/java/com/framsticks/util/dispatching/Future.java	(revision 84)
@@ -0,0 +1,8 @@
+package com.framsticks.util.dispatching;
+
+/**
+ * @author Piotr Sniegowski
+ */
+public interface Future <T> {
+    void result(T result, Exception e);
+}
Index: java/main/src/main/java/com/framsticks/util/dispatching/Task.java
===================================================================
--- java/main/src/main/java/com/framsticks/util/dispatching/Task.java	(revision 84)
+++ java/main/src/main/java/com/framsticks/util/dispatching/Task.java	(revision 84)
@@ -0,0 +1,22 @@
+package com.framsticks.util.dispatching;
+
+/**
+ * @author Piotr Sniegowski
+ */
+public abstract class Task implements Runnable {
+
+    protected final long moment;
+
+    public Task() {
+        moment = System.currentTimeMillis();
+    }
+
+    public Task(long moment) {
+        this.moment = moment;
+    }
+
+    public final long getMoment() {
+        return moment;
+    }
+
+}
Index: java/main/src/main/java/com/framsticks/util/dispatching/Thread.java
===================================================================
--- java/main/src/main/java/com/framsticks/util/dispatching/Thread.java	(revision 84)
+++ java/main/src/main/java/com/framsticks/util/dispatching/Thread.java	(revision 84)
@@ -0,0 +1,135 @@
+package com.framsticks.util.dispatching;
+
+import org.apache.log4j.Logger;
+
+import java.util.LinkedList;
+import java.util.ListIterator;
+
+/**
+ * @author Piotr Sniegowski
+ */
+public class Thread implements Dispatcher {
+
+	private static final Logger log = Logger.getLogger(Thread.class.getName());
+
+	protected final java.lang.Thread thread;
+
+	private final LinkedList<Task> queue = new LinkedList<Task>();
+
+	public Thread() {
+		thread = new java.lang.Thread(new Runnable() {
+			@Override
+			public void run() {
+				Thread.this.routine();
+			}
+		});
+	}
+	public Thread(String s) {
+		this();
+		thread.setName(s);
+		thread.start();
+	}
+
+	public Thread(String s, java.lang.Thread thread) {
+		this.thread = thread;
+		thread.setName(s);
+	}
+
+	@Override
+	public final boolean isActive() {
+		return thread.equals(java.lang.Thread.currentThread());
+	}
+
+	protected void routine() {
+		while (!java.lang.Thread.interrupted()) {
+			Task task;
+			synchronized (queue) {
+				if (queue.isEmpty()) {
+					try {
+						queue.wait();
+					} catch (InterruptedException ignored) {
+						break;
+					}
+					continue;
+				}
+				task = queue.peekFirst();
+				assert task != null;
+				if (task.moment > System.currentTimeMillis()) {
+					try {
+						queue.wait(task.moment - System.currentTimeMillis());
+					} catch (InterruptedException ignored) {
+						continue;
+					}
+					continue;
+				}
+				queue.pollFirst();
+			}
+			try {
+				task.run();
+			} catch (Exception e) {
+				log.error("error in thread: " + e);
+				e.printStackTrace();
+			}
+		}
+	}
+
+	protected void enqueueTask(Task task) {
+		synchronized (queue) {
+			ListIterator<Task> i = queue.listIterator();
+			while (i.hasNext()) {
+				Task t = i.next();
+				if (t.getMoment() > task.getMoment()) {
+					i.previous();
+					i.add(task);
+					task = null;
+					break;
+				}
+			}
+			if (task != null) {
+				queue.add(task);
+			}
+
+			/*
+			Iterator<Task> j = queue.iterator();
+			Task prev = null;
+			while (j.hasNext()) {
+				Task next = j.next();
+				assert (prev == null) || prev.getMoment() <= next.getMoment();
+				prev = next;
+			}
+			*/
+			queue.notify();
+		}
+	}
+
+	@Override
+	public void invokeLater(final Runnable runnable) {
+		if (!(runnable instanceof Task)) {
+			enqueueTask(new Task() {
+				@Override
+				public void run() {
+					runnable.run();
+				}
+			});
+			return;
+		}
+		enqueueTask((Task)runnable);
+	}
+
+	public void interrupt() {
+		thread.interrupt();
+	}
+
+	public void join() throws InterruptedException {
+		thread.join();
+	}
+
+	public void start() {
+		thread.start();
+	}
+
+	public void setName(String name) {
+		thread.setName(name);
+
+	}
+}
Index: java/main/src/main/java/com/framsticks/util/lang/Casting.java
===================================================================
--- java/main/src/main/java/com/framsticks/util/lang/Casting.java	(revision 84)
+++ java/main/src/main/java/com/framsticks/util/lang/Casting.java	(revision 84)
@@ -0,0 +1,31 @@
+package com.framsticks.util.lang;
+
+
+/**
+ * @author Piotr Sniegowski
+ */
+public abstract class Casting {
+    public static <T> T tryCast(Class<T> class_, Object object) {
+        try {
+            return class_.cast(object);
+        } catch (ClassCastException ignored) {
+            return null;
+        }
+    }
+
+    public static <T> T assertCast(Class<T> class_, Object object) {
+        try {
+            return class_.cast(object);
+        } catch (ClassCastException ignored) {
+            assert false;
+            return null;
+        }
+    }
+
+    public static <T> T throwCast(Class<T> class_, Object object) {
+        if (object == null) {
+            throw new NullPointerException();
+        }
+        return class_.cast(object);
+    }
+}
Index: java/main/src/main/java/com/framsticks/util/lang/Containers.java
===================================================================
--- java/main/src/main/java/com/framsticks/util/lang/Containers.java	(revision 84)
+++ java/main/src/main/java/com/framsticks/util/lang/Containers.java	(revision 84)
@@ -0,0 +1,41 @@
+package com.framsticks.util.lang;
+
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import org.apache.commons.collections.functors.InstanceofPredicate;
+import org.apache.commons.collections.iterators.FilterIterator;
+
+/**
+ * @author Piotr Sniegowski
+ */
+public abstract class Containers {
+	public static void resizeList(List<?> list, int size) {
+		while (list.size() < size) {
+			list.add(null);
+		}
+		while (list.size() > size) {
+			list.remove(list.size() - 1);
+		}
+	}
+
+	@SuppressWarnings("unchecked")
+	public static <T> Iterable<T> filterInstanceof(Iterator<? super T> i, Class<T> type) {
+		return new IterableIterator<T>(new FilterIterator(i, new InstanceofPredicate(type)));
+	}
+
+	@SuppressWarnings("unchecked")
+	public static <T> Iterable<T> filterInstanceof(Iterable<? super T> i, Class<T> type) {
+		return new IterableIterator<T>(new FilterIterator(i.iterator(), new InstanceofPredicate(type)));
+	}
+
+	@SuppressWarnings("unchecked")
+	public static <T> Iterable<T> filterInstanceof(Collection<? super T> c, Class<T> type) {
+		return new IterableIterator<T>(new FilterIterator(c.iterator(), new InstanceofPredicate(type)));
+	}
+
+	// @SuppressWarnings("unchecked")
+	// public static <T> Iterable<T> filterNotInstanceof(Collection<T> c, Class<? extends T> type) {
+	// 	return new IterableIterator<T>(new FilterIterator(c.iterator(), new NotPredicate(new InstanceofPredicate(type))));
+	// }
+}
Index: java/main/src/main/java/com/framsticks/util/lang/Delimeted.java
===================================================================
--- java/main/src/main/java/com/framsticks/util/lang/Delimeted.java	(revision 84)
+++ java/main/src/main/java/com/framsticks/util/lang/Delimeted.java	(revision 84)
@@ -0,0 +1,38 @@
+package com.framsticks.util.lang;
+
+import org.apache.commons.collections.Closure;
+
+public class Delimeted implements Closure {
+
+	protected final String delimeter;
+	protected final String empty;
+	protected StringBuilder builder = null;
+
+	/**
+	 * @param delimeter
+	 */
+	public Delimeted(String delimeter, String empty) {
+		this.delimeter = delimeter;
+		this.empty = empty;
+	}
+
+	public final Delimeted append(Object object) {
+		if (builder != null) {
+			builder.append(delimeter);
+		} else {
+			builder = new StringBuilder();
+		}
+		builder.append(object);
+		return this;
+	}
+
+	public final String build() {
+		return (builder != null ? builder.toString() : empty);
+	}
+
+	@Override
+	public void execute(Object input) {
+		append(input);
+	}
+
+}
Index: java/main/src/main/java/com/framsticks/util/lang/Exceptions.java
===================================================================
--- java/main/src/main/java/com/framsticks/util/lang/Exceptions.java	(revision 84)
+++ java/main/src/main/java/com/framsticks/util/lang/Exceptions.java	(revision 84)
@@ -0,0 +1,15 @@
+package com.framsticks.util.lang;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
+/**
+ * Author: Piotr Śniegowski
+ */
+public class Exceptions {
+	public static String printStackTrace(Throwable throwable) {
+		StringWriter w = new StringWriter();
+		throwable.printStackTrace(new PrintWriter(w));
+		return w.getBuffer().toString();
+	}
+}
Index: java/main/src/main/java/com/framsticks/util/lang/IterableIterator.java
===================================================================
--- java/main/src/main/java/com/framsticks/util/lang/IterableIterator.java	(revision 84)
+++ java/main/src/main/java/com/framsticks/util/lang/IterableIterator.java	(revision 84)
@@ -0,0 +1,51 @@
+package com.framsticks.util.lang;
+
+import java.util.Iterator;
+
+/**
+ * @author Piotr Sniegowski
+ */
+public class IterableIterator<T> implements Iterable<T> {
+
+	protected final Iterator<T> i;
+
+	// private static <T> Iterator<T> createIterator(final Iterator<? extends T> i) {
+	//	return new Iterator<T>() {
+
+	//		@Override
+	//		public boolean hasNext() {
+	//			return i.hasNext();
+	//		}
+
+	//		@Override
+	//		public T next() {
+	//			return i.next();
+	//		}
+
+	//		@Override
+	//		public void remove() {
+	//			i.remove();
+	//		}
+	//	};
+	// }
+
+	@SuppressWarnings("unchecked")
+	public IterableIterator(Iterator<? extends T> i) {
+		this.i = (Iterator<T>) i;
+	}
+
+	// public IterableIterator(Iterator<? extends T> i) {
+	//	this.i = createIterator(i);
+	// }
+
+	public Iterator<T> iterator() {
+		return i;
+	}
+
+
+	// @SuppressWarnings("unchecked")
+	// public static <T> IterableIterator<T> unsafe(Iterator<?> i) {
+	//	return new IterableIterator<T>((Iterator<T>) i);
+	// }
+
+}
Index: java/main/src/main/java/com/framsticks/util/lang/Iterators.java
===================================================================
--- java/main/src/main/java/com/framsticks/util/lang/Iterators.java	(revision 84)
+++ java/main/src/main/java/com/framsticks/util/lang/Iterators.java	(revision 84)
@@ -0,0 +1,19 @@
+package com.framsticks.util.lang;
+
+// import java.util.Iterator;
+
+/**
+ * @author Piotr Sniegowski
+ */
+public class Iterators {
+
+
+	// public static String resolve(Iterator<?> iterator, String separator) {
+	// 	Delimeted d = new Delimeted(separator, "");
+	// 	while (iterator.hasNext()) {
+	// 		d.append(iterator.next());
+	// 	}
+	// 	return d.build();
+	// }
+
+}
Index: java/main/src/main/java/com/framsticks/util/lang/Numbers.java
===================================================================
--- java/main/src/main/java/com/framsticks/util/lang/Numbers.java	(revision 84)
+++ java/main/src/main/java/com/framsticks/util/lang/Numbers.java	(revision 84)
@@ -0,0 +1,47 @@
+package com.framsticks.util.lang;
+
+import java.lang.reflect.InvocationTargetException;
+
+/**
+ * @author Piotr Sniegowski
+ */
+public abstract class Numbers {
+
+	@SuppressWarnings("unchecked")
+	public static <T extends Number> T parse(String value, Class<T> type) {
+		if (!Strings.notEmpty(value)) {
+			return null;
+		}
+		try {
+			return (T)type.getMethod("valueOf", String.class).invoke(null, value);
+		} catch (IllegalAccessException e) {
+			e.printStackTrace();
+		} catch (InvocationTargetException e) {
+			if (e.getTargetException() instanceof NumberFormatException) {
+				return null;
+			}
+			e.printStackTrace();
+		} catch (NoSuchMethodException e) {
+			e.printStackTrace();
+		} catch (NumberFormatException ignored) {
+			return null;
+		}
+		return null;
+	}
+
+
+
+	public static <T extends Number> T cast(Object value, Class<T> type) {
+		if (value == null) {
+			return null;
+		}
+		if (value instanceof String) {
+			return parse((String)value, type);
+		}
+		if (value.getClass() == type) {
+			return type.cast(value);
+		}
+		return null;
+	}
+
+}
Index: java/main/src/main/java/com/framsticks/util/lang/Pair.java
===================================================================
--- java/main/src/main/java/com/framsticks/util/lang/Pair.java	(revision 84)
+++ java/main/src/main/java/com/framsticks/util/lang/Pair.java	(revision 84)
@@ -0,0 +1,20 @@
+package com.framsticks.util.lang;
+
+/**
+ * @author Piotr Sniegowski
+ */
+public class Pair<T1, T2> {
+	public final T1 first;
+	public final T2 second;
+
+	public Pair(T1 first, T2 second) {
+		this.first = first;
+		this.second = second;
+	}
+
+	@Override
+	public String toString() {
+		return Strings.toStringNullProof(first) + " " + Strings.toStringNullProof(second);
+	}
+
+}
Index: java/main/src/main/java/com/framsticks/util/lang/Strings.java
===================================================================
--- java/main/src/main/java/com/framsticks/util/lang/Strings.java	(revision 84)
+++ java/main/src/main/java/com/framsticks/util/lang/Strings.java	(revision 84)
@@ -0,0 +1,44 @@
+package com.framsticks.util.lang;
+
+/**
+ * @author Piotr Sniegowski
+ */
+public abstract class Strings {
+
+	public static String valueOf(Object o) {
+		if (o == null) {
+			return null;
+		}
+		return o.toString();
+	}
+
+	public static boolean notEmpty(String str) {
+		return str != null && !str.equals("");
+	}
+
+	public static String toStringNullProof(Object object) {
+		if (object == null) {
+			return "";
+		}
+		return object.toString();
+	}
+
+	public static String collapse(String s) {
+		if (s == null) {
+			return null;
+		}
+		s = s.trim();
+		return (s.equals("")) ? null : s;
+	}
+
+	public static Pair<String, String> splitIntoPair(String string, char separator, String second) {
+		int pos = string.indexOf(separator);
+		if (pos == -1) {
+			return new Pair<String, String>(string.substring(0,
+					string.length() - 1), second);
+		} else {
+			return new Pair<String, String>(string.substring(0, pos),
+					string.substring(pos + 1));
+		}
+	}
+}
Index: java/main/src/main/java/com/framsticks/util/math/Orientation.java
===================================================================
--- java/main/src/main/java/com/framsticks/util/math/Orientation.java	(revision 84)
+++ java/main/src/main/java/com/framsticks/util/math/Orientation.java	(revision 84)
@@ -0,0 +1,79 @@
+package com.framsticks.util.math;
+
+/**
+ * @author Piotr Sniegowski
+ */
+public class Orientation {
+	public final Point3d x;
+	public final Point3d y;
+	public final Point3d z;
+
+	public Orientation(Point3d x, Point3d y, Point3d z) {
+		this.x = x;
+		this.y = y;
+		this.z = z;
+	}
+
+	public Orientation() {
+		x = new Point3d(1, 0, 0);
+		y = new Point3d(0, 1, 0);
+		z = new Point3d(0, 0, 1);
+	}
+
+	/** based on c++ void Orient::transform(Pt3D& target,const Pt3D &s) const */
+	public Point3d transform(Point3d source) {
+		Point3d.Builder b = new Point3d.Builder();
+		for (int i = 0; i < 3; ++i) {
+			double v = 0;
+			for (int j = 0; j < 3; ++j) {
+				v += source.get(j) * this.get(j).get(i);
+			}
+			b.set(i, v);
+		}
+		return b.build();
+	}
+
+	/** based on c++ void Orient::transform(Orient& target,const Orient& src) const */
+	public Orientation transform(Orientation source) {
+		return new Orientation(transform(source.x), transform(source.y), transform(source.z));
+	}
+
+	protected static Point3d rotate2D(double sin, double cos, Point3d p, int a0, int a1, int im) {
+		Point3d.Builder b = new Point3d.Builder();
+		b.set(a0, cos * p.get(a0) - sin * p.get(a1));
+		b.set(a1, sin * p.get(a0) + cos * p.get(a1));
+		b.set(im, p.get(im));
+		return b.build();
+	}
+
+	/** based on c++ Orient::rotate(const Pt3D &v) */
+	public Orientation rotate(Point3d v) {
+		Point3d[] p = new Point3d[] {x, y, z};
+
+		for (int i = 0; i < 3; ++i) {
+			double sin = Math.sin(v.get(i));
+			double cos = Math.cos(v.get(i));
+
+			for (int j = 0; j < 3; ++j) {
+				p[j] = rotate2D(sin, cos, p[j], i == 0 ? 1 : 0, i == 2 ? 1 : 2, i);
+			}
+		}
+		return new Orientation(p[0], p[1], p[2]);
+	}
+
+	final Point3d get(int i) {
+		switch (i) {
+			case 0: return x;
+			case 1: return y;
+			case 2: return z;
+		}
+		assert false;
+		return null;
+	}
+
+
+	@Override
+	public final String toString() {
+		return x + " | " + y + " | " + z;
+	}
+}
Index: java/main/src/main/java/com/framsticks/util/math/Point3d.java
===================================================================
--- java/main/src/main/java/com/framsticks/util/math/Point3d.java	(revision 84)
+++ java/main/src/main/java/com/framsticks/util/math/Point3d.java	(revision 84)
@@ -0,0 +1,67 @@
+package com.framsticks.util.math;
+	
+/**
+ * The simple class which represent point in 3d space.
+ */
+public class Point3d
+{
+	public final double x;
+	public final double y;
+	public final double z;
+
+	public Point3d() {
+		x = 0.0;
+		y = 0.0;
+		z = 0.0;
+	}
+
+	public Point3d(double x, double y, double z) {
+		this.x = x;
+		this.y = y;
+		this.z = z;
+	}
+
+	public Point3d(Point3d p) {
+		x = p.x;
+		y = p.y;
+		z = p.z;
+	}
+
+	@Override
+	public final String toString() {
+		return x + " " + y + " " + z;
+	}
+
+	public final double get(int i) {
+		switch (i) {
+			case 0: return x;
+			case 1: return y;
+			case 2: return z;
+		}
+		assert false;
+		return 0;
+	}
+
+
+	public final Point3d add(Point3d p) {
+		return new Point3d(x + p.x, y + p.y, z + p.z);
+	}
+
+	public final Point3d sub(Point3d p) {
+		return new Point3d(x - p.x, y - p.y, z - p.z);
+	}
+
+	public final double length() {
+		return Math.sqrt(x * x + y * y + z * z);
+	}
+
+	public static class Builder {
+		double[] a = new double[3];
+
+		public Point3d build() { return new Point3d(a[0], a[1], a[2]); }
+
+		public final void set(int i, double v) {
+			a[i] = v;
+		}
+	}
+}
Index: java/main/src/main/java/com/framsticks/util/swing/KeyboardModifier.java
===================================================================
--- java/main/src/main/java/com/framsticks/util/swing/KeyboardModifier.java	(revision 84)
+++ java/main/src/main/java/com/framsticks/util/swing/KeyboardModifier.java	(revision 84)
@@ -0,0 +1,27 @@
+package com.framsticks.util.swing;
+
+import javax.swing.*;
+
+/**
+ * Author: Piotr Śniegowski
+ */
+public class KeyboardModifier {
+	final InputMap inputMap;
+	final ActionMap actionMap;
+
+	public KeyboardModifier(JComponent component, int condition) {
+		inputMap = component.getInputMap(condition);
+		actionMap = component.getActionMap();
+	}
+
+	public KeyboardModifier join(KeyStroke newOne, KeyStroke oldOne) {
+		inputMap.put(newOne, inputMap.get(oldOne));
+		return this;
+	}
+
+	public KeyboardModifier add(KeyStroke keyStroke, String name, Action action) {
+		inputMap.put(keyStroke, name);
+		actionMap.put(name, action);
+		return this;
+	}
+}
Index: java/main/src/main/java/com/framsticks/util/swing/Layout.java
===================================================================
--- java/main/src/main/java/com/framsticks/util/swing/Layout.java	(revision 84)
+++ java/main/src/main/java/com/framsticks/util/swing/Layout.java	(revision 84)
@@ -0,0 +1,23 @@
+package com.framsticks.util.swing;
+
+
+import javax.swing.*;
+import java.awt.*;
+
+/**
+ * @author Piotr Sniegowski
+ */
+public class Layout {
+	public static void fixComponentSize(JComponent component, Dimension dimension) {
+		component.setPreferredSize(dimension);
+		component.setMaximumSize(dimension);
+		component.setMaximumSize(dimension);
+	}
+
+	public static void copyComponentDimensions(JComponent destination, JComponent source) {
+		destination.setPreferredSize(source.getPreferredSize());
+		destination.setMaximumSize(source.getMaximumSize());
+		destination.setMinimumSize(source.getMinimumSize());
+	}
+
+}
Index: java/main/src/main/java/com/framsticks/util/swing/MenuConstructor.java
===================================================================
--- java/main/src/main/java/com/framsticks/util/swing/MenuConstructor.java	(revision 84)
+++ java/main/src/main/java/com/framsticks/util/swing/MenuConstructor.java	(revision 84)
@@ -0,0 +1,24 @@
+package com.framsticks.util.swing;
+
+import javax.swing.*;
+
+/**
+ * Author: Piotr Śniegowski
+ */
+public class MenuConstructor {
+	protected final JMenu menu;
+
+	public MenuConstructor(JMenu menu) {
+		this.menu = menu;
+	}
+
+	public MenuConstructor add(KeyStroke accelerator, Action action) {
+		JMenuItem item = new JMenuItem(action);
+		if (accelerator != null) {
+			item.setAccelerator(accelerator);
+		}
+		menu.add(item);
+		return this;
+	}
+
+}
Index: java/main/src/main/java/com/framsticks/util/swing/TooltipConstructor.java
===================================================================
--- java/main/src/main/java/com/framsticks/util/swing/TooltipConstructor.java	(revision 84)
+++ java/main/src/main/java/com/framsticks/util/swing/TooltipConstructor.java	(revision 84)
@@ -0,0 +1,22 @@
+package com.framsticks.util.swing;
+
+public class TooltipConstructor {
+
+	protected final StringBuilder builder = new StringBuilder();
+
+	public TooltipConstructor() {
+		builder.append("<html>");
+	}
+
+	public final TooltipConstructor append(String header, Object value) {
+		if (value != null) {
+			builder.append(header).append(": ").append(value).append("<br/>");
+		}
+		return this;
+	}
+
+	public final String build() {
+		builder.append("</html>");
+		return builder.toString();
+	}
+}
Index: java/main/src/main/java/com/framsticks/util/swing/TreeNodeUtils.java
===================================================================
--- java/main/src/main/java/com/framsticks/util/swing/TreeNodeUtils.java	(revision 84)
+++ java/main/src/main/java/com/framsticks/util/swing/TreeNodeUtils.java	(revision 84)
@@ -0,0 +1,61 @@
+package com.framsticks.util.swing;
+
+import java.util.Iterator;
+
+import javax.swing.tree.DefaultTreeModel;
+import javax.swing.tree.MutableTreeNode;
+import javax.swing.tree.TreeNode;
+
+public final class TreeNodeUtils {
+
+	private TreeNodeUtils() {
+	}
+
+	public static class TreeNodeChildrenIterator implements Iterator<TreeNode> {
+
+		final TreeNode treeNode;
+		final DefaultTreeModel treeModel;
+		int index;
+
+		/**
+		 * @param treeNode
+		 * @param number
+		 */
+		public TreeNodeChildrenIterator(TreeNode treeNode, DefaultTreeModel treeModel) {
+			this.treeNode = treeNode;
+			this.treeModel = treeModel;
+			this.index = 0;
+		}
+
+		@Override
+		public boolean hasNext() {
+			return index < treeNode.getChildCount();
+		}
+
+		@Override
+		public TreeNode next() {
+			int i = index;
+			++index;
+			return (TreeNode) treeModel.getChild(treeNode, i);
+		}
+
+		@Override
+		public void remove() {
+			if (treeNode instanceof MutableTreeNode) {
+				((MutableTreeNode) treeNode).remove(index);
+				return;
+			}
+			throw new UnsupportedOperationException();
+		}
+	}
+
+	public static Iterable<TreeNode> children(final TreeNode treeNode, final DefaultTreeModel treeModel) {
+		return new Iterable<TreeNode>() {
+			@Override
+			public Iterator<TreeNode> iterator() {
+				return new TreeNodeChildrenIterator(treeNode, treeModel);
+			}
+		};
+	}
+
+}
Index: java/main/src/main/java/com/framsticks/visualization/HelloUniverse2.java
===================================================================
--- java/main/src/main/java/com/framsticks/visualization/HelloUniverse2.java	(revision 84)
+++ java/main/src/main/java/com/framsticks/visualization/HelloUniverse2.java	(revision 84)
@@ -0,0 +1,85 @@
+/*
+ * $RCSfile: HelloUniverse.java,v $
+ *
+ * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistribution of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistribution 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 Sun Microsystems, Inc. or the names of
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any
+ * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND
+ * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY
+ * EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL
+ * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF
+ * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
+ * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR
+ * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL,
+ * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND
+ * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR
+ * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGES.
+ *
+ * You acknowledge that this software is not designed, licensed or
+ * intended for use in the design, construction, operation or
+ * maintenance of any nuclear facility.
+ *
+ * $Revision: 1.2 $
+ * $Date: 2007/02/09 17:21:42 $
+ * $State: Exp $
+ */
+
+package com.framsticks.visualization;
+
+
+
+/**
+ * Simple Java 3D example program to display a spinning cube.
+ */
+@SuppressWarnings("serial")
+public class HelloUniverse2 extends javax.swing.JFrame {
+
+
+	/**
+	 * Creates new form HelloUniverse
+	 */
+	public HelloUniverse2() {
+		ViewerTest viewer = new ViewerTest();
+
+		setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
+		setTitle("HelloUniverse");
+
+		getContentPane().add(viewer, java.awt.BorderLayout.CENTER);
+
+		pack();
+
+	}
+
+	// ----------------------------------------------------------------
+
+
+	/**
+	 * @param args the command line arguments
+	 */
+	public static void main(String args[]) {
+		java.awt.EventQueue.invokeLater(new Runnable() {
+			public void run() {
+				new HelloUniverse2().setVisible(true);
+			}
+		});
+	}
+
+}
Index: java/main/src/main/java/com/framsticks/visualization/ModelVisualizer.java
===================================================================
--- java/main/src/main/java/com/framsticks/visualization/ModelVisualizer.java	(revision 84)
+++ java/main/src/main/java/com/framsticks/visualization/ModelVisualizer.java	(revision 84)
@@ -0,0 +1,8 @@
+package com.framsticks.visualization;
+
+/**
+ * Author: Piotr Śniegowski
+ */
+public class ModelVisualizer {
+
+}
Index: java/main/src/main/java/com/framsticks/visualization/SingleViewPanel.java
===================================================================
--- java/main/src/main/java/com/framsticks/visualization/SingleViewPanel.java	(revision 84)
+++ java/main/src/main/java/com/framsticks/visualization/SingleViewPanel.java	(revision 84)
@@ -0,0 +1,42 @@
+package com.framsticks.visualization;
+
+import com.framsticks.gui.Panel;
+import com.framsticks.model.Model;
+import com.framsticks.params.AccessInterface;
+
+import javax.swing.*;
+import java.awt.*;
+
+/**
+ * Author: Piotr Śniegowski
+ */
+@SuppressWarnings("serial")
+public class SingleViewPanel extends Panel {
+
+	Viewer viewer;
+
+	public SingleViewPanel(Panel.Parameters parameters) {
+		super(parameters);
+		//viewer = new Viewer();
+		this.setLayout(new BorderLayout());
+		//this.add(viewer.getViewComponent(), BorderLayout.CENTER);
+		this.add(new JLabel("test"), BorderLayout.PAGE_START);
+		this.add(new ViewerTest(), BorderLayout.CENTER);
+	}
+
+	@Override
+	public void pullValuesFromLocalToUser(AccessInterface access) {
+		Object object = access.getSelected();
+		if (!(object instanceof Model)) {
+			return;
+		}
+		// Model model = (Model)object;
+
+
+	}
+
+	@Override
+	public String getTitle() {
+		return "3D view";
+	}
+}
Index: java/main/src/main/java/com/framsticks/visualization/SingleViewPanelProvider.java
===================================================================
--- java/main/src/main/java/com/framsticks/visualization/SingleViewPanelProvider.java	(revision 84)
+++ java/main/src/main/java/com/framsticks/visualization/SingleViewPanelProvider.java	(revision 84)
@@ -0,0 +1,17 @@
+package com.framsticks.visualization;
+
+import com.framsticks.gui.Panel;
+import com.framsticks.gui.PanelProvider;
+
+/**
+ * Author: Piotr Śniegowski
+ */
+public class SingleViewPanelProvider implements PanelProvider {
+	@Override
+	public Panel providePanel(Panel.Parameters parameters) {
+		if (parameters.param.getContainedTypeName().equals("Model")) {
+			return new SingleViewPanel(parameters);
+		}
+		return null;
+	}
+}
Index: java/main/src/main/java/com/framsticks/visualization/Viewer.java
===================================================================
--- java/main/src/main/java/com/framsticks/visualization/Viewer.java	(revision 79)
+++ java/main/src/main/java/com/framsticks/visualization/Viewer.java	(revision 84)
@@ -1,5 +1,4 @@
 package com.framsticks.visualization;
 
-import com.framsticks.model.World;
 import com.sun.j3d.loaders.IncorrectFormatException;
 import com.sun.j3d.loaders.ParsingErrorException;
@@ -13,36 +12,21 @@
 import javax.media.j3d.*;
 import javax.swing.*;
-import javax.swing.text.StyledDocument;
 import javax.vecmath.Color3f;
 import javax.vecmath.Point3d;
 import javax.vecmath.Vector3f;
 import java.awt.*;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.io.FileNotFoundException;
+import java.io.*;
 
-import org.apache.log4j.Logger;
+// import org.apache.log4j.Logger;
 
 public class Viewer {
 
-    private static Logger LOGGER = Logger.getLogger(Viewer.class);
+    // private static Logger log = Logger.getLogger(Viewer.class);
 
     Canvas3D canvas3d;
     SimpleUniverse universe;
 
-    World world;
-    private JMenuBar menuBar;
-
-	private JScrollPane scrollPane;
-    private boolean scrollLock = false;
-
-	private JCheckBoxMenuItem loggingItem;
-    private JCheckBoxMenuItem autorefreshItem;
-
-    public Viewer(JMenuBar menuBar) {
+    public Viewer() {
         super();
-        this.menuBar = menuBar;
-        loggingItem = new JCheckBoxMenuItem("Logging");
-        loggingItem.setSelected(true);
 
         init();
@@ -66,5 +50,5 @@
         objScale.addChild(objTrans);
 
-        String filename = "/static/shared/res/obj/cylinder.obj";
+        String filename = "/visualization/models/cylinder.obj";
         int flags = ObjectFile.RESIZE;
         flags |= ObjectFile.TRIANGULATE;
@@ -75,5 +59,6 @@
         Scene s = null;
         try {
-            s = f.load(this.getClass().getResource(filename).getFile());
+			InputStream is = this.getClass().getResourceAsStream(filename);
+            s = f.load(new InputStreamReader(is));
         } catch (FileNotFoundException e) {
             System.err.println(e);
@@ -89,6 +74,5 @@
         objTrans.addChild(s.getSceneGroup());
 
-        BoundingSphere bounds = new BoundingSphere(new Point3d(0.0, 0.0, 0.0),
-                100.0);
+        BoundingSphere bounds = new BoundingSphere(new Point3d(0.0, 0.0, 0.0), 100.0);
 
         Color3f bgColor = new Color3f(0.05f, 0.05f, 0.5f);
@@ -105,17 +89,5 @@
         textPane.setEditable(false);
 
-	    StyledDocument styledDocument = textPane.getStyledDocument();
-
-        scrollPane = new JScrollPane(textPane);
-        //scrollPane.
-        //scrollPane
-        //		.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
-
-        // paneScrollPane.setMinimumSize(new Dimension(400, 300));
-
-        createMenuBar();
-
-        GraphicsConfiguration config = SimpleUniverse
-                .getPreferredConfiguration();
+        GraphicsConfiguration config = SimpleUniverse.getPreferredConfiguration();
 
         // Create a Canvas3D using the preferred configuration
@@ -124,6 +96,5 @@
         // Create simple universe with view branch
         universe = new SimpleUniverse(canvas3d);
-        BoundingSphere bounds = new BoundingSphere(new Point3d(0.0, 0.0, 0.0),
-                100.0);
+        BoundingSphere bounds = new BoundingSphere(new Point3d(0.0, 0.0, 0.0), 100.0);
 
         // add mouse behaviours to the ViewingPlatform
@@ -173,6 +144,5 @@
         // behaviour.addListener(canvas3d);
         // behaviour.initialize();
-        behaviour.setSchedulingBounds(new BoundingSphere(new Point3d(0.0, 0.0,
-                0.0), 100.0));
+        behaviour.setSchedulingBounds(new BoundingSphere(new Point3d(0.0, 0.0, 0.0), 100.0));
         transformGroup.addChild(content);
         // transformGroup.addChild(behaviour);
@@ -180,77 +150,8 @@
 
         universe.addBranchGraph(scene);
-
-
-    }
-
-    private void createMenuBar() {
-
-        JMenu serverItem = new JMenu("Manager");
-        menuBar.add(serverItem);
-
-        JMenuItem testModeItem = new JMenuItem("Test mode");
-        serverItem.add(testModeItem);
-
-	    JMenuItem connectItem = new JMenuItem("Connect");
-        serverItem.add(connectItem);
-
-        JMenu simulationItem = new JMenu("Simulation");
-        menuBar.add(simulationItem);
-
-	    //TODO: move init to main window
-        JMenuItem initItem = new JMenuItem("Init");
-        simulationItem.add(initItem);
-        initItem.addActionListener(new ActionListener() {
-            public void actionPerformed(ActionEvent event) {
-            }
-        });
-
-        JMenuItem refreshCreaturesItem = new JMenuItem("Refresh creatures");
-        simulationItem.add(refreshCreaturesItem);
-        refreshCreaturesItem.addActionListener(new ActionListener() {
-            public void actionPerformed(ActionEvent event) {
-
-            }
-        });
-
-        JMenuItem refreshWorldItem = new JMenuItem("Refresh world");
-        simulationItem.add(refreshWorldItem);
-        refreshWorldItem.addActionListener(new ActionListener() {
-            public void actionPerformed(ActionEvent event) {
-                refreshWorld();
-            }
-        });
-
-	    JMenu styleMenu = new JMenu("Style");
-        menuBar.add(styleMenu);
-
-	    JMenu viewMenu = new JMenu("View");
-        menuBar.add(viewMenu);
-        rebuildViewMenu(null);
-
-        JMenu optionsMenu = new JMenu("Options");
-        menuBar.add(optionsMenu);
-
-        autorefreshItem = new JCheckBoxMenuItem("Autorefresh");
-        autorefreshItem.addActionListener(new ActionListener() {
-            public void actionPerformed(ActionEvent e) {
-                if (autorefreshItem.isSelected()) {
-
-                }
-            }
-        });
-        optionsMenu.add(autorefreshItem);
-
-        optionsMenu.add(loggingItem);
-
-    }
-
-    public void refreshWorld() {
-
-
-    }
-
-    public void rebuildViewMenu(Object creatures) {
-
+		canvas3d.startRenderer();
+		Dimension d = new Dimension(500, 500);
+		canvas3d.setMinimumSize(d);
+		canvas3d.setSize(d);
     }
 
@@ -259,7 +160,4 @@
     }
 
-    public Component getControlComponent() {
-        return scrollPane;
-    }
 
 }
Index: java/main/src/main/java/com/framsticks/visualization/ViewerTest.java
===================================================================
--- java/main/src/main/java/com/framsticks/visualization/ViewerTest.java	(revision 84)
+++ java/main/src/main/java/com/framsticks/visualization/ViewerTest.java	(revision 84)
@@ -0,0 +1,134 @@
+package com.framsticks.visualization;
+
+import com.sun.j3d.utils.universe.*;
+import com.sun.j3d.utils.geometry.ColorCube;
+import org.apache.log4j.Logger;
+
+import javax.media.j3d.*;
+import javax.swing.*;
+import javax.vecmath.*;
+import java.awt.*;
+import java.awt.event.ComponentEvent;
+import java.awt.event.ComponentListener;
+
+/**
+ * Author: Piotr Śniegowski
+ */
+@SuppressWarnings("serial")
+public class ViewerTest extends JPanel {
+	private static final Logger log = Logger.getLogger(ViewerTest.class.getName());
+
+	private SimpleUniverse univ = null;
+	private BranchGroup scene = null;
+
+	public BranchGroup createSceneGraph() {
+		// Create the root of the branch graph
+		BranchGroup objRoot = new BranchGroup();
+
+		// Create the TransformGroup node and initialize it to the
+		// identity. Enable the TRANSFORM_WRITE capability so that
+		// our behavior code can modify it at run time. Add it to
+		// the root of the subgraph.
+		TransformGroup objTrans = new TransformGroup();
+		objTrans.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
+		objRoot.addChild(objTrans);
+
+		// Create a simple Shape3D node; add it to the scene graph.
+		objTrans.addChild(new ColorCube(0.4));
+
+		// Create a new Behavior object that will perform the
+		// desired operation on the specified transform and add
+		// it into the scene graph.
+		Transform3D yAxis = new Transform3D();
+		Alpha rotationAlpha = new Alpha(-1, 4000);
+
+		RotationInterpolator rotator =
+				new RotationInterpolator(rotationAlpha, objTrans, yAxis,
+						0.0f, (float) Math.PI * 2.0f);
+		BoundingSphere bounds =
+				new BoundingSphere(new Point3d(0.0, 0.0, 0.0), 100.0);
+		rotator.setSchedulingBounds(bounds);
+		objRoot.addChild(rotator);
+
+		// Have Java 3D perform optimizations on this scene graph.
+		objRoot.compile();
+
+		return objRoot;
+	}
+
+	private Canvas3D createUniverse() {
+		// Get the preferred graphics configuration for the default screen
+		GraphicsConfiguration config =
+				SimpleUniverse.getPreferredConfiguration();
+
+		// Create a Canvas3D using the preferred configuration
+		final Canvas3D c = new Canvas3D(config) {
+			@Override
+			public void paint(Graphics graphics) {
+				super.paint(graphics);
+				Toolkit.getDefaultToolkit().sync();
+			}
+
+			@Override
+			public void postRender() {
+				super.postRender();
+				//log.info("postRender()");
+			}
+			@Override
+			public void postSwap() {
+				super.postSwap();
+				//log.info("postSwap()");
+			}
+		};
+
+
+		c.addComponentListener(new ComponentListener() {
+			@Override
+			public void componentResized(ComponentEvent componentEvent) {
+			}
+
+			@Override
+			public void componentMoved(ComponentEvent componentEvent) {
+			}
+
+			@Override
+			public void componentShown(ComponentEvent componentEvent) {
+				log.info("shown");
+				c.startRenderer();
+			}
+
+			@Override
+			public void componentHidden(ComponentEvent componentEvent) {
+				log.info("hidden");
+				c.stopRenderer();
+			}
+		});
+
+		// Create simple universe with view branch
+		univ = new SimpleUniverse(c);
+
+		// This will move the ViewPlatform back a bit so the
+		// objects in the scene can be viewed.
+		univ.getViewingPlatform().setNominalViewingTransform();
+
+		// Ensure at least 5 msec per frame (i.e., < 200Hz)
+		univ.getViewer().getView().setMinimumFrameCycleTime(16);
+
+		return c;
+	}
+
+	public ViewerTest() {
+
+		this.setLayout(new java.awt.BorderLayout());
+
+		this.setPreferredSize(new java.awt.Dimension(250, 250));
+
+		Canvas3D c = createUniverse();
+		c.setSize(100, 100);
+		this.add(c, java.awt.BorderLayout.CENTER);
+
+		// Create the content branch and add it to the universe
+		scene = createSceneGraph();
+		univ.addBranchGraph(scene);
+	}
+}
Index: java/main/src/main/resources/configs/framsticks.properties
===================================================================
--- java/main/src/main/resources/configs/framsticks.properties	(revision 79)
+++ java/main/src/main/resources/configs/framsticks.properties	(revision 84)
@@ -2,5 +2,6 @@
 com.framsticks.entities.browser.size.width=1500
 com.framsticks.entities.browser.size.height=800
-com.framsticks.entities.browser.endpoints=localhost,dump,genotype_browser
+# com.framsticks.entities.browser.endpoints=localhost,dump,genotype_browser
+com.framsticks.entities.browser.endpoints=localhost
 com.framsticks.entities.browser.endpoints.dump.entity.class=com.framsticks.dumping.FileInstance
 com.framsticks.entities.browser.endpoints.dump.entity.filename=dumps/localhost:9009__.param
@@ -8,4 +9,6 @@
 com.framsticks.entities.browser.endpoints.remote_portal.entity.mount=com.framsticks.entities.remote_portal
 com.framsticks.entities.browser.endpoints.genotype_browser.entity.mount=com.framsticks.entities.genotype_browser
+com.framsticks.entities.browser.panel_providers=com.framsticks.visualization.SingleViewPanelProvider
+com.framsticks.entities.browser.resolve_paths=/simulator
 
 com.framsticks.entities.diagnostics.class=com.framsticks.diagnostics.Diagnostics
Index: java/main/src/main/resources/configs/log4j.properties
===================================================================
--- java/main/src/main/resources/configs/log4j.properties	(revision 79)
+++ java/main/src/main/resources/configs/log4j.properties	(revision 84)
@@ -29,4 +29,13 @@
 
 log4j.logger.com.framsticks=INFO
+# log4j.logger.com.framsticks.gui.controls.SliderControl=TRACE
+# log4j.logger.com.framsticks.gui.EndpointAtFrame=DEBUG
+# log4j.logger.com.framsticks.gui.TreeNode=DEBUG
+# log4j.logger.com.framsticks.gui.Frame=TRACE
+# log4j.logger.com.framsticks.gui.Browser=DEBUG
+
+#log4j.logger.com.framsticks.gui.Frame=DEBUG
+#log4j.logger.com.framsticks.gui.Browser=DEBUG
+#log4j.logger.com.framsticks.gui.EndpointAtFrame=DEBUG
 #log4j.logger.com.framsticks.remote.RemoteInstance=DEBUG
 #log4j.logger.com.framsticks.gui.TreeNode=DEBUG
Index: java/main/src/test/java/com/framsticks/gui/BrowserTest.java
===================================================================
--- java/main/src/test/java/com/framsticks/gui/BrowserTest.java	(revision 84)
+++ java/main/src/test/java/com/framsticks/gui/BrowserTest.java	(revision 84)
@@ -0,0 +1,114 @@
+package com.framsticks.gui;
+
+import javax.swing.JFrame;
+
+import org.apache.commons.configuration.PropertiesConfiguration;
+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 com.framsticks.communication.ClientConnection;
+import com.framsticks.remote.RemoteInstance;
+import com.framsticks.test.TestConfiguration;
+
+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 TestConfiguration {
+	private static final Logger log = Logger.getLogger(BrowserTest.class);
+
+	Browser browser;
+	Robot robot;
+	FrameFixture frame;
+
+	@BeforeClass
+	public void setUp() {
+		FailOnThreadViolationRepaintManager.install();
+		assertThat(executeInEDT()).isTrue();
+
+		robot = robotWithNewAwtHierarchy();
+
+		browser = new Browser();
+		browser.configure(new PropertiesConfiguration());
+
+		RemoteInstance localhost = new RemoteInstance();
+		localhost.setName("localhost");
+		localhost.setConnection(new ClientConnection("localhost:9009"));
+
+		browser.addEndpointForInstance(localhost);
+
+		browser.start();
+		// robot.waitForIdle();
+		frame = new FrameFixture(robot,
+				GuiActionRunner.execute(new GuiQuery<JFrame>() {
+					@Override
+					protected JFrame executeInEDT() throws Throwable {
+						return browser.getMainFrame();
+					}
+				}));
+
+		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
+	public void testShow() {
+		log.info("testing");
+		JTreeFixture tree = frame.tree("tree");
+		tree.clickRow(0).expandRow(0);
+		robot.waitForIdle();
+		tree.clickRow(1).expandRow(1);
+		robot.waitForIdle();
+		assertThat(tree.valueAt(1)).isEqualTo("simulator");
+		robot.waitForIdle();
+		execute(new GuiTask() {
+			@Override
+			protected void executeInEDT() throws Throwable {
+				assertThat(frame.panel("o Simulator").component().isVisible())
+						.isTrue();
+			}
+		});
+
+		clickAndExpandPath(tree, "localhost/simulator/genepools");
+		clickAndExpandPath(tree, "localhost/simulator/genepools/groups");
+		clickAndExpandPath(tree, "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);
+	}
+
+	public void sleep(int seconds) {
+		try {
+			Thread.sleep(seconds * 1000, 0);
+		} catch (InterruptedException e) {
+			e.printStackTrace();
+		}
+	}
+
+	@AfterClass
+	public void tearDown() {
+		// frame.close();
+		frame.cleanUp();
+	}
+
+}
Index: java/main/src/test/java/com/framsticks/parsers/F0ParserTest.java
===================================================================
--- java/main/src/test/java/com/framsticks/parsers/F0ParserTest.java	(revision 79)
+++ java/main/src/test/java/com/framsticks/parsers/F0ParserTest.java	(revision 84)
@@ -1,74 +1,104 @@
 package com.framsticks.parsers;
 
+import org.testng.annotations.*;
 import com.framsticks.model.*;
 import com.framsticks.model.Package;
 import com.framsticks.params.*;
 import com.framsticks.params.types.FloatParam;
-import com.framsticks.util.Point3d;
-import org.apache.log4j.PropertyConfigurator;
-import org.junit.Test;
+import com.framsticks.test.TestConfiguration;
+import com.framsticks.util.math.Point3d;
 
+import java.io.IOException;
+import java.text.ParseException;
 import java.util.List;
-
-import static org.junit.Assert.*;
+import static org.fest.assertions.Assertions.*;
+import static org.fest.assertions.Delta.*;
 
 /**
  * Author: Piotr Śniegowski
  */
-public class F0ParserTest {
+public class F0ParserTest extends TestConfiguration {
+
+	private Schema schema;
+	private List<AccessInterface> accesses;
+	private List<Object> objects;
+	private Model model;
+
+	@BeforeClass
+	public void setUp() throws Exception {
+		schema = new Schema(Schema.getDefaultDefinitionAsStream());
+		Package.register(schema.getRegistry());
+	}
 
 	@Test
-	public void testParser() throws Exception {
-		PropertyConfigurator.configure(getClass().getResource("/log4j.properties"));
-		//testing schema
-		Schema schema = new Schema(Schema.getDefaultDefinitionAsStream());
+	public void primitiveParam() {
+		FramsClass joint = schema.getRegistry().getInfoFromCache("j");
+		PrimitiveParam dx = joint.getParamEntry("dx", PrimitiveParam.class);
+		assertThat(dx).isInstanceOf(FloatParam.class);
+		assertThat(schema.getNeuroClasses().size()).isEqualTo(21);
+		assertThat(dx.getName()).isEqualTo("delta.x");
+		assertThat(dx.getMin(Double.class)).isEqualTo(-2.0, delta(0.0));
+	}
 
-		{
-			FramsClass joint = schema.getRegistry().getInfoFromCache("j");
-			Param dx = joint.getParamEntry("dx");
-			assertEquals(FloatParam.class, dx.getClass());
-			assertEquals(21, schema.getNeuroClasses().size());
-			assertEquals("delta.x", dx.getName());
-			assertEquals(-2.0, dx.getMin(Double.class), 0.0);
-		}
+	@Test
+	public void readF0() throws IOException, ParseException {
+		accesses = new F0Parser(schema, F0ParserTest.class.getResourceAsStream("/parsers/f0_example.txt")).parse();
 
-		Package.register(schema.getRegistry());
-		//testing parser
-		List<AccessInterface> accesses = new F0Parser(schema, F0ParserTest.class.getResourceAsStream("/parsers/f0_example.txt")).parse();
+		assertThat(accesses.size()).isEqualTo(12);
+		assertThat(accesses.get(0).getSelected()).isInstanceOf(Model.class);
+		assertThat(accesses.get(5).get("i", String.class)).isEqualTo("1,2,3,\"dsadsa,,,,");
+		assertThat(accesses.get(7).get("d", String.class)).isEqualTo("|:p=0.25,r=1");
+		assertThat(accesses.get(10).get("d", String.class)).isEqualTo("@:p=0.25");
+	}
 
-		{
-			assertEquals(12, accesses.size());
-			assertTrue(accesses.get(0).getSelected() instanceof Model);
-			assertEquals("1,2,3,\"dsadsa,,,,", accesses.get(5).get("i", String.class));
-			assertEquals("|:p=0.25,r=1", accesses.get(7).get("d", String.class));
-			assertEquals("@:p=0.25", accesses.get(10).get("d", String.class));
-		}
+	@Test(dependsOnMethods = {"readF0"})
+	public void stripAccessInterface() {
+		objects = Util.stripAccessInterface(accesses);
 
-		List<Object> objects = Util.stripAccessInterface(accesses);
-		{
-			assertEquals(Part.class, objects.get(1).getClass());
-			assertEquals(Joint.class, objects.get(4).getClass());
-			assertEquals(NeuroDef.class, objects.get(6).getClass());
-		}
+		assertThat(objects.get(1)).isInstanceOf(Part.class);
+		assertThat(objects.get(4)).isInstanceOf(Joint.class);
+		assertThat(objects.get(6)).isInstanceOf(NeuroDef.class);
+	}
 
-		Model model = Model.build(objects);
-		{
-			assertEquals(3, model.getParts().size());
-			assertEquals(6, model.getNeuroDefs().size());
-			assertEquals(2, model.getJoints().size());
+	@Test(dependsOnMethods = {"stripAccessInterface"})
+	public void buildModel() {
+		model = Model.build(objects);
 
-			assertEquals(new Integer(0), model.getJoints().get(0).part1);
-			assertEquals(new Integer(1), model.getJoints().get(0).part2);
-			assertEquals(new Integer(1), model.getNeuroDefs().get(0).part);
-			assertEquals(new Integer(-1), model.getNeuroDefs().get(0).joint);
-			assertEquals("|:p=0.25,r=1", model.getNeuroDefs().get(1).details);
-			assertEquals("N", model.getNeuroDefs().get(3).details);
-			assertEquals(new Integer(-1), model.getNeuroDefs().get(4).part);
+		assertThat(model.getParts().size()).isEqualTo(3);
+		assertThat(model.getNeuroDefs().size()).isEqualTo(6);
+		assertThat(model.getJoints().size()).isEqualTo(2);
 
-			assertEquals(2.0, model.getParts().get(1).getPosition().x, 0.0);
-			assertTrue(model.getParts().get(2).getPosition().sub(new Point3d(2.27236, -0.0792596, -0.958924)).length() < 0.0001);
-			assertTrue(model.getParts().get(2).getOrientation().y.sub(new Point3d(0.870277, -0.404792, 0.280644)).length() < 0.0001);
-		}
+		assertThat(model.getJoints().get(0).part1).isEqualTo(0);
+		assertThat(model.getJoints().get(0).part2).isEqualTo(1);
+		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.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);
+	}
+
+	@Test(dependsOnMethods = {"buildModel"})
+	public void print() throws Exception {
+		ListSink sink = new ListSink();
+		new F0Writer(schema, model, sink).write();
+
+		assertThat(sink.getOut()).containsExactly(
+			"p:",
+			"p:2.0,i=,Vstyle=",
+			"p:2.272364001928095,-0.07925961087140347,-0.9589242746631385,i=bla",
+			"j:0,1,dx=2.0",
+			"j:1,2,rx=8.0,5.0,6.0,dx=1.0,i=\"1,2,3,\\\"dsadsa,,,,\"",
+			"n:p=1",
+			"n:j=0,d=\"|:p=0.25,r=1\"",
+			"n:j=0,d=G",
+			"n:p=1",
+			"n:j=0,d=@:p=0.25",
+			"n:p=1,d=Nu",
+			"m:"
+		);
 
 	}
Index: java/main/src/test/java/com/framsticks/test/TestConfiguration.java
===================================================================
--- java/main/src/test/java/com/framsticks/test/TestConfiguration.java	(revision 84)
+++ java/main/src/test/java/com/framsticks/test/TestConfiguration.java	(revision 84)
@@ -0,0 +1,18 @@
+package com.framsticks.test;
+
+import org.apache.log4j.Logger;
+import org.apache.log4j.PropertyConfigurator;
+import org.testng.annotations.*;
+
+public class TestConfiguration {
+
+	private static final Logger log =
+		Logger.getLogger(TestConfiguration.class);
+
+	@BeforeClass
+	public static void setUpConfiguration() {
+		PropertyConfigurator.configure(TestConfiguration.class.getResource("/log4j.properties"));
+		log.info("logging configured");
+	}
+
+}
Index: java/main/src/test/resources/log4j.properties
===================================================================
--- java/main/src/test/resources/log4j.properties	(revision 79)
+++ java/main/src/test/resources/log4j.properties	(revision 84)
@@ -27,2 +27,4 @@
 
 log4j.logger.com.framsticks=INFO
+# log4j.logger.com.framsticks.gui.controls.SliderControl=TRACE
+# log4j.logger.com.framsticks.communication.ClientConnection=DEBUG
