KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > db4o > YapClass


1 /* Copyright (C) 2004 - 2006 db4objects Inc. http://www.db4o.com
2
3 This file is part of the db4o open source object database.
4
5 db4o is free software; you can redistribute it and/or modify it under
6 the terms of version 2 of the GNU General Public License as published
7 by the Free Software Foundation and as clarified by db4objects' GPL
8 interpretation policy, available at
9 http://www.db4o.com/about/company/legalpolicies/gplinterpretation/
10 Alternatively you can write to db4objects, Inc., 1900 S Norfolk Street,
11 Suite 350, San Mateo, CA 94403, USA.
12
13 db4o is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 for more details.
17
18 You should have received a copy of the GNU General Public License along
19 with this program; if not, write to the Free Software Foundation, Inc.,
20 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */

21 package com.db4o;
22
23 import com.db4o.config.*;
24 import com.db4o.ext.*;
25 import com.db4o.foundation.*;
26 import com.db4o.inside.*;
27 import com.db4o.inside.classindex.*;
28 import com.db4o.inside.diagnostic.*;
29 import com.db4o.inside.marshall.*;
30 import com.db4o.inside.slots.*;
31 import com.db4o.query.*;
32 import com.db4o.reflect.*;
33 import com.db4o.reflect.generic.*;
34
35 /**
36  * @exclude
37  */

