exml/src/org/atriasoft/exml/builder/IntrospectionModelComplex.java

880 lines
36 KiB
Java

package org.atriasoft.exml.builder;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.stream.Collectors;
import org.atriasoft.eStringSerialize.StringSerializer;
import org.atriasoft.etk.util.ArraysTools;
import org.atriasoft.exml.annotation.XmlAttribute;
import org.atriasoft.exml.annotation.XmlCaseSensitive;
import org.atriasoft.exml.annotation.XmlDefaultAttibute;
import org.atriasoft.exml.annotation.XmlDefaultCaseSensitive;
import org.atriasoft.exml.annotation.XmlDefaultManaged;
import org.atriasoft.exml.annotation.XmlDefaultOptional;
import org.atriasoft.exml.annotation.XmlList;
import org.atriasoft.exml.annotation.XmlManaged;
import org.atriasoft.exml.annotation.XmlName;
import org.atriasoft.exml.annotation.XmlOptional;
import org.atriasoft.exml.exception.ExmlBuilderException;
import org.atriasoft.exml.internal.Log;
import org.atriasoft.exml.parser.Tools;
public class IntrospectionModelComplex extends IntrospectionModel {
// TODO Optimize this with external object for basic types....
private final Method valueof; // used for the set Text if the object is an end point...
private final List<IntrospectionProperty> nodes = new ArrayList<>();
private final List<IntrospectionProperty> attributes = new ArrayList<>();
@Override
public List<IntrospectionProperty> getNodes() {
return this.nodes;
}
@Override
public List<IntrospectionProperty> getAttributes() {
return this.attributes;
}
public IntrospectionModelComplex(final Class<?> classType) throws ExmlBuilderException {
super(classType);
try {
final Boolean isDefaultAttribute = getIsDefaultAttribute(classType, IntrospectionModel.DEFAULT_ATTRIBUTE);
final Boolean isDefaultManaged = getIsDefaultManaged(classType, IntrospectionModel.DEFAULT_MANAGED);
final Boolean isDefaultOptional = getIsDefaultOptional(classType, IntrospectionModel.DEFAULT_OPTIONAL);
final Boolean isDefaultCaseSensitive = getIsDefaultCaseSensitive(classType, IntrospectionModel.DEFAULT_CASE_SENSITIVE);
Log.verbose("Introspect class: '" + classType.getCanonicalName() + "'");
final Constructor<?>[] constructors = this.classType.getConstructors();
Log.verbose(" Constructors: (" + constructors.length + ")");
for (final Constructor<?> elem : constructors) {
Log.verbose(" - " + elem.toGenericString());
}
final Field[] fields = this.classType.getFields();
Log.verbose(" Fields: (" + fields.length + ")");
for (final Field elem : fields) {
// we does not manage static field
if (Modifier.isStatic(elem.getModifiers())) {
continue;
}
// we does not manage private field
if (!Modifier.isPublic(elem.getModifiers())) {
continue;
}
final Boolean isAttribute = getIsAttribute(elem, isDefaultAttribute);
final Boolean isManaged = getIsManaged(elem, isDefaultManaged);
final Boolean isOptionnal = getIsOptional(elem, isDefaultOptional);
final String[] names = getNames(elem, Tools.decapitalizeFirst(elem.getName()));
final Boolean caseSensitive = getIsCaseSensitive(elem, isDefaultCaseSensitive);
final String listName = getListName(elem, null);
// TODO check if property does not already exist ...
if (isManaged) {
if (isAttribute) {
this.attributes.add(new IntrospectionPropertyField(elem, names, listName, caseSensitive, isOptionnal));
} else {
this.nodes.add(new IntrospectionPropertyField(elem, names, listName, caseSensitive, isOptionnal));
}
}
Log.verbose(" - " + elem.toGenericString());
}
final Method[] methodsTmp = this.classType.getMethods();
// filter getX setX isX
final List<Method> methods = List.of(methodsTmp).stream().filter(o -> {
if (o.getName().contentEquals("getClass")) {
return false;
}
// we does not manage private function
if (!Modifier.isPublic(o.getModifiers())) {
return false;
}
if (Modifier.isStatic(o.getModifiers())) {
if (o.getName().contentEquals("valueOf") && o.getParameterCount() == 1 && o.getParameters()[0].getType() == String.class) {
return true;
}
return false;
}
if (o.getName().startsWith("get")) {
if (o.getParameterCount() != 0 || o.getReturnType() == void.class || o.getReturnType() == Boolean.class || o.getReturnType() == boolean.class) {
return false;
}
// check name format
if (o.getName().length() == 3) {
return false;
}
if (o.getName().charAt(3) >= 'A' && o.getName().charAt(3) <= 'Z') {
return true;
}
return false;
}
if (o.getName().startsWith("set")) {
if (o.getReturnType() != void.class || o.getParameterCount() != 1) {
return false;
}
// check name format
if (o.getName().length() == 3) {
return false;
}
if (o.getName().charAt(3) >= 'A' && o.getName().charAt(3) <= 'Z') {
return true;
}
return false;
}
if (o.getName().startsWith("is")) {
if (!(o.getReturnType() == Boolean.class || o.getReturnType() == boolean.class) && o.getParameterCount() != 0) {
return false;
}
// check name format
if (o.getName().length() == 2) {
return false;
}
if (o.getName().charAt(2) >= 'A' && o.getName().charAt(2) <= 'Z') {
return true;
}
return false;
}
return false;
}).collect(Collectors.toList());
Log.verbose(" Methods: (" + methods.size() + ")");
for (final Method elem : methods) {
Log.verbose(" - " + elem.toGenericString());
}
// Separate the methods and filer as:
// XXX GetXxx(); & XXX != boolean
// void setXxx(XXX elem);
// [bB]oolean isXxx();
List<Method> methodsGet;
List<Method> methodsSet;
List<Method> methodsIs;
if (!Enum.class.isAssignableFrom(classType)) {
methodsGet = methods.stream().filter(o -> o.getName().startsWith("get")).collect(Collectors.toList());
methodsSet = methods.stream().filter(o -> o.getName().startsWith("set")).collect(Collectors.toList());
methodsIs = methods.stream().filter(o -> o.getName().startsWith("is")).collect(Collectors.toList());
} else {
methodsGet = new ArrayList<>();
methodsSet = new ArrayList<>();
methodsIs = new ArrayList<>();
}
final List<Method> valueOfString = methods.stream().filter(o -> o.getName().startsWith("valueOf")).collect(Collectors.toList());
if (valueOfString.size() == 1) {
this.valueof = valueOfString.get(0);
} else {
// some specific model:
this.valueof = null;
}
// associate methods by pair.
final List<OrderData> elements = new ArrayList<>();
for (final Method method : methodsGet) {
final String name = method.getName().substring(3);
final OrderData tmp = new OrderData(name);
tmp.getter = method;
elements.add(tmp);
}
for (final Method method : methodsIs) {
final String name = method.getName().substring(2);
for (final OrderData elem : elements) {
if (elem.name.contentEquals(name)) {
Log.error("Can not have a setXXX and isXXX with the same name ... " + method.getName());
throw new Exception("lmkjlkjlk");
}
}
final OrderData tmp = new OrderData(name);
tmp.getter = method;
elements.add(tmp);
}
for (final Method method : methodsSet) {
final String name = method.getName().substring(3);
OrderData tmp = null;
for (final OrderData elem : elements) {
if (elem.name.contentEquals(name)) {
tmp = elem;
break;
}
}
/*
Class<?> internalModelClass = null;
Class<?>[] tmppp = method.getParameterTypes();
if (tmppp.length > 0 && (List.class.isAssignableFrom(tmppp[0]))) {
Log.warning(" * " + method.getName());
Type[] empppe = method.getGenericParameterTypes();
if (empppe.length > 0) {
if (empppe[0] instanceof ParameterizedType plopppppp) {
Type[] realType = plopppppp.getActualTypeArguments();
if (realType.length > 0) {
Log.warning(" -->> " + realType[0]);
internalModelClass = Class.forName(realType[0].getTypeName());
}
}
}
for (int iii=0; iii<tmppp.length; iii++) {
Log.warning(" -- " + tmppp[iii].getCanonicalName());
}
}
*/
if (tmp == null) {
tmp = new OrderData(name);
tmp.setter = method;
elements.add(tmp);
} else {
tmp.setter = method;
}
}
// Add it in the engine
for (final OrderData elem : elements) {
Log.info("find methode : '" + elem.name + "' :");
if (elem.setter != null && elem.getter != null) {
Log.info(" setter: " + elem.setter.toGenericString());
Log.info(" getter: " + elem.getter.toGenericString());
final Boolean isAttributeSet = getIsAttribute(elem.setter, null);
final Boolean isAttributeGet = getIsAttribute(elem.getter, null);
if (isAttributeSet != null && isAttributeGet != null && isAttributeSet != isAttributeGet) {
throw new Exception("Can net set oposite information on getter and setter");
}
final Boolean isAttribute = isAttributeSet != null ? isAttributeSet : isAttributeGet != null ? isAttributeGet : isDefaultAttribute;
final Boolean isManagedSet = getIsManaged(elem.setter, null);
final Boolean isManagedGet = getIsManaged(elem.getter, null);
if (isManagedSet != null && isManagedGet != null && isManagedSet != isManagedGet) {
throw new Exception("Can net set oposite information on getter and setter");
}
final Boolean isManaged = isManagedSet != null ? isManagedSet : isManagedGet != null ? isManagedGet : isDefaultManaged;
final Boolean isOptionnalSet = getIsOptional(elem.setter, null);
final Boolean isOptionnalGet = getIsOptional(elem.getter, null);
if (isOptionnalSet != null && isOptionnalGet != null && isOptionnalSet != isOptionnalGet) {
throw new Exception("Can net set oposite information on getter and setter");
}
final Boolean isOptional = isOptionnalSet != null ? isOptionnalSet : isOptionnalGet != null ? isOptionnalGet : isDefaultOptional;
final Boolean caseSensitiveSet = getIsCaseSensitive(elem.setter, null);
final Boolean caseSensitiveGet = getIsCaseSensitive(elem.getter, null);
if (caseSensitiveSet != null && caseSensitiveGet != null && caseSensitiveSet != caseSensitiveGet) {
throw new Exception("Can net set oposite information on getter and setter");
}
final Boolean isCaseSensitive = caseSensitiveSet != null ? caseSensitiveSet : caseSensitiveGet != null ? caseSensitiveGet : isDefaultCaseSensitive;
final String[] namesSet = getNames(elem.setter, null);
final String[] namesGet = getNames(elem.getter, null);
if (namesSet != null && namesGet != null && namesSet.equals(namesGet)) {
throw new Exception("Can net set oposite information on getter and setter");
}
final String[] names = namesSet != null ? namesSet : namesGet != null ? namesGet : new String[] { Tools.decapitalizeFirst(elem.name) };
final String listNameSet = getListName(elem.setter, null);
final String listNameGet = getListName(elem.getter, null);
final String listName = listNameSet != null? listNameSet: listNameGet;
if (isAttribute) {
this.attributes.add(new IntrospectionPropertyMethod(elem.setter, elem.getter, names, listName, isCaseSensitive, isOptional));
} else {
this.nodes.add(new IntrospectionPropertyMethod(elem.setter, elem.getter, names, listName, isCaseSensitive, isOptional));
}
} else {
Boolean isManaged = null;
Boolean isOptionnal = null;
String[] names = null;
Boolean isCaseSensitive = null;
String listName = null;
Boolean isAttribute = isDefaultAttribute;
if (elem.setter != null) {
Log.info(" setter: " + elem.setter.toGenericString());
isAttribute = getIsAttribute(elem.setter, isDefaultAttribute);
isManaged = getIsManaged(elem.setter, isDefaultManaged);
isOptionnal = getIsOptional(elem.setter, isDefaultOptional);
names = getNames(elem.setter, Tools.decapitalizeFirst(elem.name));
isCaseSensitive = getIsCaseSensitive(elem.setter, isDefaultCaseSensitive);
listName= getListName(elem.setter, null);
} else {
Log.info(" setter: null");
}
if (elem.getter != null) {
Log.info(" getter: " + elem.getter.toGenericString());
isAttribute = getIsAttribute(elem.getter, isDefaultAttribute);
isManaged = getIsManaged(elem.getter, isDefaultManaged);
isOptionnal = getIsOptional(elem.getter, isDefaultOptional);
names = getNames(elem.getter, Tools.decapitalizeFirst(elem.name));
isCaseSensitive = getIsCaseSensitive(elem.getter, isDefaultCaseSensitive);
listName= getListName(elem.getter, null);
} else {
Log.info(" getter: null");
}
if (isManaged) {
if (isAttribute) {
this.attributes.add(new IntrospectionPropertyMethod(elem.setter, elem.getter, names, listName, isCaseSensitive, isOptionnal));
} else {
this.nodes.add(new IntrospectionPropertyMethod(elem.setter, elem.getter, names, listName, isCaseSensitive, isOptionnal));
}
}
}
}
} catch (Exception ex) {
ex.printStackTrace();
throw new ExmlBuilderException("Error in creating introspection data ... " + ex.getMessage());
}
}
@Override
Object createObject(final Map<String, Object> properties, final Map<String, List<Object>> nodes) throws ExmlBuilderException {
Object tmp;
try {
// pb here, can not create a primitive object with the correct elements... ==> must be generated with a siblist of elements
Constructor<?>[] constructors = this.classType.getConstructors();
Object tmp2 = null;
tmp = constructors[0].newInstance(tmp2);
} catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return null;
}
for (Entry<String, Object> elem : properties.entrySet()) {
setValue(tmp, elem.getKey(), elem.getValue());
}
for (Entry<String, List<Object>> elem : nodes.entrySet()) {
setValue(tmp, elem.getKey(), elem.getValue());
}
return tmp;
}
@Override
protected List<String> getNodeAvaillable() {
List<String> out = new ArrayList<>();
for (final IntrospectionProperty prop : this.nodes) {
out.add(prop.getNames()[0]);
}
// for (final IntrospectionProperty prop : this.attributes) {
// out.add(prop.getNames()[0]);
// }
return out;
}
protected IntrospectionProperty findNodeDescription(final String propertyName) throws ExmlBuilderException {
for (final IntrospectionProperty prop : this.nodes) {
if (prop.isCompatible(propertyName)) {
return prop;
}
}
return null;
}
protected IntrospectionProperty findPropertyDescription(final String propertyName) throws ExmlBuilderException {
for (final IntrospectionProperty prop : this.attributes) {
if (prop.isCompatible(propertyName)) {
return prop;
}
}
return null;
}
protected Boolean getIsCaseSensitive(final Field element, final Boolean defaultValue) throws ExmlBuilderException {
final Annotation[] annotation = element.getDeclaredAnnotationsByType(XmlCaseSensitive.class);
if (annotation.length == 0) {
return defaultValue;
}
if (annotation.length > 1) {
throw new ExmlBuilderException("Must not have more that ");
}
return ((XmlCaseSensitive) annotation[0]).value();
}
protected Boolean getIsCaseSensitive(final Method element, final Boolean defaultValue) throws ExmlBuilderException {
final Annotation[] annotation = element.getDeclaredAnnotationsByType(XmlCaseSensitive.class);
if (annotation.length == 0) {
return defaultValue;
}
if (annotation.length > 1) {
throw new ExmlBuilderException("Must not have more that ");
}
return ((XmlCaseSensitive) annotation[0]).value();
}
private Boolean getIsDefaultCaseSensitive(final Class<?> classType, final Boolean defaultValue) throws ExmlBuilderException {
final Annotation[] annotation = classType.getDeclaredAnnotationsByType(XmlDefaultCaseSensitive.class);
if (annotation.length == 0) {
return defaultValue;
}
if (annotation.length > 1) {
throw new ExmlBuilderException("Must not have more that ");
}
return ((XmlDefaultCaseSensitive) annotation[0]).value();
}
private Boolean getIsDefaultAttribute(final Class<?> classType, final Boolean defaultValue) throws ExmlBuilderException {
final Annotation[] annotation = classType.getDeclaredAnnotationsByType(XmlDefaultAttibute.class);
if (annotation.length == 0) {
return defaultValue;
}
if (annotation.length > 1) {
throw new ExmlBuilderException("Must not have more that ");
}
return ((XmlDefaultAttibute) annotation[0]).value();
}
private Boolean getIsDefaultManaged(final Class<?> classType, final Boolean defaultValue) throws ExmlBuilderException {
final Annotation[] annotation = classType.getDeclaredAnnotationsByType(XmlDefaultManaged.class);
if (annotation.length == 0) {
return defaultValue;
}
if (annotation.length > 1) {
throw new ExmlBuilderException("Must not have more that ");
}
return ((XmlDefaultManaged) annotation[0]).value();
}
private Boolean getIsDefaultOptional(final Class<?> classType, final Boolean defaultValue) throws ExmlBuilderException {
final Annotation[] annotation = classType.getDeclaredAnnotationsByType(XmlDefaultOptional.class);
if (annotation.length == 0) {
return defaultValue;
}
if (annotation.length > 1) {
throw new ExmlBuilderException("Must not have more that ");
}
return ((XmlDefaultOptional) annotation[0]).value();
}
protected Boolean getIsAttribute(final Field element, final Boolean parentValue) throws ExmlBuilderException {
final Annotation[] annotation = element.getDeclaredAnnotationsByType(XmlAttribute.class);
if (annotation.length == 0) {
return parentValue;
}
if (annotation.length > 1) {
throw new ExmlBuilderException("Must not have more that ");
}
return ((XmlAttribute) annotation[0]).value();
}
protected Boolean getIsAttribute(final Method element, final Boolean parentValue) throws ExmlBuilderException {
final Annotation[] annotation = element.getDeclaredAnnotationsByType(XmlAttribute.class);
if (annotation.length == 0) {
return parentValue;
}
if (annotation.length > 1) {
throw new ExmlBuilderException("Must not have more that ");
}
return ((XmlAttribute) annotation[0]).value();
}
protected Boolean getIsManaged(final Field element, final Boolean parentValue) throws ExmlBuilderException {
final Annotation[] annotation = element.getDeclaredAnnotationsByType(XmlManaged.class);
if (annotation.length == 0) {
return parentValue;
}
if (annotation.length > 1) {
throw new ExmlBuilderException("Must not have more that ");
}
return ((XmlManaged) annotation[0]).value();
}
protected Boolean getIsManaged(final Method element, final Boolean parentValue) throws ExmlBuilderException {
final Annotation[] annotation = element.getDeclaredAnnotationsByType(XmlManaged.class);
if (annotation.length == 0) {
return parentValue;
}
if (annotation.length > 1) {
throw new ExmlBuilderException("Must not have more that ");
}
return ((XmlManaged) annotation[0]).value();
}
protected Boolean getIsOptional(final Field element, final Boolean parentValue) throws Exception {
final Annotation[] annotation = element.getDeclaredAnnotationsByType(XmlOptional.class);
if (annotation.length == 0) {
return parentValue;
}
if (annotation.length > 1) {
throw new Exception("Must not have more that ");
}
return ((XmlOptional) annotation[0]).value();
}
protected Boolean getIsOptional(final Method element, final Boolean parentValue) throws Exception {
final Annotation[] annotation = element.getDeclaredAnnotationsByType(XmlOptional.class);
if (annotation.length == 0) {
return parentValue;
}
if (annotation.length > 1) {
throw new Exception("Must not have more that ");
}
return ((XmlOptional) annotation[0]).value();
}
protected String[] getNames(final Field element, final String defaultValue) throws Exception {
final Annotation[] annotation = element.getDeclaredAnnotationsByType(XmlName.class);
if (annotation.length == 0) {
if (defaultValue == null) {
return null;
}
return new String[] { defaultValue };
}
if (annotation.length > 1) {
throw new Exception("Must not have more that ");
}
final String[] tmp = ((XmlName) annotation[0]).value();
if (tmp == null) {
throw new Exception("Set null value in decorator @XmlName is not availlable on: " + element.toGenericString());
}
if (tmp.length == 0) {
throw new Exception("Set empty list value in decorator @XmlName is not availlable on: " + element.toGenericString());
}
for (final String elem : tmp) {
if (elem == null) {
throw new Exception("Set null String in list of value in decorator @XmlName is not availlable on: " + element.toGenericString());
}
if (elem.isEmpty()) {
throw new Exception("Set empty String in list of value in decorator @XmlName is not availlable on: " + element.toGenericString());
}
}
return tmp;
}
protected String[] getNames(final Method element, final String defaultValue) throws Exception {
final Annotation[] annotation = element.getDeclaredAnnotationsByType(XmlName.class);
if (annotation.length == 0) {
if (defaultValue == null) {
return null;
}
return new String[] { defaultValue };
}
if (annotation.length > 1) {
throw new Exception("Must not have more that ");
}
final String[] tmp = ((XmlName) annotation[0]).value();
if (tmp == null) {
throw new Exception("Set null value in decorator @XmlName is not availlable on: " + element.toGenericString());
}
if (tmp.length == 0) {
throw new Exception("Set empty list value in decorator @XmlName is not availlable on: " + element.toGenericString());
}
for (final String elem : tmp) {
if (elem == null) {
throw new Exception("Set null String in list of value in decorator @XmlName is not availlable on: " + element.toGenericString());
}
if (elem.isEmpty()) {
throw new Exception("Set empty String in list of value in decorator @XmlName is not availlable on: " + element.toGenericString());
}
}
return tmp;
}
protected String getListName(final Field element, final String defaultValue) throws Exception {
final Annotation[] annotation = element.getDeclaredAnnotationsByType(XmlList.class);
if (annotation.length == 0) {
return defaultValue;
}
if (annotation.length > 1) {
throw new Exception("Must not have more that ");
}
final String tmp = ((XmlList) annotation[0]).value();
if (tmp == null) {
throw new Exception("Set null value in decorator @XmlList is not availlable on: " + element.toGenericString());
}
return tmp;
}
protected String getListName(final Method element, final String defaultValue) throws Exception {
final Annotation[] annotation = element.getDeclaredAnnotationsByType(XmlList.class);
if (annotation.length == 0) {
return defaultValue;
}
if (annotation.length > 1) {
throw new Exception("Must not have more that ");
}
final String tmp = ((XmlList) annotation[0]).value();
if (tmp == null) {
throw new Exception("Set null value in decorator @XmlList is not availlable on: " + element.toGenericString());
}
return tmp;
}
@SuppressWarnings("unchecked")
private <T> T[] autoCast(final Class<T> clazz, final List<Object> data) {
T[] out = (T[]) java.lang.reflect.Array.newInstance(clazz, data.size());// T[data.size()];
for(int iii=0; iii<data.size(); iii++) {
out[iii] = (T) data.get(iii);
}
return out;
//return data.stream().map(clazz::cast).toArray(new T[data.size()]);//java.lang.reflect.Array.newInstance((propMethode.getSubType(), tmpp.size()));
}
private void setValue(final Object data, final String name, final Object value) throws ExmlBuilderException {
Log.error(" Set value ='" + name + "' propertyValue='" + value + "' " + value.getClass().getCanonicalName());
// by default use setter to set the property
final IntrospectionProperty propMethode = findNodeDescription(name);
if (propMethode != null && propMethode.canSetValue()) {
Log.verbose(" ==> find '" + Arrays.toString(propMethode.getNames()) + " type=" + propMethode.getType() + " sub-type=" + propMethode.getSubType() );
if (propMethode.getType().isAssignableFrom(value.getClass())) {
propMethode.setExistingValue(data, value);
} else if (value instanceof List){
@SuppressWarnings("unchecked")
List<Object> tmpp = (List<Object>)value;
if (propMethode.getType().isArray()) {
if (propMethode.getType().componentType() == byte.class) {
byte[] datas = ArraysTools.listByteToPrimitive(tmpp);
propMethode.setExistingValue(data, datas);
} else if (propMethode.getType().componentType() == short.class) {
short[] datas = ArraysTools.listShortToPrimitive(tmpp);
propMethode.setExistingValue(data, datas);
} else if (propMethode.getType().componentType() == int.class) {
int[] datas = ArraysTools.listIntegerToPrimitive(tmpp);
propMethode.setExistingValue(data, datas);
} else if (propMethode.getType().componentType() == long.class) {
long[] datas = ArraysTools.listLongToPrimitive(tmpp);
propMethode.setExistingValue(data, datas);
} else if (propMethode.getType().componentType() == boolean.class) {
boolean[] datas = ArraysTools.listBooleanToPrimitive(tmpp);
propMethode.setExistingValue(data, datas);
} else {
Log.verbose(" datas type: " + autoCast(propMethode.getType().componentType(), tmpp).getClass().getCanonicalName());
Log.verbose(" methode type: " + propMethode.getType().getCanonicalName());
propMethode.setExistingValue(data, autoCast(propMethode.getType().componentType(), tmpp));
}
} else if (tmpp.size() == 1) {
propMethode.setExistingValue(data, tmpp.get(0));
} else {
// impossible case ...
}
} else if (propMethode.getType() == byte.class) {
byte dataPrimitive = (Byte)value;
propMethode.setExistingValue(data, dataPrimitive);
} else if (propMethode.getType() == short.class) {
short dataPrimitive = (Short)value;
propMethode.setExistingValue(data, dataPrimitive);
} else if (propMethode.getType() == int.class) {
int dataPrimitive = (Integer)value;
propMethode.setExistingValue(data, dataPrimitive);
} else if (propMethode.getType() == long.class) {
long dataPrimitive = (Long)value;
propMethode.setExistingValue(data, dataPrimitive);
} else if (propMethode.getType() == boolean.class) {
boolean dataPrimitive = (Boolean)value;
propMethode.setExistingValue(data, dataPrimitive);
} else {
}
return;
}
// try with direct field
final IntrospectionProperty propField = findPropertyDescription(name);
if (propField != null && propField.canSetValue()) {
Log.verbose(" ==> find '" + Arrays.toString(propField.getNames()) + " type=" + propField.getType() + " sub-type=" + propField.getSubType() );
if (propField.getType().isAssignableFrom(value.getClass())) {
propField.setExistingValue(data, value);
// Some specific case for primitives values
} else if (propField.getType() == byte.class) {
byte dataPrimitive = (Byte)value;
propField.setExistingValue(data, dataPrimitive);
} else if (propField.getType() == short.class) {
short dataPrimitive = (Short)value;
propField.setExistingValue(data, dataPrimitive);
} else if (propField.getType() == int.class) {
int dataPrimitive = (Integer)value;
propField.setExistingValue(data, dataPrimitive);
} else if (propField.getType() == long.class) {
long dataPrimitive = (Long)value;
propField.setExistingValue(data, dataPrimitive);
} else if (propField.getType() == boolean.class) {
boolean dataPrimitive = (Boolean)value;
propField.setExistingValue(data, dataPrimitive);
} else {
@SuppressWarnings("unchecked")
List<Object> tmpp = (List<Object>)value;
if (propField.getType().isArray()) {
if (propField.getType().componentType() == byte.class) {
byte[] datas = ArraysTools.listByteToPrimitive(tmpp);
propField.setExistingValue(data, datas);
} else if (propField.getType().componentType() == short.class) {
short[] datas = ArraysTools.listShortToPrimitive(tmpp);
propField.setExistingValue(data, datas);
} else if (propField.getType().componentType() == int.class) {
int[] datas = ArraysTools.listIntegerToPrimitive(tmpp);
propField.setExistingValue(data, datas);
} else if (propField.getType().componentType() == long.class) {
long[] datas = ArraysTools.listLongToPrimitive(tmpp);
propField.setExistingValue(data, datas);
} else if (propField.getType().componentType() == boolean.class) {
boolean[] datas = ArraysTools.listBooleanToPrimitive(tmpp);
propField.setExistingValue(data, datas);
} else {
Log.verbose(" datas type: " + autoCast(propMethode.getType().componentType(), tmpp).getClass().getCanonicalName());
Log.verbose(" methode type: " + propMethode.getType().getCanonicalName());
propField.setExistingValue(data, autoCast(propMethode.getType().componentType(), tmpp));
}
} else if (tmpp.size() == 1) {
propField.setExistingValue(data, tmpp.get(0));
} else {
// impossible case ...
}
}
return;
}
throw new ExmlBuilderException("can not find the field '" + name + "'");
}
/**
* Detect a subNode, and ask the type of the node at the parent Class
* @param nodeName Name of the node
* @return Class of the node to create
*/
@Override
public Class<?> getTypeOfSubNode(final Object data, final String nodeName) throws ExmlBuilderException {
Log.error(" nodeType='" + nodeName + "'");
// by default use setter to set the property
final IntrospectionProperty propMethode = findNodeDescription(nodeName);
if (propMethode != null && propMethode.canSetValue()) {
Log.error(" ==> find '" + propMethode.getNames());
return propMethode.getType();
}
// try with direct field
final IntrospectionProperty propField = findPropertyDescription(nodeName);
if (propField != null && propField.canSetValue()) {
Log.error(" ==> find '" + propField.getNames());
return propMethode.getType();
}
throw new ExmlBuilderException("can not find the field '" + nodeName + "' availlable: " + getNodeAvaillable());
}
@Override
public Class<?> getTypeOfSubNodeList(final Object data, final String nodeName) throws ExmlBuilderException {
Log.error(" nodeType='" + nodeName + "'");
// by default use setter to set the property
final IntrospectionProperty propMethode = findNodeDescription(nodeName);
if (propMethode != null && propMethode.canSetValue()) {
Log.error(" ==> find '" + propMethode.getNames());
return propMethode.getSubType();
}
// try with direct field
final IntrospectionProperty propField = findPropertyDescription(nodeName);
if (propField != null && propField.canSetValue()) {
Log.error(" ==> find '" + propField.getNames());
return propMethode.getSubType();
}
throw new ExmlBuilderException("can not find the field '" + nodeName + "' availlable: " + getNodeAvaillable());
}
@Override
public String getTreeNameOfSubNode(final Object data, final String nodeName) throws ExmlBuilderException {
Log.error(" nodeType='" + nodeName + "'");
// by default use setter to set the property
final IntrospectionProperty propMethode = findNodeDescription(nodeName);
if (propMethode != null && propMethode.canSetValue()) {
Log.error(" ==> find '" + propMethode.getNames());
return propMethode.getListName();
}
// try with direct field
final IntrospectionProperty propField = findPropertyDescription(nodeName);
if (propField != null && propField.canSetValue()) {
Log.error(" ==> find '" + propField.getNames());
return propMethode.getListName();
}
throw new ExmlBuilderException("can not find the field '" + nodeName + "'");
}
@Override
public Object getValueFromText(final String text) throws ExmlBuilderException {
// Note if the type is an Array<>() or a List<>() ==> we parse element by element ... then we need to keep the undertype...
Class<?> classTypeLocal = this.classType;
Log.warning("======>>>>>>> Get input type : " + this.classType.getCanonicalName());
//Log.warning("======>>>>>>> Get input component type : " + this.classType.getComponentType().getCanonicalName());
if (this.classType.isArray()){
// generic array ...
classTypeLocal = this.classType.getComponentType();
} else if (List.class == this.classType || Collection.class.isAssignableFrom(this.classType)) {
// a generic list ....
/*if (this.subClassType != null) {
classTypeLocal = this.subClassType;
}*/
//Type[] tmpp = this.classType.getGenericInterfaces();
//Class<?>[] tmpp = this.classType.getNestMembers();
//Class<?>[] tmpp = this.classType.getClasses();
//Class<?>[] tmpp = this.classType.getDeclaredClasses();
//Class<?>[] tmpp = this.classType.getInterfaces();
//Class<?> tmpp = this.classType.getDeclaringClass();
//TypeVariable<?>[] tmpp = this.classType.getTypeParameters();
/*
Class<?> persistentClass =((ParameterizedType)classType.getGenericSuperclass()).getActualTypeArguments()[0];
*/
//Type tmpp = classType.getGenericSuperclass();
// Class<?> tmpp = classType.getInterfaces();
// Log.warning("======>>>>>>> Find List '" + tmpp + "'");
// for (int iii = 0; iii < tmpp.length; iii++) {
// Log.warning(" - " + tmpp[iii]);
// }
}
Log.warning("======>>>>>>> subElement input type : " + classTypeLocal.getCanonicalName());
if (this.valueof == null) {
if (StringSerializer.contains(classTypeLocal)) {
throw new ExmlBuilderException("function 'valueOf' for '" + classTypeLocal.getCanonicalName() + "' is not defined and not registered for specific type");
}
return StringSerializer.valueOf(classTypeLocal, text);
}
try {
return this.valueof.invoke(null, text);
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
if (Enum.class.isAssignableFrom(this.classType)) {
throw new ExmlBuilderException("Error in call 'valueOf(String ...)' for enum '" + classTypeLocal.getCanonicalName() + "' ==> '" + text + "' ... availlable list: " + Arrays.asList(this.classType.getEnumConstants()));
}
e.printStackTrace();
throw new ExmlBuilderException("Error in call 'valueOf(String ...)' for '" + classTypeLocal.getCanonicalName() + "' " + e.getMessage());
}
}
@Override
public Object getValue(final String propertyName, final String propertyValue) throws ExmlBuilderException {
Log.error(" propertyName='" + propertyName + "' propertyValue='" + propertyValue + "' ");
// by default use setter to set the property
final IntrospectionProperty propMethode = findNodeDescription(propertyName);
if (propMethode != null && propMethode.canSetValue()) {
Log.verbose(" ==> find '" + propMethode.getNames());
return propMethode.createValue(propertyValue);
}
// try with direct field
final IntrospectionProperty propField = findPropertyDescription(propertyName);
if (propField != null && propField.canSetValue()) {
Log.verbose(" ==> find '" + propField.getNames());
return propField.createValue(propertyValue);
}
throw new ExmlBuilderException("can not find the field '" + propertyName + "'");
}
@Override
public boolean isEndPoint() {
return false;
}
@Override
public String toString(final Object data) {
return null;
}
@Override
public String[] toStringList(final Object data) {
// TODO Auto-generated method stub
return null;
}
}
class OrderData {
public Method getter = null;
public final String name;
public Method setter = null;
public OrderData(final String name) {
this.name = name;
}
}