KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > versant > core > common > State


1
2 /*
3  * Copyright (c) 1998 - 2005 Versant Corporation
4  * All rights reserved. This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License v1.0
6  * which accompanies this distribution, and is available at
7  * http://www.eclipse.org/legal/epl-v10.html
8  *
9  * Contributors:
10  * Versant Corporation - initial API and implementation
11  */

12 package com.versant.core.common;
13
14 import com.versant.core.jdo.PCStateMan;
15 import com.versant.core.metadata.*;
16 import com.versant.core.jdo.DetachStateContainer;
17 import com.versant.core.jdo.VersantPersistenceManagerImp;
18 import com.versant.core.jdo.*;
19 import com.versant.core.server.OIDGraph;
20 import com.versant.core.server.PersistGraph;
21 import com.versant.core.util.IntArray;
22 import com.versant.core.util.OIDObjectOutput;
23 import com.versant.core.util.OIDObjectInput;
24
25 import javax.jdo.spi.PersistenceCapable;
26 import java.util.*;
27 import java.lang.reflect.Array JavaDoc;
28 import java.io.IOException JavaDoc;
29
30
31
32 /**
33  * This is an abstract base class for State classes. Each State class is
34  * a container for the persistent fields of a PC class and all of its
35  * superclasses. These fields may include fake fields generated by the
36  * store to hold extra store specific information (e.g. row version column
37  * values).<p>
38  * <p/>
39  * Methods always use field numbers relative to the topmost class in the
40  * heirachy. This range of numbers includes fake fields present in each
41  * class.<p>
42  * <p/>
43  * Example of the State fieldNo range for C extends B extends A:<br>
44  * A.superFieldCount[A fields] (A.superFieldCount + A.realFieldCount)[A fakes]<br>
45  * B.superFieldCount[B fields] (B.superFieldCount + B.realFieldCount)[B fakes]<br>
46  * C.superFieldCount[C fields] (C.superFieldCount + C.realFieldCount)[C fakes]<p>
47  * <p/>
48  * Each PC class has its own implementation generated for it at runtime.
49  * These classes have fast implementations of various methods in the
50  * base class designed for different data stores. The JDO meta data for each
51  * PC class is a factory for its State instances.<p>
52  *
53  *
54  * Lifecycle:
55  *
56  *
57  * State is create in datastore on a request for data. This state is offered to
58  * the l2cache and returned to the requesting client. There the state is eiter used to
59  * update the state of a PCStateMan or added directly to the LocalPMCache.
60  *
61  * Any mutable data in that is contained in a state should be considered immutable. This
62  * is because if can share the same data that was returned by a state and changing it would result
63  * in weird behaviour.
64  *
65  * TODO: Go through all data struct that is returned by state and check if
66  * immutablility can be enforced.
67  *
68  * @see ClassMetaData#fields
69  * @see ClassMetaData#realFieldCount
70  * @see ClassMetaData#superFieldCount
71  */

