/* This file is part of the db4o object database http://www.db4o.com Copyright (C) 2004 - 2011 Versant Corporation http://www.versant.com db4o is free software; you can redistribute it and/or modify it under the terms of version 3 of the GNU General Public License as published by the Free Software Foundation. db4o is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/. */ package com.db4o.reflect.generic; import com.db4o.foundation.*; import com.db4o.reflect.*; /** * @exclude */ public class GenericClass implements ReflectClass, DeepClone { private static final GenericField[] NO_FIELDS = new GenericField[0]; private final GenericReflector _reflector; private final ReflectClass _delegate; private final String _name; private GenericClass _superclass; private GenericClass _array; private boolean _isPrimitive; private int _isCollection; protected GenericConverter _converter; private GenericField[] _fields = NO_FIELDS; private int _declaredFieldCount = -1; private int _fieldCount = -1; private final int _hashCode; public GenericClass(GenericReflector reflector, ReflectClass delegateClass, String name, GenericClass superclass) { _reflector = reflector; _delegate = delegateClass; _name = name; _superclass = superclass; _hashCode = _name.hashCode(); } public GenericClass arrayClass(){ if(_array != null){ return _array; } _array = new GenericArrayClass(_reflector, this, _name, _superclass); return _array; } public Object deepClone(Object obj) { GenericReflector reflector = (GenericReflector)obj; GenericClass superClass = null; if(_superclass != null){ _superclass = (GenericClass)reflector.forName(_superclass.getName()); } GenericClass ret = new GenericClass(reflector, _delegate, _name, superClass); GenericField[] fields = new GenericField[_fields.length]; for (int i = 0; i < fields.length; i++) { fields[i] = (GenericField)_fields[i].deepClone(reflector); } ret.initFields(fields); return ret; } public boolean equals(Object obj) { if(this == obj){ return true; } if(obj == null || getClass() != obj.getClass() ){ return false; } GenericClass otherGC = (GenericClass)obj; if(_hashCode != otherGC.hashCode()){ return false; } return _name.equals(otherGC._name); } public ReflectClass getComponentType() { if(_delegate != null){ return _delegate.getComponentType(); } return null; } // TODO: consider that classes may have two fields of // the same name after refactoring. public ReflectField getDeclaredField(String name) { if(_delegate != null){ return _delegate.getDeclaredField(name); } for (int i = 0; i < _fields.length; i++) { if (_fields[i].getName().equals(name)) { return _fields[i]; } } return null; } public ReflectField[] getDeclaredFields() { if(_delegate != null){ return _delegate.getDeclaredFields(); } return _fields; } public ReflectClass getDelegate(){ if(_delegate != null){ return _delegate; } return this; } int getFieldCount() { if(_fieldCount != -1) { return _fieldCount; } _fieldCount = 0; if(_superclass != null) { _fieldCount = _superclass.getFieldCount(); } if(_declaredFieldCount == -1) { _declaredFieldCount = getDeclaredFields().length; } _fieldCount += _declaredFieldCount; return _fieldCount; } public ReflectMethod getMethod(String methodName, ReflectClass[] paramClasses) { if(_delegate != null){ return _delegate.getMethod(methodName, paramClasses); } return null; } public String getName() { return _name; } public ReflectClass getSuperclass() { if(_superclass != null){ return _superclass; } if(_delegate == null){ return _reflector.forClass(Object.class); } ReflectClass delegateSuperclass = _delegate.getSuperclass(); if(delegateSuperclass != null){ _superclass = _reflector.ensureDelegate(delegateSuperclass); } return _superclass; } public int hashCode() { return _hashCode; } public void initFields(GenericField[] fields) { int startIndex = 0; if(_superclass != null) { startIndex = _superclass.getFieldCount(); } _fields = fields; for (int i = 0; i < _fields.length; i++) { _fields[i].setIndex(startIndex + i); } } // TODO: Consider: Will this method still be necessary // once constructor logic is pushed into the reflectors? public boolean isAbstract() { if(_delegate != null){ return _delegate.isAbstract(); } return false; } public boolean isArray() { if(_delegate != null){ return _delegate.isArray(); } return false; } public boolean isAssignableFrom(ReflectClass subclassCandidate) { if(subclassCandidate == null){ return false; } if (equals(subclassCandidate)) { return true; } if(_delegate != null){ if( subclassCandidate instanceof GenericClass){ subclassCandidate = ((GenericClass)subclassCandidate).getDelegate(); } return _delegate.isAssignableFrom(subclassCandidate); } if (!(subclassCandidate instanceof GenericClass)) { return false; } return isAssignableFrom(subclassCandidate.getSuperclass()); } public boolean isCollection() { if(_isCollection == 1){ return true; } if(_isCollection == -1){ return false; } _isCollection = _reflector.isCollection(this) ? 1 : -1; return isCollection(); } public boolean isInstance(Object candidate) { if(_delegate != null){ return _delegate.isInstance(candidate); } if (!(candidate instanceof GenericObject)) { return false; } return isAssignableFrom(((GenericObject)candidate)._class); } public boolean isInterface() { if(_delegate != null){ return _delegate.isInterface(); } return false; } public boolean isPrimitive() { if(_delegate != null){ return _delegate.isPrimitive(); } return _isPrimitive; } public Object newInstance() { if(_delegate != null){ return _delegate.newInstance(); } return new GenericObject(this); } public Reflector reflector() { if(_delegate != null){ return _delegate.reflector(); } return _reflector; } void setConverter (GenericConverter converter) { _converter = converter; } void setDeclaredFieldCount(int count) { _declaredFieldCount = count; } void setPrimitive() { _isPrimitive = true; } public String toString(){ return "GenericClass " + _name; } public String toString(Object obj) { if(_converter == null) { return "(G) " + getName(); } return _converter.toString((GenericObject) obj); } public boolean ensureCanBeInstantiated() { if(_delegate != null) { return _delegate.ensureCanBeInstantiated(); } return true; } public Object nullValue() { if(_delegate == null) { return null; } return _delegate.nullValue(); } public boolean isSimple() { if(_delegate != null){ return _delegate.isSimple(); } return isPrimitive(); } }