Index: java/main/src/main/java/com/framsticks/communication/ClientSideManagedConnection.java
===================================================================
--- java/main/src/main/java/com/framsticks/communication/ClientSideManagedConnection.java	(revision 99)
+++ java/main/src/main/java/com/framsticks/communication/ClientSideManagedConnection.java	(revision 100)
@@ -17,12 +17,18 @@
 import com.framsticks.util.dispatching.FutureHandler;
 import com.framsticks.util.dispatching.JoinableState;
+import com.framsticks.util.lang.Casting;
 import com.framsticks.util.lang.Pair;
 import com.framsticks.util.lang.Strings;
 import com.framsticks.params.EventListener;
 
-import org.apache.log4j.Logger;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.LogManager;
 
 import java.util.*;
 import java.util.regex.Matcher;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
 import com.framsticks.util.dispatching.RunAt;
 
@@ -32,5 +38,5 @@
 public class ClientSideManagedConnection extends ManagedConnection {
 
-	private final static Logger log = Logger.getLogger(ClientSideManagedConnection.class);
+	private final static Logger log = LogManager.getLogger(ClientSideManagedConnection.class);
 
 	private final List<Runnable> applicationRequestsBuffer = new LinkedList<>();
@@ -60,42 +66,23 @@
 
 
-	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 final void addLine(String line) {
-			assert line != null;
-			assert currentFileContent != null;
-			currentFileContent.add(line);
-		}
-
-		public List<File> getFiles() {
-			return files;
-		}
-	}
 
 	protected List<String> readFileContent() {
 		List<String> content = new LinkedList<String>();
 		String line;
-		while (!(line = getLine()).startsWith("eof")) {
+		boolean longValue = false;
+		while (true) {
+			line = getLine();
+			if (longValue) {
+				if (line.endsWith("~") && !line.endsWith("\\~")) {
+					longValue = false;
+				}
+			} else {
+				if (line.equals("eof")) {
+					break;
+				}
+				if (line.endsWith(":~")) {
+					longValue = true;
+				}
+			}
 			content.add(line);
 		}
@@ -103,23 +90,13 @@
 	}
 
-	private static class SentQuery<C> extends InboundMessage {
+	private static class SentQuery<C> {
+
 		Request request;
 		ClientSideResponseFuture callback;
 		Dispatcher<C> dispatcher;
-
-		public void startFile(String path) {
-			finishCurrentFile();
-			if (!Strings.notEmpty(path)) {
-				assert request instanceof ApplicationRequest;
-				path = ((ApplicationRequest) request).getPath();
-			}
-			Strings.assureNotEmpty(path);
-			initCurrentFile(path);
-		}
-
-		public void eof() {
-			assert Strings.notEmpty(currentFilePath);
-			finishCurrentFile();
-			//no-operation
+		protected final List<File> files = new ArrayList<File>();
+
+		public List<File> getFiles() {
+			return files;
 		}
 
@@ -169,6 +146,5 @@
 
 		if (getState().ordinal() > JoinableState.RUNNING.ordinal()) {
-			log.fatal("not connected");
-			return;
+			throw new FramsticksException().msg("connection is not connected").arg("connection", this);
 		}
 
@@ -211,5 +187,5 @@
 				putLine(out);
 				flushOut();
-				log.debug("sending query: " + out);
+				log.debug("sending query: {}", out);
 
 			}
@@ -217,5 +193,5 @@
 		/*
 		synchronized (this) {
-			log.debug("queueing query: " + query);
+			log.debug("queueing query: {}", query);
 			queryQueue.offer(sentQuery);
 			notifyAll();
@@ -253,17 +229,22 @@
 	}
 
-	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)) {
+	private synchronized @Nonnull SentQuery<?> fetchQuery(@Nullable Integer id, boolean remove) {
+		try {
+			if (id == null) {
+				if (requestIdEnabled) {
+					throw new FramsticksException().msg("request_id is enabled and id is missing");
+				}
+				SentQuery<?> result = currentlySentQuery;
+				if (remove) {
+					currentlySentQuery = null;
+					notifyAll();
+				}
+				return result;
+			}
+
+			if (!queryMap.containsKey(id)) {
+				throw new FramsticksException().msg("id is unknown").arg("id", id);
+			}
+
 			SentQuery<?> result = queryMap.get(id);
 			if (remove) {
@@ -271,23 +252,11 @@
 			}
 			return result;
-		}
-		return null;
+
+		} catch (FramsticksException e) {
+			throw new FramsticksException().msg("failed to match response to sent query").cause(e);
+		}
 	}
 
 	private int nextQueryId = 0;
-
-	protected void processMessage(InboundMessage inboundMessage) {
-		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) {
@@ -303,5 +272,5 @@
 		String eventCalleePath = Request.takeGroup(rest, matcher, 2).toString();
 		final File file = new File("", new ListSource(readFileContent()));
-		log.debug("firing event " + eventObjectPath);
+		log.debug("firing event {}", eventObjectPath);
 		EventListener<File> listener;
 		synchronized (registeredListeners) {
@@ -314,29 +283,50 @@
 	}
 
-	protected void processMessageStartingWith(String line) {
+	protected void processFile(Pair<Integer, CharSequence> rest) {
+		final SentQuery<?> sentQuery = fetchQuery(rest.first, false);
+
+		String currentFilePath = rest.second.toString();
+		if (!Strings.notEmpty(currentFilePath)) {
+			currentFilePath = Casting.throwCast(ApplicationRequest.class, sentQuery.request).getPath();
+		}
+
+		sentQuery.files.add(new File(currentFilePath, new ListSource(readFileContent())));
+
+	}
+
+	protected void processMessageStartingWith(final String header) {
 		try {
-			Pair<CharSequence, CharSequence> command = Request.takeIdentifier(line);
-			if (command.first.equals("event")) {
+			final Pair<CharSequence, CharSequence> command = Request.takeIdentifier(header);
+			if (command == null) {
+				throw new FramsticksException().msg("failed to parse command");
+			}
+			final CharSequence keyword = command.first;
+			if (keyword.equals("event")) {
 				processEvent(command.second.toString());
 				return;
 			}
-			Pair<Integer, CharSequence> rest = takeRequestId(command.second);
-
-			if (command.first.equals("file")) {
-				SentQuery<?> sentQuery = fetchQuery(rest.first, false);
-				sentQuery.startFile(rest.second.toString());
-				processMessage(sentQuery);
+
+			final Pair<Integer, CharSequence> rest = takeRequestId(command.second);
+			if (rest == null) {
+				throw new FramsticksException().msg("failed to parse optional id and remainder");
+			}
+
+			if (keyword.equals("file")) {
+				processFile(rest);
 				return;
 			}
-
-			SentQuery<?> sentQuery = fetchQuery(rest.first, true);
-			if (sentQuery == null) {
+			if (keyword.equals("ok") || keyword.equals("error")) {
+
+				final SentQuery<?> sentQuery = fetchQuery(rest.first, true);
+
+				log.debug("parsing response for request {}", sentQuery);
+
+				sentQuery.dispatchResponseProcess(new Response(command.first.equals("ok"), rest.second.toString(), sentQuery.getFiles()));
 				return;
 			}
-			log.debug("parsing response for request " + sentQuery);
-
-			sentQuery.dispatchResponseProcess(new Response(command.first.equals("ok"), rest.second.toString(), sentQuery.getFiles()));
+
+			throw new FramsticksException().msg("unknown command keyword").arg("keyword", keyword);
 		} catch (FramsticksException e) {
-			throw new FramsticksException().msg("failed to process message").arg("starting with line", line).cause(e);
+			throw new FramsticksException().msg("failed to process message").arg("starting with line", header).cause(e);
 		}
 	}
Index: java/main/src/main/java/com/framsticks/communication/Connection.java
===================================================================
--- java/main/src/main/java/com/framsticks/communication/Connection.java	(revision 99)
+++ java/main/src/main/java/com/framsticks/communication/Connection.java	(revision 100)
@@ -8,6 +8,7 @@
 import com.framsticks.util.lang.Strings;
 
-import org.apache.log4j.Level;
-import org.apache.log4j.Logger;
+import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.LogManager;
 import java.io.BufferedReader;
 import java.io.IOException;
@@ -22,5 +23,7 @@
 
 import com.framsticks.util.dispatching.AbstractJoinable;
+import com.framsticks.util.dispatching.Dispatcher;
 import com.framsticks.util.dispatching.Dispatching;
+import com.framsticks.util.dispatching.ExceptionResultHandler;
 import com.framsticks.util.dispatching.Joinable;
 import com.framsticks.util.dispatching.JoinableCollection;
@@ -32,7 +35,7 @@
 
 @FramsClassAnnotation
-public abstract class Connection extends AbstractJoinable implements JoinableParent {
-
-	protected final static Logger log = Logger.getLogger(Connection.class);
+public abstract class Connection extends AbstractJoinable implements JoinableParent, ExceptionResultHandler {
+
+	protected final static Logger log = LogManager.getLogger(Connection.class);
 
 	private PrintWriter output = null;
@@ -48,4 +51,6 @@
 	protected final JoinableCollection<Thread<Connection>> threads = new JoinableCollection<>();
 	protected final Set<ConnectionListener> listeners = new HashSet<>();
+
+	protected ExceptionResultHandler exceptionHandler = ThrowExceptionHandler.getInstance();
 
 	/**
@@ -161,4 +166,6 @@
 			try {
 				processNextInputBatch();
+			} catch (FramsticksException e) {
+				handle(e);
 			} catch (Exception e) {
 				log.log(isRunning() ? Level.ERROR : Level.DEBUG, "caught exception: ", e);
@@ -183,6 +190,4 @@
 	}
 
-
-
 	@Override
 	protected void joinableFinish() {
@@ -197,5 +202,4 @@
 				input = null;
 			}
-
 
 			if (socket != null) {
@@ -250,5 +254,4 @@
 	}
 
-
 	@Override
 	protected void joinableJoin() throws InterruptedException {
@@ -258,14 +261,14 @@
 	protected static void startClientConnection(Connection connection) {
 		while (connection.isRunning() && !connection.isConnected()) {
-			log.debug("connecting to " + connection.address);
+			log.debug("connecting to {}", connection.address);
 			try {
 				connection.socket = new Socket(connection.getAddressObject().getHostName(), connection.getAddressObject().getPort());
 			} catch (IOException e) {
-				log.info(connection + " failed to connect (retrying): " + e);
+				log.info("{} failed to connect (retrying): ", connection, e);
 				Dispatching.sleep(0.5);
 			}
 		}
 
-		log.debug(connection + " connected");
+		log.debug("{} connected", connection);
 		try {
 			connection.socket.setSoTimeout(500);
@@ -288,5 +291,4 @@
 	}
 
-
 	/**
 	 * @return the listeners
@@ -294,4 +296,18 @@
 	public Collection<ConnectionListener> getListeners() {
 		return listeners;
+	}
+
+	/**
+	 * @return the handler
+	 */
+	public ExceptionResultHandler getExceptionHandler() {
+		return exceptionHandler;
+	}
+
+	/**
+	 * @param handler the handler to set
+	 */
+	public void setExceptionHandler(ExceptionResultHandler handler) {
+		this.exceptionHandler = handler;
 	}
 
@@ -301,3 +317,17 @@
 	}
 
+	@Override
+	public void handle(FramsticksException exception) {
+		exceptionHandler.handle(exception);
+	}
+
+	public Dispatcher<Connection> getReceiverDispatcher() {
+		return receiverThread;
+	}
+
+	public Dispatcher<Connection> getSenderDispatcher() {
+		return senderThread;
+	}
+
+
 }
Index: java/main/src/main/java/com/framsticks/communication/ServerSideManagedConnection.java
===================================================================
--- java/main/src/main/java/com/framsticks/communication/ServerSideManagedConnection.java	(revision 99)
+++ java/main/src/main/java/com/framsticks/communication/ServerSideManagedConnection.java	(revision 100)
@@ -8,5 +8,6 @@
 import com.framsticks.util.lang.Strings;
 
-import org.apache.log4j.Logger;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.LogManager;
 
 import java.net.Socket;
@@ -18,5 +19,5 @@
 public class ServerSideManagedConnection extends ManagedConnection {
 
-	private final static Logger log = Logger.getLogger(ServerSideManagedConnection.class);
+	private final static Logger log = LogManager.getLogger(ServerSideManagedConnection.class);
 
 	protected final RequestHandler requestHandler;
@@ -64,5 +65,5 @@
 
 		}
-		log.error("unhandled request: " + request);
+		log.error("unhandled request: {}", request);
 		responseCallback.pass(new Response(false, "unhandled", null));
 	}
@@ -123,5 +124,5 @@
 
 			if (log.isTraceEnabled()) {
-				log.trace("read request: " + request);
+				log.trace("read request: {}", request);
 			}
 
Index: java/main/src/main/java/com/framsticks/communication/util/LoggingStateCallback.java
===================================================================
--- java/main/src/main/java/com/framsticks/communication/util/LoggingStateCallback.java	(revision 99)
+++ java/main/src/main/java/com/framsticks/communication/util/LoggingStateCallback.java	(revision 100)
@@ -4,5 +4,5 @@
 import com.framsticks.communication.Response;
 
-import org.apache.log4j.Logger;
+import org.apache.logging.log4j.Logger;
 
 /**
Index: java/main/src/main/java/com/framsticks/core/AbstractTree.java
===================================================================
--- java/main/src/main/java/com/framsticks/core/AbstractTree.java	(revision 99)
+++ java/main/src/main/java/com/framsticks/core/AbstractTree.java	(revision 100)
@@ -1,9 +1,13 @@
 package com.framsticks.core;
 
+import java.util.Map;
+
 import javax.annotation.Nonnull;
 
-import org.apache.log4j.Logger;
-
-import com.framsticks.params.AccessInterface;
+import org.apache.commons.collections.map.ReferenceIdentityMap;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.LogManager;
+
+import com.framsticks.params.Access;
 import com.framsticks.params.CompositeParam;
 import com.framsticks.params.FramsClass;
@@ -14,4 +18,5 @@
 import com.framsticks.params.annotations.ParamAnnotation;
 import com.framsticks.util.FramsticksException;
+import com.framsticks.util.Misc;
 import com.framsticks.util.dispatching.AbstractJoinable;
 import com.framsticks.util.dispatching.Dispatcher;
@@ -25,4 +30,5 @@
 import com.framsticks.util.dispatching.Thread;
 import com.framsticks.util.dispatching.ThrowExceptionHandler;
+import com.framsticks.util.lang.Casting;
 
 /**
@@ -32,5 +38,5 @@
 public abstract class AbstractTree extends AbstractJoinable implements Dispatcher<Tree>, Tree, JoinableParent {
 
-	private static final Logger log = Logger.getLogger(AbstractTree.class);
+	private static final Logger log = LogManager.getLogger(AbstractTree.class);
 
 	private Node root = null;
@@ -45,5 +51,5 @@
 		}
 		root = new Node(this, param, null);
-		log.debug("assigned root type: " + root);
+		log.debug("assigned root type: {}", root);
 	}
 
@@ -57,5 +63,5 @@
 		}
 		root = new Node(this, root.getParam(), object);
-		log.debug("assigned root object: " + root);
+		log.debug("assigned root object: {}", root);
 	}
 
@@ -93,5 +99,5 @@
 
 	@Override
-	public @Nonnull AccessInterface prepareAccess(CompositeParam param) {
+	public @Nonnull Access prepareAccess(CompositeParam param) {
 		return registry.prepareAccess(param);
 	}
@@ -104,5 +110,5 @@
 	@AutoAppendAnnotation
 	public void usePackage(ParamsPackage paramsPackage) {
-		log.debug("using package " + paramsPackage + " in tree " + this);
+		log.debug("using package {} in tree {}", paramsPackage, this);
 		paramsPackage.register(registry);
 	}
@@ -110,5 +116,5 @@
 	@AutoAppendAnnotation
 	public void takeFromRegistry(Registry registry) {
-		log.debug("taking from registry " + registry + " in tree " + this);
+		log.debug("taking from registry {} in tree {}", registry, this);
 		this.registry.takeAllFrom(registry);
 	}
@@ -231,4 +237,51 @@
 	}
 
+
+	@SuppressWarnings("unchecked")
+	protected final Map<Object, Object> sideNotes = (Map<Object, Object>) new ReferenceIdentityMap(ReferenceIdentityMap.WEAK, ReferenceIdentityMap.HARD);
+
+	@Override
+	public void putSideNote(Object object, Object key, Object value) {
+		assert isActive();
+		Misc.throwIfNull(object);
+		Misc.throwIfNull(key);
+		Misc.throwIfNull(value);
+		Object sideNote = sideNotes.get(object);
+		if (sideNote == null) {
+			sideNote = new ReferenceIdentityMap(ReferenceIdentityMap.WEAK, ReferenceIdentityMap.HARD);
+			sideNotes.put(object, sideNote);
+		}
+		@SuppressWarnings("unchecked")
+		Map<Object, Object> sideNotesMap = (Map<Object, Object>) sideNote;
+		sideNotesMap.put(key, value);
+	}
+
+	@Override
+	public <T> T getSideNote(Object object, Object key, Class<T> valueType) {
+		assert isActive();
+		Misc.throwIfNull(object);
+		Misc.throwIfNull(key);
+		Object sideNote = sideNotes.get(object);
+		if (sideNote == null) {
+			return null;
+		}
+		return Casting.nullOrThrowCast(valueType, ((Map<?, ?>) sideNote).get(key));
+	}
+
+	@Override
+	public boolean removeSideNote(Object object, Object key) {
+		Object sideNote = sideNotes.get(object);
+		if (sideNote == null) {
+			return false;
+		}
+		@SuppressWarnings("unchecked")
+		Map<Object, Object> sideNotesMap = (Map<Object, Object>) sideNote;
+		boolean result = (sideNotesMap.remove(key) != null);
+		if (sideNotesMap.isEmpty()) {
+			sideNotes.remove(object);
+		}
+		return result;
+	}
+
 }
 
Index: java/main/src/main/java/com/framsticks/core/Framsticks.java
===================================================================
--- java/main/src/main/java/com/framsticks/core/Framsticks.java	(revision 99)
+++ java/main/src/main/java/com/framsticks/core/Framsticks.java	(revision 100)
@@ -7,6 +7,6 @@
 import com.framsticks.util.dispatching.Monitor;
 
-import org.apache.log4j.Logger;
-import org.apache.log4j.PropertyConfigurator;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.LogManager;
 
 import java.io.InputStream;
@@ -17,10 +17,8 @@
 @FramsClassAnnotation
 public class Framsticks extends JoinableCollection<Joinable> {
-	private static final Logger log = Logger.getLogger(Framsticks.class);
+	private static final Logger log = LogManager.getLogger(Framsticks.class);
 
 	public Framsticks() {
-		PropertyConfigurator.configure(getClass().getResource("/configs/log4j.properties"));
 
-		// log.info("config is: " + System.getProperties().getProperty("framsticks.config", "/configs/framsticks.xml"));
 	}
 
Index: java/main/src/main/java/com/framsticks/core/ListChange.java
===================================================================
--- java/main/src/main/java/com/framsticks/core/ListChange.java	(revision 99)
+++ java/main/src/main/java/com/framsticks/core/ListChange.java	(revision 100)
@@ -3,4 +3,5 @@
 import com.framsticks.params.annotations.FramsClassAnnotation;
 import com.framsticks.params.annotations.ParamAnnotation;
+import com.framsticks.util.Misc;
 import com.framsticks.util.lang.Strings;
 
@@ -8,6 +9,22 @@
  * @author Piotr Sniegowski
  */
-@FramsClassAnnotation
+@FramsClassAnnotation(order = {"type", "pos", "id"})
 public class ListChange {
+
+
+	/**
+	 * @param action
+	 */
+	public ListChange(Action action, Integer position, String identifier) {
+		this.action = action;
+		this.position = position;
+		this.identifier = identifier;
+	}
+
+	/**
+	 *
+	 */
+	public ListChange() {
+	}
 
 	public Action getAction() {
@@ -37,5 +54,5 @@
 		//  */
 		// Action(int value) {
-		// 	this.value = value;
+		//	this.value = value;
 		// }
 
@@ -43,5 +60,5 @@
 
 	public Action action = Action.Add;
-	@ParamAnnotation(id = "pos")
+	@ParamAnnotation(id = "pos", def = "-1")
 	public Integer position;
 	@ParamAnnotation(id = "id")
@@ -64,3 +81,13 @@
 		return action + " " + identifier + " " + position;
 	}
+
+	@Override
+	public boolean equals(Object object) {
+		if (object instanceof ListChange) {
+			ListChange r = (ListChange) object;
+			return Misc.equals(action, r.action) && Misc.equals(position, r.position) && Misc.equals(identifier, r.identifier);
+		}
+		return false;
+	}
+
 }
Index: java/main/src/main/java/com/framsticks/core/LocalTree.java
===================================================================
--- java/main/src/main/java/com/framsticks/core/LocalTree.java	(revision 99)
+++ java/main/src/main/java/com/framsticks/core/LocalTree.java	(revision 100)
@@ -1,7 +1,8 @@
 package com.framsticks.core;
 
-import org.apache.log4j.Logger;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.LogManager;
 
-import com.framsticks.params.AccessInterface;
+import com.framsticks.params.Access;
 import com.framsticks.params.CompositeParam;
 import com.framsticks.params.EventListener;
@@ -9,5 +10,4 @@
 import com.framsticks.params.ParamBuilder;
 import com.framsticks.params.PrimitiveParam;
-import com.framsticks.params.ValueParam;
 import com.framsticks.params.annotations.AutoAppendAnnotation;
 import com.framsticks.params.annotations.FramsClassAnnotation;
@@ -21,5 +21,5 @@
 @FramsClassAnnotation
 public final class LocalTree extends AbstractTree {
-	private static final Logger log = Logger.getLogger(LocalTree.class);
+	private static final Logger log = LogManager.getLogger(LocalTree.class);
 
 	protected Object rootObject;
@@ -38,5 +38,5 @@
 		registry.registerAndBuild(javaClass);
 
-		AccessInterface access = registry.createAccess(javaClass);
+		Access access = registry.createAccess(javaClass);
 
 		assignRootParam(access.buildParam(new ParamBuilder()).id(getName()).finish(CompositeParam.class));
@@ -62,15 +62,15 @@
 	public void get(Path path, Future<Path> future) {
 		assert isActive();
-		log.debug("requesting: " + path);
+		log.debug("requesting: {}", path);
 		path = resolveTopSync(path);
 		future.pass(path);
 	}
 
-	@Override
-	public void get(Path path, ValueParam param, Future<Object> future) {
-		assert isActive();
-		path = resolveTopSync(path);
-		future.pass(bindAccess(path).get(param, Object.class));
-	}
+	// @Override
+	// public void get(Path path, ValueParam param, Future<Object> future) {
+	// 	assert isActive();
+	// 	path = resolveTopSync(path);
+	// 	future.pass(bindAccess(path).get(param, Object.class));
+	// }
 
 	@Override
@@ -103,5 +103,5 @@
 			return path;
 		}
