[DEV] better introspection add node parsing, list mode and base for enums
This commit is contained in:
parent
7017468e46
commit
cd25863ed9
@ -68,23 +68,26 @@ public class Exml {
|
||||
Builder builder;
|
||||
try {
|
||||
builder = new BuilderIntrospection(classType, rootNodeName);
|
||||
final ParseXml parser = new ParseXml(builder);
|
||||
final ParsingProperty property = new ParsingProperty();
|
||||
property.setDisplayError(true);
|
||||
|
||||
final IntrospectionObject introspectionObject = (IntrospectionObject) parser.parse(data, property);
|
||||
final Object listRet = introspectionObject.getData();
|
||||
if (listRet != null && listRet instanceof List) {
|
||||
final List<T> rootList = (List<T>) listRet;
|
||||
final T[] strarr = (T[]) Array.newInstance(classType, 0);
|
||||
return rootList.toArray(strarr);
|
||||
}
|
||||
return null;
|
||||
} catch (final ExmlBuilderException ex) {
|
||||
throw ex;
|
||||
} catch (final Exception e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
final ParseXml parser = new ParseXml(builder);
|
||||
final ParsingProperty property = new ParsingProperty();
|
||||
property.setDisplayError(true);
|
||||
|
||||
final IntrospectionObject introspectionObject = (IntrospectionObject) parser.parse(data, property);
|
||||
final Object listRet = introspectionObject.getData();
|
||||
if (listRet != null && listRet instanceof List) {
|
||||
final List<T> rootList = (List<T>) listRet;
|
||||
final T[] strarr = (T[]) Array.newInstance(classType, 0);
|
||||
return rootList.toArray(strarr);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
private static String readFile(final Path path, final Charset encoding) throws IOException
|
||||
{
|
||||
@ -101,6 +104,16 @@ public class Exml {
|
||||
}
|
||||
return Exml.parse(content, classType, rootNodeName);
|
||||
}
|
||||
public static <T> T parseOne(final Path path, final Class<T> classType, final String rootNodeName) throws ExmlBuilderException, ExmlParserErrorMulti {
|
||||
T[] elements = Exml.parse(path, classType, rootNodeName);
|
||||
if (elements == null || elements.length == 0 ) {
|
||||
throw new ExmlBuilderException("Error in parsing the file, no node find ...");
|
||||
}
|
||||
if (elements.length > 1 ) {
|
||||
throw new ExmlBuilderException("Error in parsing the file, More than One node find ...");
|
||||
}
|
||||
return elements[0];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
|
@ -9,27 +9,21 @@ import java.lang.annotation.Target;
|
||||
* Marker annotation that can be used to define a group list of element:
|
||||
* {@code
|
||||
* <GROUP>
|
||||
* <ELEMENT ... > ... </ELEMENT>
|
||||
* <ELEMENT ... > ... </ELEMENT>
|
||||
* <ELEMENT ... > ... </ELEMENT>
|
||||
* <NAME> ... </NAME>
|
||||
* <NAME> ... </NAME>
|
||||
* <NAME> ... </NAME>
|
||||
* </GROUP>
|
||||
* }
|
||||
* @apiNote To change the group name @see XmlName
|
||||
*/
|
||||
@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER })
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@ExmlAnnotation
|
||||
public @interface XmlModel {
|
||||
public @interface XmlList {
|
||||
|
||||
/**
|
||||
* Group names node
|
||||
* @return The name of the group
|
||||
* @apiNote this is incompatible with XmlName
|
||||
* Element names node
|
||||
* @return The name of the elements
|
||||
*/
|
||||
String group();
|
||||
/**
|
||||
* Element names inside the group
|
||||
* @return The name of the element in the group
|
||||
* @apiNote this is incompatible with XmlName
|
||||
*/
|
||||
String element();
|
||||
String value();
|
||||
}
|
@ -17,7 +17,7 @@ public class BuilderIntrospection implements Builder {
|
||||
public BuilderIntrospection(final Class<?> classType, final String rootNodeName) throws Exception {
|
||||
this.rootNodeName = rootNodeName;
|
||||
this.rootClassType = classType;
|
||||
this.elements.put(classType, new IntrospectionData(classType));
|
||||
this.elements.put(classType, new IntrospectionData(classType, null));
|
||||
}
|
||||
|
||||
IntrospectionData findOrCreate(final Class<?> classType) throws Exception {
|
||||
@ -44,38 +44,42 @@ public class BuilderIntrospection implements Builder {
|
||||
public Object newElement(final Object parent, final String nodeName) throws ExmlBuilderException, Exception {
|
||||
Log.warning("new element on NodeName=" + nodeName);
|
||||
final IntrospectionObject introspectionObject = (IntrospectionObject) parent;
|
||||
if (introspectionObject.getDataInterface() == null) {
|
||||
final Object previousData = introspectionObject.getData();
|
||||
if ((previousData == null) || !(previousData instanceof List)) {
|
||||
// throw an error...
|
||||
return null;
|
||||
// special case of user request parsing of element with <XXX><value></value>...</XXX>
|
||||
if (nodeName.equals(introspectionObject.getListNameModel())) {
|
||||
IntrospectionData inferData = introspectionObject.getDataInterface();
|
||||
if (inferData.getClassType().isArray()) {
|
||||
inferData = findOrCreate(inferData.getClassType().getComponentType());
|
||||
} else if (List.class.isAssignableFrom(inferData.getClassType())) {
|
||||
inferData = findOrCreate(inferData.getSubClassType());
|
||||
}
|
||||
final List<Object> rootList = (List<Object>) previousData;
|
||||
// detect root node...
|
||||
// TODO Pb if the root name appeared multiple time in the XML !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ==> need a urgent correction
|
||||
return new IntrospectionObject(inferData);
|
||||
}
|
||||
|
||||
// TODO here try to remove this condition (see): YYYYYYYYYYYYYYYYYYYYYYYYYYYY
|
||||
if (introspectionObject.getDataInterface() == null) {
|
||||
if (nodeName.contentEquals(this.rootNodeName)) {
|
||||
Log.verbose("Create new class: " + this.rootClassType.getCanonicalName());
|
||||
final IntrospectionData inferData = findOrCreate(this.rootClassType);
|
||||
//final Object newElement = inferData.createObject();
|
||||
//rootList.add(newElement);
|
||||
return new IntrospectionObject(inferData);//, newElement);
|
||||
return new IntrospectionObject(inferData);
|
||||
}
|
||||
// need to add a throw on the node...
|
||||
return null; // ==> disable the parsing..
|
||||
return null; // ==> disable the parsing.. (node is not parsed...)
|
||||
}
|
||||
Class<?> typeClass = introspectionObject.getTypeOfSubNode(nodeName);
|
||||
String listTreeName = introspectionObject.getTreeNameOfSubNode(nodeName);
|
||||
if (typeClass != null) {
|
||||
// specific case for List ==> need to get the subType in introspection ...
|
||||
if (!List.class.isAssignableFrom(typeClass)) {
|
||||
Log.verbose("Create new class: '" + typeClass.getCanonicalName() + "' for node '" + nodeName + "'");
|
||||
final IntrospectionData inferData = findOrCreate(typeClass);
|
||||
// Create the data when object is ended created...
|
||||
return new IntrospectionObject(inferData);
|
||||
return new IntrospectionObject(inferData, listTreeName);
|
||||
}
|
||||
Class<?> subTypeClass = introspectionObject.getTypeOfSubNodeSubType(nodeName);
|
||||
Log.verbose("Create new 'SUB' class: '" + typeClass.getCanonicalName() + "' for node '" + nodeName + "'");
|
||||
final IntrospectionData inferData = findOrCreate(subTypeClass);
|
||||
// Create the data when object is ended created...
|
||||
return new IntrospectionObject(inferData);
|
||||
return new IntrospectionObject(inferData, listTreeName);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@ -93,6 +97,11 @@ public class BuilderIntrospection implements Builder {
|
||||
|
||||
@Override
|
||||
public Object newRoot() throws ExmlBuilderException {
|
||||
// TODO here try to set : YYYYYYYYYYYYYYYYYYYYYYYYYYYY
|
||||
/*
|
||||
final IntrospectionData inferData = findOrCreate(this.rootClassType);
|
||||
return new IntrospectionObject(inferData, rootNodeName);
|
||||
*/
|
||||
return new IntrospectionObject();
|
||||
}
|
||||
|
||||
@ -107,18 +116,18 @@ public class BuilderIntrospection implements Builder {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endElement(Object element) throws ExmlBuilderException {
|
||||
|
||||
public void endElement(final Object element) throws ExmlBuilderException {
|
||||
final IntrospectionObject introspectionObject = (IntrospectionObject) element;
|
||||
if (introspectionObject.getDataInterface() == null) {
|
||||
// property on nothing ???
|
||||
return;
|
||||
}
|
||||
introspectionObject.generateTheObject();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void newElementFinished(Object parent, String tmpname, Object element) {
|
||||
public void newElementFinished(final Object parent, final String tmpname, final Object element) {
|
||||
final IntrospectionObject introspectionElementObject = (IntrospectionObject) element;
|
||||
if (introspectionElementObject.getDataInterface() == null) {
|
||||
// property on nothing ???
|
||||
@ -126,7 +135,15 @@ public class BuilderIntrospection implements Builder {
|
||||
}
|
||||
final IntrospectionObject introspectionParentObject = (IntrospectionObject) parent;
|
||||
if (introspectionParentObject.getDataInterface() == null) {
|
||||
// property on nothing ???
|
||||
if (tmpname.equals(this.rootNodeName)) {
|
||||
// this is the root node ...
|
||||
Object tmpp = introspectionParentObject.getData();
|
||||
if( tmpp instanceof List) {
|
||||
@SuppressWarnings("unchecked")
|
||||
List<Object> elementsOut = (List<Object>)tmpp;
|
||||
elementsOut.add(introspectionElementObject.getData());
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
introspectionParentObject.addObject(tmpname, introspectionElementObject.getData());
|
||||
|
@ -6,9 +6,6 @@ import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.lang.reflect.TypeVariable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
@ -23,6 +20,7 @@ import org.atriasoft.exml.annotation.XmlCaseSensitive;
|
||||
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;
|
||||
@ -40,120 +38,148 @@ public class IntrospectionData {
|
||||
}
|
||||
private static final Map<Class<?>, Converter> VALUES_OF = new HashMap<>();
|
||||
static {
|
||||
VALUES_OF.put(byte.class, new Converter() {
|
||||
public Object valueOf(String value) {
|
||||
IntrospectionData.VALUES_OF.put(byte.class, new Converter() {
|
||||
@Override
|
||||
public Object valueOf(final String value) {
|
||||
return Byte.valueOf(value);
|
||||
}
|
||||
});
|
||||
VALUES_OF.put(Byte.class, new Converter() {
|
||||
public Object valueOf(String value) {
|
||||
IntrospectionData.VALUES_OF.put(Byte.class, new Converter() {
|
||||
@Override
|
||||
public Object valueOf(final String value) {
|
||||
return Byte.valueOf(value);
|
||||
}
|
||||
});
|
||||
VALUES_OF.put(int.class, new Converter() {
|
||||
public Object valueOf(String value) {
|
||||
IntrospectionData.VALUES_OF.put(int.class, new Converter() {
|
||||
@Override
|
||||
public Object valueOf(final String value) {
|
||||
return Integer.valueOf(value);
|
||||
}
|
||||
});
|
||||
VALUES_OF.put(Integer.class, new Converter() {
|
||||
public Object valueOf(String value) {
|
||||
IntrospectionData.VALUES_OF.put(Integer.class, new Converter() {
|
||||
@Override
|
||||
public Object valueOf(final String value) {
|
||||
return Integer.valueOf(value);
|
||||
}
|
||||
});
|
||||
VALUES_OF.put(long.class, new Converter() {
|
||||
public Object valueOf(String value) {
|
||||
IntrospectionData.VALUES_OF.put(long.class, new Converter() {
|
||||
@Override
|
||||
public Object valueOf(final String value) {
|
||||
return Long.valueOf(value);
|
||||
}
|
||||
});
|
||||
VALUES_OF.put(Long.class, new Converter() {
|
||||
public Object valueOf(String value) {
|
||||
IntrospectionData.VALUES_OF.put(Long.class, new Converter() {
|
||||
@Override
|
||||
public Object valueOf(final String value) {
|
||||
return Long.valueOf(value);
|
||||
}
|
||||
});
|
||||
VALUES_OF.put(short.class, new Converter() {
|
||||
public Object valueOf(String value) {
|
||||
IntrospectionData.VALUES_OF.put(short.class, new Converter() {
|
||||
@Override
|
||||
public Object valueOf(final String value) {
|
||||
return Short.valueOf(value);
|
||||
}
|
||||
});
|
||||
VALUES_OF.put(Short.class, new Converter() {
|
||||
public Object valueOf(String value) {
|
||||
IntrospectionData.VALUES_OF.put(Short.class, new Converter() {
|
||||
@Override
|
||||
public Object valueOf(final String value) {
|
||||
return Short.valueOf(value);
|
||||
}
|
||||
});
|
||||
VALUES_OF.put(boolean.class, new Converter() {
|
||||
public Object valueOf(String value) {
|
||||
IntrospectionData.VALUES_OF.put(boolean.class, new Converter() {
|
||||
@Override
|
||||
public Object valueOf(final String value) {
|
||||
return Boolean.valueOf(value);
|
||||
}
|
||||
});
|
||||
VALUES_OF.put(Boolean.class, new Converter() {
|
||||
public Object valueOf(String value) {
|
||||
IntrospectionData.VALUES_OF.put(Boolean.class, new Converter() {
|
||||
@Override
|
||||
public Object valueOf(final String value) {
|
||||
return Boolean.valueOf(value);
|
||||
}
|
||||
});
|
||||
VALUES_OF.put(byte[].class, new Converter() {
|
||||
public Object valueOf(String value) {
|
||||
IntrospectionData.VALUES_OF.put(byte[].class, new Converter() {
|
||||
@Override
|
||||
public Object valueOf(final String value) {
|
||||
return Tools.parseByteStringList(value);
|
||||
}
|
||||
});
|
||||
VALUES_OF.put(Byte[].class, new Converter() {
|
||||
public Object valueOf(String value) {
|
||||
IntrospectionData.VALUES_OF.put(Byte[].class, new Converter() {
|
||||
@Override
|
||||
public Object valueOf(final String value) {
|
||||
return Tools.parseByteClassStringList(value);
|
||||
}
|
||||
});
|
||||
VALUES_OF.put(short[].class, new Converter() {
|
||||
public Object valueOf(String value) {
|
||||
IntrospectionData.VALUES_OF.put(short[].class, new Converter() {
|
||||
@Override
|
||||
public Object valueOf(final String value) {
|
||||
return Tools.parseShortStringList(value);
|
||||
}
|
||||
});
|
||||
VALUES_OF.put(Short[].class, new Converter() {
|
||||
public Object valueOf(String value) {
|
||||
IntrospectionData.VALUES_OF.put(Short[].class, new Converter() {
|
||||
@Override
|
||||
public Object valueOf(final String value) {
|
||||
return Tools.parseShortClassStringList(value);
|
||||
}
|
||||
});
|
||||
VALUES_OF.put(int[].class, new Converter() {
|
||||
public Object valueOf(String value) {
|
||||
IntrospectionData.VALUES_OF.put(int[].class, new Converter() {
|
||||
@Override
|
||||
public Object valueOf(final String value) {
|
||||
return Tools.parseIntegerStringList(value);
|
||||
}
|
||||
});
|
||||
VALUES_OF.put(Integer[].class, new Converter() {
|
||||
public Object valueOf(String value) {
|
||||
IntrospectionData.VALUES_OF.put(Integer[].class, new Converter() {
|
||||
@Override
|
||||
public Object valueOf(final String value) {
|
||||
return Tools.parseIntegerClassStringList(value);
|
||||
}
|
||||
});
|
||||
VALUES_OF.put(long[].class, new Converter() {
|
||||
public Object valueOf(String value) {
|
||||
IntrospectionData.VALUES_OF.put(long[].class, new Converter() {
|
||||
@Override
|
||||
public Object valueOf(final String value) {
|
||||
return Tools.parseLongStringList(value);
|
||||
}
|
||||
});
|
||||
VALUES_OF.put(Long[].class, new Converter() {
|
||||
public Object valueOf(String value) {
|
||||
IntrospectionData.VALUES_OF.put(Long[].class, new Converter() {
|
||||
@Override
|
||||
public Object valueOf(final String value) {
|
||||
return Tools.parseLongClassStringList(value);
|
||||
}
|
||||
});
|
||||
VALUES_OF.put(boolean[].class, new Converter() {
|
||||
public Object valueOf(String value) {
|
||||
IntrospectionData.VALUES_OF.put(boolean[].class, new Converter() {
|
||||
@Override
|
||||
public Object valueOf(final String value) {
|
||||
return Tools.parseBooleanStringList(value);
|
||||
}
|
||||
});
|
||||
VALUES_OF.put(Boolean[].class, new Converter() {
|
||||
public Object valueOf(String value) {
|
||||
IntrospectionData.VALUES_OF.put(Boolean[].class, new Converter() {
|
||||
@Override
|
||||
public Object valueOf(final String value) {
|
||||
return Tools.parseBooleanClassStringList(value);
|
||||
}
|
||||
});
|
||||
VALUES_OF.put(String.class, new Converter() {
|
||||
public Object valueOf(String value) {
|
||||
IntrospectionData.VALUES_OF.put(String.class, new Converter() {
|
||||
@Override
|
||||
public Object valueOf(final String value) {
|
||||
return value;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
final Class<?> classType;
|
||||
final Class<?> subClassType;
|
||||
private final Class<?> classType;
|
||||
private final Class<?> subClassType; // TODO deprecated
|
||||
// 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> methods = new ArrayList<>();
|
||||
|
||||
private final List<IntrospectionProperty> properties = new ArrayList<>();
|
||||
|
||||
public Class<?> getClassType() {
|
||||
return this.classType;
|
||||
}
|
||||
public Class<?> getSubClassType() {
|
||||
return this.subClassType;
|
||||
}
|
||||
public IntrospectionData(final Class<?> classType) throws Exception {
|
||||
this(classType, null);
|
||||
}
|
||||
@ -176,9 +202,10 @@ public class IntrospectionData {
|
||||
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) {
|
||||
this.properties.add(new IntrospectionPropertyField(elem, names, caseSensitive, isOptionnal));
|
||||
this.properties.add(new IntrospectionPropertyField(elem, names, listName, caseSensitive, isOptionnal));
|
||||
}
|
||||
Log.verbose(" - " + elem.toGenericString());
|
||||
}
|
||||
@ -248,16 +275,25 @@ public class IntrospectionData {
|
||||
// void setXxx(XXX elem);
|
||||
// [bB]oolean isXxx();
|
||||
|
||||
final List<Method> methodsGet = methods.stream().filter(o -> o.getName().startsWith("get")).collect(Collectors.toList());
|
||||
final List<Method> methodsSet = methods.stream().filter(o -> o.getName().startsWith("set")).collect(Collectors.toList());
|
||||
final List<Method> methodsIs = methods.stream().filter(o -> o.getName().startsWith("is")).collect(Collectors.toList());
|
||||
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) {
|
||||
valueof = valueOfString.get(0);
|
||||
this.valueof = valueOfString.get(0);
|
||||
} else {
|
||||
// some specific model:
|
||||
|
||||
valueof = null;
|
||||
this.valueof = null;
|
||||
}
|
||||
// associate methods by pair.
|
||||
final List<OrderData> elements = new ArrayList<>();
|
||||
@ -350,18 +386,23 @@ public class IntrospectionData {
|
||||
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) };
|
||||
this.methods.add(new IntrospectionPropertyMethod(elem.setter, elem.getter, names, isCaseSensitive, isOptional));
|
||||
final String listNameSet = getListName(elem.setter, null);
|
||||
final String listNameGet = getListName(elem.getter, null);
|
||||
final String listName = listNameSet != null? listNameSet: listNameGet;
|
||||
this.methods.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;
|
||||
if (elem.setter != null) {
|
||||
Log.info(" setter: " + elem.setter.toGenericString());
|
||||
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");
|
||||
}
|
||||
@ -371,20 +412,22 @@ public class IntrospectionData {
|
||||
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) {
|
||||
this.methods.add(new IntrospectionPropertyMethod(elem.setter, elem.getter, names, isCaseSensitive, isOptionnal));
|
||||
this.methods.add(new IntrospectionPropertyMethod(elem.setter, elem.getter, names, listName, isCaseSensitive, isOptionnal));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Object createObject(Map<String, Object> properties, Map<String, List<Object>> nodes) throws ExmlBuilderException {
|
||||
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 coreect elements... ==> must be generated with a siblist of elements
|
||||
tmp = this.classType.getConstructor().newInstance();
|
||||
} catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException | SecurityException e) {
|
||||
// TODO Auto-generated catch block
|
||||
@ -400,6 +443,17 @@ public class IntrospectionData {
|
||||
return tmp;
|
||||
}
|
||||
|
||||
|
||||
protected List<String> getNodeAvaillable() {
|
||||
List<String> out = new ArrayList<>();
|
||||
for (final IntrospectionProperty prop : this.methods) {
|
||||
out.add(prop.getNames()[0]);
|
||||
}
|
||||
for (final IntrospectionProperty prop : this.properties) {
|
||||
out.add(prop.getNames()[0]);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
protected IntrospectionProperty findMethodDescription(final String propertyName) throws ExmlBuilderException {
|
||||
for (final IntrospectionProperty prop : this.methods) {
|
||||
if (prop.isCompatible(propertyName)) {
|
||||
@ -574,8 +628,37 @@ public class IntrospectionData {
|
||||
}
|
||||
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 hame 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 hame 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(Class<T> clazz, List<Object> data) {
|
||||
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++) {
|
||||
@ -585,7 +668,7 @@ public class IntrospectionData {
|
||||
//return data.stream().map(clazz::cast).toArray(new T[data.size()]);//java.lang.reflect.Array.newInstance((propMethode.getSubType(), tmpp.size()));
|
||||
}
|
||||
|
||||
private void setValue(Object data, String name, Object value) throws ExmlBuilderException {
|
||||
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 = findMethodDescription(name);
|
||||
@ -593,7 +676,7 @@ public class IntrospectionData {
|
||||
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 {
|
||||
} else if (value instanceof List){
|
||||
@SuppressWarnings("unchecked")
|
||||
List<Object> tmpp = (List<Object>)value;
|
||||
if (propMethode.getType().isArray()) {
|
||||
@ -617,25 +700,82 @@ public class IntrospectionData {
|
||||
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 {
|
||||
if (tmpp.size() == 1) {
|
||||
propMethode.setExistingValue(data, tmpp.get(0));
|
||||
} else {
|
||||
// impossible case ...
|
||||
}
|
||||
// impossible case ...
|
||||
}
|
||||
//Log.verbose(" ==> TODO....");
|
||||
} 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=" + propMethode.getType() + " sub-type=" + propMethode.getSubType() );
|
||||
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 {
|
||||
Log.verbose(" ==> TODO....");
|
||||
@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;
|
||||
}
|
||||
@ -680,9 +820,10 @@ public class IntrospectionData {
|
||||
Log.error(" ==> find '" + propField.getNames());
|
||||
return propMethode.getType();
|
||||
}
|
||||
throw new ExmlBuilderException("can not find the field '" + nodeName + "'");
|
||||
|
||||
throw new ExmlBuilderException("can not find the field '" + nodeName + "' availlable: " + getNodeAvaillable());
|
||||
}
|
||||
public Class<?> getTypeOfSubNodeList(Object data, String nodeName) throws ExmlBuilderException {
|
||||
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 = findMethodDescription(nodeName);
|
||||
@ -696,9 +837,26 @@ public class IntrospectionData {
|
||||
Log.error(" ==> find '" + propField.getNames());
|
||||
return propMethode.getSubType();
|
||||
}
|
||||
throw new ExmlBuilderException("can not find the field '" + nodeName + "' availlable: " + getNodeAvaillable());
|
||||
}
|
||||
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 = findMethodDescription(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 + "'");
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
@ -709,8 +867,8 @@ public class IntrospectionData {
|
||||
classTypeLocal = this.classType.getComponentType();
|
||||
} else if (List.class == this.classType || Collection.class.isAssignableFrom(this.classType)) {
|
||||
// a generic list ....
|
||||
if (subClassType != null) {
|
||||
classTypeLocal = subClassType;
|
||||
if (this.subClassType != null) {
|
||||
classTypeLocal = this.subClassType;
|
||||
}
|
||||
//Type[] tmpp = this.classType.getGenericInterfaces();
|
||||
//Class<?>[] tmpp = this.classType.getNestMembers();
|
||||
@ -732,23 +890,24 @@ public class IntrospectionData {
|
||||
Log.warning("======>>>>>>> subElement input type : " + classTypeLocal.getCanonicalName());
|
||||
|
||||
if (this.valueof == null) {
|
||||
Converter con = VALUES_OF.get(classTypeLocal);
|
||||
Converter con = IntrospectionData.VALUES_OF.get(classTypeLocal);
|
||||
if (con == null) {
|
||||
throw new ExmlBuilderException("function 'valueOf' for '" + classTypeLocal.getCanonicalName() + "' is not defined and not registered for specific type");
|
||||
} else {
|
||||
return con.valueOf(text);
|
||||
}
|
||||
return con.valueOf(text);
|
||||
}
|
||||
try {
|
||||
return this.valueof.invoke(null, text);
|
||||
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
|
||||
// TODO Auto-generated catch block
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
||||
public Object getValue(String propertyName, String propertyValue) throws ExmlBuilderException {
|
||||
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 = findMethodDescription(propertyName);
|
||||
|
@ -11,6 +11,7 @@ import org.atriasoft.exml.internal.Log;
|
||||
public class IntrospectionObject {
|
||||
private final IntrospectionData dataInterface;
|
||||
private Object data = null;
|
||||
private final String listNameModel;
|
||||
private final Map<String, Object> properties = new HashMap<>();
|
||||
private final Map<String, List<Object>> nodes = new HashMap<>();
|
||||
|
||||
@ -20,16 +21,21 @@ public class IntrospectionObject {
|
||||
public IntrospectionObject() {
|
||||
this.dataInterface = null;
|
||||
this.data = new ArrayList<>();
|
||||
this.listNameModel = null;
|
||||
}
|
||||
|
||||
public IntrospectionObject(final IntrospectionData dataInterface, final Object data) {
|
||||
public IntrospectionObject(final IntrospectionData dataInterface, final String listNameModel) {
|
||||
this.dataInterface = dataInterface;
|
||||
this.data = data;
|
||||
this.listNameModel = listNameModel;
|
||||
}
|
||||
|
||||
public IntrospectionObject(final IntrospectionData dataInterface) {
|
||||
this.dataInterface = dataInterface;
|
||||
this.data = null;
|
||||
this.listNameModel = null;
|
||||
}
|
||||
|
||||
public String getListNameModel() {
|
||||
return this.listNameModel;
|
||||
}
|
||||
|
||||
public Object getData() {
|
||||
@ -41,14 +47,12 @@ public class IntrospectionObject {
|
||||
}
|
||||
|
||||
public void setProperty(final String propertyName, final String propertyValue) throws Exception {
|
||||
this.dataInterface.setProperty(this.data, propertyName, propertyValue);
|
||||
// Old way ... this.dataInterface.setProperty(this.data, propertyName, propertyValue);
|
||||
Object value = this.dataInterface.getValue(propertyName, propertyValue);
|
||||
Object property = properties.get(propertyName);
|
||||
if (property == null) {
|
||||
properties.put(propertyName, value);
|
||||
} else {
|
||||
if (this.properties.containsKey(propertyName)) {
|
||||
throw new ExmlBuilderException("Property have multiple values ==> impossible case; A Node must contain only 1 attibutes");
|
||||
}
|
||||
this.properties.put(propertyName, value);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -59,9 +63,12 @@ public class IntrospectionObject {
|
||||
public Class<?> getTypeOfSubNode(final String nodeName) throws ExmlBuilderException {
|
||||
return this.dataInterface.getTypeOfSubNode(this.data, nodeName);
|
||||
}
|
||||
public Class<?> getTypeOfSubNodeSubType(String nodeName) throws ExmlBuilderException {
|
||||
public Class<?> getTypeOfSubNodeSubType(final String nodeName) throws ExmlBuilderException {
|
||||
return this.dataInterface.getTypeOfSubNodeList(this.data, nodeName);
|
||||
}
|
||||
public String getTreeNameOfSubNode(final String nodeName) throws ExmlBuilderException {
|
||||
return this.dataInterface.getTreeNameOfSubNode(this.data, nodeName);
|
||||
}
|
||||
|
||||
public void setText(final String text) throws ExmlBuilderException {
|
||||
if (this.data != null) {
|
||||
@ -70,26 +77,55 @@ public class IntrospectionObject {
|
||||
this.data = this.dataInterface.getValueFromText(text);
|
||||
}
|
||||
|
||||
public void addObject(String nodeName, Object value) {
|
||||
List<Object> node = nodes.get(nodeName);
|
||||
@SuppressWarnings("unchecked")
|
||||
public void addObject(final String nodeName, final Object value) {
|
||||
List<Object> node = this.nodes.get(nodeName);
|
||||
if (node == null) {
|
||||
node = new ArrayList<>();
|
||||
node.add(value);
|
||||
nodes.put(nodeName, node);
|
||||
if (value instanceof List) {
|
||||
node = (List<Object>) value;
|
||||
} else {
|
||||
node = new ArrayList<>();
|
||||
node.add(value);
|
||||
}
|
||||
this.nodes.put(nodeName, node);
|
||||
} else if (value instanceof List) {
|
||||
List<Object> nodeIn = (List<Object>) value;
|
||||
node.addAll(nodeIn);
|
||||
} else {
|
||||
node.add(value);
|
||||
}
|
||||
}
|
||||
|
||||
public void generateTheObject() throws ExmlBuilderException {
|
||||
if (data != null) {
|
||||
if (this.data != null) {
|
||||
// nothing to do ... ==> element already created
|
||||
return;
|
||||
}
|
||||
Log.info("Create the element for the Specific node ... type = " + dataInterface.classType.getCanonicalName());
|
||||
Log.info(" Properties : " + this.properties.keySet());
|
||||
Log.info(" Nodes : " + this.nodes.keySet());
|
||||
this.data = dataInterface.createObject(this.properties, this.nodes);
|
||||
if (this.listNameModel == null) {
|
||||
Log.info("Create the element for the Specific node ... type = " + this.dataInterface.getClassType().getCanonicalName());
|
||||
Log.info(" Properties : " + this.properties.keySet());
|
||||
Log.info(" Nodes : " + this.nodes.keySet());
|
||||
this.data = this.dataInterface.createObject(this.properties, this.nodes);
|
||||
} else {
|
||||
if (this.properties.size() != 0) {
|
||||
throw new ExmlBuilderException("SubNode in tree can not have propoerties !!!!");
|
||||
}
|
||||
if (this.nodes.size() == 0) {
|
||||
this.data = new ArrayList<Object>();
|
||||
return;
|
||||
}
|
||||
if (this.nodes.size() > 1) {
|
||||
throw new ExmlBuilderException("SubNode in tree can not have more than 1 subNodes !!!!");
|
||||
}
|
||||
// check name of node
|
||||
List<Object> values = this.nodes.get(this.listNameModel);
|
||||
if (values == null) {
|
||||
throw new ExmlBuilderException("SubNode in tree name is wrong !!!! must be '" + this.listNameModel + "'");
|
||||
}
|
||||
// create real object ...
|
||||
this.data = values;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -5,14 +5,22 @@ import org.atriasoft.exml.exception.ExmlBuilderException;
|
||||
public abstract class IntrospectionProperty {
|
||||
protected final Boolean caseSensitive;
|
||||
protected final Boolean isOptionnal;
|
||||
// name that can take the Node
|
||||
protected final String[] names;
|
||||
// if organized in sublist (!= null) then the subNode have this value
|
||||
protected final String listName;
|
||||
public String getListName() {
|
||||
return this.listName;
|
||||
}
|
||||
|
||||
protected final Class<?> type;
|
||||
protected final Class<?> subType;
|
||||
|
||||
public IntrospectionProperty(final Class<?>[] type, final String[] names, final Boolean caseSensitive, final Boolean isOptionnal) {
|
||||
public IntrospectionProperty(final Class<?>[] type, final String[] names, final String listName, final Boolean caseSensitive, final Boolean isOptionnal) {
|
||||
this.type = type[0];
|
||||
this.subType = type[1];
|
||||
this.names = names;
|
||||
this.listName = listName;
|
||||
this.caseSensitive = caseSensitive;
|
||||
this.isOptionnal = isOptionnal;
|
||||
}
|
||||
|
@ -1,13 +1,10 @@
|
||||
package org.atriasoft.exml.builder;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.List;
|
||||
|
||||
import org.atriasoft.exml.exception.ExmlBuilderException;
|
||||
import org.atriasoft.exml.internal.Log;
|
||||
import org.atriasoft.exml.parser.Tools;
|
||||
|
||||
public class IntrospectionPropertyField extends IntrospectionProperty {
|
||||
@ -32,8 +29,8 @@ public class IntrospectionPropertyField extends IntrospectionProperty {
|
||||
return new Class<?>[] {type, subType};
|
||||
}
|
||||
|
||||
public IntrospectionPropertyField(final Field fieldDescription, final String[] names, final Boolean caseSensitive, final Boolean isOptionnal) {
|
||||
super(getTypeField(fieldDescription), names, caseSensitive, isOptionnal);
|
||||
public IntrospectionPropertyField(final Field fieldDescription, final String[] names, final String listName, final Boolean caseSensitive, final Boolean isOptionnal) {
|
||||
super(IntrospectionPropertyField.getTypeField(fieldDescription), names, listName, caseSensitive, isOptionnal);
|
||||
this.fieldDescription = fieldDescription;
|
||||
}
|
||||
|
||||
@ -57,19 +54,19 @@ public class IntrospectionPropertyField extends IntrospectionProperty {
|
||||
public void setValue(final Object object, final String value) throws ExmlBuilderException {
|
||||
try {
|
||||
if (this.type == byte.class) {
|
||||
final byte data = Byte.valueOf(value);
|
||||
final byte data = Byte.parseByte(value);
|
||||
this.fieldDescription.setByte(object, data);
|
||||
} else if (this.type == short.class) {
|
||||
final short data = Short.valueOf(value);
|
||||
final short data = Short.parseShort(value);
|
||||
this.fieldDescription.setShort(object, data);
|
||||
} else if (this.type == int.class) {
|
||||
final int data = Integer.valueOf(value);
|
||||
final int data = Integer.parseInt(value);
|
||||
this.fieldDescription.setInt(object, data);
|
||||
} else if (this.type == long.class) {
|
||||
final long data = Long.valueOf(value);
|
||||
final long data = Long.parseLong(value);
|
||||
this.fieldDescription.setLong(object, data);
|
||||
} else if (this.type == boolean.class) {
|
||||
final boolean data = Boolean.valueOf(value);
|
||||
final boolean data = Boolean.parseBoolean(value);
|
||||
this.fieldDescription.setBoolean(object, data);
|
||||
} else if (this.type == String.class) {
|
||||
this.fieldDescription.set(object, value);
|
||||
@ -119,13 +116,15 @@ public class IntrospectionPropertyField extends IntrospectionProperty {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object createValue(String value) throws ExmlBuilderException {
|
||||
protected Object createValue(final String value) throws ExmlBuilderException {
|
||||
try {
|
||||
if (this.type == byte.class) {
|
||||
return Byte.valueOf(value);
|
||||
} else if (this.type == short.class) {
|
||||
}
|
||||
if (this.type == short.class) {
|
||||
return Short.valueOf(value);
|
||||
} else if (this.type == int.class) {
|
||||
}
|
||||
if (this.type == int.class) {
|
||||
return Integer.valueOf(value);
|
||||
} else if (this.type == long.class) {
|
||||
return Long.valueOf(value);
|
||||
@ -174,7 +173,7 @@ public class IntrospectionPropertyField extends IntrospectionProperty {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setExistingValue(Object object, Object value) throws ExmlBuilderException {
|
||||
public void setExistingValue(final Object object, final Object value) throws ExmlBuilderException {
|
||||
try {
|
||||
this.fieldDescription.set(object, value);
|
||||
} catch (IllegalArgumentException | IllegalAccessException e) {
|
||||
|
@ -4,7 +4,6 @@ import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.atriasoft.exml.exception.ExmlBuilderException;
|
||||
@ -21,21 +20,23 @@ public class IntrospectionPropertyMethod extends IntrospectionProperty {
|
||||
}
|
||||
if (getter != null) {
|
||||
type = getter.getReturnType();
|
||||
Type empppe = getter.getGenericReturnType();
|
||||
if (empppe instanceof ParameterizedType plopppppp) {
|
||||
Type[] realType = plopppppp.getActualTypeArguments();
|
||||
if (realType.length > 0) {
|
||||
subType = Class.forName(realType[0].getTypeName());
|
||||
if (Enum.class.isAssignableFrom(type)) {
|
||||
Log.verbose("Find an enum ...");
|
||||
} else {
|
||||
Type empppe = getter.getGenericReturnType();
|
||||
if (empppe instanceof ParameterizedType plopppppp) {
|
||||
Type[] realType = plopppppp.getActualTypeArguments();
|
||||
if (realType.length > 0) {
|
||||
subType = Class.forName(realType[0].getTypeName());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (setter != null) {
|
||||
if (type != null && setter.getParameters()[0].getType() != type) {
|
||||
throw new Exception("The type of the setter ands the type return by the getter are not the same ...");
|
||||
} else {
|
||||
type = setter.getParameters()[0].getType();
|
||||
}
|
||||
// specific for the list:
|
||||
type = setter.getParameters()[0].getType();
|
||||
if (List.class.isAssignableFrom(type)) {
|
||||
Class<?> internalModelClass = null;
|
||||
Type[] empppe = setter.getGenericParameterTypes();
|
||||
@ -61,8 +62,8 @@ public class IntrospectionPropertyMethod extends IntrospectionProperty {
|
||||
|
||||
protected Method getter;
|
||||
|
||||
public IntrospectionPropertyMethod(final Method setter, final Method getter, final String[] names, final Boolean isCaseSensitive, final Boolean isOptional) throws Exception {
|
||||
super(getTypefunction(setter, getter), names, isCaseSensitive, isOptional);
|
||||
public IntrospectionPropertyMethod(final Method setter, final Method getter, final String[] names, final String listName, final Boolean isCaseSensitive, final Boolean isOptional) throws Exception {
|
||||
super(IntrospectionPropertyMethod.getTypefunction(setter, getter), names, listName, isCaseSensitive, isOptional);
|
||||
this.setter = setter;
|
||||
this.getter = getter;
|
||||
}
|
||||
@ -93,19 +94,19 @@ public class IntrospectionPropertyMethod extends IntrospectionProperty {
|
||||
}
|
||||
try {
|
||||
if (this.type == byte.class) {
|
||||
final byte data = Byte.valueOf(value);
|
||||
final byte data = Byte.parseByte(value);
|
||||
this.setter.invoke(object, data);
|
||||
} else if (this.type == short.class) {
|
||||
final short data = Short.valueOf(value);
|
||||
final short data = Short.parseShort(value);
|
||||
this.setter.invoke(object, data);
|
||||
} else if (this.type == int.class) {
|
||||
final int data = Integer.valueOf(value);
|
||||
final int data = Integer.parseInt(value);
|
||||
this.setter.invoke(object, data);
|
||||
} else if (this.type == long.class) {
|
||||
final long data = Long.valueOf(value);
|
||||
final long data = Long.parseLong(value);
|
||||
this.setter.invoke(object, data);
|
||||
} else if (this.type == boolean.class) {
|
||||
final boolean data = Boolean.valueOf(value);
|
||||
final boolean data = Boolean.parseBoolean(value);
|
||||
this.setter.invoke(object, data);
|
||||
} else if (this.type == String.class) {
|
||||
this.setter.invoke(object, value);
|
||||
@ -159,19 +160,24 @@ public class IntrospectionPropertyMethod extends IntrospectionProperty {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object createValue(String value) throws ExmlBuilderException {
|
||||
protected Object createValue(final String value) throws ExmlBuilderException {
|
||||
try {
|
||||
if (this.type == byte.class) {
|
||||
return Byte.valueOf(value);
|
||||
} else if (this.type == short.class) {
|
||||
}
|
||||
if (this.type == short.class) {
|
||||
return Short.valueOf(value);
|
||||
} else if (this.type == int.class) {
|
||||
}
|
||||
if (this.type == int.class) {
|
||||
return Integer.valueOf(value);
|
||||
} else if (this.type == long.class) {
|
||||
}
|
||||
if (this.type == long.class) {
|
||||
return Long.valueOf(value);
|
||||
} else if (this.type == boolean.class) {
|
||||
}
|
||||
if (this.type == boolean.class) {
|
||||
return Boolean.valueOf(value);
|
||||
} else if (this.type == String.class) {
|
||||
}
|
||||
if (this.type == String.class) {
|
||||
return value;
|
||||
} else if (this.type == Byte.class) {
|
||||
return Byte.valueOf(value);
|
||||
@ -214,7 +220,7 @@ public class IntrospectionPropertyMethod extends IntrospectionProperty {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setExistingValue(Object object, Object value) throws ExmlBuilderException {
|
||||
public void setExistingValue(final Object object, final Object value) throws ExmlBuilderException {
|
||||
if (this.setter == null) {
|
||||
throw new ExmlBuilderException("no setter availlable");
|
||||
}
|
||||
|
@ -242,6 +242,8 @@ public class ParseXml {
|
||||
// TODO : Can have white spaces ....
|
||||
if (data.charAt(iii + 1) == '>') {
|
||||
pos.value = iii + 1;
|
||||
// end of parsing element in auto end close </>
|
||||
this.builder.endElement(parent);
|
||||
return true;
|
||||
}
|
||||
// error
|
||||
|
@ -6,7 +6,6 @@
|
||||
package test.atriasoft.exml;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.atriasoft.exml.Exml;
|
||||
import org.atriasoft.exml.exception.ExmlBuilderException;
|
||||
@ -16,10 +15,12 @@ import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import test.atriasoft.exml.introspection.ClassMethodEnum;
|
||||
import test.atriasoft.exml.introspection.ClassPublicMemberOnly;
|
||||
import test.atriasoft.exml.introspection.ClassPublicMethodOnly;
|
||||
import test.atriasoft.exml.introspection.ClassPublicMethodeNode;
|
||||
import test.atriasoft.exml.introspection.ClassPublicMethodeStructured;
|
||||
import test.atriasoft.exml.introspection.SimpleEnum;
|
||||
|
||||
public class ExmlTestIntrospection {
|
||||
@BeforeAll
|
||||
@ -329,11 +330,11 @@ public class ExmlTestIntrospection {
|
||||
+ " <value>2</value>\n"
|
||||
+ " </memberArrayByte>\n"
|
||||
+ " <memberListByte>\n"
|
||||
+ " <elem>12</elem>\n"
|
||||
+ " <elem>15</elem>\n"
|
||||
+ " <elem>123</elem>\n"
|
||||
+ " <elem>100</elem>\n"
|
||||
+ " <elem>2</elem>\n"
|
||||
+ " <elem>-12</elem>\n"
|
||||
+ " <elem>-15</elem>\n"
|
||||
+ " <elem>-123</elem>\n"
|
||||
+ " <elem>-100</elem>\n"
|
||||
+ " <elem>-2</elem>\n"
|
||||
+ " </memberListByte>\n"
|
||||
+ "</elem>\n";
|
||||
//@formatter:on
|
||||
@ -346,5 +347,27 @@ public class ExmlTestIntrospection {
|
||||
Assertions.assertEquals((byte) 15, elem.getMemberArrayByte()[1]);
|
||||
Assertions.assertEquals((byte) 123, elem.getMemberArrayByte()[2]);
|
||||
Assertions.assertEquals((byte) 100, elem.getMemberArrayByte()[3]);
|
||||
Assertions.assertEquals((byte) 2, elem.getMemberArrayByte()[4]);
|
||||
Assertions.assertEquals(5, elem.getMemberListByte().size());
|
||||
Assertions.assertEquals((byte) -12, elem.getMemberListByte().get(0));
|
||||
Assertions.assertEquals((byte) -15, elem.getMemberListByte().get(1));
|
||||
Assertions.assertEquals((byte) -123, elem.getMemberListByte().get(2));
|
||||
Assertions.assertEquals((byte) -100, elem.getMemberListByte().get(3));
|
||||
Assertions.assertEquals((byte) -2, elem.getMemberListByte().get(4));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test5() {
|
||||
//@formatter:off
|
||||
final String dataToParse = "<elem>\n"
|
||||
+ " <data>PLIF</data>\n"
|
||||
+ "</elem>\n";
|
||||
//@formatter:on
|
||||
final ClassMethodEnum[] root = Assertions.assertDoesNotThrow(() -> Exml.parse(dataToParse, ClassMethodEnum.class, "elem"));
|
||||
Assertions.assertEquals(1, root.length);
|
||||
|
||||
final ClassMethodEnum elem = root[0];
|
||||
Assertions.assertEquals(SimpleEnum.PLIF, elem.getData());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,14 @@
|
||||
package test.atriasoft.exml.introspection;
|
||||
|
||||
public class ClassMethodEnum {
|
||||
private SimpleEnum data;
|
||||
|
||||
public SimpleEnum getData() {
|
||||
return this.data;
|
||||
}
|
||||
|
||||
public void setData(final SimpleEnum data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
}
|
@ -1,7 +1,6 @@
|
||||
package test.atriasoft.exml.introspection;
|
||||
|
||||
import org.atriasoft.exml.annotation.XmlDefaultAttibute;
|
||||
import org.atriasoft.exml.annotation.XmlName;
|
||||
|
||||
@XmlDefaultAttibute
|
||||
public class ClassPublicMemberOnly {
|
||||
@ -17,7 +16,7 @@ public class ClassPublicMemberOnly {
|
||||
public Short[] memberArrayShortClass;
|
||||
public boolean memberBoolean;
|
||||
public Boolean memberBooleanClass;
|
||||
@XmlName(value = "jhkjhhkj")
|
||||
//this work !!! @XmlName(value = "jhkjhhkj")
|
||||
public byte memberByte;
|
||||
public Byte memberByteClass;
|
||||
public int memberInteger;
|
||||
|
@ -3,21 +3,22 @@ package test.atriasoft.exml.introspection;
|
||||
import java.util.List;
|
||||
|
||||
import org.atriasoft.exml.annotation.XmlDefaultManaged;
|
||||
import org.atriasoft.exml.annotation.XmlModel;
|
||||
import org.atriasoft.exml.annotation.XmlList;
|
||||
|
||||
@XmlDefaultManaged(value = false)
|
||||
public class ClassPublicMethodeStructured {
|
||||
@XmlModel(group="memberArrayByte", element="value")
|
||||
// note: when private the decorator must be set on getter or setter, liker this you can use the internal name you want...
|
||||
private byte[] memberArrayByte;
|
||||
@XmlModel(group="listByte", element="elem")
|
||||
private List<Byte> memberListByte;
|
||||
|
||||
@XmlList(value="value")
|
||||
public byte[] getMemberArrayByte() {
|
||||
return this.memberArrayByte;
|
||||
}
|
||||
public void setMemberArrayByte(final byte[] memberArrayByte) {
|
||||
this.memberArrayByte = memberArrayByte;
|
||||
}
|
||||
@XmlList(value="elem")
|
||||
public List<Byte> getMemberListByte() {
|
||||
return this.memberListByte;
|
||||
}
|
||||
|
@ -0,0 +1,7 @@
|
||||
package test.atriasoft.exml.introspection;
|
||||
|
||||
public enum SimpleEnum {
|
||||
PLIF,
|
||||
PLAF,
|
||||
PROUT;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user