1 /*******************************************************************************
\r
2 * Copyright (c) 2010 Association for Decentralized Information Management in
\r
4 * All rights reserved. This program and the accompanying materials
\r
5 * are made available under the terms of the Eclipse Public License v1.0
\r
6 * which accompanies this distribution, and is available at
\r
7 * http://www.eclipse.org/legal/epl-v10.html
\r
10 * VTT Technical Research Centre of Finland - initial API and implementation
\r
11 *******************************************************************************/
\r
12 package org.simantics.databoard.accessor.java;
14 import java.lang.ref.SoftReference;
\r
15 import java.util.Map;
\r
16 import java.util.Map.Entry;
\r
17 import java.util.Set;
\r
18 import java.util.TreeMap;
\r
19 import java.util.TreeSet;
\r
20 import java.util.concurrent.Executor;
\r
22 import org.simantics.databoard.Bindings;
\r
23 import org.simantics.databoard.accessor.Accessor;
\r
24 import org.simantics.databoard.accessor.MapAccessor;
\r
25 import org.simantics.databoard.accessor.error.AccessorConstructionException;
\r
26 import org.simantics.databoard.accessor.error.AccessorException;
\r
27 import org.simantics.databoard.accessor.error.ReferenceException;
\r
28 import org.simantics.databoard.accessor.event.Event;
\r
29 import org.simantics.databoard.accessor.event.MapEntryAdded;
\r
30 import org.simantics.databoard.accessor.event.MapEntryRemoved;
\r
31 import org.simantics.databoard.accessor.event.ValueAssigned;
\r
32 import org.simantics.databoard.accessor.impl.AccessorParams;
\r
33 import org.simantics.databoard.accessor.impl.ListenerEntry;
\r
34 import org.simantics.databoard.accessor.interestset.InterestSet;
\r
35 import org.simantics.databoard.accessor.interestset.MapInterestSet;
\r
36 import org.simantics.databoard.accessor.reference.ChildReference;
\r
37 import org.simantics.databoard.accessor.reference.KeyReference;
\r
38 import org.simantics.databoard.accessor.reference.LabelReference;
\r
39 import org.simantics.databoard.adapter.AdaptException;
\r
40 import org.simantics.databoard.adapter.Adapter;
\r
41 import org.simantics.databoard.adapter.AdapterConstructionException;
\r
42 import org.simantics.databoard.binding.ArrayBinding;
\r
43 import org.simantics.databoard.binding.Binding;
\r
44 import org.simantics.databoard.binding.MapBinding;
\r
45 import org.simantics.databoard.binding.error.BindingException;
\r
46 import org.simantics.databoard.binding.mutable.MutableVariant;
\r
47 import org.simantics.databoard.type.MapType;
\r
49 public class JavaMap extends JavaObject implements MapAccessor {
51 /** Accessors to children */
52 TreeMap<Object, SoftReference<JavaObject>> children;
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());
60 public MapType type() {
61 return (MapType) binding.type();
65 public MapBinding getBinding() {
66 return (MapBinding) binding;
69 public Binding getKeyBinding() {
70 return getBinding().getKeyBinding();
73 public Binding getValueBinding() {
74 return getBinding().getValueBinding();
78 public void clear() throws AccessorException {
\r
81 if (getBinding().size(object)==0) return;
82 boolean hasListeners = listeners!=null;
83 Binding kb = getKeyBinding();
85 Object[] keys = hasListeners ? getBinding().getKeys(object) : null;
88 getBinding().clear(object);
90 // Disconnect sub-accessor
91 for (SoftReference<JavaObject> ref : children.values()) {
92 JavaObject sa = ref.get();
93 if (sa==null) continue;
94 sa.invalidatedNotification();
99 ListenerEntry le = listeners;
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);
113 } catch (BindingException e) {
114 throw new AccessorException( e );
121 * Remove element with local key
124 * @throws AccessorException
126 void removeLocal(Object lk) throws AccessorException {
\r
129 boolean hadValue = getBinding().containsKey(object, lk);
130 if (!hadValue) return;
133 getBinding().remove(object, lk);
135 // Disconnect sub-accessor
136 JavaObject sa = getExistingAccessor(lk);
137 // Notify about disconnection of sub-accessor
139 sa.invalidatedNotification();
144 if (listeners!=null) {
145 MutableVariant var = new MutableVariant(getKeyBinding(), lk);
146 ListenerEntry le = listeners;
148 MapInterestSet is = le.getInterestSet();
149 if (is.inNotificationsOf(var)) {
150 MapEntryRemoved e = new MapEntryRemoved(var);
158 } catch (BindingException e) {
159 throw new AccessorException( e );
165 void putLocal(Object lk, Object lv) throws AccessorException {
\r
168 JavaObject sa = getExistingAccessor(lk);
170 boolean hadOldValue = getBinding().containsKey(object, lk);
173 Binding kb = getKeyBinding();
174 Binding vb = getValueBinding();
176 // Compare to old value
179 oldLv = getBinding().get(object, lk);
180 // Compare to existing value
181 // boolean equal = vb.equals(oldLv, lv);
182 // if (equal) return;
186 getBinding().put(object, lk, lv);
189 MutableVariant kv = new MutableVariant(kb, lk);
192 if (listeners!=null) {
193 ListenerEntry le = listeners;
195 MapInterestSet is = le.getInterestSet();
196 if (is.inNotificationsOf(kv)) {
198 MutableVariant vv = null;
199 if (is.inValuesOf(kv)) vv = new MutableVariant(vb, vb.isImmutable() ? lv : vb.clone(lv));
202 // Notify about new assignment to old value
203 Event e = new ValueAssigned( new KeyReference(kv), vv);
206 // Notify about new entry
207 MapEntryAdded e = new MapEntryAdded(kv, vv);
216 // Recursive write using existing sub-accessor
217 sa.setValue(getValueBinding(), lv);
220 } catch (BindingException e) {
221 throw new AccessorException( e );
222 } catch (AdaptException e) {
223 throw new AccessorException( e );
230 public void put(Binding keyBinding, Object key, Binding valueBinding,
231 Object value) throws AccessorException {
\r
236 Adapter ka = params.adapterScheme.getAdapter(keyBinding, getKeyBinding(), true, false);
237 Adapter va = params.adapterScheme.getAdapter(valueBinding, getValueBinding(), true, false);
239 Object lk = ka.adapt( rk );
240 Object lv = va.adapt( rv );
242 } catch (AdapterConstructionException e) {
243 throw new AccessorException(e);
244 } catch (AdaptException e) {
245 throw new AccessorException(e);
253 public void putAll(Binding keyBinding, Binding valueBinding, Map<Object, Object> from)
254 throws AccessorException {
\r
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);
261 for (Object rk : from.keySet()) {
262 Object rv = from.get(rk);
263 Object lk = ka.adapt( rk );
264 Object lv = va.adapt( rv );
268 } catch (AdaptException e) {
269 throw new AccessorException( e );
270 } catch (AdapterConstructionException e) {
271 throw new AccessorException( e );
278 public void putAll(Binding keyBinding, Binding valueBinding, Object[] keys, Object[] values) throws AccessorException {
\r
281 // Convert keys and values
282 int rs = keys.length;
284 Adapter ka = params.adapterScheme.getAdapter(keyBinding, getKeyBinding(), true, false);
285 Adapter va = params.adapterScheme.getAdapter(valueBinding, getValueBinding(), true, false);
287 for (int i=0; i<rs; i++) {
288 Object lk = ka.adapt( keys[i] );
289 Object lv = va.adapt( values[i] );
294 } catch (AdaptException e) {
295 throw new AccessorException( e );
296 } catch (AdapterConstructionException e) {
297 throw new AccessorException( e );
304 public void remove(Binding keyBinding, Object key) throws AccessorException {
307 Object lk = adapt(rk, keyBinding, getKeyBinding());
309 } catch (AdaptException e) {
310 throw new AccessorException( e );
311 } catch (AdapterConstructionException e) {
\r
312 throw new AccessorException( e );
\r
317 public void setValue(Binding mapBinding, Object newMap)
318 throws AccessorException {
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);
326 Adapter ka = params.adapterScheme.getAdapter(mb.getKeyBinding(), getKeyBinding(), true, false);
327 Adapter va = params.adapterScheme.getAdapter(mb.getValueBinding(), getValueBinding(), true, false);
329 for (int i=0; i<newSize; i++) {
330 rks[i] = ka.adapt(rks[i]);
331 rvs[i] = va.adapt(rvs[i]);
334 setValueLocal(rks, rvs);
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 );
346 * Set new map with local keys and values
350 * @throws AccessorException
352 void setValueLocal(Object keys[], Object values[]) throws AccessorException {
\r
355 Set<Object> oldKeys = new TreeSet<Object>(getKeyBinding());
356 getBinding().getKeys(object, oldKeys);
359 for (int i=0; i<keys.length; i++) {
360 Object key = keys[i];
361 Object value = values[i];
362 putLocal(key, value);
367 for (Object key : oldKeys) {
371 } catch (BindingException e) {
372 throw new AccessorException( e );
379 @SuppressWarnings("unchecked")
381 public <T extends Accessor> T getValueAccessor(Binding keyBinding, Object key)
382 throws AccessorConstructionException {
385 Object lk = params.adapterScheme.getAdapter(keyBinding, getKeyBinding(), true, listeners!=null).adapt(rk);
387 boolean hasKey = getBinding().containsKey(object, lk);
389 throw new AccessorConstructionException("Map doesn't contain the requested element");
392 JavaObject sa = getExistingAccessor(lk);
393 if (sa!=null) return (T) sa;
\r
397 Binding vb = getBinding().getValueBinding();
398 Binding kb = getBinding().getKeyBinding();
399 Object lv = getBinding().get(object, lk);
400 MutableVariant kv = new MutableVariant(kb, lk);
402 // Instantiate correct sub accessor.
403 sa = createSubAccessor(this, vb, lv, params);
\r
405 children.put(lk, new SoftReference<JavaObject>(sa));
407 // Add component interest sets
408 ListenerEntry le = listeners;
410 MapInterestSet is = le.getInterestSet();
412 // Generic element interest
413 InterestSet gis = is.getComponentInterest();
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);
423 // Specific element interest
424 InterestSet cis = is.getComponentInterest(kv);
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);
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);
452 * Get existing sub accessor
454 * @return sub-accessor or <code>null</code>
456 JavaObject getExistingAccessor(Object localKey)
458 SoftReference<JavaObject> ref = children.get(localKey);
459 if (ref==null) return null;
460 JavaObject result = ref.get();
462 children.remove(localKey);
468 @SuppressWarnings("unchecked")
470 public <T extends Accessor> T getComponent(ChildReference reference)
471 throws AccessorConstructionException {
472 if (reference==null) return (T) this;
\r
473 if (reference instanceof LabelReference) {
\r
474 LabelReference lr = (LabelReference) reference;
\r
476 Binding kb = getKeyBinding();
\r
477 MutableVariant variant = (MutableVariant) adapt(lr.label, Bindings.STRING, Bindings.MUTABLE_VARIANT);
\r
478 Object value = variant.getValue(kb);
\r
480 Accessor result = (T) getValueAccessor(kb, value);
\r
481 if (reference.getChildReference() != null)
\r
482 result = result.getComponent(reference.getChildReference());
\r
483 return (T) result;
\r
484 } catch (AdaptException e2) {
\r
485 throw new ReferenceException(e2);
\r
486 } catch (AdapterConstructionException e) {
\r
487 throw new ReferenceException(e);
\r
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());
496 throw new ReferenceException(reference.getClass().getName()+" is not a reference of a map");
500 public int size() throws AccessorException {
\r
503 return getBinding().size(object);
504 } catch (BindingException e) {
505 throw new AccessorException(e);
512 public boolean containsKey(Binding keyBinding, Object key)
513 throws AccessorException {
\r
516 MapBinding mb = getBinding();
517 Binding lkb = getKeyBinding();
518 Binding rkb = keyBinding;
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) {
\r
527 throw new AccessorException(e);
\r
534 public boolean containsValue(Binding valueBinding, Object value)
535 throws AccessorException {
\r
538 MapBinding mb = getBinding();
539 Binding lvb = getValueBinding();
540 Binding rvb = valueBinding;
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) {
\r
549 throw new AccessorException(e);
\r
556 public Object get(Binding keyBinding, Object key, Binding valueBinding)
557 throws AccessorException {
\r
560 MapBinding mb = getBinding();
561 Binding lkb = getKeyBinding();
562 Binding rkb = keyBinding;
563 Binding lvb = getValueBinding();
564 Binding rvb = valueBinding;
566 Object lk = adapt(rk, rkb, lkb);
567 Object lv = mb.get(object, lk);
\r
568 if (lv == null) return null;
569 Object rv = adapt(lv, lvb, rvb);
571 } catch (AdaptException e) {
572 throw new AccessorException(e);
573 } catch (BindingException e) {
574 throw new AccessorException(e);
575 } catch (AdapterConstructionException e) {
\r
576 throw new AccessorException(e);
\r
583 public int count(Binding keyBinding, Object from,
\r
584 boolean fromInclusive, Object end, boolean endInclusive)
\r
585 throws AccessorException {
\r
588 MapBinding mb = getBinding();
\r
589 Object lf = params.adapterScheme.adapt(from, keyBinding, getKeyBinding());
\r
590 Object le = params.adapterScheme.adapt(end, keyBinding, getKeyBinding());
\r
591 return mb.count(object, lf, fromInclusive, le, endInclusive);
\r
592 } catch (BindingException e) {
\r
593 throw new AccessorException(e);
\r
594 } catch (AdaptException e) {
\r
595 throw new AccessorException(e);
\r
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 {
\r
606 MapBinding mb = getBinding();
\r
607 Object lfrom = params.adapterScheme.adapt(from, keyBinding, getKeyBinding());
\r
608 Object lend = params.adapterScheme.adapt(end, keyBinding, getKeyBinding());
\r
610 return mb.getEntries(object, lfrom, fromInclusive, lend, endInclusive, keyArrayBinding, keysArray, valueArrayBinding, valueArray, limit);
\r
611 } catch (BindingException e) {
\r
612 throw new AccessorException(e);
\r
613 } catch (AdaptException e) {
\r
614 throw new AccessorException(e);
\r
622 public void getAll(Binding keyBinding, Binding valueBinding, Map<Object, Object> to)
623 throws AccessorException {
\r
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);
634 for (int i=0; i<length; i++) {
636 Object lv = values[i];
637 Object rk = ka.adapt( lk );
638 Object rv = va.adapt( lv );
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);
653 public void getAll(Binding keyBinding, Binding valueBinding, Object[] keys, Object[] values) throws AccessorException {
\r
656 int length = getBinding().size(object);
657 getBinding().getAll(object, keys, values);
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] );
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);
677 public Object[] getKeys(Binding keyBinding) throws AccessorException {
\r
680 Object[] result = getBinding().getKeys(object);
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] );
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);
698 public Object[] getValues(Binding valueBinding) throws AccessorException {
\r
701 Object[] result = getBinding().getValues(object);
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] );
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);
719 public Object getCeilingKey(Binding keyBinding, Object key) throws AccessorException {
\r
722 // Local & Requested Key Bindings
723 Binding lkb = getKeyBinding();
724 Binding rkb = keyBinding;
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);
731 } catch (AdaptException e) {
732 throw new AccessorException( e );
733 } catch (AdapterConstructionException e) {
\r
734 throw new AccessorException( e );
\r
741 public Object getFirstKey(Binding keyBinding) throws AccessorException {
\r
744 Binding lkb = getKeyBinding();
745 Binding rkb = keyBinding;
746 Object lfk = getBinding().getFirstKey(object);
747 Object rfk = adapt(lfk, lkb, rkb);
749 } catch (AdaptException e) {
750 throw new AccessorException( e );
751 } catch (AdapterConstructionException e) {
\r
752 throw new AccessorException( e );
\r
759 public Object getLastKey(Binding keyBinding) throws AccessorException {
\r
762 Binding lkb = getKeyBinding();
763 Binding rkb = keyBinding;
764 Object lfk = getBinding().getLastKey(object);
765 Object rfk = adapt(lfk, lkb, rkb);
767 } catch (AdaptException e) {
768 throw new AccessorException( e );
769 } catch (AdapterConstructionException e) {
\r
770 throw new AccessorException( e );
\r
777 public Object getFloorKey(Binding keyBinding, Object key) throws AccessorException {
\r
780 // Local & Requested Key Bindings
781 Binding lkb = getKeyBinding();
782 Binding rkb = keyBinding;
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);
789 } catch (AdaptException e) {
790 throw new AccessorException( e );
791 } catch (AdapterConstructionException e) {
\r
792 throw new AccessorException( e );
\r
799 public Object getHigherKey(Binding keyBinding, Object key) throws AccessorException {
\r
802 // Local & Requested Key Bindings
803 Binding lkb = getKeyBinding();
804 Binding rkb = keyBinding;
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);
811 } catch (AdaptException e) {
812 throw new AccessorException( e );
813 } catch (AdapterConstructionException e) {
\r
814 throw new AccessorException( e );
\r
821 public Object getLowerKey(Binding keyBinding, Object key) throws AccessorException {
\r
824 // Local & Requested Key Bindings
825 Binding lkb = getKeyBinding();
826 Binding rkb = keyBinding;
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);
833 } catch (AdaptException e) {
834 throw new AccessorException( e );
835 } catch (AdapterConstructionException e) {
\r
836 throw new AccessorException( e );
\r
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;
848 Binding kb = getBinding().getKeyBinding();
850 for (Object key : children.keySet()) {
851 JavaObject sa = getExistingAccessor(key);
852 if (sa==null) continue;
854 MutableVariant vkey = new MutableVariant(kb, key);
855 InterestSet cis = is.getComponentInterest();
857 ChildReference childPath = ChildReference.concatenate( path, new KeyReference(vkey) );
858 sa.addListener(listener, cis, childPath, executor);
860 cis = is.getComponentInterest( vkey );
862 ChildReference childPath = ChildReference.concatenate( path, new KeyReference(vkey) );
863 sa.addListener(listener, cis, childPath, executor);
869 public void removeListener(Listener listener) throws AccessorException {
870 ListenerEntry e = detachListener(listener);
872 MapInterestSet is = (MapInterestSet) e.interestSet;
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();
880 MutableVariant vkey = new MutableVariant(kb, key);
881 InterestSet cis = is.getComponentInterest();
883 sa.removeListener(listener);
885 cis = is.getComponentInterest( vkey );
887 sa.removeListener(listener);
894 Event applyLocal(Event e, boolean makeRollback) throws AccessorException {
895 Event rollback = null;
897 if (e instanceof ValueAssigned) {
\r
898 ValueAssigned va = (ValueAssigned) e;
\r
899 if (makeRollback) rollback = new ValueAssigned(getBinding(), getValue(getBinding()));
\r
900 setValue(va.newValue.getBinding(), va.newValue.getValue());
\r
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");
910 rollback = new MapEntryRemoved( ea.key );
913 put(ea.key.getBinding(), ea.key.getValue(), ea.value.getBinding(), ea.value.getValue());
915 } else if (e instanceof MapEntryRemoved) {
916 MapEntryRemoved er = (MapEntryRemoved) e;
919 boolean hadValue = containsKey(er.key.getBinding(), er.key.getValue());
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);
927 rollback = new MapEntryRemoved( er.key.clone() );
931 remove( er.key.getBinding(), er.key.getValue() );
933 } else throw new AccessorException("Cannot apply "+e.getClass().getName()+" to Map Type");