-		AccessInterface access = bindAccess(path.getUnder());
+		Access access = bindAccess(path.getUnder());
 		Object object = access.get(path.getTop().getParam(), Object.class);
 		if (object == null) {
Index: java/main/src/main/java/com/framsticks/core/Path.java
===================================================================
--- java/main/src/main/java/com/framsticks/core/Path.java	(revision 99)
+++ java/main/src/main/java/com/framsticks/core/Path.java	(revision 100)
@@ -1,5 +1,5 @@
 package com.framsticks.core;
 
-import com.framsticks.params.AccessInterface;
+import com.framsticks.params.Access;
 import com.framsticks.params.CompositeParam;
 import com.framsticks.params.Param;
@@ -25,5 +25,5 @@
 @Immutable
 public final class Path {
-	// private final static Logger log = Logger.getLogger(Path.class.getName());
+	// private final static Logger log = LogManager.getLogger(Path.class.getName());
 
 	final Tree tree;
@@ -31,5 +31,5 @@
 	final LinkedList<Node> nodes;
 
-	protected static Object getKnownChild(Tree tree, AccessInterface access, CompositeParam param, ExceptionResultHandler handler) {
+	protected static Object getKnownChild(Tree tree, Access access, CompositeParam param, ExceptionResultHandler handler) {
 		Object child = access.get(param, Object.class);
 		if (child == null) {
@@ -38,4 +38,5 @@
 		try {
 			tree.prepareAccess(param);
+			tree.putSideNote(child, CompositeParam.class, param);
 			return child;
 		} catch (FramsticksException e) {
@@ -151,5 +152,5 @@
 			Iterator<String> i = splitPath(textual);
 			while (i.hasNext() && current.getObject() != null) {
-				AccessInterface access = TreeOperations.bindAccess(current);// tree.prepareAccess(current.getParam());
+				Access access = TreeOperations.bindAccess(current);// tree.prepareAccess(current.getParam());
 				String e = i.next();
 				Param p = access.getParam(e);
@@ -163,4 +164,5 @@
 				b.append("/").append(e);
 				access.select(current.getObject());
+				tree.putSideNote(current.getObject(), CompositeParam.class, current.getParam());
 				current = new Node(current.getTree(), c, getKnownChild(tree, access, c, handler));
 				nodes.add(current);
Index: java/main/src/main/java/com/framsticks/core/Tree.java
===================================================================
--- java/main/src/main/java/com/framsticks/core/Tree.java	(revision 99)
+++ java/main/src/main/java/com/framsticks/core/Tree.java	(revision 100)
@@ -3,5 +3,5 @@
 import javax.annotation.Nonnull;
 
-import com.framsticks.params.AccessInterface;
+import com.framsticks.params.Access;
 import com.framsticks.params.CompositeParam;
 import com.framsticks.params.EventListener;
@@ -9,5 +9,4 @@
 import com.framsticks.params.PrimitiveParam;
 import com.framsticks.params.Registry;
-import com.framsticks.params.ValueParam;
 import com.framsticks.params.types.EventParam;
 import com.framsticks.params.types.ProcedureParam;
@@ -24,5 +23,5 @@
 	public void assignRootObject(Object object);
 
-	public @Nonnull AccessInterface prepareAccess(CompositeParam param);
+	public @Nonnull Access prepareAccess(CompositeParam param);
 	public void takeAllFrom(Registry source);
 
@@ -31,10 +30,10 @@
 	public void putInfoIntoCache(FramsClass framclass);
 
-	/**
-	 *
-	 * Functions accepts ValueParam, because it is also possible to get number of List elements.
-	 *
-	 */
-	public void get(Path path, ValueParam param, Future<Object> future);
+	// /**
+	//  *
+	//  * Functions accepts ValueParam, because it is also possible to get number of List elements.
+	//  *
+	//  */
+	// public void get(Path path, ValueParam param, Future<Object> future);
 
 	public void get(Path path, Future<Path> future);
@@ -65,3 +64,9 @@
 	public Registry getRegistry();
 
+	public void putSideNote(Object object, Object key, Object value);
+
+	public boolean removeSideNote(Object object, Object key);
+
+	public <T> T getSideNote(Object object, Object key, Class<T> valueType);
+
 }
Index: java/main/src/main/java/com/framsticks/core/TreeOperations.java
===================================================================
--- java/main/src/main/java/com/framsticks/core/TreeOperations.java	(revision 99)
+++ java/main/src/main/java/com/framsticks/core/TreeOperations.java	(revision 100)
@@ -8,13 +8,17 @@
 import javax.annotation.Nonnull;
 
-import org.apache.log4j.Logger;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.LogManager;
 
 import com.framsticks.communication.File;
-import com.framsticks.params.AccessInterface;
+import com.framsticks.params.Access;
+import com.framsticks.params.CompositeParam;
 import com.framsticks.params.EventListener;
 import com.framsticks.params.FramsClass;
 import com.framsticks.params.ListAccess;
 import com.framsticks.params.Param;
+import com.framsticks.params.ParamBuilder;
 import com.framsticks.params.PrimitiveParam;
+import com.framsticks.params.PropertiesAccess;
 import com.framsticks.params.UniqueListAccess;
 import com.framsticks.params.Util;
@@ -25,4 +29,5 @@
 import com.framsticks.parsers.MultiParamLoader;
 import com.framsticks.util.FramsticksException;
+import com.framsticks.util.dispatching.Dispatching;
 import com.framsticks.util.dispatching.Future;
 import com.framsticks.util.dispatching.FutureHandler;
@@ -33,103 +38,124 @@
 public final class TreeOperations {
 
-	private static final Logger log = Logger.getLogger(TreeOperations.class);
+	private static final Logger log = LogManager.getLogger(TreeOperations.class);
 
 	private TreeOperations() {
 	}
 
+	public static final Object FETCHED_MARK = new Object();
+
 	public static @Nonnull FramsClass processFetchedInfo(Tree tree, File file) {
 		assert tree.isActive();
 		FramsClass framsClass = Loaders.loadFramsClass(file.getContent());
-		log.debug("process fetched info for " + tree + ": " + framsClass);
+		log.debug("process fetched info for {}: {}", tree, framsClass);
 		tree.putInfoIntoCache(framsClass);
 		return framsClass;
 	}
 
-	public static void processFetchedValues(Path path, List<File> files) {
-		Tree tree = path.getTree();
-		assert tree.isActive();
+	public static Path create(Path path) {
+		assert !path.isResolved();
+
+		Access access = path.getTree().prepareAccess(path.getTop().getParam());
+		Object child = createAccessee(path.getTree(), access);
+		assert child != null;
+		if (path.size() == 1) {
+			path.getTree().assignRootObject(child);
+		} else {
+			Access parentAccess = bindAccess(path.getUnder());
+
+			/** this special case is not very good - maybe hide it in createAccessee? */
+			if (parentAccess instanceof UniqueListAccess) {
+				access.select(child);
+				access.set(((UniqueListAccess) parentAccess).getUidName(), path.getTop().getParam().getId());
+			}
+
+			parentAccess.set(path.getTop().getParam(), child);
+		}
+		path = path.appendResolution(child);
+		return path;
+	}
+
+	public static void processFetchedValues(final Path path, final List<File> files, final Access access, final Future<Path> future) {
 		assert files.size() == 1;
 		assert path.isTheSame(files.get(0).getPath());
 
-		if (!path.isResolved()) {
-			AccessInterface access = tree.prepareAccess(path.getTop().getParam());
-			Object child = access.createAccessee();
-			assert child != null;
-			if (path.size() == 1) {
-				tree.assignRootObject(child);
-			} else {
-				bindAccess(path.getUnder()).set(path.getTop().getParam(), child);
-			}
-			path = path.appendResolution(child);
-		}
-
-		log.debug("process fetched values: " + path);
-		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();
-				return;
-			}
-
-			ListAccess listAccess = (ListAccess) bindAccess(node);
-
-			Set<String> oldValuesIds = new HashSet<>();
-			for (Param p : listAccess.getParams()) {
-				oldValuesIds.add(p.getId());
-			}
-
-			// listAccess.clearValues();
-
-			AccessInterface elementAccess = listAccess.getElementAccess();
-			AccessInterface clonerInterface = elementAccess.cloneAccess();
-
-			loader.addAccessInterface(elementAccess);
-			MultiParamLoader.Status status;
-			int number = 0;
-			while ((status = loader.go()) != MultiParamLoader.Status.Finished) {
-				if (status == MultiParamLoader.Status.AfterObject) {
-					AccessInterface accessInterface = loader.getLastAccessInterface();
-
-					String id;
-					if (listAccess instanceof UniqueListAccess) {
-						id = ((UniqueListAccess) listAccess).computeIdentifierFor(accessInterface.getSelected());
-					} else {
-						id = Integer.toString(number);
-					}
-					++number;
-
-					Object childTo = listAccess.get(id, Object.class);
-					boolean newOne;
-					if (childTo == null) {
-						childTo = clonerInterface.createAccessee();
-						newOne = true;
-					} else {
-						assert oldValuesIds.contains(id);
-						newOne = false;
-					}
-					oldValuesIds.remove(id);
-					clonerInterface.select(childTo);
-					Util.takeAllNonNullValues(clonerInterface, accessInterface);
-					if (newOne) {
-						listAccess.set(id, childTo);
-					}
-
-					// listAccess.set(id, accessInterface.getSelected());
-					accessInterface.select(null);
-
+			log.debug("process fetched values: {}", path);
+			final Access parsingAccess = new PropertiesAccess(access.getFramsClass());
+			final List<Object> results = MultiParamLoader.loadAll(files.get(0).getContent(), parsingAccess);
+
+			Dispatching.dispatchIfNotActive(path.getTree(), new RunAt<Tree>(future) {
+				@Override
+				protected void runAt() {
+
+					Path result = path.tryResolveIfNeeded();
+
+					if (!result.isResolved()) {
+						result = create(result);
+					}
+
+					if (path.getTop().getParam() instanceof ObjectParam) {
+						assert results.size() == 1;
+						Util.takeAllNonNullValues(bindAccess(result), parsingAccess.select(results.get(0)));
+						mark(result.getTree(), result.getTopObject(), FETCHED_MARK, true);
+						future.pass(result);
+						return;
+					}
+
+
+					final ListAccess listAccess = (ListAccess) access;
+
+					listAccess.select(result.getTopObject());
+					Set<String> oldValuesIds = new HashSet<>();
+					for (Param p : listAccess.getParams()) {
+						oldValuesIds.add(p.getId());
+					}
+
+					Access targetAccess = listAccess.getElementAccess();//.cloneAccess();
+
+					int number = 0;
+					for (Object r : results) {
+
+						parsingAccess.select(r);
+						String id;
+						if (listAccess instanceof UniqueListAccess) {
+							id = parsingAccess.get(((UniqueListAccess) listAccess).getUidName(), String.class);
+						} else {
+							id = Integer.toString(number);
+						}
+						++number;
+
+						Object childTo = listAccess.get(id, Object.class);
+						boolean newOne;
+						if (childTo == null) {
+							childTo = createAccessee(result.getTree(), targetAccess);
+							newOne = true;
+						} else {
+							assert oldValuesIds.contains(id);
+							newOne = false;
+						}
+						oldValuesIds.remove(id);
+
+						targetAccess.select(childTo);
+						Util.takeAllNonNullValues(targetAccess, parsingAccess);
+						if (newOne) {
+							listAccess.set(id, childTo);
+						}
+						mark(result.getTree(), childTo, FETCHED_MARK, true);
+
+					}
+					mark(result.getTree(), result.getTopObject(), FETCHED_MARK, true);
+
+					/** It looks tricky for ArrayListAccess but should also work.
+					 *
+					 * They should be sorted.
+					 */
+					for (String id : oldValuesIds) {
+						listAccess.set(id, null);
+					}
+					future.pass(result);
 				}
-			}
-			/** It looks tricky for ArrayListAccess but should also work.
- 			 *
-			 * They should be sorted.
-			 */
-			for (String id : oldValuesIds) {
-				listAccess.set(id, null);
-			}
+			});
 
 		} catch (FramsticksException e) {
@@ -141,5 +167,5 @@
 		Tree tree = path.getTree();
 		assert tree.isActive();
-		log.debug("get info for: " + path);
+		log.debug("get info for: {}", path);
 		final String name = path.getTop().getParam().getContainedTypeName();
 		return tree.getInfoFromCache(name);
@@ -147,5 +173,5 @@
 
 	public static void findInfo(final Path path, final Future<FramsClass> future) {
-		log.debug("find info for: " + path);
+		log.debug("find info for: {}", path);
 		try {
 			Tree tree = path.getTree();
@@ -163,11 +189,18 @@
 
 
-
-	public static @Nonnull AccessInterface bindAccess(Tree tree, String path) {
-		log.debug("bind access for textual: " + path + " in " + tree);
+	public static @Nonnull Access bindAccessFromSideNote(Tree tree, Object object) {
+		CompositeParam param = tree.getSideNote(object, CompositeParam.class, CompositeParam.class);
+		if (param == null) {
+			throw new FramsticksException().msg("failed to bind access from side node").arg("tree", tree).arg("object", object).arg("type", object.getClass());
+		}
+		return tree.prepareAccess(param).select(object);
+	}
+
+	public static @Nonnull Access bindAccess(Tree tree, String path) {
+		log.debug("bind access for textual: {} in {}", path, tree);
 		return bindAccess(Path.to(tree, path));
 	}
 
-	public static @Nonnull AccessInterface bindAccess(Node node) {
+	public static @Nonnull Access bindAccess(Node node) {
 		Tree tree = node.getTree();
 		assert tree.isActive();
@@ -175,15 +208,18 @@
 
 		try {
-			return tree.prepareAccess(node.getParam()).select(node.getObject());
+			Access access = tree.prepareAccess(node.getParam());
+			tree.putSideNote(node.getObject(), CompositeParam.class, node.getParam());
+
+			return access.select(node.getObject());
 		} catch (FramsticksException e) {
 			throw new FramsticksException().msg("failed to prepare access for param").arg("param", node.getParam()).cause(e);
-			// log.error("failed to bind access for " + node.getParam() + ": " + e);
-		}
-	}
-
-	public static @Nonnull AccessInterface bindAccess(Path path) {
+			// log.error("failed to bind access for {}: ", node.getParam(), e);
+		}
+	}
+
+	public static @Nonnull Access bindAccess(Path path) {
 		assert path.getTree().isActive();
 		path.assureResolved();
-		log.debug("bind access for: " + path);
+		log.debug("bind access for: {}", path);
 		return bindAccess(path.getTop());
 	}
@@ -196,4 +232,16 @@
 			protected void runAt() {
 				tree.set(path, param, value, future);
+			}
+		});
+	}
+
+	public static void call(final Path path, final String procedureName, final Object[] arguments, final Future<Object> future) {
+		final Tree tree = path.getTree();
+
+		dispatchIfNotActive(tree, new RunAt<Tree>(future) {
+			@Override
+			protected void runAt() {
+				path.assureResolved();
+				tree.call(path, tree.getRegistry().getFramsClass(path.getTop().getParam()).getParamEntry(procedureName, ProcedureParam.class), arguments, future);
 			}
 		});
@@ -241,5 +289,5 @@
 	 * */
 	public static void tryGet(final Tree tree, final String targetPath, final Future<Path> future) {
-		log.debug("resolve textual: " + targetPath + " for " + tree);
+		log.debug("resolve textual: {} for {}", targetPath, tree);
 		dispatchIfNotActive(tree, new RunAt<Tree>(future) {
 
@@ -247,5 +295,5 @@
 			protected void runAt() {
 				final Path path = Path.tryTo(tree, targetPath).tryResolveIfNeeded();
-				log.debug("found: " + path);
+				log.debug("found: {}", path);
 				if (path.isResolved()) {
 					future.pass(path);
@@ -257,8 +305,8 @@
 					protected void result(Path result) {
 						// if (result.isResolved(targetPath)) {
-						// 	future.pass(result);
-						// 	return;
+						//	future.pass(result);
+						//	return;
 						// }
-						log.debug("retrying resolve textual: " + targetPath + " for " + tree + " with " + result);
+						log.debug("retrying resolve textual: {} for {} with {}", targetPath, tree, result);
 						tryGet(tree, targetPath, future);
 					}
@@ -273,3 +321,30 @@
 	}
 
+	public static Object createAccessee(Tree tree, CompositeParam param) {
+		Object object = tree.prepareAccess(param).createAccessee();
+		tree.putSideNote(object, CompositeParam.class, param);
+		return object;
+	}
+
+	public static Object createAccessee(Tree tree, Access access) {
+		Object object = access.createAccessee();
+		tree.putSideNote(object, CompositeParam.class, access.buildParam(new ParamBuilder()).finish(CompositeParam.class));
+		return object;
+	}
+
+	public static boolean isMarked(Tree tree, Object object, Object mark, boolean defValue) {
+		assert tree.isActive();
+		Boolean v = tree.getSideNote(object, mark, Boolean.class);
+		return (v != null ? v : defValue);
+	}
+
+	public static void mark(Tree tree, Object object, Object mark, boolean value) {
+		assert tree.isActive();
+		tree.putSideNote(object, mark, value);
+	}
+
+	public static FramsClass getFramsClass(Path path) {
+		return path.getTree().getRegistry().getFramsClass(path.getTop().getParam());
+	}
+
 }
Index: java/main/src/main/java/com/framsticks/diagnostics/Diagnostics.java
===================================================================
--- java/main/src/main/java/com/framsticks/diagnostics/Diagnostics.java	(revision 99)
+++ java/main/src/main/java/com/framsticks/diagnostics/Diagnostics.java	(revision 100)
@@ -40,5 +40,5 @@
 		// 					@Override
 		// 					public void handle(FramsticksException exception) {
-		// 						log.error("caught error during diagnostics fetching (repeating): " + exception);
+		// 						log.error("caught error during diagnostics fetching (repeating): {}", exception);
 		// 						again();
 		// 					}
Index: java/main/src/main/java/com/framsticks/dumping/LoadStream.java
===================================================================
--- java/main/src/main/java/com/framsticks/dumping/LoadStream.java	(revision 99)
+++ java/main/src/main/java/com/framsticks/dumping/LoadStream.java	(revision 100)
@@ -10,5 +10,6 @@
 import com.framsticks.util.lang.Pair;
 import com.framsticks.util.lang.Strings;
-import org.apache.log4j.Logger;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.LogManager;
 
 import java.io.BufferedReader;
@@ -22,5 +23,5 @@
 public class LoadStream extends Stream {
 
-	private final static Logger log = Logger.getLogger(LoadStream.class.getName());
+	private final static Logger log = LogManager.getLogger(LoadStream.class.getName());
 
 	protected final Tree tree;
@@ -49,5 +50,5 @@
 					query = Strings.splitIntoPair(line, ' ', "");
 					files = new LinkedList<File>();
-					log.trace("loading " + line);
+					log.trace("loading {}", line);
 					continue;
 				}
@@ -84,9 +85,9 @@
 			}
 		} catch (IOException e) {
-			log.error("failed to load: " + e);
+			log.error("failed to load: {}", e);
 			future.handle(new FramsticksException().msg("failed to load stream").cause(e));
 			return;
 		}
-		log.info("loaded in: " + stopwatch);
+		log.info("loaded in: {}", stopwatch);
 		future.pass(Path.to(tree, mountPath.getTextual()));
 	}
Index: java/main/src/main/java/com/framsticks/dumping/SaveStream.java
===================================================================
--- java/main/src/main/java/com/framsticks/dumping/SaveStream.java	(revision 99)
+++ java/main/src/main/java/com/framsticks/dumping/SaveStream.java	(revision 100)
@@ -4,5 +4,5 @@
 import com.framsticks.core.Node;
 import com.framsticks.core.Path;
-import com.framsticks.params.AccessInterface;
+import com.framsticks.params.Access;
 import com.framsticks.params.CompositeParam;
 import com.framsticks.params.FramsClass;
@@ -15,5 +15,6 @@
 import com.framsticks.util.dispatching.Future;
 
-import org.apache.log4j.Logger;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.LogManager;
 import com.framsticks.util.dispatching.RunAt;
 
@@ -27,5 +28,5 @@
 public class SaveStream extends Stream {
 
-	private final static Logger log = Logger.getLogger(SaveStream.class.getName());
+	private final static Logger log = LogManager.getLogger(SaveStream.class.getName());
 
 	protected final SinkInterface sink;
@@ -57,5 +58,5 @@
 	protected void finished() {
 		assert tree.isActive();
-		log.info("stored in " + stopwatch);
+		log.info("stored in {}", stopwatch);
 		future.pass(null);
 	}
@@ -64,7 +65,7 @@
 		assert tree.isActive();
 		if (!path.isResolved()) {
-			log.debug("path " + path + " is not resolved - skipping");
+			log.debug("path {} is not resolved - skipping", path);
 		} else {
-			AccessInterface access = bindAccess(path);
+			Access access = bindAccess(path);
 			assert access != null;
 			FramsClass framsClass = access.getFramsClass();
Index: java/main/src/main/java/com/framsticks/gui/AbstractPanel.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/AbstractPanel.java	(revision 100)
+++ java/main/src/main/java/com/framsticks/gui/AbstractPanel.java	(revision 100)
@@ -0,0 +1,53 @@
+package com.framsticks.gui;
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+import javax.swing.*;
+
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.LogManager;
+
+import com.framsticks.gui.tree.AbstractNode;
+
+/**
+ * Author: Piotr Śniegowski
+ */
+@SuppressWarnings("serial")
+public abstract class AbstractPanel extends JPanel {
+
+	private static final Logger log = LogManager.getLogger(AbstractPanel.class);
+
+	protected final Frame frame;
+
+	protected final String uniqueName;
+	protected final static AtomicInteger counter = new AtomicInteger();
+
+	/**
+	 * @param frame
+	 */
+	public AbstractPanel(Frame frame) {
+		this.frame = frame;
+		this.uniqueName = "panel_" + counter.getAndIncrement();
+
+		frame.cardPanel.add(this, uniqueName);
+		frame.cardPanelLayout.addLayoutComponent(this, uniqueName);
+		log.debug("created panel {}", uniqueName);
+	}
+
+	public final Frame getFrame() {
+		return frame;
+	}
+
+	public abstract String getTitle();
+
+	public final String getUniqueName() {
+		return uniqueName;
+	}
+
+	public abstract void fillPanelWith(AbstractNode node);
+
+	@Override
+	public String toString() {
+		return uniqueName;
+	}
+}
Index: java/main/src/main/java/com/framsticks/gui/Browser.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/Browser.java	(revision 99)
+++ java/main/src/main/java/com/framsticks/gui/Browser.java	(revision 100)
@@ -23,5 +23,6 @@
 import javax.swing.*;
 
-import org.apache.log4j.Logger;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.LogManager;
 
 import java.awt.Dimension;
@@ -40,5 +41,5 @@
 public class Browser extends AbstractJoinable implements Dispatcher<Browser>, JoinableParent, ExceptionResultHandler {
 
-	private static final Logger log = Logger.getLogger(Browser.class);
+	private static final Logger log = LogManager.getLogger(Browser.class);
 
 	protected final JoinableCollection<Frame> frames = new JoinableCollection<Frame>().setObservableName("frames");
@@ -117,5 +118,5 @@
 	@AutoAppendAnnotation
 	public void addPanelProvider(PanelProvider panelProvider) {
-		log.debug("added panel provider of type: " + panelProvider.getClass().getCanonicalName());
+		log.debug("added panel provider of type: {}", panelProvider.getClass().getCanonicalName());
 		panelProviders.add(panelProvider);
 	}
@@ -133,6 +134,7 @@
 	@AutoAppendAnnotation
 	public void addTree(Tree tree) {
-		log.debug("adding tree: " + tree);
+		log.debug("adding tree: {}", tree);
 		tree.setDispatcher(new SwingDispatcher<Tree>());
+		tree.setExceptionHandler(this);
 		trees.add(tree);
 	}
Index: java/main/src/main/java/com/framsticks/gui/EmptyPanel.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/EmptyPanel.java	(revision 99)
+++ java/main/src/main/java/com/framsticks/gui/EmptyPanel.java	(revision 100)
@@ -1,5 +1,5 @@
 package com.framsticks.gui;
 
-import com.framsticks.params.AccessInterface;
+import com.framsticks.gui.tree.AbstractNode;
 
 /**
@@ -7,12 +7,8 @@
  */
 @SuppressWarnings("serial")
-public class EmptyPanel extends Panel {
+public class EmptyPanel extends AbstractPanel {
 
-	public EmptyPanel(Parameters parameters) {
-		super(parameters);
-	}
-
-	@Override
-	public void pullValuesFromLocalToUser(AccessInterface access) {
+	public EmptyPanel(Frame frame) {
+		super(frame);
 	}
 
@@ -21,3 +17,8 @@
 		return "Empty";
 	}
+
+	@Override
+	public void fillPanelWith(AbstractNode node) {
+
+	}
 }
Index: java/main/src/main/java/com/framsticks/gui/EmptyTreePanel.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/EmptyTreePanel.java	(revision 100)
+++ java/main/src/main/java/com/framsticks/gui/EmptyTreePanel.java	(revision 100)
@@ -0,0 +1,22 @@
+package com.framsticks.gui;
+
+import com.framsticks.params.Access;
+
+@SuppressWarnings("serial")
+public class EmptyTreePanel extends TreePanel {
+
+	public EmptyTreePanel(Parameters parameters) {
+		super(parameters);
+	}
+
+	@Override
+	public void pullValuesFromLocalToUser(Access access) {
+
+	}
+
+	@Override
+	public String getTitle() {
+		return "empty";
+	}
+
+}
Index: java/main/src/main/java/com/framsticks/gui/Frame.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/Frame.java	(revision 99)
+++ java/main/src/main/java/com/framsticks/gui/Frame.java	(revision 100)
@@ -36,8 +36,10 @@
 import javax.swing.tree.TreeSelectionModel;
 
-import org.apache.log4j.Logger;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.LogManager;
 
 import com.framsticks.core.Path;
 import com.framsticks.core.Tree;
+import com.framsticks.gui.tree.AbstractNode;
 import com.framsticks.gui.tree.MetaNode;
 import com.framsticks.gui.tree.TreeCellRenderer;
@@ -50,4 +52,5 @@
 import com.framsticks.util.dispatching.JoinableParent;
 import com.framsticks.util.dispatching.JoinableState;
+import com.framsticks.util.lang.Casting;
 import com.framsticks.util.swing.KeyboardModifier;
 import com.framsticks.util.swing.MenuConstructor;
@@ -59,5 +62,5 @@
 public class Frame extends FrameJoinable implements JoinableParent {
 
-	private static final Logger log = Logger.getLogger(Frame.class.getName());
+	private static final Logger log = LogManager.getLogger(Frame.class.getName());
 
 	protected final Browser browser;
@@ -89,4 +92,5 @@
 	protected JMenu windowMenu;
 	protected JMenu helpMenu;
+	protected EmptyPanel emptyPanel;
 
 	protected final Map<Tree, TreeAtFrame> treeAtFrames = new IdentityHashMap<>();
@@ -103,5 +107,13 @@
 		 * nor it can be removed in normal way through JSlider methods  */
 		UIManager.put("Slider.paintValue", false);
-		log.debug("creating " + this);
+		log.debug("creating {}", this);
+
+		cardPanel = new JPanel();
+		cardPanel.setName("card");
+
+		cardPanelLayout = new CardLayout();
+		cardPanel.setLayout(cardPanelLayout);
+
+		emptyPanel = new EmptyPanel(this);
 
 		Container contentPane = getSwing().getContentPane();
@@ -112,5 +124,5 @@
 		treePanel.setLayout(new BorderLayout());
 
-		rootNode = new MetaNode();
+		rootNode = new MetaNode(this);
 		rootNode.setName("root");
 		treeModel = new TreeModel(this);
@@ -139,5 +151,5 @@
 			@Override
 			public void treeExpanded(TreeExpansionEvent e) {
-				// loadChildren(treeModel.convertToPath(e.getPath()), false);
+				treeModel.expandTreeNode(e.getPath());
 			}
 		});
@@ -169,5 +181,5 @@
 			.join(KeyStroke.getKeyStroke('l'), KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0));
 
-		jtree.setCellRenderer(new TreeCellRenderer());
+		jtree.setCellRenderer(new TreeCellRenderer(treeModel));
 
 		treeScrollPane = new JScrollPane(jtree);
@@ -209,6 +221,4 @@
 		leftPanel.setForeground(Color.WHITE);
 
-		cardPanel = new JPanel();
-		cardPanel.setName("card");
 		JSplitPane split = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, leftPanel, cardPanel);
 		split.setPreferredSize(browser.defaultFrameDimension);
@@ -224,11 +234,9 @@
 		mainPanelLayout.show(mainPanel, "browser");
 
-		cardPanelLayout = new CardLayout();
-		cardPanel.setLayout(cardPanelLayout);
 
 		getSwing().pack();
 		jtree.requestFocusInWindow();
 
-		log.debug("frame configured: " + this);
+		log.debug("frame configured: {}", this);
 
 		new MenuConstructor(fileMenu).add(KeyStroke.getKeyStroke(KeyEvent.VK_O, ActionEvent.CTRL_MASK), new AbstractAction("Close") {
@@ -258,5 +266,5 @@
 		Tree tree = path.getTree();
 
-		log.debug("trying mount: " + path);
+		log.debug("trying mount: {}", path);
 		if (!tree.getAssignedRoot().isResolved()) {
 			tree.get(path, new FutureHandler<Path>(this) {
@@ -274,16 +282,20 @@
 		TreeAtFrame e = new TreeAtFrame(tree, this);
 		treeAtFrames.put(tree, e);
-
-		rootNode.getChildren().add(new TreeNode(e, Path.to(tree, "/")));
+		Path rootPath = Path.to(tree, "/");
+
+		rootNode.getChildren().add(new TreeNode(e, rootPath));
 		e.rootNode = tree.getAssignedRoot();
-		treeModel.nodeStructureChanged(new TreePath(rootNode));
+		treeModel.treeStructureChanged(new TreePath(rootNode));
 		// jtree.expandPath(new TreePath(rootNode));
 	}
 
 
-	public void showPanel(Panel panel) {
+	public void showPanel(AbstractPanel panel) {
 		assert isActive();
 		assert panel != null;
+		log.debug("showing panel: {}", panel);
 		cardPanelLayout.show(cardPanel, panel.getUniqueName());
+
+		// cardPanel.revalidate();
 	}
 
@@ -297,4 +309,7 @@
 
 		Path path = treeModel.convertToPath(treePath);
+		if (path == null) {
+			return;
+		}
 		treePopupMenu.removeAll();
 
@@ -311,9 +326,28 @@
 	}
 
-	public void updatePanelIfIsLeadSelection(TreePath treePath, Path path) {
+	public void updatePanelIfIsLeadSelection(Path path) {
 		assert isActive();
+		TreePath treePath = treeModel.convertToTreePath(path, true);
+		if (treePath == null) {
+			return;
+		}
 		if (treePath.equals(jtree.getSelectionPath())) {
-			treeAtFrames.get(path.getTree()).useOrCreatePanel(treePath);
-		}
+			log.debug("updating: {} -> {}", treePath, path);
+			showPanelForTreePath(treePath);
+		}
+	}
+
+	public void showPanelForTreePath(TreePath treePath) {
+		assert isActive();
+		AbstractNode node = Casting.assertCast(AbstractNode.class, treePath.getLastPathComponent());
+
+		AbstractPanel panel = node.getPanel();
+		if (panel == null) {
+			log.error("no panel for {} found", treePath);
+			return;
+		}
+		panel.fillPanelWith(node);
+		showPanel(panel);
+		// cardPanel.revalidate();
 	}
 
@@ -323,5 +357,4 @@
 	//	assert isActive();
 	//	final TreePath treePath = treeModel.convertToTreePath(path);
-	//	log.info("go to path: " + path + "(" + treePath + ")");
 
 	//	this.dispatch(new RunAt<Frame>(this) {
@@ -394,4 +427,11 @@
 
 	/**
+	 * @return the emptyPanel
+	 */
+	public EmptyPanel getEmptyPanel() {
+		return emptyPanel;
+	}
+
+	/**
 	 * @return the treeAtFrames
 	 */
Index: java/main/src/main/java/com/framsticks/gui/FrameJoinable.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/FrameJoinable.java	(revision 99)
+++ java/main/src/main/java/com/framsticks/gui/FrameJoinable.java	(revision 100)
@@ -10,5 +10,6 @@
 import javax.swing.UIManager;
 
-import org.apache.log4j.Logger;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.LogManager;
 
 import com.framsticks.util.FramsticksException;
@@ -19,5 +20,5 @@
 public abstract class FrameJoinable extends SwingJoinable<JFrame> implements ExceptionResultHandler {
 	private static final Logger log =
-		Logger.getLogger(FrameJoinable.class);
+		LogManager.getLogger(FrameJoinable.class);
 
 	protected String title;
@@ -65,5 +66,5 @@
 						boolean found = false;
 						// for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
-						//	log.info("look and feel available: " + info.getName());
+						//	log.info("look and feel available: {}", info.getName());
 						//	if ("Nimbus".equals(info.getName())) {
 						//		UIManager.setLookAndFeel(info.getClassName());
@@ -109,5 +110,5 @@
 	protected void joinableFinish() {
 		super.joinableFinish();
-		log.debug("disposing frame " + this);
+		log.debug("disposing frame {}", this);
 		getSwing().dispose();
 	}
Index: java/main/src/main/java/com/framsticks/gui/Gui.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/Gui.java	(revision 99)
+++ java/main/src/main/java/com/framsticks/gui/Gui.java	(revision 100)
@@ -10,5 +10,6 @@
 import javax.swing.JPanel;
 
-import org.apache.log4j.Logger;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.LogManager;
 
 import com.framsticks.gui.controls.CheckBoxControl;
@@ -39,5 +40,5 @@
 public final class Gui {
 
-	private static final Logger log = Logger.getLogger(Gui.class.getName());
+	private static final Logger log = LogManager.getLogger(Gui.class.getName());
 
 	private Gui() {
@@ -117,5 +118,5 @@
 			control.setOwner(owner);
 
-			log.debug("add component for " + param);
+			log.debug("add component for {}", param);
 			JPanel line = new JPanel();
 			line.setLayout(new BoxLayout(line, BoxLayout.LINE_AXIS));
Index: java/main/src/main/java/com/framsticks/gui/ImageProvider.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/ImageProvider.java	(revision 99)
+++ java/main/src/main/java/com/framsticks/gui/ImageProvider.java	(revision 100)
@@ -4,5 +4,6 @@
 package com.framsticks.gui;
 
-import org.apache.log4j.Logger;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.LogManager;
 
 import javax.swing.*;
@@ -16,5 +17,5 @@
 public class ImageProvider {
 
-	private final static Logger log = Logger.getLogger(ImageProvider.class.getName());
+	private final static Logger log = LogManager.getLogger(ImageProvider.class.getName());
 
 
@@ -87,5 +88,5 @@
 			return icon;
 		} catch (Exception ignored) {
-			log.error("failed to read icon: " + resourceName);
+			log.error("failed to read icon: {}", resourceName);
 		}
 		return null;
Index: java/main/src/main/java/com/framsticks/gui/MainFrame.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/MainFrame.java	(revision 99)
+++ java/main/src/main/java/com/framsticks/gui/MainFrame.java	(revision 100)
@@ -11,5 +11,6 @@
 import javax.swing.WindowConstants;
 
-import org.apache.log4j.Logger;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.LogManager;
 
 import com.framsticks.util.swing.MenuConstructor;
@@ -21,5 +22,5 @@
 public class MainFrame extends Frame {
 
-	private final static Logger log = Logger.getLogger(MainFrame.class.getName());
+	private final static Logger log = LogManager.getLogger(MainFrame.class.getName());
 
 	JButton start, stop, step;
@@ -127,8 +128,8 @@
 	// 	// 			public void call(Exception e) {
 	// 	// 				if (e != null) {
-	// 	// 					log.error("failed to resolve: " + s);
+	// 	// 					log.error("failed to resolve: {}", s);
 	// 	// 					return;
 	// 	// 				}
-	// 	// 				log.info("succeeded to resolve: " + s);
+	// 	// 				log.info("succeeded to resolve: {}", s);
 	// 	// 			}
 	// 	// 		});
Index: java/main/src/main/java/com/framsticks/gui/ModifiablePanel.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/ModifiablePanel.java	(revision 99)
+++ java/main/src/main/java/com/framsticks/gui/ModifiablePanel.java	(revision 100)
@@ -1,5 +1,6 @@
 package com.framsticks.gui;
 
-import org.apache.log4j.Logger;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.LogManager;
 
 
@@ -13,7 +14,7 @@
  */
 @SuppressWarnings("serial")
-public abstract class ModifiablePanel extends Panel {
+public abstract class ModifiablePanel extends TreePanel {
 
-	private static final Logger log = Logger.getLogger(ModifiablePanel.class.getName());
+	private static final Logger log = LogManager.getLogger(ModifiablePanel.class.getName());
 
 	/**
@@ -27,7 +28,7 @@
 	protected Component contentComponent;
 
-	public ModifiablePanel(Panel.Parameters parameters) {
+	public ModifiablePanel(TreePanel.Parameters parameters) {
 		super(parameters);
-		log.debug("create panel for type: " + className);
+		log.debug("create panel for type: {}", className);
 
 
Index: java/main/src/main/java/com/framsticks/gui/MultiPanel.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/MultiPanel.java	(revision 99)
+++ java/main/src/main/java/com/framsticks/gui/MultiPanel.java	(revision 100)
@@ -1,8 +1,8 @@
 package com.framsticks.gui;
 
-import com.framsticks.params.AccessInterface;
+import com.framsticks.core.Path;
+import com.framsticks.params.Access;
 
 import javax.swing.*;
-import javax.swing.tree.TreePath;
 
 import java.awt.*;
@@ -13,16 +13,16 @@
  */
 @SuppressWarnings("serial")
-public class MultiPanel extends Panel {
+public class MultiPanel extends TreePanel {
 
-	protected final List<Panel> panels;
+	protected final List<TreePanel> panels;
 	protected final JTabbedPane tabbedPane;
 
 
-	public MultiPanel(Panel.Parameters parameters, List<Panel> panels) {
+	public MultiPanel(TreePanel.Parameters parameters, List<TreePanel> panels) {
 		super(parameters);
 		this.panels = panels;
 		tabbedPane = new JTabbedPane();
 
-		for (Panel p : panels) {
+		for (TreePanel p : panels) {
 			assert p.getClassName().equals(getClassName());
 			assert p.getTreeAtFrame() == getTreeAtFrame();
@@ -36,6 +36,6 @@
 
 	@Override
-	public void pullValuesFromLocalToUser(AccessInterface access) {
-		for (Panel p : panels) {
+	public void pullValuesFromLocalToUser(Access access) {
+		for (TreePanel p : panels) {
 			p.pullValuesFromLocalToUser(access);
 		}
@@ -48,8 +48,8 @@
 
 	@Override
-	public void setCurrentTreePath(TreePath currentTreePath) {
-		super.setCurrentTreePath(currentTreePath);
-		for (Panel p : panels) {
-			p.setCurrentTreePath(currentTreePath);
+	public void setCurrentPath(Path currentPath) {
+		super.setCurrentPath(currentPath);
+		for (TreePanel p : panels) {
+			p.setCurrentPath(currentPath);
 		}
 	}
Index: java/main/src/main/java/com/framsticks/gui/NodeAtFrame.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/NodeAtFrame.java	(revision 99)
+++ java/main/src/main/java/com/framsticks/gui/NodeAtFrame.java	(revision 100)
@@ -8,7 +8,11 @@
 public class NodeAtFrame {
 
-	protected Panel panel;
-
 	protected final Map<ValueControl, Object> localChanges = new IdentityHashMap<>();
 
+	/**
+	 *
+	 */
+	public NodeAtFrame() {
+	}
+
 }
Index: java/main/src/main/java/com/framsticks/gui/ObjectPanel.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/ObjectPanel.java	(revision 99)
+++ java/main/src/main/java/com/framsticks/gui/ObjectPanel.java	(revision 100)
@@ -1,16 +1,17 @@
 package com.framsticks.gui;
 
+import com.framsticks.core.Path;
 import com.framsticks.gui.controls.Control;
 import com.framsticks.gui.controls.ControlOwner;
 import com.framsticks.gui.controls.ValueControl;
 import com.framsticks.gui.controls.ValueControlListener;
-import com.framsticks.params.AccessInterface;
+import com.framsticks.params.Access;
 import com.framsticks.params.Param;
 import com.framsticks.params.ValueParam;
 
-import org.apache.log4j.Logger;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.LogManager;
 
 import javax.swing.*;
-import javax.swing.tree.TreePath;
 
 import java.util.Collection;
@@ -24,5 +25,5 @@
 public class ObjectPanel extends ModifiablePanel implements ControlOwner {
 
-	private static final Logger log = Logger.getLogger(ObjectPanel.class);
+	private static final Logger log = LogManager.getLogger(ObjectPanel.class);
 
 	final protected Map<Param, Control> components = new IdentityHashMap<Param, Control>();
@@ -32,5 +33,5 @@
 	protected final JScrollPane scrollPane;
 
-	public ObjectPanel(Panel.Parameters parameters, Collection<Param> params) {
+	public ObjectPanel(TreePanel.Parameters parameters, Collection<Param> params) {
 		super(parameters);
 
@@ -49,8 +50,8 @@
 				@Override
 				public boolean onChange(Object newValue) {
-					if (currentTreePath == null) {
+					if (currentPath == null) {
 						return true;
 					}
-					boolean result = treeAtFrame.changeValue(currentTreePath, c, newValue);
+					boolean result = treeAtFrame.changeValue(currentPath.assureResolved().getTopObject(), c, newValue);
 					refreshControlButtons();
 					return result;
@@ -66,19 +67,16 @@
 	protected void applyChanges() {
 		assert frame.isActive();
-		assert currentTreePath != null;
-		treeAtFrame.pushLocalChanges(currentTreePath);
+		assert currentPath != null;
+		treeAtFrame.pushLocalChanges(currentPath);
 	}
 
 	protected void refreshControlButtons() {
 		assert frame.isActive();
-		applyButton.setEnabled(treeAtFrame.hasLocalChanges(currentTreePath));
-	}
-
-	protected static void fillControlsWithValues(Map<ValueControl, Object> map) {
+		applyButton.setEnabled(treeAtFrame.hasLocalChanges(currentPath.getTopObject()));
 	}
 
 	@Override
-	public void pullValuesFromLocalToUser(AccessInterface access) {
-		assert currentTreePath != null;
+	public void pullValuesFromLocalToUser(Access access) {
+		assert currentPath != null;
 		log.debug("refreshing components");
 
@@ -89,5 +87,5 @@
 
 
-		NodeAtFrame nodeAtFrame = treeAtFrame.getLocalInfo(currentTreePath);
+		NodeAtFrame nodeAtFrame = treeAtFrame.getLocalInfo(currentPath.getTopObject());
 		if (nodeAtFrame != null) {
 			for (Map.Entry<ValueControl, Object> e : nodeAtFrame.localChanges.entrySet()) {
@@ -120,8 +118,7 @@
 
 	@Override
-	public TreePath getCurrentTreePath() {
-		return super.getCurrentTreePath();
+	public Path getCurrentPath() {
+		return super.getCurrentPath();
 	}
 
-
 }
Index: java/main/src/main/java/com/framsticks/gui/Panel.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/Panel.java	(revision 99)
+++ 	(revision )
@@ -1,96 +1,0 @@
-package com.framsticks.gui;
-
-import com.framsticks.params.AccessInterface;
-import com.framsticks.params.CompositeParam;
-import com.framsticks.params.FramsClass;
-
-import javax.swing.*;
-import javax.swing.tree.TreePath;
-
-import org.apache.log4j.Logger;
-
-/**
- * Author: Piotr Śniegowski
- */
-@SuppressWarnings("serial")
-public abstract class Panel extends JPanel {
-
-	private static final Logger log = Logger.getLogger(Panel.class);
-
-
-	public static class Parameters {
-		public final TreeAtFrame treeAtFrame;
-		public final CompositeParam param;
-
-		/** Contained type FramsClass. */
-		public final FramsClass framsClass;
-
-		public Parameters(TreeAtFrame treeAtFrame, CompositeParam param, FramsClass framsClass) {
-			this.treeAtFrame = treeAtFrame;
-			this.param = param;
-			this.framsClass = framsClass;
-		}
-	}
-
-	// private static final Logger log = Logger.getLogger(Panel.class.getName());
-
-	protected TreePath currentTreePath;
-	protected final TreeAtFrame treeAtFrame;
-	protected final Frame frame;
-	protected final String className;
-	protected final FramsClass framsClass;
-	protected final CompositeParam param;
-	protected String uniqueName = "?";
-
-	public Panel(Parameters parameters) {
-		this.treeAtFrame = parameters.treeAtFrame;
-		this.frame = parameters.treeAtFrame.getFrame();
-		this.framsClass = parameters.framsClass;
-		this.param = parameters.param;
-		this.className = parameters.param.getContainedTypeName();
-		this.setName(parameters.param.getFramsTypeName());
-		log.debug("created panel: " + this);
-	}
-
-
-
-	public final Frame getFrame() {
-		return frame;
-	}
-
-	/**
-	 * @return the currentTreePath
-	 */
-	public TreePath getCurrentTreePath() {
-		return currentTreePath;
-	}
-
-	/**
-	 * @param currentTreePath the currentTreePath to set
-	 */
-	public void setCurrentTreePath(TreePath currentTreePath) {
-		this.currentTreePath = currentTreePath;
-	}
-
-	public final TreeAtFrame getTreeAtFrame() {
-		return treeAtFrame;
-	}
-
-
-	public final String getClassName() {
-		return className;
-	}
-
-	public abstract void pullValuesFromLocalToUser(AccessInterface access);
-
-	@Override
-	public String toString() {
-		return param.toString() + "(" + uniqueName + ")";
-	}
-
-	public final String getUniqueName() {
-		return uniqueName;
-	}
-
-	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 99)
+++ java/main/src/main/java/com/framsticks/gui/PanelProvider.java	(revision 100)
@@ -6,4 +6,4 @@
  */
 public interface PanelProvider {
-	public Panel providePanel(Panel.Parameters parameters);
+	public TreePanel providePanel(TreePanel.Parameters parameters);
 }
Index: java/main/src/main/java/com/framsticks/gui/StandardPanelProvider.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/StandardPanelProvider.java	(revision 99)
+++ java/main/src/main/java/com/framsticks/gui/StandardPanelProvider.java	(revision 100)
@@ -17,5 +17,5 @@
 	@SuppressWarnings("unchecked")
 	@Override
-	public Panel providePanel(Panel.Parameters parameters) {
+	public TreePanel providePanel(TreePanel.Parameters parameters) {
 		if (parameters.param instanceof ObjectParam) {
 			return new ObjectPanel(parameters, CollectionUtils.select(parameters.framsClass.getParamEntries(), new NotPredicate(new InstanceofPredicate(CompositeParam.class))));
Index: java/main/src/main/java/com/framsticks/gui/StatusBar.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/StatusBar.java	(revision 99)
+++ java/main/src/main/java/com/framsticks/gui/StatusBar.java	(revision 100)
@@ -9,5 +9,6 @@
 import javax.swing.JTextField;
 
-import org.apache.log4j.Logger;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.LogManager;
 
 import com.framsticks.gui.controls.Control;
@@ -18,5 +19,5 @@
 
 public class StatusBar implements ExceptionResultHandler, Dispatcher<StatusBar> {
-	private static final Logger log = Logger.getLogger(StatusBar.class);
+	private static final Logger log = LogManager.getLogger(StatusBar.class);
 
 	protected JTextField statusBar;
@@ -36,5 +37,5 @@
 			@Override
 			protected void runAt() {
-				log.error("error: ", exception);
+				log.error("error: {}", exception.getMessage());
 				statusBar.setText(exception.getShortMessage(new StringBuilder()).toString());
 				if (exceptionHandler != null) {
Index: java/main/src/main/java/com/framsticks/gui/TreeAtFrame.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/TreeAtFrame.java	(revision 99)
+++ java/main/src/main/java/com/framsticks/gui/TreeAtFrame.java	(revision 100)
@@ -1,5 +1,6 @@
 package com.framsticks.gui;
 
-import org.apache.log4j.Logger;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.LogManager;
 
 import com.framsticks.core.Tree;
@@ -8,5 +9,4 @@
 import com.framsticks.core.TreeOperations;
 import com.framsticks.gui.controls.ValueControl;
-import com.framsticks.gui.tree.TreeNode;
 import com.framsticks.params.CompositeParam;
 import com.framsticks.params.FramsClass;
@@ -14,9 +14,7 @@
 import java.util.*;
 
-import javax.swing.tree.TreePath;
 
 
 import com.framsticks.util.dispatching.FutureHandler;
-import com.framsticks.util.lang.Casting;
 
 /**
@@ -25,12 +23,10 @@
 public class TreeAtFrame {
 
-	private static final Logger log = Logger.getLogger(TreeAtFrame.class);
+	private static final Logger log = LogManager.getLogger(TreeAtFrame.class);
 
 	protected final Frame frame;
 	protected final Tree tree;
-	protected final Map<String, Panel> knownPanels = new HashMap<String, Panel>();
+	protected final Map<String, TreePanel> knownPanels = new HashMap<>();
 	protected Node rootNode;
-
-	protected Map<TreeNode, NodeAtFrame> nodesStorage = new WeakHashMap<>();
 
 	public TreeAtFrame(Tree tree, Frame frame) {
@@ -50,35 +46,22 @@
 	}
 
-	public void registerPanel(Panel panel) {
-	}
-
-	public Panel findPanel(String accessId) {
-		assert frame.isActive();
-		return (knownPanels.containsKey(accessId) ? knownPanels.get(accessId) : null);
-	}
-
 	public final String getName() {
 		return tree.getName();
 	}
 
-	public Panel preparePanel(CompositeParam param, FramsClass framsClass) {
+	public TreePanel preparePanel(final CompositeParam param) {
 		assert frame.isActive();
-		Panel panel = preparePanelImpl(param, framsClass);
-		assert panel != null;
-		String accessId = param.computeAccessId();
-		panel.uniqueName = accessId + "@" + tree.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>();
+		TreePanel panel = knownPanels.get(param.getFramsTypeName());
+		if (panel != null) {
+			return panel;
+		}
 
-		Panel.Parameters parameters = new Panel.Parameters(this, param, framsClass);
+		final FramsClass framsClass = tree.getInfoFromCache(param.getContainedTypeName());
+		final List<TreePanel> panels = new ArrayList<TreePanel>();
+
+		final TreePanel.Parameters parameters = new TreePanel.Parameters(this, param, framsClass);
 		for (PanelProvider pp : frame.browser.panelProviders) {
-			Panel p = pp.providePanel(parameters);
+			TreePanel p = pp.providePanel(parameters);
 			if (p != null) {
 				panels.add(p);
@@ -87,15 +70,20 @@
 
 		if (panels.isEmpty()) {
-			return new EmptyPanel(parameters);
+			panel = new EmptyTreePanel(parameters);
+		} else 	if (panels.size() == 1) {
+			panel = panels.get(0);
+		} else {
+			panel = new MultiPanel(parameters, panels);
 		}
-		if (panels.size() == 1) {
-			return panels.get(0);
-		}
-		return new MultiPanel(parameters, panels);
 
+		knownPanels.put(param.getFramsTypeName(), panel);
+
+		log.debug("prepared panel for {}", panel);
+		return panel;
 	}
 
-	public boolean hasLocalChanges(TreePath treePath) {
-		NodeAtFrame nodeAtFrame = nodesStorage.get(treePath.getLastPathComponent());
+
+	public boolean hasLocalChanges(Object object) {
+		NodeAtFrame nodeAtFrame = tree.getSideNote(object, this, NodeAtFrame.class);
 		if (nodeAtFrame == null) {
 			return false;
@@ -104,36 +92,36 @@
 	}
 
-	public NodeAtFrame assureLocalInfo(TreePath treePath) {
+	public NodeAtFrame assureLocalInfo(Object object) {
 		assert frame.isActive();
-		NodeAtFrame nodeAtFrame = nodesStorage.get(treePath.getLastPathComponent());
+		NodeAtFrame nodeAtFrame = tree.getSideNote(object, this, NodeAtFrame.class);
 
 		if (nodeAtFrame == null) {
 			nodeAtFrame = new NodeAtFrame();
-			nodesStorage.put(Casting.throwCast(TreeNode.class, treePath.getLastPathComponent()), nodeAtFrame);
+			// log.debug();
+			tree.putSideNote(object, this, nodeAtFrame);
 		}
 		return nodeAtFrame;
 	}
 
-	public NodeAtFrame getLocalInfo(TreePath treePath) {
-		return nodesStorage.get(treePath.getLastPathComponent());
+	public NodeAtFrame getLocalInfo(Object object) {
+		return tree.getSideNote(object, this, NodeAtFrame.class);
 	}
 
-	public boolean changeValue(TreePath treePath, ValueControl component, Object newValue) {
-		log.debug("changing value of " + component + " to '" + newValue + "'");
+	public boolean changeValue(Object object, ValueControl component, Object newValue) {
+		log.debug("changing value of {} to '{}'", component, newValue);
 
-		assureLocalInfo(treePath).localChanges.put(component, newValue);
+		assureLocalInfo(object).localChanges.put(component, newValue);
 
 		return true;
 	}
 
-	public void pushLocalChanges(TreePath treePath) {
+	public void pushLocalChanges(Path path) {
 		assert frame.isActive();
+		path.assureResolved();
 
-		NodeAtFrame nodeAtFrame = nodesStorage.get(treePath.getLastPathComponent());
+		NodeAtFrame nodeAtFrame = getLocalInfo(path.getTopObject());
 		if (nodeAtFrame == null) {
 			return;
 		}
-		Path path = frame.treeModel.convertToPath(treePath);
-
 		for (Map.Entry<ValueControl, Object> e : nodeAtFrame.localChanges.entrySet()) {
 			TreeOperations.set(path, e.getKey().getParam(), e.getValue(), new FutureHandler<Integer>(frame) {
@@ -145,39 +133,3 @@
 	}
 
-	public void fillPanelWithValues(TreePath treePath) {
-		NodeAtFrame nodeAtFrame = assureLocalInfo(treePath);
-		if (nodeAtFrame == null) {
-			return;
-		}
-
-		if (nodeAtFrame.panel == null) {
-			return;
-		}
-		Node node = TreeNode.tryGetNode(treePath);
-		if (node == null) {
-			return;
-		}
-		nodeAtFrame.panel.setCurrentTreePath(treePath);
-		nodeAtFrame.panel.pullValuesFromLocalToUser(TreeOperations.bindAccess(node));
-
-		frame.showPanel(nodeAtFrame.panel);
-
-	}
-
-	public void useOrCreatePanel(TreePath treePath) {
-		// node.assureResolved();
-		Node node = TreeNode.tryGetNode(treePath);
-
-		NodeAtFrame nodeAtFrame = assureLocalInfo(treePath);
-
-		if (nodeAtFrame.panel == null) {
-			CompositeParam param = node.getParam();
-			nodeAtFrame.panel = findPanel(param.computeAccessId());
-			if (nodeAtFrame.panel == null) {
-				FramsClass framsClass = node.getTree().getInfoFromCache(param.getContainedTypeName());
-				nodeAtFrame.panel = preparePanel(param, framsClass);
-			}
-		}
-		fillPanelWithValues(treePath);
-	}
 }
Index: java/main/src/main/java/com/framsticks/gui/TreePanel.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/TreePanel.java	(revision 100)
+++ java/main/src/main/java/com/framsticks/gui/TreePanel.java	(revision 100)
@@ -0,0 +1,94 @@
+package com.framsticks.gui;
+
+import com.framsticks.core.Path;
+import com.framsticks.core.TreeOperations;
+import com.framsticks.gui.tree.AbstractNode;
+import com.framsticks.gui.tree.TreeNode;
+import com.framsticks.params.Access;
+import com.framsticks.params.CompositeParam;
+import com.framsticks.params.FramsClass;
+import com.framsticks.util.lang.Casting;
+
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.LogManager;
+
+@SuppressWarnings("serial")
+public abstract class TreePanel extends AbstractPanel {
+
+	private static final Logger log = LogManager.getLogger(TreePanel.class);
+
+	@Override
+	public void fillPanelWith(AbstractNode node) {
+		TreeNode treeNode = Casting.throwCast(TreeNode.class, node);
+
+		Path path = Path.to(treeNode.getTree(), treeNode.getTextual());
+		if (!path.isResolved()) {
+			log.error("path is not resolved: {}", path);
+			return;
+		}
+		setCurrentPath(path);
+		pullValuesFromLocalToUser(TreeOperations.bindAccess(path));
+	}
+
+	public static class Parameters {
+		public final TreeAtFrame treeAtFrame;
+		public final CompositeParam param;
+
+		/** Contained type FramsClass. */
+		public final FramsClass framsClass;
+
+		public Parameters(TreeAtFrame treeAtFrame, CompositeParam param, FramsClass framsClass) {
+			this.treeAtFrame = treeAtFrame;
+			this.param = param;
+			this.framsClass = framsClass;
+		}
+	}
+
+	protected final TreeAtFrame treeAtFrame;
+	protected final String className;
+	protected final FramsClass framsClass;
+	protected final CompositeParam param;
+	protected Path currentPath;
+
+	public TreePanel(Parameters parameters) {
+		super(parameters.treeAtFrame.getFrame());
+		this.treeAtFrame = parameters.treeAtFrame;
+		this.framsClass = parameters.framsClass;
+		this.param = parameters.param;
+		this.className = parameters.param.getContainedTypeName();
+		this.setName(parameters.param.getFramsTypeName());
+		log.debug("created panel: {}", this);
+	}
+
+	/**
+	 * @return the currentTreePath
+	 */
+	public Path getCurrentPath() {
+		return currentPath;
+	}
+
+	/**
+	 * @param currentTreePath the currentTreePath to set
+	 */
+	public void setCurrentPath(Path path) {
+		path.assureResolved();
+		this.currentPath = path;
+	}
+
+	public final TreeAtFrame getTreeAtFrame() {
+		return treeAtFrame;
+	}
+
+
+	public final String getClassName() {
+		return className;
+	}
+
+	public abstract void pullValuesFromLocalToUser(Access access);
+
+	@Override
+	public String toString() {
+		return param.getFramsTypeName() + "(" + uniqueName + ")";
+	}
+
+}
Index: java/main/src/main/java/com/framsticks/gui/console/Console.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/console/Console.java	(revision 99)
+++ java/main/src/main/java/com/framsticks/gui/console/Console.java	(revision 100)
@@ -9,5 +9,6 @@
 import javax.swing.JTextPane;
 
-import org.apache.log4j.Logger;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.LogManager;
 
 import com.framsticks.communication.Connection;
@@ -24,5 +25,5 @@
 @FramsClassAnnotation
 public abstract class Console extends FrameJoinable implements JoinableParent {
-	private static final Logger log = Logger.getLogger(Console.class);
+	private static final Logger log = LogManager.getLogger(Console.class);
 
 	/**
Index: java/main/src/main/java/com/framsticks/gui/console/ConsolePainter.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/console/ConsolePainter.java	(revision 99)
+++ java/main/src/main/java/com/framsticks/gui/console/ConsolePainter.java	(revision 100)
@@ -3,5 +3,5 @@
 import com.framsticks.communication.File;
 import com.framsticks.util.FramsticksException;
-// import org.apache.log4j.Logger;
+// import org.apache.logging.log4j.Logger;
 
 // import java.awt.Color;
@@ -16,5 +16,5 @@
  */
 public class ConsolePainter {
-	// private static final Logger log = Logger.getLogger(ConsolePainter.class.getName());
+	// private static final Logger log = LogManager.getLogger(ConsolePainter.class.getName());
 
 	private final Document doc;
Index: java/main/src/main/java/com/framsticks/gui/controls/CheckBoxControl.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/controls/CheckBoxControl.java	(revision 99)
+++ java/main/src/main/java/com/framsticks/gui/controls/CheckBoxControl.java	(revision 100)
@@ -7,5 +7,6 @@
 import javax.swing.JCheckBox;
 
-import org.apache.log4j.Logger;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.LogManager;
 
 import com.framsticks.params.types.BooleanParam;
@@ -14,5 +15,5 @@
 public class CheckBoxControl extends ValueControl {
 
-	private static final Logger log = Logger.getLogger(CheckBoxControl.class.getName());
+	private static final Logger log = LogManager.getLogger(CheckBoxControl.class.getName());
 
 	protected final JCheckBox checkBox;
@@ -25,5 +26,5 @@
 			@Override
 			public void actionPerformed(ActionEvent actionEvent) {
-				log.debug("change to: " + checkBox.isSelected());
+				log.debug("change to: {}", checkBox.isSelected());
 				notifyOfChange();
 			}
Index: java/main/src/main/java/com/framsticks/gui/controls/Control.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/controls/Control.java	(revision 99)
+++ java/main/src/main/java/com/framsticks/gui/controls/Control.java	(revision 100)
@@ -19,5 +19,5 @@
 	public static final int LINE_HEIGHT = 36;
 
-	// private static final Logger log = Logger.getLogger(Control.class.getName());
+	// private static final Logger log = LogManager.getLogger(Control.class.getName());
 
 	protected final Param param;
Index: java/main/src/main/java/com/framsticks/gui/controls/ControlOwner.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/controls/ControlOwner.java	(revision 99)
+++ java/main/src/main/java/com/framsticks/gui/controls/ControlOwner.java	(revision 100)
@@ -2,6 +2,6 @@
 
 import javax.swing.JPanel;
-import javax.swing.tree.TreePath;
 
+import com.framsticks.core.Path;
 import com.framsticks.gui.Frame;
 import com.framsticks.util.dispatching.ExceptionResultHandler;
@@ -10,5 +10,5 @@
 
 	public JPanel getPanelForControls();
-	public TreePath getCurrentTreePath();
+	public Path getCurrentPath();
 	public Frame getFrame();
 
Index: java/main/src/main/java/com/framsticks/gui/controls/EnumControl.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/controls/EnumControl.java	(revision 99)
+++ java/main/src/main/java/com/framsticks/gui/controls/EnumControl.java	(revision 100)
@@ -3,5 +3,6 @@
 import com.framsticks.params.types.EnumParam;
 import com.framsticks.util.lang.Numbers;
-import org.apache.log4j.Logger;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.LogManager;
 
 import javax.swing.*;
@@ -16,5 +17,5 @@
 	protected final JComboBox<String> list;
 
-	private static final Logger log = Logger.getLogger(EnumControl.class.getName());
+	private static final Logger log = LogManager.getLogger(EnumControl.class.getName());
 
 	public EnumControl(EnumParam enumParam) {
Index: java/main/src/main/java/com/framsticks/gui/controls/EventControl.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/controls/EventControl.java	(revision 99)
+++ java/main/src/main/java/com/framsticks/gui/controls/EventControl.java	(revision 100)
@@ -14,5 +14,5 @@
 @SuppressWarnings("serial")
 public class EventControl extends Control {
-	// private static final Logger log = Logger.getLogger(EventControl.class.getName());
+	// private static final Logger log = LogManager.getLogger(EventControl.class.getName());
 
 	protected final JButton button;
Index: java/main/src/main/java/com/framsticks/gui/controls/ProcedureControl.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/controls/ProcedureControl.java	(revision 99)
+++ java/main/src/main/java/com/framsticks/gui/controls/ProcedureControl.java	(revision 100)
@@ -1,5 +1,4 @@
 package com.framsticks.gui.controls;
 
-import com.framsticks.core.Tree;
 import com.framsticks.core.Path;
 import com.framsticks.gui.Frame;
@@ -10,12 +9,12 @@
 import com.framsticks.util.dispatching.ExceptionResultHandler;
 import com.framsticks.util.dispatching.FutureHandler;
-import com.framsticks.util.dispatching.RunAt;
 import com.framsticks.util.dispatching.ThrowExceptionHandler;
+import com.framsticks.util.swing.TooltipConstructor;
 
 import javax.swing.*;
 import javax.swing.border.BevelBorder;
-import javax.swing.tree.TreePath;
 
-import org.apache.log4j.Logger;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.LogManager;
 
 import java.awt.event.ActionEvent;
@@ -29,5 +28,5 @@
 public class ProcedureControl extends Control implements ControlOwner {
 
-	private static final Logger log = Logger.getLogger(ProcedureControl.class);
+	private static final Logger log = LogManager.getLogger(ProcedureControl.class);
 
 	protected final JButton procedureButton;
@@ -37,4 +36,10 @@
 	public ProcedureControl(ProcedureParam procedureParam) {
 		super(procedureParam);
+
+		this.setToolTipText(new TooltipConstructor()
+			.append("name", procedureParam.getName())
+			.append("id", procedureParam.getId())
+			.append("help", procedureParam.getHelp())
+			.build());
 
 		procedureButton = new JButton("Call");
@@ -56,5 +61,5 @@
 			public void actionPerformed(ActionEvent e) {
 
-				final Path path = getFrame().getTreeModel().convertToPath(getCurrentTreePath());
+				final Path path = getCurrentPath();
 
 				final List<Object> arguments = new LinkedList<Object>();
@@ -62,25 +67,27 @@
 					Object value = components.get(arg).getCurrentValue();
 					arguments.add(value);
-					log.debug("argument " + arg + ": " + value);
+					log.debug("argument {}: {}", arg, value);
 				}
 				//TODO FEH: make it show dialog
-				final ExceptionResultHandler handler = ThrowExceptionHandler.getInstance();
+				callProcedure(path, getParam(), arguments.toArray());
 
-				path.getTree().dispatch(new RunAt<Tree>(handler) {
-					@Override
-					protected void runAt() {
-						path.getTree().call(path, getParam(), arguments.toArray(), new FutureHandler<Object>(handler) {
-
-							@Override
-							public void result(Object result) {
-
-							}
-						});
-					}
-				});
 			}
 		});
 		this.add(procedureButton);
 
+	}
+
+	public static void callProcedure(final Path path, final ProcedureParam param, Object[] arguments) {
+		final ExceptionResultHandler handler = ThrowExceptionHandler.getInstance();
+
+		assert path.getTree().isActive();
+
+		path.getTree().call(path, param, arguments, new FutureHandler<Object>(handler) {
+
+			@Override
+			public void result(Object result) {
+
+			}
+		});
 	}
 
@@ -109,6 +116,6 @@
 
 	@Override
-	public TreePath getCurrentTreePath() {
-		return owner.getCurrentTreePath();
+	public Path getCurrentPath() {
+		return owner.getCurrentPath();
 	}
 
Index: java/main/src/main/java/com/framsticks/gui/controls/SliderControl.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/controls/SliderControl.java	(revision 99)
+++ java/main/src/main/java/com/framsticks/gui/controls/SliderControl.java	(revision 100)
@@ -15,5 +15,6 @@
 import javax.swing.event.ChangeListener;
 
-import org.apache.log4j.Logger;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.LogManager;
 
 import com.framsticks.params.types.DecimalParam;
@@ -26,5 +27,5 @@
 public class SliderControl extends TextControl {
 
-	private static final Logger log = Logger.getLogger(SliderControl.class.getName());
+	private static final Logger log = LogManager.getLogger(SliderControl.class.getName());
 
 	protected final JSlider slider;
@@ -115,5 +116,5 @@
 					return;
 				}
-				log.trace("changing " + getParam() + " with slider: " + slider.getValue());
+				log.trace("changing {} with slider: {}", getParam(), slider.getValue());
 				changing = slider;
 				text.setText(convertFromSliderDomain(slider.getValue()).toString());
@@ -128,5 +129,5 @@
 					return;
 				}
-				log.trace("changing " + getParam() + " with text: " + text.getText());
+				log.trace("changing {} with text: {}", getParam(), text.getText());
 				changing = text;
 				Integer i = convertToSliderDomain(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 99)
+++ java/main/src/main/java/com/framsticks/gui/controls/TextAreaControl.java	(revision 100)
@@ -23,6 +23,7 @@
 		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));
+		int maxSize = LINE_HEIGHT * 10;
+		this.setMaximumSize(new Dimension(Integer.MAX_VALUE, maxSize));
+		textArea.setMaximumSize(new Dimension(Integer.MAX_VALUE, maxSize));
 
 		this.revalidate();
Index: java/main/src/main/java/com/framsticks/gui/controls/ValueControl.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/controls/ValueControl.java	(revision 99)
+++ java/main/src/main/java/com/framsticks/gui/controls/ValueControl.java	(revision 100)
@@ -1,5 +1,6 @@
 package com.framsticks.gui.controls;
 
-import org.apache.log4j.Logger;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.LogManager;
 
 import com.framsticks.params.CastFailure;
@@ -18,5 +19,5 @@
 public abstract class ValueControl extends Control {
 	private static final Logger log =
-		Logger.getLogger(ValueControl.class);
+		LogManager.getLogger(ValueControl.class);
 
 	/**
@@ -72,5 +73,5 @@
 			ReassignResult<?> res = getParam().reassign(candidate, oldValue);
 			if (res.getFlags() != 0) {
-				log.warn("filter of param " + param + " failed: " + FlagsUtil.write(SetStateFlags.class, res.getFlags(), "0"));
+				log.warn("filter of param {} failed: {}", param, FlagsUtil.write(SetStateFlags.class, res.getFlags(), "0"));
 			}
 			return res.getValue();
Index: java/main/src/main/java/com/framsticks/gui/table/Column.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/table/Column.java	(revision 100)
+++ java/main/src/main/java/com/framsticks/gui/table/Column.java	(revision 100)
@@ -0,0 +1,40 @@
+package com.framsticks.gui.table;
+
+
+
+import com.framsticks.params.Param;
+
+public abstract class Column {
+
+	protected final Param param;
+	protected final TableModel tableModel;
+
+	/**
+	 * @param param
+	 */
+	public Column(Param param, TableModel tableModel) {
+		this.param = param;
+		this.tableModel = tableModel;
+	}
+
+	/**
+	 * @return the param
+	 */
+	public Param getParam() {
+		return param;
+	}
+
+	public abstract Class<?> getColumnClass();
+	public abstract Object getValueAt(int rowIndex);
+
+	@Override
+	public String toString() {
+		return "column for " + param;
+	}
+
+	public abstract int setValueAt(int rowIndex, Object value);
+
+	public abstract boolean isEditable();
+
+
+}
Index: java/main/src/main/java/com/framsticks/gui/table/ListPanel.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/table/ListPanel.java	(revision 99)
+++ java/main/src/main/java/com/framsticks/gui/table/ListPanel.java	(revision 100)
@@ -3,11 +3,12 @@
 
 import com.framsticks.gui.ModifiablePanel;
-import com.framsticks.params.AccessInterface;
+import com.framsticks.params.Access;
 import com.framsticks.params.ListAccess;
-import com.framsticks.params.PrimitiveParam;
+import com.framsticks.params.Param;
+import com.framsticks.util.FramsticksException;
 import com.framsticks.util.lang.Casting;
-import com.framsticks.util.lang.Containers;
 
-import org.apache.log4j.Logger;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.LogManager;
 
 import javax.swing.*;
@@ -19,5 +20,5 @@
 public class ListPanel extends ModifiablePanel {
 
-	private static final Logger log = Logger.getLogger(ListPanel.class.getName());
+	private static final Logger log = LogManager.getLogger(ListPanel.class.getName());
 
 	protected final TableModel tableModel;
@@ -29,21 +30,29 @@
 
 		final ColumnsConfig config = provider.getColumnsConfigs().get(framsClass.getName());
-		log.debug("creating ListPanel for " + parameters.framsClass + " using config " + config);
+		log.debug("creating ListPanel for {} using config {}", parameters.framsClass, config);
 
-		tableModel = new TableModel();
+		tableModel = new TableModel(this);
 		if (config != null) {
 			for (String id : config.getColumnsNames()) {
-				tableModel.addColumn(framsClass.getParamEntry(id, PrimitiveParam.class));
+				Param param = framsClass.getParam(id);
+				if (param == null) {
+					throw new FramsticksException().msg("requested param not found in frams class").arg("param", id).arg("frams class", framsClass);
+				}
+				if (!tableModel.addColumnIfSupported(param)) {
+					throw new FramsticksException().msg("param is not supported in table view").arg("param", param).arg("frams class", framsClass);
+				}
 			}
 		} else {
-			for (PrimitiveParam<?> param : Containers.filterInstanceof(framsClass.getParamEntries(), PrimitiveParam.class)) {
+			for (Param param : framsClass.getParamEntries()) {
 				if (provider.getMaximumColumnNumber() != null && tableModel.getColumnCount() >= provider.getMaximumColumnNumber()) {
 					break;
 				}
-				tableModel.addColumn(param);
+				tableModel.addColumnIfSupported(param);
 			}
 		}
 
 		table = new JTable(tableModel);
+		tableModel.setupTable();
+
 		scrollPane = new JScrollPane(table);
 		setupContentComponent(scrollPane);
@@ -63,5 +72,5 @@
 
 	@Override
-	public void pullValuesFromLocalToUser(AccessInterface access) {
+	public void pullValuesFromLocalToUser(Access access) {
 		tableModel.attachSource(Casting.throwCast(ListAccess.class, access));
 	}
@@ -71,3 +80,10 @@
 		return "List";
 	}
+
+	/**
+	 * @return the table
+	 */
+	public JTable getTable() {
+		return table;
+	}
 }
Index: java/main/src/main/java/com/framsticks/gui/table/ListPanelProvider.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/table/ListPanelProvider.java	(revision 99)
+++ java/main/src/main/java/com/framsticks/gui/table/ListPanelProvider.java	(revision 100)
@@ -5,6 +5,6 @@
 import java.util.Map;
 
-import com.framsticks.gui.Panel;
 import com.framsticks.gui.PanelProvider;
+import com.framsticks.gui.TreePanel;
 import com.framsticks.params.annotations.AutoAppendAnnotation;
 import com.framsticks.params.annotations.FramsClassAnnotation;
@@ -22,5 +22,5 @@
 
 	@Override
-	public Panel providePanel(Panel.Parameters parameters) {
+	public TreePanel providePanel(TreePanel.Parameters parameters) {
 		if (parameters.param instanceof ListParam) {
 			return new ListPanel(parameters, this);
Index: java/main/src/main/java/com/framsticks/gui/table/PrimitiveColumn.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/table/PrimitiveColumn.java	(revision 100)
+++ java/main/src/main/java/com/framsticks/gui/table/PrimitiveColumn.java	(revision 100)
@@ -0,0 +1,41 @@
+package com.framsticks.gui.table;
+
+import com.framsticks.params.PrimitiveParam;
+import com.framsticks.util.UnsupportedOperationException;
+
+public class PrimitiveColumn extends Column {
+
+	public PrimitiveColumn(PrimitiveParam<?> param, TableModel tableModel) {
+		super(param, tableModel);
+	}
+
+	@Override
+	public PrimitiveParam<?> getParam() {
+		return (PrimitiveParam<?>) param;
+	}
+
+	@Override
+	public Class<?> getColumnClass() {
+		return getParam().getStorageType();
+	}
+
+	@Override
+	public Object getValueAt(int rowIndex) {
+		Object object = tableModel.getAccess().get(rowIndex, Object.class);
+		if (object == null) {
+			return null;
+		}
+		return tableModel.getElementAccess().select(object).get(getParam(), Object.class);
+	}
+
+	@Override
+	public int setValueAt(int rowIndex, Object value) {
+		throw new UnsupportedOperationException().msg("setting value in table");
+	}
+
+	@Override
+	public boolean isEditable() {
+		return false;
+	}
+
+}
Index: java/main/src/main/java/com/framsticks/gui/table/ProcedureColumn.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/table/ProcedureColumn.java	(revision 100)
+++ java/main/src/main/java/com/framsticks/gui/table/ProcedureColumn.java	(revision 100)
@@ -0,0 +1,49 @@
+package com.framsticks.gui.table;
+
+
+import com.framsticks.core.Path;
+import com.framsticks.gui.controls.ProcedureControl;
+import com.framsticks.params.CompositeParam;
+import com.framsticks.params.types.ProcedureParam;
+
+public class ProcedureColumn extends Column {
+
+	public ProcedureColumn(ProcedureParam param, TableModel tableModel) {
+		super(param, tableModel);
+	}
+
+	@Override
+	public ProcedureParam getParam() {
+		return (ProcedureParam) param;
+	}
+
+	@Override
+	public Class<?> getColumnClass() {
+		return ProcedureParam.class;
+	}
+
+	@Override
+	public Object getValueAt(int rowIndex) {
+		return param;
+	}
+
+	@Override
+	public int setValueAt(int rowIndex, Object value) {
+		CompositeParam param = tableModel.getAccess().getCompositeParam(rowIndex);
+		if (param == null) {
+			return 0;
+		}
+		Path path = tableModel.getListPanel().getCurrentPath().appendParam(param).tryFindResolution();
+		if (!path.isResolved()) {
+			return 0;
+		}
+		ProcedureControl.callProcedure(path, getParam(), new Object[] {});
+		return 0;
+	}
+
+	@Override
+	public boolean isEditable() {
+		return true;
+	}
+
+}
Index: java/main/src/main/java/com/framsticks/gui/table/ProcedureEditor.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/table/ProcedureEditor.java	(revision 100)
+++ java/main/src/main/java/com/framsticks/gui/table/ProcedureEditor.java	(revision 100)
@@ -0,0 +1,63 @@
+package com.framsticks.gui.table;
+
+import java.awt.Component;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+import javax.swing.DefaultCellEditor;
+import javax.swing.JButton;
+import javax.swing.JCheckBox;
+import javax.swing.JTable;
+
+import com.framsticks.params.types.ProcedureParam;
+import com.framsticks.util.lang.Casting;
+
+@SuppressWarnings("serial")
+public class ProcedureEditor extends DefaultCellEditor {
+
+	protected JButton button;
+
+	private ProcedureParam procedure;
+
+	private boolean isPushed;
+
+	public ProcedureEditor(JCheckBox checkBox) {
+		super(checkBox);
+		button = new JButton();
+		button.setOpaque(true);
+		button.addActionListener(new ActionListener() {
+			public void actionPerformed(ActionEvent e) {
+				fireEditingStopped();
+			}
+		});
+	}
+
+	public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
+		TableModel.transferCellAppeariance(table, button, isSelected);
+		procedure = Casting.assertCast(ProcedureParam.class, value);
+		button.setText(procedure.getName());
+		isPushed = true;
+		return button;
+	}
+
+	public Object getCellEditorValue() {
+		if (isPushed) {
+			//
+			//
+			// JOptionPane.showMessageDialog(button, label + ": Ouch!");
+			// System.out.println(label + ": Ouch!");
+		}
+		isPushed = false;
+		return procedure;
+	}
+
+	public boolean stopCellEditing() {
+		isPushed = false;
+		return super.stopCellEditing();
+	}
+
+	protected void fireEditingStopped() {
+		super.fireEditingStopped();
+	}
+
+}
Index: java/main/src/main/java/com/framsticks/gui/table/ProcedureRenderer.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/table/ProcedureRenderer.java	(revision 100)
+++ java/main/src/main/java/com/framsticks/gui/table/ProcedureRenderer.java	(revision 100)
@@ -0,0 +1,24 @@
+package com.framsticks.gui.table;
+
+import java.awt.Component;
+
+import javax.swing.JButton;
+import javax.swing.JTable;
+import javax.swing.table.TableCellRenderer;
+
+import com.framsticks.params.types.ProcedureParam;
+
+@SuppressWarnings("serial")
+class ProcedureRenderer extends JButton implements TableCellRenderer {
+
+	public ProcedureRenderer() {
+		setOpaque(true);
+	}
+
+	public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
+		// log.info("focus: {}", hasFocus);
+		TableModel.transferCellAppeariance(table, this, isSelected);
+		setText(((ProcedureParam) value).getName());
+		return this;
+	}
+}
Index: java/main/src/main/java/com/framsticks/gui/table/TableModel.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/table/TableModel.java	(revision 99)
+++ java/main/src/main/java/com/framsticks/gui/table/TableModel.java	(revision 100)
@@ -6,24 +6,49 @@
 import java.util.List;
 
+import javax.swing.JCheckBox;
+import javax.swing.JComponent;
+import javax.swing.JTable;
+import javax.swing.UIManager;
 import javax.swing.event.TableModelEvent;
 import javax.swing.event.TableModelListener;
 
-import org.apache.log4j.Logger;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.LogManager;
 
-import com.framsticks.params.AccessInterface;
+import com.framsticks.params.Access;
 import com.framsticks.params.ListAccess;
+import com.framsticks.params.Param;
 import com.framsticks.params.PrimitiveParam;
-import com.framsticks.util.UnsupportedOperationException;
+import com.framsticks.params.types.ProcedureParam;
 import com.framsticks.util.lang.Casting;
 
 public class TableModel implements javax.swing.table.TableModel {
-	private static final Logger log =
-		Logger.getLogger(TableModel.class);
 
+	private static final Logger log = LogManager.getLogger(TableModel.class);
 
 	protected List<TableModelListener> listeners = new LinkedList<>();
 	protected ListAccess access;
-	protected AccessInterface elementAccess;
-	protected final List<PrimitiveParam<?>> columnParams = new ArrayList<>();
+	protected Access elementAccess;
+	protected final List<Column> columns = new ArrayList<>();
+	protected final ListPanel listPanel;
+	protected JTable table;
+
+	/**
+	 * @param listPanel
+	 */
+	public TableModel(ListPanel listPanel) {
+		this.listPanel = listPanel;
+	}
+
+	/**
+	 * @return the listPanel
+	 */
+	public ListPanel getListPanel() {
+		return listPanel;
+	}
+
+	public JTable getTable() {
+		return listPanel.getTable();
+	}
 
 	protected void refreshAll() {
@@ -31,5 +56,12 @@
 			l.tableChanged(new TableModelEvent(this));
 		}
+	}
 
+	/**
+	 * @param table the table to set
+	 */
+	public void setupTable() {
+		getTable().setDefaultRenderer(ProcedureParam.class, new ProcedureRenderer());
+		getTable().setDefaultEditor(ProcedureParam.class, new ProcedureEditor(new JCheckBox()));
 	}
 
@@ -38,5 +70,5 @@
 
 		this.elementAccess = this.access.getElementAccess().cloneAccess();
-		log.debug("attached " + access);
+		log.debug("attached {}", access);
 		refreshAll();
 	}
@@ -49,35 +81,35 @@
 	@Override
 	public Class<?> getColumnClass(int columnIndex) {
-		// log.debug("returning column type " + columnParams.get(columnIndex).getStorageType());
-		return columnParams.get(columnIndex).getStorageType();
+		// log.debug("returning column type {}", columnParams.get(columnIndex).getStorageType());
+		return columns.get(columnIndex).getColumnClass();
 	}
 
 	@Override
 	public int getColumnCount() {
-		// log.debug("returning column count " + columnParams.size());
-		return columnParams.size();
+		// log.debug("returning column count {}", columnParams.size());
+		return columns.size();
 	}
 
 	@Override
 	public String getColumnName(int columnIndex) {
-		return columnParams.get(columnIndex).getName();
+		return columns.get(columnIndex).getParam().getName();
 	}
 
 	@Override
 	public int getRowCount() {
-		// log.debug("returning row count " + access.getParamCount());
-		return access.getParamCount();
+		// log.debug("returning row count {}", access.getParamCount());
+		return access == null ? 0 : access.getParamCount();
 	}
 
 	@Override
 	public Object getValueAt(int rowIndex, int columnIndex) {
-		assert (rowIndex < access.getParamCount() && columnIndex < columnParams.size());
+		assert (rowIndex < access.getParamCount() && columnIndex < columns.size());
 
-		return elementAccess.select(access.get(rowIndex, Object.class)).get(columnParams.get(columnIndex), Object.class);
+		return columns.get(columnIndex).getValueAt(rowIndex);
 	}
 
 	@Override
 	public boolean isCellEditable(int rowIndex, int columnIndex) {
-		return false;
+		return columns.get(columnIndex).isEditable();
 	}
 
@@ -87,13 +119,32 @@
 	}
 
+
 	@Override
 	public void setValueAt(Object value, int rowIndex, int columnIndex) {
-		throw new UnsupportedOperationException().msg("setting value in table");
-
+		assert (rowIndex < access.getParamCount() && columnIndex < columns.size());
+		// Object object = getObjectAt(rowIndex, columnIndex);
+		// if (object == null) {
+		//	return;
+		// }
+		columns.get(columnIndex).setValueAt(rowIndex, value);
 	}
 
-	public void addColumn(PrimitiveParam<?> columnParam) {
-		log.debug("added " + columnParam);
-		columnParams.add(columnParam);
+	public void addColumn(Column column) {
+		log.debug("added {}", column);
+		columns.add(column);
+	}
+
+	/**
+	 * @return the access
+	 */
+	public ListAccess getAccess() {
+		return access;
+	}
+
+	/**
+	 * @return the elementAccess
+	 */
+	public Access getElementAccess() {
+		return elementAccess;
 	}
 
@@ -101,6 +152,33 @@
 	 * @return the columnParams
 	 */
-	public List<PrimitiveParam<?>> getColumnParams() {
-		return Collections.unmodifiableList(columnParams);
+	public List<Column> getColumns() {
+		return Collections.unmodifiableList(columns);
+	}
+
+
+	public boolean addColumnIfSupported(Param param) {
+		if (param instanceof PrimitiveParam) {
+			addColumn(new PrimitiveColumn((PrimitiveParam<?>) param, this));
+			return true;
+		}
+		if (param instanceof ProcedureParam) {
+			if (((ProcedureParam) param).getArgumentsType().size() == 0) {
+				addColumn(new ProcedureColumn((ProcedureParam) param, this));
+				return true;
+			}
+			return false;
+		}
+		return false;
+	}
+
+	public static void transferCellAppeariance(JTable table, JComponent component, boolean isSelected) {
+		if (isSelected) {
+			component.setForeground(table.getSelectionForeground());
+			component.setBackground(table.getSelectionBackground());
+		} else {
+			component.setForeground(table.getForeground());
+			component.setBackground(UIManager.getColor("Button.background"));
+		}
+
 	}
 
Index: java/main/src/main/java/com/framsticks/gui/tree/AbstractNode.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/tree/AbstractNode.java	(revision 99)
+++ java/main/src/main/java/com/framsticks/gui/tree/AbstractNode.java	(revision 100)
@@ -1,3 +1,5 @@
 package com.framsticks.gui.tree;
+
+import com.framsticks.gui.AbstractPanel;
 
 
@@ -9,9 +11,11 @@
 
 	public abstract int getChildCount();
-	public abstract AbstractNode getChild(int number);
-	public abstract int getIndexOfChild(AbstractNode child);
+	public abstract Object getChild(int number);
+	public abstract int getIndexOfChild(Object child);
 
 	public abstract boolean isLeaf();
 	public abstract void render(TreeCellRenderer renderer);
 
+	public abstract AbstractPanel getPanel();
+
 }
Index: java/main/src/main/java/com/framsticks/gui/tree/EmptyNode.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/tree/EmptyNode.java	(revision 99)
+++ java/main/src/main/java/com/framsticks/gui/tree/EmptyNode.java	(revision 100)
@@ -2,4 +2,6 @@
 
 
+import com.framsticks.gui.AbstractPanel;
+import com.framsticks.gui.Frame;
 import com.framsticks.gui.ImageProvider;
 import com.framsticks.params.CompositeParam;
@@ -8,10 +10,12 @@
 
 	protected final CompositeParam param;
+	protected final Frame frame;
 
 	/**
 	 * @param param
 	 */
-	public EmptyNode(CompositeParam param) {
+	public EmptyNode(Frame frame, CompositeParam param) {
 		this.param = param;
+		this.frame = frame;
 	}
 
@@ -22,10 +26,10 @@
 
 	@Override
-	public AbstractNode getChild(int number) {
+	public Object getChild(int number) {
 		return null;
 	}
 
 	@Override
-	public int getIndexOfChild(AbstractNode child) {
+	public int getIndexOfChild(Object child) {
 		return -1;
 	}
@@ -33,17 +37,26 @@
 	@Override
 	public boolean isLeaf() {
-		return true;
+		return false;
 	}
 
 	@Override
 	public void render(TreeCellRenderer renderer) {
-		renderer.setIcon(ImageProvider.loadImage(TreeCellRenderer.findIconName(param)));
+		// TODO Auto-generated method stub
+
+		renderer.setToolTipText("?");
 		renderer.setText(param.getId());
-		renderer.setToolTipText("?");
+		renderer.setIcon(ImageProvider.loadImage(ImageProvider.FOLDER_CLOSED));
+	}
+
+	/**
+	 * @return the param
+	 */
+	public CompositeParam getParam() {
+		return param;
 	}
 
 	@Override
-	public String toString() {
-		return param.toString();
+	public AbstractPanel getPanel() {
+		return frame.getEmptyPanel();
 	}
 
Index: java/main/src/main/java/com/framsticks/gui/tree/MetaNode.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/tree/MetaNode.java	(revision 99)
+++ java/main/src/main/java/com/framsticks/gui/tree/MetaNode.java	(revision 100)
@@ -5,15 +5,25 @@
 
 
+import com.framsticks.gui.AbstractPanel;
+import com.framsticks.gui.Frame;
 import com.framsticks.gui.ImageProvider;
 
 public class MetaNode extends AbstractNode {
 
-	protected List<AbstractNode> children = new LinkedList<>();
+	protected final Frame frame;
+	protected final List<Object> children = new LinkedList<>();
 	protected String name = "meta node";
+
+	/**
+	 * @param frame
+	 */
+	public MetaNode(Frame frame) {
+		this.frame = frame;
+	}
 
 	/**
 	 * @return the children
 	 */
-	public List<AbstractNode> getChildren() {
+	public List<Object> getChildren() {
 		return children;
 	}
@@ -39,10 +49,10 @@
 
 	@Override
-	public AbstractNode getChild(int number) {
+	public Object getChild(int number) {
 		return children.get(number);
 	}
 
 	@Override
-	public int getIndexOfChild(AbstractNode child) {
+	public int getIndexOfChild(Object child) {
 		return children.indexOf(child);
 	}
@@ -65,3 +75,8 @@
 	}
 
+	@Override
+	public AbstractPanel getPanel() {
+		return frame.getEmptyPanel();
+	}
+
 }
Index: java/main/src/main/java/com/framsticks/gui/tree/TreeCellRenderer.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/tree/TreeCellRenderer.java	(revision 99)
+++ java/main/src/main/java/com/framsticks/gui/tree/TreeCellRenderer.java	(revision 100)
@@ -15,9 +15,12 @@
 public class TreeCellRenderer extends DefaultTreeCellRenderer {
 
-	public TreeCellRenderer() {
+	protected final TreeModel treeModel;
 
-		// setOpenIcon(ImageProvider.loadImage(ImageProvider.FOLDER_OPEN));
-		// setClosedIcon(ImageProvider.loadImage(ImageProvider.FOLDER_CLOSED));
-		// setLeafIcon(ImageProvider.loadImage(ImageProvider.NODE));
+
+	/**
+	 * @param treeModel
+	 */
+	public TreeCellRenderer(TreeModel treeModel) {
+		this.treeModel = treeModel;
 	}
 
@@ -35,6 +38,6 @@
 
 		if (!(value instanceof AbstractNode)) {
-			setIcon(ImageProvider.loadImage(ImageProvider.SERVER));
-			setText("framsticks");
+			setText("?");
+			// treeModel.renderTreeObject(Casting.throwCast(TreeNode.class, value), this);
 			return this;
 		}
@@ -92,4 +95,3 @@
 
 
-
 }
Index: java/main/src/main/java/com/framsticks/gui/tree/TreeModel.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/tree/TreeModel.java	(revision 99)
+++ java/main/src/main/java/com/framsticks/gui/tree/TreeModel.java	(revision 100)
@@ -1,32 +1,44 @@
 package com.framsticks.gui.tree;
 
-// import java.util.Enumeration;
+import java.util.Enumeration;
 import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
 
+import javax.annotation.Nullable;
 import javax.swing.event.TreeModelEvent;
 import javax.swing.event.TreeModelListener;
 import javax.swing.tree.TreePath;
 
-import org.apache.log4j.Logger;
-
-
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.LogManager;
+
+import com.framsticks.core.ListChange;
 import com.framsticks.core.Node;
 import com.framsticks.core.Path;
-import com.framsticks.core.Tree;
 import com.framsticks.core.TreeOperations;
 import com.framsticks.gui.Frame;
-import com.framsticks.params.AccessInterface;
+import com.framsticks.params.Access;
+import com.framsticks.params.CompositeParam;
+import com.framsticks.params.EventListener;
+import com.framsticks.params.ListAccess;
+import com.framsticks.params.PrimitiveParam;
+import com.framsticks.params.Util;
+import com.framsticks.params.ValueParam;
+import com.framsticks.params.types.EventParam;
 import com.framsticks.util.FramsticksException;
+import com.framsticks.util.Misc;
 import com.framsticks.util.UnsupportedOperationException;
 import com.framsticks.util.dispatching.FutureHandler;
 import com.framsticks.util.lang.Casting;
 
+import static com.framsticks.core.TreeOperations.*;
+
 public class TreeModel implements javax.swing.tree.TreeModel {
-	private static final Logger log = Logger.getLogger(TreeModel.class);
+	private static final Logger log = LogManager.getLogger(TreeModel.class);
 
 
 	protected List<TreeModelListener> listeners = new LinkedList<>();
+
 
 	protected final Frame frame;
@@ -45,11 +57,11 @@
 
 	@Override
-	public AbstractNode getChild(Object parent, int number) {
-		return Casting.assertCast(AbstractNode.class, parent).getChild(number);
+	public Object getChild(Object parent, int number) {
+		return Casting.throwCast(AbstractNode.class, parent).getChild(number);
 	}
 
 	@Override
 	public int getChildCount(Object parent) {
-		return Casting.assertCast(AbstractNode.class, parent).getChildCount();
+		return Casting.throwCast(AbstractNode.class, parent).getChildCount();
 	}
 
@@ -59,5 +71,5 @@
 			return -1;
 		}
-		return Casting.assertCast(AbstractNode.class, parent).getIndexOfChild(Casting.assertCast(AbstractNode.class, child));
+		return Casting.throwCast(AbstractNode.class, parent).getIndexOfChild(child);
 	}
 
@@ -69,5 +81,5 @@
 	@Override
 	public boolean isLeaf(Object node) {
-		return Casting.assertCast(AbstractNode.class, node).isLeaf();
+		return Casting.throwCast(AbstractNode.class, node).isLeaf();
 	}
 
@@ -85,5 +97,51 @@
 	protected boolean changing = false;
 
-	public void nodeStructureChanged(TreePath treePath) {
+	public void treeNodesInserted(TreeModelEvent event) {
+		assert frame.isActive();
+		try {
+			for (TreeModelListener listener : listeners) {
+				listener.treeNodesInserted(event);
+			}
+		} catch (ArrayIndexOutOfBoundsException e) {
+		}
+	}
+
+	public void treeNodesRemoved(TreeModelEvent event) {
+		assert frame.isActive();
+		try {
+			for (TreeModelListener listener : listeners) {
+				listener.treeNodesRemoved(event);
+			}
+		} catch (ArrayIndexOutOfBoundsException e) {
+		}
+	}
+
+	public void treeNodesChanged(TreeModelEvent event) {
+		try {
+			for (TreeModelListener listener : listeners) {
+				listener.treeNodesChanged(event);
+			}
+		} catch (ArrayIndexOutOfBoundsException e) {
+		}
+	}
+
+	public TreeModelEvent prepareModelEvent(TreePath treePath, int number, TreeNode node) {
+		return new TreeModelEvent(this, treePath, new int[] {number}, new Object[] { node });
+	}
+
+
+	public TreeModelEvent prepareModelEventRegarding(Access access, String id, TreePath treeListPath) {
+
+		int number = Util.getNumberOfCompositeParamChild(access, access.get(id, Object.class));
+		if (number == -1) {
+			log.debug("encountered minor tree inconsistency in {}", treeListPath);
+			return null;
+		}
+		TreeNode node = Casting.throwCast(TreeNode.class, Casting.throwCast(TreeNode.class, treeListPath.getLastPathComponent()).getChild(number));
+		return prepareModelEvent(treeListPath, number, node);
+	}
+
+	public void treeStructureChanged(TreePath treePath) {
+
 		if (treePath == null) {
 			return;
@@ -92,18 +150,24 @@
 
 		changing = true;
-		log.debug("changing: " + treePath);
-		// Enumeration<TreePath> expanded = frame.jtree.getExpandedDescendants(treePath);
+		log.debug("changing structure: {}", treePath);
+		Enumeration<TreePath> expanded = frame.getJtree().getExpandedDescendants(treePath);
 		TreePath selection = frame.getJtree().getSelectionPath();
 
-		for (TreeModelListener listener : listeners) {
-			listener.treeStructureChanged(new TreeModelEvent(this, treePath));
-		}
-		// if (expanded != null) {
-		// 	while (expanded.hasMoreElements()) {
-		// 		TreePath expansion = expanded.nextElement();
-		// 		// log.info("reexpanding: " + expansion);
-		// 		frame.jtree.expandPath(expansion);
-		// 	}
-		// }
+		try {
+			for (TreeModelListener listener : listeners) {
+				listener.treeStructureChanged(new TreeModelEvent(this, treePath));
+			}
+		} catch (ArrayIndexOutOfBoundsException e) {
+		}
+
+
+		if (expanded != null) {
+			while (expanded.hasMoreElements()) {
+				TreePath expansion = expanded.nextElement();
+				// log.info("reexpanding: {}", expansion);
+				frame.getJtree().expandPath(expansion);
+			}
+		}
+
 		if (selection != null) {
 			frame.getJtree().setSelectionPath(selection);
@@ -112,5 +176,9 @@
 	}
 
-	public Path convertToPath(TreePath treePath) {
+	/**
+	 *
+	 * This method may return null on conversion failure, which may happen in highload situations.
+	 */
+	public @Nullable Path convertToPath(TreePath treePath) {
 		final Object[] components = treePath.getPath();
 		assert components[0] == frame.getRootNode();
@@ -128,5 +196,6 @@
 			Node node = treeNode.tryCreateNode();
 			if (node == null) {
-				throw new FramsticksException().msg("failed to recreate path").arg("treePath", treePath);
+				return null;
+				// throw new FramsticksException().msg("failed to recreate path").arg("treePath", treePath);
 			}
 			nodes.add(node);
@@ -137,5 +206,5 @@
 	}
 
-	public TreePath convertToTreePath(Path path) {
+	public TreePath convertToTreePath(Path path, boolean forceComplete) {
 		assert frame.isActive();
 
@@ -143,17 +212,15 @@
 		accumulator.add(getRoot());
 
-		for (AbstractNode r : getRoot().getChildren()) {
+		for (Object r : getRoot().getChildren()) {
 			if (r instanceof TreeNode) {
 				TreeNode root = (TreeNode) r;
 				if (root.getTree() == path.getTree()) {
+					Iterator<Node> n = path.getNodes().iterator();
+					TreeNode treeNode = root;
 					accumulator.add(root);
-
-					Iterator<Node> i = path.getNodes().iterator();
-					i.next();
-					TreeNode treeNode = root;
-
-					while (i.hasNext()) {
-						Node node = i.next();
-						treeNode = treeNode.getTreeNodeForChild(node.getObject());
+					n.next();
+					while (n.hasNext()) {
+						Node node = n.next();
+						treeNode = treeNode.prepareTreeNodeForChild(Path.build().tree(path.getTree()).buildUpTo(path.getNodes(), node).finish());
 						if (treeNode == null) {
 							break;
@@ -161,5 +228,4 @@
 						accumulator.add(treeNode);
 					}
-
 					break;
 				}
@@ -167,4 +233,11 @@
 		}
 		return new TreePath(accumulator.toArray());
+	}
+
+	/**
+	 * @return the listeners
+	 */
+	public List<TreeModelListener> getListeners() {
+		return listeners;
 	}
 
@@ -180,5 +253,5 @@
 			return;
 		}
-		AccessInterface access = TreeOperations.bindAccess(path);
+		Access access = TreeOperations.bindAccess(path);
 
 		int count = access.getCompositeParamCount();
@@ -193,5 +266,5 @@
 			return;
 		}
-		if (path.isResolved() && !reload) {
+		if (!reload && path.isResolved() && isMarked(path.getTree(), path.getTopObject(), FETCHED_MARK, false)) {
 			return;
 		}
@@ -199,13 +272,16 @@
 			@Override
 			protected void result(Path result) {
-				final TreePath treePath = convertToTreePath(result);
-
-				nodeStructureChanged(treePath);
-				frame.updatePanelIfIsLeadSelection(treePath, result);
+				final TreePath treePath = convertToTreePath(result, true);
+
+
+				if (treePath != null) {
+					treeStructureChanged(treePath);
+					frame.updatePanelIfIsLeadSelection(result);
+				}
 			}
 		});
 	}
 
-	public void chooseTreeNode(final TreePath treePath) {
+	public void expandTreeNode(TreePath treePath) {
 		assert frame.isActive();
 		if (treePath == null) {
@@ -215,15 +291,154 @@
 			return;
 		}
-
 		Path path = convertToPath(treePath);
 		if (path == null) {
 			return;
 		}
+		loadChildren(path.assureResolved(), false);
+	}
+
+	public void chooseTreeNode(final TreePath treePath) {
+		assert frame.isActive();
+		if (treePath == null) {
+			return;
+		}
+		if (isChanging()) {
+			return;
+		}
+
+		Path path = convertToPath(treePath);
+		if (path == null) {
+			return;
+		}
 		path = path.assureResolved();
-		final Tree tree = path.getTree();
-
-		frame.getTreeAtFrames().get(tree).useOrCreatePanel(treePath);
-		loadChildren(path, false);
-
-	}
+
+		log.debug("choosing {}", path);
+		frame.showPanelForTreePath(treePath);
+		loadPath(path, false);
+
+	}
+
+
+	protected void registerForEventParam(final TreeNode treeNode, Path path, final EventParam eventParam, ValueParam valueParam) {
+		/** TODO make this listener not bind hold the reference to this TreeNode, maybe hold WeakReference internally */
+		if (valueParam instanceof PrimitiveParam) {
+
+			treeNode.tryAddListener(path, eventParam, Object.class, new EventListener<Object>() {
+				@Override
+				public void action(Object argument) {
+					loadPath(treeNode.assurePath(), true);
+				}
+			});
+
+		} else if (valueParam instanceof CompositeParam) {
+
+			final CompositeParam compositeParam = (CompositeParam) valueParam;
+
+			treeNode.tryAddListener(path, eventParam, ListChange.class, new EventListener<ListChange>() {
+				@Override
+				public void action(ListChange listChange) {
+					assert treeNode.getTree().isActive();
+
+					Path parentPath = treeNode.assurePath();
+					final Path listPath = parentPath.appendParam(compositeParam).tryFindResolution();
+					if (!listPath.isResolved()) {
+						/** that situation is quietly ignored - it may happen if first event comes before the container was resolved */
+						return;
+					}
+
+					log.debug("reacting to change {} in {}", listChange, listPath);
+					final TreePath treeListPath = convertToTreePath(listPath, true);
+					if (treeListPath == null) {
+						throw new FramsticksException().msg("path was not fully converted").arg("path", listPath);
+					}
+
+					if ((listChange.getAction().equals(ListChange.Action.Modify)) && (listChange.getPosition() == -1)) {
+						// get(listPath, future);
+						// treeModel.nodeStructureChanged(treePath);
+						// frame.updatePanelIfIsLeadSelection(treePath, result);
+						return;
+					}
+					final String id = listChange.getBestIdentifier();
+
+					final ListAccess access = (ListAccess) bindAccess(listPath);
+					switch (listChange.getAction()) {
+						case Add: {
+							Path childPath = listPath.appendParam(access.prepareParamFor(id)).tryFindResolution();
+							if (!childPath.isResolved()) {
+								childPath = create(childPath);
+
+								TreeModelEvent event = prepareModelEventRegarding(access, id, treeListPath);
+								if (event != null) {
+									treeNodesInserted(event);
+								} else {
+									treeStructureChanged(treeListPath);
+								}
+								frame.updatePanelIfIsLeadSelection(listPath);
+							}
+
+							listPath.getTree().get(childPath, new FutureHandler<Path>(frame) {
+								@Override
+								protected void result(Path result) {
+									if (!result.isResolved()) {
+										log.warn("inconsistency after addition list change: {}", result);
+									}
+									assert frame.isActive();
+									final TreePath treePath = Misc.throwIfNull(frame.getTreeModel().convertToTreePath(result, true));
+
+									// treeModel.nodeStructureChanged(treePath);
+									frame.updatePanelIfIsLeadSelection(result);
+
+									log.debug("added {}({}) updated {}", id, result, treePath);
+								}
+							});
+							break;
+						}
+						case Remove: {
+
+							TreeModelEvent event = prepareModelEventRegarding(access, id, treeListPath);
+							access.set(id, null);
+							if (event != null) {
+								treeNodesRemoved(event);
+							} else {
+								treeStructureChanged(treeListPath);
+							}
+
+							frame.updatePanelIfIsLeadSelection(listPath);
+
+							break;
+						}
+						case Modify: {
+							Path childPath = listPath.appendParam(access.prepareParamFor(id)).tryResolveIfNeeded();
+							listPath.getTree().get(childPath, new FutureHandler<Path>(frame) {
+								@Override
+								protected void result(Path result) {
+									assert frame.isActive();
+									// final TreePath treePath = frame.getTreeModel().convertToTreePath(result, true);
+
+									TreeModelEvent event = prepareModelEventRegarding(access, id, treeListPath);
+									if (event != null) {
+										treeNodesChanged(event);
+									} else {
+										treeStructureChanged(treeListPath);
+									}
+
+									frame.updatePanelIfIsLeadSelection(listPath);
+									frame.updatePanelIfIsLeadSelection(result);
+								}
+							});
+							break;
+						}
+					}
+				}
+			});
+		}
+
+	}
+
+
+
+	protected final Object createdTag = new Object();
+
+
+
 }
Index: java/main/src/main/java/com/framsticks/gui/tree/TreeNode.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/tree/TreeNode.java	(revision 99)
+++ java/main/src/main/java/com/framsticks/gui/tree/TreeNode.java	(revision 100)
@@ -5,12 +5,8 @@
 import java.util.LinkedList;
 import java.util.List;
-import java.util.concurrent.atomic.AtomicInteger;
-
-import javax.swing.ImageIcon;
-import javax.swing.tree.TreePath;
-
-import org.apache.log4j.Logger;
-
-import com.framsticks.core.ListChange;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
 import com.framsticks.core.Node;
 import com.framsticks.core.Path;
@@ -19,9 +15,9 @@
 import com.framsticks.gui.ImageProvider;
 import com.framsticks.gui.TreeAtFrame;
-import com.framsticks.params.AccessInterface;
+import com.framsticks.gui.TreePanel;
+import com.framsticks.params.Access;
 import com.framsticks.params.CompositeParam;
 import com.framsticks.params.EventListener;
 import com.framsticks.params.FramsClass;
-import com.framsticks.params.PrimitiveParam;
 import com.framsticks.params.ValueParam;
 import com.framsticks.params.types.EventParam;
@@ -32,39 +28,45 @@
 import com.framsticks.util.lang.Casting;
 import com.framsticks.util.lang.Containers;
-import com.framsticks.util.lang.Pair;
 import com.framsticks.util.swing.TooltipConstructor;
+
 import static com.framsticks.core.TreeOperations.*;
 
 public class TreeNode extends AbstractNode {
-	private static final Logger log = Logger.getLogger(TreeNode.class);
-
-
-	protected static final AtomicInteger counter = new AtomicInteger();
+
+	private static final Logger log = LogManager.getLogger(TreeNode.class);
 
 	protected final WeakReference<Object> reference;
+	protected final int hashCode;
+	protected final TreeAtFrame treeAtFrame;
+	protected final String textual;
 	protected final CompositeParam param;
-	protected final TreeAtFrame treeAtFrame;
-	protected final List<Pair<WeakReference<Object>, WeakReference<TreeNode>>> children = new LinkedList<>();
-	protected final int number;
-	protected final String textualPath;
-	protected final ImageIcon imageIcon;
-	protected final TreeModel treeModel;
-
-	protected final List<EventListener<?>> listeners = new LinkedList<>();
-
+	protected TreePanel panel;
+
+	public TreeModel getTreeModel() {
+		return treeAtFrame.getFrame().getTreeModel();
+	}
+
+	/**
+	 * @param reference
+	 */
 	public TreeNode(TreeAtFrame treeAtFrame, Path path) {
 		path.assureResolved();
-		this.textualPath = path.getTextual();
+
+		this.reference = new WeakReference<Object>(path.getTopObject());
+		this.textual = path.getTextual();
+		this.treeAtFrame = treeAtFrame;
 		this.param = path.getTop().getParam();
-		this.treeAtFrame = treeAtFrame;
-		this.treeModel = treeAtFrame.getFrame().getTreeModel();
-		this.imageIcon = ImageProvider.loadImage(TreeCellRenderer.findIconName(param));
-
-		reference = new WeakReference<Object>(path.getTop().getObject());
-		number = counter.getAndIncrement();
+		hashCode = System.identityHashCode(path.getTopObject());
+
+		if (getTree().getSideNote(path.getTopObject(), getTreeModel().createdTag, Object.class) == getTreeModel().createdTag) {
+			return;
+		}
+
+		// path.getTree().putSideNote(path.getTopObject(), Textual.class, path.getTextual());
+		path.getTree().putSideNote(path.getTopObject(), getTreeModel().createdTag, getTreeModel().createdTag);
 
 		/** Iterate over all EventParams and for matching ValueParams register listeners. */
-		if (param instanceof ObjectParam) {
-			AccessInterface access = bindAccess(path);
+		if (path.getTop().getParam() instanceof ObjectParam) {
+			Access access = bindAccess(path);
 			FramsClass framsClass = access.getFramsClass();
 			for (EventParam eventParam : Containers.filterInstanceof(framsClass.getParamEntries(), EventParam.class)) {
@@ -77,139 +79,20 @@
 					continue;
 				}
-				registerForEventParam(path, eventParam, valueParam);
-			}
-		}
-	}
-
-	protected <A> void tryAddListener(final Path path, final EventParam eventParam, Class<A> argumentType, final EventListener<A> listener) {
-		treeAtFrame.getTree().addListener(path, eventParam, listener, argumentType, new FutureHandler<Void>(treeAtFrame.getFrame()) {
-			@Override
-			protected void result(Void result) {
-				assert treeAtFrame.getFrame().isActive();
-				log.debug("registered gui listener for " + eventParam + " at " + path);
-				listeners.add(listener);
-			}
-		});
-	}
-
-	protected void registerForEventParam(Path path, EventParam eventParam, ValueParam valueParam) {
-		/** TODO make this listener not bind hold the reference to this TreeNode, maybe hold WeakReference internally */
-		if (valueParam instanceof PrimitiveParam) {
-
-			tryAddListener(path, eventParam, Object.class, new EventListener<Object>() {
-				@Override
-				public void action(Object argument) {
-					treeModel.loadPath(assurePath(), true);
-				}
-			});
-
-		} else if (valueParam instanceof CompositeParam) {
-
-			final CompositeParam compositeParam = (CompositeParam) valueParam;
-
-			tryAddListener(path, eventParam, ListChange.class, new EventListener<ListChange>() {
-				@Override
-				public void action(ListChange listChange) {
-					assert treeAtFrame.getTree().isActive();
-
-					final Path listPath = assurePath().appendParam(compositeParam).tryFindResolution().assureResolved();
-					log.debug("reacting to change " + listChange + " in " + listPath);
-
-					if ((listChange.getAction().equals(ListChange.Action.Modify)) && (listChange.getPosition() == -1)) {
-						// get(listPath, future);
-						return;
-					}
-					final String id = listChange.getBestIdentifier();
-
-					AccessInterface access = bindAccess(listPath);
-					switch (listChange.getAction()) {
-						case Add: {
-							tryGet(listPath.getTree(), Path.appendString(listPath.getTextual(), id), new FutureHandler<Path>(treeAtFrame.getFrame()) {
-								@Override
-								protected void result(Path result) {
-									final Frame frame = treeAtFrame.getFrame();
-									assert frame.isActive();
-									final TreePath treePath = frame.getTreeModel().convertToTreePath(listPath);
-									treeModel.nodeStructureChanged(treePath);
-									frame.updatePanelIfIsLeadSelection(treePath, listPath);
-									log.debug("added " + id + "(" + result + ") updated " + treePath);
-								}
-							});
-							break;
-						}
-						case Remove: {
-							access.set(id, null);
-							Frame frame = treeAtFrame.getFrame();
-							treeModel.nodeStructureChanged(frame.getTreeModel().convertToTreePath(listPath));
-							break;
-						}
-						case Modify: {
-							tryGet(listPath.getTree(), Path.appendString(listPath.getTextual(), id), new FutureHandler<Path>(treeAtFrame.getFrame()) {
-								@Override
-								protected void result(Path result) {
-									final Frame frame = treeAtFrame.getFrame();
-									assert frame.isActive();
-									final TreePath treePath = frame.getTreeModel().convertToTreePath(result);
-									treeModel.nodeStructureChanged(treePath);
-									frame.updatePanelIfIsLeadSelection(treePath, listPath);
-								}
-							});
-							break;
-						}
-					}
-				}
-			});
-		}
-
-	}
-
-	protected Path assurePath() {
-		return Path.to(treeAtFrame.getTree(), textualPath).assureResolved();
-	}
-
-	public Node tryCreateNode() {
-		Object child = lock();
-		if (child == null) {
-			return null;
-		}
-		return Path.to(treeAtFrame.getTree(), textualPath).assureResolved().getTop();
-	}
-
-	@Override
-	public int getChildCount() {
-		Object referent = lock();
-		if (referent == null) {
-			return 0;
-		}
-		AccessInterface access = bindAccessFor(referent);
-		final int count = access.getCompositeParamCount();
-		return count;
-	}
-
-	public TreeNode getTreeNodeForChild(Object child) {
-		Iterator<Pair<WeakReference<Object>, WeakReference<TreeNode>>> i = children.iterator();
-		while (i.hasNext()) {
-			Pair<WeakReference<Object>, WeakReference<TreeNode>> p = i.next();
-			Object object = p.first.get();
-			if (object == null) {
-				i.remove();
-				continue;
-			}
-			TreeNode treeNode = p.second.get();
-			if (treeNode == null) {
-				i.remove();
-				continue;
-			}
-			if (object == child) {
-				return treeNode;
-			}
-		}
-		return null;
-
-		// WeakReference<GuiTreeNode> resultReference = children.get(child);
-		// if (resultReference == null) {
-		//	return null;
-		// }
-		// return resultReference.get();
+				getTreeModel().registerForEventParam(this, path, eventParam, valueParam);
+			}
+		}
+	}
+
+	@Override
+	public int hashCode() {
+		return hashCode;
+	}
+
+	@Override
+	public boolean equals(Object obj) {
+		if (obj instanceof TreeNode) {
+			return lock() == ((TreeNode) obj).lock();
+		}
+		return false;
 	}
 
@@ -220,5 +103,6 @@
 			throw new FramsticksException().msg("invalid state - missing referent");
 		}
-		AccessInterface access = bindAccessFor(referent);
+		Tree tree = getTree();
+		Access access = bindAccessForTreeObject(referent);
 
 		final int count = access.getCompositeParamCount();
@@ -227,22 +111,33 @@
 		}
 
+		/** textual path may be not valid anymore*/
 		CompositeParam childParam = access.getCompositeParam(number);
-		Object child = access.get(childParam, Object.class);
-		if (child == null) {
-			log.debug("returning dummy node for " + childParam + " in " + referent);
-			return new EmptyNode(childParam);
-		}
-
-		TreeNode result = getTreeNodeForChild(child);
-		if (result != null) {
-			return result;
-		}
-		Path path = Path.to(treeAtFrame.getTree(), Path.appendString(textualPath, childParam.getId())).assureResolved();
-		result = new TreeNode(treeAtFrame, path);
-
-		children.add(Pair.make(new WeakReference<Object>(child), new WeakReference<TreeNode>(result)));
-
-		return result;
-
+
+		try {
+			Path path = Path.to(tree, getTextual()).appendParam(childParam).tryFindResolution();
+			if (!path.isResolved()) {
+				path = create(path);
+			}
+			return prepareTreeNodeForChild(path);
+		} catch (FramsticksException e) {
+		}
+		return new EmptyNode(getFrame(), childParam);
+
+	}
+
+	public TreeNode prepareTreeNodeForChild(Path path) {
+		assert path.getTree() == getTree();
+		Object parent = lock();
+		Iterator<Node> n = path.getNodes().iterator();
+		while (n.hasNext()) {
+			if (n.next().getObject() == parent) {
+				break;
+			}
+		}
+		if (!n.hasNext()) {
+			return null;
+			// throw new FramsticksException().msg("tree node is not on path (or is last)").arg("path", path).arg("node", this);
+		}
+		return new TreeNode(treeAtFrame, path);
 	}
 
@@ -252,5 +147,5 @@
 
 	@Override
-	public int getIndexOfChild(AbstractNode child) {
+	public int getIndexOfChild(Object child) {
 		final TreeNode treeChild = Casting.tryCast(TreeNode.class, child);
 		if (treeChild == null) {
@@ -262,5 +157,5 @@
 			return -1;
 		}
-		final AccessInterface access = bindAccessFor(parentObject);
+		final Access access = bindAccessForTreeObject(parentObject);
 
 		final int count = access.getCompositeParamCount();
@@ -271,30 +166,51 @@
 			}
 		}
-		log.debug(child + " not found in " + this);
+		log.debug("{} not found in {}", child, this);
 		return -1;
 	}
 
-	/**
-	 * @return the param
-	 */
-	public CompositeParam getParam() {
-		return param;
-	}
-
-	/**
-	 * @return the tree
-	 */
+	public Frame getFrame() {
+		return getTreeAtFrame().getFrame();
+	}
+
+	public TreeAtFrame getTreeAtFrame() {
+		return treeAtFrame;
+	}
+
 	public Tree getTree() {
-		return treeAtFrame.getTree();
-	}
-
+		return getTreeAtFrame().getTree();
+	}
+
+	protected Path assurePath() {
+		return Path.to(getTree(), getTextual()).assureResolved();
+	}
 
 	@Override
 	public String toString() {
-		return param.toString();
-	}
-
-	public static Node tryGetNode(TreePath treePath) {
-		return Casting.throwCast(TreeNode.class, treePath.getLastPathComponent()).tryCreateNode();
+		return getTextual();
+	}
+
+	public Node tryCreateNode() {
+		Object child = lock();
+		if (child == null) {
+			return null;
+		}
+		String textual = getTextual();
+		Path path = Path.tryTo(getTree(), textual);
+		if (path.isResolved(textual)) {
+			return path.getTop();
+		}
+		return null;
+	}
+
+	@Override
+	public int getChildCount() {
+		Object referent = lock();
+		if (referent == null) {
+			return 0;
+		}
+		Access access = bindAccessForTreeObject(referent);
+		final int count = access.getCompositeParamCount();
+		return count;
 	}
 
@@ -305,26 +221,32 @@
 			return true;
 		}
-		return bindAccessFor(referent).getCompositeParamCount() == 0;
-	}
-
-	protected AccessInterface bindAccessFor(Object child) {
-		return treeAtFrame.getTree().prepareAccess(param).select(child);
+		return bindAccessForTreeObject(referent).getCompositeParamCount() == 0;
+	}
+
+	protected Access bindAccessForTreeObject(Object child) {
+		return bindAccessFromSideNote(getTree(), child);
 	}
 
 	@Override
 	public void render(TreeCellRenderer renderer) {
+
+		Object child = lock();
+		if (child == null) {
+			renderer.setToolTipText("?");
+			renderer.setText("?");
+			renderer.setIcon(ImageProvider.loadImage(ImageProvider.FOLDER_CLOSED));
+			return;
+		}
+		Access access = bindAccessForTreeObject(child);
+		CompositeParam param = getTree().getSideNote(child, CompositeParam.class, CompositeParam.class);
 		String name = param.getId();
 
-		Object child = lock();
-		if (child != null) {
-			AccessInterface access = bindAccessFor(child);
-
-			StringParam nameParam = Casting.tryCast(StringParam.class, access.getParam("name"));
-
-			if (nameParam != null) {
-				name = access.get(nameParam, String.class);
-			}
-
-			renderer.setToolTipText(new TooltipConstructor()
+		StringParam nameParam = Casting.tryCast(StringParam.class, access.getParam("name"));
+
+		if (nameParam != null) {
+			name = access.get(nameParam, String.class);
+		}
+
+		renderer.setToolTipText(new TooltipConstructor()
 				.append("frams", access.getId())
 				.append("java", child.getClass().getCanonicalName())
@@ -333,16 +255,50 @@
 				.append("id", param.getId())
 				.append("object", Integer.toHexString(System.identityHashCode(child)))
-				.append("number", number)
-				.append("textual path", textualPath)
+				.append("size", access.getCompositeParamCount())
 				.build());
-		} else {
-			renderer.setToolTipText(new TooltipConstructor()
-				.append("param", param)
-				.append("textual path", textualPath)
-				.build());
-		}
+
+		renderer.setIcon(ImageProvider.loadImage(TreeCellRenderer.findIconName(param)));
 		renderer.setText(name);
-		renderer.setIcon(imageIcon);
-
+	}
+
+	// public static class Textual {
+	// }
+
+	public String getTextual() {
+		return textual;
+		// return getTree().getSideNote(lock(), Textual.class, String.class);
+	}
+
+	protected final Object listenersTag = new Object();
+
+	public List<EventListener<?>> getListeners() {
+		@SuppressWarnings("unchecked")
+		List<EventListener<?>> result = getTree().getSideNote(lock(), listenersTag, List.class);
+		if (result == null) {
+			result = new LinkedList<>();
+			getTree().putSideNote(lock(), listenersTag, result);
+		}
+
+		return result;
+	}
+
+	protected <A> void tryAddListener(final Path path, final EventParam eventParam, Class<A> argumentType, final EventListener<A> listener) {
+		getTree().addListener(path, eventParam, listener, argumentType, new FutureHandler<Void>(getFrame()) {
+			@Override
+			protected void result(Void result) {
+				assert getFrame().isActive();
+				log.debug("registered gui listener for {} at {}", eventParam, path);
+				getListeners().add(listener);
+			}
+		});
+	}
+
+	@Override
+	public TreePanel getPanel() {
+		if (panel != null) {
+			return panel;
+		}
+		panel = getTreeAtFrame().preparePanel(param);
+		return panel;
 	}
 
Index: java/main/src/main/java/com/framsticks/gui/windows/ServerLogFrame.java
===================================================================
--- java/main/src/main/java/com/framsticks/gui/windows/ServerLogFrame.java	(revision 99)
+++ java/main/src/main/java/com/framsticks/gui/windows/ServerLogFrame.java	(revision 100)
@@ -2,5 +2,5 @@
 
 import com.framsticks.gui.ImageProvider;
-import org.apache.log4j.Logger;
+import org.apache.logging.log4j.LogManager;
 
 import javax.swing.*;
@@ -85,5 +85,5 @@
 			if (popUp && !this.isVisible())
 				this.setVisible(true);
-			Logger.getLogger(ServerLogFrame.class).error(
+			LogManager.getLogger(ServerLogFrame.class).error(
 					"level " + level + " class " + clazz + " function "
 							+ function + " msg " + message);
Index: java/main/src/main/java/com/framsticks/hosting/Cli.java
===================================================================
--- java/main/src/main/java/com/framsticks/hosting/Cli.java	(revision 99)
+++ java/main/src/main/java/com/framsticks/hosting/Cli.java	(revision 100)
@@ -4,5 +4,6 @@
 import java.util.TreeMap;
 
-import org.apache.log4j.Logger;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.LogManager;
 
 import com.framsticks.communication.Response;
@@ -20,5 +21,5 @@
 public class Cli {
 	private static final Logger log =
-		Logger.getLogger(Cli.class);
+		LogManager.getLogger(Cli.class);
 
 
@@ -39,5 +40,5 @@
 
 	public void addListener(Path path, EventParam param, String pathPrefix, ServerSideResponseFuture responseFuture) {
-		log.debug("adding listener for " + path + ": " + param);
+		log.debug("adding listener for {}: {}", path, param);
 
 		final CliEvent event = new CliEvent();
@@ -53,5 +54,5 @@
 			@Override
 			public void action(Object argument) {
-				log.debug("registered event " + event + " happened with " + argument);
+				log.debug("registered event {} happened with {}", event, argument);
 
 				client.connection.sendFile(
Index: java/main/src/main/java/com/framsticks/hosting/CliEvent.java
===================================================================
--- java/main/src/main/java/com/framsticks/hosting/CliEvent.java	(revision 99)
+++ java/main/src/main/java/com/framsticks/hosting/CliEvent.java	(revision 100)
@@ -56,4 +56,9 @@
 
 	@ParamAnnotation
+	public String getUid() {
+		return id;
+	}
+
+	@ParamAnnotation
 	public String getName() {
 		return id;
Index: java/main/src/main/java/com/framsticks/hosting/ClientAtServer.java
===================================================================
--- java/main/src/main/java/com/framsticks/hosting/ClientAtServer.java	(revision 99)
+++ java/main/src/main/java/com/framsticks/hosting/ClientAtServer.java	(revision 100)
@@ -81,7 +81,7 @@
 		rootTree.getRegistry().registerAndBuild(CliEvent.class);
 
-		AccessInterface access = new PropertiesAccess(rootFramsClass);
-
-		root = access.createAccessee();
+		Access access = new PropertiesAccess(rootFramsClass);
+
+		root = createAccessee(rootTree, access);
 		access.select(root);
 		access.set(id, treeRootObject);
@@ -112,5 +112,5 @@
 	}
 
-	public static File printToFile(String path, AccessInterface access) {
+	public static File printToFile(String path, Access access) {
 		ListSink sink = new ListSink();
 		access.save(sink);
@@ -128,6 +128,6 @@
 				}
 
-				// final AccessInterface access = tree.prepareAccess(path);
-				final AccessInterface access = bindAccess(path);
+				// final Access access = tree.prepareAccess(path);
+				final Access access = bindAccess(path);
 
 				if (request instanceof GetRequest) {
Index: java/main/src/main/java/com/framsticks/hosting/Server.java
===================================================================
--- java/main/src/main/java/com/framsticks/hosting/Server.java	(revision 99)
+++ java/main/src/main/java/com/framsticks/hosting/Server.java	(revision 100)
@@ -1,6 +1,7 @@
 package com.framsticks.hosting;
 
-import org.apache.log4j.Level;
-import org.apache.log4j.Logger;
+import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.LogManager;
 
 import com.framsticks.core.Tree;
@@ -28,5 +29,5 @@
 public class Server extends AbstractJoinable implements JoinableParent {
 
-	private final static Logger log = Logger.getLogger(Server.class);
+	private final static Logger log = LogManager.getLogger(Server.class);
 
 	protected int port;
@@ -131,5 +132,5 @@
 					final Socket socket = acceptSocket.accept();
 					assert socket != null;
-					log.debug("accepted socket: " + socket.getInetAddress().getHostAddress());
+					log.debug("accepted socket: {}", socket.getInetAddress().getHostAddress());
 					hosted.dispatch(new RunAt<Tree>(this) {
 						@Override
@@ -137,9 +138,9 @@
 							ClientAtServer client = new ClientAtServer(Server.this, socket);
 							clients.add(client);
-							log.info("client connected: " + client);
+							log.info("client connected: {}", client);
 						}
 					});
 				} catch (IOException e) {
-					log.log((isRunning() ? Level.ERROR : Level.DEBUG), "failed to accept socket: " + e);
+					log.log((isRunning() ? Level.ERROR : Level.DEBUG), "failed to accept socket: {}", e);
 				}
 				acceptNext();
@@ -154,9 +155,9 @@
 				try {
 					acceptSocket.bind(new InetSocketAddress(port));
-					log.debug("started accepting on port " + port);
+					log.debug("started accepting on port {}", port);
 					acceptNext();
 					return;
 				} catch (IOException e) {
-					log.warn("failed to accept on port " + port + " (repeating): " + e);
+					log.warn("failed to accept on port {} (repeating): ", port, e);
 				}
 				tryBind(1000);
@@ -201,5 +202,5 @@
 	//	} catch (ClassNotFoundException ignored) {
 	//	} catch (ConstructionException e) {
-	//		log.error("failed to use info from cache: " + e);
+	//		log.error("failed to use info from cache: {}", e);
 	//	}
 
@@ -213,5 +214,5 @@
 	//	FramsClass framsClass = getInfoFromCache(path.getTop().getObject().getClass().getCanonicalName());
 	//	if (framsClass == null) {
-	//		log.error("failed to create frams class for: " + path.getTop().getObject().getClass());
+	//		log.error("failed to create frams class for: {}", path.getTop().getObject().getClass());
 	//		future.result(null, new Exception());
 	//		return;
Index: java/main/src/main/java/com/framsticks/model/Genotype.java
===================================================================
--- java/main/src/main/java/com/framsticks/model/Genotype.java	(revision 99)
+++ java/main/src/main/java/com/framsticks/model/Genotype.java	(revision 100)
@@ -5,9 +5,9 @@
 
 
-// import org.apache.log4j.Logger;
+// import org.apache.logging.log4j.Logger;
 
 @FramsClassAnnotation
 public class Genotype extends Model {
-	// private final static Logger log = Logger.getLogger(Genotype.class);
+	// private final static Logger log = LogManager.getLogger(Genotype.class);
 
 	@ParamAnnotation
@@ -87,5 +87,5 @@
 	public double getStrsiz() { return getNumparts(); }
 	@ParamAnnotation
-	public void setStrsiz(double strsiz) { setNumparts(strsiz); }
+	public void setStrsiz(double strsiz) {}
 
 
@@ -93,5 +93,5 @@
 	public double getStrjoints() { return getNumjoints(); }
 	@ParamAnnotation
-	public void setStrjoints(double strjoints) { setNumjoints(strjoints); }
+	public void setStrjoints(double strjoints) {}
 
 
@@ -99,5 +99,5 @@
 	public double getNnsiz() { return getNumneurons(); }
 	@ParamAnnotation
-	public void setNnsiz(double nnsiz) { setNumneurons(nnsiz); }
+	public void setNnsiz(double nnsiz) {}
 
 
Index: java/main/src/main/java/com/framsticks/model/Model.java
===================================================================
--- java/main/src/main/java/com/framsticks/model/Model.java	(revision 99)
+++ java/main/src/main/java/com/framsticks/model/Model.java	(revision 100)
@@ -3,5 +3,4 @@
 import com.framsticks.params.annotations.FramsClassAnnotation;
 import com.framsticks.params.annotations.ParamAnnotation;
-import com.framsticks.util.lang.Containers;
 
 import java.util.ArrayList;
@@ -48,9 +47,9 @@
 	//this is impossible to use, because numparts field is marked as readonly
 	@ParamAnnotation
-	public void setNumparts(double numparts) { Containers.resizeList(parts, (int) (double) numparts); }
+	public void setNumparts(double numparts) {}
 	@ParamAnnotation
-	public void setNumjoints(double numjoints) { Containers.resizeList(joints, (int)(double)numjoints); }
+	public void setNumjoints(double numjoints) {}
 	@ParamAnnotation
-	public void setNumneurons(double numneurons) { Containers.resizeList(neuroDefinitions, (int)(double)numneurons); }
+	public void setNumneurons(double numneurons) {}
 
 	public List<Part> getParts() { return parts; }
Index: java/main/src/main/java/com/framsticks/model/ModelBuilder.java
===================================================================
--- java/main/src/main/java/com/framsticks/model/ModelBuilder.java	(revision 99)
+++ java/main/src/main/java/com/framsticks/model/ModelBuilder.java	(revision 100)
@@ -35,5 +35,5 @@
 			}
 			F0Parser parser = new F0Parser(schema, stream);
-			components.addAll(Util.stripAccessInterface(parser.parse(), ModelComponent.class));
+			components.addAll(Util.stripAccess(parser.parse(), ModelComponent.class));
 		}
 		return build();
Index: java/main/src/main/java/com/framsticks/params/Access.java
===================================================================
--- java/main/src/main/java/com/framsticks/params/Access.java	(revision 100)
+++ java/main/src/main/java/com/framsticks/params/Access.java	(revision 100)
@@ -0,0 +1,88 @@
+package com.framsticks.params;
+
+
+import com.framsticks.params.types.EventParam;
+import com.framsticks.params.types.ProcedureParam;
+
+
+/**
+ * The Interface Access. It's the most general class for storing data in
+ * 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)
+ */
+public interface Access {
+
+	Param getParam(int i);
+
+	Param getParam(String id);
+
+	String getId();
+
+	int getParamCount();
+
+	Object call(String id, Object[] arguments);
+
+	Object call(ProcedureParam param, Object[] arguments);
+
+	<T> T get(int i, Class<T> type);
+
+	<T> T get(String id, Class<T> type);
+
+	<T> T get(ValueParam param, Class<T> type);
+
+	<T> int set(int i, T value);
+
+	<T> int set(String id, T value);
+
+	<T> int set(ValueParam param, T value);
+
+	void reg(EventParam param, EventListener<?> listener);
+
+	void regRemove(EventParam param, EventListener<?> listener);
+
+	void setDefault(boolean numericOnly);
+
+	void setDefault(int i, boolean numericOnly);
+
+	void setMin();
+
+	void setMin(int i);
+
+	void setMax();
+
+	void setMax(int i);
+
+	void save(SinkInterface sink);
+
+	void load(SourceInterface stream);
+
+	/**
+	 * Removes all the properties values.
+	 */
+	void clearValues();
+
+	Access select(Object object);
+
+	Object getSelected();
+
+	Access cloneAccess() throws ConstructionException;
+
+	Object createAccessee();
+
+	Iterable<Param> getParams();
+
+	FramsClass getFramsClass();
+
+	void tryAutoAppend(Object object);
+
+	int getCompositeParamCount();
+
+	CompositeParam getCompositeParam(int number);
+
+	ParamBuilder buildParam(ParamBuilder builder);
+
+
+}
Index: java/main/src/main/java/com/framsticks/params/AccessInterface.java
===================================================================
--- java/main/src/main/java/com/framsticks/params/AccessInterface.java	(revision 99)
+++ 	(revision )
@@ -1,88 +1,0 @@
-package com.framsticks.params;
-
-
-import com.framsticks.params.types.EventParam;
-import com.framsticks.params.types.ProcedureParam;
-
-
-/**
- * The Interface AccessInterface. It's the most general class for storing data in
- * 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)
- */
-public interface AccessInterface {
-
-	Param getParam(int i);
-
-	Param getParam(String id);
-
-	String getId();
-
-	int getParamCount();
-
-	Object call(String id, Object[] arguments);
-
-	Object call(ProcedureParam param, Object[] arguments);
-
-	<T> T get(int i, Class<T> type);
-
-	<T> T get(String id, Class<T> type);
-
-	<T> T get(ValueParam param, Class<T> type);
-
-	<T> int set(int i, T value);
-
-	<T> int set(String id, T value);
-
-	<T> int set(ValueParam param, T value);
-
-	void reg(EventParam param, EventListener<?> listener);
-
-	void regRemove(EventParam param, EventListener<?> listener);
-
-	void setDefault(boolean numericOnly);
-
-	void setDefault(int i, boolean numericOnly);
-
-	void setMin();
-
-	void setMin(int i);
-
-	void setMax();
-
-	void setMax(int i);
-
-	void save(SinkInterface sink);
-
-	void load(SourceInterface stream);
-
-	/**
-	 * Removes all the properties values.
-	 */
-	void clearValues();
-
-	AccessInterface select(Object object);
-
-	Object getSelected();
-
-	AccessInterface cloneAccess() throws ConstructionException;
-
-	Object createAccessee();
-
-	Iterable<Param> getParams();
-
-	FramsClass getFramsClass();
-
-	void tryAutoAppend(Object object);
-
-	int getCompositeParamCount();
-
-	CompositeParam getCompositeParam(int number);
-
-	ParamBuilder buildParam(ParamBuilder builder);
-
-
-}
Index: java/main/src/main/java/com/framsticks/params/ArrayListAccess.java
===================================================================
--- java/main/src/main/java/com/framsticks/params/ArrayListAccess.java	(revision 99)
+++ java/main/src/main/java/com/framsticks/params/ArrayListAccess.java	(revision 100)
@@ -9,4 +9,5 @@
 import java.util.List;
 import java.util.ListIterator;
+import static com.framsticks.params.SetStateFlags.*;
 
 /**
@@ -18,5 +19,5 @@
 
 
-	public ArrayListAccess(AccessInterface elementAccess) {
+	public ArrayListAccess(Access elementAccess) {
 		super(elementAccess);
 	}
@@ -76,8 +77,24 @@
 	@Override
 	public <T> int set(int i, T value) {
-		while (i >= list.size()) {
-			list.add(null);
+		if (value != null) {
+			while (i >= list.size()) {
+				list.add(null);
+			}
+			list.set(i, value);
+			return 0;
 		}
-		list.set(i, value);
+		if (i >= list.size()) {
+			return PSET_HITMAX;
+		}
+		list.remove(i);
+		// for (int j = i + 1; j < list.size(); ++j) {
+		//	if (list.get(j) != null) {
+		//		list.set(i, null);
+		//		return 0;
+		//	}
+		// }
+		// while (list.size() > i) {
+		//	list.remove(i);
+		// }
 		return 0;
 	}
@@ -107,5 +124,5 @@
 	@Override
 	public ArrayListAccess select(Object object) {
-		list = (List<Object>) object;
+		list = Util.selectObjectForAccess(this, object, List.class);
 		return this;
 	}
Index: java/main/src/main/java/com/framsticks/params/CompositeParam.java
===================================================================
--- java/main/src/main/java/com/framsticks/params/CompositeParam.java	(revision 99)
+++ java/main/src/main/java/com/framsticks/params/CompositeParam.java	(revision 100)
@@ -28,5 +28,5 @@
 	}
 
-	public abstract AccessInterface prepareAccessInterface(AccessInterface access);
+	public abstract Access prepareAccess(Access access);
 
 	public abstract String computeAccessId();
Index: java/main/src/main/java/com/framsticks/params/FramsClass.java
===================================================================
--- java/main/src/main/java/com/framsticks/params/FramsClass.java	(revision 99)
+++ java/main/src/main/java/com/framsticks/params/FramsClass.java	(revision 100)
@@ -13,5 +13,6 @@
 import javax.annotation.concurrent.Immutable;
 
-import org.apache.log4j.Logger;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.LogManager;
 
 /**
@@ -31,5 +32,5 @@
 public class FramsClass {
 
-	private final static Logger log = Logger.getLogger(FramsClass.class);
+	private final static Logger log = LogManager.getLogger(FramsClass.class);
 
 	protected final String id;
@@ -73,5 +74,5 @@
 		}
 
-		log.trace("created framsclass " + this);
+		log.trace("created framsclass {}", this);
 
 	}
Index: java/main/src/main/java/com/framsticks/params/FramsClassBuilder.java
===================================================================
--- java/main/src/main/java/com/framsticks/params/FramsClassBuilder.java	(revision 99)
+++ java/main/src/main/java/com/framsticks/params/FramsClassBuilder.java	(revision 100)
@@ -14,5 +14,6 @@
 import java.util.Map;
 
-import org.apache.log4j.Logger;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.LogManager;
 
 import com.framsticks.params.annotations.AutoAppendAnnotation;
@@ -29,5 +30,5 @@
 public class FramsClassBuilder implements Builder<FramsClass> {
 	private static final Logger log =
-		Logger.getLogger(FramsClassBuilder.class);
+		LogManager.getLogger(FramsClassBuilder.class);
 
 	public static String getName(FramsClassAnnotation fca, Class<?> javaClass) {
@@ -75,5 +76,5 @@
 			//TODO parametrize this
 			if (map) {
-				b.append(" name");
+				b.append(" uid");
 			}
 
@@ -224,5 +225,5 @@
 		}
 
-		log.debug("building for class " + javaClass);
+		log.debug("building for class {}", javaClass);
 
 		FramsClassAnnotation fca = javaClass.getAnnotation(FramsClassAnnotation.class);
Index: java/main/src/main/java/com/framsticks/params/ListAccess.java
===================================================================
--- java/main/src/main/java/com/framsticks/params/ListAccess.java	(revision 99)
+++ java/main/src/main/java/com/framsticks/params/ListAccess.java	(revision 100)
@@ -7,16 +7,17 @@
 import com.framsticks.params.types.EventParam;
 import com.framsticks.params.types.ProcedureParam;
+import com.framsticks.util.UnimplementedException;
 
 /**
  * @author Piotr Sniegowski
  */
-public abstract class ListAccess implements AccessInterface {
+public abstract class ListAccess implements Access {
 
-	final AccessInterface elementAccess;
+	final Access elementAccess;
 	final String containedTypeName;
 
 	protected final ParamBuilder paramBuilder;
 
-	public ListAccess(AccessInterface elementAccess) {
+	public ListAccess(Access elementAccess) {
 		this.elementAccess = elementAccess;
 		this.containedTypeName = elementAccess.getId();
@@ -66,7 +67,8 @@
 	@Override
 	public void load(SourceInterface stream) {
+		throw new UnimplementedException().msg("load in list access");
 	}
 
-	public AccessInterface getElementAccess() {
+	public Access getElementAccess() {
 		return elementAccess;
 	}
@@ -120,3 +122,7 @@
 		return b.toString();
 	}
+
+	public CompositeParam prepareParamFor(String id) {
+		return paramBuilder.id(id).finish(CompositeParam.class);
+	}
 };
Index: java/main/src/main/java/com/framsticks/params/ParamBuilder.java
===================================================================
--- java/main/src/main/java/com/framsticks/params/ParamBuilder.java	(revision 99)
+++ java/main/src/main/java/com/framsticks/params/ParamBuilder.java	(revision 100)
@@ -10,5 +10,6 @@
 import com.framsticks.util.lang.Strings;
 
-import org.apache.log4j.Logger;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.LogManager;
 
 import java.lang.reflect.InvocationTargetException;
@@ -32,5 +33,5 @@
 @FramsClassAnnotation(name = "prop", id = "prop")
 public class ParamBuilder implements Builder<Param> {
-	private final static Logger log = Logger.getLogger(ParamBuilder.class.getName());
+	private final static Logger log = LogManager.getLogger(ParamBuilder.class.getName());
 
 	private static final String ID_FIELD = "id";
@@ -265,5 +266,5 @@
 		assert type != null;
 
-		log.trace("parsing type: " + type);
+		log.trace("parsing type: {}", type);
 
 		String[] typeSplitted = type.split(" ");
@@ -301,5 +302,5 @@
 							}
 							default: {
-								log.error("unknown type: " + first);
+								log.error("unknown type: {}", first);
 								return this;
 							}
@@ -349,5 +350,5 @@
 		}
 		default: {
-			log.error("unknown type: " + first);
+			log.error("unknown type: {}", first);
 			return this;
 		}
@@ -445,6 +446,5 @@
 
 		if (paramEntryValues.length == 0) {
-			log.warn("field empty or wrong format (" + line
-					+ ") - omitting");
+			log.warn("field empty or wrong format ({}) - omitting", line);
 			return null;
 		}
@@ -464,6 +464,5 @@
 			/** everything is ok, parameters have just finished*/
 		} catch (NumberFormatException ex) {
-			log.warn("wrong format of entry: " + line
-					+ ", omitting");
+			log.warn("wrong format of entry: {}, omitting", line);
 			return null;
 		}
@@ -492,5 +491,5 @@
 				break;
 			default:
-				log.error("unknown field for Param: " + key);
+				log.error("unknown field for Param: {}", key);
 				break;
 		}
Index: java/main/src/main/java/com/framsticks/params/ParamCandidate.java
===================================================================
--- java/main/src/main/java/com/framsticks/params/ParamCandidate.java	(revision 99)
+++ java/main/src/main/java/com/framsticks/params/ParamCandidate.java	(revision 100)
@@ -213,12 +213,12 @@
 			return false;
 		}
-		if (Collection.class.isAssignableFrom(getRawType())) {
-			return false;
-		}
-		if (setter.has()) {
-			return false;
-		}
 		if (field.has()) {
 			return Modifier.isFinal(field.get().getModifiers());
+		}
+		if (setter.has()) {
+			return false;
+		}
+		if (Collection.class.isAssignableFrom(getRawType())) {
+			return false;
 		}
 		return true;
Index: java/main/src/main/java/com/framsticks/params/PropertiesAccess.java
===================================================================
--- java/main/src/main/java/com/framsticks/params/PropertiesAccess.java	(revision 99)
+++ java/main/src/main/java/com/framsticks/params/PropertiesAccess.java	(revision 100)
@@ -76,5 +76,5 @@
 	@Override
 	public PropertiesAccess select(Object object) {
-		this.properties = (Map<String, Object>)object;
+		properties = Util.selectObjectForAccess(this, object, Map.class);
 		return this;
 	}
@@ -116,3 +116,12 @@
 	}
 
+	@Override
+	public String toString() {
+		StringBuilder b = new StringBuilder();
+		b.append(framsClass);
+		if (getSelected() != null) {
+			b.append("(").append(getSelected().size()).append(")");
+		}
+		return b.toString();
+	}
 }
Index: java/main/src/main/java/com/framsticks/params/ReflectionAccess.java
===================================================================
--- java/main/src/main/java/com/framsticks/params/ReflectionAccess.java	(revision 99)
+++ java/main/src/main/java/com/framsticks/params/ReflectionAccess.java	(revision 100)
@@ -14,5 +14,6 @@
 import javax.annotation.concurrent.Immutable;
 
-import org.apache.log4j.Logger;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.LogManager;
 
 import com.framsticks.params.annotations.AutoAppendAnnotation;
@@ -33,5 +34,5 @@
  */
 public class ReflectionAccess extends SimpleAbstractAccess {
-	private final static Logger log = Logger.getLogger(ReflectionAccess.class.getName());
+	private final static Logger log = LogManager.getLogger(ReflectionAccess.class.getName());
 
 	protected final Class<?> javaClass;
@@ -88,5 +89,5 @@
 			}
 
-			log.debug("constructing backend for " + id);
+			log.debug("constructing backend for {}", id);
 			backend = new Backend();
 
@@ -96,5 +97,5 @@
 				for (final ProcedureParam pp : filterInstanceof(framsClass.getParamEntries(), ProcedureParam.class)) {
 					if (!candidates.containsKey(pp.getId())) {
-						log.trace("java class does implement method " + pp);
+						log.trace("java class does implement method {}", pp);
 						continue;
 					}
@@ -114,5 +115,5 @@
 				for (final EventParam ep : filterInstanceof(framsClass.getParamEntries(), EventParam.class)) {
 					if (!candidates.containsKey(ep.getId())) {
-						log.trace("java class does not implement the event param " + ep);
+						log.trace("java class does not implement the event param {}", ep);
 						continue;
 					}
@@ -312,4 +313,7 @@
 				if (s == null) {
 					throw new FramsticksException().msg("trying to set unsettable");
+					// return;
+					// if (value != backend.getters.get(param).get(object, Object.class)) {
+					// }
 				}
 				s.set(object, value);
@@ -412,6 +416,5 @@
 	@Override
 	public ReflectionAccess select(Object object) {
-		assert object == null || javaClass.isInstance(object);
-		this.object = object;
+		this.object = Util.selectObjectForAccess(this, object, javaClass);
 		return this;
 	}
@@ -447,5 +450,5 @@
 			e.printStackTrace();
 		}
-		log.fatal("failed to create reflected object of class " + javaClass.getCanonicalName() + " for frams type " + framsClass.getId());
+		log.fatal("failed to create reflected object of class {} for frams type {}", javaClass.getCanonicalName(), framsClass.getId());
 		return null;
 	}
@@ -459,5 +462,5 @@
 				if (m.getParameterTypes()[0].isAssignableFrom(value.getClass())) {
 					try {
-						log.trace("auto appending with value " + value + " with method " + m);
+						log.trace("auto appending with value {} with method {}", value, m);
 						m.invoke(object, value);
 						return;
@@ -474,4 +477,13 @@
 	}
 
+	@Override
+	public String toString() {
+		StringBuilder b = new StringBuilder();
+		b.append(framsClass);
+		if (getSelected() != null) {
+			b.append("(").append(getSelected()).append(")");
+		}
+		return b.toString();
+	}
 }
 
Index: java/main/src/main/java/com/framsticks/params/Registry.java
===================================================================
--- java/main/src/main/java/com/framsticks/params/Registry.java	(revision 99)
+++ java/main/src/main/java/com/framsticks/params/Registry.java	(revision 100)
@@ -1,5 +1,6 @@
 package com.framsticks.params;
 
-import org.apache.log4j.Logger;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.LogManager;
 
 import com.framsticks.params.annotations.FramsClassAnnotation;
@@ -20,5 +21,5 @@
 @FramsClassAnnotation
 public class Registry {
-	private static final Logger log = Logger.getLogger(Registry.class.getName());
+	private static final Logger log = LogManager.getLogger(Registry.class.getName());
 
 	protected final DoubleMap<String, Class<?>> javaClasses = new DoubleMap<>();
@@ -84,5 +85,5 @@
 	}
 
-	public @Nonnull AccessInterface createAccess(String name, FramsClass framsClass) throws ConstructionException {
+	public @Nonnull Access createAccess(String name, FramsClass framsClass) throws ConstructionException {
 		// assert framsClasses.containsValue(framsClass);
 		if (javaClasses.containsKey(name)) {
@@ -93,7 +94,11 @@
 
 	public FramsClass putFramsClass(FramsClass framsClass) {
-		log.debug("caching info for " + framsClass);
+		log.debug("caching info for {}", framsClass);
 		framsClasses.put(framsClass.getId(), framsClass.getName(), framsClass);
 		return framsClass;
+	}
+
+	public FramsClass getFramsClass(@Nonnull CompositeParam param) {
+		return framsClasses.get(param.getContainedTypeName());
 	}
 
@@ -102,13 +107,13 @@
 	}
 
-	public static @Nonnull AccessInterface wrapAccessWithListIfNeeded(@Nonnull CompositeParam param, @Nonnull AccessInterface access) {
-		return param.prepareAccessInterface(access);
+	public static @Nonnull Access wrapAccessWithListIfNeeded(@Nonnull CompositeParam param, @Nonnull Access access) {
+		return param.prepareAccess(access);
 	}
 
-	public @Nonnull AccessInterface prepareAccess(CompositeParam param) throws ConstructionException {
+	public @Nonnull Access prepareAccess(CompositeParam param) throws ConstructionException {
 		return wrapAccessWithListIfNeeded(param, createAccess(param.getContainedTypeName()));
 	}
 
-	public @Nonnull AccessInterface createAccess(@Nonnull String name) throws ConstructionException {
+	public @Nonnull Access createAccess(@Nonnull String name) throws ConstructionException {
 		try {
 			Strings.assureNotEmpty(name);
Index: java/main/src/main/java/com/framsticks/params/SimpleAbstractAccess.java
===================================================================
--- java/main/src/main/java/com/framsticks/params/SimpleAbstractAccess.java	(revision 99)
+++ java/main/src/main/java/com/framsticks/params/SimpleAbstractAccess.java	(revision 100)
@@ -4,5 +4,6 @@
 import static com.framsticks.util.lang.Containers.filterInstanceof;
 
-import org.apache.log4j.Logger;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.LogManager;
 
 import com.framsticks.params.types.ObjectParam;
@@ -11,6 +12,6 @@
 
 /**
- * The Class SimpleAbstractAccess implements all the methods of AccessInterface
- * which actions can be implemented with usage of {@link AccessInterface} methods
+ * The Class SimpleAbstractAccess implements all the methods of Access
+ * which actions can be implemented with usage of {@link Access} methods
  * or concern schema, which is stored in {@link #framsClass}
  *
@@ -22,7 +23,7 @@
  * @author Piotr Sniegowski
  */
-public abstract class SimpleAbstractAccess implements AccessInterface {
-
-	private final static Logger log = Logger.getLogger(SimpleAbstractAccess.class.getName());
+public abstract class SimpleAbstractAccess implements Access {
+
+	private final static Logger log = LogManager.getLogger(SimpleAbstractAccess.class.getName());
 
 	protected final FramsClass framsClass;
@@ -190,11 +191,10 @@
 	}
 
-	private Entry readEntry(SourceInterface source) {
+	private static Entry readEntry(SourceInterface source) {
 
 		String line;
 		String key = null;
 		StringBuilder value = null;
-		while ((line = source.readLine()) != null)
-		{
+		while ((line = source.readLine()) != null) {
 			if (key == null) {
 				int colonIndex = line.indexOf(':');
@@ -216,19 +216,9 @@
 				value.append(System.getProperty("line.separator"));
 			}
-			if (line.contains("~")) {
-				value.append(line.substring(0, line.indexOf("~")));
-				return new Entry(key, value.toString());
+			if (line.endsWith("~") && !line.endsWith("\\~")) {
+				value.append(line.substring(0, line.length() - 1));
+				return new Entry(key, value.toString().replaceAll("\\\\~", "~"));
 			}
 			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;
@@ -244,17 +234,14 @@
 			Param param = getParam(entry.key);
 			if (param == null) {
-				continue;
+				throw new FramsticksException().msg("param not found in access").arg("name", entry.key).arg("access", this);
 			}
 			if (!(param instanceof ValueParam)) {
-				log.warn("param " + param + " is not a ValueParam");
-				continue;
-			}
-			if ((param.getFlags() & ParamFlags.DONTLOAD) != 0) {
-				log.debug("DontLoad flag was set - not loading...");
-			} else {
+				throw new FramsticksException().msg("param is not a value param").arg("param", param).arg("access", this);
+			}
+			if ((param.getFlags() & ParamFlags.DONTLOAD) == 0) {
 				int retFlags = this.set((ValueParam) param, entry.value);
 				if ((retFlags & (PSET_HITMIN | PSET_HITMAX)) != 0) {
 					String which = ((retFlags & PSET_HITMIN) != 0) ? "small" : "big";
-					log.warn("value of key '" + entry.key + "' was too " + which + ", adjusted");
+					log.warn("value of key '{}' was too {}, adjusted", entry.key, which);
 				}
 			}
@@ -297,13 +284,4 @@
 	}*/
 
-	@Override
-	public String toString() {
-		StringBuilder b = new StringBuilder();
-		b.append(framsClass);
-		if (getSelected() != null) {
-			b.append("(").append(getSelected()).append(")");
-		}
-		return b.toString();
-	}
 
 	@Override
Index: java/main/src/main/java/com/framsticks/params/UniqueListAccess.java
===================================================================
--- java/main/src/main/java/com/framsticks/params/UniqueListAccess.java	(revision 99)
+++ java/main/src/main/java/com/framsticks/params/UniqueListAccess.java	(revision 100)
@@ -7,5 +7,6 @@
 import com.framsticks.util.lang.Casting;
 import com.framsticks.util.lang.Numbers;
-import org.apache.log4j.Logger;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.LogManager;
 
 import java.util.*;
@@ -16,13 +17,15 @@
 public class UniqueListAccess extends ListAccess {
 
-	private static final Logger log = Logger.getLogger(UniqueListAccess.class);
+	private static final Logger log = LogManager.getLogger(UniqueListAccess.class);
 
 	Map<String, Object> map;
 
-	final String uidName;
-
-	public UniqueListAccess(AccessInterface elementAccess, String uidName) {
+	protected final String uidName;
+	protected final Access uidAccess;
+
+	public UniqueListAccess(Access elementAccess, String uidName) {
 		super(elementAccess);
 		this.uidName = uidName;
+		uidAccess = elementAccess.cloneAccess();
 	}
 
@@ -35,13 +38,21 @@
 	}
 
+	/**
+	 * @return the uidName
+	 */
+	public String getUidName() {
+		return uidName;
+	}
+
 	public static class UidComparator implements Comparator<String> {
 
-		protected String name;
+		protected Object description;
+
 
 		/**
-		 * @param name
+		 * @param description
 		 */
-		public UidComparator(String name) {
-			this.name = name;
+		public UidComparator(Object description) {
+			this.description = description;
 		}
 
@@ -65,13 +76,29 @@
 		@Override
 		public String toString() {
-			return "comparator " + name;
-		}
-
-
+			return "comparator " + description;
+		}
+
+
+	}
+
+	public static <T> Map<String, T> createMap(Class<T> type, Object description) {
+		return new TreeMap<String, T>(new UidComparator(description));
+	}
+
+	public static <M, T extends M> int getNumberInMap(Map<String, M> map, T object) {
+		Iterator<Map.Entry<String, M>> iterator = map.entrySet().iterator();
+		int number = 0;
+		while (iterator.hasNext()) {
+			if (iterator.next().getValue() == object) {
+				return number;
+			}
+			++number;
+		}
+		return -1;
 	}
 
 	@Override
 	public Map<String, Object> createAccessee() {
-		return new TreeMap<String, Object>(new UidComparator(elementAccess.toString()));
+		return createMap(Object.class, elementAccess);
 	}
 
@@ -92,5 +119,5 @@
 			return null;
 		}
-		return paramBuilder.id(getUidOf(iterator.next().getValue())).finish(CompositeParam.class);
+		return paramBuilder.id(iterator.next().getKey()).finish(CompositeParam.class);
 	}
 
@@ -110,4 +137,5 @@
 		return paramBuilder.id(id).finish(CompositeParam.class);
 	}
+
 
 	@Override
@@ -156,9 +184,5 @@
 
 	public String getUidOf(Object value) {
-		Object tmp = elementAccess.getSelected();
-		elementAccess.select(value);
-		String uid = elementAccess.get(uidName, String.class);
-		elementAccess.select(tmp);
-		return uid;
+		return uidAccess.select(value).get(uidName, String.class);
 	}
 
@@ -227,6 +251,5 @@
 	@Override
 	public UniqueListAccess select(Object object) {
-		assert (object instanceof Map);
-		map = (Map<String, Object>) object;
+		map = Util.selectObjectForAccess(this, object, Map.class);
 		return this;
 	}
@@ -242,12 +265,12 @@
 	}
 
-	public String computeIdentifierFor(Object selected) {
-		String uid = getUidOf(selected);
-		if (uid == null) {
-			log.error("missing uid field");
-			return null;
-		}
-		return uid;
-	}
+	// public String computeIdentifierFor(Object selected) {
+	//	String uid = getUidOf(selected);
+	//	if (uid == null) {
+	//		log.error("missing uid field");
+	//		return null;
+	//	}
+	//	return uid;
+	// }
 
 	@Override
Index: java/main/src/main/java/com/framsticks/params/Util.java
===================================================================
--- java/main/src/main/java/com/framsticks/params/Util.java	(revision 99)
+++ java/main/src/main/java/com/framsticks/params/Util.java	(revision 100)
@@ -24,7 +24,7 @@
 	}
 
-	public static <T> List<T> stripAccessInterface(List<AccessInterface> accesses, Class<T> type) {
+	public static <T> List<T> stripAccess(List<Access> accesses, Class<T> type) {
 		List<T> result = new ArrayList<T>();
-		for (AccessInterface a : accesses) {
+		for (Access a : accesses) {
 			Object object = a.getSelected();
 			if (!type.isInstance(object)) {
@@ -36,5 +36,5 @@
 	}
 
-	public static int takeAllNonNullValues(AccessInterface to, AccessInterface from) {
+	public static int takeAllNonNullValues(Access to, Access from) {
 		int copied = 0;
 		for (ValueParam f : filterInstanceof(from.getParams(), ValueParam.class)) {
@@ -43,4 +43,7 @@
 				continue;
 			}
+			// if (to.get(f, Object.class) != null) {
+			//	continue;
+			// }
 			to.set(f, v);
 			++copied;
@@ -49,5 +52,5 @@
 	}
 
-	public static int copyExistingParamsTypeSafe(AccessInterface to, AccessInterface from) {
+	public static int copyExistingParamsTypeSafe(Access to, Access from) {
 		int copied = 0;
 		for (ValueParam f : filterInstanceof(from.getParams(), ValueParam.class)) {
@@ -65,3 +68,23 @@
 	}
 
+	public static <T> T selectObjectForAccess(Access access, Object object, Class<T> type) {
+		if (object == null) {
+			return null;
+		}
+		if (!type.isInstance(object)) {
+			throw new FramsticksException().msg("trying to select object of wrong type").arg("object", object).arg("type", object.getClass()).arg("in", access);
+		}
+		return type.cast(object);
+	}
+
+	public static int getNumberOfCompositeParamChild(Access access, Object child) {
+		int count = access.getCompositeParamCount();
+		for (int i = 0; i < count; ++i) {
+			if (access.get(i, Object.class) == child) {
+				return i;
+			}
+		}
+		return -1;
+	}
+
 }
Index: java/main/src/main/java/com/framsticks/params/types/ArrayListParam.java
===================================================================
--- java/main/src/main/java/com/framsticks/params/types/ArrayListParam.java	(revision 99)
+++ java/main/src/main/java/com/framsticks/params/types/ArrayListParam.java	(revision 100)
@@ -1,5 +1,5 @@
 package com.framsticks.params.types;
 
-import com.framsticks.params.AccessInterface;
+import com.framsticks.params.Access;
 import com.framsticks.params.ArrayListAccess;
 import com.framsticks.params.CastFailure;
@@ -7,8 +7,6 @@
 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;
 import java.util.List;
 
@@ -32,5 +30,5 @@
 
 	@Override
-	public AccessInterface prepareAccessInterface(AccessInterface access) {
+	public Access prepareAccess(Access access) {
 		return new ArrayListAccess(access);
 	}
@@ -49,19 +47,20 @@
 		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);
+			// 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<?>>(Casting.tryCast(List.class, oldValue));
+			// return new ReassignResult<List<?>>(list);
 		}
-		if (oldValue != null) {
-			return new ReassignResult<List<?>>(Casting.throwCast(List.class, oldValue));
-		}
+		// if (oldValue != null) {
+		// 	return new ReassignResult<List<?>>(Casting.throwCast(List.class, oldValue));
+		// }
 		return new ReassignResult<List<?>>(Casting.throwCast(List.class, newValue));
 	}
Index: java/main/src/main/java/com/framsticks/params/types/ObjectParam.java
===================================================================
--- java/main/src/main/java/com/framsticks/params/types/ObjectParam.java	(revision 99)
+++ java/main/src/main/java/com/framsticks/params/types/ObjectParam.java	(revision 100)
@@ -1,5 +1,5 @@
 package com.framsticks.params.types;
 
-import com.framsticks.params.AccessInterface;
+import com.framsticks.params.Access;
 import com.framsticks.params.CastFailure;
 import com.framsticks.params.CompositeParam;
@@ -41,5 +41,5 @@
 
 	@Override
-	public AccessInterface prepareAccessInterface(AccessInterface access) {
+	public Access prepareAccess(Access access) {
 		return access;
 	}
Index: java/main/src/main/java/com/framsticks/params/types/UniqueListParam.java
===================================================================
--- java/main/src/main/java/com/framsticks/params/types/UniqueListParam.java	(revision 99)
+++ java/main/src/main/java/com/framsticks/params/types/UniqueListParam.java	(revision 100)
@@ -1,5 +1,5 @@
 package com.framsticks.params.types;
 
-import com.framsticks.params.AccessInterface;
+import com.framsticks.params.Access;
 import com.framsticks.params.CastFailure;
 import com.framsticks.params.ParamBuilder;
@@ -38,5 +38,5 @@
 
 	@Override
-	public AccessInterface prepareAccessInterface(AccessInterface access) {
+	public Access prepareAccess(Access access) {
 		return new UniqueListAccess(access, uidName);
 	}
Index: java/main/src/main/java/com/framsticks/parsers/AutoInjector.java
===================================================================
--- java/main/src/main/java/com/framsticks/parsers/AutoInjector.java	(revision 100)
+++ java/main/src/main/java/com/framsticks/parsers/AutoInjector.java	(revision 100)
@@ -0,0 +1,26 @@
+package com.framsticks.parsers;
+
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+
+import com.framsticks.params.annotations.AutoAppendAnnotation;
+import com.framsticks.params.annotations.FramsClassAnnotation;
+import com.framsticks.util.AutoBuilder;
+
+@FramsClassAnnotation
+public class AutoInjector implements AutoBuilder {
+
+	protected final List<Object> objects = new LinkedList<>();
+
+	@Override
+	public List<Object> autoFinish() {
+		return Collections.unmodifiableList(objects);
+	}
+
+	@AutoAppendAnnotation
+	public void append(Object object) {
+		objects.add(object);
+	}
+
+}
Index: java/main/src/main/java/com/framsticks/parsers/F0Parser.java
===================================================================
--- java/main/src/main/java/com/framsticks/parsers/F0Parser.java	(revision 99)
+++ java/main/src/main/java/com/framsticks/parsers/F0Parser.java	(revision 100)
@@ -21,8 +21,9 @@
 import com.framsticks.util.lang.Pair;
 import com.framsticks.util.lang.Strings;
-import org.apache.log4j.Logger;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.LogManager;
 
 import com.framsticks.params.FramsClass;
-import com.framsticks.params.AccessInterface;
+import com.framsticks.params.Access;
 import static com.framsticks.params.ParamFlags.*;
 import static com.framsticks.params.SetStateFlags.*;
@@ -33,10 +34,10 @@
 public class F0Parser {
 
-	private final static Logger log = Logger.getLogger(F0Parser.class);
+	private final static Logger log = LogManager.getLogger(F0Parser.class);
 
 	/** The schema proper for f0 representation. */
 	protected final Schema schema;
 	protected final InputStream is;
-	protected final List<AccessInterface> result = new ArrayList<AccessInterface>();
+	protected final List<Access> result = new ArrayList<Access>();
 	int lineNumber = 0;
 
@@ -48,5 +49,5 @@
 	}
 
-	protected AccessInterface processLine(String line) {
+	protected Access processLine(String line) {
 		try {
 
@@ -57,5 +58,5 @@
 				throw new Exception("unknown class id: " + classId);
 			}
-			AccessInterface access = schema.getRegistry().createAccess(classId, framsClass);
+			Access access = schema.getRegistry().createAccess(classId, framsClass);
 			access.select(access.createAccessee());
 			for (Exception e : loadFromLine(access, p.second)) {
@@ -84,5 +85,5 @@
 	 *             the parse exception
 	 */
-	public List<AccessInterface> parse() {
+	public List<Access> parse() {
 
 		try (InputStreamReader reader = new InputStreamReader(is, Encoding.getDefaultCharset())) {
@@ -105,5 +106,5 @@
 					continue;
 				}
-				AccessInterface access = processLine(line);
+				Access access = processLine(line);
 				if (access != null) {
 					result.add(access);
@@ -123,5 +124,5 @@
 
 	private static void warn(int lineNumber, String message, Exception e) {
-		log.warn("in line " + lineNumber + " the following error occurred (" + message + "): " + e);
+		log.warn("in line {} the following error occurred ({}): {}", lineNumber, message, e);
 	}
 
@@ -170,5 +171,5 @@
 	}
 
-	public List<Exception> loadFromLine(AccessInterface access, String parameters) throws Exception {
+	public List<Exception> loadFromLine(Access access, String parameters) throws Exception {
 
 		List<Entry> entries = breakIntoEntries(parameters);
@@ -250,5 +251,5 @@
 	}
 
-	private static Exception createBoundaryHitException(AccessInterface access, PrimitiveParam<?> param, String value, int flag) {
+	private static Exception createBoundaryHitException(Access access, PrimitiveParam<?> param, String value, int flag) {
 		boolean minimum = (flag & 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 99)
+++ java/main/src/main/java/com/framsticks/parsers/F0Writer.java	(revision 100)
@@ -30,5 +30,5 @@
 	}
 
-	protected void write(AccessInterface access) {
+	protected void write(Access access) {
 		if (access instanceof ListAccess) {
 			// TODO
@@ -45,5 +45,5 @@
 		for (ValueParam param : filterInstanceof(access.getParams(), ValueParam.class)) {
 			if (param instanceof CompositeParam) {
-				AccessInterface a = schema.getRegistry().prepareAccess((CompositeParam) param);
+				Access a = schema.getRegistry().prepareAccess((CompositeParam) param);
 				a.select(access.get((ValueParam) param, Object.class));
 				write(a);
@@ -81,5 +81,5 @@
 
 	public void write() {
-		AccessInterface access = schema.getRegistry().createAccess("m");
+		Access access = schema.getRegistry().createAccess("m");
 		access.select(model);
 		write(access);
Index: java/main/src/main/java/com/framsticks/parsers/GenotypeLoader.java
===================================================================
--- java/main/src/main/java/com/framsticks/parsers/GenotypeLoader.java	(revision 99)
+++ java/main/src/main/java/com/framsticks/parsers/GenotypeLoader.java	(revision 100)
@@ -5,10 +5,11 @@
 import com.framsticks.params.types.*;
 
-import org.apache.log4j.Logger;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.LogManager;
 import static com.framsticks.params.ParamFlags.*;
 
 public class GenotypeLoader extends MultiParamLoader {
 	private Genotype genotypeReturnObject = new Genotype();
-	private static Logger logger = Logger.getLogger(GenotypeLoader.class);
+	private static Logger logger = LogManager.getLogger(GenotypeLoader.class);
 
 	public GenotypeLoader() throws Exception {
@@ -54,6 +55,6 @@
 			.finish();
 
-		AccessInterface reflectionParam = new PropertiesAccess(entries);
-		addAccessInterface(reflectionParam);
+		Access reflectionParam = new PropertiesAccess(entries);
+		addAccess(reflectionParam);
 		addBreakCondition(Status.AfterObject);
 	}
Index: java/main/src/main/java/com/framsticks/parsers/Loaders.java
===================================================================
--- java/main/src/main/java/com/framsticks/parsers/Loaders.java	(revision 99)
+++ java/main/src/main/java/com/framsticks/parsers/Loaders.java	(revision 100)
@@ -4,5 +4,5 @@
 
 import com.framsticks.params.*;
-// import org.apache.log4j.Logger;
+// import org.apache.logging.log4j.Logger;
 
 /**
@@ -11,5 +11,5 @@
 public class Loaders {
 
-	// private static final Logger log = Logger.getLogger(Loaders.class.getName());
+	// private static final Logger log = LogManager.getLogger(Loaders.class.getName());
 
 	public static @Nonnull FramsClass loadFramsClass(SourceInterface source) throws ConstructionException {
@@ -19,9 +19,9 @@
 		final FramsClassBuilder builder = FramsClass.build();
 
-		final AccessInterface framsClassAccess = new ReflectionAccess(FramsClassBuilder.class, FramsClass.build().forClass(FramsClassBuilder.class));
-		AccessInterface paramBuilderAccess = new ReflectionAccess(ParamBuilder.class, FramsClass.build().forClass(ParamBuilder.class));
+		final Access framsClassAccess = new ReflectionAccess(FramsClassBuilder.class, FramsClass.build().forClass(FramsClassBuilder.class));
+		Access paramBuilderAccess = new ReflectionAccess(ParamBuilder.class, FramsClass.build().forClass(ParamBuilder.class));
 		framsClassAccess.select(builder);
-		loader.addAccessInterface(framsClassAccess);
-		loader.addAccessInterface(paramBuilderAccess);
+		loader.addAccess(framsClassAccess);
+		loader.addAccess(paramBuilderAccess);
 
 		loader.addListener(MultiParamLoader.Status.AfterObject, new MultiParamLoader.StatusListener() {
Index: java/main/src/main/java/com/framsticks/parsers/MultiParamLoader.java
===================================================================
--- java/main/src/main/java/com/framsticks/parsers/MultiParamLoader.java	(revision 99)
+++ java/main/src/main/java/com/framsticks/parsers/MultiParamLoader.java	(revision 100)
@@ -2,5 +2,6 @@
 
 import com.framsticks.params.*;
-import org.apache.log4j.Logger;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.LogManager;
 
 import java.util.*;
@@ -12,5 +13,5 @@
 	}
 
-	private final static Logger log = Logger.getLogger(MultiParamLoader.class);
+	private final static Logger log = LogManager.getLogger(MultiParamLoader.class);
 
 	/**
@@ -18,6 +19,6 @@
 	 * should be passed.
 	 */
-	public AccessInterface getLastAccessInterface() {
-		return lastAccessInterface;
+	public Access getLastAccess() {
+		return lastAccess;
 	}
 
@@ -39,5 +40,5 @@
 	}
 
-	protected AccessInterface lastAccessInterface;
+	protected Access lastAccess;
 
 	protected static final FramsClass emptyFramsClass = FramsClass.build().idAndName("<empty>").finish();
@@ -46,5 +47,5 @@
 	 * objects in the file.
 	 */
-	protected AccessInterface emptyParam = new PropertiesAccess(emptyFramsClass);
+	protected Access emptyParam = new PropertiesAccess(emptyFramsClass);
 
 	/**
@@ -87,5 +88,5 @@
 	 * List of known classes.
 	 */
-	private Map<String, AccessInterface> knownParamInterfaces = new HashMap<String, AccessInterface>();
+	private Map<String, Access> knownParamInterfaces = new HashMap<String, Access>();
 
 	/**
@@ -132,5 +133,5 @@
 				}
 			}
-			log.trace("read line: " + currentLine);
+			log.trace("read line: {}", currentLine);
 
 			// empty line
@@ -158,5 +159,5 @@
 			}
 
-			// log.warn("unknown line: " + currentLine);
+			// log.warn("unknown line: {}", currentLine);
 			changeStatus(Status.OnError);
 			if (action == LoopAction.Break) {
@@ -177,12 +178,11 @@
 	 */
 	private LoopAction tryReadObject() {
-		if (status == Status.BeforeObject
-				|| (status == Status.BeforeUnknown && lastAccessInterface != null)) {
+		if (status == Status.BeforeObject || (status == Status.BeforeUnknown && lastAccess != null)) {
 			// found object - let it load data
-			if (lastAccessInterface.getSelected() == null) {
-				lastAccessInterface.select(lastAccessInterface.createAccessee());
-			}
-			log.trace("loading into " + lastAccessInterface);
-			lastAccessInterface.load(currentSource);
+			if (lastAccess.getSelected() == null) {
+				lastAccess.select(lastAccess.createAccessee());
+			}
+			log.trace("loading into {}", lastAccess);
+			lastAccess.load(currentSource);
 
 			if (changeStatus(Status.AfterObject)) {
@@ -191,5 +191,5 @@
 			return LoopAction.Continue;
 		} else if (status == Status.BeforeUnknown) {
-			log.warn("omitting unknown object: " + lastUnknownObjectName);
+			log.warn("omitting unknown object: {}", lastUnknownObjectName);
 
 			// found unknown object
@@ -262,7 +262,7 @@
 		if (line.charAt(line.length() - 1) == ':') {
 			String typeName = line.substring(0, line.length() - 1);
-			lastAccessInterface = knownParamInterfaces.get(typeName);
-
-			if (lastAccessInterface != null) {
+			lastAccess = knownParamInterfaces.get(typeName);
+
+			if (lastAccess != null) {
 				if (changeStatus(Status.BeforeObject)) {
 					return LoopAction.Break;
@@ -299,7 +299,7 @@
 	 * Adds another class.
 	 */
-	public void addAccessInterface(AccessInterface accessInterface) {
+	public void addAccess(Access access) {
 		/**TODO: by id or by name? rather by id, because from file is always lowercase*/
-		knownParamInterfaces.put(accessInterface.getId(), accessInterface);
+		knownParamInterfaces.put(access.getId(), access);
 	}
 
@@ -325,5 +325,5 @@
 
 	public boolean setNewSource(SourceInterface source) {
-		log.debug("switching current source to " + source.getFilename() + "...");
+		log.debug("switching current source to {}...", source.getFilename());
 
 		currentSource = source;
@@ -345,10 +345,9 @@
 		// check if it is already included and break if it is
 		if (isAlreadyIncluded(includeFilename)) {
-			log.debug("circular reference ignored (" + includeFilename
-					+ ")");
+			log.debug("circular reference ignored ({})", includeFilename);
 			return;
 		}
 
-		log.info("including file " + includeFilename + "...");
+		log.info("including file {}...", includeFilename);
 
 		SourceInterface newSource = currentSource.openInclude(includeFilename);
@@ -369,5 +368,5 @@
 		for (String file : fileStack) {
 			if (filename.equals(file)) {
-				log.warn("file " + filename + " was already included");
+				log.warn("file {} was already included", filename);
 				return true;
 			}
@@ -400,5 +399,5 @@
 	 */
 	private boolean changeStatus(Status status) {
-		log.trace("changing status: " + this.status.toString() + " -> " + status.toString());
+		log.trace("changing status: {} -> {}", this.status.toString(), status.toString());
 		this.status = status;
 		if (listeners.containsKey(status)) {
@@ -411,10 +410,10 @@
 
 	public Object returnObject() {
-		assert lastAccessInterface != null;
-		Object result = lastAccessInterface.getSelected();
+		assert lastAccess != null;
+		Object result = lastAccess.getSelected();
 		if (result == null) {
 			return null;
 		}
-		lastAccessInterface.select(null);
+		lastAccess.select(null);
 		return result;
 	}
@@ -426,3 +425,19 @@
 		listeners.get(status).add(listener);
 	}
+
+	public static List<Object> loadAll(SourceInterface source, Access access) {
+		final List<Object> result = new LinkedList<>();
+
+		final MultiParamLoader loader = new MultiParamLoader();
+		loader.setNewSource(source);
+		loader.addAccess(access);
+		loader.addListener(MultiParamLoader.Status.AfterObject, new StatusListener() {
+			@Override
+			public void onStatusChange() {
+				result.add(loader.returnObject());
+			}
+		});
+		loader.go();
+		return result;
+	}
 }
Index: java/main/src/main/java/com/framsticks/parsers/Savers.java
===================================================================
--- java/main/src/main/java/com/framsticks/parsers/Savers.java	(revision 99)
+++ java/main/src/main/java/com/framsticks/parsers/Savers.java	(revision 100)
@@ -10,6 +10,6 @@
 	public static <S extends SinkInterface> S saveFramsClass(S sink, FramsClass framsClass) {
 
-		AccessInterface framsClassAccess = new ReflectionAccess(FramsClass.class);
-		AccessInterface paramAccess = new ReflectionAccess(Param.class);
+		Access framsClassAccess = new ReflectionAccess(FramsClass.class);
+		Access paramAccess = new ReflectionAccess(Param.class);
 		framsClassAccess.select(framsClass);
 		framsClassAccess.save(sink);
Index: java/main/src/main/java/com/framsticks/parsers/XmlLoader.java
===================================================================
--- java/main/src/main/java/com/framsticks/parsers/XmlLoader.java	(revision 99)
+++ java/main/src/main/java/com/framsticks/parsers/XmlLoader.java	(revision 100)
@@ -1,4 +1,7 @@
 package com.framsticks.parsers;
 
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
 import java.io.InputStream;
 import java.util.LinkedList;
@@ -8,5 +11,6 @@
 import javax.xml.parsers.DocumentBuilderFactory;
 
-import org.apache.log4j.Logger;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.LogManager;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
@@ -15,5 +19,5 @@
 import org.w3c.dom.NodeList;
 
-import com.framsticks.params.AccessInterface;
+import com.framsticks.params.Access;
 import com.framsticks.params.Registry;
 import com.framsticks.util.AutoBuilder;
@@ -22,5 +26,5 @@
 
 public class XmlLoader {
-	private static final Logger log = Logger.getLogger(XmlLoader.class);
+	private static final Logger log = LogManager.getLogger(XmlLoader.class);
 
 	protected Registry registry = new Registry();
@@ -30,4 +34,5 @@
 	 */
 	public XmlLoader() {
+		registry.registerAndBuild(AutoInjector.class);
 	}
 
@@ -56,5 +61,5 @@
 	}
 
-	public Object processElement(Element element) {
+	public Object processElement(Element element, Class<?> enclosingClass) {
 		final String name = mangleName(element.getNodeName());
 		if (name.equals("import")) {
@@ -67,6 +72,31 @@
 			}
 		}
+		if (name.equals("include")) {
+			String fileName = element.getAttribute("file");
+			if (Strings.notEmpty(fileName)) {
+				try {
+					return load(new FileInputStream(new File(fileName)), enclosingClass);
+				} catch (FileNotFoundException e) {
+					throw new FramsticksException().msg("failed to include file").arg("file", fileName).cause(e);
+				}
+			}
+			String resourceName = element.getAttribute("resource");
+			if (Strings.notEmpty(resourceName)) {
+				Class<?> javaClass = enclosingClass;
+				String className = element.getAttribute("class");
+				if (Strings.notEmpty(className)) {
+					try {
+						javaClass = Class.forName(className);
+					} catch (ClassNotFoundException e) {
+						throw new FramsticksException().msg("failed to find class for resource loading").arg("class name", className).cause(e);
+					}
+				}
 
-		AccessInterface access = registry.createAccess(name);
+				return load(javaClass.getResourceAsStream(resourceName), enclosingClass);
+			}
+			throw new FramsticksException().msg("invalid <include/> node");
+		}
+
+		Access access = registry.createAccess(name);
 
 		Object object = access.createAccessee();
@@ -81,5 +111,5 @@
 
 		NodeList children = element.getChildNodes();
-		log.debug("found " + children.getLength() + " children in " + object);
+		log.debug("found {} children in {}", children.getLength(), object);
 		for (int i = 0; i < children.getLength(); ++i) {
 			Node childNode = children.item(i);
@@ -87,5 +117,5 @@
 				continue;
 			}
-			Object childObject = processElement((Element) childNode);
+			Object childObject = processElement((Element) childNode, object.getClass());
 			if (childObject == null) {
 				continue;
@@ -104,10 +134,10 @@
 			}
 		}
-		log.debug("loaded " + object);
+		log.debug("loaded {}", object);
 
 		return object;
 	}
 
-	public Object load(InputStream stream) {
+	protected Object load(InputStream stream, Class<?> enclosingClass) {
 		try {
 			DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
@@ -119,5 +149,5 @@
 			assert element != null;
 
-			return processElement(element);
+			return processElement(element, enclosingClass);
 
 		} catch (Exception e) {
@@ -129,5 +159,5 @@
 		registry.registerAndBuild(type);
 
-		Object object = load(stream);
+		Object object = load(stream, type);
 		if (type.isAssignableFrom(object.getClass())) {
 			return type.cast(object);
Index: java/main/src/main/java/com/framsticks/portals/Portal.java
===================================================================
--- java/main/src/main/java/com/framsticks/portals/Portal.java	(revision 99)
+++ java/main/src/main/java/com/framsticks/portals/Portal.java	(revision 100)
@@ -28,5 +28,5 @@
 	//		public void run() {
 	//			++counter;
-	//			log.debug("counter is now: " + counter);
+	//			log.debug("counter is now: {}", counter);
 	//			again();
 	//		}
Index: java/main/src/main/java/com/framsticks/remote/RecursiveFetcher.java
===================================================================
--- java/main/src/main/java/com/framsticks/remote/RecursiveFetcher.java	(revision 99)
+++ java/main/src/main/java/com/framsticks/remote/RecursiveFetcher.java	(revision 100)
@@ -5,5 +5,5 @@
 import com.framsticks.core.Node;
 import com.framsticks.core.Path;
-import com.framsticks.params.AccessInterface;
+import com.framsticks.params.Access;
 import com.framsticks.params.CompositeParam;
 import com.framsticks.params.FramsClass;
@@ -15,5 +15,6 @@
 import com.framsticks.util.Logging;
 import com.framsticks.util.Stopwatch;
-import org.apache.log4j.Logger;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.LogManager;
 import static com.framsticks.util.lang.Containers.filterInstanceof;
 import com.framsticks.util.dispatching.RunAt;
@@ -24,5 +25,5 @@
 public class RecursiveFetcher {
 
-	private final static Logger log = Logger.getLogger(RecursiveFetcher.class.getName());
+	private final static Logger log = LogManager.getLogger(RecursiveFetcher.class.getName());
 
 	protected final Tree tree;
@@ -40,5 +41,5 @@
 	protected void finished() {
 		assert tree.isActive();
-		log.info("recursively fetched in " + stopwatch);
+		log.info("recursively fetched in {}", stopwatch);
 		future.pass(null);
 	}
@@ -47,7 +48,7 @@
 		assert tree.isActive();
 		if (path == null || !path.isResolved()) {
-			log.warn("path " + path + " is not resolved - skipping");
+			log.warn("path {} is not resolved - skipping", path);
 		} else {
-			AccessInterface access = bindAccess(path);
+			Access access = bindAccess(path);
 			FramsClass framsClass = access.getFramsClass();
 			assert framsClass != null;
@@ -86,5 +87,5 @@
 			@Override
 			public void handle(FramsticksException e) {
-				log.error("failed to fetch values for " + path + ": " + e);
+				log.error("failed to fetch values for {}: ", path, e);
 				process(null);
 			}
Index: java/main/src/main/java/com/framsticks/remote/RemoteTree.java
===================================================================
--- java/main/src/main/java/com/framsticks/remote/RemoteTree.java	(revision 99)
+++ java/main/src/main/java/com/framsticks/remote/RemoteTree.java	(revision 100)
@@ -15,9 +15,13 @@
 import com.framsticks.params.types.EventParam;
 import com.framsticks.params.types.ProcedureParam;
+import com.framsticks.parsers.Loaders;
 import com.framsticks.parsers.MultiParamLoader;
 import com.framsticks.core.Tree;
 import com.framsticks.util.*;
+import com.framsticks.util.dispatching.AtOnceDispatcher;
 import com.framsticks.util.dispatching.Dispatching;
 import com.framsticks.util.dispatching.Dispatching.DispatcherWaiter;
+import com.framsticks.util.dispatching.DispatchingFuture;
+import com.framsticks.util.dispatching.ExceptionResultHandler;
 import com.framsticks.util.dispatching.Future;
 import com.framsticks.util.dispatching.FutureHandler;
@@ -34,5 +38,6 @@
 import javax.annotation.Nonnull;
 
-import org.apache.log4j.Logger;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.LogManager;
 
 /**
@@ -42,5 +47,5 @@
 public final class RemoteTree extends AbstractTree implements JoinableParent {
 
-	private final static Logger log = Logger.getLogger(RemoteTree.class);
+	private final static Logger log = LogManager.getLogger(RemoteTree.class);
 
 	protected ClientSideManagedConnection connection;
@@ -62,4 +67,5 @@
 	public void setConnection(final ClientSideManagedConnection connection) {
 		this.connection = connection;
+		this.connection.setExceptionHandler(this);
 	}
 
@@ -74,19 +80,38 @@
 	}
 
-	@Override
-	public void get(final Path path, final ValueParam param, final Future<Object> future) {
-		assert isActive();
-		assert param != null;
-		// assert path.isResolved();
-		//TODO only do that if needed
-		connection.send(new GetRequest().field(param.getId()).path(path.getTextual()), this, new ClientSideResponseFuture(future) {
-			@Override
-			protected void processOk(Response response) {
-				assert isActive();
-				processFetchedValues(path, response.getFiles());
-				future.pass(bindAccess(path.tryResolveIfNeeded()).get(param, Object.class));
-			}
-		});
-	}
+	protected ExceptionResultHandler pathRemoveHandler(final Path path, final ExceptionResultHandler handler) {
+		return new ExceptionResultHandler() {
+
+			@Override
+			public void handle(final FramsticksException exception) {
+				Dispatching.dispatchIfNotActive(RemoteTree.this, new RunAt<RemoteTree>(RemoteTree.this) {
+
+					@Override
+					protected void runAt() {
+						assert path.getTree().isActive();
+						log.info("path is invalid (removing): {}", path);
+						bindAccess(path.getUnder()).set(path.getTop().getParam(), null);
+						handler.handle(exception);
+					}
+				});
+			}
+		};
+	}
+
+	// @Override
+	// public void get(final Path path, final ValueParam param, final Future<Object> future) {
+	//	assert isActive();
+	//	assert param != null;
+	//	// assert path.isResolved();
+	//	//TODO only do that if needed
+	//	connection.send(new GetRequest().field(param.getId()).path(path.getTextual()), this, new ClientSideResponseFuture(pathRemoveHandler(path, future)) {
+	//		@Override
+	//		protected void processOk(Response response) {
+	//			assert isActive();
+	//			processFetchedValues(path, response.getFiles());
+	//			future.pass(bindAccess(path.tryResolveIfNeeded()).get(param, Object.class));
+	//		}
+	//	});
+	// }
 
 	protected final Map<String, Set<Future<FramsClass>>> infoRequests = new HashMap<String, Set<Future<FramsClass>>>();
@@ -103,10 +128,10 @@
 		}
 
-		log.debug("issuing info request for " + name);
+		log.debug("issuing info request for {}", name);
 		final Set<Future<FramsClass>> futures = new HashSet<Future<FramsClass>>();
 		futures.add(future);
 		infoRequests.put(name, futures);
 
-		final Future<FramsClass> compositeFuture = new Future<FramsClass>() {
+		final Future<FramsClass> compositeFuture = DispatchingFuture.create(this, new Future<FramsClass>() {
 
 			@Override
@@ -122,4 +147,5 @@
 			protected void result(FramsClass framsClass) {
 				assert isActive();
+				putInfoIntoCache(framsClass);
 				infoRequests.remove(name);
 				for (Future<FramsClass> f : futures) {
@@ -127,11 +153,11 @@
 				}
 			}
-		};
+		});
 
 		//TODO: if the info is in the cache, then don't communicate
-		connection.send(new InfoRequest().path(path.getTextual()), this, new ClientSideResponseFuture(compositeFuture) {
+		connection.send(new InfoRequest().path(path.getTextual()), AtOnceDispatcher.getInstance(), new ClientSideResponseFuture(compositeFuture) {
 			@Override
 			protected void processOk(Response response) {
-				assert isActive();
+				assert connection.getReceiverDispatcher().isActive();
 
 				if (response.getFiles().size() != 1) {
@@ -141,5 +167,5 @@
 					throw new FramsticksException().msg("path mismatch").arg("returned path", response.getFiles().get(0).getPath());
 				}
-				FramsClass framsClass = processFetchedInfo(RemoteTree.this, response.getFiles().get(0));
+				FramsClass framsClass = Loaders.loadFramsClass(response.getFiles().get(0).getContent());
 
 				CompositeParam thisParam = path.getTop().getParam();
@@ -155,17 +181,16 @@
 	public void get(final Path path, final Future<Path> future) {
 		assert isActive();
-
-		log.trace("fetching values for " + path);
-		findInfo(path, new FutureHandler<FramsClass>(future) {
+		final ExceptionResultHandler remover = pathRemoveHandler(path, future);
+
+		log.trace("fetching values for {}", path);
+		findInfo(path, new FutureHandler<FramsClass>(remover) {
 			@Override
 			protected void result(FramsClass result) {
 
-				connection.send(new GetRequest().path(path.getTextual()), RemoteTree.this, new ClientSideResponseFuture(future) {
+				final Access access = registry.prepareAccess(path.getTop().getParam());
+				connection.send(new GetRequest().path(path.getTextual()), AtOnceDispatcher.getInstance(), new ClientSideResponseFuture(remover) {
 					@Override
 					protected void processOk(Response response) {
-						assert isActive();
-						Path p = path.tryResolveIfNeeded();
-						processFetchedValues(p, response.getFiles());
-						future.pass(p.tryResolveIfNeeded().assureResolved());
+						processFetchedValues(path, response.getFiles(), access, future);
 					}
 				});
@@ -179,5 +204,5 @@
 		final Integer flag = bindAccess(path).set(param, value);
 
-		log.trace("storing value " + param + " for " + path);
+		log.trace("storing value {} for {}", param, path);
 		//TODO break in passing exception handler is here
 		connection.send(new SetRequest().value(value.toString()).field(param.getId()).path(path.getTextual()), this, new ClientSideResponseFuture(future) {
@@ -274,5 +299,5 @@
 							return;
 						}
-						AccessInterface access = registry.createAccess(argumentType);
+						Access access = registry.createAccess(argumentType);
 						Object argument = access.createAccessee();
 						access.select(argument);
@@ -282,9 +307,9 @@
 						A typedArgument = argumentType.cast(argument);
 
-						// log.info("executing event with argument " + argumentType);
+						// log.info("executing event with argument {}", argumentType);
 						MultiParamLoader loader = new MultiParamLoader();
 						loader.setNewSource(file.getContent());
 						loader.addBreakCondition(MultiParamLoader.Status.AfterObject);
-						loader.addAccessInterface(access);
+						loader.addAccess(access);
 						loader.go();
 
Index: java/main/src/main/java/com/framsticks/running/ExternalProcess.java
===================================================================
--- java/main/src/main/java/com/framsticks/running/ExternalProcess.java	(revision 99)
+++ java/main/src/main/java/com/framsticks/running/ExternalProcess.java	(revision 100)
@@ -12,5 +12,6 @@
 
 
-import org.apache.log4j.Logger;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.LogManager;
 
 import com.framsticks.params.annotations.AutoAppendAnnotation;
@@ -31,5 +32,5 @@
 @FramsClassAnnotation
 public class ExternalProcess extends AbstractJoinable implements JoinableParent {
-	private static final Logger log = Logger.getLogger(ExternalProcess.class);
+	private static final Logger log = LogManager.getLogger(ExternalProcess.class);
 
 	protected List<String> arguments = new ArrayList<>();
@@ -83,5 +84,5 @@
 			try {
 				while ((line = output.readLine()) != null) {
-					log.trace("read line: " + line);
+					log.trace("read line: {}", line);
 					synchronized (listeners) {
 						for (OutputListener l : listeners) {
@@ -98,8 +99,8 @@
 				throw new FramsticksException().msg("failed to wait for process").cause(e);
 			}
-			log.debug("process ended " + this);
+			log.debug("process ended {}", this);
 			// process = null;
 		} catch (FramsticksException e) {
-			log.error("exception caught in process " + this, e);
+			log.error("exception caught in process {}", this, e);
 		}
 		interrupt();
@@ -119,5 +120,5 @@
 	@Override
 	protected void joinableStart() {
-		log.debug("running process with arguments: " + arguments);
+		log.debug("running process with arguments: {}", arguments);
 		builder.command(arguments);
 		try {
Index: java/main/src/main/java/com/framsticks/running/LoggingOutputListener.java
===================================================================
--- java/main/src/main/java/com/framsticks/running/LoggingOutputListener.java	(revision 99)
+++ java/main/src/main/java/com/framsticks/running/LoggingOutputListener.java	(revision 100)
@@ -1,5 +1,6 @@
 package com.framsticks.running;
 
-import org.apache.log4j.Logger;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.LogManager;
 
 import com.framsticks.params.annotations.FramsClassAnnotation;
@@ -8,5 +9,5 @@
 public class LoggingOutputListener implements OutputListener {
 	private static final Logger log =
-		Logger.getLogger(LoggingOutputListener.class);
+		LogManager.getLogger(LoggingOutputListener.class);
 
 
Index: java/main/src/main/java/com/framsticks/test/TestChild.java
===================================================================
--- java/main/src/main/java/com/framsticks/test/TestChild.java	(revision 100)
+++ java/main/src/main/java/com/framsticks/test/TestChild.java	(revision 100)
@@ -0,0 +1,47 @@
+package com.framsticks.test;
+
+import com.framsticks.core.ListChange;
+import com.framsticks.params.annotations.FramsClassAnnotation;
+import com.framsticks.params.annotations.ParamAnnotation;
+
+@FramsClassAnnotation
+public class TestChild {
+
+	protected String name = "child";
+
+	protected String uid;
+	protected final TestClass parent;
+	/**
+	 *
+	 */
+	public TestChild(TestClass parent) {
+		this.parent = parent;
+		this.uid = "c" + (parent.counter++);
+	}
+
+	/**
+	 * @return the name
+	 */
+	@ParamAnnotation
+	public String getName() {
+		return name;
+	}
+
+	/**00:10:00
+	 * @param name the name to set
+	 */
+	@ParamAnnotation
+	public void setName(String name) {
+		this.name = name;
+		parent.fireChildrenChange(this, ListChange.Action.Modify);
+	}
+
+	/**
+	 * @return the uid
+	 */
+	@ParamAnnotation
+	public String getUid() {
+		return uid;
+	}
+
+}
Index: java/main/src/main/java/com/framsticks/test/TestClass.java
===================================================================
--- java/main/src/main/java/com/framsticks/test/TestClass.java	(revision 99)
+++ java/main/src/main/java/com/framsticks/test/TestClass.java	(revision 100)
@@ -1,18 +1,39 @@
 package com.framsticks.test;
 
+import java.util.Collections;
 import java.util.LinkedList;
 import java.util.List;
+import java.util.Map;
 
-import org.apache.log4j.Logger;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.LogManager;
 
+import com.framsticks.core.ListChange;
 import com.framsticks.params.EventListener;
+import com.framsticks.params.UniqueListAccess;
 import com.framsticks.params.annotations.FramsClassAnnotation;
 import com.framsticks.params.annotations.ParamAnnotation;
 import com.framsticks.params.types.ProcedureParam;
 
-@FramsClassAnnotation(order = {"name", "history", "history_changed", "appendHistory", "resetHistory"}, register = {ChangeEvent.class})
+@FramsClassAnnotation(
+	order = {
+		"name",
+		"history",
+		"history_changed",
+		"appendHistory",
+		"resetHistory",
+		"children",
+		"createChild",
+		"children_changed"
+	},
+	register = {
+		ChangeEvent.class,
+		TestChild.class,
+		ListChange.class
+	}
+)
 public class TestClass {
 	private static final Logger log =
-		Logger.getLogger(TestClass.class);
+		LogManager.getLogger(TestClass.class);
 
 
@@ -20,4 +41,14 @@
 	protected String history = "initial|";
 	protected final List<EventListener<ChangeEvent>> historyListeners = new LinkedList<>();
+	protected final List<EventListener<ListChange>> childrenListeners = new LinkedList<>();
+
+	protected final Map<String, TestChild> children = UniqueListAccess.createMap(TestChild.class, this);
+	protected int counter = 0;
+
+	/**
+	 *
+	 */
+	public TestClass() {
+	}
 
 	/**
@@ -53,7 +84,15 @@
 	}
 
+	/**
+	 * @return the children
+	 */
+	@ParamAnnotation
+	public Map<String, TestChild> getChildren() {
+		return Collections.unmodifiableMap(children);
+	}
+
 	@ParamAnnotation(paramType = ProcedureParam.class)
 	public int appendHistory(String line) {
-		log.debug("appending '" + line + "'");
+		log.debug("appending '{}'", line);
 		history = history + line + "|";
 		fireHistoryChange();
@@ -68,4 +107,12 @@
 	}
 
+	@ParamAnnotation(paramType = ProcedureParam.class)
+	public void createChild(String name) {
+		TestChild child = new TestChild(this);
+		child.name = name;
+		children.put(child.getUid(), child);
+		fireChildrenChange(child, ListChange.Action.Add);
+	}
+
 	protected void fireHistoryChange() {
 		for (EventListener<ChangeEvent> l : historyListeners) {
@@ -73,4 +120,11 @@
 			event.history = history;
 			l.action(event);
+		}
+	}
+
+	protected void fireChildrenChange(TestChild child, ListChange.Action action) {
+		ListChange change = new ListChange(action, UniqueListAccess.getNumberInMap(children, child), child.getUid());
+		for (EventListener<ListChange> l : childrenListeners) {
+			l.action(change);
 		}
 	}
@@ -86,4 +140,14 @@
 	}
 
+	@ParamAnnotation(id = "children_changed")
+	public void addChildrenListener(EventListener<ListChange> listener) {
+		childrenListeners.add(listener);
+	}
+
+	@ParamAnnotation(id = "children_changed")
+	public void removeChildrenListener(EventListener<ListChange> listener) {
+		childrenListeners.remove(listener);
+	}
+
 	@Override
 	public String toString() {
Index: java/main/src/main/java/com/framsticks/util/Logging.java
===================================================================
--- java/main/src/main/java/com/framsticks/util/Logging.java	(revision 99)
+++ java/main/src/main/java/com/framsticks/util/Logging.java	(revision 100)
@@ -1,5 +1,5 @@
 package com.framsticks.util;
 
-import org.apache.log4j.Logger;
+import org.apache.logging.log4j.Logger;
 
 import com.framsticks.util.dispatching.ExceptionResultHandler;
@@ -28,3 +28,8 @@
 		};
 	}
+
+	public static <T> T passThru(Logger log, String header, T value) {
+		log.info("{}: {}", header, value);
+		return value;
+	}
 }
Index: java/main/src/main/java/com/framsticks/util/Misc.java
===================================================================
--- java/main/src/main/java/com/framsticks/util/Misc.java	(revision 99)
+++ java/main/src/main/java/com/framsticks/util/Misc.java	(revision 100)
@@ -1,5 +1,5 @@
 package com.framsticks.util;
 
-// import org.apache.log4j.Logger;
+// import org.apache.logging.log4j.Logger;
 
 /**
@@ -8,5 +8,5 @@
 public class Misc {
 	// private static final Logger log =
-	// 	Logger.getLogger(Misc.class);
+	// 	LogManager.getLogger(Misc.class);
 
 	public static class WithType {
@@ -34,5 +34,5 @@
 
 	public static boolean equals(Object a, Object b) {
-		// log.info("equality of " + withType(a) + " ? " + withType(b));
+		// log.info("equality of {} ? {}", withType(a), withType(b));
 		if (a != null) {
 			return (b != null && a.equals(b));
Index: java/main/src/main/java/com/framsticks/util/dispatching/AbstractJoinable.java
===================================================================
--- java/main/src/main/java/com/framsticks/util/dispatching/AbstractJoinable.java	(revision 99)
+++ java/main/src/main/java/com/framsticks/util/dispatching/AbstractJoinable.java	(revision 100)
@@ -10,5 +10,6 @@
 
 import org.apache.commons.collections.CollectionUtils;
-import org.apache.log4j.Logger;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.LogManager;
 
 import com.framsticks.util.FramsticksException;
@@ -16,5 +17,5 @@
 public abstract class AbstractJoinable implements Joinable {
 
-	private static final Logger log = Logger.getLogger(AbstractJoinable.class);
+	private static final Logger log = LogManager.getLogger(AbstractJoinable.class);
 
 	protected final Set<JoinableParent> owners = new HashSet<JoinableParent>();
@@ -41,5 +42,5 @@
 			}
 		}
-		log.debug("state: " + b);
+		log.debug("state: {}", b);
 	}
 
@@ -53,5 +54,5 @@
 		this.state = state;
 
-		log.debug(this + " is notifying " + joinableListeners.size() + " parents");
+		log.debug("{} is notifying {} parents", this, joinableListeners.size());
 
 		List<JoinableParent> parents = new LinkedList<>();
@@ -141,5 +142,5 @@
 			}
 			start = owners.isEmpty();
-			log.debug(owner + " is using " + this);
+			log.debug("{} is using {}", owner, this);
 			owners.add(owner);
 			joinableListeners.add(owner);
@@ -161,5 +162,5 @@
 			}
 			// assert owners.containsKey(owner);
-			log.debug(owner + " is droping " + this);
+			log.debug("{} is droping {}", owner, this);
 			owners.remove(owner);
 			stop = owners.isEmpty();
Index: java/main/src/main/java/com/framsticks/util/dispatching/Dispatching.java
===================================================================
--- java/main/src/main/java/com/framsticks/util/dispatching/Dispatching.java	(revision 99)
+++ java/main/src/main/java/com/framsticks/util/dispatching/Dispatching.java	(revision 100)
@@ -1,5 +1,6 @@
 package com.framsticks.util.dispatching;
 
-import org.apache.log4j.Logger;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.LogManager;
 
 import com.framsticks.util.FramsticksException;
@@ -9,5 +10,5 @@
  */
 public abstract class Dispatching {
-	private static final Logger log = Logger.getLogger(Dispatching.class);
+	private static final Logger log = LogManager.getLogger(Dispatching.class);
 
 	public static boolean isThreadSafe() {
@@ -57,30 +58,30 @@
 
 	public static void use(final Joinable joinable, final JoinableParent owner) {
-		log.debug("using " + joinable + " by " + owner);
+		log.debug("using {} by {}", joinable, owner);
 		if (joinable.use(owner)) {
-			log.debug("started " + joinable);
+			log.debug("started {}", joinable);
 		} else {
-			log.debug("start of " + joinable + " already happened");
+			log.debug("start of {} already happened", joinable);
 		}
 	}
 
 	public static void drop(final Joinable joinable, final JoinableParent owner) {
-		log.debug("droping " + joinable + " by " + owner);
+		log.debug("droping {} by {}", joinable, owner);
 		if (joinable.drop(owner)) {
-			log.debug("stoped " + joinable);
+			log.debug("stoped {}", joinable);
 		} else {
-			log.debug("stop of " + joinable + " deferred");
+			log.debug("stop of {} deferred", joinable);
 		}
 	}
 
 	public static void join(Joinable joinable) throws InterruptedException {
-		log.debug("joining " + joinable);
+		log.debug("joining {}", joinable);
 		try {
 			joinable.join();
 		} catch (InterruptedException e) {
-			log.debug("failed to join " + joinable);
+			log.debug("failed to join {}", joinable);
 			throw e;
 		}
-		log.debug("joined " + joinable);
+		log.debug("joined {}", joinable);
 	}
 
@@ -92,5 +93,5 @@
 			@Override
 			protected void runAt() {
-				log.debug("joinable " + joinable + " is notifying parent " + parent + " about change to " + state);
+				log.debug("joinable {} is notifying parent {} about change to {}", joinable, parent, state);
 				parent.childChangedState(joinable, state);
 			}
@@ -108,5 +109,5 @@
 
 	public static void joinAbsolutely(Joinable joinable) {
-		log.debug("joining absolutely " + joinable);
+		log.debug("joining absolutely {}", joinable);
 		while (true) {
 			try {
@@ -116,5 +117,5 @@
 				// throw new FramsticksException().msg("failed to join").arg("dispatcher", dispatcher).cause(e);
 			}
-			log.debug("waiting for " + joinable);
+			log.debug("waiting for {}", joinable);
 			wait(joinable, 500);
 		}
Index: java/main/src/main/java/com/framsticks/util/dispatching/DispatchingExceptionHandler.java
===================================================================
--- java/main/src/main/java/com/framsticks/util/dispatching/DispatchingExceptionHandler.java	(revision 100)
+++ java/main/src/main/java/com/framsticks/util/dispatching/DispatchingExceptionHandler.java	(revision 100)
@@ -0,0 +1,30 @@
+package com.framsticks.util.dispatching;
+
+import com.framsticks.util.FramsticksException;
+
+public class DispatchingExceptionHandler implements ExceptionResultHandler {
+
+	protected final Dispatcher<?> dispatcher;
+	protected final ExceptionResultHandler handler;
+
+	/**
+	 * @param dispatcher
+	 * @param handler
+	 */
+	public DispatchingExceptionHandler(Dispatcher<?> dispatcher, ExceptionResultHandler handler) {
+		this.dispatcher = dispatcher;
+		this.handler = handler;
+	}
+
+	@SuppressWarnings({ "rawtypes", "unchecked" })
+	@Override
+	public void handle(final FramsticksException exception) {
+		dispatcher.dispatch(new RunAt(ThrowExceptionHandler.getInstance()) {
+			@Override
+			protected void runAt() {
+				handler.handle(exception);
+			}
+		});
+	}
+
+}
Index: java/main/src/main/java/com/framsticks/util/dispatching/DispatchingFuture.java
===================================================================
--- java/main/src/main/java/com/framsticks/util/dispatching/DispatchingFuture.java	(revision 100)
+++ java/main/src/main/java/com/framsticks/util/dispatching/DispatchingFuture.java	(revision 100)
@@ -0,0 +1,43 @@
+package com.framsticks.util.dispatching;
+
+import com.framsticks.util.FramsticksException;
+
+public class DispatchingFuture<C, T> extends Future<T> {
+
+	protected final Dispatcher<? super C> dispatcher;
+	protected final Future<T> future;
+
+	/**
+	 * @param dispatcher
+	 * @param future
+	 */
+	public DispatchingFuture(Dispatcher<? super C> dispatcher, Future<T> future) {
+		this.dispatcher = dispatcher;
+		this.future = future;
+	}
+
+	@Override
+	public void handle(final FramsticksException exception) {
+		Dispatching.dispatchIfNotActive(dispatcher, new RunAt<C>(ThrowExceptionHandler.getInstance()) {
+			@Override
+			protected void runAt() {
+				future.handle(exception);
+			}
+		});
+	}
+
+	@Override
+	protected void result(final T result) {
+		Dispatching.dispatchIfNotActive(dispatcher, new RunAt<C>(future) {
+			@Override
+			protected void runAt() {
+				future.pass(result);
+			}
+		});
+	}
+
+	public static <Ca, Ta> Future<Ta> create(Dispatcher<Ca> dispatcher, Future<Ta> future) {
+		return new DispatchingFuture<Ca, Ta>(dispatcher, future);
+	}
+
+}
Index: java/main/src/main/java/com/framsticks/util/dispatching/Monitor.java
===================================================================
--- java/main/src/main/java/com/framsticks/util/dispatching/Monitor.java	(revision 99)
+++ java/main/src/main/java/com/framsticks/util/dispatching/Monitor.java	(revision 100)
@@ -1,5 +1,6 @@
 package com.framsticks.util.dispatching;
 
-import org.apache.log4j.Logger;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.LogManager;
 import com.framsticks.util.dispatching.Dispatching;
 import java.lang.Thread;
@@ -7,5 +8,5 @@
 public class Monitor implements JoinableParent {
 	private static final Logger log =
-		Logger.getLogger(Monitor.class);
+		LogManager.getLogger(Monitor.class);
 
 	protected final Joinable joinable;
@@ -30,5 +31,5 @@
 		Runtime.getRuntime().addShutdownHook(shutdownHook);
 
-		log.debug(this + " is using");
+		log.debug("{} is using", this);
 		Dispatching.use(joinable, this);
 		return this;
@@ -41,5 +42,5 @@
 
 	public Monitor waitFor() {
-		log.debug(this + " is waiting");
+		log.debug("{} is waiting", this);
 		synchronized (this) {
 			while (joinable.getState().ordinal() < JoinableState.FINISHING.ordinal()) {
@@ -47,5 +48,5 @@
 			}
 		}
-		log.debug(this + " ended waiting");
+		log.debug("{} ended waiting", this);
 		return this;
 	}
@@ -53,5 +54,5 @@
 
 	public Monitor drop() {
-		log.debug(this + " is droping");
+		log.debug("{} is droping", this);
 		Dispatching.drop(joinable, this);
 		return this;
@@ -59,7 +60,7 @@
 
 	public Monitor join() {
-		log.debug(this + " is joining");
+		log.debug("{} is joining", this);
 		Dispatching.joinAbsolutely(joinable);
-		log.debug(this + " is joined");
+		log.debug("{} is joined", this);
 
 		try {
@@ -78,5 +79,5 @@
 			this.notify();
 		}
-		log.debug(this + " received notification about transition to " + state);
+		log.debug("{} received notification about transition to {}", this, state);
 	}
 
Index: java/main/src/main/java/com/framsticks/util/dispatching/Thread.java
===================================================================
--- java/main/src/main/java/com/framsticks/util/dispatching/Thread.java	(revision 99)
+++ java/main/src/main/java/com/framsticks/util/dispatching/Thread.java	(revision 100)
@@ -1,5 +1,6 @@
 package com.framsticks.util.dispatching;
 
-import org.apache.log4j.Logger;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.LogManager;
 
 import java.util.LinkedList;
@@ -15,5 +16,5 @@
 public class Thread<C> extends AbstractJoinable implements JoinableDispatcher<C> {
 
-	private static final Logger log = Logger.getLogger(Thread.class);
+	private static final Logger log = LogManager.getLogger(Thread.class);
 
 	protected final java.lang.Thread thread;
@@ -46,5 +47,5 @@
 
 	protected void routine() {
-		log.debug("starting thread " + this);
+		log.debug("starting thread {}", this);
 		assert getMonitor() != null;
 		ExceptionHandler exceptionHandler = getMonitor().getTaskExceptionHandler();
@@ -83,5 +84,5 @@
 			}
 		}
-		log.debug("finishing thread " + this);
+		log.debug("finishing thread {}", this);
 		finish();
 	}
@@ -138,5 +139,5 @@
 	protected void joinableJoin() throws InterruptedException {
 		thread.join(500);
-		log.debug("joined " + this);
+		log.debug("joined {}", this);
 	}
 
Index: java/main/src/main/java/com/framsticks/util/lang/Casting.java
===================================================================
--- java/main/src/main/java/com/framsticks/util/lang/Casting.java	(revision 99)
+++ java/main/src/main/java/com/framsticks/util/lang/Casting.java	(revision 100)
@@ -29,3 +29,10 @@
 		return class_.cast(object);
 	}
+
+	public static <T> T nullOrThrowCast(Class<T> class_, Object object) {
+		if (object == null) {
+			return null;
+		}
+		return class_.cast(object);
+	}
 }
Index: java/main/src/main/java/com/framsticks/util/lang/FlagsUtil.java
===================================================================
--- java/main/src/main/java/com/framsticks/util/lang/FlagsUtil.java	(revision 99)
+++ java/main/src/main/java/com/framsticks/util/lang/FlagsUtil.java	(revision 100)
@@ -2,5 +2,6 @@
 
 import java.lang.reflect.Field;
-import org.apache.log4j.Logger;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.LogManager;
 
 import com.framsticks.util.lang.Delimeted;
@@ -8,5 +9,5 @@
 public final class FlagsUtil {
 
-	private final static Logger log = Logger.getLogger(FlagsUtil.class);
+	private final static Logger log = LogManager.getLogger(FlagsUtil.class);
 
 	private FlagsUtil() {
@@ -41,7 +42,7 @@
 					allFlags |= Integer.parseInt(field.get(null).toString());
 				} catch (SecurityException e) {
-					log.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 | IllegalArgumentException | IllegalAccessException e) {
-					log.warn("selected flag is not known (" + flag + ")");
+					log.warn("selected flag is not known ({})", flag);
 				}
 			}
Index: java/main/src/main/java/com/framsticks/visualization/SingleViewPanel.java
===================================================================
--- java/main/src/main/java/com/framsticks/visualization/SingleViewPanel.java	(revision 99)
+++ java/main/src/main/java/com/framsticks/visualization/SingleViewPanel.java	(revision 100)
@@ -1,7 +1,7 @@
 package com.framsticks.visualization;
 
-import com.framsticks.gui.Panel;
+import com.framsticks.gui.TreePanel;
 import com.framsticks.model.Model;
-import com.framsticks.params.AccessInterface;
+import com.framsticks.params.Access;
 
 import javax.swing.*;
@@ -12,9 +12,9 @@
  */
 @SuppressWarnings("serial")
-public class SingleViewPanel extends Panel {
+public class SingleViewPanel extends TreePanel {
 
 	Viewer viewer;
 
-	public SingleViewPanel(Panel.Parameters parameters) {
+	public SingleViewPanel(TreePanel.Parameters parameters) {
 		super(parameters);
 		//viewer = new Viewer();
@@ -26,5 +26,5 @@
 
 	@Override
-	public void pullValuesFromLocalToUser(AccessInterface access) {
+	public void pullValuesFromLocalToUser(Access access) {
 		Object object = access.getSelected();
 		if (!(object instanceof Model)) {
Index: java/main/src/main/java/com/framsticks/visualization/SingleViewPanelProvider.java
===================================================================
--- java/main/src/main/java/com/framsticks/visualization/SingleViewPanelProvider.java	(revision 99)
+++ java/main/src/main/java/com/framsticks/visualization/SingleViewPanelProvider.java	(revision 100)
@@ -1,6 +1,6 @@
 package com.framsticks.visualization;
 
-import com.framsticks.gui.Panel;
 import com.framsticks.gui.PanelProvider;
+import com.framsticks.gui.TreePanel;
 
 /**
@@ -9,5 +9,5 @@
 public class SingleViewPanelProvider implements PanelProvider {
 	@Override
-	public Panel providePanel(Panel.Parameters parameters) {
+	public TreePanel providePanel(TreePanel.Parameters parameters) {
 		if (parameters.param.getContainedTypeName().equals("Model")) {
 			return new SingleViewPanel(parameters);
Index: java/main/src/main/java/com/framsticks/visualization/Viewer.java
===================================================================
--- java/main/src/main/java/com/framsticks/visualization/Viewer.java	(revision 99)
+++ java/main/src/main/java/com/framsticks/visualization/Viewer.java	(revision 100)
@@ -19,9 +19,10 @@
 import java.io.*;
 
-import org.apache.log4j.Logger;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.LogManager;
 
 public class Viewer {
 
-	private static Logger log = Logger.getLogger(Viewer.class);
+	private static Logger log = LogManager.getLogger(Viewer.class);
 
 	Canvas3D canvas3d;
Index: java/main/src/main/java/com/framsticks/visualization/ViewerTest.java
===================================================================
--- java/main/src/main/java/com/framsticks/visualization/ViewerTest.java	(revision 99)
+++ java/main/src/main/java/com/framsticks/visualization/ViewerTest.java	(revision 100)
@@ -3,5 +3,6 @@
 import com.sun.j3d.utils.universe.*;
 import com.sun.j3d.utils.geometry.ColorCube;
-import org.apache.log4j.Logger;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.LogManager;
 
 import javax.media.j3d.*;
@@ -17,5 +18,5 @@
 @SuppressWarnings("serial")
 public class ViewerTest extends JPanel {
-	private static final Logger log = Logger.getLogger(ViewerTest.class.getName());
+	private static final Logger log = LogManager.getLogger(ViewerTest.class.getName());
 
 	private SimpleUniverse univ = null;
Index: java/main/src/main/resources/configs/common-columns.xml
===================================================================
--- java/main/src/main/resources/configs/common-columns.xml	(revision 100)
+++ java/main/src/main/resources/configs/common-columns.xml	(revision 100)
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<AutoInjector>
+	<ColumnsConfig className="Genotype" columnsNames="uid name mutate" />
+	<ColumnsConfig className="Part" columnsNames="x y z" />
+</AutoInjector>
Index: java/main/src/main/resources/configs/framsticks.xml
===================================================================
--- java/main/src/main/resources/configs/framsticks.xml	(revision 99)
+++ java/main/src/main/resources/configs/framsticks.xml	(revision 100)
@@ -21,5 +21,6 @@
 		<!-- </LocalTree> -->
 		<RemoteTree name="remote" address="localhost:9007" />
-		<ColumnsConfig className="Genotype" columnsNames="uid name" />
+		<include resource="/configs/common-columns.xml" />
+		<!-- <ColumnsConfig className="Genotype" columnsNames="uid name" /> -->
 	</Browser>
 	<Server name="server" port="9007">
Index: java/main/src/main/resources/configs/log4j.properties
===================================================================
--- java/main/src/main/resources/configs/log4j.properties	(revision 99)
+++ 	(revision )
@@ -1,61 +1,0 @@
-# -------------------------------------------------------------------
-# Global logger configuration
-# -------------------------------------------------------------------
-#log4j.rootLogger=INFO, STDOUT, FILE
-log4j.rootLogger=DEBUG, STDOUT
-
-
-# -------------------------------------------------------------------
-# Disable certain libraries from spamming the output
-# -------------------------------------------------------------------
-
-# Apache commons
-log4j.logger.org.apache.commons=WARN
-
-# HttpClient
-log4j.logger.httpclient=WARN
-
-
-# -------------------------------------------------------------------
-# Define appenders.
-# -------------------------------------------------------------------
-
-# A plain console appender
-log4j.appender.STDOUT=org.apache.log4j.ConsoleAppender
-log4j.appender.STDOUT.Target=System.out
-log4j.appender.STDOUT.layout=org.apache.log4j.PatternLayout
-log4j.appender.STDOUT.layout.ConversionPattern=%d{ABSOLUTE} [%-5p] [%t] %c -- %m%n
-
-
-log4j.logger.com.framsticks=INFO
-# log4j.logger.com.framsticks.gui.table=DEBUG
-# log4j.logger.com.framsticks.gui.Panel=DEBUG
-# log4j.logger.com.framsticks.remote.RemoteTree=DEBUG
-# log4j.logger.com.framsticks.gui.Frame=DEBUG
-# log4j.logger.com.framsticks.gui.controls.ProcedureControl=DEBUG
-# log4j.logger.com.framsticks.params.ReflectionAccess=TRACE
-# log4j.logger.com.framsticks.util.dispatching.Dispatching=DEBUG
-# log4j.logger.com.framsticks.util.dispatching.AbstractJoinable=DEBUG
-# log4j.logger.com.framsticks.util.dispatching.JoinableCollection=DEBUG
-
-# log4j.logger.com.framsticks.gui=DEBUG
-# 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.gui.TreeNode=DEBUG
-#log4j.logger.com.framsticks.gui.components.CheckBox=DEBUG
-
-#log4j.logger.com.framsticks.core=DEBUG
-#log4j.logger.com.framsticks.gui.TreeNode=TRACE
-#log4j.logger.com.framsticks.gui.ObjectPanel=TRACE
-#log4j.logger.com.framsticks.communication=DEBUG
-#log4j.logger.com.framsticks.communication.ServerConnection=DEBUG
-#log4j.logger.com.framsticks.portals=DEBUG
-#log4j.logger.com.framsticks.gui=DEBUG
-#log4j.logger.com.framsticks.dumping.LoadStream=TRACE
Index: java/main/src/main/resources/log4j2.xml
===================================================================
--- java/main/src/main/resources/log4j2.xml	(revision 100)
+++ java/main/src/main/resources/log4j2.xml	(revision 100)
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<configuration status="WARN">
+	<appenders>
+		<Console name="Console" target="SYSTEM_OUT">
+			<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
+		</Console>
+		<File name="File" fileName="framsticks.log">
+			<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
+		</File>
+	</appenders>
+	<loggers>
+		<!-- <logger name="com.framsticks.hosting.Cli" level="debug" /> -->
+		<!-- <logger name="com.framsticks.gui.tree.TreeModel" level="debug" /> -->
+		<!-- <logger name="com.framsticks.params.SimpleAbstractAccess" level="debug" /> -->
+		<!-- <logger name="com.framsticks.gui.Frame" level="debug" /> -->
+		<root level="info">
+			<appender-ref ref="Console"/>
+			<appender-ref ref="File"/>
+		</root>
+	</loggers>
+</configuration>
Index: java/main/src/test/java/com/framsticks/core/ListChangeTest.java
===================================================================
--- java/main/src/test/java/com/framsticks/core/ListChangeTest.java	(revision 99)
+++ java/main/src/test/java/com/framsticks/core/ListChangeTest.java	(revision 100)
@@ -1,3 +1,5 @@
 package com.framsticks.core;
+
+import java.util.Arrays;
 
 import org.testng.annotations.BeforeMethod;
@@ -6,4 +8,5 @@
 import com.framsticks.core.ListChange.Action;
 import com.framsticks.params.FramsClass;
+import com.framsticks.params.ListSink;
 import com.framsticks.params.ListSource;
 import com.framsticks.params.ReflectionAccess;
@@ -57,9 +60,13 @@
 	@Test(dependsOnMethods = "createReflectionAccess")
 	public void load() throws Exception {
-		access.select(listChange).load(ListSource.createFrom("type:2", "pos:5", "id:test"));
+		access.select(listChange).load(ListSource.createFrom("type:2", "pos:0", "id:test"));
 
 		assertThat(listChange.action).isEqualTo(Action.Modify);
-		assertThat(listChange.position).isEqualTo(5);
+		assertThat(listChange.position).isEqualTo(0);
 		assertThat(listChange.identifier).isEqualTo("test");
+
+		ListSink sink = new ListSink();
+		access.select(listChange).save(sink);
+		assertThat(sink.getOut()).isEqualTo(Arrays.asList("ListChange:", "type:2", "pos:0", "id:test", ""));
 	}
 
Index: java/main/src/test/java/com/framsticks/core/LocalTreeTest.java
===================================================================
--- java/main/src/test/java/com/framsticks/core/LocalTreeTest.java	(revision 99)
+++ java/main/src/test/java/com/framsticks/core/LocalTreeTest.java	(revision 100)
@@ -16,5 +16,5 @@
 import com.framsticks.util.dispatching.Monitor;
 import com.framsticks.util.dispatching.RunAt;
-import com.framsticks.params.AccessInterface;
+import com.framsticks.params.Access;
 import com.framsticks.params.ReflectionAccess;
 import com.framsticks.params.types.FloatParam;
@@ -72,5 +72,5 @@
 				Path path = Path.to(tree, "/");
 				assertThat(path.isResolved());
-				AccessInterface access = TreeOperations.bindAccess(path);
+				Access access = TreeOperations.bindAccess(path);
 				assertThat(access.get("se", Double.class)).isEqualTo(1.0);
 
Index: java/main/src/test/java/com/framsticks/dumping/StreamTest.java
===================================================================
--- java/main/src/test/java/com/framsticks/dumping/StreamTest.java	(revision 99)
+++ java/main/src/test/java/com/framsticks/dumping/StreamTest.java	(revision 100)
@@ -16,5 +16,5 @@
 		// 				public void result(Path result, Exception e) {
 		// 					if (e != null) {
-		// 						log.error("failed to load file: " + e);
+		// 						log.error("failed to load file: {}", e);
 		// 						fireRun(e);
 		// 						return;
@@ -26,5 +26,5 @@
 		// 			stream.load();
 		// 		} catch (IOException e) {
-		// 			log.error("io failure: " + e);
+		// 			log.error("io failure: {}", e);
 		// 			fireRun(e);
 		// 		}
Index: java/main/src/test/java/com/framsticks/gui/BrowserBaseTest.java
===================================================================
--- java/main/src/test/java/com/framsticks/gui/BrowserBaseTest.java	(revision 99)
+++ java/main/src/test/java/com/framsticks/gui/BrowserBaseTest.java	(revision 100)
@@ -3,5 +3,6 @@
 import javax.swing.JFrame;
 
-import org.apache.log4j.Logger;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.LogManager;
 import org.fest.swing.edt.GuiQuery;
 import org.fest.swing.fixture.FrameFixture;
@@ -18,5 +19,5 @@
 public abstract class BrowserBaseTest extends GuiTest {
 
-	private static final Logger log = Logger.getLogger(BrowserTest.class);
+	private static final Logger log = LogManager.getLogger(BrowserTest.class);
 
 	protected Browser browser;
@@ -52,4 +53,5 @@
 		Dispatching.sleep(2.0);
 		tree.expandPath(path);
+		Dispatching.sleep(2.0);
 		robot.waitForIdle();
 	}
Index: java/main/src/test/java/com/framsticks/gui/BrowserTest.java
===================================================================
--- java/main/src/test/java/com/framsticks/gui/BrowserTest.java	(revision 99)
+++ java/main/src/test/java/com/framsticks/gui/BrowserTest.java	(revision 100)
@@ -7,5 +7,6 @@
 
 
-import org.apache.log4j.Logger;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.LogManager;
 import org.fest.swing.edt.GuiTask;
 import org.testng.annotations.Test;
@@ -17,5 +18,5 @@
 public class BrowserTest extends BrowserBaseTest {
 
-	private static final Logger log = Logger.getLogger(BrowserTest.class);
+	private static final Logger log = LogManager.getLogger(BrowserTest.class);
 
 	RemoteTree localhost;
@@ -34,5 +35,5 @@
 	}
 
-	@Test(timeOut = 30000)
+	@Test(timeOut = 60000)
 	public void testShow() {
 		Dispatching.synchronize(localhost, 1.0);
Index: java/main/src/test/java/com/framsticks/gui/LocalTreeBrowserTest.java
===================================================================
--- java/main/src/test/java/com/framsticks/gui/LocalTreeBrowserTest.java	(revision 99)
+++ java/main/src/test/java/com/framsticks/gui/LocalTreeBrowserTest.java	(revision 100)
@@ -29,5 +29,5 @@
 	}
 
-	@Test(timeOut = 10000)
+	@Test(timeOut = 30000)
 	public void testShow() {
 		tree.dispatch(new RunAt<Tree>(failOnException) {
Index: java/main/src/test/java/com/framsticks/gui/ProcedureBrowserTest.java
===================================================================
--- java/main/src/test/java/com/framsticks/gui/ProcedureBrowserTest.java	(revision 99)
+++ java/main/src/test/java/com/framsticks/gui/ProcedureBrowserTest.java	(revision 100)
@@ -10,5 +10,5 @@
 import com.framsticks.core.Tree;
 import com.framsticks.core.LocalTree;
-import com.framsticks.params.AccessInterface;
+import com.framsticks.params.Access;
 import com.framsticks.params.EventListener;
 import com.framsticks.params.FramsClass;
@@ -62,8 +62,7 @@
 			@Override
 			protected void runAt() {
-				AccessInterface access = bindAccess(tree, "/");
+				Access access = bindAccess(tree, "/");
 				assertThat(access).isInstanceOf(ReflectionAccess.class);
 				FramsClass framsClass = access.getFramsClass();
-				assertThat(framsClass.getParamCount()).isEqualTo(5);
 				assertThat(framsClass.getParam(0).getId()).isEqualTo("name");
 				assertThat(framsClass.getParam(1).getId()).isEqualTo("history");
@@ -94,5 +93,5 @@
 			@Override
 			protected void runAt() {
-				AccessInterface access = bindAccess(tree, "/");
+				Access access = bindAccess(tree, "/");
 				assertThat(access.get("history", String.class)).isEqualTo("initial|Żółw|");
 
@@ -107,5 +106,5 @@
 			@Override
 			protected void runAt() {
-				AccessInterface access = bindAccess(tree, "/");
+				Access access = bindAccess(tree, "/");
 				assertThat(access.get("history", String.class)).isEqualTo("");
 
Index: java/main/src/test/java/com/framsticks/hosting/ServerTest.java
===================================================================
--- java/main/src/test/java/com/framsticks/hosting/ServerTest.java	(revision 99)
+++ java/main/src/test/java/com/framsticks/hosting/ServerTest.java	(revision 100)
@@ -8,4 +8,5 @@
 import org.testng.annotations.Test;
 
+import com.framsticks.core.ListChange;
 import com.framsticks.core.LocalTree;
 import com.framsticks.core.Path;
@@ -18,9 +19,10 @@
 import com.framsticks.core.Tree;
 import com.framsticks.params.FramsClass;
-import com.framsticks.params.AccessInterface;
+import com.framsticks.params.Access;
 import com.framsticks.params.EventListener;
 import com.framsticks.params.PrimitiveParam;
 import com.framsticks.params.PropertiesAccess;
 import com.framsticks.params.types.EventParam;
+import com.framsticks.params.types.StringParam;
 // import com.framsticks.params.types.EventParam;
 import com.framsticks.params.types.ProcedureParam;
@@ -44,5 +46,9 @@
 	protected TestClass hostedObject;
 	protected EventListener<ChangeEvent> listener;
+	protected EventListener<ListChange> childListener;
+
 	protected List<String> listenerArguments = new LinkedList<>();
+	protected List<ListChange> childrenChanges = new LinkedList<>();
+
 
 	@Override
@@ -90,5 +96,5 @@
 				assertThat(path.isResolved()).isTrue();
 				remotePath = path;
-				AccessInterface access = bindAccess(path);
+				Access access = bindAccess(path);
 				assertThat(access).isInstanceOf(PropertiesAccess.class);
 				assertThat(access.get("name", String.class)).isEqualTo("a test name");
@@ -167,5 +173,54 @@
 	}
 
-	@Test(dependsOnMethods = "callMethod")
+
+	@Test(dependsOnMethods = "deregisterListener")
+	public void registerChildListener() {
+
+		childListener = new EventListener<ListChange>() {
+			@Override
+			public void action(ListChange listChange) {
+				childrenChanges.add(listChange);
+			}
+		};
+
+		addListener(remotePath, remoteTestFramsClass.getParamEntry("children_changed", EventParam.class), childListener, ListChange.class, produceWaiter(1.0).passInFuture(Void.class));
+	}
+
+	@Test(dependsOnMethods = "registerChildListener")
+	public void createChild() {
+		final Waiter waiter = produceWaiter(2.0);
+		call(remotePath, "createChild", new Object[] { "a child" }, produceWaiter(2.0).passInFuture(Object.class));
+		call(remotePath, "createChild", new Object[] { "another child" }, produceWaiter(2.0).passInFuture(Object.class));
+
+		tryGet(remote, "/testClass/children/c0", new FutureHandler<Path>(failOnException) {
+
+			@Override
+			protected void result(Path result) {
+				set(result, getFramsClass(result).getParamEntry("name", StringParam.class), "new_name", new FutureHandler<Integer>(failOnException) {
+
+					@Override
+					protected void result(Integer result) {
+						waiter.pass();
+					}
+				});
+			}
+		});
+	}
+
+	@Test(dependsOnMethods = "createChild")
+	public void deregisterChildListener() {
+		removeListener(remotePath, remoteTestFramsClass.getParamEntry("children_changed", EventParam.class), childListener, produceWaiter(1.0).passInFuture(Void.class));
+	}
+
+	@Test(dependsOnMethods = "deregisterChildListener")
+	public void checkListChanges() {
+		assertThat(childrenChanges).isEqualTo(Arrays.asList(
+			new ListChange(ListChange.Action.Add, 0, "c0"),
+			new ListChange(ListChange.Action.Add, 1, "c1"),
+			new ListChange(ListChange.Action.Modify, 0, "c0")
+		));
+	}
+
+	@Test(dependsOnMethods = "checkListChanges")
 	public void endWait() {
 		monitor.useFor(1.0);
Index: java/main/src/test/java/com/framsticks/model/ModelPackageTest.java
===================================================================
--- java/main/src/test/java/com/framsticks/model/ModelPackageTest.java	(revision 99)
+++ java/main/src/test/java/com/framsticks/model/ModelPackageTest.java	(revision 100)
@@ -21,5 +21,4 @@
 	@Test(dataProvider = "classesList")
 	public void testFramsClass(Class<?> javaClass, String name, int paramCount, Object[][] paramsTests) throws InstantiationException, IllegalAccessException {
-		// log.info("testing " + name + " " + javaClass + " " + Package.class.getResource(filename));
 		String filename = "/info/" + name + ".info";
 		InputStream stream = ModelPackage.class.getResourceAsStream(filename);
Index: java/main/src/test/java/com/framsticks/params/FramsClassBuilderTest.java
===================================================================
--- java/main/src/test/java/com/framsticks/params/FramsClassBuilderTest.java	(revision 99)
+++ java/main/src/test/java/com/framsticks/params/FramsClassBuilderTest.java	(revision 100)
@@ -34,5 +34,5 @@
 	@Test
 	public void checkProcedureParams() {
-		assertThat(framsClass.getParamCount()).isEqualTo(5);
+		assertThat(framsClass.getParamCount()).isEqualTo(8);
 
 		assertThat(framsClass.getParam("name")).isInstanceOf(StringParam.class);
@@ -80,4 +80,20 @@
 					"name:ResetHistory",
 					"type:p()",
+					"",
+					"prop:",
+					"id:children",
+					"name:Children",
+					"type:l TestChild uid",
+					"flags:1",
+					"",
+					"prop:",
+					"id:createChild",
+					"name:CreateChild",
+					"type:p(s arg0)",
+					"",
+					"prop:",
+					"id:children_changed",
+					"name:ChildrenListener",
+					"type:e ListChange",
 					""
 				)
Index: java/main/src/test/java/com/framsticks/params/ParamBuilderTest.java
===================================================================
--- java/main/src/test/java/com/framsticks/params/ParamBuilderTest.java	(revision 99)
+++ java/main/src/test/java/com/framsticks/params/ParamBuilderTest.java	(revision 100)
@@ -14,5 +14,5 @@
 	ParamBuilder builder;
 	FramsClass builderFramsClass;
-	AccessInterface access;
+	Access access;
 
 	@Test
@@ -34,5 +34,5 @@
 		MultiParamLoader loader = new MultiParamLoader();
 		loader.setNewSource(source);
-		loader.addAccessInterface(access);
+		loader.addAccess(access);
 		loader.addBreakCondition(MultiParamLoader.Status.AfterObject);
 
Index: java/main/src/test/java/com/framsticks/parsers/F0ParserTest.java
===================================================================
--- java/main/src/test/java/com/framsticks/parsers/F0ParserTest.java	(revision 99)
+++ java/main/src/test/java/com/framsticks/parsers/F0ParserTest.java	(revision 100)
@@ -24,5 +24,5 @@
 
 	private Schema schema;
-	private List<AccessInterface> accesses;
+	private List<Access> accesses;
 	private List<ModelComponent> components;
 	private Model model;
@@ -72,6 +72,6 @@
 
 	@Test(dependsOnMethods = {"readF0"})
-	public void stripAccessInterface() {
-		components = Util.stripAccessInterface(accesses, ModelComponent.class);
+	public void stripAccess() {
+		components = Util.stripAccess(accesses, ModelComponent.class);
 
 		assertThat(components.get(1)).isInstanceOf(Part.class);
@@ -81,5 +81,5 @@
 	}
 
-	@Test(dependsOnMethods = {"stripAccessInterface"})
+	@Test(dependsOnMethods = {"stripAccess"})
 	public void buildModel() {
 		model = new ModelBuilder().addComponents(components).finish();
Index: java/main/src/test/java/com/framsticks/test/TestConfiguration.java
===================================================================
--- java/main/src/test/java/com/framsticks/test/TestConfiguration.java	(revision 99)
+++ java/main/src/test/java/com/framsticks/test/TestConfiguration.java	(revision 100)
@@ -6,6 +6,6 @@
 import java.util.Set;
 
-import org.apache.log4j.Logger;
-import org.apache.log4j.PropertyConfigurator;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.LogManager;
 import org.testng.annotations.*;
 
@@ -21,10 +21,9 @@
 public class TestConfiguration {
 
-	private static final Logger log = Logger.getLogger(TestConfiguration.class);
+	private static final Logger log = LogManager.getLogger(TestConfiguration.class);
 
 	@BeforeClass
 	public void setUpConfiguration() {
-		PropertyConfigurator.configure(TestConfiguration.class.getResource("/log4j.properties"));
-		log.info("testing " + this.getClass());
+		log.info("testing {}", this.getClass());
 	}
 
@@ -86,10 +85,14 @@
 	@BeforeMethod
 	public void clearWaiters() {
-		waiters.clear();
+		synchronized (waiters) {
+			waiters.clear();
+		}
 	}
 
 	protected Dispatching.Waiter produceWaiter(double timeOut) {
 		Waiter waiter = new Waiter(timeOut, failOnException);
-		waiters.add(waiter);
+		synchronized (waiters) {
+			waiters.add(waiter);
+		}
 		return waiter;
 	}
@@ -98,5 +101,5 @@
 		@Override
 		public void handle(FramsticksException e) {
-			log.error("passing exception as assertion in " + TestConfiguration.this.getClass(), e);
+			log.error("passing exception as assertion in {}", TestConfiguration.this.getClass(), e);
 			addAsyncAssertion(e);
 		}
Index: java/main/src/test/resources/log4j.properties
===================================================================
--- java/main/src/test/resources/log4j.properties	(revision 99)
+++ 	(revision )
@@ -1,43 +1,0 @@
-# -------------------------------------------------------------------
-# Global logger configuration
-# -------------------------------------------------------------------
-#log4j.rootLogger=INFO, STDOUT, FILE
-log4j.rootLogger=DEBUG, STDOUT
-
-
-# -------------------------------------------------------------------
-# Disable certain libraries from spamming the output
-# -------------------------------------------------------------------
-
-# Apache commons
-log4j.logger.org.apache.commons=WARN
-
-# HttpClient
-log4j.logger.httpclient=WARN
-
-# -------------------------------------------------------------------
-# Define appenders.
-# -------------------------------------------------------------------
-
-# A plain console appender
-log4j.appender.STDOUT=org.apache.log4j.ConsoleAppender
-log4j.appender.STDOUT.Target=System.out
-log4j.appender.STDOUT.layout=org.apache.log4j.PatternLayout
-log4j.appender.STDOUT.layout.ConversionPattern=%d{ABSOLUTE} [%-5p] [%t] %c -- %m%n
-
-log4j.logger.com.framsticks=WARN
-log4j.logger.com.framsticks.test.TestConfiguration=INFO
-# log4j.logger.com.framsticks.hosting.Cli=DEBUG
-# log4j.logger.com.framsticks.core.AbstractTree=DEBUG
-# log4j.logger.com.framsticks.remote.RemoteTree=DEBUG
-# log4j.logger.com.framsticks.gui.console.TrackConsole=DEBUG
-# log4j.logger.com.framsticks.gui.controls.ProcedureControl=DEBUG
-# log4j.logger.com.framsticks.test.TestClass=DEBUG
-# log4j.logger.com.framsticks.communication.ServerConnection=TRACE
-# log4j.logger.com.framsticks.util.dispatching.Dispatching=DEBUG
-# log4j.logger.com.framsticks.parsers.F0Writer=TRACE
-# log4j.logger.com.framsticks.running=DEBUG
-# log4j.logger.com.framsticks.parsers.XmlLoader=DEBUG
-# log4j.logger.com.framsticks.parsers.MultiParamLoader=TRACE
-# log4j.logger.com.framsticks.gui.controls.SliderControl=TRACE
-# log4j.logger.com.framsticks.communication.ClientConnection=DEBUG
Index: java/main/src/test/resources/log4j2.xml
===================================================================
--- java/main/src/test/resources/log4j2.xml	(revision 100)
+++ java/main/src/test/resources/log4j2.xml	(revision 100)
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<configuration status="WARN">
+	<appenders>
+		<Console name="Console" target="SYSTEM_OUT">
+			<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
+		</Console>
+	</appenders>
+	<loggers>
+		<logger name="com.framsticks" level="warn" />
+		<logger name="com.framsticks.test.TestConfiguration" level="info" />
+		<root level="info">
+			<appender-ref ref="Console"/>
+		</root>
+	</loggers>
+</configuration>
