]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.databoard/src/org/simantics/databoard/accessor/java/JavaMap.java
Fixed all line endings of the repository
[simantics/platform.git] / bundles / org.simantics.databoard / src / org / simantics / databoard / accessor / java / JavaMap.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.java;
13
14 import java.lang.ref.SoftReference;
15 import java.util.Map;
16 import java.util.Map.Entry;
17 import java.util.Set;
18 import java.util.TreeMap;
19 import java.util.TreeSet;
20 import java.util.concurrent.Executor;
21
22 import org.simantics.databoard.Bindings;
23 import org.simantics.databoard.accessor.Accessor;
24 import org.simantics.databoard.accessor.MapAccessor;
25 import org.simantics.databoard.accessor.error.AccessorConstructionException;
26 import org.simantics.databoard.accessor.error.AccessorException;
27 import org.simantics.databoard.accessor.error.ReferenceException;
28 import org.simantics.databoard.accessor.event.Event;
29 import org.simantics.databoard.accessor.event.MapEntryAdded;
30 import org.simantics.databoard.accessor.event.MapEntryRemoved;
31 import org.simantics.databoard.accessor.event.ValueAssigned;
32 import org.simantics.databoard.accessor.impl.AccessorParams;
33 import org.simantics.databoard.accessor.impl.ListenerEntry;
34 import org.simantics.databoard.accessor.interestset.InterestSet;
35 import org.simantics.databoard.accessor.interestset.MapInterestSet;
36 import org.simantics.databoard.accessor.reference.ChildReference;
37 import org.simantics.databoard.accessor.reference.KeyReference;
38 import org.simantics.databoard.accessor.reference.LabelReference;
39 import org.simantics.databoard.adapter.AdaptException;
40 import org.simantics.databoard.adapter.Adapter;
41 import org.simantics.databoard.adapter.AdapterConstructionException;
42 import org.simantics.databoard.binding.ArrayBinding;
43 import org.simantics.databoard.binding.Binding;
44 import org.simantics.databoard.binding.MapBinding;
45 import org.simantics.databoard.binding.error.BindingException;
46 import org.simantics.databoard.binding.mutable.MutableVariant;
47 import org.simantics.databoard.type.MapType;
48
49 public class JavaMap extends JavaObject implements MapAccessor {
50
51         /** Accessors to children */
52         TreeMap<Object, SoftReference<JavaObject>> children;
53         
54         public JavaMap(Accessor parent, MapBinding binding, Object object, AccessorParams params) {
55                 super(parent, binding, object, params);
56                 children = new TreeMap<Object, SoftReference<JavaObject>>(binding.getKeyBinding());
57         }
58         
59         @Override
60         public MapType type() {
61                 return (MapType) binding.type();
62         }
63         
64         @Override
65         public MapBinding getBinding() {
66                 return (MapBinding) binding;
67         }
68         
69         public Binding getKeyBinding() {
70                 return getBinding().getKeyBinding();
71         }
72
73         public Binding getValueBinding() {
74                 return getBinding().getValueBinding();
75         }
76
77         @Override
78         public void clear() throws AccessorException {
79                 writeLock();
80                 try {
81                         if (getBinding().size(object)==0) return;
82                         boolean hasListeners = listeners!=null;
83                         Binding kb = getKeyBinding();
84
85                         Object[] keys = hasListeners ? getBinding().getKeys(object) : null; 
86                         
87                         // Write
88                         getBinding().clear(object);
89                                                 
90                         // Disconnect sub-accessor
91                         for (SoftReference<JavaObject> ref : children.values()) {
92                                 JavaObject sa = ref.get();
93                                 if (sa==null) continue;
94                                 sa.invalidatedNotification();
95                         }
96                         children.clear();
97                         
98                         // Notify Listeners
99                         ListenerEntry le = listeners;
100                         while (le!=null) {                              
101                                 MapInterestSet is = le.getInterestSet();
102                                 for (Object key : keys) {
103                                         MutableVariant var = new MutableVariant(kb, key);
104                                         if (is.inNotificationsOf(var)) {
105                                                 MapEntryRemoved e = new MapEntryRemoved(var); 
106                                                 emitEvent(le, e);
107                                         }
108                                 }
109                                                                 
110                                 le = le.next;
111                         }               
112                         
113                 } catch (BindingException e) {
114                         throw new AccessorException( e );
115                 } finally {
116                         writeUnlock();
117                 }
118         }
119
120         /**
121          * Remove element with local key
122          * 
123          * @param localKey
124          * @throws AccessorException
125          */
126         void removeLocal(Object lk) throws AccessorException {
127                 writeLock();
128                 try {
129                         boolean hadValue = getBinding().containsKey(object, lk); 
130                         if (!hadValue) return;
131                         
132                         // Write
133                         getBinding().remove(object, lk);
134                                                 
135                         // Disconnect sub-accessor
136                         JavaObject sa = getExistingAccessor(lk);
137                         // Notify about disconnection of sub-accessor
138                         if (sa!=null) {
139                                 sa.invalidatedNotification();
140                                 children.remove(lk);
141                         }                               
142                         
143                         // Notify Listeners
144                         if (listeners!=null) {
145                                 MutableVariant var = new MutableVariant(getKeyBinding(), lk);
146                                 ListenerEntry le = listeners;
147                                 while (le!=null) {                              
148                                         MapInterestSet is = le.getInterestSet();                                
149                                         if (is.inNotificationsOf(var)) {
150                                                 MapEntryRemoved e = new MapEntryRemoved(var); 
151                                                 emitEvent(le, e);
152                                         }
153                                                                         
154                                         le = le.next;
155                                 }               
156                         }
157                         
158                 } catch (BindingException e) {
159                         throw new AccessorException( e );
160                 } finally {
161                         writeUnlock();
162                 }
163         }
164         
165         void putLocal(Object lk, Object lv) throws AccessorException {
166                 writeLock();
167                 try {
168                         JavaObject sa = getExistingAccessor(lk);                                
169                         if (sa==null) {
170                                 boolean hadOldValue = getBinding().containsKey(object, lk);
171                                 
172                                 // Init
173                                 Binding kb = getKeyBinding();
174                                 Binding vb = getValueBinding();
175                                 
176                                 // Compare to old value
177                                 Object oldLv = null;
178                                 if (hadOldValue) {
179                                         oldLv = getBinding().get(object, lk);
180                                         // Compare to existing value
181 //                                      boolean equal = vb.equals(oldLv, lv);
182 //                                      if (equal) return;
183                                 }                               
184
185                                 // Write
186                                 getBinding().put(object, lk, lv);
187                                                                                         
188                                 // Key variant
189                                 MutableVariant kv = new MutableVariant(kb, lk);
190                                 
191                                 // Notify Listeners
192                                 if (listeners!=null) {
193                                         ListenerEntry le = listeners;
194                                         while (le!=null) {                              
195                                                 MapInterestSet is = le.getInterestSet();
196                                                 if (is.inNotificationsOf(kv)) {
197                                                         
198                                                         MutableVariant vv = null;
199                                                         if (is.inValuesOf(kv)) vv = new MutableVariant(vb, vb.isImmutable() ? lv : vb.clone(lv));
200                                                         
201                                                         if (hadOldValue) {
202                                                                 // Notify about new assignment to old value                                                             
203                                                                 Event e = new ValueAssigned( new KeyReference(kv), vv);
204                                                                 emitEvent(le, e);
205                                                         } else {
206                                                                 // Notify about new entry
207                                                                 MapEntryAdded e = new MapEntryAdded(kv, vv);
208                                                                 emitEvent(le, e);
209                                                         }
210                                                 }
211                                                 
212                                                 le = le.next;
213                                         }
214                                 }
215                         } else {
216                                 // Recursive write using existing sub-accessor
217                                 sa.setValue(getValueBinding(), lv);
218                         }                       
219                         
220                 } catch (BindingException e) {
221                         throw new AccessorException( e );
222                 } catch (AdaptException e) {
223                         throw new AccessorException( e );
224                 } finally {
225                         writeUnlock();
226                 }
227         }
228         
229         @Override
230         public void put(Binding keyBinding, Object key, Binding valueBinding,
231                         Object value) throws AccessorException {
232                 writeLock();
233                 try {
234                         Object rk = key;
235                         Object rv = value;
236                         Adapter ka = params.adapterScheme.getAdapter(keyBinding, getKeyBinding(), true, false);
237                         Adapter va = params.adapterScheme.getAdapter(valueBinding, getValueBinding(), true, false);
238                         
239                         Object lk = ka.adapt( rk );
240                         Object lv = va.adapt( rv );                             
241                         putLocal(lk, lv);
242                 } catch (AdapterConstructionException e) {
243                         throw new AccessorException(e);
244                 } catch (AdaptException e) {
245                         throw new AccessorException(e);
246                 } finally {
247                         writeUnlock();
248                 }
249                 
250         }
251
252         @Override
253         public void putAll(Binding keyBinding, Binding valueBinding, Map<Object, Object> from)
254                         throws AccessorException {
255                 writeLock();
256                 try {
257                         // Convert keys and values
258                         Adapter ka = params.adapterScheme.getAdapter(keyBinding, getKeyBinding(), true, false);
259                         Adapter va = params.adapterScheme.getAdapter(valueBinding, getValueBinding(), true, false);
260                         
261                         for (Object rk : from.keySet()) {
262                                 Object rv = from.get(rk);
263                                 Object lk = ka.adapt( rk );
264                                 Object lv = va.adapt( rv );                             
265                                 putLocal(lk, lv);
266                         }
267                         
268                 } catch (AdaptException e) {
269                         throw new AccessorException( e );
270                 } catch (AdapterConstructionException e) {
271                         throw new AccessorException( e );
272                 } finally {
273                         writeUnlock();
274                 }
275         }
276                 
277         @Override
278         public void putAll(Binding keyBinding, Binding valueBinding, Object[] keys, Object[] values) throws AccessorException {
279                 writeLock();
280                 try {
281                         // Convert keys and values
282                         int rs = keys.length;
283                         
284                         Adapter ka = params.adapterScheme.getAdapter(keyBinding, getKeyBinding(), true, false);
285                         Adapter va = params.adapterScheme.getAdapter(valueBinding, getValueBinding(), true, false);
286                         
287                         for (int i=0; i<rs; i++) {
288                                 Object lk = ka.adapt( keys[i] );
289                                 Object lv = va.adapt( values[i] );
290                                 
291                                 putLocal(lk, lv);
292                         }
293                         
294                 } catch (AdaptException e) {
295                         throw new AccessorException( e );
296                 } catch (AdapterConstructionException e) {
297                         throw new AccessorException( e );
298                 } finally {
299                         writeUnlock();
300                 }
301         }
302
303         @Override
304         public void remove(Binding keyBinding, Object key) throws AccessorException {
305                 try {
306                         Object rk = key;
307                         Object lk = adapt(rk, keyBinding, getKeyBinding());
308                         removeLocal(lk);
309                 } catch (AdaptException e) {
310                         throw new AccessorException( e );
311                 } catch (AdapterConstructionException e) {
312                         throw new AccessorException( e );
313                 }
314         }
315
316         @Override
317         public void setValue(Binding mapBinding, Object newMap)
318                         throws AccessorException {
319                 try {
320                         MapBinding mb = (MapBinding) mapBinding;
321                         int newSize = mb.size(newMap);
322                         Object rks[] = new Object[newSize];
323                         Object rvs[] = new Object[newSize];
324                         mb.getAll(newMap, rks, rvs);
325                         
326                         Adapter ka = params.adapterScheme.getAdapter(mb.getKeyBinding(), getKeyBinding(), true, false);
327                         Adapter va = params.adapterScheme.getAdapter(mb.getValueBinding(), getValueBinding(), true, false);
328                         
329                         for (int i=0; i<newSize; i++) {
330                                 rks[i] = ka.adapt(rks[i]);
331                                 rvs[i] = va.adapt(rvs[i]);
332                         }
333
334                         setValueLocal(rks, rvs);
335                         
336                 } catch (BindingException e) {
337                         throw new AccessorException( e ); 
338                 } catch (AdapterConstructionException e) {
339                         throw new AccessorException( e ); 
340                 } catch (AdaptException e) {
341                         throw new AccessorException( e ); 
342                 }
343         }
344
345         /**
346          * Set new map with local keys and values
347          * 
348          * @param keys 
349          * @param values
350          * @throws AccessorException 
351          */
352         void setValueLocal(Object keys[], Object values[]) throws AccessorException {
353                 writeLock();
354                 try {
355                         Set<Object> oldKeys = new TreeSet<Object>(getKeyBinding());
356                         getBinding().getKeys(object, oldKeys);
357                                                 
358                         // 1. Put
359                         for (int i=0; i<keys.length; i++) {
360                                 Object key = keys[i];
361                                 Object value = values[i];                               
362                                 putLocal(key, value);                           
363                                 oldKeys.remove(key);
364                         }
365                         
366                         // 2. Remove
367                         for (Object key : oldKeys) {
368                                 removeLocal(key);
369                         }
370                         
371                 } catch (BindingException e) {
372                         throw new AccessorException( e );
373                 } finally {
374                         writeUnlock();
375                 }
376                 
377         }
378         
379         @SuppressWarnings("unchecked")
380         @Override
381         public <T extends Accessor> T getValueAccessor(Binding keyBinding, Object key)
382                         throws AccessorConstructionException {
383                 try {
384                         Object rk = key;
385                         Object lk = params.adapterScheme.getAdapter(keyBinding, getKeyBinding(), true, listeners!=null).adapt(rk);
386
387                         boolean hasKey = getBinding().containsKey(object, lk);
388                         if (!hasKey) {
389                                 throw new AccessorConstructionException("Map doesn't contain the requested element");
390                         }
391                         
392                         JavaObject sa = getExistingAccessor(lk);
393                         if (sa!=null) return (T) sa;
394                         
395                         readLock();
396                         try {
397                                 Binding vb = getBinding().getValueBinding();
398                                 Binding kb = getBinding().getKeyBinding();
399                                 Object lv = getBinding().get(object, lk);
400                                 MutableVariant kv = new MutableVariant(kb, lk);
401                                         
402                                 // Instantiate correct sub accessor. 
403                                 sa = createSubAccessor(this, vb, lv, params);
404                                 sa.keyInParent = lk;                    
405                                 children.put(lk, new SoftReference<JavaObject>(sa));
406                                 
407                                 // Add component interest sets
408                                 ListenerEntry le = listeners;
409                                 while (le!=null) {                              
410                                         MapInterestSet is = le.getInterestSet();
411         
412                                         // Generic element interest
413                                         InterestSet gis = is.getComponentInterest(); 
414                                         if (gis != null) {
415                                                 try {
416                                                         ChildReference childPath = ChildReference.concatenate(le.path, new KeyReference(kv) );
417                                                         sa.addListener(le.listener, gis, childPath, le.executor);
418                                                 } catch (AccessorException e) {
419                                                         throw new AccessorConstructionException(e);
420                                                 }
421                                         }
422                                                 
423                                         // Specific element interest
424                                         InterestSet cis = is.getComponentInterest(kv); 
425                                         if (cis != null) {
426                                                 try {
427                                                         ChildReference childPath = ChildReference.concatenate(le.path, new KeyReference(kv) );
428                                                         sa.addListener(le.listener, cis, childPath, le.executor);
429                                                 } catch (AccessorException e) {
430                                                         throw new AccessorConstructionException(e);
431                                                 }
432                                         }
433                                         
434                                         // Next listener
435                                         le = le.next;
436                                 }                                       
437                         } finally {
438                                 readUnlock();
439                         }
440                         
441                         return (T) sa;
442                 } catch (BindingException e) {
443                         throw new AccessorConstructionException(e);
444                 } catch (AdaptException e) {
445                         throw new AccessorConstructionException(e);
446                 } catch (AdapterConstructionException e) {
447                         throw new AccessorConstructionException(e);
448                 }       
449         }
450
451         /**
452          * Get existing sub accessor
453          * @param index
454          * @return sub-accessor or <code>null</code>
455          */
456         JavaObject getExistingAccessor(Object localKey)
457         {
458                 SoftReference<JavaObject> ref = children.get(localKey);
459                 if (ref==null) return null;
460                 JavaObject result = ref.get();
461                 if (result==null) {
462                         children.remove(localKey);
463                         return null;
464                 }
465                 return result;
466         }       
467         
468         @SuppressWarnings("unchecked")
469         @Override
470         public <T extends Accessor> T getComponent(ChildReference reference)
471                         throws AccessorConstructionException {
472                 if (reference==null) return (T) this;
473                 if (reference instanceof LabelReference) {
474                         LabelReference lr = (LabelReference) reference;
475                         try {
476                                 Binding kb = getKeyBinding();
477                                 MutableVariant variant = (MutableVariant) adapt(lr.label, Bindings.STRING, Bindings.MUTABLE_VARIANT);
478                                 Object value = variant.getValue(kb);
479                                 
480                                 Accessor result = (T) getValueAccessor(kb, value);
481                                 if (reference.getChildReference() != null)
482                                         result = result.getComponent(reference.getChildReference());
483                                 return (T) result;                      
484                         } catch (AdaptException e2) {
485                                 throw new ReferenceException(e2);                               
486                         } catch (AdapterConstructionException e) {
487                                 throw new ReferenceException(e);                                
488                         }                       
489                 } else if (reference instanceof KeyReference) {
490                         KeyReference ref = (KeyReference) reference;
491                         Accessor result = getValueAccessor(ref.key.getBinding(), ref.key.getValue());
492                         if (reference.getChildReference() != null)
493                                 result = result.getComponent(reference.getChildReference());
494                         return (T) result;                      
495                 } 
496                 throw new ReferenceException(reference.getClass().getName()+" is not a reference of a map");    
497         }
498         
499         @Override
500         public int size() throws AccessorException {
501                 readLock();
502                 try {
503                         return getBinding().size(object);
504                 } catch (BindingException e) {
505                         throw new AccessorException(e);
506                 } finally {
507                         readUnlock();
508                 }
509         }
510
511         @Override
512         public boolean containsKey(Binding keyBinding, Object key)
513                         throws AccessorException {
514                 readLock();
515                 try {
516                         MapBinding mb = getBinding();
517                         Binding lkb = getKeyBinding();
518                         Binding rkb = keyBinding;
519                         Object rk = key;
520                         Object lk = adapt(rk, rkb, lkb);
521                         return mb.containsKey(object, lk);
522                 } catch (AdaptException e) {
523                         throw new AccessorException(e);
524                 } catch (BindingException e) {
525                         throw new AccessorException(e);
526                 } catch (AdapterConstructionException e) {
527                         throw new AccessorException(e);
528                 } finally {
529                         readUnlock();
530                 }
531         }
532
533         @Override
534         public boolean containsValue(Binding valueBinding, Object value)
535                         throws AccessorException {
536                 readLock();
537                 try {
538                         MapBinding mb = getBinding();
539                         Binding lvb = getValueBinding();
540                         Binding rvb = valueBinding;
541                         Object rv = value;
542                         Object lv = adapt(rv, rvb, lvb);
543                         return mb.containsValue(object, lv);
544                 } catch (AdaptException e) {
545                         throw new AccessorException(e);
546                 } catch (BindingException e) {
547                         throw new AccessorException(e);
548                 } catch (AdapterConstructionException e) {
549                         throw new AccessorException(e);
550                 } finally {
551                         readUnlock();
552                 }
553         }
554
555         @Override
556         public Object get(Binding keyBinding, Object key, Binding valueBinding)
557                         throws AccessorException {
558                 readLock();
559                 try {
560                         MapBinding mb = getBinding();
561                         Binding lkb = getKeyBinding();
562                         Binding rkb = keyBinding;
563                         Binding lvb = getValueBinding();
564                         Binding rvb = valueBinding;
565                         Object rk = key;
566                         Object lk = adapt(rk, rkb, lkb);
567                         Object lv = mb.get(object, lk);
568                         if (lv == null) return null;
569                         Object rv = adapt(lv, lvb, rvb);
570                         return rv;
571                 } catch (AdaptException e) {
572                         throw new AccessorException(e);
573                 } catch (BindingException e) {
574                         throw new AccessorException(e);
575                 } catch (AdapterConstructionException e) {
576                         throw new AccessorException(e);
577                 } finally {
578                         readUnlock();
579                 }
580         }
581         
582         @Override
583         public int count(Binding keyBinding, Object from,
584                         boolean fromInclusive, Object end, boolean endInclusive)
585                         throws AccessorException {
586                 readLock();
587                 try {
588                         MapBinding mb = getBinding();
589                         Object lf = params.adapterScheme.adapt(from, keyBinding, getKeyBinding());
590                         Object le = params.adapterScheme.adapt(end, keyBinding, getKeyBinding());
591                         return mb.count(object, lf, fromInclusive, le, endInclusive);                   
592                 } catch (BindingException e) {
593                         throw new AccessorException(e);
594                 } catch (AdaptException e) {
595                         throw new AccessorException(e);
596                 } finally {
597                         readUnlock();
598                 }               
599         }
600
601         
602         @Override
603         public int getEntries(Binding keyBinding, Object from, boolean fromInclusive, Object end, boolean endInclusive, ArrayBinding keyArrayBinding, Object keysArray, ArrayBinding valueArrayBinding, Object valueArray, int limit) throws AccessorException {
604                 readLock();
605                 try {
606                         MapBinding mb = getBinding();
607                         Object lfrom = params.adapterScheme.adapt(from, keyBinding, getKeyBinding());
608                         Object lend = params.adapterScheme.adapt(end, keyBinding, getKeyBinding());
609
610                         return mb.getEntries(object, lfrom, fromInclusive, lend, endInclusive, keyArrayBinding, keysArray, valueArrayBinding, valueArray, limit);
611                 } catch (BindingException e) {
612                         throw new AccessorException(e);
613                 } catch (AdaptException e) {
614                         throw new AccessorException(e);
615                 } finally {
616                         readUnlock();
617                 }               
618         }
619                 
620
621         @Override
622         public void getAll(Binding keyBinding, Binding valueBinding, Map<Object, Object> to)
623                         throws AccessorException {
624                 readLock();
625                 try {
626                         MapBinding mb = getBinding();
627                         Adapter ka = params.adapterScheme.getAdapter(getKeyBinding(), keyBinding, true, false);
628                         Adapter va = params.adapterScheme.getAdapter(getValueBinding(), valueBinding, true, false);
629                         int length = mb.size(object);
630                         Object[] keys = new Object[ length ];
631                         Object[] values = new Object[ length ];
632                         mb.getAll(object, keys, values);
633                         
634                         for (int i=0; i<length; i++) {
635                                 Object lk = keys[i];
636                                 Object lv = values[i];
637                                 Object rk = ka.adapt( lk );
638                                 Object rv = va.adapt( lv );
639                                 to.put(rk, rv);
640                         }
641                 } catch (AdaptException e) {
642                         throw new AccessorException(e);
643                 } catch (AdapterConstructionException e) {
644                         throw new AccessorException(e);
645                 } catch (BindingException e) {
646                         throw new AccessorException(e);
647                 } finally {
648                         readUnlock();
649                 }
650         }
651
652         @Override
653         public void getAll(Binding keyBinding, Binding valueBinding, Object[] keys, Object[] values) throws AccessorException {
654                 readLock();
655                 try {
656                         int length = getBinding().size(object);
657                         getBinding().getAll(object, keys, values);
658                         // Convert elements
659                         Adapter ka = params.adapterScheme.getAdapter(getKeyBinding(), keyBinding, true, false);
660                         Adapter va = params.adapterScheme.getAdapter(getValueBinding(), valueBinding, true, false);                     
661                         for (int i=0; i<length; i++) {
662                                 keys[i] = ka.adapt( keys[i] );
663                                 values[i] = va.adapt( values[i] );
664                         }
665                 } catch (AdaptException e) {
666                         throw new AccessorException(e);
667                 } catch (AdapterConstructionException e) {
668                         throw new AccessorException(e);
669                 } catch (BindingException e) {
670                         throw new AccessorException(e);
671                 } finally {
672                         readUnlock();
673                 }
674         }
675
676         @Override
677         public Object[] getKeys(Binding keyBinding) throws AccessorException {
678                 readLock();
679                 try {
680                         Object[] result = getBinding().getKeys(object);                 
681                         // Convert elements
682                         Adapter adapter = params.adapterScheme.getAdapter(getKeyBinding(), keyBinding, true, false);                    
683                         for (int i=0; i<result.length; i++)
684                                 result[i] = adapter.adapt( result[i] );
685                         return result;
686                 } catch (AdaptException e) {
687                         throw new AccessorException(e);
688                 } catch (AdapterConstructionException e) {
689                         throw new AccessorException(e);
690                 } catch (BindingException e) {
691                         throw new AccessorException(e);
692                 } finally {
693                         readUnlock();
694                 }
695         }
696         
697         @Override
698         public Object[] getValues(Binding valueBinding) throws AccessorException {
699                 readLock();
700                 try {
701                         Object[] result = getBinding().getValues(object);                       
702                         // Convert elements
703                         Adapter adapter = params.adapterScheme.getAdapter(getValueBinding(), valueBinding, true, false);
704                         for (int i=0; i<result.length; i++)
705                                 result[i] = adapter.adapt( result[i] );
706                         return result;
707                 } catch (AdaptException e) {
708                         throw new AccessorException(e);
709                 } catch (AdapterConstructionException e) {
710                         throw new AccessorException(e);
711                 } catch (BindingException e) {
712                         throw new AccessorException(e);
713                 } finally {
714                         readUnlock();
715                 }
716         }
717
718         @Override
719         public Object getCeilingKey(Binding keyBinding, Object key) throws AccessorException {
720                 readLock();
721                 try {
722                         // Local & Requested Key Bindings
723                         Binding lkb = getKeyBinding();
724                         Binding rkb = keyBinding;
725                         Object rk = key;
726                         Object lk = adapt(rk, rkb, lkb);                        
727                         Object lck = getBinding().getCeilingKey(object, lk);
728                         if (lck==null) return null;
729                         Object rck = adapt(lck, lkb, rkb);
730                         return rck;
731                 } catch (AdaptException e) {
732                         throw new AccessorException( e );
733                 } catch (AdapterConstructionException e) {
734                         throw new AccessorException( e );
735                 } finally {
736                         readUnlock();
737                 }
738         }
739
740         @Override
741         public Object getFirstKey(Binding keyBinding) throws AccessorException {
742                 readLock();
743                 try {
744                         Binding lkb = getKeyBinding();
745                         Binding rkb = keyBinding;
746                         Object lfk = getBinding().getFirstKey(object);
747                         Object rfk = adapt(lfk, lkb, rkb);
748                         return rfk;
749                 } catch (AdaptException e) {
750                         throw new AccessorException( e );
751                 } catch (AdapterConstructionException e) {
752                         throw new AccessorException( e );
753                 } finally {
754                         readUnlock();
755                 }
756         }
757         
758         @Override
759         public Object getLastKey(Binding keyBinding) throws AccessorException {
760                 readLock();
761                 try {
762                         Binding lkb = getKeyBinding();
763                         Binding rkb = keyBinding;
764                         Object lfk = getBinding().getLastKey(object);
765                         Object rfk = adapt(lfk, lkb, rkb);
766                         return rfk;
767                 } catch (AdaptException e) {
768                         throw new AccessorException( e );
769                 } catch (AdapterConstructionException e) {
770                         throw new AccessorException( e );
771                 } finally {
772                         readUnlock();
773                 }
774         }
775
776         @Override
777         public Object getFloorKey(Binding keyBinding, Object key) throws AccessorException {
778                 readLock();
779                 try {
780                         // Local & Requested Key Bindings
781                         Binding lkb = getKeyBinding();
782                         Binding rkb = keyBinding;
783                         Object rk = key;
784                         Object lk = adapt(rk, rkb, lkb);                        
785                         Object lfk = getBinding().getFloorKey(object, lk);
786                         if (lfk==null) return null;
787                         Object rfk = adapt(lfk, lkb, rkb);
788                         return rfk;
789                 } catch (AdaptException e) {
790                         throw new AccessorException( e );
791                 } catch (AdapterConstructionException e) {
792                         throw new AccessorException( e );
793                 } finally {
794                         readUnlock();
795                 }
796         }
797
798         @Override
799         public Object getHigherKey(Binding keyBinding, Object key) throws AccessorException {
800                 readLock();
801                 try {
802                         // Local & Requested Key Bindings
803                         Binding lkb = getKeyBinding();
804                         Binding rkb = keyBinding;
805                         Object rk = key;
806                         Object lk = adapt(rk, rkb, lkb);                        
807                         Object lhk = getBinding().getHigherKey(object, lk);
808                         if (lhk==null) return null;
809                         Object rhk = adapt(lhk, lkb, rkb);
810                         return rhk;
811                 } catch (AdaptException e) {
812                         throw new AccessorException( e );
813                 } catch (AdapterConstructionException e) {
814                         throw new AccessorException( e );
815                 } finally {
816                         readUnlock();
817                 }
818         }
819
820         @Override
821         public Object getLowerKey(Binding keyBinding, Object key) throws AccessorException {
822                 readLock();
823                 try {
824                         // Local & Requested Key Bindings
825                         Binding lkb = getKeyBinding();
826                         Binding rkb = keyBinding;
827                         Object rk = key;
828                         Object lk = adapt(rk, rkb, lkb);                        
829                         Object llk = getBinding().getLowerKey(object, lk);
830                         if (llk==null) return null;
831                         Object rlk = adapt(llk, lkb, rkb);
832                         return rlk;
833                 } catch (AdaptException e) {
834                         throw new AccessorException( e );
835                 } catch (AdapterConstructionException e) {
836                         throw new AccessorException( e );
837                 } finally {
838                         readUnlock();
839                 }
840         }
841         
842         @Override
843         public void addListener(Listener listener, InterestSet interestSet,
844                         ChildReference path, Executor executor) throws AccessorException {
845                 super.addListener(listener, interestSet, path, executor);
846                 MapInterestSet is = (MapInterestSet) interestSet;
847                 
848                 Binding kb = getBinding().getKeyBinding();
849                 
850                 for (Object key : children.keySet()) {
851                         JavaObject sa = getExistingAccessor(key);
852                         if (sa==null) continue;
853                         
854                         MutableVariant vkey = new MutableVariant(kb, key);
855                         InterestSet cis = is.getComponentInterest();
856                         if (cis!=null) {
857                                 ChildReference childPath = ChildReference.concatenate( path, new KeyReference(vkey) );
858                                 sa.addListener(listener, cis, childPath, executor);                             
859                         }
860                         cis = is.getComponentInterest( vkey );
861                         if (cis!=null) {
862                                 ChildReference childPath = ChildReference.concatenate( path, new KeyReference(vkey) );
863                                 sa.addListener(listener, cis, childPath, executor);                             
864                         }
865                 }
866         }               
867         
868         @Override
869         public void removeListener(Listener listener) throws AccessorException {
870                 ListenerEntry e = detachListener(listener);
871                 if (e==null) return;
872                 MapInterestSet is = (MapInterestSet) e.interestSet;
873                 
874                 Binding kb = getBinding().getKeyBinding();              
875                 for (Entry<Object, SoftReference<JavaObject>> entry : children.entrySet()) {
876                         JavaObject sa = entry.getValue().get();
877                         if (sa==null) continue;
878                         Object key = entry.getKey();
879                         
880                         MutableVariant vkey = new MutableVariant(kb, key);
881                         InterestSet cis = is.getComponentInterest();
882                         if (cis!=null) {
883                                 sa.removeListener(listener);                            
884                         }
885                         cis = is.getComponentInterest( vkey );
886                         if (cis!=null) {
887                                 sa.removeListener(listener);                            
888                         }
889                 }
890                 
891         }
892
893         @Override
894         Event applyLocal(Event e, boolean makeRollback) throws AccessorException {
895                 Event rollback = null;
896                 
897                 if (e instanceof ValueAssigned) {
898                         ValueAssigned va = (ValueAssigned) e;
899                         if (makeRollback) rollback = new ValueAssigned(getBinding(), getValue(getBinding())); 
900                         setValue(va.newValue.getBinding(), va.newValue.getValue());
901                         return rollback;
902                 } else if (e instanceof MapEntryAdded) {
903                         MapEntryAdded ea = (MapEntryAdded) e;
904                         if (ea.key==null) throw new AccessorException("Cannot apply entry added event because key is missing");
905                         if (ea.value==null) throw new AccessorException("Cannot apply entry added event because value is missing");
906                         boolean hadValue = containsKey(ea.key.getBinding(), ea.key.getValue());
907                         if (hadValue) throw new AccessorException("Could not add entry to key that already existed");
908                         
909                         if (makeRollback) {                             
910                                 rollback = new MapEntryRemoved( ea.key );
911                         }
912                         
913                         put(ea.key.getBinding(), ea.key.getValue(), ea.value.getBinding(), ea.value.getValue());
914                         
915                 } else if (e instanceof MapEntryRemoved) {
916                         MapEntryRemoved er = (MapEntryRemoved) e;
917                         
918                         if (makeRollback) {
919                                 boolean hadValue = containsKey(er.key.getBinding(), er.key.getValue());
920                                 
921                                 if (hadValue) {                         
922                                         Object oldValueObj = get(er.key.getBinding(), er.key.getValue(), getBinding().getValueBinding());
923                                         MutableVariant oldKey = er.key;
924                                         MutableVariant oldValue = new MutableVariant(getBinding().getValueBinding(), oldValueObj);
925                                         rollback = new MapEntryAdded(oldKey, oldValue);
926                                 } else {
927                                         rollback = new MapEntryRemoved( er.key.clone() );
928                                 }
929                         }
930                         
931                         remove( er.key.getBinding(), er.key.getValue() );
932                         
933                 } else throw new AccessorException("Cannot apply "+e.getClass().getName()+" to Map Type");
934                 
935                 return rollback;
936         }
937
938 }
939