1 2 12 package com.versant.core.jdo; 13 14 import com.versant.core.jdo.sco.*; 15 import com.versant.core.jdo.sco.detached.DetachSCOFactoryRegistry; 16 import com.versant.core.metadata.*; 17 import com.versant.core.common.OID; 18 import com.versant.core.common.State; 19 import com.versant.core.common.*; 20 21 import javax.jdo.spi.JDOImplHelper; 22 import javax.jdo.spi.PersistenceCapable; 23 import java.lang.reflect.Array ; 24 import java.util.HashMap ; 25 import java.util.Map ; 26 27 33 public class DetachStateContainer { 34 35 private static final int INITIAL_SIZE = 16; 36 private final JDOImplHelper jdoImplHelper = JDOImplHelper.getInstance(); 37 38 private int size; 39 private int sizeFG; 40 private int sizeRefs; 41 private int capacity = INITIAL_SIZE; 42 private int capacityFG = INITIAL_SIZE; 43 private int capacityRefs = INITIAL_SIZE * 2; 44 private int posFG = -1; 45 46 private State[] states = new State[capacity]; 47 private PersistenceCapable[] pcs = new PersistenceCapable[capacity]; 48 private OID[] oids = new OID[capacity]; 49 private FetchGroup[][] stateFG = new FetchGroup[capacity][]; 50 private FetchGroup[] fetchGroups = new FetchGroup[capacityFG]; 51 private int[] stateIndexs = new int[capacityFG]; 52 private State[] stateRefs = new State[capacityRefs]; 53 private Map oidMap = new HashMap (); 54 55 private final VersantDetachStateManager stateManager = new VersantDetachStateManager(); 56 private final VersantDetachedStateManager detachedStateManager = new VersantDetachedStateManager(); 57 private final VersantPersistenceManagerImp pm; 58 private final DetachSCOFactoryRegistry scoFactoryRegistry = new DetachSCOFactoryRegistry(); 59 private final ModelMetaData modelMetaData; 60 61 public DetachStateContainer(VersantPersistenceManagerImp pm) { 62 this.pm = pm; 63 modelMetaData = pm.modelMetaData; 64 stateManager.setDsc(this); 65 } 66 67 73 public int add(OID oid, State newState) { 74 addState(newState); Integer integer = (Integer )oidMap.get(oid); 76 if (integer == null) { 77 if (size == capacity) { 79 capacity = (capacity * 3) / 2 + 1; 81 State[] ns = new State[capacity]; 82 System.arraycopy(states, 0, ns, 0, size); 83 states = ns; 84 PersistenceCapable[] npcs = new PersistenceCapable[capacity]; 85 System.arraycopy(pcs, 0, npcs, 0, size); 86 pcs = npcs; 87 OID[] noids = new OID[capacity]; 88 System.arraycopy(oids, 0, noids, 0, size); 89 oids = noids; 90 FetchGroup[][] nStateFG = new FetchGroup[capacity][]; 91 System.arraycopy(stateFG, 0, nStateFG, 0, size); 92 stateFG = nStateFG; 93 } 94 states[size] = newState; 95 oids[size] = oid; 96 oidMap.put(oid, new Integer (size)); 97 return size++; 98 } else { 99 int i = integer.intValue(); 101 State realState = states[i]; 102 if (realState == null) { 103 states[i] = newState; 104 } else if (realState != newState) { 105 if (newState != null) { 106 realState.updateNonFilled(newState); 107 } 108 newState = realState; 109 } 110 return i; 111 } 112 } 113 114 117 public void add(OID oid, State newState, FetchGroup fg) { 118 int stateIndex = add(oid, newState); 119 if (fg == null) return; 120 if (newState != null) { 121 fg = fg.resolve(newState.getClassMetaData(modelMetaData)); 122 } 123 for (FetchGroup superFG = fg; superFG != null; 124 superFG = superFG.superFetchGroup) { 125 addImpl(stateIndex, superFG); 126 } 127 } 128 129 public void addImpl(int stateIndex, FetchGroup fg) { 130 FetchGroup[] sfg = stateFG[stateIndex]; 131 if (sfg == null) { 132 sfg = new FetchGroup[4]; 133 stateFG[stateIndex] = sfg; 134 } 135 int length = sfg.length; 136 boolean add = true; 137 for (int i = 0; i < length; i++) { 138 FetchGroup fetchGroup = sfg[i]; 139 if (fetchGroup == fg) { 140 return; 142 } else if (fetchGroup == null) { 143 sfg[i] = fg; 145 add = false; 146 break; 147 } 148 } 149 if (add) { 150 int oldSize = sfg.length; 152 int newSize = oldSize * 2; 153 FetchGroup[] nfg = new FetchGroup[newSize]; 154 System.arraycopy(sfg, 0, nfg, 0, oldSize); 155 sfg = nfg; 156 sfg[oldSize] = fg; 157 stateFG[stateIndex] = sfg; 158 } 159 if (sizeFG == capacityFG) { 160 capacityFG = (capacityFG * 3) / 2 + 1; 162 FetchGroup[] ng = new FetchGroup[capacityFG]; 163 System.arraycopy(fetchGroups, 0, ng, 0, sizeFG); 164 fetchGroups = ng; 165 int[] nsi = new int[capacityFG]; 166 System.arraycopy(stateIndexs, 0, nsi, 0, sizeFG); 167 stateIndexs = nsi; 168 } 169 fetchGroups[sizeFG] = fg; 170 stateIndexs[sizeFG] = stateIndex; 171 sizeFG++; 172 } 173 174 177 private void addState(State newState) { 178 if (sizeRefs == capacityRefs) { 180 capacityRefs = (capacityRefs * 3) / 2 + 1; 181 State[] ns = new State[capacityRefs]; 182 System.arraycopy(stateRefs, 0, ns, 0, sizeRefs); 183 stateRefs = ns; 184 } 185 stateRefs[sizeRefs++] = newState; 186 } 187 188 191 public void createPcClasses(ModelMetaData jmd) { 192 if (pcs[0] != null) return; 193 for (int i = 0; i < size; i++) { 194 PersistenceCapable pc = jdoImplHelper.newInstance( 195 states[i].getClassMetaData(jmd).cls, stateManager); 196 if (!(pc instanceof VersantDetachable)) { 197 throw BindingSupportImpl.getInstance().runtime("'" + pc.getClass().getName() + "' is not detachable please enhance " + 198 "classes with the detach option set to true"); 199 } 200 VersantDetachable detachable = (VersantDetachable)pc; 201 Object externalOID = pm.getExternalOID(oids[i]); 202 oidMap.put(externalOID, new Integer (i)); 203 detachable.versantSetOID(externalOID); 204 detachable.versantSetVersion(states[i].getOptimisticLockingValue()); 205 pcs[i] = detachable; 206 } 207 for (int i = 0; i < size; i++) { 208 PersistenceCapable pc = pcs[i]; 209 ClassMetaData cmd = states[i].getClassMetaData(jmd); 210 FieldMetaData[] pkFields = cmd.top.pkFields; 211 if (pkFields != null) { 212 for (int j = 0; j < pkFields.length; j++) { 213 FieldMetaData fmd = cmd.pkFields[j]; 214 int managedFieldNo = fmd.managedFieldNo; 215 if (!stateManager.isLoaded(pc, managedFieldNo)) { 216 pc.jdoReplaceField(managedFieldNo); 217 } 218 219 } 220 } 221 } 222 for (int i = 0; i < size; i++) { 223 PersistenceCapable pc = pcs[i]; 224 FetchGroup[] sfg = stateFG[i]; 225 int sfgLength = sfg.length; 226 for (int cfg = 0; cfg < sfgLength; cfg++) { 227 FetchGroup fg = sfg[cfg]; 228 if (fg == null) { 229 break; 230 } 231 boolean defaultFG = fg == fg.classMetaData.fetchGroups[0]; 232 for (int j = 0; j < fg.fields.length; j++) { 233 FetchGroupField field = fg.fields[j]; 234 FieldMetaData fmd = field.fmd; 235 if (fmd.fake) continue; 236 if (fmd.scoField) continue; 237 if (defaultFG && !fmd.isJDODefaultFetchGroup()) continue; 238 int managedFieldNo = fmd.managedFieldNo; 239 if (stateManager.isLoaded(pc, managedFieldNo)) continue; 240 pc.jdoReplaceField(managedFieldNo); 241 } 242 } 243 } 244 for (int i = 0; i < size; i++) { 245 PersistenceCapable pc = pcs[i]; 246 FetchGroup[] sfg = stateFG[i]; 247 int sfgLength = sfg.length; 248 for (int cfg = 0; cfg < sfgLength; cfg++) { 249 FetchGroup fg = sfg[cfg]; 250 if (fg == null) { 251 break; 252 } 253 boolean defaultFG = fg == fg.classMetaData.fetchGroups[0]; 254 for (int j = 0; j < fg.fields.length; j++) { 255 FetchGroupField field = fg.fields[j]; 256 FieldMetaData fmd = field.fmd; 257 if (fmd.fake) continue; 258 if (!fmd.scoField) continue; 259 if (defaultFG && !fmd.isJDODefaultFetchGroup()) continue; 260 int managedFieldNo = fmd.managedFieldNo; 261 if (stateManager.isLoaded(pc, managedFieldNo)) continue; 262 pc.jdoReplaceField(managedFieldNo); 263 } 264 } 265 } 266 for (int i = 0; i < size; i++) { 267 pcs[i].jdoReplaceStateManager(detachedStateManager); 268 } 269 } 270 271 274 public boolean hasNextFetchGroup() { 275 posFG++; 276 return posFG < sizeFG; 277 } 278 279 282 public State getNextFetchGroupState() { 283 return states[stateIndexs[posFG]]; 284 } 285 286 289 public FetchGroup getNextFetchGroup() { 290 return fetchGroups[posFG]; 291 } 292 293 296 public OID getNextFetchGroupOID() { 297 return oids[stateIndexs[posFG]]; 298 } 299 300 303 public boolean contains(OID oid) { 304 if (oid == null) return false; 305 return oidMap.containsKey(oid); 306 } 307 308 311 public PersistenceCapable getPC(OID oid) { 312 return pcs[((Integer )oidMap.get(oid)).intValue()]; 313 } 314 315 public State getState(PersistenceCapable pc) { 316 Object oid = ((VersantDetachable)pc).versantGetOID(); 317 Integer integer = (Integer )oidMap.get(oid); 318 if (integer == null) { 319 return null; 320 } 321 return states[integer.intValue()]; 322 } 323 324 public Object getObjectField(VersantDetachable pc, int fieldNo) { 325 State state = getState(pc); 326 ClassMetaData cmd = state.getClassMetaData(); 327 FieldMetaData fmd = cmd.stateFields[cmd.absToRel[fieldNo]]; 328 int category = fmd.category; 329 Object o = state.getInternalObjectFieldAbs(fieldNo); 330 331 switch (category) { 332 case MDStatics.CATEGORY_COLLECTION: 333 if (o != null) { 334 VersantSCOCollectionFactory factory = scoFactoryRegistry.getJDOGenieSCOCollectionFactory( 335 fmd); 336 if (o instanceof VersantSCOCollection) { 337 CollectionData collectionData = new CollectionData(); 338 ((VersantSCOCollection)o).fillCollectionData( 339 collectionData); 340 collectionData.valueCount = getDetachCopy( 341 collectionData.values, 342 collectionData.valueCount); 343 return factory.createSCOCollection(pc, pm, 344 detachedStateManager, fmd, collectionData); 345 } else { 346 CollectionData collectionData = new CollectionData(); 347 Object [] values = (Object [])o; 348 int length = values.length; 349 collectionData.values = new Object [length]; 350 System.arraycopy(values, 0, collectionData.values, 0, 351 length); 352 collectionData.valueCount = collectionData.values.length; 353 collectionData.valueCount = getDetachCopy( 354 collectionData.values, 355 collectionData.valueCount); 356 return factory.createSCOCollection(pc, pm, 357 detachedStateManager, fmd, collectionData); 358 } 359 } 360 break; 361 case MDStatics.CATEGORY_ARRAY: 362 if (o != null) { 363 if (!o.getClass().isArray()) return o; 364 Class type = o.getClass().getComponentType(); 365 int length = Array.getLength(o); 366 Object newArray = Array.newInstance(type, length); 367 System.arraycopy(o, 0, newArray, 0, length); 368 if (fmd.isElementTypePC()) { 369 getDetachCopy((Object [])newArray, length); 370 } 371 return newArray; 372 } 373 break; 374 case MDStatics.CATEGORY_MAP: 375 if (o != null) { 376 VersantSCOMapFactory factory = scoFactoryRegistry.getJDOGenieSCOMapFactory( 377 fmd); 378 if (o instanceof VersantSCOMap) { 379 MapData mapData = new MapData(); 380 ((VersantSCOMap)o).fillMapData(mapData); 381 mapData.entryCount = getDetachCopy(mapData.keys, 382 mapData.entryCount); 383 mapData.entryCount = getDetachCopy(mapData.values, 384 mapData.entryCount); 385 return factory.createSCOHashMap(pc, pm, 386 detachedStateManager, fmd, mapData); 387 } else { 388 MapEntries entries = (MapEntries)o; 389 MapData mapData = new MapData(); 390 mapData.entryCount = entries.keys.length; 391 Object [] keys = new Object [mapData.entryCount]; 392 System.arraycopy(entries.keys, 0, keys, 0, 393 mapData.entryCount); 394 Object [] values = new Object [mapData.entryCount]; 395 System.arraycopy(entries.values, 0, values, 0, 396 mapData.entryCount); 397 mapData.keys = keys; 398 mapData.values = values; 399 mapData.entryCount = getDetachCopy(mapData.keys, 400 mapData.entryCount); 401 mapData.entryCount = getDetachCopy(mapData.values, 402 mapData.entryCount); 403 return factory.createSCOHashMap(pc, pm, 404 detachedStateManager, fmd, mapData); 405 } 406 } 407 break; 408 case MDStatics.CATEGORY_EXTERNALIZED: 409 if (o != null) { 410 if (state.isResolvedForClient(fieldNo)){ 411 o = fmd.externalizer.toExternalForm(pm, o); 412 } 413 o = fmd.externalizer.fromExternalForm(pm, o); 414 } 415 return o; 416 case MDStatics.CATEGORY_REF: 417 case MDStatics.CATEGORY_POLYREF: 418 if (o != null) { 419 if (fmd.scoField) { 420 VersantSCOFactory factory = scoFactoryRegistry.getJdoGenieSCOFactory( 421 fmd); 422 return factory.createSCO(pc, pm, detachedStateManager, 423 fmd, o); 424 } else { 425 return getDetachCopy(o); 426 } 427 } 428 break; 429 } 430 return o; 431 } 432 433 public PersistenceCapable getDetachCopy(OID oid) { 434 Integer integer = (Integer )oidMap.get(oid); 435 int index = integer == null ? -1 : integer.intValue(); 436 if (index < 0) { 437 throw BindingSupportImpl.getInstance().exception( 438 "Could not find detached copy of object with oid='" + oid + "'"); 439 } 440 return pcs[index]; 441 } 442 443 public PersistenceCapable getDetachCopy(PersistenceCapable pc) { 444 PCStateMan internalSM = pm.getInternalSM(pc); 445 return getDetachCopy(internalSM.oid); 446 } 447 448 public int getDetachCopy(Object [] objects, int count) { 449 count = Math.min(count, objects.length); 450 for (int i = 0; i < count; i++) { 451 Object o = objects[i]; 452 if (o != null) { 453 objects[i] = getDetachCopy(o); 454 } else { 455 return i; 456 } 457 } 458 return count; 459 } 460 461 public Object getDetachCopy(Object o) { 462 if (o instanceof OID) { 463 return getDetachCopy((OID)o); 464 } else if (o instanceof PersistenceCapable) { 465 return getDetachCopy((PersistenceCapable)o); 466 } 467 return o; 468 } 469 470 public VersantDetachStateManager getStateManager() { 471 return stateManager; 472 } 473 } 474 | Popular Tags |