001: /* Copyright (C) 2004 - 2007 db4objects Inc. http://www.db4o.com
002:
003: This file is part of the db4o open source object database.
004:
005: db4o is free software; you can redistribute it and/or modify it under
006: the terms of version 2 of the GNU General Public License as published
007: by the Free Software Foundation and as clarified by db4objects' GPL
008: interpretation policy, available at
009: http://www.db4o.com/about/company/legalpolicies/gplinterpretation/
010: Alternatively you can write to db4objects, Inc., 1900 S Norfolk Street,
011: Suite 350, San Mateo, CA 94403, USA.
012:
013: db4o is distributed in the hope that it will be useful, but WITHOUT ANY
014: WARRANTY; without even the implied warranty of MERCHANTABILITY or
015: FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
016: for more details.
017:
018: You should have received a copy of the GNU General Public License along
019: with this program; if not, write to the Free Software Foundation, Inc.,
020: 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
021: package com.db4o.internal.cs;
022:
023: import com.db4o.foundation.Hashtable4;
024: import com.db4o.reflect.ReflectClass;
025: import com.db4o.reflect.ReflectField;
026: import com.db4o.reflect.generic.GenericClass;
027: import com.db4o.reflect.generic.GenericField;
028: import com.db4o.reflect.generic.GenericReflector;
029:
030: public class ClassInfoHelper {
031:
032: private Hashtable4 _classMetaTable = new Hashtable4();
033:
034: private Hashtable4 _genericClassTable = new Hashtable4();
035:
036: public ClassInfo getClassMeta(ReflectClass claxx) {
037:
038: String className = claxx.getName();
039: if (isSystemClass(className)) {
040: return ClassInfo.newSystemClass(className);
041: }
042:
043: ClassInfo existing = lookupClassMeta(className);
044: if (existing != null) {
045: return existing;
046: }
047:
048: return newUserClassMeta(claxx);
049: }
050:
051: private ClassInfo newUserClassMeta(ReflectClass claxx) {
052:
053: ClassInfo classMeta = ClassInfo.newUserClass(claxx.getName());
054: classMeta.setSuperClass(mapSuperclass(claxx));
055:
056: registerClassMeta(claxx.getName(), classMeta);
057:
058: classMeta.setFields(mapFields(claxx.getDeclaredFields()));
059: return classMeta;
060: }
061:
062: private ClassInfo mapSuperclass(ReflectClass claxx) {
063: ReflectClass super Class = claxx.getSuperclass();
064: if (super Class != null) {
065: return getClassMeta(super Class);
066: }
067: return null;
068: }
069:
070: private FieldInfo[] mapFields(ReflectField[] fields) {
071: FieldInfo[] fieldsMeta = new FieldInfo[fields.length];
072: for (int i = 0; i < fields.length; ++i) {
073: final ReflectField field = fields[i];
074: boolean isArray = field.getFieldType().isArray();
075: ReflectClass fieldClass = isArray ? field.getFieldType()
076: .getComponentType() : field.getFieldType();
077: boolean isPrimitive = fieldClass.isPrimitive();
078: // TODO: need to handle NArray, currently it ignores NArray and alway sets NArray flag false.
079: fieldsMeta[i] = new FieldInfo(field.getName(),
080: getClassMeta(fieldClass), isPrimitive, isArray,
081: false);
082: }
083: return fieldsMeta;
084: }
085:
086: private static boolean isSystemClass(String className) {
087: // TODO: We should send the whole class meta if we'd like to support
088: // java and .net communication (We have this request in our user forum
089: // http://developer.db4o.com/forums/thread/31504.aspx). If we only want
090: // to support java & .net platform separately, then this method should
091: // be moved to Platform4.
092: return className.startsWith("java");
093: }
094:
095: private ClassInfo lookupClassMeta(String className) {
096: return (ClassInfo) _classMetaTable.get(className);
097: }
098:
099: private void registerClassMeta(String className, ClassInfo classMeta) {
100: _classMetaTable.put(className, classMeta);
101: }
102:
103: public GenericClass classMetaToGenericClass(
104: GenericReflector reflector, ClassInfo classMeta) {
105: if (classMeta.isSystemClass()) {
106: return (GenericClass) reflector.forName(classMeta
107: .getClassName());
108: }
109:
110: String className = classMeta.getClassName();
111: // look up from generic class table.
112: GenericClass genericClass = lookupGenericClass(className);
113: if (genericClass != null) {
114: return genericClass;
115: }
116:
117: ReflectClass reflectClass = reflector.forName(className);
118: if (reflectClass != null) {
119: return (GenericClass) reflectClass;
120: }
121:
122: GenericClass genericSuperClass = null;
123: ClassInfo super ClassMeta = classMeta.getSuperClass();
124: if (super ClassMeta != null) {
125: genericSuperClass = classMetaToGenericClass(reflector,
126: super ClassMeta);
127: }
128:
129: genericClass = new GenericClass(reflector, null, className,
130: genericSuperClass);
131: registerGenericClass(className, genericClass);
132:
133: FieldInfo[] fields = classMeta.getFields();
134: GenericField[] genericFields = new GenericField[fields.length];
135:
136: for (int i = 0; i < fields.length; ++i) {
137: ClassInfo fieldClassMeta = fields[i].getFieldClass();
138: String fieldName = fields[i].getFieldName();
139: GenericClass genericFieldClass = classMetaToGenericClass(
140: reflector, fieldClassMeta);
141: genericFields[i] = new GenericField(fieldName,
142: genericFieldClass, fields[i]._isPrimitive);
143: }
144:
145: genericClass.initFields(genericFields);
146: return genericClass;
147: }
148:
149: private GenericClass lookupGenericClass(String className) {
150: return (GenericClass) _genericClassTable.get(className);
151: }
152:
153: private void registerGenericClass(String className,
154: GenericClass classMeta) {
155: _genericClassTable.put(className, classMeta);
156: ((GenericReflector) classMeta.reflector()).register(classMeta);
157: }
158:
159: }
|