KickJava   Java API By Example, From Geeks To Geeks.

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


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.sco.VersantSimpleSCO;
15 import com.versant.core.jdo.*;
16 import com.versant.core.metadata.*;
17 import com.versant.core.server.OIDGraph;
18 import com.versant.core.util.IntArray;
19 import com.versant.core.util.OIDObjectOutput;
20 import com.versant.core.util.OIDObjectInput;
21
22 import javax.jdo.spi.PersistenceCapable;
23 import java.io.*;
24 import java.util.*;
25
26 /**
27  * This is a State implementation suitable for use with any PC class. It is
28  * intended for use during development when the State class generating code is
29  * broken. The meta data OID factory method can just return these for all
30  * PC classes. Performance is not important for this class as it will not
31  * be used in a production release.
32  */

33 public class GenericState extends State {
34
35     protected transient ClassMetaData cmd;
36
37     /**
38      * The JDBC tests set this flag to disable the checkFilled calls on
39      * getString etc.
40      */

41     public static boolean RUNNING_JDBC_TESTS = false;
42
43     /**
44      * This holds the data for all of the persistent fields and any extra
45      * data required for a particular store. The persistent fields are
46      * stored first in fieldNo order (i.e. alphabetically) followed by
47      * the store defined values (if any).
48      */

49     protected Object JavaDoc[] data;
50     /**
51      * Each field or extra store value that has a valid entry in data has a
52      * flag set here.
53      */

54     protected boolean[] filled;
55
56     /**
57      * Keeps track of dirty fields. This is the result of all setXXX methods. The
58      * setInternalXXX method does not change the status to dirty. This is only
59      * used on the client side.
60      */

61     protected transient boolean[] dirtyFields;
62     /**
63      * Keeps tracks of which fields have been resolved for client side usage. eg
64      * ensure that an oid field is resolved to the actual PersistantCapable instance.
65      */

66     protected transient boolean[] resolvedForClient;
67
68     /**
69      * A global indication if this state has any dirty fields.
70      */

71     protected boolean dirty;
72
73     /**
74      * The index of the persistant class.
75      */

76     protected int classIndex;
77
78     public GenericState() {
79     }
80
81     public GenericState(ClassMetaData cmd) {
82         this.cmd = cmd;
83         classIndex = cmd.index;
84         int n = cmd.superFieldCount + cmd.fields.length;
85         data = new Object JavaDoc[n];
86         filled = new boolean[n];
87     }
88
89     /**
90      * Return a new State instance
91      *
92      * @return new State instance
93      */

94     public State newInstance() {
95         return new GenericState(cmd);
96     }
97
98     /**
99      * Return the index of our PC class in the meta data. Do not use this
100      * to get the meta data for our class. Call getClassMetaData instead.
101      *
102      * @see ModelMetaData#classes
103      * @see #getClassMetaData
104      */

105     public int getClassIndex() {
106         return classIndex;
107     }
108
109     private final int convertAbsToState(int managedFieldNo) {
110         return cmd.managedFields[managedFieldNo].stateFieldNo;
111     }
112
113     /**
114      * Get the meta data for our class.
115      *
116      * @param jmd The meta data we belong to
117      */

118     public ClassMetaData getClassMetaData(ModelMetaData jmd) {
119         return jmd.classes[classIndex];
120     }
121
122     public void setClassMetaData(ClassMetaData cmd) {
123         this.cmd = cmd;
124         int n = cmd.superFieldCount + cmd.fields.length;
125         dirtyFields = new boolean[n];
126         resolvedForClient = new boolean[n];
127     }
128
129     public ClassMetaData getClassMetaData() {
130         return cmd;
131     }
132
133     public boolean containsField(int stateFieldNo) {
134         return filled[stateFieldNo];
135     }
136
137     public boolean containsFieldAbs(int absFieldNo) {
138         return containsField(convertAbsToState(absFieldNo));
139     }
140
141     public boolean containFields(int[] stateFieldNos) {
142         for (int i = 0; i < stateFieldNos.length; i++) {
143             if (!filled[stateFieldNos[i]]) return false;
144         }
145         return true;
146     }
147
148     public boolean containFieldsAbs(int[] absFieldNos) {
149         int[] stateFieldNos = new int[absFieldNos.length];
150         for (int i = 0; i < absFieldNos.length; i++) {
151             stateFieldNos[i] = convertAbsToState(absFieldNos[i]);
152         }
153         return containFields(stateFieldNos);
154     }
155
156     public boolean isEmpty() {
157         for (int i = 0; i < filled.length; i++) {
158             if (filled[i]) return false;
159         }
160         return true;
161     }
162
163     public boolean containsFetchGroup(FetchGroup fetchGroup) {
164         while (fetchGroup != null) {
165             int[] fgn = fetchGroup.stateFieldNos;
166             for (int i = fgn.length - 1; i >= 0; i--) {
167                 if (!containsField(fgn[i])) {
168                     return false;
169                 }
170             }
171             fetchGroup = fetchGroup.superFetchGroup;
172         }
173         return true;
174     }
175
176     /**
177      * Put the stateField numbers of all fields we have into stateFieldNoBuf. The number of field
178      * numbers stored is returned.
179      */

180     public int getFieldNos(int[] stateFieldNoBuf) {
181         int c = 0;
182         for (int i = 0; i < filled.length; i++) {
183             if (filled[i]) stateFieldNoBuf[c++] = i;
184         }
185         return c;
186     }
187
188     /**
189      * Put the stateField numbers of all pass 1 fields we have into stateFieldNoBuf. The number of
190      * field numbers stored is returned.
191      *
192      * @see FieldMetaData#secondaryField
193      * @see ClassMetaData#pass2Fields
194      */

195     public int getPass1FieldNos(int[] stateFieldNoBuf) {
196         int c = 0;
197         for (int i = 0; i < filled.length; i++) {
198             if (filled[i] && cmd.stateFields[i].primaryField) stateFieldNoBuf[c++] = i;
199         }
200         return c;
201     }
202
203     public int getPass1FieldRefFieldNosWithNewOids(int[] stateFieldNoBuf) {
204         int c = 0;
205         for (int i = 0; i < filled.length; i++) {
206             if (filled[i] && cmd.stateFields[i].primaryField
207                     && (cmd.stateFields[i].category == MDStatics.CATEGORY_REF
208                     || cmd.stateFields[i].category == MDStatics.CATEGORY_POLYREF))
209                 stateFieldNoBuf[c++] = i;
210         }
211         return c;
212     }
213
214     /**
215      * Put the stateField numbers of all pass 2 fields we have into stateFieldNoBuf. The number of
216      * field numbers stored is returned.
217      *
218      * @see FieldMetaData#secondaryField
219      * @see ClassMetaData#pass2Fields
220      */

221     public int getPass2FieldNos(int[] stateFieldNoBuf) {
222         checkCmd();
223         int c = 0;
224         for (int i = 0; i < filled.length; i++) {
225             if (filled[i] && cmd.stateFields[i].secondaryField) stateFieldNoBuf[c++] = i;
226         }
227         return c;
228     }
229
230     /**
231      * Do we contain any pass 1 fields?
232      *
233      * @see FieldMetaData#secondaryField
234      * @see ClassMetaData#pass2Fields
235      */

236     public boolean containsPass1Fields() {
237         checkCmd();
238         for (int i = 0; i < filled.length; i++) {
239             if (filled[i] && cmd.stateFields[i].primaryField) return true;
240         }
241         return false;
242     }
243
244     /**
245      * Do we contain any pass 2 fields?
246      *
247      * @see FieldMetaData#secondaryField
248      * @see ClassMetaData#pass2Fields
249      */

250     public boolean containsPass2Fields() {
251         checkCmd();
252         for (int i = 0; i < filled.length; i++) {
253             if (filled[i] && cmd.stateFields[i].secondaryField) return true;
254         }
255         return false;
256     }
257
258     /**
259      * Return 0 if state has the same field numbers as us, less than 0 we are
260      * less than it or greater than 0 if we are greater than it. The definition
261      * of less than and greater than is up to the state implementation but
262      * must be detirministic. For fields that are stored using Oracle style
263      * LOBs then the nullness of the value must also be considered in the
264      * comparison i.e. states with field x null and not null respectively
265      * are different.
266      *
267      * @param state State to compare to (will be for same class)
268      */

269     public int compareToPass1(State state) {
270         GenericState s = (GenericState)state;
271         checkCmd();
272         boolean[] sf = s.filled;
273         for (int i = 0; i < filled.length; i++) {
274             if (!cmd.stateFields[i].primaryField) continue;
275             boolean a = filled[i];
276             boolean b = sf[i];
277             if (a && !b) return -1;
278             if (!a && b) return +1;
279         }
280         return 0;
281     }
282
283     public void clear() {
284         data = new Object JavaDoc[data.length];
285         filled = new boolean[filled.length];
286         makeClean();
287         if (resolvedForClient != null) {
288             resolvedForClient = new boolean[resolvedForClient.length];
289         }
290     }
291
292     public void clearFilledFlags() {
293         filled = new boolean[filled.length];
294     }
295
296     public void makeClean() {
297         Arrays.fill(dirtyFields, false);
298         dirty = false;
299     }
300
301     public void clearNonFilled(State state) {
302         GenericState gState = (GenericState)state;
303         boolean[] localFilled = gState.filled;
304         for (int i = localFilled.length - 1; i >= 0; i--) {
305             if (!localFilled[i] && (cmd.stateFields[i].autoSet == MDStatics.AUTOSET_NO)) {
306                 data[i] = null;
307                 filled[i] = false;
308                 resolvedForClient[i] = false;
309             }
310         }
311     }
312
313     public void clearCollectionFields() {
314         checkCmd();
315         for (int i = 0; i < data.length; i++) {
316             int category = cmd.stateFields[i].category;
317             if (category == MDStatics.CATEGORY_COLLECTION
318                     || category == MDStatics.CATEGORY_MAP
319                     || category == MDStatics.CATEGORY_ARRAY) {
320                 data[i] = null;
321                 filled[i] = false;
322                 if (resolvedForClient != null) resolvedForClient[i] = false;
323             }
324         }
325     }
326
327     public void clearSCOFields() {
328         checkCmd();
329         for (int i = 0; i < cmd.scoFieldNos.length; i++) {
330             int scoFieldNo = cmd.scoFieldNos[i];
331             data[scoFieldNo] = null;
332             filled[scoFieldNo] = false;
333             resolvedForClient[scoFieldNo] = false;
334         }
335     }
336
337     public final void clearTransactionNonPersistentFields() {
338         checkCmd();
339         final int n = cmd.txFieldNos.length;
340         for (int i = 0; i < n; i++) {
341             dirtyFields[cmd.txFieldNos[i]] = false;
342         }
343     }
344
345     /**
346      * Does this State contain exactly the same fields as the supplied State?
347      *
348      * @param state State to compare to (will be for same class)
349      */

350     public boolean hasSameFields(State state) {
351         GenericState s = (GenericState)state;
352         int n = filled.length;
353         int i;
354         for (i = 0; i < n && filled[i] == s.filled[i]; i++) ;
355         return i == n;
356     }
357
358     /**
359      * Is the supplied stateFieldNo null?
360      */

361     public boolean isNull(int stateFieldNo) {
362         return data[stateFieldNo] == null;
363     }
364
365     /**
366      * Does this State contain all of the application identity fields for
367      * its class? This returns false if the class does not use application
368      * identity.
369      */

370     public boolean containsApplicationIdentityFields() {
371         checkCmd();
372         if (cmd.identityType != MDStatics.IDENTITY_TYPE_APPLICATION) return false;
373         FieldMetaData[] pkf = cmd.pcHeirachy[0].pkFields;
374         for (int i = pkf.length - 1; i >= 0; i--) {
375             if (!containsField(pkf[i].stateFieldNo)) return false;
376         }
377         return true;
378     }
379
380     public boolean containsValidAppIdFields() {
381         checkCmd();
382         if (cmd.identityType != MDStatics.IDENTITY_TYPE_APPLICATION) return false;
383         FieldMetaData[] pkf = cmd.pcHeirachy[0].pkFields;
384         for (int i = pkf.length - 1; i >= 0; i--) {
385             if (!containsField(pkf[i].stateFieldNo)) return false;
386             if (data[pkf[i].stateFieldNo] == null) return false;
387             if (data[pkf[i].stateFieldNo].equals(pkf[i].getPKDefaultValue())) return false;
388         }
389         return true;
390     }
391
392     /**
393      * Clear any application identity fields from this State. This is a NOP
394      * if the class does not use application identity.
395      */

396     public void clearApplicationIdentityFields() {
397         checkCmd();
398         if (cmd.top.identityType != MDStatics.IDENTITY_TYPE_APPLICATION) return;
399         FieldMetaData[] pkf = cmd.top.pkFields;
400         for (int i = pkf.length - 1; i >= 0; i--) {
401             data[pkf[i].stateFieldNo] = null;
402             filled[pkf[i].stateFieldNo] = false;
403         }
404     }
405
406     /**
407      * Populate the primary key fields from the OID. This is only called
408      * for PC classes that are using application identity.
409      */

410     public void copyFields(OID oid) {
411         checkCmd();
412         if (cmd.identityType != MDStatics.IDENTITY_TYPE_APPLICATION) return;
413         GenericOID goid = (GenericOID)oid;
414         Object JavaDoc[] pk = goid.getPk();
415         FieldMetaData[] pkFields = cmd.pcHeirachy[0].pkFields;
416         for (int i = 0; i < pk.length; i++) {
417             data[pkFields[i].stateFieldNo] = pk[i];
418             filled[pkFields[i].stateFieldNo] = true;
419         }
420     }
421
422     /**
423      * Replace any NewObjectOID's in fields in fieldNos in this state with
424      * their realOID's. Entries in fieldNos that are less than 0 should be
425      * skipped. Note that skipped entries will never be for fields that could
426      * hold OIDs.
427      */

428     public boolean replaceNewObjectOIDs(int[] fieldNos, int fieldNosLength) {
429         boolean containsUnResolvedNewOids = false;
430         for (int i = 0; i < fieldNosLength; i++) {
431             int fieldNo = fieldNos[i];
432             if (fieldNo >= 0) {
433                 FieldMetaData fmd = cmd.stateFields[fieldNo];
434                 Object JavaDoc o;
435                 switch (fmd.category) {
436                     case MDStatics.CATEGORY_REF:
437                     case MDStatics.CATEGORY_POLYREF:
438                         o = data[fieldNo];
439                         if (o != null && o instanceof NewObjectOID) {
440                             if (((NewObjectOID)o).realOID == null) {
441                                 containsUnResolvedNewOids = true;
442                             } else {
443                                 data[fieldNo] = ((NewObjectOID)o).realOID;
444                             }
445                         }
446                         break;
447                 }
448             }
449         }
450         return containsUnResolvedNewOids;
451     }
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 void copyKeyFields(OID oid) {
459         GenericOID gOid = (GenericOID)oid;
460         Object JavaDoc[] pk = gOid.getPk();
461         FieldMetaData[] pkFields = cmd.pkFields;
462         for (int i = 0; i < pk.length; i++) {
463             pk[i] = getInternalObjectField(pkFields[i].stateFieldNo);
464         }
465     }
466
467     public boolean checkKeyFields(OID oid) {
468         GenericOID gOid = (GenericOID)oid;
469         Object JavaDoc[] pk = gOid.getPk();
470         for (int i = 0; i < pk.length; i++) {
471             if (!pk[i].equals(
472                     getInternalObjectField(cmd.pkFields[i].stateFieldNo))) {
473                 return false;
474             }
475         }
476         return true;
477     }
478
479     /**
480      * Populate the OID from this state. This is called for classes
481      * using application identity when a primary key field of an existing
482      * object is updated. It will not be called otherwise. Note that if the
483      * primary key consists of multiple fields then those that have not
484      * changed may not be in state.
485      */

486     public void copyKeyFieldsUpdate(OID oid) {
487         GenericOID gOid = (GenericOID)oid;
488         Object JavaDoc[] pk = gOid.getPk();
489         FieldMetaData[] pkFields = cmd.pkFields;
490         for (int i = 0; i < pk.length; i++) {
491             int fieldNo = pkFields[i].stateFieldNo;
492             if (containsField(fieldNo)) {
493                 pk[i] = getInternalObjectField(fieldNo);
494             }
495         }
496     }
497
498     /**
499      * Add the graph indexes of all OIDs that we have direct references to
500      * (e.g. foreign keys) to edges. This is called as part of the graph
501      * sorting process.
502      *
503      * @see com.versant.core.server.PersistGraph#sort
504      */

505     public void findDirectEdges(OIDGraph graph,
506             IntArray edges) {
507         int[] fieldNos = cmd.directRefStateFieldNos;
508         int n = fieldNos.length;
509         for (int i = 0; i < n; i++) {
510             int fieldNo = fieldNos[i];
511             if (!containsField(fieldNo)) continue;
512             findDirectEdges(graph, cmd, fieldNo, this, edges);
513         }
514     }
515
516     /**
517      * Update all autoset fields that must be set on commit of a new JDO
518      * instance.
519      *
520      * @see FieldMetaData#autoSet
521      */

522     public void updateAutoSetFieldsCreated(Date now) {
523         if (!cmd.hasAutoSetFields) return;
524         FieldMetaData[] stateFields = cmd.stateFields;
525         for (int i = stateFields.length - 1; i >= 0; i--) {
526             FieldMetaData fmd = cmd.stateFields[i];
527             int autoset = fmd.autoSet;
528             if (autoset != MDStatics.AUTOSET_CREATED
529                     && autoset != MDStatics.AUTOSET_BOTH) {
530                 continue;
531             }
532             switch (fmd.typeCode) {
533                 case MDStatics.DATE:
534                     setInternalObjectField(i, now);
535                     break;
536                     
537                 case MDStatics.INT:
538                     setInternalIntField(i, 1);
539                     break;
540                 case MDStatics.SHORT:
541                     setInternalShortField(i, (short)1);
542                     break;
543                 case MDStatics.BYTE:
544                     setInternalByteField(i, (byte)1);
545                     break;
546                 default:
547                     throw BindingSupportImpl.getInstance().internal("Invalid typeCode " + fmd.typeCode +
548                             " for autoset field: stateFieldNo " + i +
549                             " " + fmd.name);
550             }
551         }
552     }
553
554     /**
555      * Update all autoset fields that must be set on commit of modifications
556      * to an existing JDO instance.
557      *
558      * @param oldState The pre-modification state of the instance.
559      * @see FieldMetaData#autoSet
560      */

561     public void updateAutoSetFieldsModified(Date now, State oldState) {
562         if (!cmd.hasAutoSetFields) return;
563         FieldMetaData[] stateFields = cmd.stateFields;
564         for (int i = stateFields.length - 1; i >= 0; i--) {
565             FieldMetaData fmd = cmd.stateFields[i];
566             int autoset = fmd.autoSet;
567             if (autoset != MDStatics.AUTOSET_MODIFIED
568                     && autoset != MDStatics.AUTOSET_BOTH) {
569                 continue;
570             }
571             // carl leave this check out of the generated State class
572
if (fmd.typeCode != MDStatics.DATE && !oldState.containsField(i)) {
573                 throw BindingSupportImpl.getInstance().internal("oldState does not contain version field: " +
574                         "stateFieldNo " + i + " " + fmd.name);
575             }
576             switch (fmd.typeCode) {
577                 case MDStatics.DATE:
578                     setInternalObjectField(i, now);
579                     break;
580                       
581                 case MDStatics.INT:
582                     setInternalIntField(i,
583                             (oldState.getIntField(i) + 1) & 0x7FFFFFFF);
584                     break;
585                 case MDStatics.SHORT:
586                     setInternalShortField(i, (short)
587                             ((oldState.getShortField(i) + 1) & 0x7FFF));
588                     break;
589                 case MDStatics.BYTE:
590                     setInternalByteField(i, (byte)
591                             ((oldState.getByteField(i) + 1) & 0x7F));
592                     break;
593                 default:
594                     throw BindingSupportImpl.getInstance().internal("Invalid typeCode " + fmd.typeCode +
595                             " for autoset field: stateFieldNo " + i +
596                             " " + fmd.name);
597             }
598         }
599     }
600
601     public boolean getBooleanField(int stateFieldNo) {
602         return data[stateFieldNo] != null ? ((Boolean JavaDoc)data[stateFieldNo]).booleanValue() : false;
603     }
604
605     public boolean getBooleanFieldAbs(int field) {
606         return getBooleanField(convertAbsToState(field));
607     }
608
609     public char getCharField(int stateFieldNo) {
610         return data[stateFieldNo] != null ? ((Character JavaDoc)data[stateFieldNo]).charValue() : '0';
611     }
612
613     public char getCharFieldAbs(int field) {
614         return getCharField(convertAbsToState(field));
615     }
616
617     public byte getByteField(int stateFieldNo) {
618         return data[stateFieldNo] != null ? ((Byte JavaDoc)data[stateFieldNo]).byteValue() : (byte)0;
619     }
620
621     public byte getByteFieldAbs(int field) {
622         return getByteField(convertAbsToState(field));
623     }
624
625     public short getShortField(int stateFieldNo) {
626         return data[stateFieldNo] != null ? ((Short JavaDoc)data[stateFieldNo]).shortValue() : (short)0;
627     }
628
629     public short getShortFieldAbs(int field) {
630         return getShortField(convertAbsToState(field));
631     }
632
633     public int getIntField(int stateFieldNo) {
634         return data[stateFieldNo] != null ? ((Integer JavaDoc)data[stateFieldNo]).intValue() : 0;
635     }
636
637     public int getIntFieldAbs(int field) {
638         return getIntField(convertAbsToState(field));
639     }
640
641     public long getLongField(int stateFieldNo) {
642         return data[stateFieldNo] != null ? ((Long JavaDoc)data[stateFieldNo]).longValue() : 0;
643     }
644
645     public long getLongFieldInternal(int stateFieldNo) {
646         return data[stateFieldNo] != null ? ((Long JavaDoc)data[stateFieldNo]).longValue() : 0;
647     }
648
649     public long getLongFieldAbs(int field) {
650         return getLongField(convertAbsToState(field));
651     }
652
653     public float getFloatField(int stateFieldNo) {
654         return data[stateFieldNo] != null ? ((Float JavaDoc)data[stateFieldNo]).floatValue() : 0;
655     }
656
657     public float getFloatFieldAbs(int field) {
658         return getFloatField(convertAbsToState(field));
659     }
660
661     public double getDoubleField(int stateFieldNo) {
662         return data[stateFieldNo] != null ? ((Double JavaDoc)data[stateFieldNo]).doubleValue() : 0;
663     }
664
665     public double getDoubleFieldAbs(int field) {
666         return getDoubleField(convertAbsToState(field));
667     }
668
669     public String JavaDoc getStringField(int stateFieldNo) {
670         return (String JavaDoc)data[stateFieldNo];
671     }
672
673     public String JavaDoc getStringFieldAbs(int field) {
674         return getStringField(convertAbsToState(field));
675     }
676
677     public Object JavaDoc getObjectField(int stateFieldNo, PersistenceCapable owningPC,
678             PersistenceContext pm, OID oid) {
679         Object JavaDoc o = data[stateFieldNo];
680         if (!resolvedForClient[stateFieldNo]) {
681             if (o != null) {
682                 FieldMetaData fmd = cmd.stateFields[stateFieldNo];
683                 if (fmd.scoField) {
684                     if (fmd.category == MDStatics.CATEGORY_ARRAY) {
685                         if (fmd.elementTypeMetaData != null) {
686                             o = data[stateFieldNo] = resolveArrayOIDs(
687                                     (Object JavaDoc[])o, pm, fmd.elementType);
688                         }
689                     } else {
690                         data[stateFieldNo] = fmd.createSCO(pm, pm.getInternalSM(
691                                 owningPC), fmd,
692                                 owningPC, o);
693                         o = data[stateFieldNo];
694                     }
695                 } else {
696                     switch (fmd.category) {
697                         case MDStatics.CATEGORY_EXTERNALIZED:
698                             data[stateFieldNo] = o = fmd.externalizer.fromExternalForm(
699                                     pm, o);
700                             break;
701                         case MDStatics.CATEGORY_REF:
702                         case MDStatics.CATEGORY_POLYREF:
703                             data[stateFieldNo] = o = pm.getObjectByIdForState(
704                                     (OID)o, stateFieldNo, classIndex, oid);
705                             break;
706                     }
707                 }
708                 resolvedForClient[stateFieldNo] = true;
709             } else if (cmd.isEmbeddedRef(stateFieldNo)) {
710                 data[stateFieldNo] = o = pm.getObjectByIdForState(null,
711                         stateFieldNo, classIndex, oid);
712                 resolvedForClient[stateFieldNo] = true;
713             }
714         }
715         if (Debug.DEBUG) {
716             if (o != null && !cmd.stateFields[stateFieldNo].type.isAssignableFrom(
717                     o.getClass())) {
718                 Debug.OUT.println("########### stateFieldNo = " + stateFieldNo);
719                 cmd.dump();
720                 throw BindingSupportImpl.getInstance().internal("Type error");
721             }
722         }
723         return o;
724     }
725
726     public boolean isFieldNullorZero(int stateFieldNo) {
727         if (Debug.DEBUG) {
728             if (!filled[stateFieldNo]) {
729                 throw BindingSupportImpl.getInstance().internal(
730                         "Field " + stateFieldNo + " is not loaded");
731             }
732         }
733         Object JavaDoc o = data[stateFieldNo];
734         if (o == null) {
735             return true;
736         }
737         FieldMetaData f = cmd.stateFields[stateFieldNo];
738         switch (f.typeCode) {
739             case MDStatics.BOOLEAN:
740             case MDStatics.BOOLEANW:
741                 return !((Boolean JavaDoc)o).booleanValue();
742             case MDStatics.BYTE:
743             case MDStatics.BYTEW:
744             case MDStatics.SHORT:
745             case MDStatics.SHORTW:
746             case MDStatics.INT:
747             case MDStatics.INTW:
748                 return ((Number JavaDoc)o).intValue() == 0;
749             case MDStatics.LONG:
750             case MDStatics.LONGW:
751                 return ((Long JavaDoc)o).longValue() == 0L;
752             case MDStatics.FLOAT:
753             case MDStatics.FLOATW:
754                 return ((Float JavaDoc)o).floatValue() == 0.0f;
755             case MDStatics.DOUBLE:
756             case MDStatics.DOUBLEW:
757             case MDStatics.BIGDECIMAL:
758             case MDStatics.BIGINTEGER:
759                 return ((Number JavaDoc)o).doubleValue() == 0.0;
760         }
761         return false;
762     }
763
764     public Object JavaDoc getObjectFieldAbs(int absFieldNo,
765             PersistenceCapable owningPC, PersistenceContext sm,
766             OID oid) {
767         return getObjectField(convertAbsToState(absFieldNo), owningPC, sm, oid);
768     }
769
770     public void setBooleanField(int field, boolean newValue) {
771         makeDirty(field);
772         setInternalBooleanField(field, newValue);
773     }
774
775     public void setBooleanFieldAbs(int field, boolean newValue) {
776         setBooleanField(convertAbsToState(field), newValue);
777     }
778
779     public void setCharField(int stateFieldNo, char newValue) {
780         makeDirty(stateFieldNo);
781         setInternalCharField(stateFieldNo, newValue);
782     }
783
784     public void setCharFieldAbs(int absFieldNo, char newValue) {
785         setCharField(convertAbsToState(absFieldNo), newValue);
786     }
787
788     public void setByteField(int field, byte newValue) {
789         makeDirty(field);
790         setInternalByteField(field, newValue);
791     }
792
793     public void setByteFieldAbs(int absFieldNo, byte newValue) {
794         setByteField(convertAbsToState(absFieldNo), newValue);
795     }
796
797     public void setShortField(int field, short newValue) {
798         makeDirty(field);
799         setInternalShortField(field, newValue);
800     }
801
802     public void setShortFieldAbs(int field, short newValue) {
803         setShortField(convertAbsToState(field), newValue);
804     }
805
806     public void setIntField(int field, int newValue) {
807         makeDirty(field);
808         setInternalIntField(field, newValue);
809     }
810
811     public void setIntFieldAbs(int absFieldNo, int newValue) {
812         setIntField(convertAbsToState(absFieldNo), newValue);
813     }
814
815     public void setLongField(int field, long newValue) {
816         makeDirty(field);
817         setInternalLongField(field, newValue);
818     }
819
820     public void setLongFieldAbs(int field, long newValue) {
821         setLongField(convertAbsToState(field), newValue);
822     }
823
824     public void setFloatField(int field, float newValue) {
825         makeDirty(field);
826         setInternalFloatField(field, newValue);
827     }
828
829     public void setFloatFieldAbs(int field, float newValue) {
830         setFloatField(convertAbsToState(field), newValue);
831     }
832
833     public void setDoubleField(int field, double newValue) {
834         makeDirty(field);
835         setInternalDoubleField(field, newValue);
836     }
837
838     public void setDoubleFieldAbs(int field, double newValue) {
839         setDoubleField(convertAbsToState(field), newValue);
840     }
841
842     public void setStringField(int field, String JavaDoc newValue) {
843         makeDirty(field);
844         setInternalStringField(field, newValue);
845     }
846
847     public void setStringFieldAbs(int field, String JavaDoc newValue) {
848         setStringField(convertAbsToState(field), newValue);
849     }
850
851     public void setObjectField(int field, Object JavaDoc newValue) {
852         checkCmd();
853         makeDirty(field);
854         resolvedForClient[field] = true;
855         if (Debug.DEBUG) {
856             if (newValue != null && !cmd.stateFields[field].type.isAssignableFrom(
857                     newValue.getClass())) {
858                 Debug.OUT.println("########### field = " + field);
859                 Debug.OUT.println(
860                         "## field type = " + cmd.stateFields[field].type.getName());
861                 Debug.OUT.println(
862                         "## object type = " + newValue.getClass().getName());
863                 cmd.dump();
864                 throw BindingSupportImpl.getInstance().internal("Type error");
865             }
866         }
867         setInternalObjectField(field, newValue);
868     }
869
870     public void setObjectFieldAbs(int field, Object JavaDoc newValue) {
871         setObjectField(convertAbsToState(field), newValue);
872     }
873
874     public void setObjectFieldUnresolved(int field, Object JavaDoc newValue) {
875         checkCmd();
876         makeDirty(field);
877         resolvedForClient[field] = false;
878         setInternalObjectField(field, newValue);
879     }
880
881     public void setObjectFieldUnresolvedAbs(int field, Object JavaDoc newValue) {
882         setObjectFieldUnresolved(convertAbsToState(field), newValue);
883     }
884
885 //=======================setInternalXXX====================================
886

887     public void setInternalBooleanField(int field, boolean newValue) {
888         data[field] = newValue ? Boolean.TRUE : Boolean.FALSE;
889         filled[field] = true;
890     }
891
892     public void setInternalBooleanFieldAbs(int field, boolean newValue) {
893         setInternalBooleanField(convertAbsToState(field), newValue);
894     }
895
896     public void setInternalCharField(int field, char newValue) {
897         data[field] = new Character JavaDoc(newValue);
898         filled[field] = true;
899     }
900
901     public void setInternalCharFieldAbs(int field, char newValue) {
902         setInternalCharField(convertAbsToState(field), newValue);
903     }
904
905     public void setInternalByteField(int field, byte newValue) {
906         data[field] = new Byte JavaDoc(newValue);
907         filled[field] = true;
908     }
909
910     public void setInternalByteFieldAbs(int field, byte newValue) {
911         setInternalByteField(convertAbsToState(field), newValue);
912     }
913
914     public void setInternalShortField(int field, short newValue) {
915         data[field] = new Short JavaDoc(newValue);
916         filled[field] = true;
917     }
918
919     public void setInternalShortFieldAbs(int field, short newValue) {
920         setInternalShortField(convertAbsToState(field), newValue);
921     }
922
923     public void setInternalIntField(int field, int newValue) {
924         data[field] = new Integer JavaDoc(newValue);
925         filled[field] = true;
926     }
927
928     public void setInternalIntFieldAbs(int field, int newValue) {
929         setInternalIntField(convertAbsToState(field), newValue);
930     }
931
932     public void setInternalLongField(int field, long newValue) {
933         data[field] = new Long JavaDoc(newValue);
934         filled[field] = true;
935     }
936
937     public void setFilled(int stateFieldNo) {
938         filled[stateFieldNo] = true;
939     }
940
941     public void setInternalLongFieldAbs(int field, long newValue) {
942         setInternalLongField(convertAbsToState(field), newValue);
943     }
944
945     public void setInternalFloatField(int field, float newValue) {
946         data[field] = new Float JavaDoc(newValue);
947         filled[field] = true;
948     }
949
950     public void setInternalFloatFieldAbs(int field, float newValue) {
951         setInternalFloatField(convertAbsToState(field), newValue);
952     }
953
954     public void setInternalDoubleField(int field, double newValue) {
955         data[field] = new Double JavaDoc(newValue);
956         filled[field] = true;
957     }
958
959     public void setInternalDoubleFieldAbs(int field, double newValue) {
960         setInternalDoubleField(convertAbsToState(field), newValue);
961     }
962
963     public void setInternalStringField(int field, String JavaDoc newValue) {
964         data[field] = newValue;
965         filled[field] = true;
966     }
967
968     public void setInternalStringFieldAbs(int field, String JavaDoc newValue) {
969         setInternalStringField(convertAbsToState(field), newValue);
970     }
971
972     public void setInternalObjectField(int field, Object JavaDoc newValue) {
973         data[field] = newValue;
974         filled[field] = true;
975     }
976
977     public void setInternalObjectFieldAbs(int field, Object JavaDoc newValue) {
978         setInternalObjectField(convertAbsToState(field), newValue);
979     }
980
981 //==========================getInternalXXX======================================
982

983     public Object JavaDoc getInternalObjectField(int stateFieldNo) {
984         return data[stateFieldNo];
985     }
986
987     public Object JavaDoc getInternalObjectFieldAbs(int field) {
988         return getInternalObjectField(convertAbsToState(field));
989     }
990
991     public void updateFrom(State state) {
992         GenericState gState = (GenericState)state;
993         boolean[] fields = gState.filled;
994         Object JavaDoc[] otherData = gState.data;
995         for (int i = 0; i < fields.length; i++) {
996             if (fields[i]) {
997                 data[i] = otherData[i];
998                 filled[i] = true;
999             }
1000        }
1001    }
1002
1003    /**
1004     * Mark all dirty fields as clean and not filled and not resolved.
1005     * <p/>
1006     * filled &= ~dirty
1007     * resolved &= ~dirty
1008     * dirty = 0
1009     */

1010    public void clearDirtyFields() {
1011        for (int i = 0; i < dirtyFields.length; i++) {
1012            if (dirtyFields[i]) {
1013                dirtyFields[i] = false;
1014                filled[i] = false;
1015                resolvedForClient[i] = false;
1016            }
1017        }
1018    }
1019
1020    public void updateNonFilled(State state) {
1021        GenericState gState = (GenericState)state;
1022        if (Debug.DEBUG) {
1023            if (gState.getClassIndex() != getClassIndex()) {
1024                throw BindingSupportImpl.getInstance().internal(
1025                        "Incompatible states");
1026            }
1027        }
1028        boolean[] fields = gState.filled;
1029        Object JavaDoc[] otherData = gState.data;
1030        for (int i = 0; i < fields.length; i++) {
1031            if (fields[i] && !filled[i]) {
1032                data[i] = otherData[i];
1033                filled[i] = true;
1034            }
1035        }
1036    }
1037
1038    public void clearNonAutoSetFields() {
1039        for (int i = 0; i < cmd.nonAutoSetStateFieldNos.length; i++) {
1040            int f = cmd.nonAutoSetStateFieldNos[i];
1041            data[f] = null;
1042            filled[f] = false;
1043        }
1044    }
1045
1046    public void retrieve(VersantPersistenceManagerImp sm) {
1047        FetchGroup fg = cmd.refFetchGroup;
1048        while (fg != null) {
1049            retrieveImp(fg.stateFieldNos, sm);
1050            fg = fg.superFetchGroup;
1051        }
1052    }
1053
1054    private void retrieveImp(int[] fieldNos, VersantPersistenceManagerImp sm) {
1055        int fieldNo = 0;
1056        FieldMetaData fmd = null;
1057        for (int i = fieldNos.length - 1; i >= 0; i--) {
1058            fieldNo = fieldNos[i];
1059            if (data[fieldNo] != null) {
1060                fmd = cmd.stateFields[fieldNo];
1061                if (fmd.persistenceModifier != MDStatics.PERSISTENCE_MODIFIER_TRANSACTIONAL) {
1062                    switch (fmd.category) {
1063                        case MDStatics.CATEGORY_ARRAY:
1064                            sm.retrieveAllImp((Object JavaDoc[])data[fieldNo]);
1065                            break;
1066                        case MDStatics.CATEGORY_COLLECTION:
1067                            sm.retrieveAllImp((Collection)data[fieldNo]);
1068                            break;
1069                        case MDStatics.CATEGORY_MAP:
1070                            StateUtil.retrieve((Map)data[fieldNo], sm, fmd);
1071                            break;
1072                        case MDStatics.CATEGORY_REF:
1073                        case MDStatics.CATEGORY_POLYREF:
1074                            sm.retrieveImp(data[fieldNo]);
1075                            break;
1076                        default:
1077                            throw BindingSupportImpl.getInstance().internal(
1078                                    "Type not allowed");
1079                    }
1080                }
1081            }
1082        }
1083    }
1084
1085    /**
1086     * @param pm
1087     * @param pcStateMan
1088     */

1089    public void addRefs(VersantPersistenceManagerImp pm, PCStateMan pcStateMan) {
1090        if (dirty) {
1091            FetchGroup fg = findFirstRefFG(cmd);
1092            while (fg != null) {
1093                addRefs(fg.stateFieldNos, pm, pcStateMan);
1094                fg = fg.superFetchGroup;
1095            }
1096        }
1097    }
1098
1099    private FetchGroup findFirstRefFG(ClassMetaData cmd) {
1100        if (cmd.refFetchGroup != null) return cmd.refFetchGroup;
1101        if (cmd.refFetchGroup == null && cmd.pcSuperMetaData == null) return null;
1102        return findFirstRefFG(cmd.pcSuperMetaData);
1103    }
1104
1105    /**
1106     * A ref may be a direct ref or an item in collection/map/array.
1107     */

1108    private final void addRefs(int[] fieldNos,
1109            VersantPersistenceManagerImp pm, PCStateMan sm) {
1110        int fieldNo = 0;
1111        FieldMetaData fmd = null;
1112        // the fields MUST be processed in ascending order or embedded
1113
// reference fields containing other embedded reference fields
1114
// will not work as the embedded-embedded field will be
1115
// processed prior to being filled
1116
for (int i = 0; i < fieldNos.length; i++) {
1117            fieldNo = fieldNos[i];
1118            if (dirtyFields[fieldNo]) {
1119                if (data[fieldNo] != null) {
1120                    fmd = cmd.stateFields[fieldNo];
1121                    if (fmd.persistenceModifier != MDStatics.PERSISTENCE_MODIFIER_TRANSACTIONAL) {
1122                        switch (fmd.category) {
1123                            case MDStatics.CATEGORY_ARRAY:
1124                                StateUtil.doReachable((Object JavaDoc[])data[fieldNo],
1125                                        pm);
1126                                break;
1127                            case MDStatics.CATEGORY_COLLECTION:
1128                                StateUtil.doReachable(
1129                                        (Collection)data[fieldNo], pm);
1130                                break;
1131                            case MDStatics.CATEGORY_MAP:
1132                                StateUtil.doReachable((Map)data[fieldNo], pm,
1133                                        fmd);
1134                                break;
1135                            case MDStatics.CATEGORY_REF:
1136                            case MDStatics.CATEGORY_POLYREF:
1137                                if (data[fieldNo] instanceof PersistenceCapable) {
1138                                    if (fmd.embedded) {
1139                                        StateUtil.doReachableEmbeddedReference(
1140                                                (PersistenceCapable)data[fieldNo],
1141                                                pm, sm, fmd);
1142                                    } else {
1143                                        StateUtil.doReachable(
1144                                                (PersistenceCapable)data[fieldNo], pm);
1145                                    }
1146                                }
1147                                break;
1148                            default:
1149                                throw BindingSupportImpl.getInstance().internal(
1150                                        "Type not allowed");
1151                        }
1152                    }
1153                }
1154            }
1155        }
1156    }
1157
1158    public void validateForCache() {
1159        checkCmd();
1160        FieldMetaData[] fmds = cmd.stateFields;
1161        for (int i = 0; i < fmds.length; i++) {
1162            FieldMetaData fieldMetaData = fmds[i];
1163            Object JavaDoc o = data[fieldMetaData.stateFieldNo];
1164            if (o != null) {
1165                int cat = fieldMetaData.category;
1166                if (cat == MDStatics.CATEGORY_REF || cat == MDStatics.CATEGORY_POLYREF) {
1167                    if (!(o instanceof OID)) {
1168                        fieldMetaData.dump(Debug.OUT, " ");
1169                        throw BindingSupportImpl.getInstance().internal(
1170                                "The instance is not valid to be added to cache");
1171                    }
1172                }
1173            }
1174        }
1175    }
1176
1177    public void makeDirty(int stateFieldNo) {
1178        dirty = true;
1179        dirtyFields[stateFieldNo] = true;
1180    }
1181
1182    public void makeDirtyAbs(int absFieldNo) {
1183        makeDirty(convertAbsToState(absFieldNo));
1184    }
1185
1186    public boolean isDirty() {
1187        return dirty;
1188    }
1189
1190    public boolean isDirty(int absFieldNo) {
1191        return dirtyFields[convertAbsToState(absFieldNo)];
1192    }
1193
1194    /**
1195     * This must be called once the state is ready to be sent off to the server.
1196     * <p/>
1197     * All FirstClass instances will be resolved to an OID and second class
1198     * instances will be resolved to some serializable/storable format that represents the
1199     * state of the field.
1200     */

1201    private void prepare(PersistenceContext pm,
1202            VersantStateManager sm) {
1203        FieldMetaData fmd = null;
1204        for (int i = 0; i < data.length; i++) {
1205            if (filled[i] && data[i] != null) {
1206                fmd = cmd.stateFields[i];
1207                if (fmd.scoField) {
1208                    if (fmd.typeCode == MDStatics.DATE) {
1209                        data[i] = StateUtil.getPValueForSCO(
1210                                (java.util.Date JavaDoc)data[i]);
1211
1212                    } else {
1213                        switch (fmd.category) {
1214                            case MDStatics.CATEGORY_ARRAY:
1215                                if ((data[i] instanceof OID[]) == false && fmd.isElementTypePC()) {
1216                                    data[i] = resolveArrayValues(
1217                                            (Object JavaDoc[])data[i], pm);
1218                                }
1219                                break;
1220                            case MDStatics.CATEGORY_COLLECTION:
1221                                if ((data[i] instanceof OID[]) == false) {
1222                                    data[i] = StateUtil.getPValueForSCO(
1223                                            (Collection)data[i], pm, sm, fmd);
1224                                }
1225                                break;
1226                            case MDStatics.CATEGORY_MAP:
1227                                if ((data[i] instanceof MapEntries) == false) {
1228                                    data[i] = StateUtil.getPValueForSCO(
1229                                        (Map)data[i], pm, fmd);
1230                                }
1231                                break;
1232                            default:
1233                                throw BindingSupportImpl.getInstance().internal("No logic defined for field type "
1234                                        + MDStaticUtils.toSimpleName(
1235                                                fmd.typeCode)
1236                                        + " field name = " + fmd.name);
1237                        }
1238                    }
1239                } else {
1240                    switch (fmd.category) {
1241                        case MDStatics.CATEGORY_EXTERNALIZED:
1242                            data[i] = fmd.externalizer.toExternalForm(pm.getPersistenceManager(),
1243                                    data[i]);
1244                            break;
1245                        case MDStatics.CATEGORY_REF:
1246                        case MDStatics.CATEGORY_POLYREF:
1247                            if (fmd.embedded) {
1248                                data[i] = null;
1249                            } else if (data[i] instanceof PersistenceCapable) {
1250                                data[i] = StateUtil.getPValueForRef(
1251                                        (PersistenceCapable)data[i], pm);
1252                            }
1253                            break;
1254                    }
1255                }
1256            }
1257        }
1258    }
1259
1260    /**
1261     * This is to copy the fields that is filled in on the supplied state to the
1262     * current state. The objective behind it is to keep a copy of the date to
1263     * compare against the db at the time of commit. The only field types of interest
1264     * is java.util.Date and Reference fields.
1265     *
1266     * @param state
1267     * @param sm
1268     */

1269    public void copyFieldsForOptimisticLocking(State state,
1270            VersantPersistenceManagerImp sm) {
1271        GenericState gState = (GenericState)state;
1272        boolean[] fields = gState.filled;
1273        Object JavaDoc[] otherData = gState.data;
1274        FieldMetaData fmd = null;
1275        for (int i = 0; i < fields.length; i++) {
1276            if (fields[i] && !filled[i]) {
1277                if (otherData[i] != null) {
1278                    fmd = cmd.stateFields[i];
1279                    boolean resolved = gState.resolvedForClient != null ? gState.resolvedForClient[i] : false;
1280                    if (fmd.typeCode == MDStatics.DATE) {
1281                        if (resolved) {
1282
1283                            data[i] = ((Date)otherData[i]).clone();
1284
1285
1286
1287                        } else {
1288                            data[i] = otherData[i];
1289                        }
1290                        filled[i] = true;
1291                    } else if (fmd.category == MDStatics.CATEGORY_REF
1292                            || fmd.category == MDStatics.CATEGORY_POLYREF) {
1293                        if (resolved) {
1294                            data[i] = sm.getInternalOID(
1295                                    (PersistenceCapable)otherData[i]);
1296                        } else {
1297                            data[i] = otherData[i];
1298                        }
1299                        filled[i] = true;
1300                    } else {
1301                        data[i] = otherData[i];
1302                        filled[i] = true;
1303                    }
1304                }
1305            }
1306        }
1307    }
1308
1309    /**
1310     * This copies all the fakeFields from one the supplied state.
1311     *
1312     * @param state
1313     */

1314    public void copyOptimisticLockingField(State state) {
1315        GenericState gState = (GenericState)state;
1316        FieldMetaData optimisticLockingField = cmd.optimisticLockingField;
1317        if (optimisticLockingField == null) return;
1318        if (gState.filled[optimisticLockingField.stateFieldNo]) {
1319            data[optimisticLockingField.stateFieldNo] = gState.data[optimisticLockingField.stateFieldNo];
1320            filled[optimisticLockingField.stateFieldNo] = true;
1321        }
1322    }
1323
1324    /**
1325     * This will replace all fields that should be a SCO field with it's SCO implementation.
1326     */

1327    public int replaceSCOFields(PersistenceCapable owner,
1328            VersantPersistenceManagerImp sm, int[] absFields) {
1329        if (cmd.scoFieldNos.length == 0) return 0;
1330        int[] scoStateFieldNos = cmd.scoFieldNos;
1331        int count = 0;
1332        for (int i = 0; i < scoStateFieldNos.length; i++) {
1333            int scoStateFieldNo = scoStateFieldNos[i];
1334            if (data[scoStateFieldNo] != null) {
1335                FieldMetaData fmd = cmd.stateFields[scoStateFieldNo];
1336                data[scoStateFieldNo] = fmd.createSCO(sm, sm.getInternalSM(
1337                        owner),
1338                        fmd, owner, data[scoStateFieldNo]);
1339                absFields[count++] = cmd.stateFields[scoStateFieldNo].managedFieldNo;
1340            }
1341        }
1342        return count;
1343    }
1344
1345
1346
1347
1348    public void unmanageSCOFields() {
1349        final Object JavaDoc[] d = data;
1350        for (int i = 0; i < cmd.scoFieldNos.length; i++) {
1351            final int scoFieldNo = cmd.scoFieldNos[i];
1352            if ((d[scoFieldNo] != null)) {
1353                if ((d[scoFieldNo] instanceof VersantSimpleSCO)) {
1354                    ((VersantSimpleSCO)d[scoFieldNo]).makeTransient();
1355                }
1356            }
1357        }
1358    }
1359
1360    public State getCopy() {
1361        checkCmd();
1362        final GenericState copy = new GenericState(cmd);
1363        System.arraycopy(this.filled, 0, copy.filled, 0, copy.filled.length);
1364        System.arraycopy(this.data, 0, copy.data, 0, copy.data.length);
1365        return copy;
1366    }
1367
1368    /**
1369     * <p>This return a deep clone of this state instance with only fields that
1370     * must be sent to the server to persist changes to this instance filled
1371     * in. For JdbcDataStore this will include only the dirty fields. For
1372     * VdsDataStore this includes all fields so the whole DataStoreObject
1373     * can be written.</p>
1374     * <p/>
1375     * <p>All 'First Class Objects' will be resolved to an OID and
1376     * 'Second Class Objects' will be resolved to some serializable/storable
1377     * format that represents the state of the field.</p>
1378     *
1379     * @return True if some fields were written to stateToStore and false if
1380     * not (i.e. we have no dirty fields)
1381     */

1382    public boolean fillToStoreState(State stateToStore,
1383            PersistenceContext pm,
1384            VersantStateManager sm) {
1385        GenericState state = (GenericState)stateToStore;
1386        if (dirty) {
1387            if (cmd.storeAllFields) {
1388                // we must include all primary fields not just the dirty ones
1389
for (int i = 0; i < data.length; i++) {
1390                    FieldMetaData fmd = cmd.stateFields[i];
1391                    if (fmd.persistenceModifier ==
1392                            MDStatics.PERSISTENCE_MODIFIER_TRANSACTIONAL) {
1393                        continue;
1394                    } else if (fmd.primaryField) {
1395                        if (filled[i]) {
1396                            state.data[i] = data[i];
1397                            state.filled[i] = true;
1398                        }
1399                    } else if (fmd.secondaryField) {
1400                        if (dirtyFields[i]) {
1401                            state.data[i] = data[i];
1402                            state.filled[i] = true;
1403                        } else {
1404                            state.data[i] = null;
1405                            state.filled[i] = false;
1406                        }
1407                    } else {
1408                        throw BindingSupportImpl.getInstance().internal("not primaryField " +
1409                                "or secondaryField: " + fmd.getQName());
1410                    }
1411                }
1412                state.prepare(pm, sm);
1413            } else {
1414                int count = 0;
1415                for (int i = 0; i < data.length; i++) {
1416                    if (dirtyFields[i]) {
1417                        count++;
1418                        state.data[i] = data[i];
1419                        state.filled[i] = true;
1420                    } else {
1421                        state.data[i] = null;
1422                        state.filled[i] = false;
1423                    }
1424                }
1425                if (count == 0) {
1426                    dirty = false;
1427                    state = null;
1428                } else {
1429                    state.prepare(pm, sm);
1430                }
1431            }
1432        } else {
1433            state = null;
1434        }
1435        return state != null;
1436    }
1437
1438    public void fillForRead(State dest,
1439            VersantPersistenceManagerImp pm) {
1440        if (Debug.DEBUG) {
1441            // method only implemented for VDS - should not be called for JDBC
1442
if (!cmd.storeAllFields) {
1443                throw BindingSupportImpl.getInstance().internal("Only implemented for " +
1444                        "classes with cmd.storeAllFields true");
1445            }
1446        }
1447        GenericState state = (GenericState)dest;
1448        for (int i = 0; i < data.length; i++) {
1449            FieldMetaData fmd = cmd.stateFields[i];
1450            // filled[i] will be true for VDS so we do not need to check it
1451
if (fmd.fake) {
1452                state.data[i] = data[i];
1453                state.filled[i] = true;
1454            } else {
1455                int cat = fmd.category;
1456                if (cat == MDStatics.CATEGORY_REF
1457                        || cat == MDStatics.CATEGORY_POLYREF) {
1458                    Object JavaDoc o = data[i];
1459                    if (o instanceof PersistenceCapable) {
1460                        PersistenceCapable pc = (PersistenceCapable)o;
1461                        if (pc.jdoGetPersistenceManager() == null) {
1462                            o = null;
1463                        } else {
1464                            o = StateUtil.getPValueForRef(pc, pm);
1465                        }
1466                    }
1467                    state.data[i] = o;
1468                    state.filled[i] = true;
1469                }
1470            }
1471        }
1472    }
1473
1474    public String JavaDoc toString() {
1475        checkCmd();
1476        StringBuffer JavaDoc s = new StringBuffer JavaDoc();
1477        s.append("GenericState@");
1478        s.append(Integer.toHexString(System.identityHashCode(this)));
1479        s.append(" ");
1480        String JavaDoc name = cmd.qname;
1481        int i = name.lastIndexOf('.');
1482        if (i >= 0) name = name.substring(i + 1);
1483        s.append(name);
1484        s.append(" {\n");
1485        boolean first = true;
1486        int n = data.length;
1487        for (i = 0; i < n; i++) {
1488            if (!filled[i]) continue;
1489            if (first) {
1490                first = false;
1491            } else {
1492                s.append(",\n ");
1493            }
1494            s.append(cmd.stateFields[i].name);
1495            s.append('[');
1496            s.append(cmd.stateFields[i].stateFieldNo);
1497            s.append(']');
1498            s.append('=');
1499            s.append(toString(data[i]));
1500            s.append(
1501                    " type = " + (data[i] != null ? data[i].getClass().getName() : " null"));
1502            s.append(" SysId = " + System.identityHashCode(data[i]));
1503            s.append(" jdoClsId = " + cmd.classId);
1504            if (resolvedForClient != null) {
1505                s.append(" res = " + resolvedForClient[i]);
1506            }
1507        }
1508        s.append('}');
1509        return s.toString();
1510    }
1511
1512    private String JavaDoc toString(Object JavaDoc o) {
1513        if (o == null) return "null";
1514        if (o instanceof String JavaDoc) {
1515            String JavaDoc s = (String JavaDoc)o;
1516            if (s.length() > 100) return s.substring(0, 100) + " ...";
1517            return s;
1518        } else if (o instanceof OID) {
1519            return ((OID)o).toStringImp();
1520        } else {
1521            return o.toString();
1522        }
1523    }
1524
1525    protected final void checkCmd() {
1526        if (cmd == null) {
1527            throw BindingSupportImpl.getInstance().internal("the cmd is null");
1528        }
1529    }
1530
1531    public void writeExternal(OIDObjectOutput os) throws IOException {
1532// if (Debug.DEBUG) {
1533
// System.out.println("%%% GenericState.writeExternal " + cmd.qname);
1534
// }
1535
os.writeBoolean(dirty);
1536        for (int i = 0; i < filled.length; i++) {
1537            os.writeBoolean(filled[i]);
1538        }
1539        for (int i = 0; i < data.length; i++) {
1540            if (!filled[i]) {
1541                continue;
1542            }
1543            FieldMetaData fmd = cmd.stateFields[i];
1544// if (Debug.DEBUG) {
1545
// Object o = data[i];
1546
// System.out.println("%%% GenericState.writeExternal " + fmd +
1547
// " " + (o instanceof OID ? ((OID)o).toStringImp() : String.valueOf(o)));
1548
// os.writeUTF("begin " + fmd.name);
1549
// }
1550
switch (fmd.category) {
1551                case MDStatics.CATEGORY_ARRAY:
1552                    SerUtils.writeArrayField(fmd, os, data[i]);
1553                    break;
1554                case MDStatics.CATEGORY_COLLECTION:
1555                case MDStatics.CATEGORY_MAP:
1556                    SerUtils.writeCollectionOrMapField(os, fmd, data[i]);
1557                    break;
1558                case MDStatics.CATEGORY_EXTERNALIZED:
1559                case MDStatics.CATEGORY_SIMPLE:
1560                    SerUtils.writeSimpleField(fmd, os, data[i]);
1561                    break;
1562                case MDStatics.CATEGORY_REF:
1563                case MDStatics.CATEGORY_POLYREF:
1564                    os.write((OID)data[i]);
1565                    break;
1566                case MDStatics.CATEGORY_TRANSACTIONAL:
1567                    break;
1568                default:
1569                    throw BindingSupportImpl.getInstance().internal("No logic defined for field type "
1570                            + MDStaticUtils.toSimpleName(fmd.typeCode)
1571                            + " field name = " + fmd.name);
1572            }
1573// if (Debug.DEBUG) {
1574
// os.writeUTF("end " + fmd.name);
1575
// }
1576
}
1577    }
1578
1579// private void expect(OIDObjectInput is, String expected)
1580
// throws IOException {
1581
// String s = is.readUTF();
1582
// if (!expected.equals(s)) {
1583
// throw new StreamCorruptedException("Expected: '" + expected +
1584
// "' got '" + s + "'");
1585
// }
1586
// }
1587

1588    public void readExternal(OIDObjectInput is) throws ClassNotFoundException JavaDoc,
1589            IOException {
1590// if (Debug.DEBUG) {
1591
// System.out.println("%%% GenericState.readExternal " + cmd);
1592
// }
1593
// no need to read the classIndex and cmd as they are set in the
1594
// constructor
1595
dirty = is.readBoolean();
1596        for (int i = 0; i < filled.length; i++) {
1597            filled[i] = is.readBoolean();
1598        }
1599        for (int i = 0; i < data.length; i++) {
1600            if (!filled[i]) {
1601                continue;
1602            }
1603            FieldMetaData fmd = cmd.stateFields[i];
1604// if (Debug.DEBUG) {
1605
// System.out.println("%%% GenericState.readExternal " + fmd);
1606
// expect(is, "begin " + fmd.name);
1607
// }
1608
switch (fmd.category) {
1609                case MDStatics.CATEGORY_ARRAY:
1610                    data[i] = SerUtils.readArrayField(fmd, is);
1611                    break;
1612                case MDStatics.CATEGORY_COLLECTION:
1613                case MDStatics.CATEGORY_MAP:
1614                    data[i] = SerUtils.readCollectionOrMapField(is, fmd);
1615                    break;
1616                case MDStatics.CATEGORY_SIMPLE:
1617                case MDStatics.CATEGORY_EXTERNALIZED:
1618                    data[i] = SerUtils.readSimpleField(fmd, is);
1619                    break;
1620                case MDStatics.CATEGORY_REF:
1621                case MDStatics.CATEGORY_POLYREF:
1622                    data[i] = is.readOID();
1623                    break;
1624                case MDStatics.CATEGORY_TRANSACTIONAL:
1625                    break;
1626                default:
1627                    throw BindingSupportImpl.getInstance().internal("No logic defined for field type "
1628                            + MDStaticUtils.toSimpleName(fmd.typeCode)
1629                            + " field name = " + fmd.name);
1630            };
1631// if (Debug.DEBUG) {
1632
// Object o = data[i];
1633
// System.out.println("%%% GenericState.readExternal " + fmd +
1634
// " " + (o instanceof OID ? ((OID)o).toStringImp() : String.valueOf(o)));
1635
// expect(is, "end " + fmd.name);
1636
// }
1637
}
1638    }
1639
1640    public String JavaDoc getVersion() {
1641        return Debug.VERSION;
1642    }
1643
1644    public static Object JavaDoc readSimple(int type, DataInput is) throws IOException {
1645        if (is.readInt() == 0) {
1646            return null;
1647        } else {
1648            switch (type) {
1649                case MDStatics.INTW:
1650                case MDStatics.INT:
1651                    return new Integer JavaDoc(is.readInt());
1652                case MDStatics.SHORTW:
1653                case MDStatics.SHORT:
1654                    return new Short JavaDoc(is.readShort());
1655                case MDStatics.STRING:
1656                    return is.readUTF();
1657                case MDStatics.BOOLEANW:
1658                case MDStatics.BOOLEAN:
1659                    return new Boolean JavaDoc(is.readBoolean());
1660                case MDStatics.BYTEW:
1661                case MDStatics.BYTE:
1662                    return new Byte JavaDoc(is.readByte());
1663                case MDStatics.DOUBLEW:
1664                case MDStatics.DOUBLE:
1665                    return new Double JavaDoc(is.readDouble());
1666                case MDStatics.FLOATW:
1667                case MDStatics.FLOAT:
1668                    return new Float JavaDoc(is.readFloat());
1669                case MDStatics.LONGW:
1670                case MDStatics.LONG:
1671                    return new Long JavaDoc(is.readLong());
1672                case MDStatics.DATE:
1673                    return new Date(is.readLong());
1674                case MDStatics.LOCALE:
1675                    return new Locale(is.readUTF(), is.readUTF(), is.readUTF());
1676                default:
1677                    throw BindingSupportImpl.getInstance().internal(
1678                            "readSimpleField for " + type + " is not supported");
1679            }
1680        }
1681    }
1682
1683    public boolean isHollow() {
1684        for (int i = 0; i < filled.length; i++) {
1685            if (filled[i]) return false;
1686        }
1687        for (int i = 0; i < data.length; i++) {
1688            if (data[i] != null) return false;
1689        }
1690        return true;
1691    }
1692
1693    public boolean equals(Object JavaDoc obj) {
1694        try {
1695            GenericState state = (GenericState)obj;
1696            int n = filled.length;
1697            for (int i = 0; i < n; i++) {
1698                if (filled[i] != state.filled[i]) {
1699                    return false;
1700                }
1701                if (data[i] != null) {
1702                    if (!data[i].equals(state.data[i])) {
1703                        return false;
1704                    }
1705                } else {
1706                    if (state.data != null) {
1707                        return false;
1708                    }
1709                }
1710                return true;
1711            }
1712        } catch (ClassCastException JavaDoc e) {
1713            return false;
1714        }
1715        return false;
1716    }
1717
1718    public boolean isResolvedForClient(int stateFieldNo) {
1719        if (resolvedForClient != null && resolvedForClient[stateFieldNo]) {
1720            return true;
1721        }
1722        return false;
1723    }
1724
1725    /**
1726     * The value of the version field on the pc.
1727     * This will return null if there are no version fields.
1728     */

1729    public Object JavaDoc getOptimisticLockingValue() {
1730        if (cmd.optimisticLockingField != null) {
1731            return data[cmd.optimisticLockingField.stateFieldNo];
1732        }
1733        return null;
1734    }
1735
1736    /**
1737     * Add the values of any non-null reference fields used as back or inverse
1738     * fields for unmanaged one-to-many collections for eviction from the L2
1739     * cache on commit. Note that the filled status of the field is not
1740     * checked. This method is called only for newly managed instances so
1741     * all fields will be filled.
1742     */

1743    public void addOneToManyInverseFieldsForL2Evict(
1744            VersantPersistenceManagerImp pm) {
1745        checkCmd();
1746        for (int i = 0; i < data.length; i++) {
1747            FieldMetaData fmd = cmd.stateFields[i];
1748            if (fmd.isDetail && !fmd.managed) {
1749                Object JavaDoc o = data[i];
1750                if (o != null) {
1751                    pm.evictFromL2CacheAfterCommitImp(o);
1752                }
1753            }
1754        }
1755    }
1756
1757}
1758
1759
Popular Tags