package org.xins.common;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.AbstractList;
import java.util.AbstractSet;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import org.w3c.dom.Attr;
import org.xins.common.service.Descriptor;
import org.xins.common.service.TargetDescriptor;
import org.xins.common.text.TextUtils;
import org.xins.common.types.EnumItem;
import org.xins.common.types.ItemList;
import org.xins.common.types.standard.Date;
import org.xins.common.types.standard.Timestamp;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.xins.common.collections.PropertyReader;
import org.xins.common.collections.PropertyReaderConverter;
import org.xins.common.xml.ElementList;
public class BeanUtils {
private static final Class[] STRING_CLASS = {String.class};
public static Object populate(Object source, Object destination) throws IllegalArgumentException {
return populate(source, destination, null);
}
public static Object populate(Object source, Object destination, Properties propertiesMapping)
throws IllegalArgumentException {
MandatoryArgumentChecker.check("source", source, "destination", destination);
Method[] sourceMethods = source.getClass().getMethods();
for (int i = 0; i < sourceMethods.length; i++) {
String getMethodName = sourceMethods[i].getName();
Class getMethodReturnType = sourceMethods[i].getReturnType();
if ((getMethodName.startsWith("get") && getMethodName.length() > 3 && !getMethodName.equals("getClass")) ||
(getMethodName.startsWith("is") && getMethodName.length() > 2 &&
(getMethodReturnType == Boolean.class || getMethodReturnType == Boolean.TYPE)) ||
(getMethodName.startsWith("has") && getMethodName.length() > 3 &&
(getMethodReturnType == Boolean.class || getMethodReturnType == Boolean.TYPE))) {
String destProperty = null;
if (getMethodName.startsWith("is")) {
destProperty = getMethodName.substring(2);
} else {
destProperty = getMethodName.substring(3);
}
if (propertiesMapping != null && propertiesMapping.getProperty(destProperty) != null) {
destProperty = propertiesMapping.getProperty(destProperty);
}
String setMethodName = "set" + destProperty;
try {
Object value = sourceMethods[i].invoke(source, null);
if (value != null) {
Object setValue = convertObject(value, destination, destProperty);
if (setValue != null) {
invokeMethod(destination, setMethodName, setValue);
}
}
} catch (Exception nsmex) {
Utils.logIgnoredException(nsmex);
}
}
}
try {
Method dataElementMethod = source.getClass().getMethod("dataElement", null);
Object dataElement = dataElementMethod.invoke(source, null);
if ("org.xins.client.DataElement".equals(dataElement.getClass().getName())) {
Method toXMLElementMethod = dataElement.getClass().getMethod("toXMLElement", null);
Element element = (Element) toXMLElementMethod.invoke(dataElement, null);
xmlToObject(element, destination);
} else if ("org.xins.common.xml.Element".equals(dataElement.getClass().getName())) {
Element element = (Element) dataElement;
xmlToObject(element, destination);
}
} catch (Exception e) {
}
return destination;
}
public static Object convert(Object origValue, Class destClass) {
if (origValue.getClass() == destClass) {
return origValue;
}
try {
if (EnumItem.class.isAssignableFrom(destClass)) {
String enumTypeClassName = destClass.getName().substring(0, destClass.getName().length() - 5);
Object enumType = Class.forName(enumTypeClassName).getDeclaredField("SINGLETON").get(null);
Method convertionMethod = enumType.getClass().getMethod("getItemByValue", STRING_CLASS);
Object[] convertParams = {origValue.toString()};
Object convertedObj = convertionMethod.invoke(null, convertParams);
return convertedObj;
} else if (destClass == String.class) {
return origValue.toString();
} else if (destClass == Boolean.class || destClass == Boolean.TYPE) {
if ("true".equals(origValue) || Boolean.TRUE.equals(origValue)) {
return Boolean.TRUE;
} else if ("false".equals(origValue) || Boolean.FALSE.equals(origValue)) {
return Boolean.FALSE;
}
} else if (origValue instanceof String && destClass == Date.Value.class) {
return Date.SINGLETON.fromString((String) origValue);
} else if (origValue instanceof String && destClass == Timestamp.Value.class) {
return Timestamp.SINGLETON.fromString((String) origValue);
} else if (origValue instanceof Collection && ItemList.class.isAssignableFrom(destClass)) {
ItemList destValue = (ItemList) destClass.newInstance();
destValue.add((Collection) origValue);
return destValue;
} else if (origValue instanceof ItemList && Collection.class.isAssignableFrom(destClass)) {
Class collectionClass = destClass;
if (destClass.isAssignableFrom(AbstractList.class) || destClass == List.class || destClass == Collection.class) {
collectionClass = ArrayList.class;
} else if (destClass.isAssignableFrom(AbstractSet.class) || destClass == Set.class) {
collectionClass = HashSet.class;
}
Collection destValue = (Collection) collectionClass.newInstance();
Collection values = ((ItemList) origValue).get();
destValue.addAll(values);
return destValue;
} else if ((origValue instanceof java.util.Date | origValue instanceof Calendar) &&
(destClass == Date.Value.class || destClass == Timestamp.Value.class)) {
Class[] idemClass = {origValue.getClass()};
Object[] valueArgs = {origValue};
Constructor dateConstructor = destClass.getConstructor(idemClass);
return dateConstructor.newInstance(valueArgs);
} else if (origValue instanceof Date.Value && destClass == java.util.Date.class) {
return ((Date.Value) origValue).toDate();
} else if (origValue instanceof Timestamp.Value && destClass == java.util.Date.class) {
return ((Timestamp.Value) origValue).toDate();
} else if (origValue instanceof String) {
Method convertionMethod = null;
if (destClass.isPrimitive()) {
if (destClass == Byte.TYPE) {
destClass = Byte.class;
} else if (destClass == Short.TYPE) {
destClass = Short.class;
} else if (destClass == Integer.TYPE) {
destClass = Integer.class;
} else if (destClass == Long.TYPE) {
destClass = Long.class;
} else if (destClass == Float.TYPE) {
destClass = Float.class;
} else if (destClass == Double.TYPE) {
destClass = Double.class;
}
}
try {
convertionMethod = destClass.getMethod("valueOf", STRING_CLASS);
} catch (NoSuchMethodException nsmex) {
}
if (convertionMethod == null) {
try {
convertionMethod = destClass.getMethod("fromStringForOptional", STRING_CLASS);
} catch (NoSuchMethodException nsmex) {
}
}
if (convertionMethod != null) {
String[] convertParams = {origValue.toString()};
Object convertedObj = convertionMethod.invoke(null, convertParams);
return convertedObj;
}
} else if (origValue instanceof Number && destClass.isPrimitive()) {
return origValue;
}
} catch (Exception ex) {
Log.log_1600(String.valueOf(origValue), origValue.getClass().getName(),
destClass.getName(), ex.getClass().getName(), ex.getMessage());
}
return null;
}
private static Object convertObject(Object origValue, Object destination, String property) throws Exception {
String setMethodName = "set" + TextUtils.firstCharUpper(property);
try {
Class[] idemClass = {origValue.getClass()};
destination.getClass().getMethod(setMethodName, idemClass);
return origValue;
} catch (NoSuchMethodException nsmex) {
}
Method[] destMethods = destination.getClass().getMethods();
for (int i = 0; i < destMethods.length; i++) {
if (destMethods[i].getName().equals(setMethodName)) {
Class destClass = destMethods[i].getParameterTypes()[0];
Object converted = convert(origValue, destClass);
if (converted != null) {
return converted;
}
}
}
return null;
}
public static Object xmlToObject(Element element, Object result,
Map elementMapping, Map attributeMapping) {
return xmlToObject(element, result, elementMapping, attributeMapping, true);
}
public static Object xmlToObject(Element element, Object result) {
return xmlToObject(element, result, null, null, true);
}
private static Object xmlToObject(Element element, Object result,
Map elementMapping, Map attributeMapping, boolean topLevel) {
if (element == null) {
return result;
}
String elementName = element.getTagName();
if (topLevel && elementName.equals("data")) {
for (Element nextChild : new ElementList(element)) {
xmlToObject(nextChild, result, elementMapping, attributeMapping, true);
}
} else {
try {
String hungarianName = TextUtils.firstCharUpper(elementName);
if (elementMapping != null && elementMapping.containsKey(elementName)) {
hungarianName = TextUtils.firstCharUpper((String) elementMapping.get(elementName));
}
Class[] argsClasses = {getElementClass(hungarianName, result)};
Method addMethod = result.getClass().getMethod("add" + hungarianName, argsClasses);
Object childElement = elementToObject(element, result, elementMapping, attributeMapping);
if (childElement != null) {
Object[] addArgs = { childElement };
addMethod.invoke(result, addArgs);
}
} catch (Exception ex) {
Utils.logIgnoredException(ex);
}
}
return result;
}
private static Class getElementClass(String hungarianName, Object result) throws ClassNotFoundException {
String elementClassName = result.getClass().getName();
if (elementClassName.indexOf("$") != -1) {
elementClassName = elementClassName.substring(0, elementClassName.indexOf("$"));
}
elementClassName += "$" + hungarianName;
Class elementClass = Class.forName(elementClassName);
return elementClass;
}
private static Object elementToObject(Element element, Object result, Map elementMapping, Map attributeMapping) {
String elementName = element.getTagName();
String hungarianName = TextUtils.firstCharUpper(elementName);
if (elementMapping != null && elementMapping.containsKey(elementName)) {
hungarianName = TextUtils.firstCharUpper((String) elementMapping.get(elementName));
}
Object newElement;
try {
newElement = getElementClass(hungarianName, result).newInstance();
} catch (Exception ex) {
Utils.logIgnoredException(ex);
return null;
}
NamedNodeMap attributes = element.getAttributes();
for (int i = 0; i < attributes.getLength(); i++) {
Attr attr = (Attr) attributes.item(i);
String name = attr.getName();
if (attributeMapping != null && attributeMapping.containsKey(name)) {
name = (String) attributeMapping.get(name);
}
String value = attr.getValue();
try {
Object setArg = convertObject(value, newElement, name);
invokeMethod(newElement, "set" + TextUtils.firstCharUpper(name), setArg);
} catch (Exception ex) {
Utils.logIgnoredException(ex);
}
}
String text = element.getTextContent();
if (text != null && text.trim().length() > 0) {
try {
Method pcdataMethod = newElement.getClass().getMethod("pcdata", STRING_CLASS);
Object[] pcdataArgs = { text };
pcdataMethod.invoke(newElement, pcdataArgs);
} catch (Exception ex) {
Utils.logIgnoredException(ex);
}
}
for (Element child : new ElementList(element)) {
xmlToObject(child, newElement, elementMapping, attributeMapping, false);
}
return newElement;
}
public static Map<String, Object> getParameters(Object source) throws IllegalArgumentException {
MandatoryArgumentChecker.check("source", source);
Map<String, Object> valuesMap = new LinkedHashMap<String, Object>();
Method[] sourceMethods = source.getClass().getMethods();
for (int i = 0; i < sourceMethods.length; i++) {
String getMethodName = sourceMethods[i].getName();
Class getMethodReturnType = sourceMethods[i].getReturnType();
if ((getMethodName.startsWith("get") && getMethodName.length() > 3 && !getMethodName.equals("getClass")) ||
(getMethodName.startsWith("is") && getMethodName.length() > 2 &&
(getMethodReturnType == Boolean.class || getMethodReturnType == Boolean.TYPE)) ||
(getMethodName.startsWith("has") && getMethodName.length() > 3 &&
(getMethodReturnType == Boolean.class || getMethodReturnType == Boolean.TYPE))) {
String propertyName = null;
if (getMethodName.startsWith("is")) {
propertyName = getMethodName.substring(2);
} else {
propertyName = getMethodName.substring(3);
}
propertyName = TextUtils.firstCharLower(propertyName);
try {
Object propertyValue = sourceMethods[i].invoke(source, null);
if (propertyValue != null) {
valuesMap.put(propertyName, propertyValue);
}
} catch (Exception ex) {
Utils.logIgnoredException(ex);
}
}
}
return valuesMap;
}
public static Map getParametersAsString(Object source) throws IllegalArgumentException {
Map<String, String> stringMap = new LinkedHashMap<String, String>();
Map<String, Object> originalMap = getParameters(source);
for (Map.Entry<String, Object> param : originalMap.entrySet()) {
String paramName = param.getKey();
Object paramValue = param.getValue();
String stringValue = String.valueOf(paramValue);
stringMap.put(paramName, stringValue);
}
return stringMap;
}
public static Map<String, Object> getParametersAsObject(Object source) throws IllegalArgumentException {
Map<String, Object> objectMap = new LinkedHashMap<String, Object>();
Map<String, Object> originalMap = getParameters(source);
for (Map.Entry<String, Object> param : originalMap.entrySet()) {
String paramName = param.getKey();
Object paramValue = param.getValue();
if (paramValue instanceof Date.Value) {
paramValue = ((Date.Value) paramValue).toDate();
} else if (paramValue instanceof Timestamp.Value) {
paramValue = ((Timestamp.Value) paramValue).toDate();
} else if (paramValue instanceof PropertyReader) {
paramValue = PropertyReaderConverter.toProperties((PropertyReader) paramValue);
} else if (paramValue instanceof ItemList) {
paramValue = ((ItemList) paramValue).get();
} else if (paramValue instanceof EnumItem) {
paramValue = ((EnumItem) paramValue).getValue();
} else if (paramValue instanceof TargetDescriptor) {
paramValue = ((TargetDescriptor) paramValue).getURL();
} else if (paramValue instanceof Descriptor) {
}
objectMap.put(paramName, paramValue);
}
return objectMap;
}
public static Object setParameters(Map properties, Object destination) throws IllegalArgumentException {
MandatoryArgumentChecker.check("properties", properties, "destination", destination);
Iterator itProperties = properties.entrySet().iterator();
while (itProperties.hasNext()) {
Map.Entry nextProp = (Map.Entry) itProperties.next();
try {
String propertyName = (String) nextProp.getKey();
Object propertyValue = nextProp.getValue();
String methodName = "set" + TextUtils.firstCharUpper(propertyName);
Object methodArg = convertObject(propertyValue, destination, propertyName);
invokeMethod(destination, methodName, methodArg);
} catch (Exception ex) {
Utils.logIgnoredException(ex);
}
}
return destination;
}
private static void invokeMethod(Object destination, String methodName, Object argument) throws Exception {
Class argumentClass = argument.getClass();
Class[] argsClasses = { argumentClass };
if (argument instanceof Boolean) {
try {
destination.getClass().getMethod(methodName, argsClasses);
} catch (NoSuchMethodException nsmex) {
argumentClass = Boolean.TYPE;
}
} else if (argument instanceof Number) {
try {
destination.getClass().getMethod(methodName, argsClasses);
} catch (NoSuchMethodException nsmex) {
argumentClass = (Class) argumentClass.getDeclaredField("TYPE").get(argument);
}
}
Class[] argsClasses2 = { argumentClass };
Object[] args = { argument };
Method setMethod = destination.getClass().getMethod(methodName, argsClasses2);
setMethod.invoke(destination, args);
}
}