72 public abstract class State
73  {
74
75     /**
76      * To check if the state is hollow.
77      * This is for debug/testing only.
78      *
79      * @return
80      */

81     public abstract boolean isHollow();
82
83     /**
84      * Return a new State instance
85      *
86      * @return new State instance
87      */

88     public abstract State newInstance();
89
90     /**
91      * Return the index of our PC class in the meta data. Do not use this
92      * to get the meta data for our class. Call getClassMetaData instead.
93      *
94      * @see ModelMetaData#classes
95      * @see #getClassMetaData
96      */

97     public abstract int getClassIndex();
98
99     /**
100      * Get the meta data for our class.
101      *
102      * @param jmd The meta data we belong to
103      */

104     public abstract ClassMetaData getClassMetaData(ModelMetaData jmd);
105
106     /**
107      * Return true if any field is dirty.
108      *
109      * @return
110      */

111     public abstract boolean isDirty();
112
113     /**
114      * Check if a specific field is dirty.
115      *
116      * @param fieldNo
117      * @return
118      */

119     public abstract boolean isDirty(int fieldNo);
120
121     /**
122      * This is just for testing and will not be called in (real)runtime.
123      */

124     public void validateForCache() {
125
126     }
127
128     /**
129      * Mark the specified field as dirty.
130      *
131      * @param fieldNo
132      */

133     public abstract void makeDirtyAbs(int fieldNo);
134
135     /**
136      * Mark all dirty fields as clean and not filled and not resolved.
137      */

138     public abstract void clearDirtyFields();
139
140     /**
141      * Update this state from the supplied state. All fields will be updated even
142      * if it is filled in on this state.
143      *
144      * @param state
145      */

146     public abstract void updateFrom(State state);
147
148     /**
149      * Update this state from the supplied state. Only the fields not filled in
150      * on the current state and filled in on the supplied state will be updated.
151      *
152      * @param state
153      */

154     public abstract void updateNonFilled(State state);
155
156     /**
157      * Clear all the non autoSet fields.
158      */

159     public abstract void clearNonAutoSetFields();
160
161     public abstract void retrieve(VersantPersistenceManagerImp sm);
162
163     /**
164      * Clear the fields in this state that is not filled in on the supplied state.
165      *
166      * @param state
167      */

168     public abstract void clearNonFilled(State state);
169
170     /**
171      * Clear all fields of type mem.
172      */

173     public abstract void clearCollectionFields();
174
175     /**
176      * This cleares all the sco fields of the state of their values and sets it
177      * to non filled.
178      */

179     public abstract void clearSCOFields();
180
181     /**
182      * Clear all the transaction but non persistent fields.
183      */

184     public abstract void clearTransactionNonPersistentFields();
185
186     /**
187      * <p>This return a deep clone of this state instance with only fields that
188      * must be sent to the server to persist changes to this instance filled
189      * in. For JdbcDataStore this will include only the dirty fields. For
190      * VdsDataStore this includes all fields so the whole DataStoreObject
191      * can be written.</p>
192      * <p/>
193      * <p>All 'First Class Objects' will be resolved to an OID and
194      * 'Second Class Objects' will be resolved to some serializable/storable
195      * format that represents the state of the field.</p>
196      *
197      * @return True if some fields were written to stateToStore and false if
198      * not (i.e. we have no dirty fields)
199      */

200     public abstract boolean fillToStoreState(State stateToStore,
201             PersistenceContext sm,
202             VersantStateManager pcStateMan);
203
204     /**
205      * Fill dest with all of the fake and ref fields of this State. This is used
206      * for stores that require the current values of fake fields to be sent when
207      * fetching certain fields (e.g. fetching a Collection stored as an SCO
208      * in VDS). The ref fields are converted into OIDs if they are pc.
209      */

210     public abstract void fillForRead(State dest,
211             VersantPersistenceManagerImp sm);
212
213     /**
214      * Make a shallow copy of the state.
215      *
216      * @return
217      */

218     public abstract State getCopy();
219
220     /**
221      * This must copy the fields from the supplied to the current state. The copied
222      * fields is used for to compare against to detect concurrent updates.
223      *
224      * @param state
225      * @param sm
226      */

227     public abstract void copyFieldsForOptimisticLocking(State state,
228             VersantPersistenceManagerImp sm);
229
230     /**
231      * This copies the optimistic locking field if not already set.
232      * @param state
233      */

234     public abstract void copyOptimisticLockingField(State state);
235
236     /**
237      * This will replace all fields that should be a SCO field with it's SCO implementation.
238      * This is used for retain values where the client has set a field that must be a sco field and
239      * this must be converted after commit.
240      */

241     public abstract int replaceSCOFields(PersistenceCapable owner,
242             VersantPersistenceManagerImp sm,
243             int[] absFieldNos);
244
245
246
247
248     /**
249      * Called when the pc instance is made transient to unset the sco instance of
250      * the pc owner.
251      */

252     public abstract void unmanageSCOFields();
253
254     /**
255      */

256     public abstract void addRefs(VersantPersistenceManagerImp sm, PCStateMan pcStateMan);
257
258     /**
259      * Clear the state of all its fields and reset it to notFilled.
260      */

261     public abstract void clear();
262
263     /**
264      * Reset the filled flag for each field.
265      */

266     public abstract void clearFilledFlags();
267
268     /**
269      * Reset the dirty status of the state and its fields.
270      */

271     public abstract void makeClean();
272
273     /**
274      * Set the meta data for this State. If this is stored in a field it
275      * must be transient. This will be called again when saving so there
276      * is no need to trundle it back and forth.
277      */

278     public abstract void setClassMetaData(ClassMetaData cmd);
279
280     /**
281      * Return the ClassMetaData.
282      */

283     public abstract ClassMetaData getClassMetaData();
284
285     /**
286      * Return true if the value for this stateFieldNo is valid i.e. it has been
287      * read from the data store or set by a client etc etc.
288      */

289     public abstract boolean containsField(int stateFieldNo);
290
291     /**
292      * Return true if the value for this absFieldNo is valid i.e. it has been
293      * read from the data store or set by a client etc etc.
294      */

295     public abstract boolean containsFieldAbs(int absFieldNo);
296
297     /**
298      * Check if the state contains the specified stateFieldNos.
299      */

300     public abstract boolean containFields(int[] stateFieldNos);
301
302     /**
303      * Check if the state contains the specified absFieldNos.
304      */

305     public abstract boolean containFieldsAbs(int[] absFieldNos);
306
307     /**
308      * Check if the state holds any values.
309      */

310     public abstract boolean isEmpty();
311
312     /**
313      * Return true if all the fields defined in the specified fetch group
314      * are filled in.
315      */

316     public abstract boolean containsFetchGroup(FetchGroup fetchGroup);
317
318     /**
319      * Put the numbers of all fields we have into buf. The number of field
320      * numbers stored is returned.
321      */

322     public abstract int getFieldNos(int[] buf);
323
324     /**
325      * Put the numbers of all pass 1 fields we have into buf. The number of
326      * field numbers stored is returned.
327      *
328      * @see FieldMetaData#secondaryField
329      * @see ClassMetaData#pass2Fields
330      */

331     public abstract int getPass1FieldNos(int[] buf);
332
333     /**
334      * Fill the array with the stateFieldNo of reference fields that contain
335      * NewOid's.
336      */

337     public abstract int getPass1FieldRefFieldNosWithNewOids(
338             int[] stateFieldNoBuf);
339
340     /**
341      * Put the numbers of all pass 2 fields we have into buf. The number of
342      * field numbers stored is returned.
343      *
344      * @see FieldMetaData#secondaryField
345      * @see ClassMetaData#pass2Fields
346      */

347     public abstract int getPass2FieldNos(int[] buf);
348
349     /**
350      * Do we contain any pass 1 fields?
351      *
352      * @see FieldMetaData#secondaryField
353      * @see ClassMetaData#pass2Fields
354      */

355     public abstract boolean containsPass1Fields();
356
357     /**
358      * Do we contain any pass 2 fields?
359      *
360      * @see FieldMetaData#secondaryField
361      * @see ClassMetaData#pass2Fields
362      */

363     public abstract boolean containsPass2Fields();
364
365     /**
366      * Return 0 if state has the same field numbers as us, less than 0 we are
367      * less than it or greater than 0 if we are greater than it. The definition
368      * of less than and greater than is up to the state implementation but
369      * must be detirministic. For fields that are stored using Oracle style
370      * LOBs then the nullness of the value must also be considered in the
371      * comparison i.e. states with field x null and not null respectively
372      * are different.
373      *
374      * @param state State to compare to (will be for same class)
375      */

376     public abstract int compareToPass1(State state);
377
378     /**
379      * Does this State contain exactly the same fields as the supplied State?
380      *
381      * @param state State to compare to (will be for same class)
382      */

383     public abstract boolean hasSameFields(State state);
384
385     /**
386      * Is the supplied stateFieldNo null?
387      */

388     public abstract boolean isNull(int stateFieldNo);
389
390     /**
391      * Does this State contain all of the application identity fields for
392      * its class? This returns false if the class does not use application
393      * identity.
394      */

395     public abstract boolean containsApplicationIdentityFields();
396
397     /**
398      * Does this State contain all of the application identity fields for
399      * its class with values different to a default instance of the application
400      * identity class? This returns false if the class does not use application
401      * identity.
402      */

403     public abstract boolean containsValidAppIdFields();
404
405     /**
406      * Clear any application identity fields from this State. This is a NOP
407      * if the class does not use application identity.
408      */

409     public abstract void clearApplicationIdentityFields();
410
411     /**
412      * Populate the primary key fields from the OID. This is only called
413      * for PC classes that are using application identity.
414      */

415     public abstract void copyFields(OID oid);
416
417     /**
418      * Replace any NewObjectOID's in fields in fieldNos in this state with
419      * their realOID's. Entries in fieldNos that are less than 0 should be
420      * skipped. Note that skipped entries will never be for fields that could
421      * hold OIDs.
422      */

423     public abstract boolean replaceNewObjectOIDs(int[] fieldNos,
424             int fieldNosLength);
425
426     /**
427      * Add the graph indexes of all OIDs that we have direct references to
428      * (e.g. foreign keys) to edges. This is called as part of the graph
429      * sorting process.
430      *
431      * @see PersistGraph#sort
432      */

433     public abstract void findDirectEdges(OIDGraph graph,
434             IntArray edges);
435
436     /**
437      * Update all autoset fields that must be set on commit of a new JDO
438      * instance.
439      *
440      * @see FieldMetaData#autoSet
441      */

442     public abstract void updateAutoSetFieldsCreated(Date now);
443
444     /**
445      * Update all autoset fields that must be set on commit of modifications
446      * to an existing JDO instance.
447      *
448      * @param oldState The pre-modification state of the instance.
449      * @see FieldMetaData#autoSet
450      */

451     public abstract void updateAutoSetFieldsModified(Date now, State oldState);
452
453     /**
454      * Populate the OID from this state. This is called for classes
455      * using application identity when a new object is persisted. It will
456      * not be called otherwise.
457      */

458     public abstract void copyKeyFields(OID oid);
459
460     /**
461      * Check to see if the state contains the same id field as the oid. The oid
462      * that is passed in is filled correctly.
463      */

464     public abstract boolean checkKeyFields(OID oid);
465
466     /**
467      * Populate the OID from this state. This is called for classes
468      * using application identity when a primary key field of an existing
469      * object is updated. It will not be called otherwise. Note that if the
470      * primary key consists of multiple fields then those that have not
471      * changed may not be in state.
472      */

473     public abstract void copyKeyFieldsUpdate(OID oid);
474
475     /**
476      * Return the value for the field.
477      */

478     public abstract boolean getBooleanField(int stateFieldNo);
479
480     public abstract boolean getBooleanFieldAbs(int absFieldNo);
481
482     /**
483      * Return the value for the field.
484      */

485     public abstract char getCharField(int stateFieldNo);
486
487     public abstract char getCharFieldAbs(int absFieldNo);
488
489     /**
490      * Return the value for the field.
491      */

492     public abstract byte getByteField(int stateFieldNo);
493
494     public abstract byte getByteFieldAbs(int absFieldNo);
495
496     /**
497      * Return the value for the field.
498      */

499     public abstract short getShortField(int stateFieldNo);
500
501     public abstract short getShortFieldAbs(int absFieldNo);
502
503     /**
504      * Return the value for the field.
505      */

506     public abstract int getIntField(int stateFieldNo);
507
508     public abstract int getIntFieldAbs(int absFieldNo);
509
510     /**
511      * Return the value for the field.
512      */

513     public abstract long getLongField(int stateFieldNo);
514
515     public abstract long getLongFieldAbs(int absFieldNo);
516
517     /**
518      * Return the value for the field or 0L if it is not filled.
519      */

520     public abstract long getLongFieldInternal(int stateFieldNo);
521
522     /**
523      * Return the value for the field.
524      */

525     public abstract float getFloatField(int stateFieldNo);
526
527     public abstract float getFloatFieldAbs(int absFieldNo);
528
529     /**
530      * Return the value for the field.
531      */

532     public abstract double getDoubleField(int stateFieldNo);
533
534     public abstract double getDoubleFieldAbs(int absFieldNo);
535
536     /**
537      * Return the value for the field.
538      */

539     public abstract String JavaDoc getStringField(int stateFieldNo);
540
541     public abstract String JavaDoc getStringFieldAbs(int absFieldNo);
542
543     /**
544      * Return the value for the field.
545      */

546     public abstract Object JavaDoc getObjectField(int stateFieldNo,
547             PersistenceCapable owningPC, PersistenceContext pm,
548             OID oid);
549
550     public abstract Object JavaDoc getObjectFieldAbs(int absFieldNo,
551             PersistenceCapable owningPC, PersistenceContext pm,
552             OID oid);
553
554     /**
555      * Set the value of the field.
556      */

557     public abstract void setBooleanField(int stateFieldNo, boolean newValue);
558
559     public abstract void setBooleanFieldAbs(int absFieldNo, boolean newValue);
560
561     /**
562      * Set the value of the field.
563      */

564     public abstract void setCharField(int stateFieldNo, char newValue);
565
566     public abstract void setCharFieldAbs(int absFieldNo, char newValue);
567
568     /**
569      * Set the value of the field.
570      */

571     public abstract void setByteField(int stateFieldNo, byte newValue);
572
573     public abstract void setByteFieldAbs(int absFieldNo, byte newValue);
574
575     /**
576      * Set the value of the field.
577      */

578     public abstract void setShortField(int stateFieldNo, short newValue);
579
580     public abstract void setShortFieldAbs(int absFieldNo, short newValue);
581
582     /**
583      * Set the value of the field.
584      */

585     public abstract void setIntField(int stateFieldNo, int newValue);
586
587     public abstract void setIntFieldAbs(int absFieldNo, int newValue);
588
589     /**
590      * Set the value of the field.
591      */

592     public abstract void setLongField(int stateFieldNo, long newValue);
593
594     public abstract void setLongFieldAbs(int absFieldNo, long newValue);
595
596     /**
597      * Set the value of the field.
598      */

599     public abstract void setFloatField(int stateFieldNo, float newValue);
600
601     public abstract void setFloatFieldAbs(int absFieldNo, float newValue);
602
603     /**
604      * Set the value of the field.
605      */

606     public abstract void setDoubleField(int stateFieldNo, double newValue);
607
608     public abstract void setDoubleFieldAbs(int absFieldNo, double newValue);
609
610     /**
611      * Set the value of the field.
612      */

613     public abstract void setStringField(int stateFieldNo, String JavaDoc newValue);
614
615     public abstract void setStringFieldAbs(int absFieldNo, String JavaDoc newValue);
616
617     /**
618      * Set the value of the field.
619      */

620     public abstract void setObjectField(int stateFieldNo, Object JavaDoc newValue);
621
622     public abstract void setObjectFieldAbs(int absFieldNo, Object JavaDoc newValue);
623
624     public abstract void setObjectFieldUnresolved(int field, Object JavaDoc newValue);
625
626     public abstract void setObjectFieldUnresolvedAbs(int field,
627             Object JavaDoc newValue);
628
629 //==============================internal usage==================================
630

631     /**
632      * Return the internal value for the field.
633      */

634     public abstract Object JavaDoc getInternalObjectField(int field);
635
636     public abstract Object JavaDoc getInternalObjectFieldAbs(int field);
637
638     /**
639      * Set the value of the field internally.
640      */

641     public abstract void setInternalBooleanField(int field, boolean newValue);
642
643     public abstract void setInternalBooleanFieldAbs(int field,
644             boolean newValue);
645
646     /**
647      * Set the value of the field internally.
648      */

649     public abstract void setInternalCharField(int field, char newValue);
650
651     public abstract void setInternalCharFieldAbs(int field, char newValue);
652
653     /**
654      * Set the value of the field internally.
655      */

656     public abstract void setInternalByteField(int field, byte newValue);
657
658     public abstract void setInternalByteFieldAbs(int field, byte newValue);
659
660     /**
661      * Set the value of the field internally.
662      */

663     public abstract void setInternalShortField(int field, short newValue);
664
665     public abstract void setInternalShortFieldAbs(int field, short newValue);
666
667     /**
668      * Set the value of the field internally.
669      */

670     public abstract void setInternalIntField(int field, int newValue);
671
672     public abstract void setInternalIntFieldAbs(int field, int newValue);
673
674     /**
675      * Set the value of the field internally.
676      */

677     public abstract void setInternalLongField(int field, long newValue);
678
679     public abstract void setInternalLongFieldAbs(int field, long newValue);
680
681     /**
682      * Set the value of the field internally.
683      */

684     public abstract void setInternalFloatField(int field, float newValue);
685
686     public abstract void setInternalFloatFieldAbs(int field, float newValue);
687
688     /**
689      * Set the value of the field internally.
690      */

691     public abstract void setInternalDoubleField(int field, double newValue);
692
693     public abstract void setInternalDoubleFieldAbs(int field, double newValue);
694
695     /**
696      * Set the value of the field internally.
697      */

698     public abstract void setInternalStringField(int field, String JavaDoc newValue);
699
700     public abstract void setInternalStringFieldAbs(int field, String JavaDoc newValue);
701
702     /**
703      * Set the value of the field internally.
704      */

705     public abstract void setInternalObjectField(int field, Object JavaDoc newValue);
706
707     public abstract void setInternalObjectFieldAbs(int field, Object JavaDoc newValue);
708
709 // public void readExternal(ObjectInput in, JDOMetaData jmd,
710
// IntObjectHashMap map) throws IOException, ClassNotFoundException {
711
// }
712

713     public abstract String JavaDoc getVersion();
714
715     /**
716      * Add all states referenced by fields in fg to the dcs.
717      */

718     public void addFetchGroupStatesToDCS(FetchGroup fg, DetachStateContainer dcs,
719             VersantPersistenceManagerImp pm, OID oid, ClassMetaData cmd) {
720         // we need to check all fields that may reference other states and
721
// add those states to the dcs with the "nextFetchGroups" so they
722
// are checked in turn
723
FetchGroupField[] fields = fg.fields;
724         boolean defaultFG = fg == cmd.fetchGroups[0];
725         int length = fields.length;
726         for (int fieldNo = 0; fieldNo < length; fieldNo++) {
727             FetchGroupField field = fields[fieldNo];
728             FieldMetaData fmd = field.fmd;
729             if (fmd.fake) continue;
730             if (defaultFG && !fmd.isJDODefaultFetchGroup()) continue;
731             FetchGroup nextFetchGroup = field.nextFetchGroup;
732             FetchGroup nextKeyFetchGroup = field.nextKeyFetchGroup;
733             if (nextFetchGroup == null && nextKeyFetchGroup == null) continue;
734             int category = fmd.category;
735             int stateFieldNo;
736             Object JavaDoc o;
737             switch (category) {
738                 case MDStatics.CATEGORY_COLLECTION:
739                     o = getInternalObjectField(stateFieldNo = fmd.stateFieldNo);
740                     if (o != null) {
741                         if (isResolvedForClient(stateFieldNo)) {
742                             // TODO add method to SCOs to get data w/o iterator
743
for (Iterator i = ((Collection)o).iterator();
744                                  i.hasNext();) {
745                                 addPCToDCS(dcs, (PersistenceCapable)i.next(),
746                                         nextFetchGroup, pm);
747                             }
748                         } else {
749                             Object JavaDoc[] a = (Object JavaDoc[])o;
750                             int c = a.length;
751                             for (int i = 0; i < c; i++) {
752                                 Object JavaDoc object = a[i];
753                                 if (object == null) break;
754                                 addOIDToDCS(dcs, (OID)object, nextFetchGroup,
755                                         pm);
756                             }
757                         }
758                     }
759                     break;
760                 case MDStatics.CATEGORY_ARRAY:
761                     if (fmd.elementTypeMetaData != null) {
762                         o = getInternalObjectField(
763                                 stateFieldNo = fmd.stateFieldNo);
764                         if (o != null) {
765                             if (isResolvedForClient(stateFieldNo)) {
766                                 Object JavaDoc[] a = (Object JavaDoc[])o;
767                                 int c = a.length;
768                                 for (int i = 0; i < c; i++) {
769                                     Object JavaDoc object = a[i];
770                                     if (object != null) {
771                                         addPCToDCS(dcs, (PersistenceCapable)object,
772                                                 nextFetchGroup, pm);
773                                     }
774                                 }
775                             } else {
776                                 Object JavaDoc[] a = (Object JavaDoc[])o;
777                                 int c = a.length;
778                                 for (int i = 0; i < c; i++) {
779                                     Object JavaDoc object = a[i];
780                                     if (object != null) {
781                                         addOIDToDCS(dcs, (OID)object, nextFetchGroup,
782                                                 pm);
783                                     }
784                                 }
785                             }
786                         }
787                     }
788                     break;
789                 case MDStatics.CATEGORY_MAP:
790                     o = getInternalObjectField(stateFieldNo = fmd.stateFieldNo);
791                     if (o != null) {
792                         if (isResolvedForClient(stateFieldNo)) {
793                             // TODO add method to SCOs to get data w/o iterator
794
for (Iterator i = ((Map)o).entrySet().iterator();
795                                  i.hasNext();) {
796                                 Map.Entry e = (Map.Entry)i.next();
797                                 if (nextKeyFetchGroup != null) {
798                                     addPCToDCS(dcs, (PersistenceCapable)e.getKey(),
799                                             nextKeyFetchGroup, pm);
800                                 }
801                                 if (nextFetchGroup != null) {
802                                     addPCToDCS(dcs, (PersistenceCapable)e.getValue(),
803                                             nextFetchGroup, pm);
804                                 }
805                             }
806                         } else {
807                             MapEntries e = (MapEntries)o;
808                             if (nextKeyFetchGroup != null) {
809                                 Object JavaDoc[] a = e.keys;
810                                 int c = a.length;
811                                 for (int i = 0; i < c; i++) {
812                                     OID nextOid = (OID)a[i];
813                                     if (nextOid == null) break;
814                                     addOIDToDCS(dcs, nextOid,
815                                             nextKeyFetchGroup, pm);
816                                 }
817                             }
818                             if (nextFetchGroup != null) {
819                                 Object JavaDoc[] a = e.values;
820                                 int c = a.length;
821                                 for (int i = 0; i < c; i++) {
822                                     OID nextOid = (OID)a[i];
823                                     if (nextOid == null) break;
824                                     addOIDToDCS(dcs, nextOid, nextFetchGroup,
825                                             pm);
826                                 }
827                             }
828                         }
829                     }
830                     break;
831                 case MDStatics.CATEGORY_REF:
832                 case MDStatics.CATEGORY_POLYREF:
833                     o = getInternalObjectField(stateFieldNo = fmd.stateFieldNo);
834                     if (o != null) {
835                         if (isResolvedForClient(stateFieldNo)) {
836                             addPCToDCS(dcs, (PersistenceCapable)o,
837                                     nextFetchGroup, pm);
838                         } else {
839                             OID nextOid = (OID)o;
840                             if (nextOid != null) {
841                                 addOIDToDCS(dcs, nextOid, nextFetchGroup, pm);
842                             }
843                         }
844                     }
845                     break;
846             }
847         }
848     }
849
850     /**
851      * Get the state for the oid from the local cache (if any). Add the oid
852      * and state to the dcs. This does not check if it is already present.
853      */

854     private void addOIDToDCS(DetachStateContainer dcs, OID oid,
855             FetchGroup nextFetchGroup, VersantPersistenceManagerImp pm) {
856         State ns = pm.getCache().getStateByOID(oid);
857         dcs.add(oid, ns, nextFetchGroup);
858         // it is ok if ns is null as it will be fetched later
859
}
860
861     /**
862      * Add the state for the pc and its oid to dcs. This is a NOP if the oid
863      * is already present.
864      */

865     private void addPCToDCS(DetachStateContainer dcs, PersistenceCapable pc,
866             FetchGroup nextFetchGroup, VersantPersistenceManagerImp pm) {
867         PCStateMan internalSM = pm.getInternalSM(pc);
868         dcs.add(internalSM.oid, internalSM.state, nextFetchGroup);
869         // dcs.add will do nothing if the oid is already present
870
}
871
872     public Object JavaDoc resolveArrayOIDs(Object JavaDoc[] oids,
873             PersistenceContext sm, Class JavaDoc type) {
874         Object JavaDoc[] vals = (Object JavaDoc[])Array.newInstance(type, oids.length);
875         for (int i = 0; i < vals.length; i++) {
876             if (oids[i] != null) {
877                 vals[i] = sm.getObjectById(oids[i], false);
878             }
879         }
880         return vals;
881     }
882
883     public Object JavaDoc resolveArrayValues(Object JavaDoc vals[],
884             PersistenceContext pm) {
885         OID oids[] = new OID[vals.length];
886         for (int i = 0; i < oids.length; i++) {
887             if (vals[i] != null) {
888                 oids[i] = pm.getInternalOID((PersistenceCapable)vals[i]);
889             }
890         }
891
892         return oids;
893     }
894
895     /**
896      * Is this state field nummber resolved for the Client
897      */

898     public abstract boolean isResolvedForClient(int stateFieldNo);
899
900     /**
901      * The value of the version field on the pc.
902      * This will return null if there are no version fields.
903      */

904     public abstract Object JavaDoc getOptimisticLockingValue();
905
906     /**
907      * Mark field as filled.
908      */

909     public abstract void setFilled(int stateFieldNo);
910
911     /**
912      * Add the values of any non-null reference fields used as back or inverse
913      * fields for unmanaged one-to-many collections for eviction from the L2
914      * cache on commit. Note that the filled status of the field is not
915      * checked. This method is called only for newly managed instances so
916      * all fields will be filled.
917      */

918     public abstract void addOneToManyInverseFieldsForL2Evict(
919             VersantPersistenceManagerImp pm);
920
921
922
923     /**
924      * If the data of this state may be used to update the cache.
925      */

926     public boolean isCacheble() {
927         return true;
928     }
929     
930     /**
931      * Find the graph indexes of all the OIDs directly referenced by fieldNo
932      * and add them to edges. Any referenced OIDs that are not in the graph
933      * should be ignored.
934      */

935     protected void findDirectEdges(OIDGraph graph, ClassMetaData cmd,
936             int fieldNo, State state, IntArray edges) {
937         OID oid = (OID)state.getInternalObjectField(fieldNo);
938         if (oid == null) return;
939         int index = graph.indexOf(oid);
940         if (index >= 0) edges.add(index);
941     }
942
943     /**
944      * Is the field null or zero?
945      */

946     public abstract boolean isFieldNullorZero(int stateFieldNo);
947
948     /**
949      * Our version of writeExternal for serialization.
950      */

951     public abstract void writeExternal(OIDObjectOutput os) throws IOException JavaDoc;
952
953     /**
954      * Our version of readExternal for serialization.
955      */

956     public abstract void readExternal(OIDObjectInput is)
957             throws IOException JavaDoc, ClassNotFoundException JavaDoc;
958
959 }
960
Popular Tags