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.dna.impl;
005:
006: import com.tc.io.TCByteBufferInput;
007: import com.tc.io.TCByteBufferOutput;
008: import com.tc.io.TCDataOutput;
009: import com.tc.io.TCSerializable;
010: import com.tc.util.Assert;
011:
012: import gnu.trove.TIntObjectHashMap;
013: import gnu.trove.TLongObjectHashMap;
014: import gnu.trove.TObjectIntHashMap;
015: import gnu.trove.TObjectIntProcedure;
016:
017: import java.io.IOException;
018:
019: public class ObjectStringSerializer implements TCSerializable {
020:
021: private final TObjectIntHashMap stringToID = new TObjectIntHashMap();
022: private final TIntObjectHashMap idToString = new TIntObjectHashMap();
023: private final TLongObjectHashMap fields = new TLongObjectHashMap();
024:
025: private static class SerializeProcedure implements
026: TObjectIntProcedure {
027: private final TCDataOutput out;
028:
029: public SerializeProcedure(TCDataOutput out) {
030: this .out = out;
031: }
032:
033: public boolean execute(Object key, int value) {
034: out.writeString((String) key);
035: out.writeInt(value);
036: return true;
037: }
038: }
039:
040: public synchronized void serializeTo(TCByteBufferOutput serialOutput) {
041: serialOutput.writeInt(stringToID.size());
042: stringToID.forEachEntry(new SerializeProcedure(serialOutput));
043: }
044:
045: public synchronized Object deserializeFrom(
046: TCByteBufferInput serialInput) throws IOException {
047: int size = serialInput.readInt();
048: for (int i = 0; i < size; i++) {
049: addStringAndID(serialInput.readString(), serialInput
050: .readInt());
051: }
052: return this ;
053: }
054:
055: public synchronized void writeString(TCByteBufferOutput out,
056: String string) {
057: int sid = -1;
058: if (stringToID.containsKey(string)) {
059: sid = idForString(string);
060: } else {
061: sid = createID(string);
062: }
063: out.writeInt(sid);
064: }
065:
066: public synchronized void writeFieldName(TCByteBufferOutput out,
067: String fieldName) {
068: int lastDot = fieldName.lastIndexOf('.');
069: String cn = fieldName.substring(0, lastDot);
070: String fn = fieldName
071: .substring(lastDot + 1, fieldName.length());
072:
073: writeString(out, cn);
074: writeString(out, fn);
075: }
076:
077: public synchronized String readString(TCByteBufferInput in)
078: throws IOException {
079: int id = in.readInt();
080:
081: String string = stringForID(id);
082: if (string == null) {
083: throw new AssertionError("cid:" + id + " map:" + stringToID);
084: }
085:
086: return string;
087: }
088:
089: public synchronized String readFieldName(TCByteBufferInput in)
090: throws IOException {
091: final int classId;
092: classId = in.readInt();
093:
094: final int fieldId;
095: fieldId = in.readInt();
096:
097: long key = ((long) classId << 32) + fieldId;
098: String rv = (String) fields.get(key);
099: if (rv == null) {
100: String cn = stringForID(classId);
101: Assert.eval(cn != null);
102: String fn = stringForID(fieldId);
103: Assert.eval(fn != null);
104: StringBuffer buf = new StringBuffer(cn.length()
105: + fn.length() + 1); // +1 for '.'
106: buf.append(cn).append('.').append(fn);
107: rv = buf.toString().intern();
108: fields.put(key, rv);
109: }
110:
111: return rv;
112: }
113:
114: private void addStringAndID(String name, int id) {
115: name = name.intern();
116: stringToID.put(name, id);
117: idToString.put(id, name);
118: }
119:
120: private String stringForID(int id) {
121: return (String) idToString.get(id);
122: }
123:
124: private int idForString(String string) {
125: return stringToID.get(string);
126: }
127:
128: private int createID(String string) {
129: Assert.assertNotNull(string);
130: int newID = stringToID.size() + 1;
131: stringToID.put(string, newID);
132: idToString.put(newID, string);
133: return newID;
134: }
135: }
|