38 public class YapClass extends YapMeta implements TypeHandler4, StoredClass {
39
40     public YapClass i_ancestor;
41
42     Config4Class i_config;
43     public int _metaClassID;
44     
45     public YapField[] i_fields;
46     
47     private final ClassIndexStrategy _index;
48     
49     protected String JavaDoc i_name;
50
51     protected final YapStream i_stream;
52
53     byte[] i_nameBytes;
54     private YapReader i_reader;
55
56     private Db4oTypeImpl i_db4oType;
57     
58     private ReflectClass _reflector;
59     private boolean _isEnum;
60     public boolean i_dontCallConstructors;
61     
62     private EventDispatcher _eventDispatcher;
63     
64     private boolean _internal;
65     
66     private boolean _unversioned;
67     
68     // for indexing purposes.
69
// TODO: check race conditions, upon multiple calls against the same class
70
private int i_lastID;
71     
72     
73     boolean isInternal() {
74         return _internal;
75     }
76
77     private ClassIndexStrategy createIndexStrategy() {
78         return new BTreeClassIndexStrategy(this);
79     }
80
81     YapClass(YapStream stream, ReflectClass reflector){
82         i_stream = stream;
83         _reflector = reflector;
84         _index = createIndexStrategy();
85     }
86     
87     void activateFields(Transaction a_trans, Object JavaDoc a_object, int a_depth) {
88         if(objectCanActivate(a_trans.stream(), a_object)){
89             activateFields1(a_trans, a_object, a_depth);
90         }
91     }
92
93     void activateFields1(Transaction a_trans, Object JavaDoc a_object, int a_depth) {
94         for (int i = 0; i < i_fields.length; i++) {
95             i_fields[i].cascadeActivation(a_trans, a_object, a_depth, true);
96         }
97         if (i_ancestor != null) {
98             i_ancestor.activateFields1(a_trans, a_object, a_depth);
99         }
100     }
101
102     public final void addFieldIndices(YapWriter a_writer, Slot oldSlot) {
103         if(hasIndex() || hasVirtualAttributes()){
104             ObjectHeader oh = new ObjectHeader(i_stream, this, a_writer);
105             oh._marshallerFamily._object.addFieldIndices(this, oh._headerAttributes, a_writer, oldSlot);
106         }
107     }
108     
109     void addMembers(YapStream a_stream) {
110         bitTrue(YapConst.CHECKED_CHANGES);
111         if (addTranslatorFields(a_stream)) {
112             return;
113         }
114
115         if (a_stream.detectSchemaChanges()) {
116             boolean dirty = isDirty();
117
118             Collection4 members = new Collection4();
119
120             if (null != i_fields) {
121                 members.addAll(i_fields);
122                 if(i_fields.length==1&&i_fields[0] instanceof YapFieldTranslator) {
123                     setStateOK();
124                     return;
125                 }
126             }
127             if(generateVersionNumbers()) {
128                 if(! hasVersionField()) {
129                     members.add(a_stream.i_handlers.i_indexes.i_fieldVersion);
130                     dirty = true;
131                 }
132             }
133             if(generateUUIDs()) {
134                 if(! hasUUIDField()) {
135                     members.add(a_stream.i_handlers.i_indexes.i_fieldUUID);
136                     dirty = true;
137                 }
138             }
139             dirty = collectReflectFields(a_stream, members) | dirty;
140             if (dirty) {
141                 i_stream.setDirtyInSystemTransaction(this);
142                 i_fields = new YapField[members.size()];
143                 members.toArray(i_fields);
144                 for (int i = 0; i < i_fields.length; i++) {
145                     i_fields[i].setArrayPosition(i);
146                 }
147             } else {
148                 if (members.size() == 0) {
149                     i_fields = new YapField[0];
150                 }
151             }
152             
153             DiagnosticProcessor dp = i_stream.i_handlers._diagnosticProcessor;
154             if(dp.enabled()){
155                 dp.checkClassHasFields(this);
156             }
157             
158         } else {
159             if (i_fields == null) {
160                 i_fields = new YapField[0];
161             }
162         }
163         setStateOK();
164     }
165
166     private boolean collectReflectFields(YapStream stream, Collection4 collectedFields) {
167         boolean dirty=false;
168         ReflectField[] fields = classReflector().getDeclaredFields();
169         for (int i = 0; i < fields.length; i++) {
170             if (storeField(fields[i])) {
171                 TypeHandler4 wrapper = stream.i_handlers.handlerForClass(stream, fields[i].getFieldType());
172                 if (wrapper == null) {
173                     continue;
174                 }
175                 YapField field = new YapField(this, fields[i], wrapper);
176
177                 boolean found = false;
178                 Iterator4 m = collectedFields.iterator();
179                 while (m.moveNext()) {
180                     if (((YapField)m.current()).equals(field)) {
181                         found = true;
182                         break;
183                     }
184                 }
185                 if (found) {
186                     continue;
187                 }
188
189                 // this has no effect on YapClients
190
dirty = true;
191                 // we need a local dirty flag to tell us to reconstruct
192
// i_fields
193

194                 collectedFields.add(field);
195             }
196         }
197         return dirty;
198     }
199
200     private boolean addTranslatorFields(YapStream a_stream) {
201         
202         ObjectTranslator ot = getTranslator();
203         if (ot == null) {
204             return false;
205         }
206         
207         if (isNewTranslator(ot)) {
208             i_stream.setDirtyInSystemTransaction(this);
209         }
210         
211         int fieldCount = 1;
212         
213         boolean versions = generateVersionNumbers() && ! ancestorHasVersionField();
214         boolean uuids = generateUUIDs() && ! ancestorHasUUIDField();
215         
216         if(versions){
217             fieldCount = 2;
218         }
219         
220         if(uuids){
221             fieldCount = 3;
222         }
223         
224         i_fields = new YapField[fieldCount];
225         
226         i_fields[0] = new YapFieldTranslator(this, ot);
227         
228         // Some explanation on the thoughts here:
229

230         // Since i_fields for the translator are generated every time,
231
// we want to make sure that the order of fields is consistent.
232

233         // Therefore it's easier to implement with fixed index places in
234
// the i_fields array:
235

236         // [0] is the translator
237
// [1] is the version
238
// [2] is the UUID
239

240         if(versions || uuids) {
241             
242             // We don't want to have a null field, so let's add the version
243
// number, if we have a UUID, even if it's not needed.
244

245             i_fields[1] = a_stream.i_handlers.i_indexes.i_fieldVersion;
246         }
247         
248         if(uuids){
249             i_fields[2] = a_stream.i_handlers.i_indexes.i_fieldUUID;
250         }
251         
252         setStateOK();
253         return true;
254     }
255     
256     private ObjectTranslator getTranslator() {
257         return i_config == null
258             ? null
259             : i_config.getTranslator();
260     }
261
262     private boolean isNewTranslator(ObjectTranslator ot) {
263         return !hasFields()
264             || !ot.getClass().getName().equals(i_fields[0].getName());
265     }
266
267     private boolean hasFields() {
268         return i_fields != null
269             && i_fields.length > 0;
270     }
271
272     void addToIndex(YapFile a_stream, Transaction a_trans, int a_id) {
273         if (a_stream.maintainsIndices()) {
274             addToIndex1(a_stream, a_trans, a_id);
275         }
276     }
277
278     void addToIndex1(YapFile a_stream, Transaction a_trans, int a_id) {
279         if (i_ancestor != null) {
280             i_ancestor.addToIndex1(a_stream, a_trans, a_id);
281         }
282         if (hasIndex()) {
283             _index.add(a_trans, a_id);
284         }
285     }
286
287     boolean allowsQueries() {
288         return hasIndex();
289     }
290
291     public boolean canHold(ReflectClass claxx) {
292         if (claxx == null) {
293             return true;
294         }
295         if (_reflector != null) {
296             if(classReflector().isCollection()){
297                 return true;
298             }
299             return classReflector().isAssignableFrom(claxx);
300         }
301         return false;
302     }
303     
304     public void cascadeActivation(
305         Transaction a_trans,
306         Object JavaDoc a_object,
307         int a_depth,
308         boolean a_activate) {
309         Config4Class config = configOrAncestorConfig();
310         if (config != null) {
311             if (a_activate) {
312                 a_depth = config.adjustActivationDepth(a_depth);
313             }
314         }
315         if (a_depth > 0) {
316             YapStream stream = a_trans.stream();
317             if (a_activate) {
318                 if(isValueType()){
319                     activateFields(a_trans, a_object, a_depth - 1);
320                 }else{
321                     stream.stillToActivate(a_object, a_depth - 1);
322                 }
323             } else {
324                 stream.stillToDeactivate(a_object, a_depth - 1, false);
325             }
326         }
327     }
328
329     void checkChanges() {
330         if (stateOK()) {
331             if (!bitIsTrue(YapConst.CHECKED_CHANGES)) {
332                 bitTrue(YapConst.CHECKED_CHANGES);
333                 if (i_ancestor != null) {
334                     i_ancestor.checkChanges();
335                     // Ancestor first, so the object length calculates
336
// correctly
337
}
338                 if (_reflector != null) {
339                     addMembers(i_stream);
340                     if (!i_stream.isClient()) {
341                         write(i_stream.getSystemTransaction());
342                     }
343                 }
344             }
345         }
346     }
347     
348     public void checkDb4oType() {
349         ReflectClass claxx = classReflector();
350         if (claxx == null){
351             return;
352         }
353         if (i_stream.i_handlers.ICLASS_INTERNAL.isAssignableFrom(claxx)) {
354             _internal = true;
355         }
356         if (i_stream.i_handlers.ICLASS_UNVERSIONED.isAssignableFrom(claxx)) {
357             _unversioned = true;
358         }
359         if (i_stream.i_handlers.ICLASS_DB4OTYPEIMPL.isAssignableFrom(claxx)) {
360             try {
361                 i_db4oType = (Db4oTypeImpl)claxx.newInstance();
362             } catch (Exception JavaDoc e) {
363             }
364         }
365     }
366
367     public void checkUpdateDepth(YapWriter a_bytes) {
368         int depth = a_bytes.getUpdateDepth();
369         Config4Class config = configOrAncestorConfig();
370         if (depth == YapConst.UNSPECIFIED) {
371             depth = checkUpdateDepthUnspecified(a_bytes.getStream());
372             if (classReflector().isCollection()) {
373                 depth = adjustDepth(depth);
374             }
375         }
376         if ((config != null && (config.cascadeOnDelete() == YapConst.YES || config.cascadeOnUpdate() == YapConst.YES))) {
377             depth = adjustDepth(depth);
378         }
379         a_bytes.setUpdateDepth(depth - 1);
380     }
381
382     private int adjustDepth(int depth) {
383         int depthBorder = reflector().collectionUpdateDepth(classReflector());
384         if (depth>Integer.MIN_VALUE && depth < depthBorder) {
385             depth = depthBorder;
386         }
387         return depth;
388     }
389
390     int checkUpdateDepthUnspecified(YapStream a_stream) {
391         int depth = a_stream.configImpl().updateDepth() + 1;
392         if (i_config != null && i_config.updateDepth() != 0) {
393             depth = i_config.updateDepth() + 1;
394         }
395         if (i_ancestor != null) {
396             int ancestordepth = i_ancestor.checkUpdateDepthUnspecified(a_stream);
397             if (ancestordepth > depth) {
398                 return ancestordepth;
399             }
400         }
401         return depth;
402     }
403
404     public Object JavaDoc coerce(ReflectClass claxx, Object JavaDoc obj) {
405         return canHold(claxx) ? obj : No4.INSTANCE;
406     }
407
408     void collectConstraints(
409         Transaction a_trans,
410         QConObject a_parent,
411         Object JavaDoc a_object,
412         Visitor4 a_visitor) {
413         if (i_fields != null) {
414             for (int i = 0; i < i_fields.length; i++) {
415                 i_fields[i].collectConstraints(a_trans, a_parent, a_object, a_visitor);
416             }
417         }
418         if (i_ancestor != null) {
419             i_ancestor.collectConstraints(a_trans, a_parent, a_object, a_visitor);
420         }
421     }
422     
423     final TreeInt collectFieldIDs(MarshallerFamily mf, ObjectHeaderAttributes attributes, TreeInt tree, YapWriter a_bytes, String JavaDoc name) {
424         return mf._object.collectFieldIDs(tree, this, attributes, a_bytes, name);
425     }
426
427     final boolean configInstantiates(){
428         return i_config != null && i_config.instantiates();
429     }
430
431     public Config4Class configOrAncestorConfig() {
432         if (i_config != null) {
433             return i_config;
434         }
435         if (i_ancestor != null) {
436             return i_ancestor.configOrAncestorConfig();
437         }
438         return null;
439     }
440
441     public void copyValue(Object JavaDoc a_from, Object JavaDoc a_to) {
442         // do nothing
443
}
444
445     private boolean createConstructor(YapStream a_stream, String JavaDoc a_name) {
446         
447         ReflectClass claxx;
448         try {
449             claxx = a_stream.reflector().forName(a_name);
450         } catch (Throwable JavaDoc t) {
451             claxx = null;
452         }
453         
454         return createConstructor(a_stream,claxx , a_name, true);
455     }
456
457     public boolean createConstructor(YapStream a_stream, ReflectClass a_class, String JavaDoc a_name, boolean errMessages) {
458         
459         _reflector = a_class;
460         
461         _eventDispatcher = EventDispatcher.forClass(a_stream, a_class);
462         
463         if(! Deploy.csharp){
464             if(a_class != null){
465                 _isEnum = Platform4.jdk().isEnum(reflector(), a_class);
466             }
467         }
468         
469         if(configInstantiates()){
470             return true;
471         }
472         
473         if(a_class != null){
474             if(a_stream.i_handlers.ICLASS_TRANSIENTCLASS.isAssignableFrom(a_class)
475                 || Platform4.isTransient(a_class)) {
476                 a_class = null;
477             }
478         }
479         if (a_class == null) {
480             if(a_name == null || !Platform4.isDb4oClass(a_name)){
481                 if(errMessages){
482                     a_stream.logMsg(23, a_name);
483                 }
484             }
485             setStateDead();
486             return false;
487         }
488         
489         if(a_stream.i_handlers.createConstructor(a_class, ! callConstructor())){
490             return true;
491         }
492         
493         setStateDead();
494         if(errMessages){
495             a_stream.logMsg(7, a_name);
496         }
497         
498         if (a_stream.configImpl().exceptionsOnNotStorable()) {
499             throw new ObjectNotStorableException(a_class);
500         }
501
502         return false;
503         
504     }
505
506     public void deactivate(Transaction a_trans, Object JavaDoc a_object, int a_depth) {
507         if(objectCanDeactivate(a_trans.stream(), a_object)){
508             deactivate1(a_trans, a_object, a_depth);
509             objectOnDeactivate(a_trans.stream(), a_object);
510         }
511     }
512
513     private void objectOnDeactivate(YapStream stream, Object JavaDoc obj) {
514         stream.callbacks().objectOnDeactivate(obj);
515         dispatchEvent(stream, obj, EventDispatcher.DEACTIVATE);
516     }
517
518     private boolean objectCanDeactivate(YapStream stream, Object JavaDoc obj) {
519         return stream.callbacks().objectCanDeactivate(obj)
520             && dispatchEvent(stream, obj, EventDispatcher.CAN_DEACTIVATE);
521     }
522
523     void deactivate1(Transaction a_trans, Object JavaDoc a_object, int a_depth) {
524         
525         for (int i = 0; i < i_fields.length; i++) {
526             i_fields[i].deactivate(a_trans, a_object, a_depth);
527         }
528         if (i_ancestor != null) {
529             i_ancestor.deactivate1(a_trans, a_object, a_depth);
530         }
531     }
532
533     final void delete(YapWriter a_bytes, Object JavaDoc a_object) {
534         ObjectHeader oh = new ObjectHeader(i_stream, this, a_bytes);
535         delete1(oh._marshallerFamily, oh._headerAttributes, a_bytes, a_object);
536     }
537
538     private final void delete1(MarshallerFamily mf, ObjectHeaderAttributes attributes, YapWriter a_bytes, Object JavaDoc a_object) {
539         removeFromIndex(a_bytes.getTransaction(), a_bytes.getID());
540         deleteMembers(mf, attributes, a_bytes, a_bytes.getTransaction().stream().i_handlers.arrayType(a_object), false);
541     }
542
543     public void deleteEmbedded(MarshallerFamily mf, YapWriter a_bytes) {
544         if (a_bytes.cascadeDeletes() > 0) {
545             int id = a_bytes.readInt();
546             if (id > 0) {
547                 deleteEmbedded1(mf, a_bytes, id);
548             }
549         } else {
550             a_bytes.incrementOffset(linkLength());
551         }
552     }
553
554     public void deleteEmbedded1(MarshallerFamily mf, YapWriter a_bytes, int a_id) {
555         if (a_bytes.cascadeDeletes() > 0) {
556             
557             YapStream stream = a_bytes.getStream();
558             
559             // short-term reference to prevent WeakReference-gc to hit
560
Object JavaDoc obj = stream.getByID2(a_bytes.getTransaction(), a_id);
561
562             int cascade = a_bytes.cascadeDeletes() - 1;
563             if (obj != null) {
564                 if (isCollection(obj)) {
565                     cascade += reflector().collectionUpdateDepth(reflector().forObject(obj)) - 1;
566                 }
567             }
568
569             YapObject yo = stream.getYapObject(a_id);
570             if (yo != null) {
571                 a_bytes.getStream().delete2(a_bytes.getTransaction(), yo, obj,cascade, false);
572             }
573         }
574     }
575
576     void deleteMembers(MarshallerFamily mf, ObjectHeaderAttributes attributes, YapWriter a_bytes, int a_type, boolean isUpdate) {
577         try{
578             Config4Class config = configOrAncestorConfig();
579             if (config != null && (config.cascadeOnDelete() == YapConst.YES)) {
580                 int preserveCascade = a_bytes.cascadeDeletes();
581                 if (classReflector().isCollection()) {
582                     int newCascade =
583                         preserveCascade + reflector().collectionUpdateDepth(classReflector()) - 3;
584                     if (newCascade < 1) {
585                         newCascade = 1;
586                     }
587                     a_bytes.setCascadeDeletes(newCascade);
588                 } else {
589                     a_bytes.setCascadeDeletes(1);
590                 }
591                 mf._object.deleteMembers(this, attributes, a_bytes, a_type, isUpdate);
592                 a_bytes.setCascadeDeletes(preserveCascade);
593             } else {
594                 mf._object.deleteMembers(this, attributes, a_bytes, a_type, isUpdate);
595             }
596         }catch(Exception JavaDoc e){
597             
598             // This a catch for changed class hierarchies.
599
// It's quite ugly to catch all here but it does
600
// help to heal migration from earlier db4o
601
// versions.
602

603             if(Debug.atHome){
604                 e.printStackTrace();
605             }
606         }
607     }
608
609     public final boolean dispatchEvent(YapStream stream, Object JavaDoc obj, int message) {
610         if(_eventDispatcher == null || ! stream.dispatchsEvents()){
611             return true;
612         }
613         return _eventDispatcher.dispatch(stream, obj, message);
614     }
615     
616     public final boolean equals(TypeHandler4 a_dataType) {
617         return (this == a_dataType);
618     }
619     
620     public final int fieldCount(){
621         int count = i_fields.length;
622         
623         if(i_ancestor != null){
624             count += i_ancestor.fieldCount();
625         }
626         
627         return count;
628     }
629     
630     private static class YapFieldIterator implements Iterator4 {
631         private final YapClass _initialClazz;
632         private YapClass _curClazz;
633         private int _curIdx;
634         
635         public YapFieldIterator(YapClass clazz) {
636             _initialClazz=clazz;
637             reset();
638         }
639         
640         public Object JavaDoc current() {
641             return _curClazz.i_fields[_curIdx];
642         }
643
644         public boolean moveNext() {
645             if(_curClazz==null) {
646                 _curClazz=_initialClazz;
647                 _curIdx=0;
648             }
649             else {
650                 _curIdx++;
651             }
652             while(_curClazz!=null&&!indexInRange()) {
653                 _curClazz=_curClazz.i_ancestor;
654                 _curIdx=0;
655             }
656             return _curClazz!=null&&indexInRange();
657         }
658
659         public void reset() {
660             _curClazz=null;
661             _curIdx=-1;
662         }
663
664         private boolean indexInRange() {
665             return _curIdx<_curClazz.i_fields.length;
666         }
667     }
668     
669     public Iterator4 fields() {
670         return new YapFieldIterator(this);
671     }
672
673     // Scrolls offset in passed reader to the offset the passed field should
674
// be read at.
675
//
676
// returns null if not successful or if the field value at this offset is null
677
// returns MarshallerFamily from the object header if it is successful and
678
// if the value at this offset is not null
679
final MarshallerFamily findOffset(YapReader a_bytes, YapField a_field) {
680         if (a_bytes == null) {
681             return null;
682         }
683         a_bytes._offset = 0;
684         ObjectHeader oh = new ObjectHeader(i_stream, this, a_bytes);
685         boolean res = oh.objectMarshaller().findOffset(this, oh._headerAttributes, a_bytes, a_field);
686         if(! res){
687             return null;
688         }
689         return oh._marshallerFamily;
690     }
691
692     void forEachYapField(Visitor4 visitor) {
693         if (i_fields != null) {
694             for (int i = 0; i < i_fields.length; i++) {
695                 visitor.visit(i_fields[i]);
696             }
697         }
698         if (i_ancestor != null) {
699             i_ancestor.forEachYapField(visitor);
700         }
701     }
702     
703     public static YapClass forObject(Transaction trans, Object JavaDoc obj, boolean allowCreation){
704         ReflectClass reflectClass = trans.reflector().forObject(obj);
705         if (reflectClass != null && reflectClass.getSuperclass() == null && obj != null) {
706             throw new ObjectNotStorableException(obj.toString());
707         }
708         if(allowCreation){
709             return trans.stream().produceYapClass(reflectClass);
710         }
711         return trans.stream().getYapClass(reflectClass);
712     }
713     
714     public boolean generateUUIDs() {
715         if(! generateVirtual()){
716             return false;
717         }
718         int configValue = (i_config == null) ? 0 : i_config.generateUUIDs();
719         
720         return generate1(i_stream.config().generateUUIDs(), configValue);
721     }
722
723     private boolean generateVersionNumbers() {
724         if(! generateVirtual()){
725             return false;
726         }
727         int configValue = (i_config == null) ? 0 : i_config.generateVersionNumbers();
728         return generate1(i_stream.config().generateVersionNumbers(), configValue);
729     }
730     
731     private boolean generateVirtual(){
732         if(_unversioned){
733             return false;
734         }
735         if(_internal){
736             return false;
737         }
738         return true;
739     }
740     
741     private boolean generate1(int bootRecordValue, int configValue) {
742         if(bootRecordValue < 0) {
743             return false;
744         }
745         if(configValue < 0) {
746             return false;
747         }
748         if(bootRecordValue > 1) {
749             return true;
750         }
751         return configValue > 0;
752     }
753
754
755     YapClass getAncestor() {
756         return i_ancestor;
757     }
758
759     Object JavaDoc getComparableObject(Object JavaDoc forObject) {
760         if (i_config != null) {
761             if (i_config.queryAttributeProvider() != null) {
762                 return i_config.queryAttributeProvider().attribute(forObject);
763             }
764         }
765         return forObject;
766     }
767
768     YapClass getHigherHierarchy(YapClass a_yapClass) {
769         YapClass yc = getHigherHierarchy1(a_yapClass);
770         if (yc != null) {
771             return yc;
772         }
773         return a_yapClass.getHigherHierarchy1(this);
774     }
775
776     private YapClass getHigherHierarchy1(YapClass a_yapClass) {
777         if (a_yapClass == this) {
778             return this;
779         }
780         if (i_ancestor != null) {
781             return i_ancestor.getHigherHierarchy1(a_yapClass);
782         }
783         return null;
784     }
785
786     YapClass getHigherOrCommonHierarchy(YapClass a_yapClass) {
787         YapClass yc = getHigherHierarchy1(a_yapClass);
788         if (yc != null) {
789             return yc;
790         }
791         if (i_ancestor != null) {
792             yc = i_ancestor.getHigherOrCommonHierarchy(a_yapClass);
793             if (yc != null) {
794                 return yc;
795             }
796         }
797         return a_yapClass.getHigherHierarchy1(this);
798     }
799
800     public byte getIdentifier() {
801         return YapConst.YAPCLASS;
802     }
803
804     public long[] getIDs() {
805         synchronized(i_stream.i_lock){
806             if (! stateOK()) {
807                 return new long[0];
808             }
809             return getIDs(i_stream.getTransaction());
810         }
811     }
812
813     public long[] getIDs(Transaction trans) {
814         if (! stateOK()) {
815             return new long[0];
816         }
817         if (! hasIndex()) {
818             return new long[0];
819         }
820         return trans.stream().getIDsForClass(trans, this);
821     }
822
823     public boolean hasIndex() {
824         return i_db4oType == null || i_db4oType.hasClassIndex();
825     }
826     
827     private boolean ancestorHasUUIDField(){
828         if(i_ancestor == null) {
829             return false;
830         }
831         return i_ancestor.hasUUIDField();
832     }
833     
834     private boolean hasUUIDField() {
835         if(ancestorHasUUIDField()){
836             return true;
837         }
838         if(i_fields != null) {
839             for (int i = 0; i < i_fields.length; i++) {
840                 if(i_fields[i] instanceof YapFieldUUID) {
841                     return true;
842                 }
843             }
844         }
845         return false;
846     }
847     
848     private boolean ancestorHasVersionField(){
849         if(i_ancestor == null){
850             return false;
851         }
852         return i_ancestor.hasVersionField();
853     }
854     
855     private boolean hasVersionField() {
856         if(ancestorHasVersionField()){
857             return true;
858         }
859         if(i_fields != null) {
860             for (int i = 0; i < i_fields.length; i++) {
861                 if(i_fields[i] instanceof YapFieldVersion) {
862                     return true;
863                 }
864             }
865         }
866         return false;
867     }
868
869     public ClassIndexStrategy index() {
870         return _index;
871     }
872     
873     int indexEntryCount(Transaction ta){
874         if(!stateOK()){
875             return 0;
876         }
877         return _index.entryCount(ta);
878     }
879     
880     public Object JavaDoc indexEntryToObject(Transaction trans, Object JavaDoc indexEntry){
881         if(indexEntry == null){
882             return null;
883         }
884         int id = ((Integer JavaDoc)indexEntry).intValue();
885         return getStream().getByID2(trans, id);
886     }
887
888     public ReflectClass classReflector(){
889         return _reflector;
890     }
891
892     public String JavaDoc getName() {
893         if(i_name == null){
894             if(_reflector != null){
895                 i_name = _reflector.getName();
896             }
897         }
898         return i_name;
899     }
900     
901     public StoredClass getParentStoredClass(){
902         return getAncestor();
903     }
904
905     public StoredField[] getStoredFields(){
906         synchronized(i_stream.i_lock){
907             if(i_fields == null){
908                 return null;
909             }
910             StoredField[] fields = new StoredField[i_fields.length];
911             System.arraycopy(i_fields, 0, fields, 0, i_fields.length);
912             return fields;
913         }
914     }
915
916     YapStream getStream() {
917         return i_stream;
918     }
919
920     public int getTypeID() {
921         return YapConst.TYPE_CLASS;
922     }
923
924     public YapClass getYapClass(YapStream a_stream) {
925         return this;
926     }
927
928     public YapField getYapField(final String JavaDoc name) {
929         final YapField[] yf = new YapField[1];
930         forEachYapField(new Visitor4() {
931             public void visit(Object JavaDoc obj) {
932                 if (name.equals(((YapField)obj).getName())) {
933                     yf[0] = (YapField)obj;
934                 }
935             }
936         });
937         return yf[0];
938
939     }
940     
941     public boolean hasFixedLength(){
942         return true;
943     }
944
945     public boolean hasField(YapStream a_stream, String JavaDoc a_field) {
946         if(classReflector().isCollection()){
947             return true;
948         }
949         return getYapField(a_field) != null;
950     }
951     
952     boolean hasVirtualAttributes(){
953         if(_internal){
954             return false;
955         }
956         return hasVersionField() || hasUUIDField();
957     }
958
959     public boolean holdsAnyClass() {
960       return classReflector().isCollection();
961     }
962
963     void incrementFieldsOffset1(YapReader a_bytes) {
964         int length = Debug.atHome ? readFieldCountSodaAtHome(a_bytes) : readFieldCount(a_bytes);
965         for (int i = 0; i < length; i++) {
966             i_fields[i].incrementOffset(a_bytes);
967         }
968     }
969
970     public Object JavaDoc comparableObject(Transaction a_trans, Object JavaDoc a_object) {
971         return a_object;
972     }
973     
974     final boolean init( YapStream a_stream, YapClass a_ancestor,ReflectClass claxx) {
975         
976         if(DTrace.enabled){
977             DTrace.YAPCLASS_INIT.log(getID());
978         }
979         
980         i_ancestor = a_ancestor;
981         
982         Config4Impl config = a_stream.configImpl();
983         String JavaDoc className = claxx.getName();
984         setConfig(config.configClass(className));
985         
986         if(! createConstructor(a_stream, claxx, className, false)){
987             return false;
988         }
989         
990         checkDb4oType();
991         if (allowsQueries()) {
992             _index.initialize(a_stream);
993         }
994         i_name = className;
995         i_ancestor = a_ancestor;
996         bitTrue(YapConst.CHECKED_CHANGES);
997         
998         return true;
999     }
1000    
1001    final void initConfigOnUp(Transaction systemTrans) {
1002        Config4Class extendedConfig=Platform4.extendConfiguration(_reflector, i_stream.configure(), i_config);
1003        if(extendedConfig!=null) {
1004            i_config=extendedConfig;
1005        }
1006        if (i_config == null) {
1007            return;
1008        }
1009        if (! stateOK()) {
1010            return;
1011        }
1012        
1013        if (i_fields == null) {
1014            return;
1015        }
1016        
1017        for (int i = 0; i < i_fields.length; i++) {
1018            YapField curField = i_fields[i];
1019            String JavaDoc fieldName = curField.getName();
1020            if(!curField.hasConfig()&&extendedConfig!=null&&extendedConfig.configField(fieldName)!=null) {
1021                curField.initIndex(this,fieldName);
1022            }
1023            curField.initConfigOnUp(systemTrans);
1024        }
1025    }
1026
1027    void initOnUp(Transaction systemTrans) {
1028        if (! stateOK()) {
1029            return;
1030        }
1031        initConfigOnUp(systemTrans);
1032        storeStaticFieldValues(systemTrans, false);
1033    }
1034
1035    Object JavaDoc instantiate(YapObject a_yapObject, Object JavaDoc a_object, MarshallerFamily mf, ObjectHeaderAttributes attributes, YapWriter a_bytes, boolean a_addToIDTree) {
1036        
1037        // overridden in YapClassPrimitive
1038
// never called for primitive YapAny
1039

1040        YapStream stream = a_bytes.getStream();
1041        Transaction trans = a_bytes.getTransaction();
1042        boolean create = (a_object == null);
1043
1044        if (i_config != null) {
1045            a_bytes.setInstantiationDepth(
1046                i_config.adjustActivationDepth(a_bytes.getInstantiationDepth()));
1047        }
1048
1049        boolean doFields =
1050            (a_bytes.getInstantiationDepth() > 0)
1051                || (i_config != null && (i_config.cascadeOnActivate() == YapConst.YES));
1052
1053        if (create) {
1054            if (configInstantiates()) {
1055                int bytesOffset = a_bytes._offset;
1056                a_bytes.incrementOffset(YapConst.INT_LENGTH);
1057                // Field length is always 1
1058
try {
1059                    a_object = i_config.instantiate(stream, i_fields[0].read(mf, a_bytes));
1060                } catch (Exception JavaDoc e) {
1061                    Messages.logErr(stream.configImpl(), 6, classReflector().getName(), e);
1062                    return null;
1063                }
1064                a_bytes._offset = bytesOffset;
1065            } else {
1066                if (_reflector == null) {
1067                    return null;
1068                }
1069
1070                stream.instantiating(true);
1071                try {
1072                    a_object = _reflector.newInstance();
1073                } catch (NoSuchMethodError JavaDoc e) {
1074                    stream.logMsg(7, classReflector().getName());
1075                    stream.instantiating(false);
1076                    return null;
1077                } catch (Exception JavaDoc e) {
1078                    // TODO: be more helpful here
1079
stream.instantiating(false);
1080                    return null;
1081                }
1082                stream.instantiating(false);
1083
1084            }
1085            if (a_object instanceof TransactionAware) {
1086                ((TransactionAware)a_object).setTrans(a_bytes.getTransaction());
1087            }
1088            if (a_object instanceof Db4oTypeImpl) {
1089                ((Db4oTypeImpl)a_object).setYapObject(a_yapObject);
1090            }
1091            a_yapObject.setObjectWeak(stream, a_object);
1092            stream.hcTreeAdd(a_yapObject);
1093        } else {
1094            if(! stream.i_refreshInsteadOfActivate){
1095                if (a_yapObject.isActive()) {
1096                    doFields = false;
1097                }
1098            }
1099        }
1100        
1101        if(a_addToIDTree){
1102            a_yapObject.addToIDTree(stream);
1103        }
1104        
1105        if (doFields) {
1106            if(objectCanActivate(stream, a_object)){
1107                a_yapObject.setStateClean();
1108                instantiateFields(a_yapObject, a_object, mf, attributes, a_bytes);
1109                objectOnActivate(stream, a_object);
1110            }else{
1111                if (create) {
1112                    a_yapObject.setStateDeactivated();
1113                }
1114            }
1115        } else {
1116            if (create) {
1117                a_yapObject.setStateDeactivated();
1118            } else {
1119                if (a_bytes.getInstantiationDepth() > 1) {
1120                    activateFields(trans, a_object, a_bytes.getInstantiationDepth() - 1);
1121                }
1122            }
1123        }
1124        return a_object;
1125    }
1126
1127    private void objectOnActivate(YapStream stream, Object JavaDoc obj) {
1128        stream.callbacks().objectOnActivate(obj);
1129        dispatchEvent(stream, obj, EventDispatcher.ACTIVATE);
1130    }
1131
1132    private boolean objectCanActivate(YapStream stream, Object JavaDoc obj) {
1133        return stream.callbacks().objectCanActivate(obj)
1134            && dispatchEvent(stream, obj, EventDispatcher.CAN_ACTIVATE);
1135    }
1136
1137    Object JavaDoc instantiateTransient(YapObject a_yapObject, Object JavaDoc a_object, MarshallerFamily mf, ObjectHeaderAttributes attributes, YapWriter a_bytes) {
1138
1139        // overridden in YapClassPrimitive
1140
// never called for primitive YapAny
1141

1142        YapStream stream = a_bytes.getStream();
1143
1144        if (configInstantiates()) {
1145            int bytesOffset = a_bytes._offset;
1146            a_bytes.incrementOffset(YapConst.INT_LENGTH);
1147            // Field length is always 1
1148
try {
1149                a_object = i_config.instantiate(stream, i_fields[0].read(mf, a_bytes));
1150            } catch (Exception JavaDoc e) {
1151                Messages.logErr(stream.configImpl(), 6, classReflector().getName(), e);
1152                return null;
1153            }
1154            a_bytes._offset = bytesOffset;
1155        } else {
1156            if (_reflector == null) {
1157                return null;
1158            }
1159            stream.instantiating(true);
1160            try {
1161                a_object = _reflector.newInstance();
1162            } catch (NoSuchMethodError JavaDoc e) {
1163                stream.logMsg(7, classReflector().getName());
1164                stream.instantiating(false);
1165                return null;
1166            } catch (Exception JavaDoc e) {
1167                // TODO: be more helpful here
1168
stream.instantiating(false);
1169                return null;
1170            }
1171            stream.instantiating(false);
1172        }
1173        stream.peeked(a_yapObject.getID(), a_object);
1174        instantiateFields(a_yapObject, a_object, mf, attributes, a_bytes);
1175        return a_object;
1176    }
1177
1178    void instantiateFields(YapObject a_yapObject, Object JavaDoc a_onObject, MarshallerFamily mf,ObjectHeaderAttributes attributes, YapWriter a_bytes) {
1179        mf._object.instantiateFields(this, attributes, a_yapObject, a_onObject, a_bytes);
1180    }
1181
1182    public boolean indexNullHandling() {
1183        return true;
1184    }
1185
1186    public boolean isArray() {
1187        return classReflector().isCollection();
1188    }
1189    
1190    boolean isCollection(Object JavaDoc obj) {
1191        return reflector().forObject(obj).isCollection();
1192    }
1193
1194    public boolean isDirty() {
1195        if (!stateOK()) {
1196            return false;
1197        }
1198        return super.isDirty();
1199    }
1200    
1201    boolean isEnum(){
1202        return _isEnum;
1203    }
1204    
1205    public boolean isPrimitive(){
1206        return false;
1207    }
1208    
1209    public int isSecondClass(){
1210        return YapConst.NO;
1211    }
1212
1213    /**
1214     * no any, primitive, array or other tricks. overriden in YapClassAny and
1215     * YapClassPrimitive
1216     */

1217    boolean isStrongTyped() {
1218        return true;
1219    }
1220    
1221    boolean isValueType(){
1222        return Platform4.isValueType(classReflector());
1223    }
1224    
1225    public void calculateLengths(Transaction trans, ObjectHeaderAttributes header, boolean topLevel, Object JavaDoc obj, boolean withIndirection) {
1226        if(topLevel){
1227            header.addBaseLength(linkLength());
1228        }else{
1229            header.addPayLoadLength(linkLength());
1230        }
1231    }
1232
1233    public String JavaDoc nameToWrite() {
1234        if(i_config != null && i_config.writeAs() != null){
1235            return i_config.writeAs();
1236        }
1237        if(i_name == null){
1238            return "";
1239        }
1240        return i_stream.configImpl().resolveAliasRuntimeName(i_name);
1241    }
1242    
1243    final boolean callConstructor() {
1244        i_dontCallConstructors = ! callConstructor1();
1245        return ! i_dontCallConstructors;
1246    }
1247    
1248    private final boolean callConstructor1() {
1249        int res = callConstructorSpecialized();
1250        if(res != YapConst.DEFAULT){
1251            return res == YapConst.YES;
1252        }
1253        return (i_stream.configImpl().callConstructors() == YapConst.YES);
1254    }
1255    
1256    private final int callConstructorSpecialized(){
1257        if(i_config!= null){
1258            int res = i_config.callConstructor();
1259            if(res != YapConst.DEFAULT){
1260                return res;
1261            }
1262        }
1263        if(_isEnum){
1264            return YapConst.NO;
1265        }
1266        if(i_ancestor != null){
1267            return i_ancestor.callConstructorSpecialized();
1268        }
1269        return YapConst.DEFAULT;
1270    }
1271
1272    public int ownLength() {
1273        return MarshallerFamily.current()._class.marshalledLength(i_stream, this);
1274    }
1275    
1276    public ReflectClass primitiveClassReflector(){
1277        return null;
1278    }
1279
1280    void purge() {
1281        _index.purge();
1282        
1283        // TODO: may want to add manual purge to Btree
1284
// indexes here
1285
}
1286
1287    public Object JavaDoc read(MarshallerFamily mf, YapWriter a_bytes, boolean redirect) throws CorruptionException{
1288        try {
1289            int id = a_bytes.readInt();
1290            int depth = a_bytes.getInstantiationDepth() - 1;
1291
1292            Transaction trans = a_bytes.getTransaction();
1293            YapStream stream = trans.stream();
1294
1295            if (a_bytes.getUpdateDepth() == YapConst.TRANSIENT) {
1296                return stream.peekPersisted1(trans, id, depth);
1297            }
1298            
1299            if (isValueType()) {
1300
1301                // for C# value types only:
1302
// they need to be instantiated fully before setting them
1303
// on the parent object because the set call modifies identity.
1304

1305                // We also have to instantiate structs completely every time.
1306
if(depth < 1){
1307                    depth = 1;
1308                }
1309                
1310                // TODO: Do we want value types in the ID tree?
1311
// Shouldn't we treat them like strings and update
1312
// them every time ???
1313

1314                
1315                YapObject yo = stream.getYapObject(id);
1316                if (yo != null) {
1317                    Object JavaDoc obj = yo.getObject();
1318                    if(obj == null){
1319                        stream.removeReference(yo);
1320                    }else{
1321                        yo.activate(trans, obj, depth, false);
1322                        return yo.getObject();
1323                    }
1324                }
1325                
1326                return new YapObject(id).read(
1327                    trans,
1328                    null,
1329                    null,
1330                    depth,
1331                    YapConst.ADD_TO_ID_TREE, false);
1332            }
1333
1334            Object JavaDoc ret = stream.getByID2(trans, id);
1335
1336            if (ret instanceof Db4oTypeImpl) {
1337                depth = ((Db4oTypeImpl)ret).adjustReadDepth(depth);
1338            }
1339
1340            // this is OK for primitive YapAnys. They will not be added
1341
// to the list, since they will not be found in the ID tree.
1342
stream.stillToActivate(ret, depth);
1343
1344            return ret;
1345
1346        } catch (Exception JavaDoc e) {
1347        }
1348        return null;
1349    }
1350    
1351    public Object JavaDoc readQuery(Transaction a_trans, MarshallerFamily mf, boolean withRedirection, YapReader a_reader, boolean a_toArray) throws CorruptionException{
1352        try {
1353            return a_trans.stream().getByID2(a_trans, a_reader.readInt());
1354        } catch (Exception JavaDoc e) {
1355            if (Debug.atHome) {
1356                e.printStackTrace();
1357            }
1358        }
1359        return null;
1360    }
1361
1362    public TypeHandler4 readArrayHandler(Transaction a_trans, MarshallerFamily mf, YapReader[] a_bytes) {
1363        if (isArray()) {
1364            return this;
1365        }
1366        return null;
1367    }
1368
1369    public TypeHandler4 readArrayHandler1(YapReader[] a_bytes) {
1370        if(DTrace.enabled){
1371            if(a_bytes[0] instanceof YapWriter){
1372                DTrace.READ_ARRAY_WRAPPER.log(((YapWriter)a_bytes[0]).getID());
1373            }
1374        }
1375        if (isArray()) {
1376            if (Platform4.isCollectionTranslator(this.i_config)) {
1377                a_bytes[0].incrementOffset(YapConst.INT_LENGTH);
1378                return new YapArray(i_stream, null, false);
1379            }
1380            incrementFieldsOffset1(a_bytes[0]);
1381            if (i_ancestor != null) {
1382                return i_ancestor.readArrayHandler1(a_bytes);
1383            }
1384        }
1385        return null;
1386    }
1387    
1388    public QCandidate readSubCandidate(MarshallerFamily mf, YapReader reader, QCandidates candidates, boolean withIndirection) {
1389        int id = reader.readInt();
1390        if(id == 0){
1391            return null;
1392        }
1393        return new QCandidate(candidates, null, id, true);
1394    }
1395
1396    public void readCandidates(MarshallerFamily mf, final YapReader a_bytes, final QCandidates a_candidates) {
1397        int id = 0;
1398
1399        int offset = a_bytes._offset;
1400        try {
1401            id = a_bytes.readInt();
1402        } catch (Exception JavaDoc e) {
1403        }
1404        a_bytes._offset = offset;
1405
1406        if (id != 0) {
1407            final Transaction trans = a_candidates.i_trans;
1408            Object JavaDoc obj = trans.stream().getByID1(trans, id);
1409            if (obj != null) {
1410
1411                a_candidates.i_trans.stream().activate1(trans, obj, 2);
1412                Platform4.forEachCollectionElement(obj, new Visitor4() {
1413                    public void visit(Object JavaDoc elem) {
1414                        a_candidates.addByIdentity(new QCandidate(a_candidates, elem, (int)trans.stream().getID(elem), true));
1415                    }
1416                });
1417            }
1418
1419        }
1420    }
1421
1422    public final int readFieldCount(YapReader a_bytes) {
1423        int count = a_bytes.readInt();
1424        if (count > i_fields.length) {
1425            if (Debug.atHome) {
1426                System.out.println(
1427                    "YapClass.readFieldCount "
1428                        + getName()
1429                        + " count to high:"
1430                        + count
1431                        + " i_fields:"
1432                        + i_fields.length);
1433                new Exception JavaDoc().printStackTrace();
1434            }
1435            return i_fields.length;
1436        }
1437        return count;
1438    }
1439
1440    public int readFieldCountSodaAtHome(YapReader a_bytes) {
1441        if (Debug.atHome) {
1442            int count = a_bytes.readInt();
1443            if (count > i_fields.length) {
1444                return i_fields.length;
1445            }
1446            return count;
1447        }
1448        return 0;
1449    }
1450
1451    public Object JavaDoc readIndexEntry(YapReader a_reader) {
1452        return new Integer JavaDoc(a_reader.readInt());
1453    }
1454    
1455    public Object JavaDoc readIndexEntry(MarshallerFamily mf, YapWriter a_writer) throws CorruptionException{
1456        return readIndexEntry(a_writer);
1457    }
1458
1459    byte[] readName(Transaction a_trans) {
1460        i_reader = a_trans.stream().readReaderByID(a_trans, getID());
1461        if (i_reader != null) {
1462            return readName1(a_trans, i_reader);
1463        }
1464        return null;
1465    }
1466
1467    public final byte[] readName1(Transaction trans, YapReader reader) {
1468        i_reader = reader;
1469        
1470        try {
1471            ClassMarshaller marshaller = MarshallerFamily.current()._class;
1472            i_nameBytes = marshaller.readName(trans, reader);
1473            _metaClassID = marshaller.readMetaClassID(reader);
1474
1475            setStateUnread();
1476
1477            bitFalse(YapConst.CHECKED_CHANGES);
1478            bitFalse(YapConst.STATIC_FIELDS_STORED);
1479
1480            return i_nameBytes;
1481
1482        } catch (Throwable JavaDoc t) {
1483            setStateDead();
1484            if (Debug.atHome) {
1485                t.printStackTrace();
1486            }
1487        }
1488        return null;
1489    }
1490    
1491    void readVirtualAttributes(Transaction a_trans, YapObject a_yapObject) {
1492        int id = a_yapObject.getID();
1493        YapStream stream = a_trans.stream();
1494        YapReader reader = stream.readReaderByID(a_trans, id);
1495        ObjectHeader oh = new ObjectHeader(stream, this, reader);
1496        oh.objectMarshaller().readVirtualAttributes(a_trans, this, a_yapObject, oh._headerAttributes, reader);
1497    }
1498    
1499    GenericReflector reflector() {
1500        return i_stream.reflector();
1501    }
1502    
1503    public void rename(String JavaDoc newName){
1504        if (!i_stream.isClient()) {
1505            int tempState = i_state;
1506            setStateOK();
1507            i_name = newName;
1508            setStateDirty();
1509            write(i_stream.getSystemTransaction());
1510            i_state = tempState;
1511        }else{
1512            Exceptions4.throwRuntimeException(58);
1513        }
1514    }
1515
1516    void createConfigAndConstructor(
1517        Hashtable4 a_byteHashTable,
1518        YapStream a_stream,
1519        ReflectClass a_class) {
1520        if (a_class == null) {
1521            if (i_nameBytes != null) {
1522                String JavaDoc name = a_stream.stringIO().read(i_nameBytes);
1523                i_name = a_stream.configImpl().resolveAliasStoredName(name);
1524            }
1525        } else {
1526            i_name = a_class.getName();
1527        }
1528        setConfig(i_stream.configImpl().configClass(i_name));
1529        if (a_class == null) {
1530            createConstructor(a_stream, i_name);
1531        } else {
1532            createConstructor(a_stream, a_class, i_name, true);
1533        }
1534        if (i_nameBytes != null) {
1535            a_byteHashTable.remove(i_nameBytes);
1536            i_nameBytes = null;
1537        }
1538    }
1539
1540    boolean readThis() {
1541        if (stateUnread()) {
1542            setStateOK();
1543            setStateClean();
1544            forceRead();
1545            return true;
1546        }
1547        return false;
1548    }
1549    
1550    final void forceRead(){
1551        if(i_reader == null || bitIsTrue(YapConst.READING)){
1552            return;
1553        }
1554        
1555        bitTrue(YapConst.READING);
1556        
1557        MarshallerFamily.forConverterVersion(i_stream.converterVersion())._class.read(i_stream, this, i_reader);
1558       
1559        i_nameBytes = null;
1560        i_reader = null;
1561        bitFalse(YapConst.READING);
1562    }
1563
1564    public boolean readArray(Object JavaDoc array, YapReader reader) {
1565        return false;
1566    }
1567
1568    public void readThis(Transaction a_trans, YapReader a_reader) {
1569        throw Exceptions4.virtualException();
1570    }
1571
1572    void refresh() {
1573        if (!stateUnread()) {
1574            createConstructor(i_stream, i_name);
1575            bitFalse(YapConst.CHECKED_CHANGES);
1576            checkChanges();
1577            if (i_fields != null) {
1578                for (int i = 0; i < i_fields.length; i++) {
1579                    i_fields[i].refresh();
1580                }
1581            }
1582        }
1583    }
1584
1585    void removeFromIndex(Transaction ta, int id) {
1586        if (hasIndex()) {
1587            _index.remove(ta, id);
1588        }
1589        if (i_ancestor != null) {
1590            i_ancestor.removeFromIndex(ta, id);
1591        }
1592    }
1593
1594    boolean renameField(String JavaDoc a_from, String JavaDoc a_to) {
1595        boolean renamed = false;
1596        for (int i = 0; i < i_fields.length; i++) {
1597            if (i_fields[i].getName().equals(a_to)) {
1598                i_stream.logMsg(9, "class:" + getName() + " field:" + a_to);
1599                return false;
1600            }
1601        }
1602        for (int i = 0; i < i_fields.length; i++) {
1603            if (i_fields[i].getName().equals(a_from)) {
1604                i_fields[i].setName(a_to);
1605                renamed = true;
1606            }
1607        }
1608        return renamed;
1609    }
1610    
1611    void setConfig(Config4Class config){
1612        // The configuration can be set by a ObjectClass#readAs setting
1613
// from YapClassCollection, right after reading the meta information
1614
// for the first time. In that case we never change the setting
1615
if(i_config == null){
1616            i_config = config;
1617        }
1618    }
1619
1620    void setName(String JavaDoc a_name) {
1621        i_name = a_name;
1622    }
1623
1624    private final void setStateDead() {
1625        bitTrue(YapConst.DEAD);
1626        bitFalse(YapConst.CONTINUE);
1627    }
1628
1629    private final void setStateUnread() {
1630        bitFalse(YapConst.DEAD);
1631        bitTrue(YapConst.CONTINUE);
1632    }
1633
1634    private final void setStateOK() {
1635        bitFalse(YapConst.DEAD);
1636        bitFalse(YapConst.CONTINUE);
1637    }
1638    
1639    boolean stateDead(){
1640        return bitIsTrue(YapConst.DEAD);
1641    }
1642
1643    private final boolean stateOK() {
1644        return bitIsFalse(YapConst.CONTINUE)
1645            && bitIsFalse(YapConst.DEAD)
1646            && bitIsFalse(YapConst.READING);
1647    }
1648    
1649    final boolean stateOKAndAncestors(){
1650        if(! stateOK() || i_fields == null){
1651            return false;
1652        }
1653        if(i_ancestor != null){
1654            return i_ancestor.stateOKAndAncestors();
1655        }
1656        return true;
1657    }
1658
1659    boolean stateUnread() {
1660        return bitIsTrue(YapConst.CONTINUE)
1661            && bitIsFalse(YapConst.DEAD)
1662            && bitIsFalse(YapConst.READING);
1663    }
1664
1665    boolean storeField(ReflectField a_field) {
1666        if (a_field.isStatic()) {
1667            return false;
1668        }
1669        if (a_field.isTransient()) {
1670            Config4Class config = configOrAncestorConfig();
1671            if (config == null) {
1672                return false;
1673            }
1674            if (!config.storeTransientFields()) {
1675                return false;
1676            }
1677        }
1678        return Platform4.canSetAccessible() || a_field.isPublic();
1679    }
1680    
1681    public StoredField storedField(String JavaDoc a_name, Object JavaDoc a_type) {
1682        synchronized(i_stream.i_lock){
1683            
1684            YapClass yc = i_stream.getYapClass(i_stream.configImpl().reflectorFor(a_type));
1685            
1686            if(i_fields != null){
1687                for (int i = 0; i < i_fields.length; i++) {
1688                    if(i_fields[i].getName().equals(a_name)){
1689                        if(yc == null || yc == i_fields[i].getFieldYapClass(i_stream)){
1690                            return (i_fields[i]);
1691                        }
1692                    }
1693                }
1694            }
1695            
1696            //TODO: implement field creation
1697

1698            return null;
1699        }
1700    }
1701
1702    void storeStaticFieldValues(Transaction trans, boolean force) {
1703        if (!bitIsTrue(YapConst.STATIC_FIELDS_STORED) || force) {
1704            bitTrue(YapConst.STATIC_FIELDS_STORED);
1705            boolean store =
1706                (i_config != null && i_config.staticFieldValuesArePersisted())
1707            || Platform4.storeStaticFieldValues(trans.reflector(), classReflector());
1708            
1709            if (store) {
1710                YapStream stream = trans.stream();
1711                stream.showInternalClasses(true);
1712                Query q = stream.query(trans);
1713                q.constrain(YapConst.CLASS_STATICCLASS);
1714                q.descend("name").constrain(i_name);
1715                StaticClass sc = new StaticClass();
1716                sc.name = i_name;
1717                ObjectSet os = q.execute();
1718                StaticField[] oldFields = null;
1719                if (os.size() > 0) {
1720                    sc = (StaticClass)os.next();
1721                    stream.activate1(trans, sc, 4);
1722                    oldFields = sc.fields;
1723                }
1724                ReflectField[] fields = classReflector().getDeclaredFields();
1725
1726                Collection4 newFields = new Collection4();
1727
1728                for (int i = 0; i < fields.length; i++) {
1729                    if (fields[i].isStatic()) {
1730                        fields[i].setAccessible();
1731                        String JavaDoc fieldName = fields[i].getName();
1732                        Object JavaDoc value = fields[i].get(null);
1733                        boolean handled = false;
1734                        if (oldFields != null) {
1735                            for (int j = 0; j < oldFields.length; j++) {
1736                                if (fieldName.equals(oldFields[j].name)) {
1737                                    if (oldFields[j].value != null
1738                                        && value != null
1739                                        && oldFields[j].value.getClass() == value.getClass()) {
1740                                        long id = stream.getID1(oldFields[j].value);
1741                                        if (id > 0) {
1742                                            if (oldFields[j].value != value) {
1743                                                
1744                                                // This is the clue:
1745
// Bind the current static member to it's old database identity,
1746
// so constants and enums will work with '=='
1747
stream.bind1(trans, value, id);
1748                                                
1749                                                // This may produce unwanted side effects if the static field object
1750
// was modified in the current session. TODO:Add documentation case.
1751

1752                                                stream.refresh(value, Integer.MAX_VALUE);
1753                                                
1754                                                oldFields[j].value = value;
1755                                            }
1756                                            handled = true;
1757                                        }
1758                                    }
1759                                    if (!handled) {
1760                                        if(value == null){
1761                                            try{
1762                                                fields[i].set(null, oldFields[j].value);
1763                                            }catch(Exception JavaDoc ex){
1764                                                // fail silently
1765
}
1766                                            
1767                                        }else{
1768                                            oldFields[j].value = value;
1769                                            if (!stream.isClient()) {
1770                                                stream.setInternal(trans, oldFields[j], true);
1771                                            }
1772                                        }
1773                                    }
1774                                    newFields.add(oldFields[j]);
1775                                    handled = true;
1776                                    break;
1777                                }
1778                            }
1779                        }
1780                        if (!handled) {
1781                            newFields.add(new StaticField(fieldName, value));
1782                        }
1783                    }
1784                }
1785                if (newFields.size() > 0) {
1786                    sc.fields = new StaticField[newFields.size()];
1787                    newFields.toArray(sc.fields);
1788                    if (!stream.isClient()) {
1789                        stream.setInternal(trans, sc, true);
1790                    }
1791                }
1792                stream.showInternalClasses(false);
1793            }
1794        }
1795    }
1796
1797    public boolean supportsIndex() {
1798        return true;
1799    }
1800
1801    public String JavaDoc toString() {
1802        if(i_name == null && i_nameBytes != null){
1803            YapStringIO stringIO =
1804                i_stream == null ?
1805                    YapConst.stringIO
1806                  : i_stream.stringIO();
1807            return stringIO.read(i_nameBytes);
1808        }
1809        return i_name;
1810    }
1811    
1812    public boolean writeArray(Object JavaDoc array, YapReader reader) {
1813        return false;
1814    }
1815
1816    public boolean writeObjectBegin() {
1817        if (!stateOK()) {
1818            return false;
1819        }
1820        return super.writeObjectBegin();
1821    }
1822
1823    public void writeIndexEntry(YapReader a_writer, Object JavaDoc a_object) {
1824        
1825        if(a_object == null){
1826            a_writer.writeInt(0);
1827            return;
1828        }
1829        
1830        a_writer.writeInt(((Integer JavaDoc)a_object).intValue());
1831    }
1832    
1833    public Object JavaDoc writeNew(MarshallerFamily mf, Object JavaDoc a_object, boolean topLevel, YapWriter a_bytes, boolean withIndirection, boolean restoreLinkOffset) {
1834        if (a_object == null) {
1835            a_bytes.writeInt(0);
1836            return new Integer JavaDoc(0);
1837        }
1838
1839        int id = a_bytes.getStream().setInternal(
1840                    a_bytes.getTransaction(),
1841                    a_object,
1842                    a_bytes.getUpdateDepth(), true);
1843        
1844        a_bytes.writeInt(id);
1845        return new Integer JavaDoc(id);
1846    }
1847
1848    public final void writeThis(Transaction trans, YapReader writer) {
1849        MarshallerFamily.current()._class.write(trans, this, writer);
1850    }
1851
1852    // Comparison_______________________
1853

1854    private ReflectClass i_compareTo;
1855    
1856    public void prepareComparison(Transaction a_trans, Object JavaDoc obj) {
1857        prepareComparison(obj);
1858    }
1859
1860    public YapComparable prepareComparison(Object JavaDoc obj) {
1861        if (obj != null) {
1862            if(obj instanceof Integer JavaDoc){
1863                i_lastID = ((Integer JavaDoc)obj).intValue();
1864            }else{
1865                i_lastID = (int)i_stream.getID(obj);
1866            }
1867            i_compareTo = reflector().forObject(obj);
1868        } else {
1869            i_lastID = 0;
1870            i_compareTo = null;
1871        }
1872        return this;
1873    }
1874    
1875    public Object JavaDoc current(){
1876        if(i_compareTo == null){
1877            return null;
1878        }
1879        return new Integer JavaDoc(i_lastID);
1880    }
1881
1882    public int compareTo(Object JavaDoc a_obj) {
1883        if(a_obj instanceof Integer JavaDoc){
1884            return ((Integer JavaDoc)a_obj).intValue() - i_lastID;
1885        }
1886        if( (a_obj == null) && (i_compareTo == null)){
1887            return 0;
1888        }
1889        return -1;
1890    }
1891    
1892    public boolean isEqual(Object JavaDoc obj) {
1893        if (obj == null) {
1894            return i_compareTo == null;
1895        }
1896        return i_compareTo.isAssignableFrom(reflector().forObject(obj));
1897    }
1898
1899    public boolean isGreater(Object JavaDoc obj) {
1900        return false;
1901    }
1902
1903    public boolean isSmaller(Object JavaDoc obj) {
1904        return false;
1905    }
1906
1907    public String JavaDoc toString(MarshallerFamily mf, YapWriter writer, YapObject yapObject, int depth, int maxDepth) {
1908        int length = readFieldCount(writer);
1909        String JavaDoc str = "";
1910        for (int i = 0; i < length; i++) {
1911            str += i_fields[i].toString(mf, writer);
1912        }
1913        if (i_ancestor != null) {
1914            str+= i_ancestor.toString(mf, writer, yapObject, depth, maxDepth);
1915        }
1916        return str;
1917
1918    }
1919
1920    public static void defragObject(ReaderPair readers) {
1921        ObjectHeader header=ObjectHeader.defrag(readers);
1922        header._marshallerFamily._object.defragFields(header.yapClass(),header,readers);
1923        if (Deploy.debug) {
1924            readers.readEnd();
1925        }
1926    }
1927
1928    public void defrag(MarshallerFamily mf, ReaderPair readers, boolean redirect) {
1929        if(hasIndex()) {
1930            readers.copyID();
1931        }
1932        else {
1933            readers.copyUnindexedID();
1934        }
1935        int restLength = (linkLength()-YapConst.INT_LENGTH);
1936        readers.incrementOffset(restLength);
1937    }
1938    
1939    public void defragClass(ReaderPair readers, int classIndexID) throws CorruptionException {
1940        MarshallerFamily mf = MarshallerFamily.current();
1941        mf._class.defrag(this,i_stream.stringIO(), readers, classIndexID);
1942    }
1943
1944    public static YapClass readClass(YapStream stream, YapReader reader) {
1945        ObjectHeader oh = new ObjectHeader(stream, reader);
1946        return oh.yapClass();
1947    }
1948
1949    public boolean isAssignableFrom(YapClass other) {
1950        return classReflector().isAssignableFrom(other.classReflector());
1951    }
1952
1953    public final void defragIndexEntry(ReaderPair readers) {
1954        readers.copyID();
1955    }
1956}
1957
Popular Tags