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.objectserver.managedobject;
005:
006: import com.tc.object.ObjectID;
007: import com.tc.object.SerializationUtil;
008: import com.tc.object.dna.api.DNACursor;
009: import com.tc.object.dna.api.DNAWriter;
010: import com.tc.object.dna.api.LogicalAction;
011: import com.tc.objectserver.mgmt.FacadeUtil;
012: import com.tc.objectserver.mgmt.LogicalManagedObjectFacade;
013: import com.tc.objectserver.mgmt.ManagedObjectFacade;
014: import com.tc.objectserver.mgmt.MapEntryFacade;
015: import com.tc.objectserver.mgmt.MapEntryFacadeImpl;
016: import com.tc.text.PrettyPrintable;
017: import com.tc.text.PrettyPrinter;
018:
019: import java.io.IOException;
020: import java.io.ObjectInput;
021: import java.io.ObjectOutput;
022: import java.util.Iterator;
023: import java.util.Map;
024: import java.util.Set;
025: import java.util.Map.Entry;
026:
027: /**
028: * state for maps
029: */
030: public class MapManagedObjectState extends LogicalManagedObjectState
031: implements PrettyPrintable {
032: protected Map references;
033:
034: protected MapManagedObjectState(long classID, Map map) {
035: super (classID);
036: references = map;
037: }
038:
039: protected MapManagedObjectState(ObjectInput in) throws IOException {
040: super (in);
041: }
042:
043: public void apply(ObjectID objectID, DNACursor cursor,
044: BackReferences includeIDs) throws IOException {
045: while (cursor.next()) {
046: LogicalAction action = cursor.getLogicalAction();
047: int method = action.getMethod();
048: Object[] params = action.getParameters();
049: applyMethod(objectID, includeIDs, method, params);
050: }
051: }
052:
053: protected void applyMethod(ObjectID objectID,
054: BackReferences includeIDs, int method, Object[] params) {
055: switch (method) {
056: case SerializationUtil.PUT:
057:
058: mapPreProcess(params);
059: Object key = getKey(params);
060: Object value = getValue(params);
061: references.put(key, value);
062: if (key instanceof ObjectID) {
063: ObjectID v = (ObjectID) key;
064: getListener().changed(objectID, null, v);
065: addBackReferenceForKey(includeIDs, v, objectID);
066: }
067: if (value instanceof ObjectID) {
068: ObjectID v = (ObjectID) value;
069: getListener().changed(objectID, null, v);
070: addBackReferenceForValue(includeIDs, v, objectID);
071: }
072: break;
073: case SerializationUtil.REMOVE:
074: references.remove(params[0]);
075: break;
076: case SerializationUtil.CLEAR:
077: references.clear();
078: break;
079: default:
080: throw new AssertionError("Invalid action:" + method);
081: }
082:
083: }
084:
085: protected void addBackReferenceForKey(BackReferences includeIDs,
086: ObjectID key, ObjectID map) {
087: includeIDs.addBackReference(key, map);
088: }
089:
090: protected void addBackReferenceForValue(BackReferences includeIDs,
091: ObjectID value, ObjectID map) {
092: includeIDs.addBackReference(value, map);
093: }
094:
095: private Object getKey(Object[] params) {
096: // Hack hack big hack for trove maps which replace the key on set as opposed to HashMaps which do not.
097: return params.length == 3 ? params[1] : params[0];
098: }
099:
100: private Object getValue(Object[] params) {
101: // Hack hack big hack for trove maps which replace the key on set as opposed to HashMaps which do not.
102: return params.length == 3 ? params[2] : params[1];
103: }
104:
105: private void mapPreProcess(Object[] params) {
106: // Hack hack big hack for trove maps which replace the key on set as opposed to HashMaps which do not.
107: if (params.length == 3) {
108: references.remove(params[0]);
109: }
110: }
111:
112: public void dehydrate(ObjectID objectID, DNAWriter writer) {
113: for (Iterator i = references.entrySet().iterator(); i.hasNext();) {
114: Entry entry = (Entry) i.next();
115: Object key = entry.getKey();
116: Object value = entry.getValue();
117: writer.addLogicalAction(SerializationUtil.PUT,
118: new Object[] { key, value });
119: }
120: }
121:
122: protected void addAllObjectReferencesTo(Set refs) {
123: addAllObjectReferencesFromIteratorTo(this .references.keySet()
124: .iterator(), refs);
125: addAllObjectReferencesFromIteratorTo(this .references.values()
126: .iterator(), refs);
127: }
128:
129: public PrettyPrinter prettyPrint(PrettyPrinter out) {
130: PrettyPrinter rv = out;
131: out = out.println("MapManagedObjectState").duplicateAndIndent();
132: out.indent().println("references: " + references);
133: return rv;
134: }
135:
136: public ManagedObjectFacade createFacade(ObjectID objectID,
137: String className, int limit) {
138: final int size = references.size();
139:
140: if (limit < 0) {
141: limit = size;
142: } else {
143: limit = Math.min(limit, size);
144: }
145:
146: MapEntryFacade[] data = new MapEntryFacade[limit];
147:
148: int index = 0;
149:
150: for (Iterator i = references.entrySet().iterator(); i.hasNext()
151: && index < limit; index++) {
152: Entry entry = (Entry) i.next();
153: Object key = FacadeUtil.processValue(entry.getKey());
154: Object value = FacadeUtil.processValue(entry.getValue());
155: data[index] = new MapEntryFacadeImpl(key, value);
156: }
157:
158: return LogicalManagedObjectFacade.createMapInstance(objectID,
159: className, data, size);
160: }
161:
162: protected void basicWriteTo(ObjectOutput out) throws IOException {
163: // CollectionsPersistor will save retrieve data in references map.
164: if (false)
165: throw new IOException();
166: }
167:
168: public void setMap(Map map) {
169: if (this .references != null) {
170: throw new AssertionError(
171: "The references map is already set ! " + references);
172: }
173: this .references = map;
174: }
175:
176: public Map getMap() {
177: return references;
178: }
179:
180: // CollectionsPersistor will save retrieve data in references map.
181: static MapManagedObjectState readFrom(ObjectInput in)
182: throws IOException, ClassNotFoundException {
183: if (false) {
184: // This is added to make the compiler happy. For some reason if I have readFrom() method throw
185: // ClassNotFoundException in LinkedHashMapManagedObjectState, it shows as an error !!
186: throw new ClassNotFoundException();
187: }
188: return new MapManagedObjectState(in);
189: }
190:
191: public byte getType() {
192: return MAP_TYPE;
193: }
194:
195: protected boolean basicEquals(LogicalManagedObjectState o) {
196: MapManagedObjectState mmo = (MapManagedObjectState) o;
197: return references.equals(mmo.references);
198: }
199: }
|