From cd25863ed97216b783d87060b81db9c2fd2485a9 Mon Sep 17 00:00:00 2001 From: Edouard DUPIN Date: Tue, 29 Jun 2021 00:02:19 +0200 Subject: [PATCH] [DEV] better introspection add node parsing, list mode and base for enums --- src/org/atriasoft/exml/Exml.java | 37 ++- .../{XmlModel.java => XmlList.java} | 22 +- .../exml/builder/BuilderIntrospection.java | 55 ++-- .../exml/builder/IntrospectionData.java | 311 +++++++++++++----- .../exml/builder/IntrospectionObject.java | 74 +++-- .../exml/builder/IntrospectionProperty.java | 10 +- .../builder/IntrospectionPropertyField.java | 29 +- .../builder/IntrospectionPropertyMethod.java | 54 +-- src/org/atriasoft/exml/parser/ParseXml.java | 2 + .../atriasoft/exml/ExmlTestIntrospection.java | 35 +- .../exml/introspection/ClassMethodEnum.java | 14 + .../introspection/ClassPublicMemberOnly.java | 3 +- .../ClassPublicMethodeStructured.java | 9 +- .../exml/introspection/SimpleEnum.java | 7 + 14 files changed, 470 insertions(+), 192 deletions(-) rename src/org/atriasoft/exml/annotation/{XmlModel.java => XmlList.java} (52%) create mode 100644 test/src/test/atriasoft/exml/introspection/ClassMethodEnum.java create mode 100644 test/src/test/atriasoft/exml/introspection/SimpleEnum.java diff --git a/src/org/atriasoft/exml/Exml.java b/src/org/atriasoft/exml/Exml.java index 7d7186e..4e0bd8d 100644 --- a/src/org/atriasoft/exml/Exml.java +++ b/src/org/atriasoft/exml/Exml.java @@ -68,30 +68,33 @@ 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 rootList = (List) 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 rootList = (List) 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 { byte[] encoded = Files.readAllBytes(path); return new String(encoded, encoding); } - + public static T[] parse(final Path path, final Class classType, final String rootNodeName) throws ExmlBuilderException, ExmlParserErrorMulti { String content = null; try { @@ -101,6 +104,16 @@ public class Exml { } return Exml.parse(content, classType, rootNodeName); } + public static T parseOne(final Path path, final Class 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]; + } /** diff --git a/src/org/atriasoft/exml/annotation/XmlModel.java b/src/org/atriasoft/exml/annotation/XmlList.java similarity index 52% rename from src/org/atriasoft/exml/annotation/XmlModel.java rename to src/org/atriasoft/exml/annotation/XmlList.java index 3ab86f7..7cd186e 100644 --- a/src/org/atriasoft/exml/annotation/XmlModel.java +++ b/src/org/atriasoft/exml/annotation/XmlList.java @@ -9,27 +9,21 @@ import java.lang.annotation.Target; * Marker annotation that can be used to define a group list of element: * {@code * - * ... - * ... - * ... + * ... + * ... + * ... * * } + * @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(); } \ No newline at end of file diff --git a/src/org/atriasoft/exml/builder/BuilderIntrospection.java b/src/org/atriasoft/exml/builder/BuilderIntrospection.java index b9c4de9..db90b50 100644 --- a/src/org/atriasoft/exml/builder/BuilderIntrospection.java +++ b/src/org/atriasoft/exml/builder/BuilderIntrospection.java @@ -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 ... + 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 rootList = (List) 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 elementsOut = (List)tmpp; + elementsOut.add(introspectionElementObject.getData()); + } + } return; } introspectionParentObject.addObject(tmpname, introspectionElementObject.getData()); diff --git a/src/org/atriasoft/exml/builder/IntrospectionData.java b/src/org/atriasoft/exml/builder/IntrospectionData.java index 9ce8e70..bc50abd 100644 --- a/src/org/atriasoft/exml/builder/IntrospectionData.java +++ b/src/org/atriasoft/exml/builder/IntrospectionData.java @@ -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, 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 methods = new ArrayList<>(); private final List 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 methodsGet = methods.stream().filter(o -> o.getName().startsWith("get")).collect(Collectors.toList()); - final List methodsSet = methods.stream().filter(o -> o.getName().startsWith("set")).collect(Collectors.toList()); - final List methodsIs = methods.stream().filter(o -> o.getName().startsWith("is")).collect(Collectors.toList()); + List methodsGet; + List methodsSet; + List 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 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 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 properties, Map> nodes) throws ExmlBuilderException { + Object createObject(final Map properties, final Map> 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 getNodeAvaillable() { + List 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[] autoCast(Class clazz, List data) { + private T[] autoCast(final Class clazz, final List data) { T[] out = (T[]) java.lang.reflect.Array.newInstance(clazz, data.size());// T[data.size()]; for(int iii=0; iii 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 tmpp = (List)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 tmpp = (List)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,8 +837,25 @@ 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... @@ -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); diff --git a/src/org/atriasoft/exml/builder/IntrospectionObject.java b/src/org/atriasoft/exml/builder/IntrospectionObject.java index 6e9ee78..cf96732 100644 --- a/src/org/atriasoft/exml/builder/IntrospectionObject.java +++ b/src/org/atriasoft/exml/builder/IntrospectionObject.java @@ -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 properties = new HashMap<>(); private final Map> nodes = new HashMap<>(); @@ -20,18 +21,23 @@ 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() { return this.data; } @@ -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 node = nodes.get(nodeName); + @SuppressWarnings("unchecked") + public void addObject(final String nodeName, final Object value) { + List node = this.nodes.get(nodeName); if (node == null) { - node = new ArrayList<>(); - node.add(value); - nodes.put(nodeName, node); + if (value instanceof List) { + node = (List) value; + } else { + node = new ArrayList<>(); + node.add(value); + } + this.nodes.put(nodeName, node); + } else if (value instanceof List) { + List nodeIn = (List) 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(); + return; + } + if (this.nodes.size() > 1) { + throw new ExmlBuilderException("SubNode in tree can not have more than 1 subNodes !!!!"); + } + // check name of node + List 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; + } + } } diff --git a/src/org/atriasoft/exml/builder/IntrospectionProperty.java b/src/org/atriasoft/exml/builder/IntrospectionProperty.java index a8a4396..c0bce17 100644 --- a/src/org/atriasoft/exml/builder/IntrospectionProperty.java +++ b/src/org/atriasoft/exml/builder/IntrospectionProperty.java @@ -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; } diff --git a/src/org/atriasoft/exml/builder/IntrospectionPropertyField.java b/src/org/atriasoft/exml/builder/IntrospectionPropertyField.java index a4614bd..8f016d3 100644 --- a/src/org/atriasoft/exml/builder/IntrospectionPropertyField.java +++ b/src/org/atriasoft/exml/builder/IntrospectionPropertyField.java @@ -1,15 +1,12 @@ 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 { private final Field fieldDescription; @@ -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) { diff --git a/src/org/atriasoft/exml/builder/IntrospectionPropertyMethod.java b/src/org/atriasoft/exml/builder/IntrospectionPropertyMethod.java index 1ac442a..b8dbb75 100644 --- a/src/org/atriasoft/exml/builder/IntrospectionPropertyMethod.java +++ b/src/org/atriasoft/exml/builder/IntrospectionPropertyMethod.java @@ -4,13 +4,12 @@ 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; import org.atriasoft.exml.internal.Log; import org.atriasoft.exml.parser.Tools; - + public class IntrospectionPropertyMethod extends IntrospectionProperty { private static Class[] getTypefunction(final Method setter, final Method getter) throws Exception { Class type = null; @@ -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"); } diff --git a/src/org/atriasoft/exml/parser/ParseXml.java b/src/org/atriasoft/exml/parser/ParseXml.java index c700dc3..889a061 100644 --- a/src/org/atriasoft/exml/parser/ParseXml.java +++ b/src/org/atriasoft/exml/parser/ParseXml.java @@ -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 diff --git a/test/src/test/atriasoft/exml/ExmlTestIntrospection.java b/test/src/test/atriasoft/exml/ExmlTestIntrospection.java index b937b3a..45feccc 100644 --- a/test/src/test/atriasoft/exml/ExmlTestIntrospection.java +++ b/test/src/test/atriasoft/exml/ExmlTestIntrospection.java @@ -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 { + " 2\n" + " \n" + " \n" - + " 12\n" - + " 15\n" - + " 123\n" - + " 100\n" - + " 2\n" + + " -12\n" + + " -15\n" + + " -123\n" + + " -100\n" + + " -2\n" + " \n" + "\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 = "\n" + + " PLIF\n" + + "\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()); } } + diff --git a/test/src/test/atriasoft/exml/introspection/ClassMethodEnum.java b/test/src/test/atriasoft/exml/introspection/ClassMethodEnum.java new file mode 100644 index 0000000..bc2aa8b --- /dev/null +++ b/test/src/test/atriasoft/exml/introspection/ClassMethodEnum.java @@ -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; + } + +} diff --git a/test/src/test/atriasoft/exml/introspection/ClassPublicMemberOnly.java b/test/src/test/atriasoft/exml/introspection/ClassPublicMemberOnly.java index e338b9f..ac92924 100644 --- a/test/src/test/atriasoft/exml/introspection/ClassPublicMemberOnly.java +++ b/test/src/test/atriasoft/exml/introspection/ClassPublicMemberOnly.java @@ -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; diff --git a/test/src/test/atriasoft/exml/introspection/ClassPublicMethodeStructured.java b/test/src/test/atriasoft/exml/introspection/ClassPublicMethodeStructured.java index eb5d985..7ba5f64 100644 --- a/test/src/test/atriasoft/exml/introspection/ClassPublicMethodeStructured.java +++ b/test/src/test/atriasoft/exml/introspection/ClassPublicMethodeStructured.java @@ -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 memberListByte; - + + @XmlList(value="value") public byte[] getMemberArrayByte() { return this.memberArrayByte; } public void setMemberArrayByte(final byte[] memberArrayByte) { this.memberArrayByte = memberArrayByte; } + @XmlList(value="elem") public List getMemberListByte() { return this.memberListByte; } diff --git a/test/src/test/atriasoft/exml/introspection/SimpleEnum.java b/test/src/test/atriasoft/exml/introspection/SimpleEnum.java new file mode 100644 index 0000000..fab5025 --- /dev/null +++ b/test/src/test/atriasoft/exml/introspection/SimpleEnum.java @@ -0,0 +1,7 @@ +package test.atriasoft.exml.introspection; + +public enum SimpleEnum { + PLIF, + PLAF, + PROUT; +}