KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > db4o > reflect > generic > GenericReflector


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.reflect.generic;
22
23 import com.db4o.*;
24 import com.db4o.foundation.*;
25 import com.db4o.inside.marshall.*;
26 import com.db4o.reflect.*;
27
28 /**
29  * @exclude
30  */

31 public class GenericReflector implements Reflector, DeepClone {
32     
33     private Reflector _delegate;
34     private GenericArrayReflector _array;
35     
36     private final Hashtable4 _classByName = new Hashtable4();
37     private final Hashtable4 _classByClass = new Hashtable4();
38     private final Collection4 _classes = new Collection4();
39     private final Hashtable4 _classByID = new Hashtable4();
40     
41     private Collection4 _collectionPredicates = new Collection4();
42     private Collection4 _collectionUpdateDepths = new Collection4();
43     private Collection4 _pendingClasses = new Collection4();
44     
45     private Transaction _trans;
46     private YapStream _stream;
47     
48     public GenericReflector(Transaction trans, Reflector delegateReflector){
49         setTransaction(trans);
50         _delegate = delegateReflector;
51         if(_delegate != null){
52             _delegate.setParent(this);
53         }
54     }
55     
56     public Object JavaDoc deepClone(Object JavaDoc obj) {
57         GenericReflector myClone = new GenericReflector(null, (Reflector)_delegate.deepClone(this));
58         myClone._collectionPredicates = (Collection4)_collectionPredicates.deepClone(myClone);
59         myClone._collectionUpdateDepths = (Collection4)_collectionUpdateDepths.deepClone(myClone);
60         
61         
62         // Interesting, adding the following messes things up.
63
// Keep the code, since it may make sense to carry the
64
// global reflectors into a running db4o session.
65

66         
67 // Iterator4 i = _classes.iterator();
68
// while(i.hasNext()){
69
// GenericClass clazz = (GenericClass)i.next();
70
// clazz = (GenericClass)clazz.deepClone(myClone);
71
// myClone._classByName.put(clazz.getName(), clazz);
72
// myClone._classes.add(clazz);
73
// }
74

75         return myClone;
76     }
77     
78     YapStream getStream(){
79         return _stream;
80     }
81
82     public boolean hasTransaction(){
83         return _trans != null;
84     }
85     
86     public void setTransaction(Transaction trans){
87         if(trans != null){
88             _trans = trans;
89             _stream = trans.stream();
90         }
91     }
92
93     public ReflectArray array() {
94         if(_array == null){
95             _array = new GenericArrayReflector(this);
96         }
97         return _array;
98     }
99
100     public int collectionUpdateDepth(ReflectClass candidate) {
101         Iterator4 i = _collectionUpdateDepths.iterator();
102         while(i.moveNext()){
103             CollectionUpdateDepthEntry entry = (CollectionUpdateDepthEntry) i.current();
104             if (entry._predicate.match(candidate)) {
105                 return entry._depth;
106             }
107         }
108         return 2;
109         
110         //TODO: will need knowledge for .NET collections here
111
}
112
113     public boolean constructorCallsSupported() {
114         return _delegate.constructorCallsSupported();
115     }
116
117     GenericClass ensureDelegate(ReflectClass clazz){
118         if(clazz == null){
119             return null;
120         }
121         GenericClass claxx = (GenericClass)_classByName.get(clazz.getName());
122         if(claxx == null){
123             // We don't have to worry about the superclass, it can be null
124
// because handling is delegated anyway
125
String JavaDoc name = clazz.getName();
126             claxx = new GenericClass(this,clazz, name,null);
127             _classes.add(claxx);
128             _classByName.put(name, claxx);
129         }
130         return claxx;
131     }
132     
133     public ReflectClass forClass(Class JavaDoc clazz) {
134         if(clazz == null){
135             return null;
136         }
137         ReflectClass claxx = (ReflectClass) _classByClass.get(clazz);
138         if(claxx != null){
139             return claxx;
140         }
141         claxx = forName(clazz.getName());
142         if(claxx != null){
143             _classByClass.put(clazz, claxx);
144             return claxx;
145         }
146         claxx = _delegate.forClass(clazz);
147         if(claxx == null){
148             return null;
149         }
150         claxx = ensureDelegate(claxx);
151         _classByClass.put(clazz, claxx);
152         return claxx;
153     }
154     
155
156     public ReflectClass forName(String JavaDoc className) {
157         ReflectClass clazz = (ReflectClass)_classByName.get(className);
158         if(clazz != null){
159             return clazz;
160         }
161         clazz = _delegate.forName(className);
162         if(clazz != null){
163             return ensureDelegate(clazz);
164         }
165         
166         if(_stream == null) {
167             return null;
168         }
169         
170         if(_stream.classCollection() != null){
171             int classID = _stream.classCollection().getYapClassID(className);
172             if(classID > 0){
173                 clazz = ensureClassInitialised(classID);
174                 _classByName.put(className, clazz);
175                 return clazz;
176             }
177         }
178         
179         return null;
180     }
181
182     public ReflectClass forObject(Object JavaDoc obj) {
183         if (obj instanceof GenericObject){
184             return forGenericObject((GenericObject)obj);
185         }
186         return _delegate.forObject(obj);
187     }
188
189     private ReflectClass forGenericObject(final GenericObject genericObject) {
190         GenericClass claxx = genericObject._class;
191         if(claxx == null){
192             throw new IllegalStateException JavaDoc();
193         }
194         String JavaDoc name = claxx.getName();
195         if(name == null){
196             throw new IllegalStateException JavaDoc();
197         }
198         GenericClass existingClass = (GenericClass) _classByName.get(name);
199         if(existingClass == null){
200             _classByName.put(name, claxx);
201             return claxx;
202         }
203         // TODO: Using .equals() here would be more consistent with
204
// the equals() method in GenericClass.
205
if(existingClass != claxx){
206             
207             throw new IllegalStateException JavaDoc();
208         }
209         
210         return claxx;
211     }
212     
213     public Reflector getDelegate(){
214         return _delegate;
215     }
216
217     public boolean isCollection(ReflectClass candidate) {
218         //candidate = candidate.getDelegate();
219
Iterator4 i = _collectionPredicates.iterator();
220         while(i.moveNext()){
221             if (((ReflectClassPredicate)i.current()).match(candidate)) {
222                 return true;
223             }
224         }
225         return _delegate.isCollection(candidate.getDelegate());
226         
227         //TODO: will need knowledge for .NET collections here
228
// possibility: call registercollection with strings
229
}
230
231     public void registerCollection(Class JavaDoc clazz) {
232         registerCollection(classPredicate(clazz));
233     }
234
235     public void registerCollection(ReflectClassPredicate predicate) {
236         _collectionPredicates.add(predicate);
237     }
238
239     private ReflectClassPredicate classPredicate(Class JavaDoc clazz) {
240         final ReflectClass collectionClass = forClass(clazz);
241         ReflectClassPredicate predicate = new ReflectClassPredicate() {
242             public boolean match(ReflectClass candidate) {
243                 return collectionClass.isAssignableFrom(candidate);
244             }
245         };
246         return predicate;
247     }
248
249     public void registerCollectionUpdateDepth(Class JavaDoc clazz, int depth) {
250         registerCollectionUpdateDepth(classPredicate(clazz), depth);
251     }
252
253     public void registerCollectionUpdateDepth(ReflectClassPredicate predicate, int depth) {
254         _collectionUpdateDepths.add(new CollectionUpdateDepthEntry(predicate, depth));
255     }
256     
257     public void register(GenericClass clazz) {
258         String JavaDoc name = clazz.getName();
259         if(_classByName.get(name) == null){
260             _classByName.put(name, clazz);
261             _classes.add(clazz);
262         }
263     }
264     
265     public ReflectClass[] knownClasses() {
266         readAll();
267         
268         Collection4 classes = new Collection4();
269         collectKnownClasses(classes);
270         return (ReflectClass[])classes.toArray(new ReflectClass[classes.size()]);
271     }
272
273     private void collectKnownClasses(Collection4 classes) {
274         Iterator4 i = _classes.iterator();
275         while(i.moveNext()){
276             GenericClass clazz = (GenericClass)i.current();
277             if(! _stream.i_handlers.ICLASS_INTERNAL.isAssignableFrom(clazz)){
278                 if(! clazz.isSecondClass()){
279                     if(! clazz.isArray()){
280                         classes.add(clazz);
281                     }
282                 }
283             }
284         }
285     }
286     
287     private void readAll(){
288         for(Iterator4 idIter=_stream.classCollection().ids();idIter.moveNext();) {
289             ensureClassAvailability(((Integer JavaDoc)idIter.current()).intValue());
290         }
291         for(Iterator4 idIter=_stream.classCollection().ids();idIter.moveNext();) {
292             ensureClassRead(((Integer JavaDoc)idIter.current()).intValue());
293         }
294     }
295     
296     private GenericClass ensureClassInitialised (int id) {
297         GenericClass ret = ensureClassAvailability(id);
298         while(_pendingClasses.size() > 0) {
299             Collection4 pending = _pendingClasses;
300             _pendingClasses = new Collection4();
301             Iterator4 i = pending.iterator();
302             while(i.moveNext()) {
303                 ensureClassRead(((Integer JavaDoc)i.current()).intValue());
304             }
305         }
306         return ret;
307     }
308     
309     private GenericClass ensureClassAvailability (int id) {
310
311         if(id == 0){
312             return null;
313         }
314         
315         GenericClass ret = (GenericClass)_classByID.get(id);
316         if(ret != null){
317             return ret;
318         }
319         
320         YapReader classreader=_stream.readWriterByID(_trans,id);
321
322         ClassMarshaller marshaller = marshallerFamily()._class;
323         RawClassSpec spec=marshaller.readSpec(_trans, classreader);
324
325         String JavaDoc className = spec.name();
326         ret = (GenericClass)_classByName.get(className);
327         if(ret != null){
328             _classByID.put(id, ret);
329             _pendingClasses.add(new Integer JavaDoc(id));
330             return ret;
331         }
332         
333         ReflectClass nativeClass = _delegate.forName(className);
334         ret = new GenericClass(this, nativeClass,className, ensureClassAvailability(spec.superClassID()));
335         ret.setDeclaredFieldCount(spec.numFields());
336         
337         // step 1 only add to _classByID, keep the class out of _classByName and _classes
338
_classByID.put(id, ret);
339         _pendingClasses.add(new Integer JavaDoc(id));
340         
341         return ret;
342     }
343
344     private MarshallerFamily marshallerFamily() {
345         return MarshallerFamily.forConverterVersion(_stream.converterVersion());
346     }
347     
348     private void ensureClassRead(int id) {
349
350         GenericClass clazz = (GenericClass)_classByID.get(id);
351         
352         YapReader classreader=_stream.readWriterByID(_trans,id);
353
354         ClassMarshaller classMarshaller = marshallerFamily()._class;
355         RawClassSpec classInfo=classMarshaller.readSpec(_trans, classreader);
356         String JavaDoc className=classInfo.name();
357         
358         // Having the class in the _classByName Map for now indicates
359
// that the class is fully read. This is breakable if we start
360
// returning GenericClass'es in other methods like forName
361
// even if a native class has not been found
362
if(_classByName.get(className) != null){
363             return;
364         }
365         
366         // step 2 add the class to _classByName and _classes to denote reading is completed
367
_classByName.put(className, clazz);
368         _classes.add(clazz);
369         
370         int numFields=classInfo.numFields();
371         GenericField[] fields=new GenericField[numFields];
372         FieldMarshaller fieldMarshaller=marshallerFamily()._field;
373         
374         for (int i = 0; i < numFields; i++) {
375             
376             RawFieldSpec fieldInfo=fieldMarshaller.readSpec(_stream, classreader);
377             String JavaDoc fieldName=fieldInfo.name();
378             int handlerID=fieldInfo.handlerID();
379             
380             if (fieldInfo.isVirtual()) {
381                 fields[i] = new GenericVirtualField(fieldName);
382                 continue;
383             }
384             GenericClass fieldClass = null;
385
386             // need to take care of special handlers here
387
switch (handlerID){
388                 case YapHandlers.ANY_ID:
389                     fieldClass = (GenericClass)forClass(Object JavaDoc.class);
390                     break;
391                 case YapHandlers.ANY_ARRAY_ID:
392                     fieldClass = ((GenericClass)forClass(Object JavaDoc.class)).arrayClass();
393                     break;
394                 default:
395                     ensureClassAvailability(handlerID);
396                     fieldClass = (GenericClass)_classByID.get(handlerID);
397             }
398                         
399             fields[i]=new GenericField(fieldName,fieldClass, fieldInfo.isPrimitive(), fieldInfo.isArray(), fieldInfo.isNArray());
400         }
401         
402         clazz.initFields(fields);
403     }
404     
405
406     public void registerPrimitiveClass(int id, String JavaDoc name, GenericConverter converter) {
407         GenericClass existing = (GenericClass)_classByID.get(id);
408         if (existing != null) {
409             if (null != converter) {
410                 existing.setSecondClass();
411             } else {
412                 existing.setConverter(null);
413             }
414             return;
415         }
416         ReflectClass clazz = _delegate.forName(name);
417         
418         GenericClass claxx = null;
419         if(clazz != null) {
420             claxx = ensureDelegate(clazz);
421         }else {
422             claxx = new GenericClass(this, null, name, null);
423             _classByName.put(name, claxx);
424             claxx.initFields(new GenericField[] {new GenericField(null, null, true, false, false)});
425             claxx.setConverter(converter);
426             _classes.add(claxx);
427         }
428         claxx.setSecondClass();
429         claxx.setPrimitive();
430         _classByID.put(id, claxx);
431     }
432
433     public void setParent(Reflector reflector) {
434         // do nothing, the generic reflector does not have a parant
435
}
436
437 }
438
Free Books   Free Magazines  
Popular Tags