001: /*
002: * All content copyright (c) 2003-2006 Terracotta, Inc., except as may otherwise be noted in a separate copyright
003: * notice. All rights reserved.
004: */
005: package com.tc.object.applicator;
006:
007: import com.tc.object.ClientObjectManager;
008: import com.tc.object.ObjectID;
009: import com.tc.object.SerializationUtil;
010: import com.tc.object.TCObject;
011: import com.tc.object.TraversedReferences;
012: import com.tc.object.bytecode.Manageable;
013: import com.tc.object.dna.api.DNA;
014: import com.tc.object.dna.api.DNACursor;
015: import com.tc.object.dna.api.DNAWriter;
016: import com.tc.object.dna.api.DNAEncoding;
017: import com.tc.object.dna.api.LogicalAction;
018: import com.tc.object.tx.optimistic.OptimisticTransactionManager;
019: import com.tc.object.tx.optimistic.TCObjectClone;
020: import com.tc.util.Assert;
021:
022: import java.io.IOException;
023: import java.util.ArrayList;
024: import java.util.IdentityHashMap;
025: import java.util.Iterator;
026: import java.util.List;
027: import java.util.Map;
028: import java.util.Set;
029:
030: /**
031: * ChangeApplicator for HashSets.
032: */
033: public class HashSetApplicator extends BaseApplicator {
034:
035: public HashSetApplicator(DNAEncoding encoding) {
036: super (encoding);
037: }
038:
039: public void hydrate(ClientObjectManager objectManager,
040: TCObject tcObject, DNA dna, Object pojo)
041: throws IOException, ClassNotFoundException {
042: Set set = (Set) pojo;
043: DNACursor cursor = dna.getCursor();
044:
045: while (cursor.next(encoding)) {
046: LogicalAction action = cursor.getLogicalAction();
047: int method = action.getMethod();
048: Object[] params = action.getParameters();
049: apply(objectManager, set, method, params);
050: }
051: }
052:
053: protected void apply(ClientObjectManager objectManager, Set set,
054: int method, Object[] params) throws ClassNotFoundException {
055: switch (method) {
056: case SerializationUtil.ADD:
057: Object v = getValue(params);
058: Object value = v instanceof ObjectID ? objectManager
059: .lookupObject((ObjectID) v) : v;
060: set.add(value);
061: break;
062: case SerializationUtil.REMOVE:
063: Object rkey = params[0] instanceof ObjectID ? objectManager
064: .lookupObject((ObjectID) params[0]) : params[0];
065: set.remove(rkey);
066: break;
067: case SerializationUtil.REMOVE_ALL:
068: set.removeAll(getObjectParams(objectManager, params));
069: break;
070: case SerializationUtil.CLEAR:
071: set.clear();
072: break;
073: default:
074: throw new AssertionError("invalid action:" + method);
075: }
076: }
077:
078: private List getObjectParams(ClientObjectManager objectManager,
079: Object[] params) throws ClassNotFoundException {
080: List retParams = new ArrayList(params.length);
081:
082: for (int i = 0; i < params.length; i++) {
083: retParams.add(params[i] instanceof ObjectID ? objectManager
084: .lookupObject((ObjectID) params[i]) : params[i]);
085: }
086: return retParams;
087: }
088:
089: private Object getValue(Object[] params) {
090: // hack to deal with trove set which replaces on set unlike java Set which does not
091: return params.length == 2 ? params[1] : params[0];
092: }
093:
094: public void dehydrate(ClientObjectManager objectManager,
095: TCObject tcObject, DNAWriter writer, Object pojo) {
096: Set set = (Set) pojo;
097: for (Iterator i = set.iterator(); i.hasNext();) {
098: Object value = i.next();
099: if (!objectManager.isPortableInstance(value)) {
100: continue;
101: }
102:
103: final Object addValue = getDehydratableObject(value,
104: objectManager);
105:
106: if (addValue == null) {
107: continue;
108: }
109:
110: writer.addLogicalAction(SerializationUtil.ADD,
111: new Object[] { addValue });
112: }
113: }
114:
115: public TraversedReferences getPortableObjects(Object pojo,
116: TraversedReferences addTo) {
117: Set set = (Set) pojo;
118: for (Iterator i = set.iterator(); i.hasNext();) {
119: Object o = i.next();
120: if (o != null && isPortableReference(o.getClass())) {
121: addTo.addAnonymousReference(o);
122: }
123: }
124: return addTo;
125: }
126:
127: public Object getNewInstance(ClientObjectManager objectManager,
128: DNA dna) {
129: throw new UnsupportedOperationException();
130: }
131:
132: public Map connectedCopy(Object source, Object dest, Map visited,
133: ClientObjectManager objectManager,
134: OptimisticTransactionManager txManager) {
135: Map cloned = new IdentityHashMap();
136:
137: Manageable sourceManageable = (Manageable) source;
138: Manageable destManaged = (Manageable) dest;
139:
140: Set sourceSet = (Set) source;
141: Set destSet = (Set) dest;
142:
143: for (Iterator i = sourceSet.iterator(); i.hasNext();) {
144: Object v = i.next();
145: Object copyValue = null;
146:
147: if (isLiteralInstance(v)) {
148: copyValue = v;
149: } else if (visited.containsKey(v)) {
150: Assert.eval(visited.get(v) != null);
151: copyValue = visited.get(v);
152: } else {
153: Assert.eval(!isLiteralInstance(v));
154: copyValue = objectManager.createNewCopyInstance(v,
155: createParentIfNecessary(visited, objectManager,
156: cloned, v));
157:
158: visited.put(v, copyValue);
159: cloned.put(v, copyValue);
160: }
161: destSet.add(copyValue);
162: }
163:
164: destManaged.__tc_managed(new TCObjectClone(sourceManageable
165: .__tc_managed(), txManager));
166: return cloned;
167: }
168: }
|