]> gerrit.simantics Code Review - simantics/platform.git/blob - 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
1 /*******************************************************************************
2  * Copyright (c) 2010- Association for Decentralized Information Management in
3  * Industry THTH ry.
4  * All rights reserved. This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License v1.0
6  * which accompanies this distribution, and is available at
7  * http://www.eclipse.org/legal/epl-v10.html
8  * 
9  * Contributors:
10  *    VTT Technical Research Centre of Finland - initial API and implementation
11  *******************************************************************************/
12 package org.simantics.databoard.accessor.wire;
13
14 import java.lang.ref.ReferenceQueue;
15 import java.lang.ref.WeakReference;
16 import java.util.ArrayList;
17 import java.util.Collection;
18 import java.util.HashMap;
19 import java.util.LinkedList;
20 import java.util.List;
21 import java.util.Map;
22 import java.util.Map.Entry;
23 import java.util.TreeMap;
24 import java.util.concurrent.CopyOnWriteArrayList;
25 import java.util.concurrent.Executor;
26
27 import org.simantics.databoard.Bindings;
28 import org.simantics.databoard.Datatypes;
29 import org.simantics.databoard.Methods;
30 import org.simantics.databoard.accessor.Accessor;
31 import org.simantics.databoard.accessor.ArrayAccessor;
32 import org.simantics.databoard.accessor.BooleanAccessor;
33 import org.simantics.databoard.accessor.ByteAccessor;
34 import org.simantics.databoard.accessor.CloseableAccessor;
35 import org.simantics.databoard.accessor.DoubleAccessor;
36 import org.simantics.databoard.accessor.FloatAccessor;
37 import org.simantics.databoard.accessor.IntegerAccessor;
38 import org.simantics.databoard.accessor.LongAccessor;
39 import org.simantics.databoard.accessor.MapAccessor;
40 import org.simantics.databoard.accessor.OptionalAccessor;
41 import org.simantics.databoard.accessor.RecordAccessor;
42 import org.simantics.databoard.accessor.StringAccessor;
43 import org.simantics.databoard.accessor.UnionAccessor;
44 import org.simantics.databoard.accessor.VariantAccessor;
45 import org.simantics.databoard.accessor.error.AccessorConstructionException;
46 import org.simantics.databoard.accessor.error.AccessorException;
47 import org.simantics.databoard.accessor.error.ReferenceException;
48 import org.simantics.databoard.accessor.event.ArrayElementRemoved;
49 import org.simantics.databoard.accessor.event.Event;
50 import org.simantics.databoard.accessor.event.MapEntryAdded;
51 import org.simantics.databoard.accessor.event.MapEntryRemoved;
52 import org.simantics.databoard.accessor.event.OptionalValueAssigned;
53 import org.simantics.databoard.accessor.event.OptionalValueRemoved;
54 import org.simantics.databoard.accessor.event.ValueAssigned;
55 import org.simantics.databoard.accessor.impl.ListenerEntry;
56 import org.simantics.databoard.accessor.interestset.InterestSet;
57 import org.simantics.databoard.accessor.reference.ChildReference;
58 import org.simantics.databoard.accessor.reference.ComponentReference;
59 import org.simantics.databoard.accessor.reference.IndexReference;
60 import org.simantics.databoard.accessor.reference.KeyReference;
61 import org.simantics.databoard.accessor.reference.NameReference;
62 import org.simantics.databoard.accessor.wire.IWireServer.AccessorInfo;
63 import org.simantics.databoard.accessor.wire.IWireServer.ApplyResult;
64 import org.simantics.databoard.adapter.AdaptException;
65 import org.simantics.databoard.binding.ArrayBinding;
66 import org.simantics.databoard.binding.Binding;
67 import org.simantics.databoard.binding.MapBinding;
68 import org.simantics.databoard.binding.error.BindingConstructionException;
69 import org.simantics.databoard.binding.error.BindingException;
70 import org.simantics.databoard.binding.impl.ArrayListBinding;
71 import org.simantics.databoard.binding.impl.ObjectArrayBinding;
72 import org.simantics.databoard.binding.impl.TreeMapBinding;
73 import org.simantics.databoard.binding.mutable.MutableVariant;
74 import org.simantics.databoard.method.MethodInterface;
75 import org.simantics.databoard.type.ArrayType;
76 import org.simantics.databoard.type.BooleanType;
77 import org.simantics.databoard.type.ByteType;
78 import org.simantics.databoard.type.Datatype;
79 import org.simantics.databoard.type.DoubleType;
80 import org.simantics.databoard.type.FloatType;
81 import org.simantics.databoard.type.IntegerType;
82 import org.simantics.databoard.type.LongType;
83 import org.simantics.databoard.type.MapType;
84 import org.simantics.databoard.type.OptionalType;
85 import org.simantics.databoard.type.RecordType;
86 import org.simantics.databoard.type.StringType;
87 import org.simantics.databoard.type.UnionType;
88 import org.simantics.databoard.type.VariantType;
89 import org.simantics.databoard.util.BijectionMap;
90
91 /**
92  * WireAccessor provides an accessor over TCP/IP connection.
93  * 
94  * All method invocation is blocking. WireAccessor may be accessed from 
95  * simultanous threads.
96  * 
97  *
98  * @author Toni Kalajainen <toni.kalajainen@vtt.fi>
99  */
100 public class WireClient implements IWireClient {
101
102         /** A queue of released accessors */
103         ReferenceQueue<WireAccessor> releaseQueue = new ReferenceQueue<WireAccessor>();
104         Map<ChildReference, WireAccessorReference> subAccessorMap = new HashMap<ChildReference, WireAccessorReference>();
105         
106 //      Map<Integer, Accessor> accessorMap = new HashMap<Integer, Accessor>();
107         BijectionMap<Integer, ListenerEntry> listenerMap = new BijectionMap<Integer, ListenerEntry>();
108         
109         MethodInterface serverMi;
110         MethodInterface clientMi;
111         IWireServer server;
112         WireAccessor root;
113         
114         public WireClient() {
115                 try {
116                         this.clientMi = Methods.bindInterface(IWireClient.class, this);
117                 } catch (BindingConstructionException e) {
118                         throw new RuntimeException(e);
119                 }
120         }
121         
122         public void setServerMethodInterface(MethodInterface serverMi) {
123                 try {
124                         this.serverMi = serverMi;
125                         this.server = Methods.createProxy(IWireServer.class, serverMi);
126                 } catch (BindingConstructionException e) {
127                         throw new RuntimeException(e);
128                 }
129         }
130         
131         public MethodInterface getServerMethodInterface() {
132                 return serverMi;
133         }
134         
135         public MethodInterface getClientMethodInterface() {
136                 return clientMi;
137         }
138         
139         public void close() {
140                 try {
141                         closeReleasedAccessors();                       
142                 } catch (WireException e) {
143                         e.printStackTrace();
144                 }
145                 
146         }
147         
148         /**
149          * Create an accessor. Does not dispose or add to cache, use getAccessor instead
150          * @param ref
151          * @return
152          * @throws WireException
153          */
154         WireAccessor createAccessor(ChildReference ref) throws WireException {
155                 AccessorInfo ai = server.openAccessor(ref);
156                 if (ai.type instanceof BooleanType) {
157                         return new WireBoolean(ai.accessorId, ai.type, ref);
158                 } else
159                 if (ai.type instanceof ByteType) {
160                         return new WireByte(ai.accessorId, ai.type, ref);
161                 } else 
162                 if (ai.type instanceof IntegerType) {
163                         return new WireInteger(ai.accessorId, ai.type, ref);
164                 } else 
165                 if (ai.type instanceof LongType) {
166                         return new WireLong(ai.accessorId, ai.type, ref);
167                 } else 
168                 if (ai.type instanceof FloatType) {
169                         return new WireFloat(ai.accessorId, ai.type, ref);
170                 } else 
171                 if (ai.type instanceof DoubleType) {
172                         return new WireDouble(ai.accessorId, ai.type, ref);
173                 } else  
174                 if (ai.type instanceof StringType) {
175                         return new WireByte(ai.accessorId, ai.type, ref);
176                 } else 
177                 if (ai.type instanceof MapType) {
178                         return new WireMap(ai.accessorId, ai.type, ref);
179                 } else 
180                 if (ai.type instanceof OptionalType) {
181                         return new WireOptional(ai.accessorId, ai.type, ref);
182                 } else 
183                 if (ai.type instanceof RecordType) {
184                         return new WireRecord(ai.accessorId, ai.type, ref);
185                 } else 
186                 if (ai.type instanceof UnionType) {
187                         return new WireUnion(ai.accessorId, ai.type, ref);
188                 } else 
189                 if (ai.type instanceof VariantType) {
190                         return new WireVariant(ai.accessorId, ai.type, ref);
191                 } 
192                 throw new WireException("error, unknown data type "+ai.type);
193         }
194         
195         /**
196          * Create or get wire accessor
197          * @param ref path from root
198          * @return wire accessor
199          * @throws WireException
200          */
201         public WireAccessor getAccessor(ChildReference ref) throws WireException {
202                 synchronized(subAccessorMap) {
203                         // Rseult Check cache
204                         closeReleasedAccessors();
205                         WireAccessorReference war = subAccessorMap.get(ref);
206                         WireAccessor result = war == null ? null : war.get();
207                         if (result != null) return result;
208                         
209                         result = createAccessor(ref);
210                         war = new WireAccessorReference(result);
211                         subAccessorMap.put(ref, war);
212                         
213                         return result;
214                 }
215         }
216         
217         /**
218          * Close garbage collected accessors
219          * @throws WireException 
220          */
221         void closeReleasedAccessors() throws WireException {
222                 if (releaseQueue.poll()==null) return;
223                 ArrayList<Integer> ids = new ArrayList<Integer>();
224                 while (releaseQueue.poll() != null) {
225                         try {
226                                 WireAccessorReference ref = (WireAccessorReference) releaseQueue.remove();
227                                 ids.add( ref.accId );
228                         } catch (InterruptedException e) {
229                         }
230                 }
231                 // Close accessors
232                 server.closeAccessors( ids.toArray(new Integer[ids.size()]) );
233         }
234         
235         @Override
236         public int onEvents(int lisId, Event[] events) {
237                 ListenerEntry listener = null;
238                 synchronized(listenerMap) {
239                         listener = listenerMap.getRight(lisId);
240                 }
241                 if (listener==null) return 0;
242
243                 List<Event> list = new CopyOnWriteArrayList<Event>(events);
244                 listener.emitEvents(list);
245                 
246                 return 0;
247         }
248         
249         class WireAccessorReference extends WeakReference<WireAccessor> {
250
251                 int accId;
252                 
253                 public WireAccessorReference(WireAccessor referent) {
254                         super(referent, releaseQueue);
255                         this.accId = referent.accId;
256                 }
257                 
258         }
259         
260         abstract class WireAccessor implements Accessor, CloseableAccessor {
261                 int accId;
262                 ChildReference ref;
263                 Datatype type;          
264                 
265                 WireAccessor(int accId, Datatype type, ChildReference ref) {
266                         this.accId = accId;
267                         this.type = type;
268                         this.ref = ref;                 
269                 }
270
271                 @Override
272                 public Object getValue(Binding binding) throws AccessorException {
273                         try {
274                                 MutableVariant value = server.getValue(accId);
275                                 return value.getValue(binding);
276                         } catch (WireException e) {
277                                 throw new AccessorException(e);
278                         } catch (AdaptException e) {
279                                 throw new AccessorException(e);
280                         }
281                 }
282                 
283                 @Override
284                 public void getValue(Binding binding, Object obj)
285                                 throws AccessorException {
286             try {
287                 MutableVariant value= server.getValue(accId);
288                 binding.readFrom(value.getBinding(), value.getValue(), obj);
289             } catch ( WireException e ) {
290                 throw new AccessorException(e);
291             } catch ( BindingException e ) {
292                 throw new AccessorException(e);
293             }
294                 }
295                 
296                 @Override
297                 public boolean getValue(ChildReference path, Binding binding, Object obj) throws AccessorException {
298                         try {
299                                 Accessor a = getComponent(path);
300                                 a.getValue(binding, obj);
301                                 return true;
302                         } catch (ReferenceException re) {
303                                 return false;
304                         } catch (AccessorConstructionException e) {
305                                 throw new AccessorException(e);
306                         }
307                 }       
308                 
309                 public Object getValue(ChildReference path, Binding binding) throws AccessorException {
310                         try {
311                                 Accessor a = getComponent(path);
312                                 return a.getValue(binding);
313                         } catch (ReferenceException re) {
314                                 return null;
315                         } catch (AccessorConstructionException e) {
316                                 throw new AccessorException(e);
317                         }
318                 }
319                 
320                 
321                 void applyEvent(Event...events) throws AccessorException {
322                         ApplyResult result = server.apply(accId, events, false);
323                         if (result.error != null) throw new AccessorException( result.error );
324                 }
325                 
326                 @Override
327                 public void setValue(Binding binding, Object newValue) throws AccessorException {
328                         applyEvent( new ValueAssigned(binding, newValue) ); 
329                 }
330                 
331                 public boolean setValue(ChildReference path, Binding binding, Object obj) throws AccessorException {
332                         try {
333                                 Accessor a = getComponent(path);
334                                 a.setValue(binding, obj);
335                                 return true;
336                         } catch (ReferenceException re) {
337                                 return false;
338                         } catch (AccessorConstructionException e) {
339                                 throw new AccessorException(e);
340                         }
341                 }
342                 
343                 @SuppressWarnings("unchecked")
344                 @Override
345                 public <T extends Accessor> T getComponent(ChildReference reference)
346                 throws AccessorConstructionException {
347                         try {
348                                 // Create a reference from the root
349                                 ChildReference r = ChildReference.concatenate(ref, reference);
350                                 return (T) WireClient.this.getAccessor( r );
351                         } catch (WireException e) {
352                                 throw new AccessorConstructionException( e ); 
353                         }
354                 }
355
356                 @Override
357                 public void apply(List<Event> changeSet, LinkedList<Event> rollback)
358                                 throws AccessorException {
359                         
360                         ApplyResult result = server.apply(accId, changeSet.toArray(new Event[changeSet.size()]), rollback!=null);
361                         if (rollback!=null && result.rollbackLog!=null)
362                                 rollback.addAll( result.rollbackLog );
363                         if (result.error != null) throw new AccessorException( result.error );
364                         
365                 }
366
367                 @Override
368                 public Datatype type() { 
369                         return type;
370                 }
371
372                 @Override
373                 public void addListener(Listener listener, InterestSet interestSet,
374                                 ChildReference pathPrefix, Executor executor) throws AccessorException {
375                         try {
376                                 ListenerEntry le = new ListenerEntry(listener, interestSet, pathPrefix, executor);
377                                 int lisId = server.addListener(accId, interestSet, pathPrefix);
378                                 synchronized(listenerMap) {
379                                         listenerMap.map(lisId, le);
380                                 }
381                         } catch (WireException e) {
382                                 throw new AccessorException(e);
383                         }
384                 }
385
386                 @Override
387                 public void removeListener(Listener listener) throws AccessorException {
388                         Integer lisId = null;
389                         synchronized(listenerMap) {
390                                 for (Entry<Integer, ListenerEntry> e : listenerMap.getEntries()) {
391                                         if (e.getValue().listener == listener) {
392                                                 lisId = e.getKey();
393                                                 break;
394                                         }
395                                 }
396                                 if (lisId==null) return;
397                                 listenerMap.removeWithLeft(lisId);
398                         }
399                         try {
400                                 server.removeListener(lisId);
401                         } catch (WireException e) {
402                                 throw new AccessorException( e );
403                         }                       
404                 }
405                 
406                 public void close() throws AccessorException {
407                         try {
408                                 server.closeAccessors( new Integer[] {accId} );
409                         } catch (WireException e) {
410                                 throw new AccessorException( e );
411                         }
412                 }
413
414         }
415         
416         class WireBoolean extends WireAccessor implements BooleanAccessor {
417
418                 WireBoolean(int accId, Datatype type, ChildReference ref) {
419                         super(accId, type, ref);
420                 }
421                 
422                 @Override
423                 public BooleanType type() { 
424                         return (BooleanType) type;
425                 }
426                 
427                 @Override
428                 public boolean getValue() throws AccessorException {
429                         try {
430                                 MutableVariant value = server.getValue(accId);
431                                 return (Boolean) value.getValue( Bindings.BOOLEAN );
432                         } catch (WireException e) {
433                                 throw new AccessorException( e );
434                         } catch (AdaptException e) {
435                                 throw new AccessorException( e );
436                         }
437                 }
438
439                 @Override
440                 public void setValue(boolean value) throws AccessorException {
441                         Event e = new ValueAssigned(null, Bindings.BOOLEAN, value); 
442                         Event[] list = new Event[] {e};
443                         ApplyResult result = server.apply(accId, list, false);
444                         if (result.error != null) throw new AccessorException( result.error );
445                 }
446         }       
447         
448         class WireByte extends WireAccessor implements ByteAccessor {
449
450                 WireByte(int accId, Datatype type, ChildReference ref) {
451                         super(accId, type, ref);
452                 }
453                 
454                 @Override
455                 public ByteType type() { 
456                         return (ByteType) type;
457                 }
458                 
459                 @Override
460                 public byte getValue() throws AccessorException {
461                         try {
462                                 MutableVariant value = server.getValue(accId);
463                                 return (Byte) value.getValue( Bindings.BYTE );
464                         } catch (WireException e) {
465                                 throw new AccessorException( e );
466                         } catch (AdaptException e) {
467                                 throw new AccessorException( e );
468                         }
469                 }
470                 
471                 @Override
472                 public void setValue(byte value) throws AccessorException {
473                         Event e = new ValueAssigned(null, Bindings.BYTE, value); 
474                         Event[] list = new Event[] {e};
475                         ApplyResult result = server.apply(accId, list, false);
476                         if (result.error != null) throw new AccessorException( result.error );
477                 }
478         }
479
480         class WireInteger extends WireAccessor implements IntegerAccessor {
481
482                 WireInteger(int accId, Datatype type, ChildReference ref) {
483                         super(accId, type, ref);
484                 }
485                 
486                 @Override
487                 public IntegerType type() { 
488                         return (IntegerType) type;
489                 }
490                 
491                 @Override
492                 public int getValue() throws AccessorException {
493                         try {
494                                 MutableVariant value = server.getValue(accId);
495                                 return (Integer) value.getValue( Bindings.INTEGER );
496                         } catch (WireException e) {
497                                 throw new AccessorException( e );
498                         } catch (AdaptException e) {
499                                 throw new AccessorException( e );
500                         }
501                 }
502
503                 @Override
504                 public void setValue(int value) throws AccessorException {
505                         Event e = new ValueAssigned(Bindings.INTEGER, value); 
506                         Event[] list = new Event[] {e};
507                         ApplyResult result = server.apply(accId, list, false);
508                         if (result.error != null) throw new AccessorException( result.error );
509                 }
510
511         }
512
513         class WireLong extends WireAccessor implements LongAccessor {
514
515                 WireLong(int accId, Datatype type, ChildReference ref) {
516                         super(accId, type, ref);
517                 }
518                 
519                 @Override
520                 public LongType type() { 
521                         return (LongType) type;
522                 }
523                 
524                 @Override
525                 public long getValue() throws AccessorException {
526                         try {
527                                 MutableVariant value = server.getValue(accId);
528                                 return (Long) value.getValue( Bindings.LONG );
529                         } catch (WireException e) {
530                                 throw new AccessorException( e );
531                         } catch (AdaptException e) {
532                                 throw new AccessorException( e );
533                         }
534                 }
535
536                 @Override
537                 public void setValue(long value) throws AccessorException {
538                         Event e = new ValueAssigned(Bindings.LONG, value); 
539                         Event[] list = new Event[] {e};
540                         ApplyResult result = server.apply(accId, list, false);
541                         if (result.error != null) throw new AccessorException( result.error );
542                 }
543
544         }
545
546         class WireFloat extends WireAccessor implements FloatAccessor {
547
548                 WireFloat(int accId, Datatype type, ChildReference ref) {
549                         super(accId, type, ref);
550                 }
551                 
552                 @Override
553                 public FloatType type() { 
554                         return (FloatType) type;
555                 }
556                 
557                 @Override
558                 public float getValue() throws AccessorException {
559                         try {
560                                 MutableVariant value = server.getValue(accId);
561                                 return (Float) value.getValue( Bindings.FLOAT );
562                         } catch (WireException e) {
563                                 throw new AccessorException( e );
564                         } catch (AdaptException e) {
565                                 throw new AccessorException( e );
566                         }
567                 }
568
569                 @Override
570                 public void setValue(float value) throws AccessorException {
571                         Event e = new ValueAssigned(Bindings.FLOAT, value); 
572                         Event[] list = new Event[] {e};
573                         ApplyResult result = server.apply(accId, list, false);
574                         if (result.error != null) throw new AccessorException( result.error );
575                 }
576
577         }
578
579         class WireDouble extends WireAccessor implements DoubleAccessor {
580
581                 WireDouble(int accId, Datatype type, ChildReference ref) {
582                         super(accId, type, ref);
583                 }
584                 
585                 @Override
586                 public DoubleType type() { 
587                         return (DoubleType) type;
588                 }
589                 
590                 @Override
591                 public double getValue() throws AccessorException {
592                         try {
593                                 MutableVariant value = server.getValue(accId);
594                                 return (Double) value.getValue( Bindings.DOUBLE );
595                         } catch (WireException e) {
596                                 throw new AccessorException( e );
597                         } catch (AdaptException e) {
598                                 throw new AccessorException( e );
599                         }
600                 }
601
602                 @Override
603                 public void setValue(double value) throws AccessorException {
604                         Event e = new ValueAssigned(Bindings.DOUBLE, value); 
605                         Event[] list = new Event[] {e};
606                         ApplyResult result = server.apply(accId, list, false);
607                         if (result.error != null) throw new AccessorException( result.error );
608                 }
609
610         }
611
612         class WireArray extends WireAccessor implements ArrayAccessor {
613
614                 WireArray(int accId, Datatype type, ChildReference ref) {
615                         super(accId, type, ref);
616                 }
617                 
618                 @Override
619                 public ArrayType type() { 
620                         return (ArrayType) type;
621                 }
622
623                 @Override
624                 public void add(Binding binding, Object value) throws AccessorException {
625                         try {
626                                 server.addAll(accId, -1, new MutableVariant(binding, value));
627                         } catch (WireException e) {
628                                 throw new AccessorException(e);
629                         }
630                 }
631
632                 @Override
633                 public void addAll(Binding binding, Object[] values) throws AccessorException {
634                         try {
635                                 ArrayBinding ab = new ObjectArrayBinding(new ArrayType(binding.type()), binding);
636                                 MutableVariant array = new MutableVariant(ab, values);
637                                 server.addAll(accId, -1, array);
638                         } catch (WireException e) {
639                                 throw new AccessorException(e);
640                         }
641                 }
642
643                 @Override
644                 public void addAll(int index, Binding binding, Object[] values)
645                                 throws AccessorException {
646                         try {
647                                 ArrayBinding ab = new ObjectArrayBinding(new ArrayType(binding.type()), binding);
648                                 MutableVariant array = new MutableVariant(ab, values);
649                                 server.addAll(accId, index, array);
650                         } catch (WireException e) {
651                                 throw new AccessorException(e);
652                         }
653                 }
654
655                 @Override
656                 public void add(int index, Binding binding, Object value) throws AccessorException {
657                         try {
658                                 server.addAll(accId, index, new MutableVariant(binding, value));
659                         } catch (WireException e) {
660                                 throw new AccessorException(e);
661                         }
662                 }
663
664                 @Override
665                 public void set(int index, Binding binding, Object value)
666                                 throws AccessorException {
667                         applyEvent(new ValueAssigned(new IndexReference(index), binding, value));
668                 }
669
670                 @Override
671                 public void remove(int index, int count) throws AccessorException {
672                         applyEvent(new ArrayElementRemoved(index));                     
673                 }
674
675                 @SuppressWarnings("unchecked")
676                 @Override
677                 public <T extends Accessor> T getAccessor(int index)
678                                 throws AccessorConstructionException {
679                         return (T) getComponent(new IndexReference(index));
680                 }
681
682                 @Override
683                 public Object get(int index, Binding valueBinding)
684                                 throws AccessorException {
685                         try {
686                                 MutableVariant v = server.getArrayElement(accId, index);
687                                 return v.getValue(valueBinding);
688                         } catch (WireException e) {
689                                 throw new AccessorException(e);
690                         } catch (AdaptException e) {
691                                 throw new AccessorException(e);
692                         }
693                 }
694                 
695                 @Override
696                 public void get(int index, Binding valueBinding, Object dst)
697                                 throws AccessorException {
698                         try {
699                                 MutableVariant v = server.getArrayElement(accId, index);
700                                 valueBinding.readFrom(v.getBinding(), v.getValue(), v);
701                         } catch (WireException e) {
702                                 throw new AccessorException(e);
703                         } catch (BindingException e) {
704                                 throw new AccessorException(e);
705                         }
706                 }               
707
708                 @Override
709                 public void getAll(Binding valueBinding, Object[] array)
710                                 throws AccessorException {
711                         ObjectArrayBinding arrayBinding = new ObjectArrayBinding(type(), valueBinding);
712                         Object[] a2 = (Object[]) getValue(arrayBinding);
713                         System.arraycopy(a2, 0, array, 0, a2.length);                   
714                 }
715
716                 @Override
717                 public void getAll(Binding valueBinding, Collection<Object> values)
718                                 throws AccessorException {
719                         ArrayListBinding arrayBinding = new ArrayListBinding(type(), valueBinding);
720                         ArrayList<?> a2 = (ArrayList<?>) getValue(arrayBinding);
721                         values.addAll(a2);                      
722                 }
723                 
724                 @Override
725                 public void setSize(int newSize) throws AccessorException {
726                         throw new AccessorException("Not implemented");
727                 }
728
729                 @Override
730                 public int size() throws AccessorException {
731                         try {
732                                 return server.size(accId);
733                         } catch (WireException e) {
734                                 throw new AccessorException( e );
735                         }
736                 }
737         }
738         
739         class WireMap extends WireAccessor implements MapAccessor {
740
741                 WireMap(int accId, Datatype type, ChildReference ref) {
742                         super(accId, type, ref);
743                 }
744                 
745                 @Override
746                 public MapType type() { 
747                         return (MapType) type;
748                 }               
749
750                 @Override
751                 public int size() throws AccessorException {
752                         try {
753                                 return server.size(accId);
754                         } catch (WireException e) {
755                                 throw new AccessorException( e );
756                         }
757                 }
758
759                 @Override
760                 public Object get(Binding keyBinding, Object key, Binding valueBinding)
761                                 throws AccessorException {
762                         try {
763                                 MutableVariant value = server.getMapValue(accId, new MutableVariant(keyBinding, key));
764                 if (value.type().equals(Datatypes.VOID)) return null;
765                                 return value.getValue(valueBinding);
766                         } catch (WireException e) {
767                                 throw new AccessorException( e );
768                         } catch (AdaptException e) {
769                                 throw new AccessorException( e );
770                         }
771                 }
772
773                 @Override
774                 public boolean containsKey(Binding keyBinding, Object key)
775                                 throws AccessorException {
776                         try {
777                                 return server.containsKey(accId, new MutableVariant(keyBinding, key));
778                         } catch (WireException e) {
779                                 throw new AccessorException( e );
780                         }
781                 }
782
783                 @Override
784                 public boolean containsValue(Binding valueBinding, Object value)
785                                 throws AccessorException {
786                         try {
787                                 return server.containsValue(accId, new MutableVariant(valueBinding, value));
788                         } catch (WireException e) {
789                                 throw new AccessorException( e );
790                         }
791                 }
792
793                 @Override
794                 public void put(Binding keyBinding, Object key, Binding valueBinding,
795                                 Object value) throws AccessorException {
796                         applyEvent( new MapEntryAdded(new MutableVariant(keyBinding, key), new MutableVariant(valueBinding, value)) );
797                 }
798
799                 @Override
800                 public void remove(Binding keyBinding, Object key)
801                                 throws AccessorException {
802                         applyEvent( new MapEntryRemoved(new MutableVariant(keyBinding, key)) );
803                 }
804
805                 @Override
806                 public void clear() throws AccessorException {
807                         try {
808                                 server.clear(accId);
809                         } catch (WireException e) {
810                                 throw new AccessorException(e);
811                         }                       
812                 }
813
814                 @Override
815                 public void putAll(Binding keyBinding, Binding valueBinding,
816                                 Map<Object, Object> from) throws AccessorException {
817                         
818                         int count = from.size();
819                         Event events[] = new Event[ count ];
820                         int i = 0;
821                         for (Entry<Object, Object> e : from.entrySet()) {
822                                 MutableVariant key = new MutableVariant( keyBinding, e.getKey() );
823                                 MutableVariant value = new MutableVariant( valueBinding, e.getValue() );
824                                 events[i] = new MapEntryAdded( key, value );
825                                 ++i;
826                         }
827                         applyEvent( events );                                           
828                 }
829
830                 @Override
831                 public void putAll(Binding keyBinding, Binding valueBinding,
832                                 Object[] keys, Object[] values) throws AccessorException {
833                         if (keys.length != values.length) throw new AccessorException("bad args");
834                         int count = keys.length;
835                         Event events[] = new Event[ count ];
836                         for (int i=0; i<count; i++) {
837                                 events[i] = new MapEntryAdded( new MutableVariant(keyBinding, keys[i]), new MutableVariant(valueBinding, values[i]) );
838                         }
839                         applyEvent( events );                   
840                 }
841
842                 @SuppressWarnings("unchecked")
843         @Override
844                 public void getAll(Binding keyBinding, Binding valueBinding,
845                                 Map<Object, Object> to) throws AccessorException {
846                         MapBinding binding = new TreeMapBinding(keyBinding, valueBinding);
847                         TreeMap<Object, Object> v = (TreeMap<Object, Object>) getValue(binding);
848                         to.putAll(v);
849                 }
850
851                 @SuppressWarnings("unchecked")
852         @Override
853                 public void getAll(Binding keyBinding, Binding valueBinding,
854                                 Object[] keys, Object[] values) throws AccessorException {
855                         MapBinding binding = new TreeMapBinding(keyBinding, valueBinding);
856                         TreeMap<Object, Object> v = (TreeMap<Object, Object>) getValue(binding);
857                         int i=0;
858                         for (Entry<Object, Object> e : v.entrySet()) {
859                                 keys[i] = e.getKey();
860                                 values[i] = e.getValue();
861                                 ++i;
862                         }
863                 }
864
865                 @Override
866                 public Object[] getKeys(Binding keyBinding) throws AccessorException {
867                         try {
868                                 MutableVariant array = server.getMapKeys(accId);
869                                 ArrayBinding binding = new ObjectArrayBinding( keyBinding );
870                                 return (Object[]) array.getValue(binding);
871                         } catch (WireException e) {
872                                 throw new AccessorException( e );
873                         } catch (AdaptException e) {
874                                 throw new AccessorException( e );
875                         }
876                 }
877
878                 @Override
879                 public int count(Binding keyBinding, Object from,
880                                 boolean fromInclusive, Object end, boolean endInclusive)
881                                 throws AccessorException {
882                         throw new AccessorException("Not implemented");
883                 }
884
885                 @Override
886                 public int getEntries(Binding keyBinding, Object from,
887                                 boolean fromInclusive, Object end, boolean endInclusive,
888                                 ArrayBinding keyArrayBinding, Object dstKeys,
889                                 ArrayBinding valueArrayBinding, Object dstValues, int limit)
890                                 throws AccessorException {
891                         throw new AccessorException("Not implemented");
892                 }
893                 
894
895                 @Override
896                 public Object[] getValues(Binding valueBinding)
897                                 throws AccessorException {
898                         try {
899                                 MutableVariant array = server.getMapValues(accId);
900                                 ArrayBinding binding = new ObjectArrayBinding( valueBinding );
901                                 return (Object[]) array.getValue(binding);
902                         } catch (WireException e) {
903                                 throw new AccessorException( e );
904                         } catch (AdaptException e) {
905                                 throw new AccessorException( e );
906                         }
907                 }
908
909                 @SuppressWarnings("unchecked")
910                 @Override
911                 public <T extends Accessor> T getValueAccessor(Binding keyBinding, Object key) throws AccessorConstructionException {
912                         return (T) getComponent( new KeyReference(keyBinding, key) );
913                 }
914
915                 @Override
916                 public Object getFirstKey(Binding keyBinding) throws AccessorException {
917                         try {
918                                 MutableVariant result = server.getFirstKey(accId);
919                 if (result.type().equals(Datatypes.VOID)) return null;
920                                 return result.getValue(keyBinding);
921                         } catch (WireException e) {
922                                 throw new AccessorException(e);
923                         } catch (AdaptException e) {
924                                 throw new AccessorException(e);
925                         }
926                 }
927
928                 @Override
929                 public Object getLastKey(Binding keyBinding) throws AccessorException {
930                         try {
931                                 MutableVariant result = server.getLastKey(accId);
932                 if (result.type().equals(Datatypes.VOID)) return null;
933                                 return result.getValue(keyBinding);
934                         } catch (WireException e) {
935                                 throw new AccessorException(e);
936                         } catch (AdaptException e) {
937                                 throw new AccessorException(e);
938                         }
939                 }
940
941                 @Override
942                 public Object getLowerKey(Binding keyBinding, Object key)
943                                 throws AccessorException {
944                         try {
945                                 MutableVariant result = server.getLowerKey(accId, new MutableVariant(keyBinding, key));
946                                 if (result.type().equals(Datatypes.VOID)) return null;
947                                 return result.getValue(keyBinding);
948                         } catch (WireException e) {
949                                 throw new AccessorException(e);
950                         } catch (AdaptException e) {
951                                 throw new AccessorException(e);
952                         }
953                 }
954
955                 @Override
956                 public Object getFloorKey(Binding keyBinding, Object key)
957                                 throws AccessorException {
958                         try {
959                                 MutableVariant result = server.getFloorKey(accId, new MutableVariant(keyBinding, key));
960                 if (result.type() == Datatypes.VOID) return null;
961                                 return result.getValue(keyBinding);
962                         } catch (WireException e) {
963                                 throw new AccessorException(e);
964                         } catch (AdaptException e) {
965                                 throw new AccessorException(e);
966                         }
967                 }
968
969                 @Override
970                 public Object getCeilingKey(Binding keyBinding, Object key)
971                                 throws AccessorException {
972                         try {
973                                 MutableVariant result = server.getCeilingKey(accId, new MutableVariant(keyBinding, key));
974                 if (result.type().equals(Datatypes.VOID)) return null;
975                                 return result.getValue(keyBinding);
976                         } catch (WireException e) {
977                                 throw new AccessorException(e);
978                         } catch (AdaptException e) {
979                                 throw new AccessorException(e);
980                         }
981                 }
982
983                 @Override
984                 public Object getHigherKey(Binding keyBinding, Object key)
985                                 throws AccessorException {
986                         try {
987                                 MutableVariant result = server.getHigherKey(accId, new MutableVariant(keyBinding, key));
988                 if (result.type().equals(Datatypes.VOID)) return null;
989                                 return result.getValue(keyBinding);
990                         } catch (WireException e) {
991                                 throw new AccessorException(e);
992                         } catch (AdaptException e) {
993                                 throw new AccessorException(e);
994                         }
995                 }
996                 
997         }
998         
999         class WireOptional extends WireAccessor implements OptionalAccessor {
1000
1001                 WireOptional(int accId, Datatype type, ChildReference ref) {
1002                         super(accId, type, ref);
1003                 }
1004                 
1005                 @Override
1006                 public OptionalType type() { 
1007                         return (OptionalType) type;
1008                 }                               
1009
1010                 @Override
1011                 public void setNoValue() throws AccessorException {
1012                         applyEvent( new OptionalValueRemoved() );
1013                 }
1014
1015                 @Override
1016                 public boolean hasValue() throws AccessorException {
1017                         try {
1018                                 return server.hasValue(accId);
1019                         } catch (WireException e) {
1020                                 throw new AccessorException( e );                               
1021                         }
1022                 }
1023
1024                 @Override
1025                 public Object getComponentValue(Binding componentBinding)
1026                                 throws AccessorException {
1027                         try {
1028                                 WireAccessor sa = createAccessor( new ComponentReference() );
1029                                 try {
1030                                         return sa.getValue(componentBinding);
1031                                 } finally {
1032                                         sa.close();
1033                                 }
1034                         } catch (WireException e) {
1035                                 throw new AccessorException( e );                               
1036                         }
1037                 }
1038
1039                 @Override
1040                 public void setComponentValue(Binding binding, Object value)
1041                                 throws AccessorException {                      
1042                         applyEvent(new OptionalValueAssigned(binding, value));
1043                 }
1044
1045                 @SuppressWarnings("unchecked")
1046                 @Override
1047                 public <T extends Accessor> T getComponentAccessor()
1048                                 throws AccessorConstructionException {
1049                         return (T) getComponent( new ComponentReference() );
1050                 }
1051                 
1052         }
1053         
1054         class WireRecord extends WireAccessor implements RecordAccessor {
1055
1056                 WireRecord(int accId, Datatype type, ChildReference ref) {
1057                         super(accId, type, ref);
1058                 }
1059                 
1060                 @Override
1061                 public RecordType type() { 
1062                         return (RecordType) type;
1063                 }               
1064
1065                 @Override
1066                 public int count() throws AccessorException {                   
1067                         try {
1068                                 return server.size(accId);
1069                         } catch (WireException e) {
1070                                 throw new AccessorException(e);
1071                         }
1072                 }
1073
1074                 @SuppressWarnings("unchecked")
1075                 @Override
1076                 public <T extends Accessor> T getFieldAccessor(int index)
1077                                 throws AccessorConstructionException {
1078                         return (T) getComponent( new IndexReference(index) );
1079                 }
1080
1081                 @SuppressWarnings("unchecked")
1082                 @Override
1083                 public <T extends Accessor> T getFieldAccessor(String fieldName)
1084                                 throws AccessorConstructionException {
1085                         return (T) getComponent( new NameReference( fieldName ) );
1086                 }
1087
1088                 @Override
1089                 public Object getFieldValue(String fieldName, Binding fieldBinding)
1090                                 throws AccessorException {
1091                         int fieldIndex = type().getComponentIndex(fieldName);
1092                         if (fieldIndex<0) throw new AccessorException("Field "+fieldName+" does not exist");
1093                         return getFieldValue(fieldIndex, fieldBinding);
1094                 }
1095                 
1096                 @Override
1097                 public Object getFieldValue(int index, Binding fieldBinding)
1098                                 throws AccessorException {
1099                         try {
1100                                 WireAccessor sa = createAccessor( new IndexReference(index) );
1101                                 try {
1102                                         return sa.getValue(fieldBinding);
1103                                 } finally {
1104                                         sa.close();
1105                                 }
1106                         } catch (WireException e) {
1107                                 throw new AccessorException( e );                               
1108                         }
1109                 }
1110                 
1111                 public void setFieldValue(String fieldName, Binding fieldBinding, Object value) throws AccessorException {
1112                         int fieldIndex = type().getComponentIndex(fieldName);
1113                         if (fieldIndex<0) throw new AccessorException("Field "+fieldName+" does not exist");
1114                         setFieldValue(fieldIndex, fieldBinding, value);
1115                 };
1116
1117                 @Override
1118                 public void setFieldValue(int index, Binding fieldBinding, Object value)
1119                                 throws AccessorException {
1120                         try {
1121                                 WireAccessor sa = createAccessor( new IndexReference(index) );
1122                                 try {
1123                                         sa.setValue(fieldBinding, value);
1124                                 } finally {
1125                                         sa.close();
1126                                 }
1127                         } catch (WireException e) {
1128                                 throw new AccessorException( e );                               
1129                         }
1130                 }
1131                 
1132         }
1133         
1134         class WireString extends WireAccessor implements StringAccessor {
1135
1136                 WireString(int accId, Datatype type, ChildReference ref) {
1137                         super(accId, type, ref);
1138                 }
1139
1140                 @Override
1141                 public StringType type() { 
1142                         return (StringType) type;
1143                 }               
1144
1145                 @Override
1146                 public String getValue() throws AccessorException {
1147                         try {
1148                                 MutableVariant value = server.getValue(accId);
1149                                 return (String) value.getValue( Bindings.STRING );
1150                         } catch (WireException e) {
1151                                 throw new AccessorException( e );
1152                         } catch (AdaptException e) {
1153                                 throw new AccessorException( e );
1154                         }
1155                 }
1156
1157                 @Override
1158                 public void setValue(String newValue) throws AccessorException {
1159                         Event e = new ValueAssigned( Bindings.STRING, newValue); 
1160                         Event[] list = new Event[] {e};
1161                         ApplyResult result = server.apply(accId, list, false);
1162                         if (result.error != null) throw new AccessorException( result.error );
1163                 }
1164                 
1165         }
1166         
1167         class WireUnion extends WireAccessor implements UnionAccessor {
1168
1169                 WireUnion(int accId, Datatype type, ChildReference ref) {
1170                         super(accId, type, ref);
1171                 }
1172                 
1173                 @Override
1174                 public UnionType type() { 
1175                         return (UnionType) type;
1176                 }                               
1177
1178                 @Override
1179                 public int count() throws AccessorException {
1180                         try {
1181                                 return server.size(accId);
1182                         } catch (WireException e) {
1183                                 throw new AccessorException(e);
1184                         }
1185                 }
1186
1187                 @Override
1188                 public int getTag() throws AccessorException {
1189                         try {
1190                                 return server.getTag(accId);
1191                         } catch (WireException e) {
1192                                 throw new AccessorException(e);
1193                         }
1194                 }
1195
1196                 @SuppressWarnings("unchecked")
1197                 @Override
1198                 public <T extends Accessor> T getComponentAccessor()
1199                                 throws AccessorConstructionException {
1200                         return (T) getComponent(new ComponentReference());
1201                 }
1202
1203                 @Override
1204                 public Object getComponentValue(Binding componentBinding)
1205                                 throws AccessorException {
1206                         try {
1207                                 WireAccessor sa = createAccessor( new ComponentReference() );
1208                                 try {
1209                                         return sa.getValue(componentBinding);
1210                                 } finally {
1211                                         sa.close();
1212                                 }
1213                         } catch (WireException e) {
1214                                 throw new AccessorException( e );                               
1215                         }
1216                 }
1217
1218                 @Override
1219                 public void setComponentValue(int tag, Binding componentBinding,
1220                                 Object componentValue) throws AccessorException {
1221                         try {
1222                                 WireAccessor sa = createAccessor( new ComponentReference() );
1223                                 try {
1224                                         sa.setValue(componentBinding, componentValue);
1225                                 } finally {
1226                                         sa.close();
1227                                 }
1228                         } catch (WireException e) {
1229                                 throw new AccessorException( e );                               
1230                         }                       
1231                         
1232                 }
1233                 
1234         }
1235         
1236         class WireVariant extends WireAccessor implements VariantAccessor {
1237
1238                 WireVariant(int accId, Datatype type, ChildReference ref) {
1239                         super(accId, type, ref);
1240                 }
1241
1242                 @Override
1243                 public VariantType type() { 
1244                         return (VariantType) type;
1245                 }               
1246                 
1247                 @SuppressWarnings("unchecked")
1248                 @Override
1249                 public <T extends Accessor> T getContentAccessor()
1250                                 throws AccessorConstructionException {
1251                         return (T) getComponent(new ComponentReference());
1252                 }
1253
1254                 @Override
1255                 public void setContentValue(Binding valueBinding, Object value)
1256                                 throws AccessorException {
1257                         try {
1258                                 WireAccessor sa = createAccessor( new ComponentReference() );
1259                                 try {
1260                                         sa.setValue(valueBinding, value);
1261                                 } finally {
1262                                         sa.close();
1263                                 }
1264                         } catch (WireException e) {
1265                                 throw new AccessorException( e );                               
1266                         }
1267                 }
1268
1269                 @Override
1270                 public Object getContentValue(Binding contentBinding)
1271                                 throws AccessorException {
1272                         try {
1273                                 WireAccessor sa = createAccessor( new ComponentReference() );
1274                                 try {
1275                                         return sa.getValue(contentBinding);
1276                                 } finally {
1277                                         sa.close();
1278                                 }
1279                         } catch (WireException e) {
1280                                 throw new AccessorException( e );                               
1281                         }
1282                 }
1283
1284                 @Override
1285                 public Datatype getContentType() throws AccessorException {
1286                         try {
1287                                 WireAccessor sa = createAccessor( new ComponentReference() );
1288                                 try {
1289                                         return sa.type();
1290                                 } finally {
1291                                         sa.close();
1292                                 }
1293                         } catch (WireException e) {
1294                                 throw new AccessorException( e );                               
1295                         }
1296                 }
1297                 
1298         }
1299
1300         
1301 }
1302