]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.databoard/src/org/simantics/databoard/accessor/wire/WireClient.java
Fixed all line endings of the repository
[simantics/platform.git] / bundles / org.simantics.databoard / src / org / simantics / databoard / accessor / wire / WireClient.java
index 0fcafe1ce105350b4a018d7f5dbe9d48bda10ed8..35b7951e87446d8306220689a39b52f1f661b05e 100644 (file)
-/*******************************************************************************\r
- * Copyright (c) 2010- Association for Decentralized Information Management in\r
- * Industry THTH ry.\r
- * All rights reserved. This program and the accompanying materials\r
- * are made available under the terms of the Eclipse Public License v1.0\r
- * which accompanies this distribution, and is available at\r
- * http://www.eclipse.org/legal/epl-v10.html\r
- * \r
- * Contributors:\r
- *    VTT Technical Research Centre of Finland - initial API and implementation\r
- *******************************************************************************/\r
-package org.simantics.databoard.accessor.wire;\r
-\r
-import java.lang.ref.ReferenceQueue;\r
-import java.lang.ref.WeakReference;\r
-import java.util.ArrayList;\r
-import java.util.Collection;\r
-import java.util.HashMap;\r
-import java.util.LinkedList;\r
-import java.util.List;\r
-import java.util.Map;\r
-import java.util.Map.Entry;\r
-import java.util.TreeMap;\r
-import java.util.concurrent.CopyOnWriteArrayList;\r
-import java.util.concurrent.Executor;\r
-\r
-import org.simantics.databoard.Bindings;\r
-import org.simantics.databoard.Datatypes;\r
-import org.simantics.databoard.Methods;\r
-import org.simantics.databoard.accessor.Accessor;\r
-import org.simantics.databoard.accessor.ArrayAccessor;\r
-import org.simantics.databoard.accessor.BooleanAccessor;\r
-import org.simantics.databoard.accessor.ByteAccessor;\r
-import org.simantics.databoard.accessor.CloseableAccessor;\r
-import org.simantics.databoard.accessor.DoubleAccessor;\r
-import org.simantics.databoard.accessor.FloatAccessor;\r
-import org.simantics.databoard.accessor.IntegerAccessor;\r
-import org.simantics.databoard.accessor.LongAccessor;\r
-import org.simantics.databoard.accessor.MapAccessor;\r
-import org.simantics.databoard.accessor.OptionalAccessor;\r
-import org.simantics.databoard.accessor.RecordAccessor;\r
-import org.simantics.databoard.accessor.StringAccessor;\r
-import org.simantics.databoard.accessor.UnionAccessor;\r
-import org.simantics.databoard.accessor.VariantAccessor;\r
-import org.simantics.databoard.accessor.error.AccessorConstructionException;\r
-import org.simantics.databoard.accessor.error.AccessorException;\r
-import org.simantics.databoard.accessor.error.ReferenceException;\r
-import org.simantics.databoard.accessor.event.ArrayElementRemoved;\r
-import org.simantics.databoard.accessor.event.Event;\r
-import org.simantics.databoard.accessor.event.MapEntryAdded;\r
-import org.simantics.databoard.accessor.event.MapEntryRemoved;\r
-import org.simantics.databoard.accessor.event.OptionalValueAssigned;\r
-import org.simantics.databoard.accessor.event.OptionalValueRemoved;\r
-import org.simantics.databoard.accessor.event.ValueAssigned;\r
-import org.simantics.databoard.accessor.impl.ListenerEntry;\r
-import org.simantics.databoard.accessor.interestset.InterestSet;\r
-import org.simantics.databoard.accessor.reference.ChildReference;\r
-import org.simantics.databoard.accessor.reference.ComponentReference;\r
-import org.simantics.databoard.accessor.reference.IndexReference;\r
-import org.simantics.databoard.accessor.reference.KeyReference;\r
-import org.simantics.databoard.accessor.reference.NameReference;\r
-import org.simantics.databoard.accessor.wire.IWireServer.AccessorInfo;\r
-import org.simantics.databoard.accessor.wire.IWireServer.ApplyResult;\r
-import org.simantics.databoard.adapter.AdaptException;\r
-import org.simantics.databoard.binding.ArrayBinding;\r
-import org.simantics.databoard.binding.Binding;\r
-import org.simantics.databoard.binding.MapBinding;\r
-import org.simantics.databoard.binding.error.BindingConstructionException;\r
-import org.simantics.databoard.binding.error.BindingException;\r
-import org.simantics.databoard.binding.impl.ArrayListBinding;\r
-import org.simantics.databoard.binding.impl.ObjectArrayBinding;\r
-import org.simantics.databoard.binding.impl.TreeMapBinding;\r
-import org.simantics.databoard.binding.mutable.MutableVariant;\r
-import org.simantics.databoard.method.MethodInterface;\r
-import org.simantics.databoard.type.ArrayType;\r
-import org.simantics.databoard.type.BooleanType;\r
-import org.simantics.databoard.type.ByteType;\r
-import org.simantics.databoard.type.Datatype;\r
-import org.simantics.databoard.type.DoubleType;\r
-import org.simantics.databoard.type.FloatType;\r
-import org.simantics.databoard.type.IntegerType;\r
-import org.simantics.databoard.type.LongType;\r
-import org.simantics.databoard.type.MapType;\r
-import org.simantics.databoard.type.OptionalType;\r
-import org.simantics.databoard.type.RecordType;\r
-import org.simantics.databoard.type.StringType;\r
-import org.simantics.databoard.type.UnionType;\r
-import org.simantics.databoard.type.VariantType;\r
-import org.simantics.databoard.util.BijectionMap;\r
-\r
-/**\r
- * WireAccessor provides an accessor over TCP/IP connection.\r
- * \r
- * All method invocation is blocking. WireAccessor may be accessed from \r
- * simultanous threads.\r
- * \r
- *\r
- * @author Toni Kalajainen <toni.kalajainen@vtt.fi>\r
- */\r
-public class WireClient implements IWireClient {\r
-\r
-       /** A queue of released accessors */\r
-       ReferenceQueue<WireAccessor> releaseQueue = new ReferenceQueue<WireAccessor>();\r
-       Map<ChildReference, WireAccessorReference> subAccessorMap = new HashMap<ChildReference, WireAccessorReference>();\r
-       \r
-//     Map<Integer, Accessor> accessorMap = new HashMap<Integer, Accessor>();\r
-       BijectionMap<Integer, ListenerEntry> listenerMap = new BijectionMap<Integer, ListenerEntry>();\r
-       \r
-       MethodInterface serverMi;\r
-       MethodInterface clientMi;\r
-       IWireServer server;\r
-       WireAccessor root;\r
-       \r
-       public WireClient() {\r
-               try {\r
-                       this.clientMi = Methods.bindInterface(IWireClient.class, this);\r
-               } catch (BindingConstructionException e) {\r
-                       throw new RuntimeException(e);\r
-               }\r
-       }\r
-       \r
-       public void setServerMethodInterface(MethodInterface serverMi) {\r
-               try {\r
-                       this.serverMi = serverMi;\r
-                       this.server = Methods.createProxy(IWireServer.class, serverMi);\r
-               } catch (BindingConstructionException e) {\r
-                       throw new RuntimeException(e);\r
-               }\r
-       }\r
-       \r
-       public MethodInterface getServerMethodInterface() {\r
-               return serverMi;\r
-       }\r
-       \r
-       public MethodInterface getClientMethodInterface() {\r
-               return clientMi;\r
-       }\r
-       \r
-       public void close() {\r
-               try {\r
-                       closeReleasedAccessors();                       \r
-               } catch (WireException e) {\r
-                       e.printStackTrace();\r
-               }\r
-               \r
-       }\r
-       \r
-       /**\r
-        * Create an accessor. Does not dispose or add to cache, use getAccessor instead\r
-        * @param ref\r
-        * @return\r
-        * @throws WireException\r
-        */\r
-       WireAccessor createAccessor(ChildReference ref) throws WireException {\r
-               AccessorInfo ai = server.openAccessor(ref);\r
-               if (ai.type instanceof BooleanType) {\r
-                       return new WireBoolean(ai.accessorId, ai.type, ref);\r
-               } else\r
-               if (ai.type instanceof ByteType) {\r
-                       return new WireByte(ai.accessorId, ai.type, ref);\r
-               } else \r
-               if (ai.type instanceof IntegerType) {\r
-                       return new WireInteger(ai.accessorId, ai.type, ref);\r
-               } else \r
-               if (ai.type instanceof LongType) {\r
-                       return new WireLong(ai.accessorId, ai.type, ref);\r
-               } else \r
-               if (ai.type instanceof FloatType) {\r
-                       return new WireFloat(ai.accessorId, ai.type, ref);\r
-               } else \r
-               if (ai.type instanceof DoubleType) {\r
-                       return new WireDouble(ai.accessorId, ai.type, ref);\r
-               } else  \r
-               if (ai.type instanceof StringType) {\r
-                       return new WireByte(ai.accessorId, ai.type, ref);\r
-               } else \r
-               if (ai.type instanceof MapType) {\r
-                       return new WireMap(ai.accessorId, ai.type, ref);\r
-               } else \r
-               if (ai.type instanceof OptionalType) {\r
-                       return new WireOptional(ai.accessorId, ai.type, ref);\r
-               } else \r
-               if (ai.type instanceof RecordType) {\r
-                       return new WireRecord(ai.accessorId, ai.type, ref);\r
-               } else \r
-               if (ai.type instanceof UnionType) {\r
-                       return new WireUnion(ai.accessorId, ai.type, ref);\r
-               } else \r
-               if (ai.type instanceof VariantType) {\r
-                       return new WireVariant(ai.accessorId, ai.type, ref);\r
-               } \r
-               throw new WireException("error, unknown data type "+ai.type);\r
-       }\r
-       \r
-       /**\r
-        * Create or get wire accessor\r
-        * @param ref path from root\r
-        * @return wire accessor\r
-        * @throws WireException\r
-        */\r
-       public WireAccessor getAccessor(ChildReference ref) throws WireException {\r
-               synchronized(subAccessorMap) {\r
-                       // Rseult Check cache\r
-                       closeReleasedAccessors();\r
-                       WireAccessorReference war = subAccessorMap.get(ref);\r
-                       WireAccessor result = war == null ? null : war.get();\r
-                       if (result != null) return result;\r
-                       \r
-                       result = createAccessor(ref);\r
-                       war = new WireAccessorReference(result);\r
-                       subAccessorMap.put(ref, war);\r
-                       \r
-                       return result;\r
-               }\r
-       }\r
-       \r
-       /**\r
-        * Close garbage collected accessors\r
-        * @throws WireException \r
-        */\r
-       void closeReleasedAccessors() throws WireException {\r
-               if (releaseQueue.poll()==null) return;\r
-               ArrayList<Integer> ids = new ArrayList<Integer>();\r
-               while (releaseQueue.poll() != null) {\r
-                       try {\r
-                               WireAccessorReference ref = (WireAccessorReference) releaseQueue.remove();\r
-                               ids.add( ref.accId );\r
-                       } catch (InterruptedException e) {\r
-                       }\r
-               }\r
-               // Close accessors\r
-               server.closeAccessors( ids.toArray(new Integer[ids.size()]) );\r
-       }\r
-       \r
-       @Override\r
-       public int onEvents(int lisId, Event[] events) {\r
-               ListenerEntry listener = null;\r
-               synchronized(listenerMap) {\r
-                       listener = listenerMap.getRight(lisId);\r
-               }\r
-               if (listener==null) return 0;\r
-\r
-               List<Event> list = new CopyOnWriteArrayList<Event>(events);\r
-               listener.emitEvents(list);\r
-               \r
-               return 0;\r
-       }\r
-       \r
-       class WireAccessorReference extends WeakReference<WireAccessor> {\r
-\r
-               int accId;\r
-               \r
-               public WireAccessorReference(WireAccessor referent) {\r
-                       super(referent, releaseQueue);\r
-                       this.accId = referent.accId;\r
-               }\r
-               \r
-       }\r
-       \r
-       abstract class WireAccessor implements Accessor, CloseableAccessor {\r
-               int accId;\r
-               ChildReference ref;\r
-               Datatype type;          \r
-               \r
-               WireAccessor(int accId, Datatype type, ChildReference ref) {\r
-                       this.accId = accId;\r
-                       this.type = type;\r
-                       this.ref = ref;                 \r
-               }\r
-\r
-               @Override\r
-               public Object getValue(Binding binding) throws AccessorException {\r
-                       try {\r
-                               MutableVariant value = server.getValue(accId);\r
-                               return value.getValue(binding);\r
-                       } catch (WireException e) {\r
-                               throw new AccessorException(e);\r
-                       } catch (AdaptException e) {\r
-                               throw new AccessorException(e);\r
-                       }\r
-               }\r
-               \r
-               @Override\r
-               public void getValue(Binding binding, Object obj)\r
-                               throws AccessorException {\r
-            try {\r
-                MutableVariant value= server.getValue(accId);\r
-                binding.readFrom(value.getBinding(), value.getValue(), obj);\r
-            } catch ( WireException e ) {\r
-                throw new AccessorException(e);\r
-            } catch ( BindingException e ) {\r
-                throw new AccessorException(e);\r
-            }\r
-               }\r
-               \r
-               @Override\r
-               public boolean getValue(ChildReference path, Binding binding, Object obj) throws AccessorException {\r
-                       try {\r
-                               Accessor a = getComponent(path);\r
-                               a.getValue(binding, obj);\r
-                               return true;\r
-                       } catch (ReferenceException re) {\r
-                               return false;\r
-                       } catch (AccessorConstructionException e) {\r
-                               throw new AccessorException(e);\r
-                       }\r
-               }       \r
-               \r
-               public Object getValue(ChildReference path, Binding binding) throws AccessorException {\r
-                       try {\r
-                               Accessor a = getComponent(path);\r
-                               return a.getValue(binding);\r
-                       } catch (ReferenceException re) {\r
-                               return null;\r
-                       } catch (AccessorConstructionException e) {\r
-                               throw new AccessorException(e);\r
-                       }\r
-               }\r
-               \r
-               \r
-               void applyEvent(Event...events) throws AccessorException {\r
-                       ApplyResult result = server.apply(accId, events, false);\r
-                       if (result.error != null) throw new AccessorException( result.error );\r
-               }\r
-               \r
-               @Override\r
-               public void setValue(Binding binding, Object newValue) throws AccessorException {\r
-                       applyEvent( new ValueAssigned(binding, newValue) ); \r
-               }\r
-               \r
-               public boolean setValue(ChildReference path, Binding binding, Object obj) throws AccessorException {\r
-                       try {\r
-                               Accessor a = getComponent(path);\r
-                               a.setValue(binding, obj);\r
-                               return true;\r
-                       } catch (ReferenceException re) {\r
-                               return false;\r
-                       } catch (AccessorConstructionException e) {\r
-                               throw new AccessorException(e);\r
-                       }\r
-               }\r
-               \r
-               @SuppressWarnings("unchecked")\r
-               @Override\r
-               public <T extends Accessor> T getComponent(ChildReference reference)\r
-               throws AccessorConstructionException {\r
-                       try {\r
-                               // Create a reference from the root\r
-                               ChildReference r = ChildReference.concatenate(ref, reference);\r
-                               return (T) WireClient.this.getAccessor( r );\r
-                       } catch (WireException e) {\r
-                               throw new AccessorConstructionException( e ); \r
-                       }\r
-               }\r
-\r
-               @Override\r
-               public void apply(List<Event> changeSet, LinkedList<Event> rollback)\r
-                               throws AccessorException {\r
-                       \r
-                       ApplyResult result = server.apply(accId, changeSet.toArray(new Event[changeSet.size()]), rollback!=null);\r
-                       if (rollback!=null && result.rollbackLog!=null)\r
-                               rollback.addAll( result.rollbackLog );\r
-                       if (result.error != null) throw new AccessorException( result.error );\r
-                       \r
-               }\r
-\r
-               @Override\r
-               public Datatype type() { \r
-                       return type;\r
-               }\r
-\r
-               @Override\r
-               public void addListener(Listener listener, InterestSet interestSet,\r
-                               ChildReference pathPrefix, Executor executor) throws AccessorException {\r
-                       try {\r
-                               ListenerEntry le = new ListenerEntry(listener, interestSet, pathPrefix, executor);\r
-                               int lisId = server.addListener(accId, interestSet, pathPrefix);\r
-                               synchronized(listenerMap) {\r
-                                       listenerMap.map(lisId, le);\r
-                               }\r
-                       } catch (WireException e) {\r
-                               throw new AccessorException(e);\r
-                       }\r
-               }\r
-\r
-               @Override\r
-               public void removeListener(Listener listener) throws AccessorException {\r
-                       Integer lisId = null;\r
-                       synchronized(listenerMap) {\r
-                               for (Entry<Integer, ListenerEntry> e : listenerMap.getEntries()) {\r
-                                       if (e.getValue().listener == listener) {\r
-                                               lisId = e.getKey();\r
-                                               break;\r
-                                       }\r
-                               }\r
-                               if (lisId==null) return;\r
-                               listenerMap.removeWithLeft(lisId);\r
-                       }\r
-                       try {\r
-                               server.removeListener(lisId);\r
-                       } catch (WireException e) {\r
-                               throw new AccessorException( e );\r
-                       }                       \r
-               }\r
-               \r
-               public void close() throws AccessorException {\r
-                       try {\r
-                               server.closeAccessors( new Integer[] {accId} );\r
-                       } catch (WireException e) {\r
-                               throw new AccessorException( e );\r
-                       }\r
-               }\r
-\r
-       }\r
-       \r
-       class WireBoolean extends WireAccessor implements BooleanAccessor {\r
-\r
-               WireBoolean(int accId, Datatype type, ChildReference ref) {\r
-                       super(accId, type, ref);\r
-               }\r
-               \r
-               @Override\r
-               public BooleanType type() { \r
-                       return (BooleanType) type;\r
-               }\r
-               \r
-               @Override\r
-               public boolean getValue() throws AccessorException {\r
-                       try {\r
-                               MutableVariant value = server.getValue(accId);\r
-                               return (Boolean) value.getValue( Bindings.BOOLEAN );\r
-                       } catch (WireException e) {\r
-                               throw new AccessorException( e );\r
-                       } catch (AdaptException e) {\r
-                               throw new AccessorException( e );\r
-                       }\r
-               }\r
-\r
-               @Override\r
-               public void setValue(boolean value) throws AccessorException {\r
-                       Event e = new ValueAssigned(null, Bindings.BOOLEAN, value); \r
-                       Event[] list = new Event[] {e};\r
-                       ApplyResult result = server.apply(accId, list, false);\r
-                       if (result.error != null) throw new AccessorException( result.error );\r
-               }\r
-       }       \r
-       \r
-       class WireByte extends WireAccessor implements ByteAccessor {\r
-\r
-               WireByte(int accId, Datatype type, ChildReference ref) {\r
-                       super(accId, type, ref);\r
-               }\r
-               \r
-               @Override\r
-               public ByteType type() { \r
-                       return (ByteType) type;\r
-               }\r
-               \r
-               @Override\r
-               public byte getValue() throws AccessorException {\r
-                       try {\r
-                               MutableVariant value = server.getValue(accId);\r
-                               return (Byte) value.getValue( Bindings.BYTE );\r
-                       } catch (WireException e) {\r
-                               throw new AccessorException( e );\r
-                       } catch (AdaptException e) {\r
-                               throw new AccessorException( e );\r
-                       }\r
-               }\r
-               \r
-               @Override\r
-               public void setValue(byte value) throws AccessorException {\r
-                       Event e = new ValueAssigned(null, Bindings.BYTE, value); \r
-                       Event[] list = new Event[] {e};\r
-                       ApplyResult result = server.apply(accId, list, false);\r
-                       if (result.error != null) throw new AccessorException( result.error );\r
-               }\r
-       }\r
-\r
-       class WireInteger extends WireAccessor implements IntegerAccessor {\r
-\r
-               WireInteger(int accId, Datatype type, ChildReference ref) {\r
-                       super(accId, type, ref);\r
-               }\r
-               \r
-               @Override\r
-               public IntegerType type() { \r
-                       return (IntegerType) type;\r
-               }\r
-               \r
-               @Override\r
-               public int getValue() throws AccessorException {\r
-                       try {\r
-                               MutableVariant value = server.getValue(accId);\r
-                               return (Integer) value.getValue( Bindings.INTEGER );\r
-                       } catch (WireException e) {\r
-                               throw new AccessorException( e );\r
-                       } catch (AdaptException e) {\r
-                               throw new AccessorException( e );\r
-                       }\r
-               }\r
-\r
-               @Override\r
-               public void setValue(int value) throws AccessorException {\r
-                       Event e = new ValueAssigned(Bindings.INTEGER, value); \r
-                       Event[] list = new Event[] {e};\r
-                       ApplyResult result = server.apply(accId, list, false);\r
-                       if (result.error != null) throw new AccessorException( result.error );\r
-               }\r
-\r
-       }\r
-\r
-       class WireLong extends WireAccessor implements LongAccessor {\r
-\r
-               WireLong(int accId, Datatype type, ChildReference ref) {\r
-                       super(accId, type, ref);\r
-               }\r
-               \r
-               @Override\r
-               public LongType type() { \r
-                       return (LongType) type;\r
-               }\r
-               \r
-               @Override\r
-               public long getValue() throws AccessorException {\r
-                       try {\r
-                               MutableVariant value = server.getValue(accId);\r
-                               return (Long) value.getValue( Bindings.LONG );\r
-                       } catch (WireException e) {\r
-                               throw new AccessorException( e );\r
-                       } catch (AdaptException e) {\r
-                               throw new AccessorException( e );\r
-                       }\r
-               }\r
-\r
-               @Override\r
-               public void setValue(long value) throws AccessorException {\r
-                       Event e = new ValueAssigned(Bindings.LONG, value); \r
-                       Event[] list = new Event[] {e};\r
-                       ApplyResult result = server.apply(accId, list, false);\r
-                       if (result.error != null) throw new AccessorException( result.error );\r
-               }\r
-\r
-       }\r
-\r
-       class WireFloat extends WireAccessor implements FloatAccessor {\r
-\r
-               WireFloat(int accId, Datatype type, ChildReference ref) {\r
-                       super(accId, type, ref);\r
-               }\r
-               \r
-               @Override\r
-               public FloatType type() { \r
-                       return (FloatType) type;\r
-               }\r
-               \r
-               @Override\r
-               public float getValue() throws AccessorException {\r
-                       try {\r
-                               MutableVariant value = server.getValue(accId);\r
-                               return (Float) value.getValue( Bindings.FLOAT );\r
-                       } catch (WireException e) {\r
-                               throw new AccessorException( e );\r
-                       } catch (AdaptException e) {\r
-                               throw new AccessorException( e );\r
-                       }\r
-               }\r
-\r
-               @Override\r
-               public void setValue(float value) throws AccessorException {\r
-                       Event e = new ValueAssigned(Bindings.FLOAT, value); \r
-                       Event[] list = new Event[] {e};\r
-                       ApplyResult result = server.apply(accId, list, false);\r
-                       if (result.error != null) throw new AccessorException( result.error );\r
-               }\r
-\r
-       }\r
-\r
-       class WireDouble extends WireAccessor implements DoubleAccessor {\r
-\r
-               WireDouble(int accId, Datatype type, ChildReference ref) {\r
-                       super(accId, type, ref);\r
-               }\r
-               \r
-               @Override\r
-               public DoubleType type() { \r
-                       return (DoubleType) type;\r
-               }\r
-               \r
-               @Override\r
-               public double getValue() throws AccessorException {\r
-                       try {\r
-                               MutableVariant value = server.getValue(accId);\r
-                               return (Double) value.getValue( Bindings.DOUBLE );\r
-                       } catch (WireException e) {\r
-                               throw new AccessorException( e );\r
-                       } catch (AdaptException e) {\r
-                               throw new AccessorException( e );\r
-                       }\r
-               }\r
-\r
-               @Override\r
-               public void setValue(double value) throws AccessorException {\r
-                       Event e = new ValueAssigned(Bindings.DOUBLE, value); \r
-                       Event[] list = new Event[] {e};\r
-                       ApplyResult result = server.apply(accId, list, false);\r
-                       if (result.error != null) throw new AccessorException( result.error );\r
-               }\r
-\r
-       }\r
-\r
-       class WireArray extends WireAccessor implements ArrayAccessor {\r
-\r
-               WireArray(int accId, Datatype type, ChildReference ref) {\r
-                       super(accId, type, ref);\r
-               }\r
-               \r
-               @Override\r
-               public ArrayType type() { \r
-                       return (ArrayType) type;\r
-               }\r
-\r
-               @Override\r
-               public void add(Binding binding, Object value) throws AccessorException {\r
-                       try {\r
-                               server.addAll(accId, -1, new MutableVariant(binding, value));\r
-                       } catch (WireException e) {\r
-                               throw new AccessorException(e);\r
-                       }\r
-               }\r
-\r
-               @Override\r
-               public void addAll(Binding binding, Object[] values) throws AccessorException {\r
-                       try {\r
-                               ArrayBinding ab = new ObjectArrayBinding(new ArrayType(binding.type()), binding);\r
-                               MutableVariant array = new MutableVariant(ab, values);\r
-                               server.addAll(accId, -1, array);\r
-                       } catch (WireException e) {\r
-                               throw new AccessorException(e);\r
-                       }\r
-               }\r
-\r
-               @Override\r
-               public void addAll(int index, Binding binding, Object[] values)\r
-                               throws AccessorException {\r
-                       try {\r
-                               ArrayBinding ab = new ObjectArrayBinding(new ArrayType(binding.type()), binding);\r
-                               MutableVariant array = new MutableVariant(ab, values);\r
-                               server.addAll(accId, index, array);\r
-                       } catch (WireException e) {\r
-                               throw new AccessorException(e);\r
-                       }\r
-               }\r
-\r
-               @Override\r
-               public void add(int index, Binding binding, Object value) throws AccessorException {\r
-                       try {\r
-                               server.addAll(accId, index, new MutableVariant(binding, value));\r
-                       } catch (WireException e) {\r
-                               throw new AccessorException(e);\r
-                       }\r
-               }\r
-\r
-               @Override\r
-               public void set(int index, Binding binding, Object value)\r
-                               throws AccessorException {\r
-                       applyEvent(new ValueAssigned(new IndexReference(index), binding, value));\r
-               }\r
-\r
-               @Override\r
-               public void remove(int index, int count) throws AccessorException {\r
-                       applyEvent(new ArrayElementRemoved(index));                     \r
-               }\r
-\r
-               @SuppressWarnings("unchecked")\r
-               @Override\r
-               public <T extends Accessor> T getAccessor(int index)\r
-                               throws AccessorConstructionException {\r
-                       return (T) getComponent(new IndexReference(index));\r
-               }\r
-\r
-               @Override\r
-               public Object get(int index, Binding valueBinding)\r
-                               throws AccessorException {\r
-                       try {\r
-                               MutableVariant v = server.getArrayElement(accId, index);\r
-                               return v.getValue(valueBinding);\r
-                       } catch (WireException e) {\r
-                               throw new AccessorException(e);\r
-                       } catch (AdaptException e) {\r
-                               throw new AccessorException(e);\r
-                       }\r
-               }\r
-               \r
-               @Override\r
-               public void get(int index, Binding valueBinding, Object dst)\r
-                               throws AccessorException {\r
-                       try {\r
-                               MutableVariant v = server.getArrayElement(accId, index);\r
-                               valueBinding.readFrom(v.getBinding(), v.getValue(), v);\r
-                       } catch (WireException e) {\r
-                               throw new AccessorException(e);\r
-                       } catch (BindingException e) {\r
-                               throw new AccessorException(e);\r
-                       }\r
-               }               \r
-\r
-               @Override\r
-               public void getAll(Binding valueBinding, Object[] array)\r
-                               throws AccessorException {\r
-                       ObjectArrayBinding arrayBinding = new ObjectArrayBinding(type(), valueBinding);\r
-                       Object[] a2 = (Object[]) getValue(arrayBinding);\r
-                       System.arraycopy(a2, 0, array, 0, a2.length);                   \r
-               }\r
-\r
-               @Override\r
-               public void getAll(Binding valueBinding, Collection<Object> values)\r
-                               throws AccessorException {\r
-                       ArrayListBinding arrayBinding = new ArrayListBinding(type(), valueBinding);\r
-                       ArrayList<?> a2 = (ArrayList<?>) getValue(arrayBinding);\r
-                       values.addAll(a2);                      \r
-               }\r
-               \r
-               @Override\r
-               public void setSize(int newSize) throws AccessorException {\r
-                       throw new AccessorException("Not implemented");\r
-               }\r
-\r
-               @Override\r
-               public int size() throws AccessorException {\r
-                       try {\r
-                               return server.size(accId);\r
-                       } catch (WireException e) {\r
-                               throw new AccessorException( e );\r
-                       }\r
-               }\r
-       }\r
-       \r
-       class WireMap extends WireAccessor implements MapAccessor {\r
-\r
-               WireMap(int accId, Datatype type, ChildReference ref) {\r
-                       super(accId, type, ref);\r
-               }\r
-               \r
-               @Override\r
-               public MapType type() { \r
-                       return (MapType) type;\r
-               }               \r
-\r
-               @Override\r
-               public int size() throws AccessorException {\r
-                       try {\r
-                               return server.size(accId);\r
-                       } catch (WireException e) {\r
-                               throw new AccessorException( e );\r
-                       }\r
-               }\r
-\r
-               @Override\r
-               public Object get(Binding keyBinding, Object key, Binding valueBinding)\r
-                               throws AccessorException {\r
-                       try {\r
-                               MutableVariant value = server.getMapValue(accId, new MutableVariant(keyBinding, key));\r
-                if (value.type().equals(Datatypes.VOID)) return null;\r
-                               return value.getValue(valueBinding);\r
-                       } catch (WireException e) {\r
-                               throw new AccessorException( e );\r
-                       } catch (AdaptException e) {\r
-                               throw new AccessorException( e );\r
-                       }\r
-               }\r
-\r
-               @Override\r
-               public boolean containsKey(Binding keyBinding, Object key)\r
-                               throws AccessorException {\r
-                       try {\r
-                               return server.containsKey(accId, new MutableVariant(keyBinding, key));\r
-                       } catch (WireException e) {\r
-                               throw new AccessorException( e );\r
-                       }\r
-               }\r
-\r
-               @Override\r
-               public boolean containsValue(Binding valueBinding, Object value)\r
-                               throws AccessorException {\r
-                       try {\r
-                               return server.containsValue(accId, new MutableVariant(valueBinding, value));\r
-                       } catch (WireException e) {\r
-                               throw new AccessorException( e );\r
-                       }\r
-               }\r
-\r
-               @Override\r
-               public void put(Binding keyBinding, Object key, Binding valueBinding,\r
-                               Object value) throws AccessorException {\r
-                       applyEvent( new MapEntryAdded(new MutableVariant(keyBinding, key), new MutableVariant(valueBinding, value)) );\r
-               }\r
-\r
-               @Override\r
-               public void remove(Binding keyBinding, Object key)\r
-                               throws AccessorException {\r
-                       applyEvent( new MapEntryRemoved(new MutableVariant(keyBinding, key)) );\r
-               }\r
-\r
-               @Override\r
-               public void clear() throws AccessorException {\r
-                       try {\r
-                               server.clear(accId);\r
-                       } catch (WireException e) {\r
-                               throw new AccessorException(e);\r
-                       }                       \r
-               }\r
-\r
-               @Override\r
-               public void putAll(Binding keyBinding, Binding valueBinding,\r
-                               Map<Object, Object> from) throws AccessorException {\r
-                       \r
-                       int count = from.size();\r
-                       Event events[] = new Event[ count ];\r
-                       int i = 0;\r
-                       for (Entry<Object, Object> e : from.entrySet()) {\r
-                               MutableVariant key = new MutableVariant( keyBinding, e.getKey() );\r
-                               MutableVariant value = new MutableVariant( valueBinding, e.getValue() );\r
-                               events[i] = new MapEntryAdded( key, value );\r
-                               ++i;\r
-                       }\r
-                       applyEvent( events );                                           \r
-               }\r
-\r
-               @Override\r
-               public void putAll(Binding keyBinding, Binding valueBinding,\r
-                               Object[] keys, Object[] values) throws AccessorException {\r
-                       if (keys.length != values.length) throw new AccessorException("bad args");\r
-                       int count = keys.length;\r
-                       Event events[] = new Event[ count ];\r
-                       for (int i=0; i<count; i++) {\r
-                               events[i] = new MapEntryAdded( new MutableVariant(keyBinding, keys[i]), new MutableVariant(valueBinding, values[i]) );\r
-                       }\r
-                       applyEvent( events );                   \r
-               }\r
-\r
-               @SuppressWarnings("unchecked")\r
-        @Override\r
-               public void getAll(Binding keyBinding, Binding valueBinding,\r
-                               Map<Object, Object> to) throws AccessorException {\r
-                       MapBinding binding = new TreeMapBinding(keyBinding, valueBinding);\r
-                       TreeMap<Object, Object> v = (TreeMap<Object, Object>) getValue(binding);\r
-                       to.putAll(v);\r
-               }\r
-\r
-               @SuppressWarnings("unchecked")\r
-        @Override\r
-               public void getAll(Binding keyBinding, Binding valueBinding,\r
-                               Object[] keys, Object[] values) throws AccessorException {\r
-                       MapBinding binding = new TreeMapBinding(keyBinding, valueBinding);\r
-                       TreeMap<Object, Object> v = (TreeMap<Object, Object>) getValue(binding);\r
-                       int i=0;\r
-                       for (Entry<Object, Object> e : v.entrySet()) {\r
-                               keys[i] = e.getKey();\r
-                               values[i] = e.getValue();\r
-                               ++i;\r
-                       }\r
-               }\r
-\r
-               @Override\r
-               public Object[] getKeys(Binding keyBinding) throws AccessorException {\r
-                       try {\r
-                               MutableVariant array = server.getMapKeys(accId);\r
-                               ArrayBinding binding = new ObjectArrayBinding( keyBinding );\r
-                               return (Object[]) array.getValue(binding);\r
-                       } catch (WireException e) {\r
-                               throw new AccessorException( e );\r
-                       } catch (AdaptException e) {\r
-                               throw new AccessorException( e );\r
-                       }\r
-               }\r
-\r
-               @Override\r
-               public int count(Binding keyBinding, Object from,\r
-                               boolean fromInclusive, Object end, boolean endInclusive)\r
-                               throws AccessorException {\r
-                       throw new AccessorException("Not implemented");\r
-               }\r
-\r
-               @Override\r
-               public int getEntries(Binding keyBinding, Object from,\r
-                               boolean fromInclusive, Object end, boolean endInclusive,\r
-                               ArrayBinding keyArrayBinding, Object dstKeys,\r
-                               ArrayBinding valueArrayBinding, Object dstValues, int limit)\r
-                               throws AccessorException {\r
-                       throw new AccessorException("Not implemented");\r
-               }\r
-               \r
-\r
-               @Override\r
-               public Object[] getValues(Binding valueBinding)\r
-                               throws AccessorException {\r
-                       try {\r
-                               MutableVariant array = server.getMapValues(accId);\r
-                               ArrayBinding binding = new ObjectArrayBinding( valueBinding );\r
-                               return (Object[]) array.getValue(binding);\r
-                       } catch (WireException e) {\r
-                               throw new AccessorException( e );\r
-                       } catch (AdaptException e) {\r
-                               throw new AccessorException( e );\r
-                       }\r
-               }\r
-\r
-               @SuppressWarnings("unchecked")\r
-               @Override\r
-               public <T extends Accessor> T getValueAccessor(Binding keyBinding, Object key) throws AccessorConstructionException {\r
-                       return (T) getComponent( new KeyReference(keyBinding, key) );\r
-               }\r
-\r
-               @Override\r
-               public Object getFirstKey(Binding keyBinding) throws AccessorException {\r
-                       try {\r
-                               MutableVariant result = server.getFirstKey(accId);\r
-                if (result.type().equals(Datatypes.VOID)) return null;\r
-                               return result.getValue(keyBinding);\r
-                       } catch (WireException e) {\r
-                               throw new AccessorException(e);\r
-                       } catch (AdaptException e) {\r
-                               throw new AccessorException(e);\r
-                       }\r
-               }\r
-\r
-               @Override\r
-               public Object getLastKey(Binding keyBinding) throws AccessorException {\r
-                       try {\r
-                               MutableVariant result = server.getLastKey(accId);\r
-                if (result.type().equals(Datatypes.VOID)) return null;\r
-                               return result.getValue(keyBinding);\r
-                       } catch (WireException e) {\r
-                               throw new AccessorException(e);\r
-                       } catch (AdaptException e) {\r
-                               throw new AccessorException(e);\r
-                       }\r
-               }\r
-\r
-               @Override\r
-               public Object getLowerKey(Binding keyBinding, Object key)\r
-                               throws AccessorException {\r
-                       try {\r
-                               MutableVariant result = server.getLowerKey(accId, new MutableVariant(keyBinding, key));\r
-                               if (result.type().equals(Datatypes.VOID)) return null;\r
-                               return result.getValue(keyBinding);\r
-                       } catch (WireException e) {\r
-                               throw new AccessorException(e);\r
-                       } catch (AdaptException e) {\r
-                               throw new AccessorException(e);\r
-                       }\r
-               }\r
-\r
-               @Override\r
-               public Object getFloorKey(Binding keyBinding, Object key)\r
-                               throws AccessorException {\r
-                       try {\r
-                               MutableVariant result = server.getFloorKey(accId, new MutableVariant(keyBinding, key));\r
-                if (result.type() == Datatypes.VOID) return null;\r
-                               return result.getValue(keyBinding);\r
-                       } catch (WireException e) {\r
-                               throw new AccessorException(e);\r
-                       } catch (AdaptException e) {\r
-                               throw new AccessorException(e);\r
-                       }\r
-               }\r
-\r
-               @Override\r
-               public Object getCeilingKey(Binding keyBinding, Object key)\r
-                               throws AccessorException {\r
-                       try {\r
-                               MutableVariant result = server.getCeilingKey(accId, new MutableVariant(keyBinding, key));\r
-                if (result.type().equals(Datatypes.VOID)) return null;\r
-                               return result.getValue(keyBinding);\r
-                       } catch (WireException e) {\r
-                               throw new AccessorException(e);\r
-                       } catch (AdaptException e) {\r
-                               throw new AccessorException(e);\r
-                       }\r
-               }\r
-\r
-               @Override\r
-               public Object getHigherKey(Binding keyBinding, Object key)\r
-                               throws AccessorException {\r
-                       try {\r
-                               MutableVariant result = server.getHigherKey(accId, new MutableVariant(keyBinding, key));\r
-                if (result.type().equals(Datatypes.VOID)) return null;\r
-                               return result.getValue(keyBinding);\r
-                       } catch (WireException e) {\r
-                               throw new AccessorException(e);\r
-                       } catch (AdaptException e) {\r
-                               throw new AccessorException(e);\r
-                       }\r
-               }\r
-               \r
-       }\r
-       \r
-       class WireOptional extends WireAccessor implements OptionalAccessor {\r
-\r
-               WireOptional(int accId, Datatype type, ChildReference ref) {\r
-                       super(accId, type, ref);\r
-               }\r
-               \r
-               @Override\r
-               public OptionalType type() { \r
-                       return (OptionalType) type;\r
-               }                               \r
-\r
-               @Override\r
-               public void setNoValue() throws AccessorException {\r
-                       applyEvent( new OptionalValueRemoved() );\r
-               }\r
-\r
-               @Override\r
-               public boolean hasValue() throws AccessorException {\r
-                       try {\r
-                               return server.hasValue(accId);\r
-                       } catch (WireException e) {\r
-                               throw new AccessorException( e );                               \r
-                       }\r
-               }\r
-\r
-               @Override\r
-               public Object getComponentValue(Binding componentBinding)\r
-                               throws AccessorException {\r
-                       try {\r
-                               WireAccessor sa = createAccessor( new ComponentReference() );\r
-                               try {\r
-                                       return sa.getValue(componentBinding);\r
-                               } finally {\r
-                                       sa.close();\r
-                               }\r
-                       } catch (WireException e) {\r
-                               throw new AccessorException( e );                               \r
-                       }\r
-               }\r
-\r
-               @Override\r
-               public void setComponentValue(Binding binding, Object value)\r
-                               throws AccessorException {                      \r
-                       applyEvent(new OptionalValueAssigned(binding, value));\r
-               }\r
-\r
-               @SuppressWarnings("unchecked")\r
-               @Override\r
-               public <T extends Accessor> T getComponentAccessor()\r
-                               throws AccessorConstructionException {\r
-                       return (T) getComponent( new ComponentReference() );\r
-               }\r
-               \r
-       }\r
-       \r
-       class WireRecord extends WireAccessor implements RecordAccessor {\r
-\r
-               WireRecord(int accId, Datatype type, ChildReference ref) {\r
-                       super(accId, type, ref);\r
-               }\r
-               \r
-               @Override\r
-               public RecordType type() { \r
-                       return (RecordType) type;\r
-               }               \r
-\r
-               @Override\r
-               public int count() throws AccessorException {                   \r
-                       try {\r
-                               return server.size(accId);\r
-                       } catch (WireException e) {\r
-                               throw new AccessorException(e);\r
-                       }\r
-               }\r
-\r
-               @SuppressWarnings("unchecked")\r
-               @Override\r
-               public <T extends Accessor> T getFieldAccessor(int index)\r
-                               throws AccessorConstructionException {\r
-                       return (T) getComponent( new IndexReference(index) );\r
-               }\r
-\r
-               @SuppressWarnings("unchecked")\r
-               @Override\r
-               public <T extends Accessor> T getFieldAccessor(String fieldName)\r
-                               throws AccessorConstructionException {\r
-                       return (T) getComponent( new NameReference( fieldName ) );\r
-               }\r
-\r
-               @Override\r
-               public Object getFieldValue(String fieldName, Binding fieldBinding)\r
-                               throws AccessorException {\r
-                       int fieldIndex = type().getComponentIndex(fieldName);\r
-                       if (fieldIndex<0) throw new AccessorException("Field "+fieldName+" does not exist");\r
-                       return getFieldValue(fieldIndex, fieldBinding);\r
-               }\r
-               \r
-               @Override\r
-               public Object getFieldValue(int index, Binding fieldBinding)\r
-                               throws AccessorException {\r
-                       try {\r
-                               WireAccessor sa = createAccessor( new IndexReference(index) );\r
-                               try {\r
-                                       return sa.getValue(fieldBinding);\r
-                               } finally {\r
-                                       sa.close();\r
-                               }\r
-                       } catch (WireException e) {\r
-                               throw new AccessorException( e );                               \r
-                       }\r
-               }\r
-               \r
-               public void setFieldValue(String fieldName, Binding fieldBinding, Object value) throws AccessorException {\r
-                       int fieldIndex = type().getComponentIndex(fieldName);\r
-                       if (fieldIndex<0) throw new AccessorException("Field "+fieldName+" does not exist");\r
-                       setFieldValue(fieldIndex, fieldBinding, value);\r
-               };\r
-\r
-               @Override\r
-               public void setFieldValue(int index, Binding fieldBinding, Object value)\r
-                               throws AccessorException {\r
-                       try {\r
-                               WireAccessor sa = createAccessor( new IndexReference(index) );\r
-                               try {\r
-                                       sa.setValue(fieldBinding, value);\r
-                               } finally {\r
-                                       sa.close();\r
-                               }\r
-                       } catch (WireException e) {\r
-                               throw new AccessorException( e );                               \r
-                       }\r
-               }\r
-               \r
-       }\r
-       \r
-       class WireString extends WireAccessor implements StringAccessor {\r
-\r
-               WireString(int accId, Datatype type, ChildReference ref) {\r
-                       super(accId, type, ref);\r
-               }\r
-\r
-               @Override\r
-               public StringType type() { \r
-                       return (StringType) type;\r
-               }               \r
-\r
-               @Override\r
-               public String getValue() throws AccessorException {\r
-                       try {\r
-                               MutableVariant value = server.getValue(accId);\r
-                               return (String) value.getValue( Bindings.STRING );\r
-                       } catch (WireException e) {\r
-                               throw new AccessorException( e );\r
-                       } catch (AdaptException e) {\r
-                               throw new AccessorException( e );\r
-                       }\r
-               }\r
-\r
-               @Override\r
-               public void setValue(String newValue) throws AccessorException {\r
-                       Event e = new ValueAssigned( Bindings.STRING, newValue); \r
-                       Event[] list = new Event[] {e};\r
-                       ApplyResult result = server.apply(accId, list, false);\r
-                       if (result.error != null) throw new AccessorException( result.error );\r
-               }\r
-               \r
-       }\r
-       \r
-       class WireUnion extends WireAccessor implements UnionAccessor {\r
-\r
-               WireUnion(int accId, Datatype type, ChildReference ref) {\r
-                       super(accId, type, ref);\r
-               }\r
-               \r
-               @Override\r
-               public UnionType type() { \r
-                       return (UnionType) type;\r
-               }                               \r
-\r
-               @Override\r
-               public int count() throws AccessorException {\r
-                       try {\r
-                               return server.size(accId);\r
-                       } catch (WireException e) {\r
-                               throw new AccessorException(e);\r
-                       }\r
-               }\r
-\r
-               @Override\r
-               public int getTag() throws AccessorException {\r
-                       try {\r
-                               return server.getTag(accId);\r
-                       } catch (WireException e) {\r
-                               throw new AccessorException(e);\r
-                       }\r
-               }\r
-\r
-               @SuppressWarnings("unchecked")\r
-               @Override\r
-               public <T extends Accessor> T getComponentAccessor()\r
-                               throws AccessorConstructionException {\r
-                       return (T) getComponent(new ComponentReference());\r
-               }\r
-\r
-               @Override\r
-               public Object getComponentValue(Binding componentBinding)\r
-                               throws AccessorException {\r
-                       try {\r
-                               WireAccessor sa = createAccessor( new ComponentReference() );\r
-                               try {\r
-                                       return sa.getValue(componentBinding);\r
-                               } finally {\r
-                                       sa.close();\r
-                               }\r
-                       } catch (WireException e) {\r
-                               throw new AccessorException( e );                               \r
-                       }\r
-               }\r
-\r
-               @Override\r
-               public void setComponentValue(int tag, Binding componentBinding,\r
-                               Object componentValue) throws AccessorException {\r
-                       try {\r
-                               WireAccessor sa = createAccessor( new ComponentReference() );\r
-                               try {\r
-                                       sa.setValue(componentBinding, componentValue);\r
-                               } finally {\r
-                                       sa.close();\r
-                               }\r
-                       } catch (WireException e) {\r
-                               throw new AccessorException( e );                               \r
-                       }                       \r
-                       \r
-               }\r
-               \r
-       }\r
-       \r
-       class WireVariant extends WireAccessor implements VariantAccessor {\r
-\r
-               WireVariant(int accId, Datatype type, ChildReference ref) {\r
-                       super(accId, type, ref);\r
-               }\r
-\r
-               @Override\r
-               public VariantType type() { \r
-                       return (VariantType) type;\r
-               }               \r
-               \r
-               @SuppressWarnings("unchecked")\r
-               @Override\r
-               public <T extends Accessor> T getContentAccessor()\r
-                               throws AccessorConstructionException {\r
-                       return (T) getComponent(new ComponentReference());\r
-               }\r
-\r
-               @Override\r
-               public void setContentValue(Binding valueBinding, Object value)\r
-                               throws AccessorException {\r
-                       try {\r
-                               WireAccessor sa = createAccessor( new ComponentReference() );\r
-                               try {\r
-                                       sa.setValue(valueBinding, value);\r
-                               } finally {\r
-                                       sa.close();\r
-                               }\r
-                       } catch (WireException e) {\r
-                               throw new AccessorException( e );                               \r
-                       }\r
-               }\r
-\r
-               @Override\r
-               public Object getContentValue(Binding contentBinding)\r
-                               throws AccessorException {\r
-                       try {\r
-                               WireAccessor sa = createAccessor( new ComponentReference() );\r
-                               try {\r
-                                       return sa.getValue(contentBinding);\r
-                               } finally {\r
-                                       sa.close();\r
-                               }\r
-                       } catch (WireException e) {\r
-                               throw new AccessorException( e );                               \r
-                       }\r
-               }\r
-\r
-               @Override\r
-               public Datatype getContentType() throws AccessorException {\r
-                       try {\r
-                               WireAccessor sa = createAccessor( new ComponentReference() );\r
-                               try {\r
-                                       return sa.type();\r
-                               } finally {\r
-                                       sa.close();\r
-                               }\r
-                       } catch (WireException e) {\r
-                               throw new AccessorException( e );                               \r
-                       }\r
-               }\r
-               \r
-       }\r
-\r
-       \r
-}\r
-\r
+/*******************************************************************************
+ * Copyright (c) 2010- Association for Decentralized Information Management in
+ * Industry THTH ry.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *    VTT Technical Research Centre of Finland - initial API and implementation
+ *******************************************************************************/
+package org.simantics.databoard.accessor.wire;
+
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.TreeMap;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.Executor;
+
+import org.simantics.databoard.Bindings;
+import org.simantics.databoard.Datatypes;
+import org.simantics.databoard.Methods;
+import org.simantics.databoard.accessor.Accessor;
+import org.simantics.databoard.accessor.ArrayAccessor;
+import org.simantics.databoard.accessor.BooleanAccessor;
+import org.simantics.databoard.accessor.ByteAccessor;
+import org.simantics.databoard.accessor.CloseableAccessor;
+import org.simantics.databoard.accessor.DoubleAccessor;
+import org.simantics.databoard.accessor.FloatAccessor;
+import org.simantics.databoard.accessor.IntegerAccessor;
+import org.simantics.databoard.accessor.LongAccessor;
+import org.simantics.databoard.accessor.MapAccessor;
+import org.simantics.databoard.accessor.OptionalAccessor;
+import org.simantics.databoard.accessor.RecordAccessor;
+import org.simantics.databoard.accessor.StringAccessor;
+import org.simantics.databoard.accessor.UnionAccessor;
+import org.simantics.databoard.accessor.VariantAccessor;
+import org.simantics.databoard.accessor.error.AccessorConstructionException;
+import org.simantics.databoard.accessor.error.AccessorException;
+import org.simantics.databoard.accessor.error.ReferenceException;
+import org.simantics.databoard.accessor.event.ArrayElementRemoved;
+import org.simantics.databoard.accessor.event.Event;
+import org.simantics.databoard.accessor.event.MapEntryAdded;
+import org.simantics.databoard.accessor.event.MapEntryRemoved;
+import org.simantics.databoard.accessor.event.OptionalValueAssigned;
+import org.simantics.databoard.accessor.event.OptionalValueRemoved;
+import org.simantics.databoard.accessor.event.ValueAssigned;
+import org.simantics.databoard.accessor.impl.ListenerEntry;
+import org.simantics.databoard.accessor.interestset.InterestSet;
+import org.simantics.databoard.accessor.reference.ChildReference;
+import org.simantics.databoard.accessor.reference.ComponentReference;
+import org.simantics.databoard.accessor.reference.IndexReference;
+import org.simantics.databoard.accessor.reference.KeyReference;
+import org.simantics.databoard.accessor.reference.NameReference;
+import org.simantics.databoard.accessor.wire.IWireServer.AccessorInfo;
+import org.simantics.databoard.accessor.wire.IWireServer.ApplyResult;
+import org.simantics.databoard.adapter.AdaptException;
+import org.simantics.databoard.binding.ArrayBinding;
+import org.simantics.databoard.binding.Binding;
+import org.simantics.databoard.binding.MapBinding;
+import org.simantics.databoard.binding.error.BindingConstructionException;
+import org.simantics.databoard.binding.error.BindingException;
+import org.simantics.databoard.binding.impl.ArrayListBinding;
+import org.simantics.databoard.binding.impl.ObjectArrayBinding;
+import org.simantics.databoard.binding.impl.TreeMapBinding;
+import org.simantics.databoard.binding.mutable.MutableVariant;
+import org.simantics.databoard.method.MethodInterface;
+import org.simantics.databoard.type.ArrayType;
+import org.simantics.databoard.type.BooleanType;
+import org.simantics.databoard.type.ByteType;
+import org.simantics.databoard.type.Datatype;
+import org.simantics.databoard.type.DoubleType;
+import org.simantics.databoard.type.FloatType;
+import org.simantics.databoard.type.IntegerType;
+import org.simantics.databoard.type.LongType;
+import org.simantics.databoard.type.MapType;
+import org.simantics.databoard.type.OptionalType;
+import org.simantics.databoard.type.RecordType;
+import org.simantics.databoard.type.StringType;
+import org.simantics.databoard.type.UnionType;
+import org.simantics.databoard.type.VariantType;
+import org.simantics.databoard.util.BijectionMap;
+
+/**
+ * WireAccessor provides an accessor over TCP/IP connection.
+ * 
+ * All method invocation is blocking. WireAccessor may be accessed from 
+ * simultanous threads.
+ * 
+ *
+ * @author Toni Kalajainen <toni.kalajainen@vtt.fi>
+ */
+public class WireClient implements IWireClient {
+
+       /** A queue of released accessors */
+       ReferenceQueue<WireAccessor> releaseQueue = new ReferenceQueue<WireAccessor>();
+       Map<ChildReference, WireAccessorReference> subAccessorMap = new HashMap<ChildReference, WireAccessorReference>();
+       
+//     Map<Integer, Accessor> accessorMap = new HashMap<Integer, Accessor>();
+       BijectionMap<Integer, ListenerEntry> listenerMap = new BijectionMap<Integer, ListenerEntry>();
+       
+       MethodInterface serverMi;
+       MethodInterface clientMi;
+       IWireServer server;
+       WireAccessor root;
+       
+       public WireClient() {
+               try {
+                       this.clientMi = Methods.bindInterface(IWireClient.class, this);
+               } catch (BindingConstructionException e) {
+                       throw new RuntimeException(e);
+               }
+       }
+       
+       public void setServerMethodInterface(MethodInterface serverMi) {
+               try {
+                       this.serverMi = serverMi;
+                       this.server = Methods.createProxy(IWireServer.class, serverMi);
+               } catch (BindingConstructionException e) {
+                       throw new RuntimeException(e);
+               }
+       }
+       
+       public MethodInterface getServerMethodInterface() {
+               return serverMi;
+       }
+       
+       public MethodInterface getClientMethodInterface() {
+               return clientMi;
+       }
+       
+       public void close() {
+               try {
+                       closeReleasedAccessors();                       
+               } catch (WireException e) {
+                       e.printStackTrace();
+               }
+               
+       }
+       
+       /**
+        * Create an accessor. Does not dispose or add to cache, use getAccessor instead
+        * @param ref
+        * @return
+        * @throws WireException
+        */
+       WireAccessor createAccessor(ChildReference ref) throws WireException {
+               AccessorInfo ai = server.openAccessor(ref);
+               if (ai.type instanceof BooleanType) {
+                       return new WireBoolean(ai.accessorId, ai.type, ref);
+               } else
+               if (ai.type instanceof ByteType) {
+                       return new WireByte(ai.accessorId, ai.type, ref);
+               } else 
+               if (ai.type instanceof IntegerType) {
+                       return new WireInteger(ai.accessorId, ai.type, ref);
+               } else 
+               if (ai.type instanceof LongType) {
+                       return new WireLong(ai.accessorId, ai.type, ref);
+               } else 
+               if (ai.type instanceof FloatType) {
+                       return new WireFloat(ai.accessorId, ai.type, ref);
+               } else 
+               if (ai.type instanceof DoubleType) {
+                       return new WireDouble(ai.accessorId, ai.type, ref);
+               } else  
+               if (ai.type instanceof StringType) {
+                       return new WireByte(ai.accessorId, ai.type, ref);
+               } else 
+               if (ai.type instanceof MapType) {
+                       return new WireMap(ai.accessorId, ai.type, ref);
+               } else 
+               if (ai.type instanceof OptionalType) {
+                       return new WireOptional(ai.accessorId, ai.type, ref);
+               } else 
+               if (ai.type instanceof RecordType) {
+                       return new WireRecord(ai.accessorId, ai.type, ref);
+               } else 
+               if (ai.type instanceof UnionType) {
+                       return new WireUnion(ai.accessorId, ai.type, ref);
+               } else 
+               if (ai.type instanceof VariantType) {
+                       return new WireVariant(ai.accessorId, ai.type, ref);
+               } 
+               throw new WireException("error, unknown data type "+ai.type);
+       }
+       
+       /**
+        * Create or get wire accessor
+        * @param ref path from root
+        * @return wire accessor
+        * @throws WireException
+        */
+       public WireAccessor getAccessor(ChildReference ref) throws WireException {
+               synchronized(subAccessorMap) {
+                       // Rseult Check cache
+                       closeReleasedAccessors();
+                       WireAccessorReference war = subAccessorMap.get(ref);
+                       WireAccessor result = war == null ? null : war.get();
+                       if (result != null) return result;
+                       
+                       result = createAccessor(ref);
+                       war = new WireAccessorReference(result);
+                       subAccessorMap.put(ref, war);
+                       
+                       return result;
+               }
+       }
+       
+       /**
+        * Close garbage collected accessors
+        * @throws WireException 
+        */
+       void closeReleasedAccessors() throws WireException {
+               if (releaseQueue.poll()==null) return;
+               ArrayList<Integer> ids = new ArrayList<Integer>();
+               while (releaseQueue.poll() != null) {
+                       try {
+                               WireAccessorReference ref = (WireAccessorReference) releaseQueue.remove();
+                               ids.add( ref.accId );
+                       } catch (InterruptedException e) {
+                       }
+               }
+               // Close accessors
+               server.closeAccessors( ids.toArray(new Integer[ids.size()]) );
+       }
+       
+       @Override
+       public int onEvents(int lisId, Event[] events) {
+               ListenerEntry listener = null;
+               synchronized(listenerMap) {
+                       listener = listenerMap.getRight(lisId);
+               }
+               if (listener==null) return 0;
+
+               List<Event> list = new CopyOnWriteArrayList<Event>(events);
+               listener.emitEvents(list);
+               
+               return 0;
+       }
+       
+       class WireAccessorReference extends WeakReference<WireAccessor> {
+
+               int accId;
+               
+               public WireAccessorReference(WireAccessor referent) {
+                       super(referent, releaseQueue);
+                       this.accId = referent.accId;
+               }
+               
+       }
+       
+       abstract class WireAccessor implements Accessor, CloseableAccessor {
+               int accId;
+               ChildReference ref;
+               Datatype type;          
+               
+               WireAccessor(int accId, Datatype type, ChildReference ref) {
+                       this.accId = accId;
+                       this.type = type;
+                       this.ref = ref;                 
+               }
+
+               @Override
+               public Object getValue(Binding binding) throws AccessorException {
+                       try {
+                               MutableVariant value = server.getValue(accId);
+                               return value.getValue(binding);
+                       } catch (WireException e) {
+                               throw new AccessorException(e);
+                       } catch (AdaptException e) {
+                               throw new AccessorException(e);
+                       }
+               }
+               
+               @Override
+               public void getValue(Binding binding, Object obj)
+                               throws AccessorException {
+            try {
+                MutableVariant value= server.getValue(accId);
+                binding.readFrom(value.getBinding(), value.getValue(), obj);
+            } catch ( WireException e ) {
+                throw new AccessorException(e);
+            } catch ( BindingException e ) {
+                throw new AccessorException(e);
+            }
+               }
+               
+               @Override
+               public boolean getValue(ChildReference path, Binding binding, Object obj) throws AccessorException {
+                       try {
+                               Accessor a = getComponent(path);
+                               a.getValue(binding, obj);
+                               return true;
+                       } catch (ReferenceException re) {
+                               return false;
+                       } catch (AccessorConstructionException e) {
+                               throw new AccessorException(e);
+                       }
+               }       
+               
+               public Object getValue(ChildReference path, Binding binding) throws AccessorException {
+                       try {
+                               Accessor a = getComponent(path);
+                               return a.getValue(binding);
+                       } catch (ReferenceException re) {
+                               return null;
+                       } catch (AccessorConstructionException e) {
+                               throw new AccessorException(e);
+                       }
+               }
+               
+               
+               void applyEvent(Event...events) throws AccessorException {
+                       ApplyResult result = server.apply(accId, events, false);
+                       if (result.error != null) throw new AccessorException( result.error );
+               }
+               
+               @Override
+               public void setValue(Binding binding, Object newValue) throws AccessorException {
+                       applyEvent( new ValueAssigned(binding, newValue) ); 
+               }
+               
+               public boolean setValue(ChildReference path, Binding binding, Object obj) throws AccessorException {
+                       try {
+                               Accessor a = getComponent(path);
+                               a.setValue(binding, obj);
+                               return true;
+                       } catch (ReferenceException re) {
+                               return false;
+                       } catch (AccessorConstructionException e) {
+                               throw new AccessorException(e);
+                       }
+               }
+               
+               @SuppressWarnings("unchecked")
+               @Override
+               public <T extends Accessor> T getComponent(ChildReference reference)
+               throws AccessorConstructionException {
+                       try {
+                               // Create a reference from the root
+                               ChildReference r = ChildReference.concatenate(ref, reference);
+                               return (T) WireClient.this.getAccessor( r );
+                       } catch (WireException e) {
+                               throw new AccessorConstructionException( e ); 
+                       }
+               }
+
+               @Override
+               public void apply(List<Event> changeSet, LinkedList<Event> rollback)
+                               throws AccessorException {
+                       
+                       ApplyResult result = server.apply(accId, changeSet.toArray(new Event[changeSet.size()]), rollback!=null);
+                       if (rollback!=null && result.rollbackLog!=null)
+                               rollback.addAll( result.rollbackLog );
+                       if (result.error != null) throw new AccessorException( result.error );
+                       
+               }
+
+               @Override
+               public Datatype type() { 
+                       return type;
+               }
+
+               @Override
+               public void addListener(Listener listener, InterestSet interestSet,
+                               ChildReference pathPrefix, Executor executor) throws AccessorException {
+                       try {
+                               ListenerEntry le = new ListenerEntry(listener, interestSet, pathPrefix, executor);
+                               int lisId = server.addListener(accId, interestSet, pathPrefix);
+                               synchronized(listenerMap) {
+                                       listenerMap.map(lisId, le);
+                               }
+                       } catch (WireException e) {
+                               throw new AccessorException(e);
+                       }
+               }
+
+               @Override
+               public void removeListener(Listener listener) throws AccessorException {
+                       Integer lisId = null;
+                       synchronized(listenerMap) {
+                               for (Entry<Integer, ListenerEntry> e : listenerMap.getEntries()) {
+                                       if (e.getValue().listener == listener) {
+                                               lisId = e.getKey();
+                                               break;
+                                       }
+                               }
+                               if (lisId==null) return;
+                               listenerMap.removeWithLeft(lisId);
+                       }
+                       try {
+                               server.removeListener(lisId);
+                       } catch (WireException e) {
+                               throw new AccessorException( e );
+                       }                       
+               }
+               
+               public void close() throws AccessorException {
+                       try {
+                               server.closeAccessors( new Integer[] {accId} );
+                       } catch (WireException e) {
+                               throw new AccessorException( e );
+                       }
+               }
+
+       }
+       
+       class WireBoolean extends WireAccessor implements BooleanAccessor {
+
+               WireBoolean(int accId, Datatype type, ChildReference ref) {
+                       super(accId, type, ref);
+               }
+               
+               @Override
+               public BooleanType type() { 
+                       return (BooleanType) type;
+               }
+               
+               @Override
+               public boolean getValue() throws AccessorException {
+                       try {
+                               MutableVariant value = server.getValue(accId);
+                               return (Boolean) value.getValue( Bindings.BOOLEAN );
+                       } catch (WireException e) {
+                               throw new AccessorException( e );
+                       } catch (AdaptException e) {
+                               throw new AccessorException( e );
+                       }
+               }
+
+               @Override
+               public void setValue(boolean value) throws AccessorException {
+                       Event e = new ValueAssigned(null, Bindings.BOOLEAN, value); 
+                       Event[] list = new Event[] {e};
+                       ApplyResult result = server.apply(accId, list, false);
+                       if (result.error != null) throw new AccessorException( result.error );
+               }
+       }       
+       
+       class WireByte extends WireAccessor implements ByteAccessor {
+
+               WireByte(int accId, Datatype type, ChildReference ref) {
+                       super(accId, type, ref);
+               }
+               
+               @Override
+               public ByteType type() { 
+                       return (ByteType) type;
+               }
+               
+               @Override
+               public byte getValue() throws AccessorException {
+                       try {
+                               MutableVariant value = server.getValue(accId);
+                               return (Byte) value.getValue( Bindings.BYTE );
+                       } catch (WireException e) {
+                               throw new AccessorException( e );
+                       } catch (AdaptException e) {
+                               throw new AccessorException( e );
+                       }
+               }
+               
+               @Override
+               public void setValue(byte value) throws AccessorException {
+                       Event e = new ValueAssigned(null, Bindings.BYTE, value); 
+                       Event[] list = new Event[] {e};
+                       ApplyResult result = server.apply(accId, list, false);
+                       if (result.error != null) throw new AccessorException( result.error );
+               }
+       }
+
+       class WireInteger extends WireAccessor implements IntegerAccessor {
+
+               WireInteger(int accId, Datatype type, ChildReference ref) {
+                       super(accId, type, ref);
+               }
+               
+               @Override
+               public IntegerType type() { 
+                       return (IntegerType) type;
+               }
+               
+               @Override
+               public int getValue() throws AccessorException {
+                       try {
+                               MutableVariant value = server.getValue(accId);
+                               return (Integer) value.getValue( Bindings.INTEGER );
+                       } catch (WireException e) {
+                               throw new AccessorException( e );
+                       } catch (AdaptException e) {
+                               throw new AccessorException( e );
+                       }
+               }
+
+               @Override
+               public void setValue(int value) throws AccessorException {
+                       Event e = new ValueAssigned(Bindings.INTEGER, value); 
+                       Event[] list = new Event[] {e};
+                       ApplyResult result = server.apply(accId, list, false);
+                       if (result.error != null) throw new AccessorException( result.error );
+               }
+
+       }
+
+       class WireLong extends WireAccessor implements LongAccessor {
+
+               WireLong(int accId, Datatype type, ChildReference ref) {
+                       super(accId, type, ref);
+               }
+               
+               @Override
+               public LongType type() { 
+                       return (LongType) type;
+               }
+               
+               @Override
+               public long getValue() throws AccessorException {
+                       try {
+                               MutableVariant value = server.getValue(accId);
+                               return (Long) value.getValue( Bindings.LONG );
+                       } catch (WireException e) {
+                               throw new AccessorException( e );
+                       } catch (AdaptException e) {
+                               throw new AccessorException( e );
+                       }
+               }
+
+               @Override
+               public void setValue(long value) throws AccessorException {
+                       Event e = new ValueAssigned(Bindings.LONG, value); 
+                       Event[] list = new Event[] {e};
+                       ApplyResult result = server.apply(accId, list, false);
+                       if (result.error != null) throw new AccessorException( result.error );
+               }
+
+       }
+
+       class WireFloat extends WireAccessor implements FloatAccessor {
+
+               WireFloat(int accId, Datatype type, ChildReference ref) {
+                       super(accId, type, ref);
+               }
+               
+               @Override
+               public FloatType type() { 
+                       return (FloatType) type;
+               }
+               
+               @Override
+               public float getValue() throws AccessorException {
+                       try {
+                               MutableVariant value = server.getValue(accId);
+                               return (Float) value.getValue( Bindings.FLOAT );
+                       } catch (WireException e) {
+                               throw new AccessorException( e );
+                       } catch (AdaptException e) {
+                               throw new AccessorException( e );
+                       }
+               }
+
+               @Override
+               public void setValue(float value) throws AccessorException {
+                       Event e = new ValueAssigned(Bindings.FLOAT, value); 
+                       Event[] list = new Event[] {e};
+                       ApplyResult result = server.apply(accId, list, false);
+                       if (result.error != null) throw new AccessorException( result.error );
+               }
+
+       }
+
+       class WireDouble extends WireAccessor implements DoubleAccessor {
+
+               WireDouble(int accId, Datatype type, ChildReference ref) {
+                       super(accId, type, ref);
+               }
+               
+               @Override
+               public DoubleType type() { 
+                       return (DoubleType) type;
+               }
+               
+               @Override
+               public double getValue() throws AccessorException {
+                       try {
+                               MutableVariant value = server.getValue(accId);
+                               return (Double) value.getValue( Bindings.DOUBLE );
+                       } catch (WireException e) {
+                               throw new AccessorException( e );
+                       } catch (AdaptException e) {
+                               throw new AccessorException( e );
+                       }
+               }
+
+               @Override
+               public void setValue(double value) throws AccessorException {
+                       Event e = new ValueAssigned(Bindings.DOUBLE, value); 
+                       Event[] list = new Event[] {e};
+                       ApplyResult result = server.apply(accId, list, false);
+                       if (result.error != null) throw new AccessorException( result.error );
+               }
+
+       }
+
+       class WireArray extends WireAccessor implements ArrayAccessor {
+
+               WireArray(int accId, Datatype type, ChildReference ref) {
+                       super(accId, type, ref);
+               }
+               
+               @Override
+               public ArrayType type() { 
+                       return (ArrayType) type;
+               }
+
+               @Override
+               public void add(Binding binding, Object value) throws AccessorException {
+                       try {
+                               server.addAll(accId, -1, new MutableVariant(binding, value));
+                       } catch (WireException e) {
+                               throw new AccessorException(e);
+                       }
+               }
+
+               @Override
+               public void addAll(Binding binding, Object[] values) throws AccessorException {
+                       try {
+                               ArrayBinding ab = new ObjectArrayBinding(new ArrayType(binding.type()), binding);
+                               MutableVariant array = new MutableVariant(ab, values);
+                               server.addAll(accId, -1, array);
+                       } catch (WireException e) {
+                               throw new AccessorException(e);
+                       }
+               }
+
+               @Override
+               public void addAll(int index, Binding binding, Object[] values)
+                               throws AccessorException {
+                       try {
+                               ArrayBinding ab = new ObjectArrayBinding(new ArrayType(binding.type()), binding);
+                               MutableVariant array = new MutableVariant(ab, values);
+                               server.addAll(accId, index, array);
+                       } catch (WireException e) {
+                               throw new AccessorException(e);
+                       }
+               }
+
+               @Override
+               public void add(int index, Binding binding, Object value) throws AccessorException {
+                       try {
+                               server.addAll(accId, index, new MutableVariant(binding, value));
+                       } catch (WireException e) {
+                               throw new AccessorException(e);
+                       }
+               }
+
+               @Override
+               public void set(int index, Binding binding, Object value)
+                               throws AccessorException {
+                       applyEvent(new ValueAssigned(new IndexReference(index), binding, value));
+               }
+
+               @Override
+               public void remove(int index, int count) throws AccessorException {
+                       applyEvent(new ArrayElementRemoved(index));                     
+               }
+
+               @SuppressWarnings("unchecked")
+               @Override
+               public <T extends Accessor> T getAccessor(int index)
+                               throws AccessorConstructionException {
+                       return (T) getComponent(new IndexReference(index));
+               }
+
+               @Override
+               public Object get(int index, Binding valueBinding)
+                               throws AccessorException {
+                       try {
+                               MutableVariant v = server.getArrayElement(accId, index);
+                               return v.getValue(valueBinding);
+                       } catch (WireException e) {
+                               throw new AccessorException(e);
+                       } catch (AdaptException e) {
+                               throw new AccessorException(e);
+                       }
+               }
+               
+               @Override
+               public void get(int index, Binding valueBinding, Object dst)
+                               throws AccessorException {
+                       try {
+                               MutableVariant v = server.getArrayElement(accId, index);
+                               valueBinding.readFrom(v.getBinding(), v.getValue(), v);
+                       } catch (WireException e) {
+                               throw new AccessorException(e);
+                       } catch (BindingException e) {
+                               throw new AccessorException(e);
+                       }
+               }               
+
+               @Override
+               public void getAll(Binding valueBinding, Object[] array)
+                               throws AccessorException {
+                       ObjectArrayBinding arrayBinding = new ObjectArrayBinding(type(), valueBinding);
+                       Object[] a2 = (Object[]) getValue(arrayBinding);
+                       System.arraycopy(a2, 0, array, 0, a2.length);                   
+               }
+
+               @Override
+               public void getAll(Binding valueBinding, Collection<Object> values)
+                               throws AccessorException {
+                       ArrayListBinding arrayBinding = new ArrayListBinding(type(), valueBinding);
+                       ArrayList<?> a2 = (ArrayList<?>) getValue(arrayBinding);
+                       values.addAll(a2);                      
+               }
+               
+               @Override
+               public void setSize(int newSize) throws AccessorException {
+                       throw new AccessorException("Not implemented");
+               }
+
+               @Override
+               public int size() throws AccessorException {
+                       try {
+                               return server.size(accId);
+                       } catch (WireException e) {
+                               throw new AccessorException( e );
+                       }
+               }
+       }
+       
+       class WireMap extends WireAccessor implements MapAccessor {
+
+               WireMap(int accId, Datatype type, ChildReference ref) {
+                       super(accId, type, ref);
+               }
+               
+               @Override
+               public MapType type() { 
+                       return (MapType) type;
+               }               
+
+               @Override
+               public int size() throws AccessorException {
+                       try {
+                               return server.size(accId);
+                       } catch (WireException e) {
+                               throw new AccessorException( e );
+                       }
+               }
+
+               @Override
+               public Object get(Binding keyBinding, Object key, Binding valueBinding)
+                               throws AccessorException {
+                       try {
+                               MutableVariant value = server.getMapValue(accId, new MutableVariant(keyBinding, key));
+                if (value.type().equals(Datatypes.VOID)) return null;
+                               return value.getValue(valueBinding);
+                       } catch (WireException e) {
+                               throw new AccessorException( e );
+                       } catch (AdaptException e) {
+                               throw new AccessorException( e );
+                       }
+               }
+
+               @Override
+               public boolean containsKey(Binding keyBinding, Object key)
+                               throws AccessorException {
+                       try {
+                               return server.containsKey(accId, new MutableVariant(keyBinding, key));
+                       } catch (WireException e) {
+                               throw new AccessorException( e );
+                       }
+               }
+
+               @Override
+               public boolean containsValue(Binding valueBinding, Object value)
+                               throws AccessorException {
+                       try {
+                               return server.containsValue(accId, new MutableVariant(valueBinding, value));
+                       } catch (WireException e) {
+                               throw new AccessorException( e );
+                       }
+               }
+
+               @Override
+               public void put(Binding keyBinding, Object key, Binding valueBinding,
+                               Object value) throws AccessorException {
+                       applyEvent( new MapEntryAdded(new MutableVariant(keyBinding, key), new MutableVariant(valueBinding, value)) );
+               }
+
+               @Override
+               public void remove(Binding keyBinding, Object key)
+                               throws AccessorException {
+                       applyEvent( new MapEntryRemoved(new MutableVariant(keyBinding, key)) );
+               }
+
+               @Override
+               public void clear() throws AccessorException {
+                       try {
+                               server.clear(accId);
+                       } catch (WireException e) {
+                               throw new AccessorException(e);
+                       }                       
+               }
+
+               @Override
+               public void putAll(Binding keyBinding, Binding valueBinding,
+                               Map<Object, Object> from) throws AccessorException {
+                       
+                       int count = from.size();
+                       Event events[] = new Event[ count ];
+                       int i = 0;
+                       for (Entry<Object, Object> e : from.entrySet()) {
+                               MutableVariant key = new MutableVariant( keyBinding, e.getKey() );
+                               MutableVariant value = new MutableVariant( valueBinding, e.getValue() );
+                               events[i] = new MapEntryAdded( key, value );
+                               ++i;
+                       }
+                       applyEvent( events );                                           
+               }
+
+               @Override
+               public void putAll(Binding keyBinding, Binding valueBinding,
+                               Object[] keys, Object[] values) throws AccessorException {
+                       if (keys.length != values.length) throw new AccessorException("bad args");
+                       int count = keys.length;
+                       Event events[] = new Event[ count ];
+                       for (int i=0; i<count; i++) {
+                               events[i] = new MapEntryAdded( new MutableVariant(keyBinding, keys[i]), new MutableVariant(valueBinding, values[i]) );
+                       }
+                       applyEvent( events );                   
+               }
+
+               @SuppressWarnings("unchecked")
+        @Override
+               public void getAll(Binding keyBinding, Binding valueBinding,
+                               Map<Object, Object> to) throws AccessorException {
+                       MapBinding binding = new TreeMapBinding(keyBinding, valueBinding);
+                       TreeMap<Object, Object> v = (TreeMap<Object, Object>) getValue(binding);
+                       to.putAll(v);
+               }
+
+               @SuppressWarnings("unchecked")
+        @Override
+               public void getAll(Binding keyBinding, Binding valueBinding,
+                               Object[] keys, Object[] values) throws AccessorException {
+                       MapBinding binding = new TreeMapBinding(keyBinding, valueBinding);
+                       TreeMap<Object, Object> v = (TreeMap<Object, Object>) getValue(binding);
+                       int i=0;
+                       for (Entry<Object, Object> e : v.entrySet()) {
+                               keys[i] = e.getKey();
+                               values[i] = e.getValue();
+                               ++i;
+                       }
+               }
+
+               @Override
+               public Object[] getKeys(Binding keyBinding) throws AccessorException {
+                       try {
+                               MutableVariant array = server.getMapKeys(accId);
+                               ArrayBinding binding = new ObjectArrayBinding( keyBinding );
+                               return (Object[]) array.getValue(binding);
+                       } catch (WireException e) {
+                               throw new AccessorException( e );
+                       } catch (AdaptException e) {
+                               throw new AccessorException( e );
+                       }
+               }
+
+               @Override
+               public int count(Binding keyBinding, Object from,
+                               boolean fromInclusive, Object end, boolean endInclusive)
+                               throws AccessorException {
+                       throw new AccessorException("Not implemented");
+               }
+
+               @Override
+               public int getEntries(Binding keyBinding, Object from,
+                               boolean fromInclusive, Object end, boolean endInclusive,
+                               ArrayBinding keyArrayBinding, Object dstKeys,
+                               ArrayBinding valueArrayBinding, Object dstValues, int limit)
+                               throws AccessorException {
+                       throw new AccessorException("Not implemented");
+               }
+               
+
+               @Override
+               public Object[] getValues(Binding valueBinding)
+                               throws AccessorException {
+                       try {
+                               MutableVariant array = server.getMapValues(accId);
+                               ArrayBinding binding = new ObjectArrayBinding( valueBinding );
+                               return (Object[]) array.getValue(binding);
+                       } catch (WireException e) {
+                               throw new AccessorException( e );
+                       } catch (AdaptException e) {
+                               throw new AccessorException( e );
+                       }
+               }
+
+               @SuppressWarnings("unchecked")
+               @Override
+               public <T extends Accessor> T getValueAccessor(Binding keyBinding, Object key) throws AccessorConstructionException {
+                       return (T) getComponent( new KeyReference(keyBinding, key) );
+               }
+
+               @Override
+               public Object getFirstKey(Binding keyBinding) throws AccessorException {
+                       try {
+                               MutableVariant result = server.getFirstKey(accId);
+                if (result.type().equals(Datatypes.VOID)) return null;
+                               return result.getValue(keyBinding);
+                       } catch (WireException e) {
+                               throw new AccessorException(e);
+                       } catch (AdaptException e) {
+                               throw new AccessorException(e);
+                       }
+               }
+
+               @Override
+               public Object getLastKey(Binding keyBinding) throws AccessorException {
+                       try {
+                               MutableVariant result = server.getLastKey(accId);
+                if (result.type().equals(Datatypes.VOID)) return null;
+                               return result.getValue(keyBinding);
+                       } catch (WireException e) {
+                               throw new AccessorException(e);
+                       } catch (AdaptException e) {
+                               throw new AccessorException(e);
+                       }
+               }
+
+               @Override
+               public Object getLowerKey(Binding keyBinding, Object key)
+                               throws AccessorException {
+                       try {
+                               MutableVariant result = server.getLowerKey(accId, new MutableVariant(keyBinding, key));
+                               if (result.type().equals(Datatypes.VOID)) return null;
+                               return result.getValue(keyBinding);
+                       } catch (WireException e) {
+                               throw new AccessorException(e);
+                       } catch (AdaptException e) {
+                               throw new AccessorException(e);
+                       }
+               }
+
+               @Override
+               public Object getFloorKey(Binding keyBinding, Object key)
+                               throws AccessorException {
+                       try {
+                               MutableVariant result = server.getFloorKey(accId, new MutableVariant(keyBinding, key));
+                if (result.type() == Datatypes.VOID) return null;
+                               return result.getValue(keyBinding);
+                       } catch (WireException e) {
+                               throw new AccessorException(e);
+                       } catch (AdaptException e) {
+                               throw new AccessorException(e);
+                       }
+               }
+
+               @Override
+               public Object getCeilingKey(Binding keyBinding, Object key)
+                               throws AccessorException {
+                       try {
+                               MutableVariant result = server.getCeilingKey(accId, new MutableVariant(keyBinding, key));
+                if (result.type().equals(Datatypes.VOID)) return null;
+                               return result.getValue(keyBinding);
+                       } catch (WireException e) {
+                               throw new AccessorException(e);
+                       } catch (AdaptException e) {
+                               throw new AccessorException(e);
+                       }
+               }
+
+               @Override
+               public Object getHigherKey(Binding keyBinding, Object key)
+                               throws AccessorException {
+                       try {
+                               MutableVariant result = server.getHigherKey(accId, new MutableVariant(keyBinding, key));
+                if (result.type().equals(Datatypes.VOID)) return null;
+                               return result.getValue(keyBinding);
+                       } catch (WireException e) {
+                               throw new AccessorException(e);
+                       } catch (AdaptException e) {
+                               throw new AccessorException(e);
+                       }
+               }
+               
+       }
+       
+       class WireOptional extends WireAccessor implements OptionalAccessor {
+
+               WireOptional(int accId, Datatype type, ChildReference ref) {
+                       super(accId, type, ref);
+               }
+               
+               @Override
+               public OptionalType type() { 
+                       return (OptionalType) type;
+               }                               
+
+               @Override
+               public void setNoValue() throws AccessorException {
+                       applyEvent( new OptionalValueRemoved() );
+               }
+
+               @Override
+               public boolean hasValue() throws AccessorException {
+                       try {
+                               return server.hasValue(accId);
+                       } catch (WireException e) {
+                               throw new AccessorException( e );                               
+                       }
+               }
+
+               @Override
+               public Object getComponentValue(Binding componentBinding)
+                               throws AccessorException {
+                       try {
+                               WireAccessor sa = createAccessor( new ComponentReference() );
+                               try {
+                                       return sa.getValue(componentBinding);
+                               } finally {
+                                       sa.close();
+                               }
+                       } catch (WireException e) {
+                               throw new AccessorException( e );                               
+                       }
+               }
+
+               @Override
+               public void setComponentValue(Binding binding, Object value)
+                               throws AccessorException {                      
+                       applyEvent(new OptionalValueAssigned(binding, value));
+               }
+
+               @SuppressWarnings("unchecked")
+               @Override
+               public <T extends Accessor> T getComponentAccessor()
+                               throws AccessorConstructionException {
+                       return (T) getComponent( new ComponentReference() );
+               }
+               
+       }
+       
+       class WireRecord extends WireAccessor implements RecordAccessor {
+
+               WireRecord(int accId, Datatype type, ChildReference ref) {
+                       super(accId, type, ref);
+               }
+               
+               @Override
+               public RecordType type() { 
+                       return (RecordType) type;
+               }               
+
+               @Override
+               public int count() throws AccessorException {                   
+                       try {
+                               return server.size(accId);
+                       } catch (WireException e) {
+                               throw new AccessorException(e);
+                       }
+               }
+
+               @SuppressWarnings("unchecked")
+               @Override
+               public <T extends Accessor> T getFieldAccessor(int index)
+                               throws AccessorConstructionException {
+                       return (T) getComponent( new IndexReference(index) );
+               }
+
+               @SuppressWarnings("unchecked")
+               @Override
+               public <T extends Accessor> T getFieldAccessor(String fieldName)
+                               throws AccessorConstructionException {
+                       return (T) getComponent( new NameReference( fieldName ) );
+               }
+
+               @Override
+               public Object getFieldValue(String fieldName, Binding fieldBinding)
+                               throws AccessorException {
+                       int fieldIndex = type().getComponentIndex(fieldName);
+                       if (fieldIndex<0) throw new AccessorException("Field "+fieldName+" does not exist");
+                       return getFieldValue(fieldIndex, fieldBinding);
+               }
+               
+               @Override
+               public Object getFieldValue(int index, Binding fieldBinding)
+                               throws AccessorException {
+                       try {
+                               WireAccessor sa = createAccessor( new IndexReference(index) );
+                               try {
+                                       return sa.getValue(fieldBinding);
+                               } finally {
+                                       sa.close();
+                               }
+                       } catch (WireException e) {
+                               throw new AccessorException( e );                               
+                       }
+               }
+               
+               public void setFieldValue(String fieldName, Binding fieldBinding, Object value) throws AccessorException {
+                       int fieldIndex = type().getComponentIndex(fieldName);
+                       if (fieldIndex<0) throw new AccessorException("Field "+fieldName+" does not exist");
+                       setFieldValue(fieldIndex, fieldBinding, value);
+               };
+
+               @Override
+               public void setFieldValue(int index, Binding fieldBinding, Object value)
+                               throws AccessorException {
+                       try {
+                               WireAccessor sa = createAccessor( new IndexReference(index) );
+                               try {
+                                       sa.setValue(fieldBinding, value);
+                               } finally {
+                                       sa.close();
+                               }
+                       } catch (WireException e) {
+                               throw new AccessorException( e );                               
+                       }
+               }
+               
+       }
+       
+       class WireString extends WireAccessor implements StringAccessor {
+
+               WireString(int accId, Datatype type, ChildReference ref) {
+                       super(accId, type, ref);
+               }
+
+               @Override
+               public StringType type() { 
+                       return (StringType) type;
+               }               
+
+               @Override
+               public String getValue() throws AccessorException {
+                       try {
+                               MutableVariant value = server.getValue(accId);
+                               return (String) value.getValue( Bindings.STRING );
+                       } catch (WireException e) {
+                               throw new AccessorException( e );
+                       } catch (AdaptException e) {
+                               throw new AccessorException( e );
+                       }
+               }
+
+               @Override
+               public void setValue(String newValue) throws AccessorException {
+                       Event e = new ValueAssigned( Bindings.STRING, newValue); 
+                       Event[] list = new Event[] {e};
+                       ApplyResult result = server.apply(accId, list, false);
+                       if (result.error != null) throw new AccessorException( result.error );
+               }
+               
+       }
+       
+       class WireUnion extends WireAccessor implements UnionAccessor {
+
+               WireUnion(int accId, Datatype type, ChildReference ref) {
+                       super(accId, type, ref);
+               }
+               
+               @Override
+               public UnionType type() { 
+                       return (UnionType) type;
+               }                               
+
+               @Override
+               public int count() throws AccessorException {
+                       try {
+                               return server.size(accId);
+                       } catch (WireException e) {
+                               throw new AccessorException(e);
+                       }
+               }
+
+               @Override
+               public int getTag() throws AccessorException {
+                       try {
+                               return server.getTag(accId);
+                       } catch (WireException e) {
+                               throw new AccessorException(e);
+                       }
+               }
+
+               @SuppressWarnings("unchecked")
+               @Override
+               public <T extends Accessor> T getComponentAccessor()
+                               throws AccessorConstructionException {
+                       return (T) getComponent(new ComponentReference());
+               }
+
+               @Override
+               public Object getComponentValue(Binding componentBinding)
+                               throws AccessorException {
+                       try {
+                               WireAccessor sa = createAccessor( new ComponentReference() );
+                               try {
+                                       return sa.getValue(componentBinding);
+                               } finally {
+                                       sa.close();
+                               }
+                       } catch (WireException e) {
+                               throw new AccessorException( e );                               
+                       }
+               }
+
+               @Override
+               public void setComponentValue(int tag, Binding componentBinding,
+                               Object componentValue) throws AccessorException {
+                       try {
+                               WireAccessor sa = createAccessor( new ComponentReference() );
+                               try {
+                                       sa.setValue(componentBinding, componentValue);
+                               } finally {
+                                       sa.close();
+                               }
+                       } catch (WireException e) {
+                               throw new AccessorException( e );                               
+                       }                       
+                       
+               }
+               
+       }
+       
+       class WireVariant extends WireAccessor implements VariantAccessor {
+
+               WireVariant(int accId, Datatype type, ChildReference ref) {
+                       super(accId, type, ref);
+               }
+
+               @Override
+               public VariantType type() { 
+                       return (VariantType) type;
+               }               
+               
+               @SuppressWarnings("unchecked")
+               @Override
+               public <T extends Accessor> T getContentAccessor()
+                               throws AccessorConstructionException {
+                       return (T) getComponent(new ComponentReference());
+               }
+
+               @Override
+               public void setContentValue(Binding valueBinding, Object value)
+                               throws AccessorException {
+                       try {
+                               WireAccessor sa = createAccessor( new ComponentReference() );
+                               try {
+                                       sa.setValue(valueBinding, value);
+                               } finally {
+                                       sa.close();
+                               }
+                       } catch (WireException e) {
+                               throw new AccessorException( e );                               
+                       }
+               }
+
+               @Override
+               public Object getContentValue(Binding contentBinding)
+                               throws AccessorException {
+                       try {
+                               WireAccessor sa = createAccessor( new ComponentReference() );
+                               try {
+                                       return sa.getValue(contentBinding);
+                               } finally {
+                                       sa.close();
+                               }
+                       } catch (WireException e) {
+                               throw new AccessorException( e );                               
+                       }
+               }
+
+               @Override
+               public Datatype getContentType() throws AccessorException {
+                       try {
+                               WireAccessor sa = createAccessor( new ComponentReference() );
+                               try {
+                                       return sa.type();
+                               } finally {
+                                       sa.close();
+                               }
+                       } catch (WireException e) {
+                               throw new AccessorException( e );                               
+                       }
+               }
+               
+       }
+
+       
+}
+