/*
* Copyright 1998-2009 University Corporation for Atmospheric Research/Unidata
*
* Portions of this software were developed by the Unidata Program at the
* University Corporation for Atmospheric Research.
*
* Access and use of this software shall impose the following obligations
* and understandings on the user. The user is granted the right, without
* any fee or cost, to use, copy, modify, alter, enhance and distribute
* this software, and any derivative works thereof, and its supporting
* documentation for any purpose whatsoever, provided that this entire
* notice appears in all copies of the software, derivative works and
* supporting documentation. Further, UCAR requests that the user credit
* UCAR/Unidata in any publications that result from the use of this
* software or in any product that includes this software. The names UCAR
* and/or Unidata, however, may not be used in any advertising or publicity
* to endorse or promote any products or commercial entity unless specific
* written permission is obtained from UCAR/Unidata. The user also
* understands that UCAR/Unidata is not obligated to provide the user with
* any support, consulting, training or assistance of any kind with regard
* to the use, operation and performance of this software nor to provide
* the user with any updates, revisions, new versions or "bug fixes."
*
* THIS SOFTWARE IS PROVIDED BY UCAR/UNIDATA "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL UCAR/UNIDATA BE LIABLE FOR ANY SPECIAL,
* INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
* FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
* WITH THE ACCESS, USE OR PERFORMANCE OF THIS SOFTWARE.
*/
package ucar.util.prefs;
import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;
class Bean {
private Object o; // the wrapped object
private BeanParser p = null; // the bean parser (shared for all beans of same class)
// wrap an object in a Bean
public Bean(Object o) {
this.o = o;
}
// create a bean from an XML element
public Bean(org.xml.sax.Attributes atts) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
String className = atts.getValue("class");
Class<?> c = Class.forName(className);
o = c.newInstance();
p = BeanParser.getParser( c);
p.readProperties(o, atts);
}
// write XML using the bean properties of the contained object
public void writeProperties(PrintWriter out) throws IOException {
if (p == null) p = BeanParser.getParser( o.getClass());
p.writeProperties(o, out);
}
// get the wrapped object
public Object getObject() { return o; }
public Class<?> getBeanClass() { return o.getClass(); }
static class Collection {
private java.util.Collection<Object> collect; // the underlying collection
private Class<?> beanClass; // the class of the beans in the collection
private BeanParser p = null; // the bean parser (shared for all beans of same class)
// wrap a collection in a bean
Collection(java.util.Collection<Object> collect) {
this.collect = collect;
if (!collect.isEmpty()) {
Iterator iter = collect.iterator();
beanClass = iter.next().getClass();
p = BeanParser.getParser(beanClass);
}
}
// create a bean collection from an XML element
Collection(org.xml.sax.Attributes atts) throws ClassNotFoundException { // , InstantiationException, IllegalAccessException {
String className = atts.getValue("class");
beanClass = Class.forName( className);
p = BeanParser.getParser( beanClass);
collect = new ArrayList<>();
}
// write XML using the bean properties of the specified object
public void writeProperties(PrintWriter out, Object thiso) throws IOException {
p.writeProperties(thiso, out);
}
// get the underlying java.util.Collection
public java.util.Collection getCollection() { return collect; }
public Class<?> getBeanClass() { return beanClass; }
// write XML using the bean properties of the contained object
public Object readProperties(org.xml.sax.Attributes atts) throws InstantiationException, IllegalAccessException {
Object o = beanClass.newInstance();
p.readProperties(o, atts);
collect.add(o);
return o;
}
}
private static class BeanParser {
private static boolean debugBean = false;
private static Map<Class<?>, BeanParser> parsers = new HashMap<>();
static BeanParser getParser(Class<?> beanClass) {
BeanParser parser;
if (null == (parser = parsers.get(beanClass))) {
parser = new BeanParser(beanClass);
parsers.put(beanClass, parser);
}
return parser;
}
private Map<String, PropertyDescriptor> properties = new TreeMap<>();
private Object[] args = new Object[1];
BeanParser(Class<?> beanClass) {
// get bean info
BeanInfo info;
try {
info = Introspector.getBeanInfo(beanClass, Object.class);
} catch (IntrospectionException e) {
e.printStackTrace();
return;
}
if (debugBean)
System.out.println( "Bean "+beanClass.getName());
// properties must have read and write method
PropertyDescriptor[] pds = info.getPropertyDescriptors();
for (PropertyDescriptor pd : pds) {
if ((pd.getReadMethod() != null) && (pd.getWriteMethod() != null)) {
properties.put(pd.getName(), pd);
if (debugBean) {
System.out.println(" property " + pd.getName());
}
}
}
}
void writeProperties(Object bean, PrintWriter out) throws IOException {
for (PropertyDescriptor pds : properties.values()) {
Method getter = pds.getReadMethod();
try {
Object value = getter.invoke(bean, (Object[]) null);
if (value == null) {
continue;
}
if (value instanceof String) {
value = XMLStore.quote((String) value);
} else if (value instanceof Date) {
value = ((Date) value).getTime();
}
out.print(pds.getName() + "='" + value + "' ");
if (debugBean) {
System.out.println(" property get " + pds.getName() + "='" + value + "' ");
}
} catch (InvocationTargetException | IllegalAccessException e) {
e.printStackTrace();
}
}
}
void readProperties(Object bean, org.xml.sax.Attributes atts) {
for (Object o1 : properties.values()) {
PropertyDescriptor pds = (PropertyDescriptor) o1;
Method setter = pds.getWriteMethod();
if (setter == null) {
continue;
}
try {
String sArg = atts.getValue(pds.getName());
Object arg = getArgument(pds.getPropertyType(), sArg);
if (debugBean) {
System.out.println(" property set " + pds.getName() + "=" + sArg + " == " + arg);
}
if (arg == null) {
return;
}
args[0] = arg;
setter.invoke(bean, args);
} catch (NumberFormatException | InvocationTargetException | IllegalAccessException e) {
e.printStackTrace();
}
}
}
private Object getArgument(Class<?> c, String value) {
if (c == String.class) {
return value;
} else if (c == int.class) {
return Integer.valueOf(value);
} else if (c == double.class) {
return Double.valueOf(value);
} else if (c == boolean.class) {
if (value == null) {
// Boolean.valueOf(null) actually returns "false", which we don't want.
return null;
} else {
return Boolean.valueOf(value);
}
} else if (c == float.class) {
return Float.valueOf(value);
} else if (c == short.class) {
return Short.valueOf(value);
} else if (c == long.class) {
return Long.valueOf(value);
} else if (c == byte.class) {
return Byte.valueOf(value);
} else if (c == Date.class) {
long time = Long.parseLong(value);
return new Date(time);
} else {
return null;
}
}
}
}