/*
* Copyright (C) 2005 Joe Walnes.
* Copyright (C) 2006, 2007, 2008 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
* style license a copy of which has been included with this distribution in
* the LICENSE.txt file.
*
* Created on 12. April 2005 by Joe Walnes
*/
package com.thoughtworks.xstream.converters.javabean;
import com.thoughtworks.xstream.converters.reflection.ObjectAccessException;
import com.thoughtworks.xstream.core.util.OrderRetainingMap;
//import java.beans.BeanInfo;
//import java.beans.IntrospectionException;
//import java.beans.Introspector;
//import java.beans.PropertyDescriptor;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import java.util.WeakHashMap;
public class BeanProvider {
protected static final Object[] NO_PARAMS = new Object[0];
private final Comparator propertyNameComparator;
private final transient Map propertyNameCache = new WeakHashMap();
public BeanProvider() {
this(null);
}
public BeanProvider(final Comparator propertyNameComparator) {
this.propertyNameComparator = propertyNameComparator;
}
public Object newInstance(Class type) {
try {
return getDefaultConstrutor(type).newInstance(NO_PARAMS);
} catch (InstantiationException e) {
throw new ObjectAccessException("Cannot construct " + type.getName(), e);
} catch (IllegalAccessException e) {
throw new ObjectAccessException("Cannot construct " + type.getName(), e);
} catch (InvocationTargetException e) {
if (e.getTargetException() instanceof RuntimeException) {
throw (RuntimeException)e.getTargetException();
} else if (e.getTargetException() instanceof Error) {
throw (Error)e.getTargetException();
} else {
throw new ObjectAccessException("Constructor for "
+ type.getName()
+ " threw an exception", e);
}
}
}
public void visitSerializableProperties(Object object, Visitor visitor) {
// PropertyDescriptor[] propertyDescriptors = getSerializableProperties(object);
// for (int i = 0; i < propertyDescriptors.length; i++) {
// PropertyDescriptor property = propertyDescriptors[i];
// try {
// Method readMethod = property.getReadMethod();
// String name = property.getName();
// Class definedIn = readMethod.getDeclaringClass();
// if (visitor.shouldVisit(name, definedIn)) {
// Object value = readMethod.invoke(object, new Object[0]);
// visitor.visit(name, property.getPropertyType(), definedIn, value);
// }
// } catch (IllegalArgumentException e) {
// throw new ObjectAccessException("Could not get property "
// + object.getClass()
// + "."
// + property.getName(), e);
// } catch (IllegalAccessException e) {
// throw new ObjectAccessException("Could not get property "
// + object.getClass()
// + "."
// + property.getName(), e);
// } catch (InvocationTargetException e) {
// throw new ObjectAccessException("Could not get property "
// + object.getClass()
// + "."
// + property.getName(), e);
// }
// }
}
public void writeProperty(Object object, String propertyName, Object value) {
// PropertyDescriptor property = getProperty(propertyName, object.getClass());
// try {
// property.getWriteMethod().invoke(object, new Object[]{value});
// } catch (IllegalArgumentException e) {
// throw new ObjectAccessException("Could not set property "
// + object.getClass()
// + "."
// + property.getName(), e);
// } catch (IllegalAccessException e) {
// throw new ObjectAccessException("Could not set property "
// + object.getClass()
// + "."
// + property.getName(), e);
// } catch (InvocationTargetException e) {
// throw new ObjectAccessException("Could not set property "
// + object.getClass()
// + "."
// + property.getName(), e);
// }
}
public Class getPropertyType(Object object, String name) {
// return getProperty(name, object.getClass()).getPropertyType();
return null;
}
public boolean propertyDefinedInClass(String name, Class type) {
// return getProperty(name, type) != null;
return false;
}
/**
* Returns true if the Bean provider can instantiate the specified class
*/
public boolean canInstantiate(Class type) {
return getDefaultConstrutor(type) != null;
}
/**
* Returns the default constructor, or null if none is found
*
* @param type
*/
protected Constructor getDefaultConstrutor(Class type) {
Constructor[] constructors = type.getConstructors();
for (int i = 0; i < constructors.length; i++) {
Constructor c = constructors[i];
if (c.getParameterTypes().length == 0 && Modifier.isPublic(c.getModifiers()))
return c;
}
return null;
}
// private PropertyDescriptor[] getSerializableProperties(Object object) {
// Map nameMap = getNameMap(object.getClass());
// List result = new ArrayList(nameMap.size());
// Set names = nameMap.keySet();
// if (propertyNameComparator != null) {
// Set sortedSet = new TreeSet(propertyNameComparator);
// sortedSet.addAll(names);
// names = sortedSet;
// }
// for (final Iterator iter = names.iterator(); iter.hasNext();) {
// final PropertyDescriptor descriptor = (PropertyDescriptor)nameMap.get(iter.next());
// if (canStreamProperty(descriptor)) {
// result.add(descriptor);
// }
// }
// return (PropertyDescriptor[])result.toArray(new PropertyDescriptor[result.size()]);
// }
// protected boolean canStreamProperty(PropertyDescriptor descriptor) {
// return descriptor.getReadMethod() != null && descriptor.getWriteMethod() != null;
// }
public boolean propertyWriteable(String name, Class type) {
// PropertyDescriptor property = getProperty(name, type);
// return property.getWriteMethod() != null;
return false;
}
// private PropertyDescriptor getProperty(String name, Class type) {
// return (PropertyDescriptor)getNameMap(type).get(name);
// }
private Map getNameMap(Class type) {
Map nameMap = (Map)propertyNameCache.get(type);
if (nameMap == null) {
// BeanInfo beanInfo;
// try {
// beanInfo = Introspector.getBeanInfo(type, Object.class);
// } catch (IntrospectionException e) {
// throw new ObjectAccessException("Cannot get BeanInfo of type " + type.getName(), e);
// }
nameMap = new OrderRetainingMap();
propertyNameCache.put(type, nameMap);
// PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
// for (int i = 0; i < propertyDescriptors.length; i++) {
// PropertyDescriptor descriptor = propertyDescriptors[i];
// nameMap.put(descriptor.getName(), descriptor);
// }
}
return nameMap;
}
interface Visitor {
boolean shouldVisit(String name, Class definedIn);
void visit(String name, Class type, Class definedIn, Object value);
}
}