001: /*
002: * All content copyright (c) 2003-2006 Terracotta, Inc., except as may otherwise be noted in a separate copyright notice. All rights reserved.
003: */
004: package com.tc.object.applicator;
005:
006: import com.tc.object.ClientObjectManager;
007: import com.tc.object.ObjectID;
008: import com.tc.object.TCObject;
009: import com.tc.object.TraversedReferences;
010: import com.tc.object.dna.api.DNA;
011: import com.tc.object.dna.api.DNACursor;
012: import com.tc.object.dna.api.DNAWriter;
013: import com.tc.object.dna.api.DNAEncoding;
014: import com.tc.object.dna.api.LogicalAction;
015: import com.tc.object.dna.api.PhysicalAction;
016: import com.tc.util.Assert;
017: import com.tc.util.FieldUtils;
018:
019: import java.io.IOException;
020: import java.lang.reflect.Field;
021: import java.util.Collection;
022: import java.util.Comparator;
023: import java.util.Iterator;
024: import java.util.TreeMap;
025: import java.util.TreeSet;
026:
027: /**
028: * ChangeApplicator for HashSets.
029: */
030: public class TreeSetApplicator extends HashSetApplicator {
031: private static final String COMPARATOR_FIELDNAME = TreeMapApplicator.COMPARATOR_FIELDNAME;
032: private static final Field COMPARATOR_FIELD;
033: private static final Field TREE_MAP_FIELD;
034:
035: static {
036: try {
037: COMPARATOR_FIELD = TreeMap.class
038: .getDeclaredField("comparator");
039: COMPARATOR_FIELD.setAccessible(true);
040:
041: TREE_MAP_FIELD = TreeSet.class.getDeclaredField("m");
042: TREE_MAP_FIELD.setAccessible(true);
043: } catch (Exception e) {
044: throw new RuntimeException(e);
045: }
046: }
047:
048: public TreeSetApplicator(DNAEncoding encoding) {
049: super (encoding);
050: }
051:
052: public void hydrate(ClientObjectManager objectManager,
053: TCObject tcObject, DNA dna, Object pojo)
054: throws IOException, ClassNotFoundException {
055: TreeSet set = (TreeSet) pojo;
056: DNACursor cursor = dna.getCursor();
057:
058: if (!cursor.next(encoding)) {
059: return;
060: }
061:
062: Object action = cursor.getAction();
063: if (action instanceof PhysicalAction) {
064: PhysicalAction pa = (PhysicalAction) action;
065: Assert
066: .assertEquals(COMPARATOR_FIELDNAME, pa
067: .getFieldName());
068: setComparator(set, objectManager.lookupObject((ObjectID) pa
069: .getObject()));
070: } else {
071: LogicalAction la = (LogicalAction) action;
072: int method = la.getMethod();
073: Object[] params = la.getParameters();
074: super .apply(objectManager, set, method, params);
075: }
076:
077: while (cursor.next(encoding)) {
078: LogicalAction la = cursor.getLogicalAction();
079: int method = la.getMethod();
080: Object[] params = la.getParameters();
081: super .apply(objectManager, set, method, params);
082: }
083: }
084:
085: private void setComparator(Object treeSet, Object comparator) {
086: try {
087: Object treeMap = TREE_MAP_FIELD.get(treeSet);
088: FieldUtils.tcSet(treeMap, comparator, COMPARATOR_FIELD);
089: } catch (Exception e) {
090: throw new RuntimeException(e);
091: }
092: }
093:
094: public void dehydrate(ClientObjectManager objectManager,
095: TCObject tcObject, DNAWriter writer, Object pojo) {
096: TreeSet set = (TreeSet) pojo;
097: Comparator cmp = set.comparator();
098: if (cmp != null) {
099: Object cmpObj = getDehydratableObject(cmp, objectManager);
100: if (cmpObj != null) {
101: writer.addPhysicalAction(COMPARATOR_FIELDNAME, cmpObj);
102: }
103: }
104:
105: super .dehydrate(objectManager, tcObject, writer, pojo);
106: }
107:
108: public TraversedReferences getPortableObjects(Object pojo,
109: TraversedReferences addTo) {
110: TreeSet set = (TreeSet) pojo;
111: filterPortableObject(set.comparator(), addTo);
112: filterPortableObjects(set, addTo);
113: return addTo;
114: }
115:
116: private void filterPortableObjects(Collection objects,
117: TraversedReferences addTo) {
118: for (Iterator i = objects.iterator(); i.hasNext();) {
119: Object value = i.next();
120: filterPortableObject(value, addTo);
121: }
122: }
123:
124: private void filterPortableObject(Object value,
125: TraversedReferences addTo) {
126: if (value != null && isPortableReference(value.getClass())) {
127: addTo.addAnonymousReference(value);
128: }
129: }
130: }
|