1 11 12 package org.eclipse.jface.internal.databinding.provisional.observable.mapping; 13 14 import java.util.Collections ; 15 import java.util.HashMap ; 16 import java.util.HashSet ; 17 import java.util.Iterator ; 18 import java.util.Map ; 19 import java.util.Set ; 20 21 import org.eclipse.jface.internal.databinding.provisional.observable.IObservable; 22 import org.eclipse.jface.internal.databinding.provisional.observable.set.IObservableSet; 23 import org.eclipse.jface.internal.databinding.provisional.observable.set.ISetChangeListener; 24 import org.eclipse.jface.internal.databinding.provisional.observable.set.SetDiff; 25 import org.eclipse.jface.internal.databinding.provisional.observable.set.WritableSet; 26 27 31 public class BidirectionalMapping extends AbstractObservableMapping implements 32 IBidirectionalMapping, IObservableMappingWithDomain { 33 34 private final IObservableMapping wrappedMapping; 35 36 private IObservableSet range; 37 38 private Map valueToElements = new HashMap (); 39 40 private ISetChangeListener domainListener = new ISetChangeListener() { 41 public void handleSetChange(IObservableSet source, SetDiff diff) { 42 Set rangeAdditions = new HashSet (); 43 for (Iterator it = diff.getAdditions().iterator(); it.hasNext();) { 44 Object added = it.next(); 45 Object mappingValue = wrappedMapping.getMappingValue(added); 46 rangeAdditions.add(mappingValue); 47 addMapping(mappingValue, added); 48 } 49 range.addAll(rangeAdditions); 50 for (Iterator it = diff.getRemovals().iterator(); it.hasNext();) { 51 Object removed = it.next(); 52 removeMapping(wrappedMapping.getMappingValue(removed), removed); 53 } 54 range.retainAll(valueToElements.keySet()); 55 } 56 }; 57 58 private IMappingChangeListener mappingChangeListener = new IMappingChangeListener() { 59 public void handleMappingValueChange(IObservable source, 60 MappingDiff diff) { 61 Set affectedElements = diff.getElements(); 62 for (Iterator it = affectedElements.iterator(); it.hasNext();) { 63 Object element = it.next(); 64 Object oldFunctionValue = diff.getOldMappingValues(element, 65 new int[0])[0]; 66 Object newFunctionValue = diff.getNewMappingValues(element, 67 new int[0])[0]; 68 removeMapping(oldFunctionValue, element); 69 addMapping(newFunctionValue, element); 70 } 71 Set tempRange = valueToElements.keySet(); 72 range.addAll(tempRange); 73 range.retainAll(tempRange); 74 fireMappingValueChange(diff); 75 } 76 }; 77 78 private IObservableSet domain; 79 80 83 public BidirectionalMapping(IObservableMappingWithDomain functionWithDomain) { 84 this(functionWithDomain, functionWithDomain.getDomain()); 85 } 86 87 91 public BidirectionalMapping(IObservableMapping wrappedMapping, 92 IObservableSet domain) { 93 this.wrappedMapping = wrappedMapping; 94 this.domain = domain; 95 Set tempRange = new HashSet (); 96 for (Iterator it = domain.iterator(); it.hasNext();) { 97 Object element = it.next(); 98 Object functionValue = wrappedMapping.getMappingValue(element); 99 addMapping(functionValue, element); 100 tempRange.add(functionValue); 101 } 102 this.range = new WritableSet(tempRange); 103 domain.addSetChangeListener(domainListener); 104 } 105 106 111 private void addMapping(Object functionValue, Object element) { 112 Object elementOrSet = valueToElements.get(functionValue); 113 if (elementOrSet == null) { 114 valueToElements.put(functionValue, element); 115 return; 116 } 117 if (!(elementOrSet instanceof Set )) { 118 elementOrSet = new HashSet (Collections.singleton(elementOrSet)); 119 valueToElements.put(functionValue, elementOrSet); 120 } 121 Set set = (Set ) elementOrSet; 122 set.add(element); 123 } 124 125 130 private void removeMapping(Object functionValue, Object element) { 131 Object elementOrSet = valueToElements.get(functionValue); 132 if (elementOrSet instanceof Set ) { 133 Set set = (Set ) elementOrSet; 134 set.remove(element); 135 if (set.size() == 0) { 136 valueToElements.remove(functionValue); 137 } 138 } else { 139 valueToElements.remove(functionValue); 140 } 141 } 142 143 protected Object doGetMappingValue(Object element) { 144 return wrappedMapping.getMappingValue(element); 145 } 146 147 public void setMappingValue(Object element, Object value) { 148 wrappedMapping.setMappingValue(element, value); 149 } 150 151 public IObservableSet getRange() { 152 return range; 153 } 154 155 public Set getDomainElementsForValue(Object value) { 156 return null; 157 } 158 159 public void dispose() { 160 wrappedMapping.removeMappingChangeListener(mappingChangeListener); 161 domain.removeSetChangeListener(domainListener); 162 } 163 164 public IObservableSet getDomain() { 165 return domain; 166 } 167 168 public Object getValueType() { 169 return wrappedMapping.getValueType(); 170 } 171 172 } 173 | Popular Tags |