1 5 package com.tc.object.dna.impl; 6 7 import com.tc.bytes.TCByteBuffer; 8 import com.tc.io.TCByteBufferInputStream; 9 import com.tc.io.TCByteBufferOutput; 10 import com.tc.io.TCSerializable; 11 import com.tc.object.ObjectID; 12 import com.tc.object.dna.api.DNA; 13 import com.tc.object.dna.api.DNACursor; 14 import com.tc.object.dna.api.DNAException; 15 import com.tc.object.dna.api.LiteralAction; 16 import com.tc.object.dna.api.LogicalAction; 17 import com.tc.object.dna.api.PhysicalAction; 18 import com.tc.util.Assert; 19 20 import java.io.IOException ; 21 22 public class DNAImpl implements DNA, DNACursor, TCSerializable { 23 private static final DNAEncoding DNA_STORAGE_ENCODING = new DNAEncoding(DNAEncoding.STORAGE); 24 25 private final ObjectStringSerializer serializer; 26 private final boolean createOutput; 27 28 protected TCByteBufferInputStream input; 29 protected TCByteBuffer[] dataOut; 30 31 private int actionCount = 0; 32 private int origActionCount; 33 private boolean isDelta; 34 35 private ObjectID id; 37 private ObjectID parentID; 38 private String typeName; 39 private int arrayLength; 40 private String loaderDesc; 41 42 private Object currentAction; 44 45 private boolean wasDeserialized = false; 46 47 public DNAImpl(ObjectStringSerializer serializer, boolean createOutput) { 48 this.serializer = serializer; 49 this.createOutput = createOutput; 50 } 51 52 public String getTypeName() { 53 return typeName; 54 } 55 56 public ObjectID getObjectID() throws DNAException { 57 return id; 58 } 59 60 public ObjectID getParentObjectID() throws DNAException { 61 return parentID; 62 } 63 64 public DNACursor getCursor() { 65 return this; 66 } 67 68 public boolean next() throws IOException { 69 try { 70 return next(DNA_STORAGE_ENCODING); 71 } catch (ClassNotFoundException e) { 72 throw Assert.failure("Internal error"); 74 } 75 } 76 77 public boolean next(DNAEncoding encoding) throws IOException , ClassNotFoundException { 78 boolean hasNext = actionCount > 0; 79 if (hasNext) { 80 parseNext(encoding); 81 actionCount--; 82 } else { 83 if (input.available() > 0) { throw new IOException (input.available() + " bytes remaining (expect 0)"); } 84 } 85 return hasNext; 86 } 87 88 private void parseNext(DNAEncoding encoding) throws IOException , ClassNotFoundException { 89 byte recordType = input.readByte(); 90 91 switch (recordType) { 92 case DNAEncoding.PHYSICAL_ACTION_TYPE: 93 parsePhysical(encoding, false); 94 return; 95 case DNAEncoding.PHYSICAL_ACTION_TYPE_REF_OBJECT: 96 parsePhysical(encoding, true); 97 return; 98 case DNAEncoding.LOGICAL_ACTION_TYPE: 99 parseLogical(encoding); 100 return; 101 case DNAEncoding.ARRAY_ELEMENT_ACTION_TYPE: 102 parseArrayElement(encoding); 103 return; 104 case DNAEncoding.ENTIRE_ARRAY_ACTION_TYPE: 105 parseEntireArray(encoding); 106 return; 107 case DNAEncoding.LITERAL_VALUE_ACTION_TYPE: 108 parseLiteralValue(encoding); 109 return; 110 case DNAEncoding.SUB_ARRAY_ACTION_TYPE: 111 parseSubArray(encoding); 112 return; 113 default: 114 throw new IOException ("Invalid record type: " + recordType); 115 } 116 117 } 119 120 private void parseSubArray(DNAEncoding encoding) throws IOException , ClassNotFoundException { 121 int startPos = input.readInt(); 122 Object subArray = encoding.decode(input); 123 currentAction = new PhysicalAction(subArray, startPos); 124 } 125 126 private void parseEntireArray(DNAEncoding encoding) throws IOException , ClassNotFoundException { 127 Object array = encoding.decode(input); 128 currentAction = new PhysicalAction(array); 129 } 130 131 private void parseLiteralValue(DNAEncoding encoding) throws IOException , ClassNotFoundException { 132 Object value = encoding.decode(input); 133 currentAction = new LiteralAction(value); 134 } 135 136 private void parseArrayElement(DNAEncoding encoding) throws IOException , ClassNotFoundException { 137 int index = input.readInt(); 138 Object value = encoding.decode(input); 139 currentAction = new PhysicalAction(index, value, value instanceof ObjectID); 140 } 141 142 private void parsePhysical(DNAEncoding encoding, boolean isReference) throws IOException , ClassNotFoundException { 143 String fieldName = serializer.readFieldName(input); 144 145 Object value = encoding.decode(input); 146 currentAction = new PhysicalAction(fieldName, value, value instanceof ObjectID || isReference); 147 } 148 149 private void parseLogical(DNAEncoding encoding) throws IOException , ClassNotFoundException { 150 int method = input.readInt(); 151 int paramCount = input.read(); 152 if (paramCount < 0) throw new AssertionError ("Invalid param count:" + paramCount); 153 Object [] params = new Object [paramCount]; 154 for (int i = 0; i < params.length; i++) { 155 params[i] = encoding.decode(input); 156 } 157 currentAction = new LogicalAction(method, params); 158 } 159 160 public LogicalAction getLogicalAction() { 161 return (LogicalAction) this.currentAction; 162 } 163 164 public PhysicalAction getPhysicalAction() { 165 return (PhysicalAction) this.currentAction; 166 } 167 168 public Object getAction() { 169 return this.currentAction; 170 } 171 172 public String toString() { 173 try { 174 StringBuffer buf = new StringBuffer (); 175 buf.append("DNAImpl\n"); 176 buf.append("{\n"); 177 buf.append(" type->" + getTypeName() + "\n"); 178 buf.append(" id->" + getObjectID() + "\n"); 179 buf.append(" version->" + getVersion() + "\n"); 180 buf.append(" isDelta->" + isDelta() + "\n"); 181 buf.append(" actionCount->" + actionCount + "\n"); 182 buf.append(" actionCount (orig)->" + origActionCount + "\n"); 183 buf.append(" deserialized?->" + wasDeserialized + "\n"); 184 buf.append("}\n"); 185 return buf.toString(); 186 } catch (Exception e) { 187 return e.getMessage(); 188 } 189 } 190 191 public int getArraySize() { 192 return arrayLength; 193 } 194 195 public boolean hasLength() { 196 return getArraySize() >= 0; 197 } 198 199 public long getVersion() { 200 return NULL_VERSION; 201 } 202 203 206 public synchronized void serializeTo(TCByteBufferOutput serialOutput) { 207 serialOutput.write(dataOut); 208 } 209 210 public Object deserializeFrom(TCByteBufferInputStream serialInput) throws IOException { 211 this.wasDeserialized = true; 212 213 serialInput.mark(); 214 int dnaLength = serialInput.readInt(); 215 if (dnaLength <= 0) throw new IOException ("Invalid length:" + dnaLength); 216 217 serialInput.tcReset(); 218 219 this.input = serialInput.duplicateAndLimit(dnaLength); 220 serialInput.skip(dnaLength); 221 222 if (createOutput) { 223 this.dataOut = input.toArray(); 225 } 226 227 input.readInt(); 229 230 this.actionCount = input.readInt(); 231 this.origActionCount = actionCount; 232 233 if (actionCount < 0) throw new IOException ("Invalid action count:" + actionCount); 234 235 this.isDelta = input.readBoolean(); 236 237 this.id = new ObjectID(input.readLong()); 238 this.parentID = new ObjectID(input.readLong()); 239 this.typeName = serializer.readString(input); 240 this.loaderDesc = serializer.readString(input); 241 this.arrayLength = input.readInt(); 242 243 return this; 244 } 245 246 public String getDefiningLoaderDescription() { 247 return this.loaderDesc; 248 } 249 250 public int getActionCount() { 251 return this.actionCount; 252 } 253 254 public boolean isDelta() { 255 return this.isDelta; 256 } 257 258 public void reset() throws UnsupportedOperationException { 259 throw new UnsupportedOperationException ("Reset is not supported by this class"); 260 } 261 262 } 263 | Popular Tags |