/* 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.core;
import com.db4o.*;
import com.db4o.foundation.*;
import com.db4o.internal.*;
import com.db4o.reflect.*;
public class ConstructorSupport {
public static ReflectConstructorSpec createConstructor(final ConstructorAwareReflectClass claxx, Class clazz, ReflectorConfiguration config, ReflectConstructor[] constructors){
if (claxx == null) {
return ReflectConstructorSpec.INVALID_CONSTRUCTOR;
}
if (claxx.isAbstract() || claxx.isInterface()) {
return ReflectConstructorSpec.INVALID_CONSTRUCTOR;
}
if(! Platform4.callConstructor()){
boolean skipConstructor = !config.callConstructor(claxx);
if(!claxx.isCollection()) {
ReflectConstructor serializableConstructor = skipConstructor(claxx, skipConstructor, config.testConstructors());
if(serializableConstructor != null){
return new ReflectConstructorSpec(serializableConstructor, null);
}
}
}
if (!config.testConstructors()) {
return new ReflectConstructorSpec(new PlatformReflectConstructor(clazz), null);
}
if(ReflectPlatform.createInstance(clazz) != null) {
return new ReflectConstructorSpec(new PlatformReflectConstructor(clazz), null);
}
Tree sortedConstructors = sortConstructorsByParamsCount(constructors);
return findConstructor(claxx, sortedConstructors);
}
private static ReflectConstructorSpec findConstructor(final ReflectClass claxx,
Tree sortedConstructors) {
if (sortedConstructors == null) {
return ReflectConstructorSpec.INVALID_CONSTRUCTOR;
}
Iterator4 iter = new TreeNodeIterator(sortedConstructors);
while (iter.moveNext()) {
Object current = iter.current();
ReflectConstructor constructor = (ReflectConstructor) ((TreeIntObject) current)._object;
Object[] args = nullArgumentsFor(constructor);
Object res = constructor.newInstance(args);
if (res != null) {
return new ReflectConstructorSpec(constructor, args);
}
}
return ReflectConstructorSpec.INVALID_CONSTRUCTOR;
}
private static Object[] nullArgumentsFor(ReflectConstructor constructor) {
ReflectClass[] paramTypes = constructor.getParameterTypes();
Object[] params = new Object[paramTypes.length];
for (int j = 0; j < params.length; j++) {
params[j] = paramTypes[j].nullValue();
}
return params;
}
private static Tree sortConstructorsByParamsCount(final ReflectConstructor[] constructors) {
Tree sortedConstructors = null;
// sort constructors by parameter count
for (int i = 0; i < constructors.length; i++) {
int parameterCount = constructors[i].getParameterTypes().length;
sortedConstructors = Tree.add(sortedConstructors,
new TreeIntObject(i + constructors.length * parameterCount,
constructors[i]));
}
return sortedConstructors;
}
public static ReflectConstructor skipConstructor(ConstructorAwareReflectClass claxx, boolean skipConstructor, boolean testConstructor) {
if (!skipConstructor) {
return null;
}
ReflectConstructor serializableConstructor = claxx.getSerializableConstructor();
if (serializableConstructor == null) {
return null;
}
if(!testConstructor || Deploy.csharp) {
return serializableConstructor;
}
Object obj = serializableConstructor.newInstance((Object[]) null);
if (obj != null) {
return serializableConstructor;
}
return null;
}
}