]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.databoard/src/org/simantics/databoard/accessor/java/JavaArray.java
Fixed all line endings of the repository
[simantics/platform.git] / bundles / org.simantics.databoard / src / org / simantics / databoard / accessor / java / JavaArray.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.io.File;
15 import java.lang.ref.SoftReference;
16 import java.util.Collection;
17 import java.util.HashMap;
18 import java.util.Map;
19 import java.util.Map.Entry;
20 import java.util.SortedMap;
21 import java.util.TreeMap;
22 import java.util.concurrent.Executor;
23
24 import org.simantics.databoard.accessor.Accessor;
25 import org.simantics.databoard.accessor.ArrayAccessor;
26 import org.simantics.databoard.accessor.StreamAccessor;
27 import org.simantics.databoard.accessor.error.AccessorConstructionException;
28 import org.simantics.databoard.accessor.error.AccessorException;
29 import org.simantics.databoard.accessor.error.ReferenceException;
30 import org.simantics.databoard.accessor.event.ArrayElementAdded;
31 import org.simantics.databoard.accessor.event.ArrayElementRemoved;
32 import org.simantics.databoard.accessor.event.Event;
33 import org.simantics.databoard.accessor.event.ValueAssigned;
34 import org.simantics.databoard.accessor.impl.AccessorParams;
35 import org.simantics.databoard.accessor.impl.ListenerEntry;
36 import org.simantics.databoard.accessor.interestset.ArrayInterestSet;
37 import org.simantics.databoard.accessor.interestset.InterestSet;
38 import org.simantics.databoard.accessor.reference.ChildReference;
39 import org.simantics.databoard.accessor.reference.IndexReference;
40 import org.simantics.databoard.accessor.reference.LabelReference;
41 import org.simantics.databoard.adapter.AdaptException;
42 import org.simantics.databoard.adapter.Adapter;
43 import org.simantics.databoard.adapter.AdapterConstructionException;
44 import org.simantics.databoard.binding.ArrayBinding;
45 import org.simantics.databoard.binding.Binding;
46 import org.simantics.databoard.binding.error.BindingException;
47 import org.simantics.databoard.binding.mutable.MutableVariant;
48 import org.simantics.databoard.type.ArrayType;
49
50 public class JavaArray extends JavaObject implements ArrayAccessor, StreamAccessor {
51
52         /** Accessors to children */
53         TreeMap<Integer, SoftReference<JavaObject>> children = new TreeMap<Integer, SoftReference<JavaObject>>(); 
54         
55         public JavaArray(Accessor parent, ArrayBinding binding, Object object, AccessorParams params) {
56                 super(parent, binding, object, params);
57         }
58         
59         @Override
60         public ArrayBinding getBinding() {
61                 return (ArrayBinding) binding;
62         }
63
64         @Override
65         public ArrayType type() {
66                 return (ArrayType) getBinding().type();
67         }               
68
69         @Override
70         public void add(Binding binding, Object value) throws AccessorException {
71                 add(size(), binding, value);
72         }
73
74         @Override
75         public void addAll(Binding binding, Object[] values) throws AccessorException
76         {
77                 addAll(size(), binding, values);
78         }
79         
80         @Override
81         public void add(int index, Binding binding, Object value) throws AccessorException {            
82                 writeLock();
83                 try {
84                         boolean lastEntry = index==size();
85                         // Write
86                         Binding rcb = binding;
87                         Binding lcb = getBinding().getComponentBinding();
88                         Object rcv = value;
89                         Object lcv = params.adapterScheme.clone(rcv, rcb, lcb);
90                         getBinding().add(object, index, lcv);
91                         
92                         //  Update child map keys
93                         if (!lastEntry && !children.isEmpty()) {
94                                 Integer key = children.lastKey();
95                                 while (key != null && key >= index) {
96                                         SoftReference<JavaObject> v = children.remove(key);
97                                         if (v.get()!=null) children.put(key+1, v);
98                                         key = children.lowerKey(key);
99                                 }
100                         }                       
101                         
102                         // Notify Listeners
103                         ListenerEntry le = listeners;
104                         while (le!=null) {                              
105                                 ArrayInterestSet is = le.getInterestSet();
106                                 if (is.inNotifications()) {
107                                         MutableVariant newValue = null;
108                                         if (is.inValues()) newValue = new MutableVariant(lcb, lcb.isImmutable() ? lcv : lcb.clone(lcv));                                        
109                                         ArrayElementAdded e = new ArrayElementAdded(index, newValue);
110                                         emitEvent(le, e);
111                                 }
112                                 
113                                 // Update indices of interest sets
114                                 if (is.componentInterests!=null) {
115                                         Map<Integer, InterestSet> oldCis = is.componentInterests;
116                                         boolean needUpdates = false;
117                                         for (Integer i : oldCis.keySet()) {
118                                                 needUpdates |= i>=index;
119                                                 if (needUpdates) break;
120                                         }
121                                         
122                                         if (needUpdates) {
123                                                 Map<Integer, InterestSet> newCis = new HashMap<Integer, InterestSet>(oldCis.size()); 
124                                                 for (Integer i : oldCis.keySet())
125                                                 {
126                                                         Integer oldKey = i;
127                                                         Integer newKey = i>=index ? i+1 : i;
128                                                         InterestSet oldValue = oldCis.get(oldKey);
129                                                         newCis.put(newKey, oldValue); 
130                                                 }
131                                                 is.componentInterests = newCis;
132                                         }
133                                 }
134
135                                 /*
136                                 boolean hadSa = getExistingAccessor(index) != null;
137                                 
138                                 if (!hadSa) {
139                                         // Add component interest listener
140                                         InterestSet cis = is.getComponentInterest(); 
141                                         if (cis != null) {
142                                                 Accessor sa = getAccessor(index);
143                                         }                               
144                                         cis = is.getComponentInterest(index); 
145                                         if (cis != null) {
146                                                 Accessor sa = getAccessor(index);
147                                         }
148                                 }
149                                 */
150                                 
151                                 le = le.next;
152                         }                       
153                         
154                 } catch (IndexOutOfBoundsException e) {
155                         throw new AccessorException(e);
156                 } catch (BindingException e) {
157                         throw new AccessorException(e);
158                 } catch (AdaptException e) {
159                         throw new AccessorException(e);
160 //              } catch (AccessorConstructionException e) {
161 //                      throw new AccessorException(e);
162                 } finally {
163                         writeUnlock();
164                 }
165                 
166         }
167
168         @Override
169         public void addAll(int index, Binding binding, Object[] values)
170         throws AccessorException {
171                 writeLock();
172                 try {
173                         int oldCount = size();
174                         int count = values.length;
175                         Binding rcb = binding;
176                         Binding lcb = getBinding().getComponentBinding();
177                         boolean lastEntry = index == oldCount;
178                         
179                         // Write All
180                         for (int i=0; i<values.length; i++) {
181                                 Object rcv = values[i];
182                                 Object lcv = params.adapterScheme.clone(rcv, rcb, lcb);                         
183                                 getBinding().add(object, i+index, lcv);                         
184                         }
185                         
186                         //  Update child map keys
187                         if (!lastEntry && !children.isEmpty()) {
188                                 Integer key = children.lastKey();
189                                 while (key != null && key >= index) {
190                                         SoftReference<JavaObject> value = children.remove(key);
191                                         if (value.get()!=null) children.put(key+values.length, value);
192                                         key = children.lowerKey(key);
193                                 }
194                         }
195                         
196                         // Update indices of interest sets      
197                         {
198                                 ListenerEntry le = listeners;
199                                 while (le!=null) {                              
200                                         ArrayInterestSet is = le.getInterestSet();
201                                         if (is.componentInterests!=null) {
202                                                 Map<Integer, InterestSet> oldCis = is.componentInterests;
203                                                 boolean needUpdates = false;
204                                                 for (Integer i : oldCis.keySet()) {
205                                                         needUpdates |= i>=index;
206                                                         if (needUpdates) break;
207                                                 }
208                                                 
209                                                 if (needUpdates) {
210                                                         Map<Integer, InterestSet> newCis = new HashMap<Integer, InterestSet>(oldCis.size()); 
211                                                         for (Integer i : oldCis.keySet())
212                                                         {
213                                                                 Integer oldKey = i;
214                                                                 Integer newKey = i>=index ? i+count : i;
215                                                                 InterestSet oldValue = oldCis.get(oldKey);
216                                                                 newCis.put(newKey, oldValue); 
217                                                         }
218                                                         is.componentInterests = newCis;
219                                                 }
220                                         }
221                                         
222                                         // Add component interest listener
223                                         /*
224                                         for (int i = index; i<index+values.length; i++) {
225                                                 
226                                                 boolean hadSa = getExistingAccessor(i)!=null;
227                                                 if (hadSa) continue; 
228                                                 
229                                                 InterestSet cis = is.getComponentInterest(); 
230                                                 if (cis != null) {
231                                                         Accessor sa = getAccessor(i);
232                                                 }                               
233                                                 cis = is.getComponentInterest(index); 
234                                                 if (cis != null) {
235                                                         Accessor sa = getAccessor(i);
236                                                 }
237                                         }*/                             
238                                         
239                                         le = le.next;
240                                 }               
241                         }
242
243                         // Notify Listeners
244                         if (listeners!=null) {
245                                 for (int i=0; i<values.length; i++) {
246                                         Object lcv = getBinding().get(object, i+index);
247                                         ListenerEntry le = listeners;                           
248                                         while (le!=null) {                              
249                                                 ArrayInterestSet is = le.getInterestSet();
250                                                 if (is.inNotifications()) {
251                                                         MutableVariant newValue = null;
252                                                         if (is.inValues()) newValue = new MutableVariant(lcb, lcb.isImmutable() ? lcv : lcb.clone(lcv));                                        
253                                                         ArrayElementAdded e = new ArrayElementAdded(i+index, newValue);
254                                                         emitEvent(le, e);
255                                                 }
256                                         }
257                                 }
258                         }
259                                                                         
260                         
261                 } catch (IndexOutOfBoundsException e) {
262                         throw new AccessorException(e);
263                 } catch (BindingException e) {
264                         throw new AccessorException(e);
265                 } catch (AdaptException e) {
266                         throw new AccessorException(e);
267 //              } catch (AccessorConstructionException e) {
268 //                      throw new AccessorException(e);
269                 } finally {
270                         writeUnlock();
271                 }
272         }
273
274         @SuppressWarnings("unchecked")
275         @Override
276         public <T extends Accessor> T getComponent(ChildReference reference)
277                         throws AccessorConstructionException {
278                 if (reference==null) return (T) this;
279                 if (reference instanceof LabelReference) {
280                         LabelReference lr = (LabelReference) reference;
281                         try {
282                                 Integer index = new Integer( lr.label );
283                                 Accessor result = getAccessor(index);
284                                 if (reference.getChildReference() != null)
285                                         result = result.getComponent(reference.getChildReference());
286                                 return (T) result;
287                         } catch ( NumberFormatException nfe ) {
288                                 throw new ReferenceException(nfe);
289                         }                       
290                 } else if (reference instanceof IndexReference) {
291                         IndexReference ref = (IndexReference) reference;
292                         int index = ref.getIndex();
293                         Accessor result = getAccessor(index);
294                         if (reference.getChildReference() != null)
295                                 result = result.getComponent(reference.getChildReference());
296                         return (T) result;
297                 } throw new ReferenceException(reference.getClass().getName()+" is not a reference of an array");       
298         }
299         
300         @SuppressWarnings("unchecked")
301         @Override
302         public <T extends Accessor> T getAccessor(int index) throws AccessorConstructionException {
303                 try {
304                         int size = getBinding().size(object);
305                         if (index<0 || index>=size) throw new ReferenceException("Element index ("+index+") out of bounds ("+size+")");
306                         
307                         // Get existing or create new
308                         JavaObject sa = getExistingAccessor(index);
309                         if (sa==null) {
310                                 readLock();
311                                 try {
312                                         // Instantiate new accessor
313                                         Binding cb = getBinding().getComponentBinding();
314                                         Object cv = getBinding().get(object, index);
315         
316                                         // Instantiate correct sub accessor. 
317                                         sa = createSubAccessor(this, cb, cv, params);
318                                         sa.keyInParent = index;
319                                         children.put(index, new SoftReference<JavaObject>(sa) );
320         
321                                         // Add component interest sets
322                                         ListenerEntry le = listeners;
323                                         while (le!=null) {                              
324                                                 ArrayInterestSet is = le.getInterestSet();
325         
326                                                 // Generic element interest
327                                                 InterestSet gis = is.getComponentInterest(); 
328                                                 if (gis != null) {
329                                                         try {
330                                                                 ChildReference childPath = ChildReference.concatenate(le.path, new IndexReference(index) );
331                                                                 sa.addListener(le.listener, gis, childPath, le.executor);
332                                                         } catch (AccessorException e) {
333                                                                 throw new AccessorConstructionException(e);
334                                                         }
335                                                 }
336                                                 
337                                                 // Specific element interest
338                                                 InterestSet cis = is.getComponentInterest(index); 
339                                                 if (cis != null) {
340                                                         try {
341                                                                 ChildReference childPath = ChildReference.concatenate(le.path, new IndexReference(index) );
342                                                                 sa.addListener(le.listener, cis, childPath, le.executor);
343                                                         } catch (AccessorException e) {
344                                                                 throw new AccessorConstructionException(e);
345                                                         }
346                                                 }
347                                                 
348                                                 // Next listener
349                                                 le = le.next;
350                                         }
351                                 } finally {
352                                         readUnlock();
353                                 }                               
354                         }
355                         
356                         return (T) sa;
357                 } catch (BindingException e) {
358                         throw new AccessorConstructionException(e);
359                 }
360         }
361         
362         /**
363          * Get existing sub accessor
364          * @param index
365          * @return sub-accessor or <code>null</code>
366          */
367         JavaObject getExistingAccessor(int index)
368         {               
369                 SoftReference<JavaObject> ref = children.get(index);
370                 if (ref==null) return null;
371                 JavaObject res = (JavaObject) ref.get();
372 //              if (res==null) children.remove(index);
373                 return res;
374         }       
375
376         @Override
377         public void getAll(Binding valueBinding, Collection<Object> values)
378                         throws AccessorException {
379                 readLock();
380                 try {
381                         Adapter adapter = params.adapterScheme.getAdapter(getBinding().getComponentBinding(), valueBinding, true, true);
382                         for (int i=0; i<size(); i++) {
383                                 Object o = getBinding().get(object, i);
384                                 values.add( adapter.adapt(o) );
385                         }
386                 } catch (AdapterConstructionException e) {
387                         throw new AccessorException(e);
388                 } catch (AdaptException e) {
389                         throw new AccessorException(e);
390                 } catch (IndexOutOfBoundsException e) {
391                         throw new AccessorException(e);
392                 } catch (BindingException e) {
393                         throw new AccessorException(e);
394                 } finally {
395                         readUnlock();
396                 }
397         }
398
399         @Override
400         public void getAll(Binding valueBinding, Object[] array) throws AccessorException {
401                 readLock();
402                 try {
403                         Adapter adapter = params.adapterScheme.getAdapter(getBinding().getComponentBinding(), valueBinding, true, true);
404                         for (int i=0; i<size(); i++) {
405                                 Object o = getBinding().get(object, i);
406                                 array[i] = adapter.adapt(o);                            
407                         }
408                 } catch (BindingException e) {
409                         throw new AccessorException(e);
410                 } catch (AdaptException e) {
411                         throw new AccessorException(e);
412                 } catch (AdapterConstructionException e) {
413                         throw new AccessorException(e);
414                 } finally {
415                         readUnlock();
416                 }
417         }       
418         
419         @Override
420         public Object get(int index, Binding valueBinding)
421                         throws AccessorException {
422                 readLock();
423                 try {
424                         Adapter adapter = params.adapterScheme.getAdapter(getBinding().getComponentBinding(), valueBinding, true, true);
425                         Object o = getBinding().get(object, index);
426                         o = adapter.adapt(o);
427                         return o;
428                 } catch (BindingException e) {
429                         throw new AccessorException(e);
430                 } catch (AdaptException e) {
431                         throw new AccessorException(e);
432                 } catch (AdapterConstructionException e) {
433                         throw new AccessorException(e);
434                 } finally {
435                         readUnlock();
436                 }
437         }
438         
439         @Override
440         public void get(int index, Binding valueBinding, Object dst)
441                         throws AccessorException {
442                 readLock();
443                 try {                   
444                         Binding scb = getBinding().getComponentBinding();
445                         Object sv = getBinding().get(object, index);
446                         valueBinding.readFrom(scb, sv, dst);
447                 } catch (BindingException e) {
448                         throw new AccessorException(e);
449                 } finally {
450                         readUnlock();
451                 }
452         }       
453
454         @Override
455         public void remove(int index, int count) throws AccessorException {             
456                 if (index<0 || index+count>size()) throw new AccessorException("Index out of bounds");
457                 
458                 writeLock();
459                 try {           
460                         boolean lastEntry = index==size()-count;
461                         
462                         // Write
463                         getBinding().remove(object, index, count);
464                         
465                         // Disconnect sub-accessor
466                         JavaObject sa = getExistingAccessor(index);
467                         // Notify about disconnection of sub-accessor
468                         if (sa!=null) {
469                                 sa.invalidatedNotification();
470                                 children.remove(index);
471                                 sa = null;
472                         }       
473                         
474                         // Remove children
475                         SortedMap<Integer, SoftReference<JavaObject>> sm = children.subMap(index, true, index+count, false);
476                         for (Entry<Integer, SoftReference<JavaObject>> e : sm.entrySet()) {
477                             JavaObject bo = e.getValue().get();
478                             if (bo==null) continue;
479                             bo.invalidatedNotification();                           
480                         }
481                         sm.clear();
482                         
483                         //  Update the keys of consecutive children
484                         if (!lastEntry && !children.isEmpty()) {
485                                 Integer lastKey = children.lastKey();
486                                 Integer key = children.higherKey(index);
487                                 while (key != null && key <= lastKey) {
488                                         SoftReference<JavaObject> value = children.remove(key);
489                                         if (value.get()!=null) children.put(key-count, value);
490                                         key = children.higherKey(key);
491                                 }
492                         }               
493                         
494                         // Notify Listeners
495                         ListenerEntry le = listeners;
496                         while (le!=null) {                              
497                                 ArrayInterestSet is = le.getInterestSet();
498                                 if (is.inNotifications()) {
499                                         for (int i=0; i<count; i++) {
500                                                 ArrayElementRemoved e = new ArrayElementRemoved(index);
501                                                 emitEvent(le, e);
502                                         }
503                                 }
504                         
505                                 // Update indices of interest sets
506                                 if (is.componentInterests!=null) {
507                                         Map<Integer, InterestSet> oldCis = is.componentInterests;
508                                         boolean needUpdates = false;
509                                         for (Integer interestIndex : oldCis.keySet()) {
510                                                 needUpdates |= interestIndex>=index;
511                                                 if (needUpdates) break;
512                                         }
513                                         
514                                         if (needUpdates) {
515                                                 Map<Integer, InterestSet> newCis = new HashMap<Integer, InterestSet>(oldCis.size()); 
516                                                 for (Integer interestIndex : oldCis.keySet())
517                                                 {
518                                                         // The component interest is removed
519                                                         if (interestIndex>=index && interestIndex<index+count) continue;
520                                                                                                                         
521                                                         Integer oldKey = interestIndex;
522                                                         Integer newKey = interestIndex>=index ? interestIndex+count : interestIndex;
523                                                         InterestSet oldValue = oldCis.get(oldKey);
524                                                         newCis.put(newKey, oldValue); 
525                                                 }
526                                                 is.componentInterests = newCis;
527                                         }
528                                 }
529                                 
530                                 le = le.next;
531                         }               
532                         
533                         
534                 } catch (IndexOutOfBoundsException e) {
535                         throw new AccessorException(e);
536                 } catch (BindingException e) {
537                         throw new AccessorException(e);
538                 } finally {
539                         writeUnlock();
540                 }
541                 
542         }
543
544         @Override
545         public void set(int index, Binding binding, Object value)
546                         throws AccessorException {
547                 if (index<0 || index>=size()) throw new AccessorException("Index out of bounds");
548                 writeLock();
549                 try {           
550                         JavaObject sa = getExistingAccessor(index);
551                         
552                         // Create sub-accessor, if there is an interest
553                         /*
554                         if (sa==null) {
555                                 ListenerEntry le = listeners;
556                                 while (le!=null) {                              
557                                         // Update indices of interest sets
558                                         ArrayInterestSet is = le.getInterestSet();
559                                         if (is.getComponentInterest()!=null || is.getComponentInterest(index)!=null) {
560                                                 sa = (JavaObject) getAccessor(index);
561                                                 break;
562                                         }
563                                         le = le.next;
564                                 }
565                         }*/
566         
567                         // Write with sub-accessor
568                         if (sa!=null) {
569                                 sa.setValue(binding, value);
570                                 return;                 
571                         }               
572                 
573                         // Write value
574                         Binding lcb = getBinding().getComponentBinding();
575                         Binding rcb = binding;
576                         Object rcv = value;
577                         Object lcv = params.adapterScheme.clone(rcv, rcb, lcb);
578                         getBinding().set(object, index, lcv);
579                         
580                         // Notify Listeners                     
581                         ListenerEntry le = listeners;
582                         while (le!=null) {                              
583                                 ArrayInterestSet is = le.getInterestSet();
584                                 if (is.inNotificationsOf(index)) {
585                                         MutableVariant newValue = null;
586                                         if (is.inValues()) newValue = new MutableVariant(lcb, lcb.isImmutable() ? lcv : lcb.clone(lcv));                                        
587                                         Event e = new ValueAssigned(new IndexReference(index), newValue);
588                                         emitEvent(le, e);
589                                 }
590                                 le = le.next;
591                         }                       
592                                                 
593                 } catch (AdaptException e) {
594                         throw new AccessorException(e);
595                 } catch (BindingException e) {
596                         throw new AccessorException(e);
597 //              } catch (AccessorConstructionException e) {
598 //                      throw new AccessorException(e);
599                 } finally {
600                         writeUnlock();
601                 }
602         }
603
604         @Override
605         public void setValue(Binding arrayBinding, Object newArray)
606                         throws AccessorException {
607                 writeLock();
608                 try {
609                         // Replace all elements
610                         ArrayBinding ab = ((ArrayBinding)arrayBinding);
611                         int newLength = ab.size(newArray);
612                         int oldLength = size();
613                         
614                         // 1. Set
615                         int commonLength = Math.min(newLength, oldLength);
616                         Binding cb = ab.getComponentBinding();
617                         for (int i=0; i<commonLength; i++) {
618                                 Object elementValue = ab.get(newArray, i);
619                                 set(i, cb, elementValue); 
620                         }
621                         
622                         // 2. Add
623                         if (newLength>oldLength) {
624                                 for (int i=oldLength; i<newLength; i++) {
625                                         Object elementValue = ab.get(newArray, i);
626                                         add(cb, elementValue);
627                                 }
628                         } 
629                         
630                         // 3. Remove
631                         else if (newLength<oldLength) {
632                                 remove(newLength, oldLength-newLength);
633                         }
634                         
635                 } catch (BindingException e) {
636                         throw new AccessorException(e);
637                 } finally {
638                         writeUnlock();
639                 }
640         }
641         
642         @Override
643         public void setSize(int newSize) throws AccessorException {
644                 if (newSize<0) throw new AccessorException("Index out of bounds");
645                 
646                 writeLock();
647                 try {
648                         int oldSize = getBinding().size(object);
649         
650                         // Add dummy instances
651                         if (newSize>oldSize) {
652                                 Binding c = getBinding().getComponentBinding();
653                                 int count = newSize-oldSize;
654                                 Object[] arr = new Object[count];
655                                 for (int i=0; i<count; i++) arr[i] = c.createDefault();
656                                 addAll(oldSize, c, arr);
657                         }
658                         
659                         // Remove instances  
660                         if (newSize<oldSize) {
661                                 remove(newSize, oldSize-newSize);
662                         }
663                 
664                 } catch (BindingException e) {
665                         throw new AccessorException( e );
666                 } finally {
667                         writeUnlock();
668                 }
669                 
670         }
671         
672         @Override
673         public int size() throws AccessorException {    
674                 readLock();
675                 try {
676                         return getBinding().size(object);
677                 } catch (BindingException e) {
678                         throw new AccessorException(e);
679                 } finally {
680                         readUnlock();
681                 }
682         }
683
684
685         @Override
686         public void addListener(Listener listener, InterestSet interestSet,
687                         ChildReference path, Executor executor) throws AccessorException {
688                 super.addListener(listener, interestSet, path, executor);
689                 ArrayInterestSet is = (ArrayInterestSet) interestSet;
690                 
691                 for (Integer index : children.keySet()) {
692                         JavaObject sa = getExistingAccessor(index);
693                         if (sa==null) continue;
694                         InterestSet cis = is.getComponentInterest();
695                         if (cis!=null) {
696                                 ChildReference childPath = ChildReference.concatenate( path, new IndexReference(index) );
697                                 sa.addListener(listener, cis, childPath, executor);                             
698                         }
699                         cis = is.getComponentInterest(index);
700                         if (cis!=null) {
701                                 ChildReference childPath = ChildReference.concatenate( path, new IndexReference(index) );
702                                 sa.addListener(listener, cis, childPath, executor);                             
703                         }
704                 }
705         }       
706         
707         @Override
708         public void removeListener(Listener listener) throws AccessorException {
709                 ListenerEntry e = detachListener(listener);
710                 if (e==null) return;
711                 ArrayInterestSet is = (ArrayInterestSet) e.interestSet;
712                 
713                 for (Integer index : children.keySet()) {
714                         JavaObject sa = getExistingAccessor(index);
715                         if (sa==null) continue;
716                         InterestSet cis = is.getComponentInterest();
717                         if (cis!=null) {
718                                 sa.removeListener(listener);
719                         }
720                         cis = is.getComponentInterest(index);
721                         if (cis!=null) {
722                                 sa.removeListener(listener);
723                         }                       
724                 }
725         }
726         
727         @Override
728         Event applyLocal(Event e, boolean makeRollback) throws AccessorException {
729                 try {
730                         Event rollback = null;
731                         if (e instanceof ValueAssigned) {
732                                 ValueAssigned va = (ValueAssigned) e;
733                                 if (makeRollback) rollback = new ValueAssigned(getBinding(), getValue(getBinding())); 
734                                 setValue(va.newValue.getBinding(), va.newValue.getValue());
735                         } else
736                         if (e instanceof ArrayElementAdded) {
737                                 ArrayElementAdded aa = (ArrayElementAdded) e;
738                                 add(aa.index, aa.value.getBinding(), aa.value.getValue());
739                                 if (makeRollback) rollback = new ArrayElementRemoved(aa.index);
740                         } else if (e instanceof ArrayElementRemoved) {
741                                 ArrayElementRemoved ar = (ArrayElementRemoved) e;
742                                 if (ar.index<0 || ar.index >=size()) throw new AccessorException("Array index out of bounds");
743                                 if (makeRollback) {
744                                         Binding cb = getBinding().getComponentBinding();
745                                         Object cv = getBinding().get(object, ar.index);
746                                         if (!cb.isImmutable()) cv = cb.clone(cv);
747                                         rollback = new ArrayElementAdded(ar.index, new MutableVariant(cb, cv));
748                                 }
749                                 remove(ar.index, 1);
750                         } else {
751                                 throw new AccessorException("Cannot apply "+e.getClass().getName()+" to Array");
752                         }
753                         
754                         return rollback;
755                 } catch (BindingException be) {
756                         throw new AccessorException( be );
757                 } catch (AdaptException ae) {
758                         throw new AccessorException( ae );
759                 }
760         }
761
762         @Override
763         public void flush() throws AccessorException {
764         }
765
766         @Override
767         public void close() throws AccessorException {
768         }
769
770         @Override
771         public void reset() throws AccessorException {
772         }
773
774         @Override
775         public void addNoflush(Binding binding, Object value)
776                         throws AccessorException {
777                 add(binding, value);
778         }
779
780         @Override
781         public void addAllNoflush(Binding binding, Object[] values)
782                         throws AccessorException {
783                 addAll(binding, values);
784         }
785
786         @Override
787         public void addAllNoflush(int index, Binding binding, Object[] values)
788                         throws AccessorException {
789                 addAll(index, binding, values);
790         }
791
792         @Override
793         public void addNoflush(int index, Binding binding, Object value)
794                         throws AccessorException {
795                 add(index, binding, value);
796         }
797
798         @Override
799         public void setValueNoflush(Binding binding, Object newValue)
800                         throws AccessorException {
801                 setValue(binding, newValue);
802         }
803
804         @Override
805         public void setNoflush(int index, Binding binding, Object value) throws AccessorException {
806                 set(index, binding, value);
807         }
808
809         @Override
810         public void removeNoflush(int index, int count) throws AccessorException {
811                 remove(index, count);
812         }
813
814         @Override
815         public void setSizeNoflush(int newSize) throws AccessorException {
816                 setSize(newSize);
817         }
818
819         @Override
820         public File file() {
821                 return null;
822         }
823         
824
825 }
826