KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > db4o > YapField


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.ObjectTranslator;
24 import com.db4o.ext.StoredField;
25 import com.db4o.foundation.*;
26 import com.db4o.inside.Exceptions4;
27 import com.db4o.inside.btree.*;
28 import com.db4o.inside.marshall.*;
29 import com.db4o.inside.slots.*;
30 import com.db4o.reflect.*;
31 import com.db4o.reflect.generic.*;
32
33 /**
34  * @exclude
35  */

36 public class YapField implements StoredField {
37
38     private YapClass i_yapClass;
39
40     // position in YapClass i_fields
41
private int i_arrayPosition;
42
43     protected String JavaDoc i_name;
44
45     private boolean i_isArray;
46
47     private boolean i_isNArray;
48
49     private boolean i_isPrimitive;
50
51     private ReflectField i_javaField;
52
53     TypeHandler4 i_handler;
54
55     private int i_handlerID;
56
57     private int i_state;
58
59     private static final int NOT_LOADED = 0;
60
61     private static final int UNAVAILABLE = -1;
62
63     private static final int AVAILABLE = 1;
64
65     private Config4Field i_config;
66
67     private Db4oTypeImpl i_db4oType;
68     
69     private BTree _index;
70
71     static final YapField[] EMPTY_ARRAY = new YapField[0];
72
73     public YapField(YapClass a_yapClass) {
74         i_yapClass = a_yapClass;
75     }
76
77     YapField(YapClass a_yapClass, ObjectTranslator a_translator) {
78         // for YapFieldTranslator only
79
i_yapClass = a_yapClass;
80         init(a_yapClass, a_translator.getClass().getName());
81         i_state = AVAILABLE;
82         YapStream stream =getStream();
83         i_handler = stream.i_handlers.handlerForClass(
84             stream, stream.reflector().forClass(a_translator.storedClass()));
85     }
86
87     YapField(YapClass a_yapClass, ReflectField a_field, TypeHandler4 a_handler) {
88         init(a_yapClass, a_field.getName());
89         i_javaField = a_field;
90         i_javaField.setAccessible();
91         i_handler = a_handler;
92         
93         // TODO: beautify !!! possibly pull up isPrimitive to ReflectField
94
boolean isPrimitive = false;
95         if(a_field instanceof GenericField){
96             isPrimitive = ((GenericField)a_field).isPrimitive();
97         }
98         configure( a_field.getFieldType(), isPrimitive);
99         checkDb4oType();
100         i_state = AVAILABLE;
101     }
102
103     public void addFieldIndex(MarshallerFamily mf, YapClass yapClass, YapWriter writer, Slot oldSlot) {
104         if (! hasIndex()) {
105             writer.incrementOffset(linkLength());
106             return;
107         }
108         
109         addIndexEntry(writer, readIndexEntry(mf, writer));
110     }
111
112     protected void addIndexEntry(YapWriter a_bytes, Object JavaDoc indexEntry) {
113         addIndexEntry(a_bytes.getTransaction(), a_bytes.getID(), indexEntry);
114     }
115
116     public void addIndexEntry(Transaction trans, int parentID, Object JavaDoc indexEntry) {
117         if (! hasIndex()) {
118             return;
119         }
120             
121         BTree index = getIndex(trans);
122         
123         // Although we checked hasIndex() already, we have to check
124
// again here since index creation in YapFieldUUID can be
125
// unsuccessful if it's called too early for PBootRecord.
126
if(index == null){
127             return;
128         }
129         
130         index.add(trans, new FieldIndexKey(parentID, indexEntry));
131     }
132     
133     public boolean canUseNullBitmap(){
134         return true;
135     }
136     
137     // alive() checked
138
public Object JavaDoc readIndexEntry(MarshallerFamily mf, YapWriter writer){
139         try {
140             return i_handler.readIndexEntry(mf, writer);
141         } catch (CorruptionException e) {
142         }
143         return null;
144     }
145     
146     public void removeIndexEntry(Transaction trans, int parentID, Object JavaDoc indexEntry){
147         if (! hasIndex()) {
148             return;
149         }
150         
151         if(_index == null){
152             return;
153         }
154         _index.remove(trans, new FieldIndexKey(parentID, indexEntry));
155     }
156
157     public boolean alive() {
158         if (i_state == AVAILABLE) {
159             return true;
160         }
161         if (i_state == NOT_LOADED) {
162
163             if (i_handler == null) {
164
165                 // this may happen if the local YapClassCollection has not
166
// been updated from the server and presumably in some
167
// refactoring cases. The origin is not verified but we
168
// saw a database that had 0 in some wrapper IDs.
169

170                 // We try to heal the problem by re-reading the class.
171

172                 // This could be inherently dangerous, if the class type of
173
// a field was modified.
174

175                 // TODO: add class refactoring features
176

177                 i_handler = loadJavaField1();
178                 if (i_handler != null) {
179                     if (i_handlerID == 0) {
180                         i_handlerID = i_handler.getID();
181                     } else {
182                         if (i_handler.getID() != i_handlerID) {
183                             i_handler = null;
184                         }
185                     }
186                 }
187             }
188
189             loadJavaField();
190             
191             if(i_handler == null || i_javaField == null){
192                 i_state = UNAVAILABLE;
193                 i_javaField = null;
194             }else{
195
196                 // TODO: This part is not quite correct.
197
// We are using the old array information read from file to wrap.
198

199                 // If a schema evolution changes an array to a different variable,
200
// we are in trouble here.
201

202                 i_handler = wrapHandlerToArrays(getStream(), i_handler);
203
204                 i_state = AVAILABLE;
205                 checkDb4oType();
206             }
207         }
208         return i_state == AVAILABLE;
209
210     }
211
212     boolean canAddToQuery(String JavaDoc fieldName){
213         if(! alive()){
214             return false;
215         }
216         return fieldName.equals(getName()) && getParentYapClass() != null && !getParentYapClass().isInternal();
217     }
218     
219     boolean canHold(ReflectClass claxx) {
220         // alive() is checked in QField caller
221
if (claxx == null) {
222             return !i_isPrimitive;
223         }
224         return i_handler.canHold(claxx);
225     }
226
227     public Object JavaDoc coerce(ReflectClass claxx, Object JavaDoc obj) {
228         // alive() is checked in QField caller
229

230         if (claxx == null || obj == null) {
231             return i_isPrimitive ? No4.INSTANCE : obj;
232         }
233         return i_handler.coerce(claxx, obj);
234     }
235
236     public final boolean canLoadByIndex() {
237         if (i_handler instanceof YapClass) {
238             YapClass yc = (YapClass) i_handler;
239             if(yc.isArray()){
240                 return false;
241             }
242         }
243         return true;
244     }
245
246     void cascadeActivation(Transaction a_trans, Object JavaDoc a_object, int a_depth,
247         boolean a_activate) {
248         if (alive()) {
249             try {
250                 Object JavaDoc cascadeTo = getOrCreate(a_trans, a_object);
251                 if (cascadeTo != null && i_handler != null) {
252                     i_handler.cascadeActivation(a_trans, cascadeTo, a_depth,
253                         a_activate);
254                 }
255             } catch (Exception JavaDoc e) {
256             }
257         }
258     }
259
260     private void checkDb4oType() {
261         if (i_javaField != null) {
262             if (getStream().i_handlers.ICLASS_DB4OTYPE.isAssignableFrom(i_javaField.getFieldType())) {
263                 i_db4oType = YapHandlers.getDb4oType(i_javaField.getFieldType());
264             }
265         }
266     }
267
268     void collectConstraints(Transaction a_trans, QConObject a_parent,
269         Object JavaDoc a_template, Visitor4 a_visitor) {
270         Object JavaDoc obj = getOn(a_trans, a_template);
271         if (obj != null) {
272             Collection4 objs = Platform4.flattenCollection(a_trans.stream(), obj);
273             Iterator4 j = objs.iterator();
274             while (j.moveNext()) {
275                 obj = j.current();
276                 if (obj != null) {
277                     
278                     if (i_isPrimitive) {
279                         if (i_handler instanceof YapJavaClass) {
280                             if (obj.equals(((YapJavaClass) i_handler)
281                                 .primitiveNull())) {
282                                 return;
283                             }
284                         }
285                     }
286                     
287                     if(Deploy.csharp){
288                         if(Platform4.ignoreAsConstraint(obj)){
289                             return;
290                         }
291                     }
292                     if (!a_parent.hasObjectInParentPath(obj)) {
293                         a_visitor.visit(new QConObject(a_trans, a_parent,
294                             qField(a_trans), obj));
295                     }
296                 }
297             }
298         }
299     }
300
301     public final TreeInt collectIDs(MarshallerFamily mf, TreeInt tree, YapWriter a_bytes) {
302         if (alive()) {
303             if (i_handler instanceof YapClass) {
304                 tree = (TreeInt) Tree.add(tree, new TreeInt(a_bytes.readInt()));
305             } else if (i_handler instanceof YapArray) {
306                 tree = ((YapArray) i_handler).collectIDs(mf, tree, a_bytes);
307             }
308         }
309         return tree;
310
311     }
312
313     void configure(ReflectClass a_class, boolean isPrimitive) {
314         i_isPrimitive = isPrimitive | a_class.isPrimitive();
315         i_isArray = a_class.isArray();
316         if (i_isArray) {
317             ReflectArray reflectArray = getStream().reflector().array();
318             i_isNArray = reflectArray.isNDimensional(a_class);
319             a_class = reflectArray.getComponentType(a_class);
320             if (Deploy.csharp) {
321             } else {
322                 i_isPrimitive = a_class.isPrimitive();
323             }
324             if (i_isNArray) {
325                 i_handler = new YapArrayN(getStream(), i_handler, i_isPrimitive);
326             } else {
327                 i_handler = new YapArray(getStream(), i_handler, i_isPrimitive);
328             }
329         }
330     }
331
332     void deactivate(Transaction a_trans, Object JavaDoc a_onObject, int a_depth) {
333         if (!alive()) {
334             return;
335         }
336         try {
337             boolean isEnumClass = i_yapClass.isEnum();
338             if (i_isPrimitive && !i_isArray) {
339                 if(!isEnumClass) {
340                     i_javaField.set(a_onObject, ((YapJavaClass) i_handler)
341                         .primitiveNull());
342                 }
343                 return;
344             }
345             if (a_depth > 0) {
346                 cascadeActivation(a_trans, a_onObject, a_depth, false);
347             }
348             if(!isEnumClass) {
349                 i_javaField.set(a_onObject, null);
350             }
351         } catch (Throwable JavaDoc t) {
352         }
353     }
354
355     public void delete(MarshallerFamily mf, YapWriter a_bytes, boolean isUpdate) {
356         if (! alive()) {
357             incrementOffset(a_bytes);
358             return;
359         }
360         
361         removeIndexEntry(mf, a_bytes);
362         
363         boolean dotnetValueType = false;
364         if(Deploy.csharp){
365             dotnetValueType = Platform4.isValueType(i_handler.classReflector());
366         }
367         
368         if ((i_config != null && i_config.cascadeOnDelete() == YapConst.YES)
369             || dotnetValueType) {
370             int preserveCascade = a_bytes.cascadeDeletes();
371             a_bytes.setCascadeDeletes(1);
372             i_handler.deleteEmbedded(mf, a_bytes);
373             a_bytes.setCascadeDeletes(preserveCascade);
374         }else if(i_config != null && i_config.cascadeOnDelete() == YapConst.NO){
375             int preserveCascade = a_bytes.cascadeDeletes();
376             a_bytes.setCascadeDeletes(0);
377             i_handler.deleteEmbedded(mf, a_bytes);
378             a_bytes.setCascadeDeletes(preserveCascade);
379         } else {
380             i_handler.deleteEmbedded(mf, a_bytes);
381         }
382     }
383
384     private final void removeIndexEntry(MarshallerFamily mf, YapWriter a_bytes) {
385         if(! hasIndex()){
386             return;
387         }
388         int offset = a_bytes._offset;
389         Object JavaDoc obj = null;
390         try {
391             obj = i_handler.readIndexEntry(mf, a_bytes);
392         } catch (CorruptionException e) {
393             if(Debug.atHome){
394                 e.printStackTrace();
395             }
396         }
397         removeIndexEntry(a_bytes.getTransaction(), a_bytes.getID(), obj);
398         a_bytes._offset = offset;
399     }
400
401     public boolean equals(Object JavaDoc obj) {
402         if (obj instanceof YapField) {
403             YapField yapField = (YapField) obj;
404             yapField.alive();
405             alive();
406             return yapField.i_isPrimitive == i_isPrimitive
407                 && yapField.i_handler.equals(i_handler)
408                 && yapField.i_name.equals(i_name);
409         }
410         return false;
411     }
412
413     public Object JavaDoc get(Object JavaDoc a_onObject) {
414         if (i_yapClass != null) {
415             YapStream stream = i_yapClass.getStream();
416             if (stream != null) {
417                 synchronized (stream.i_lock) {
418                     stream.checkClosed();
419                     YapObject yo = stream.getYapObject(a_onObject);
420                     if (yo != null) {
421                         int id = yo.getID();
422                         if (id > 0) {
423                             YapWriter writer = stream.readWriterByID(stream
424                                 .getTransaction(), id);
425                             if (writer != null) {
426                                 
427                                 writer._offset = 0;
428                                 ObjectHeader oh = new ObjectHeader(stream, i_yapClass, writer);
429                                 if(oh.objectMarshaller().findOffset(i_yapClass,oh._headerAttributes, writer, this)){
430                                     try {
431                                         return read(oh._marshallerFamily, writer);
432                                     } catch (CorruptionException e) {
433                                         if (Debug.atHome) {
434                                             e.printStackTrace();
435                                         }
436                                     }
437                                 }
438                             }
439                         }
440                     }
441                 }
442             }
443         }
444         return null;
445     }
446
447     public String JavaDoc getName() {
448         return i_name;
449     }
450
451     YapClass getFieldYapClass(YapStream a_stream) {
452         // alive needs to be checked by all callers: Done
453
return i_handler.getYapClass(a_stream);
454     }
455     
456     public TypeHandler4 getHandler() {
457         // alive needs to be checked by all callers: Done
458
return i_handler;
459     }
460     
461     public int getHandlerID(){
462         return i_handlerID;
463     }
464
465     public Object JavaDoc getOn(Transaction a_trans, Object JavaDoc a_OnObject) {
466         if (alive()) {
467             try {
468                 return i_javaField.get(a_OnObject);
469             } catch (Throwable JavaDoc t) {
470                 // this is typically the case, if a field is removed from an
471
// object.
472
}
473         }
474         return null;
475     }
476
477     /**
478      * dirty hack for com.db4o.types some of them need to be set automatically
479      * TODO: Derive from YapField for Db4oTypes
480      */

481     public Object JavaDoc getOrCreate(Transaction a_trans, Object JavaDoc a_OnObject) {
482         if (alive()) {
483             try {
484                 Object JavaDoc obj = i_javaField.get(a_OnObject);
485                 if (i_db4oType != null) {
486                     if (obj == null) {
487                         obj = i_db4oType.createDefault(a_trans);
488                         i_javaField.set(a_OnObject, obj);
489                     }
490                 }
491                 return obj;
492             } catch (Throwable JavaDoc t) {
493                 if(Debug.atHome){
494                     t.printStackTrace();
495                 }
496             }
497             // this is typically the case, if a field is removed from an
498
// object.
499
}
500         return null;
501     }
502
503     public YapClass getParentYapClass() {
504         // alive needs to be checked by all callers: Done
505
return i_yapClass;
506     }
507
508     public ReflectClass getStoredType() {
509         if (!Deploy.csharp) {
510             if (i_isPrimitive) {
511                 return i_handler.primitiveClassReflector();
512             }
513         }
514         if(i_handler==null) {
515             return null;
516         }
517         return i_handler.classReflector();
518     }
519     
520     public YapStream getStream(){
521         if(i_yapClass == null){
522             return null;
523         }
524         return i_yapClass.getStream();
525     }
526     
527     public boolean hasConfig() {
528         return i_config!=null;
529     }
530     
531     public boolean hasIndex() {
532         // alive needs to be checked by all callers: Done
533
return _index != null;
534     }
535
536     public final void incrementOffset(YapReader a_bytes) {
537         a_bytes.incrementOffset(linkLength());
538     }
539
540     public final void init(YapClass a_yapClass, String JavaDoc a_name) {
541         i_yapClass = a_yapClass;
542         i_name = a_name;
543         initIndex(a_yapClass, a_name);
544     }
545
546     final void initIndex(YapClass a_yapClass, String JavaDoc a_name) {
547         if (a_yapClass.i_config != null) {
548             i_config = a_yapClass.i_config.configField(a_name);
549             if (Debug.configureAllFields) {
550                 if (i_config == null) {
551                     i_config = (Config4Field) a_yapClass.i_config
552                         .objectField(i_name);
553                 }
554             }
555         }
556     }
557     
558     public void init(int handlerID, boolean isPrimitive, boolean isArray, boolean isNArray) {
559         i_handlerID = handlerID;
560         i_isPrimitive = isPrimitive;
561         i_isArray = isArray;
562         i_isNArray = isNArray;
563     }
564
565     private boolean _initialized=false;
566
567     final void initConfigOnUp(Transaction trans) {
568         if (i_config != null&&!_initialized) {
569             _initialized=true;
570             i_config.initOnUp(trans, this);
571         }
572     }
573
574     public void instantiate(MarshallerFamily mf, YapObject a_yapObject, Object JavaDoc a_onObject, YapWriter a_bytes)
575         throws CorruptionException {
576         
577         if (! alive()) {
578             incrementOffset(a_bytes);
579             return;
580         }
581             
582         Object JavaDoc toSet = null;
583         try {
584             toSet = read(mf, a_bytes);
585         } catch (Exception JavaDoc e) {
586             throw new CorruptionException();
587         }
588         if (i_db4oType != null) {
589             if (toSet != null) {
590                 ((Db4oTypeImpl) toSet).setTrans(a_bytes.getTransaction());
591             }
592         }
593         
594         set(a_onObject, toSet);
595         
596     }
597
598     public boolean isArray() {
599         return i_isArray;
600     }
601
602     
603     public int linkLength() {
604         alive();
605         if (i_handler == null) {
606             // must be a YapClass
607
return YapConst.ID_LENGTH;
608         }
609         return i_handler.linkLength();
610     }
611     
612     public void calculateLengths(Transaction trans, ObjectHeaderAttributes header, Object JavaDoc obj){
613         alive();
614         if (i_handler == null) {
615             
616             // must be a YapClass
617

618             header.addBaseLength(YapConst.ID_LENGTH);
619             return ;
620         }
621         
622         i_handler.calculateLengths(trans, header, true, obj, true);
623     }
624     
625
626     public void loadHandler(YapStream a_stream) {
627         i_handler=a_stream.handlerByID(i_handlerID);
628     }
629
630     private void loadJavaField() {
631         TypeHandler4 handler = loadJavaField1();
632         if (handler == null || (!handler.equals(i_handler))) {
633             i_javaField = null;
634             i_state = UNAVAILABLE;
635         }
636     }
637
638     private TypeHandler4 loadJavaField1() {
639         try {
640             YapStream stream = i_yapClass.getStream();
641             ReflectClass claxx = i_yapClass.classReflector();
642             if(claxx == null){
643                 return null;
644             }
645             i_javaField = claxx.getDeclaredField(i_name);
646             if (i_javaField == null) {
647                 return null;
648             }
649             i_javaField.setAccessible();
650             stream.showInternalClasses(true);
651             TypeHandler4 handler = stream.i_handlers.handlerForClass(stream,
652                 i_javaField.getFieldType());
653             stream.showInternalClasses(false);
654             return handler;
655         } catch (Exception JavaDoc e) {
656             if (Debug.atHome) {
657                 e.printStackTrace();
658             }
659         }
660         return null;
661     }
662
663     public void marshall(
664             YapObject yo,
665             Object JavaDoc obj,
666             MarshallerFamily mf,
667             YapWriter writer,
668             Config4Class config,
669             boolean isNew) {
670         
671         // alive needs to be checked by all callers: Done
672

673         Object JavaDoc indexEntry = null;
674         
675         if (obj != null
676             && ((config != null && (config.cascadeOnUpdate() == YapConst.YES)) || (i_config != null && (i_config.cascadeOnUpdate() == YapConst.YES)))) {
677             int min = 1;
678             if (i_yapClass.isCollection(obj)) {
679                 GenericReflector reflector = i_yapClass.reflector();
680                 min = reflector.collectionUpdateDepth(reflector.forObject(obj));
681             }
682             int updateDepth = writer.getUpdateDepth();
683             if (updateDepth < min) {
684                 writer.setUpdateDepth(min);
685             }
686             indexEntry = i_handler.writeNew(mf, obj, true, writer, true, true);
687             writer.setUpdateDepth(updateDepth);
688         } else {
689             indexEntry = i_handler.writeNew(mf, obj, true, writer, true, true);
690         }
691         addIndexEntry(writer, indexEntry);
692     }
693
694     public boolean needsArrayAndPrimitiveInfo(){
695         return true;
696     }
697
698     public boolean needsHandlerId(){
699         return true;
700     }
701     
702     YapComparable prepareComparison(Object JavaDoc obj) {
703         if (alive()) {
704             i_handler.prepareComparison(obj);
705             return i_handler;
706         }
707         return null;
708     }
709     
710     QField qField(Transaction a_trans) {
711         int yapClassID = 0;
712         if(i_yapClass != null){
713             yapClassID = i_yapClass.getID();
714         }
715         return new QField(a_trans, i_name, this, yapClassID, i_arrayPosition);
716     }
717
718     Object JavaDoc read(MarshallerFamily mf, YapWriter a_bytes) throws CorruptionException {
719         if (!alive()) {
720             incrementOffset(a_bytes);
721             return null;
722         }
723         return i_handler.read(mf, a_bytes, true);
724     }
725
726     Object JavaDoc readQuery(Transaction a_trans, MarshallerFamily mf, YapReader a_reader)
727         throws CorruptionException {
728         return i_handler.readQuery(a_trans, mf, true, a_reader, false);
729     }
730     
731     public void readVirtualAttribute(Transaction a_trans, YapReader a_reader, YapObject a_yapObject) {
732         a_reader.incrementOffset(i_handler.linkLength());
733     }
734
735     void refresh() {
736         TypeHandler4 handler = loadJavaField1();
737         if (handler != null) {
738             handler = wrapHandlerToArrays(getStream(), handler);
739             if (handler.equals(i_handler)) {
740                 return;
741             }
742         }
743         i_javaField = null;
744         i_state = UNAVAILABLE;
745     }
746
747     public void rename(String JavaDoc newName) {
748         YapStream stream = i_yapClass.getStream();
749         if (! stream.isClient()) {
750             i_name = newName;
751             i_yapClass.setStateDirty();
752             i_yapClass.write(stream.getSystemTransaction());
753         } else {
754             Exceptions4.throwRuntimeException(58);
755         }
756     }
757
758     public void setArrayPosition(int a_index) {
759         i_arrayPosition = a_index;
760     }
761     
762     public final void set(Object JavaDoc onObject, Object JavaDoc obj){
763         
764         try {
765             i_javaField.set(onObject, obj);
766         } catch (Throwable JavaDoc t) {
767             if(Debug.atHome){
768                 t.printStackTrace();
769             }
770         }
771     }
772
773     void setName(String JavaDoc a_name) {
774         i_name = a_name;
775     }
776
777     boolean supportsIndex() {
778         return alive() && i_handler.supportsIndex();
779     }
780     
781     public final void traverseValues(final Visitor4 userVisitor) {
782         if(! alive()){
783             return;
784         }
785         
786         assertHasIndex();
787         
788         YapStream stream = i_yapClass.getStream();
789         if(stream.isClient()){
790             Exceptions4.throwRuntimeException(Messages.CLIENT_SERVER_UNSUPPORTED);
791         }
792         
793         synchronized(stream.lock()){
794             final Transaction trans = stream.getTransaction();
795             _index.traverseKeys(trans, new Visitor4() {
796                 public void visit(Object JavaDoc obj) {
797                     FieldIndexKey key = (FieldIndexKey) obj;
798                     userVisitor.visit(i_handler.indexEntryToObject(trans, key.value()));
799                 }
800             });
801         }
802     }
803
804     private void assertHasIndex() {
805         if(! hasIndex()){
806             Exceptions4.throwRuntimeException(Messages.ONLY_FOR_INDEXED_FIELDS);
807         }
808     }
809
810
811     private final TypeHandler4 wrapHandlerToArrays(YapStream a_stream, TypeHandler4 a_handler) {
812         if (i_isNArray) {
813             a_handler = new YapArrayN(a_stream, a_handler, i_isPrimitive);
814         } else {
815             if (i_isArray) {
816                 a_handler = new YapArray(a_stream, a_handler, i_isPrimitive);
817             }
818         }
819         return a_handler;
820     }
821
822     public String JavaDoc toString() {
823         StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
824         if (i_yapClass != null) {
825             sb.append(i_yapClass.getName());
826             sb.append(".");
827             sb.append(getName());
828         }
829         return sb.toString();
830     }
831
832     public final String JavaDoc toString(MarshallerFamily mf, YapWriter writer) {
833         String JavaDoc str = "\n Field " + i_name;
834         if (! alive()) {
835             incrementOffset(writer);
836         }else{
837             Object JavaDoc obj = null;
838             try{
839                 obj = read(mf, writer);
840             }catch(Exception JavaDoc e){
841                 // can happen
842
}
843             if(obj == null){
844                 str += "\n [null]";
845             }else{
846                 str+="\n " + obj.toString();
847             }
848         }
849         return str;
850     }
851
852     public void initIndex(Transaction systemTrans) {
853         initIndex(systemTrans, 0);
854     }
855
856     public void initIndex(Transaction systemTrans, final int id) {
857         if(_index != null){
858             throw new IllegalStateException JavaDoc();
859         }
860         if(systemTrans.stream().isClient()){
861             return;
862         }
863         _index = newBTree(systemTrans, id);
864     }
865
866     protected BTree newBTree(Transaction systemTrans, final int id) {
867         return new BTree(systemTrans, id, new FieldIndexKeyHandler(systemTrans.stream(), i_handler));
868     }
869     
870     public BTree getIndex(Transaction transaction){
871         return _index;
872     }
873
874     public boolean isVirtual() {
875         return false;
876     }
877
878     public boolean isPrimitive() {
879         return i_isPrimitive;
880     }
881     
882     public BTreeRange search(Transaction transaction, Object JavaDoc value) {
883         assertHasIndex();
884         BTreeNodeSearchResult lowerBound = searchLowerBound(transaction, value);
885         BTreeNodeSearchResult upperBound = searchUpperBound(transaction, value);
886         return lowerBound.createIncludingRange(upperBound);
887     }
888     
889     private BTreeNodeSearchResult searchUpperBound(Transaction transaction, final Object JavaDoc value) {
890         return searchBound(transaction, Integer.MAX_VALUE, value);
891     }
892
893     private BTreeNodeSearchResult searchLowerBound(Transaction transaction, final Object JavaDoc value) {
894         return searchBound(transaction, 0, value);
895     }
896
897     private BTreeNodeSearchResult searchBound(Transaction transaction, int bound, Object JavaDoc keyPart) {
898         return getIndex(transaction).searchLeaf(transaction, new FieldIndexKey(bound, keyPart), SearchTarget.LOWEST);
899     }
900
901     public boolean rebuildIndexForClass(YapFile stream, YapClass yapClass) {
902         // FIXME: BTree traversal over index here.
903
long[] ids = yapClass.getIDs();
904         for (int i = 0; i < ids.length; i++) {
905             rebuildIndexForObject(stream, yapClass, (int)ids[i]);
906         }
907         return ids.length > 0;
908     }
909
910     protected void rebuildIndexForObject(YapFile stream, final YapClass yapClass, final int objectId) {
911         YapWriter writer = stream.readWriterByID(stream.getSystemTransaction(), objectId);
912         if (writer != null) {
913             rebuildIndexForWriter(stream, writer, objectId);
914         } else {
915             if(Deploy.debug){
916                 throw new RuntimeException JavaDoc("Unexpected null object for ID");
917             }
918         }
919     }
920
921     protected void rebuildIndexForWriter(YapFile stream, YapWriter writer, final int objectId) {
922         ObjectHeader oh = new ObjectHeader(stream, writer);
923         Object JavaDoc obj = readIndexEntryForRebuild(writer, oh);
924         addIndexEntry(stream.getSystemTransaction(), objectId, obj);
925     }
926
927     private Object JavaDoc readIndexEntryForRebuild(YapWriter writer, ObjectHeader oh) {
928         return oh.objectMarshaller().readIndexEntry(oh.yapClass(), oh._headerAttributes, this, writer);
929     }
930
931     public void dropIndex(Transaction systemTrans) {
932         if(_index == null){
933             return;
934         }
935         YapStream stream = systemTrans.stream();
936         if (stream.configImpl().messageLevel() > YapConst.NONE) {
937             stream.message("dropping index " + toString());
938         }
939         _index.free(systemTrans);
940         stream.setDirtyInSystemTransaction(getParentYapClass());
941         _index = null;
942     }
943     
944     public void defragField(MarshallerFamily mf,ReaderPair readers) {
945         getHandler().defrag(mf, readers, true);
946     }
947 }
Popular Tags