From 956f78642b3867033e8d3d4c71a7128f227e7fa0 Mon Sep 17 00:00:00 2001 From: Edouard DUPIN Date: Fri, 2 Jul 2021 23:41:02 +0200 Subject: [PATCH] [DEV] continue integration --- src/module-info.java | 1 + .../atriasoft/eStringSerialize/Converter.java | 22 + .../eStringSerialize/StringSerializer.java | 475 ++++++++++++++++++ src/org/atriasoft/exml/Exml.java | 13 +- .../exml/builder/BuilderIntrospection.java | 26 +- .../exml/builder/IntrospectionModel.java | 68 +++ .../builder/IntrospectionModelBaseType.java | 50 ++ ...ta.java => IntrospectionModelComplex.java} | 221 ++------ .../builder/IntrospectionModelFactory.java | 17 + .../exml/builder/IntrospectionObject.java | 8 +- .../exml/builder/IntrospectionProperty.java | 97 ++-- .../builder/IntrospectionPropertyField.java | 128 ----- .../builder/IntrospectionPropertyMethod.java | 135 +---- .../generator/GeneratorIntrospection.java | 105 ++-- src/org/atriasoft/exml/parser/Tools.java | 23 +- .../exml/serializer/SerializerXml.java | 10 +- .../exml/ExmlTestIntrospectionBoolean.java | 211 ++++++++ .../ExmlTestIntrospectionBooleanNative.java | 49 ++ .../exml/ExmlTestIntrospectionGenerate.java | 1 + 19 files changed, 1094 insertions(+), 566 deletions(-) create mode 100644 src/org/atriasoft/eStringSerialize/Converter.java create mode 100644 src/org/atriasoft/eStringSerialize/StringSerializer.java create mode 100644 src/org/atriasoft/exml/builder/IntrospectionModel.java create mode 100644 src/org/atriasoft/exml/builder/IntrospectionModelBaseType.java rename src/org/atriasoft/exml/builder/{IntrospectionData.java => IntrospectionModelComplex.java} (84%) create mode 100644 src/org/atriasoft/exml/builder/IntrospectionModelFactory.java create mode 100644 test/src/test/atriasoft/exml/ExmlTestIntrospectionBoolean.java create mode 100644 test/src/test/atriasoft/exml/ExmlTestIntrospectionBooleanNative.java diff --git a/src/module-info.java b/src/module-info.java index ada1f63..dad64d6 100644 --- a/src/module-info.java +++ b/src/module-info.java @@ -5,6 +5,7 @@ */ open module org.atriasoft.exml { + exports org.atriasoft.eStringSerialize; exports org.atriasoft.exml; exports org.atriasoft.exml.model; exports org.atriasoft.exml.exception; diff --git a/src/org/atriasoft/eStringSerialize/Converter.java b/src/org/atriasoft/eStringSerialize/Converter.java new file mode 100644 index 0000000..b2aad44 --- /dev/null +++ b/src/org/atriasoft/eStringSerialize/Converter.java @@ -0,0 +1,22 @@ +package org.atriasoft.eStringSerialize; + +public interface Converter { + /** + * Un-serialize a String in a specified Object + * @param value String to parse + * @return Data generated or Null + */ + Object valueOf(final String value); + /** + * Serialize in a string the require data + * @param data Object to serialize + * @return The new data... + */ + String toString(final Object data); + /** + * Serialize in a string the require data + * @param data Object to serialize + * @return The new data... + */ + String[] toStringList(final Object data); +} \ No newline at end of file diff --git a/src/org/atriasoft/eStringSerialize/StringSerializer.java b/src/org/atriasoft/eStringSerialize/StringSerializer.java new file mode 100644 index 0000000..d68b242 --- /dev/null +++ b/src/org/atriasoft/eStringSerialize/StringSerializer.java @@ -0,0 +1,475 @@ +package org.atriasoft.eStringSerialize; + +import java.util.HashMap; +import java.util.Map; + +import org.atriasoft.exml.parser.Tools; + +public class StringSerializer { + private static final Map, Converter> VALUES_OF = new HashMap<>(); + static { + StringSerializer.VALUES_OF.put(byte.class, new Converter() { + @Override + public Object valueOf(final String value) { + return Byte.valueOf(value); + } + + @Override + public String toString(final Object data) { + return Byte.toString((Byte)data); + } + + @Override + public String[] toStringList(final Object data) { + return new String[] { toString(data) }; + } + }); + StringSerializer.VALUES_OF.put(Byte.class, new Converter() { + @Override + public Object valueOf(final String value) { + return Byte.valueOf(value); + } + + @Override + public String toString(final Object data) { + return Byte.toString((Byte)data); + } + + @Override + public String[] toStringList(final Object data) { + return new String[] { toString(data) }; + } + }); + StringSerializer.VALUES_OF.put(int.class, new Converter() { + @Override + public Object valueOf(final String value) { + return Integer.valueOf(value); + } + + @Override + public String toString(final Object data) { + return Integer.toString((Integer)data); + } + + @Override + public String[] toStringList(final Object data) { + return new String[] { toString(data) }; + } + }); + StringSerializer.VALUES_OF.put(Integer.class, new Converter() { + @Override + public Object valueOf(final String value) { + return Integer.valueOf(value); + } + + @Override + public String toString(final Object data) { + return Integer.toString((Integer)data); + } + + @Override + public String[] toStringList(final Object data) { + return new String[] { toString(data) }; + } + }); + StringSerializer.VALUES_OF.put(long.class, new Converter() { + @Override + public Object valueOf(final String value) { + return Long.valueOf(value); + } + + @Override + public String toString(final Object data) { + return Long.toString((Long)data); + } + + @Override + public String[] toStringList(final Object data) { + return new String[] { toString(data) }; + } + }); + StringSerializer.VALUES_OF.put(Long.class, new Converter() { + @Override + public Object valueOf(final String value) { + return Long.valueOf(value); + } + + @Override + public String toString(final Object data) { + return Long.toString((Long)data); + } + + @Override + public String[] toStringList(final Object data) { + return new String[] { toString(data) }; + } + }); + StringSerializer.VALUES_OF.put(short.class, new Converter() { + @Override + public Object valueOf(final String value) { + return Short.valueOf(value); + } + + @Override + public String toString(final Object data) { + return Short.toString((Short)data); + } + + @Override + public String[] toStringList(final Object data) { + return new String[] { toString(data) }; + } + }); + StringSerializer.VALUES_OF.put(Short.class, new Converter() { + @Override + public Object valueOf(final String value) { + return Short.valueOf(value); + } + + @Override + public String toString(final Object data) { + return Short.toString((Short)data); + } + + @Override + public String[] toStringList(final Object data) { + return new String[] { toString(data) }; + } + }); + StringSerializer.VALUES_OF.put(boolean.class, new Converter() { + @Override + public Object valueOf(final String value) { + return Boolean.valueOf(value); + } + + @Override + public String toString(final Object data) { + return Boolean.toString((Boolean)data); + } + + @Override + public String[] toStringList(final Object data) { + return new String[] { toString(data) }; + } + }); + StringSerializer.VALUES_OF.put(Boolean.class, new Converter() { + @Override + public Object valueOf(final String value) { + return Boolean.valueOf(value); + } + + @Override + public String toString(final Object data) { + return Boolean.toString((Boolean)data); + } + + @Override + public String[] toStringList(final Object data) { + return new String[] { toString(data) }; + } + }); + StringSerializer.VALUES_OF.put(byte[].class, new Converter() { + @Override + public Object valueOf(final String value) { + return Tools.parseByteStringList(value); + } + + @Override + public String toString(final Object data) { + return Tools.toString((byte[])data); + } + + @Override + public String[] toStringList(final Object data) { + byte[] dataCast = (byte[])data; + String[] out = new String[dataCast.length]; + for (int iii=0; iii clazz) { + return StringSerializer.VALUES_OF.containsKey(clazz); + } + /** + * Un-serialize a String in a specified Object + * @param value String to parse + * @return Data generated or Null + */ + public static Object valueOf(final Class clazz, final String value) { + if (value == null) { + return null; + } + Converter conv = StringSerializer.VALUES_OF.get(clazz); + return conv.valueOf(value); + } + public static String toString(final byte data) { + return Byte.toString(data); + } + public static String toString(final boolean data) { + return Boolean.toString(data); + } + public static String toString(final int data) { + return Integer.toString(data); + } + public static String toString(final short data) { + return Short.toString(data); + } + public static String toString(final long data) { + return Long.toString(data); + } + /** + * Serialize in a string the require data + * @param data Object to serialize + * @return The new data... + */ + public static String toString(final Object data) { + if (data == null) { + return null; + } + Class clazz = data.getClass(); + Converter conv = StringSerializer.VALUES_OF.get(clazz); + return conv.toString(data); + } + public static String[] toStringList(final Object data) { + if (data == null) { + return null; + } + Converter conv = StringSerializer.VALUES_OF.get(data.getClass()); + return conv.toStringList(data); + } + + private StringSerializer() {} +} diff --git a/src/org/atriasoft/exml/Exml.java b/src/org/atriasoft/exml/Exml.java index 261a37a..341e544 100644 --- a/src/org/atriasoft/exml/Exml.java +++ b/src/org/atriasoft/exml/Exml.java @@ -104,8 +104,19 @@ public class Exml { e.printStackTrace(); return null; } - } + + public static T parseOne(final String data, final Class classType, final String rootNodeName) throws ExmlBuilderException, ExmlParserErrorMulti { + T[] elements = Exml.parse(data, 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]; + } + private static String readFile(final Path path, final Charset encoding) throws IOException { byte[] encoded = Files.readAllBytes(path); diff --git a/src/org/atriasoft/exml/builder/BuilderIntrospection.java b/src/org/atriasoft/exml/builder/BuilderIntrospection.java index db90b50..6decf8f 100644 --- a/src/org/atriasoft/exml/builder/BuilderIntrospection.java +++ b/src/org/atriasoft/exml/builder/BuilderIntrospection.java @@ -9,7 +9,7 @@ import org.atriasoft.exml.internal.Log; public class BuilderIntrospection implements Builder { // Keep in cach all the object alredy parsed ==> optimize CPU - final Map, IntrospectionData> elements = new HashMap<>(); + final Map, IntrospectionModel> elements = new HashMap<>(); // The root class (need to keep it if we use 2 time the builder, the root class is no more accessible). final Class rootClassType; final String rootNodeName; @@ -17,15 +17,15 @@ 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, null)); + this.elements.put(classType, IntrospectionModelFactory.createModel(classType)); } - IntrospectionData findOrCreate(final Class classType) throws Exception { - IntrospectionData out = this.elements.get(classType); + IntrospectionModel findOrCreate(final Class classType) throws Exception { + IntrospectionModel out = this.elements.get(classType); if (out != null) { return out; } - out = new IntrospectionData(classType); + out = IntrospectionModelFactory.createModel(classType); this.elements.put(classType, out); return out; } @@ -46,11 +46,11 @@ public class BuilderIntrospection implements Builder { final IntrospectionObject introspectionObject = (IntrospectionObject) parent; // special case of user request parsing of element with ... if (nodeName.equals(introspectionObject.getListNameModel())) { - IntrospectionData inferData = introspectionObject.getDataInterface(); + IntrospectionModel inferData = introspectionObject.getDataInterface(); if (inferData.getClassType().isArray()) { inferData = findOrCreate(inferData.getClassType().getComponentType()); } else if (List.class.isAssignableFrom(inferData.getClassType())) { - inferData = findOrCreate(inferData.getSubClassType()); + Log.critical("inferData = findOrCreate(inferData.getSubClassType());"); } return new IntrospectionObject(inferData); } @@ -59,7 +59,7 @@ public class BuilderIntrospection implements Builder { if (introspectionObject.getDataInterface() == null) { if (nodeName.contentEquals(this.rootNodeName)) { Log.verbose("Create new class: " + this.rootClassType.getCanonicalName()); - final IntrospectionData inferData = findOrCreate(this.rootClassType); + final IntrospectionModel inferData = findOrCreate(this.rootClassType); return new IntrospectionObject(inferData); } // need to add a throw on the node... @@ -71,13 +71,13 @@ public class BuilderIntrospection implements Builder { // 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); + final IntrospectionModel inferData = findOrCreate(typeClass); // Create the data when object is ended created... 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); + final IntrospectionModel inferData = findOrCreate(subTypeClass); // Create the data when object is ended created... return new IntrospectionObject(inferData, listTreeName); } @@ -127,7 +127,7 @@ public class BuilderIntrospection implements Builder { } @Override - public void newElementFinished(final Object parent, final String tmpname, final 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 ??? @@ -135,7 +135,7 @@ public class BuilderIntrospection implements Builder { } final IntrospectionObject introspectionParentObject = (IntrospectionObject) parent; if (introspectionParentObject.getDataInterface() == null) { - if (tmpname.equals(this.rootNodeName)) { + if (tmpName.equals(this.rootNodeName)) { // this is the root node ... Object tmpp = introspectionParentObject.getData(); if( tmpp instanceof List) { @@ -146,6 +146,6 @@ public class BuilderIntrospection implements Builder { } return; } - introspectionParentObject.addObject(tmpname, introspectionElementObject.getData()); + introspectionParentObject.addObject(tmpName, introspectionElementObject.getData()); } } diff --git a/src/org/atriasoft/exml/builder/IntrospectionModel.java b/src/org/atriasoft/exml/builder/IntrospectionModel.java new file mode 100644 index 0000000..460a9dc --- /dev/null +++ b/src/org/atriasoft/exml/builder/IntrospectionModel.java @@ -0,0 +1,68 @@ +package org.atriasoft.exml.builder; + +import java.util.List; +import java.util.Map; + +import org.atriasoft.exml.exception.ExmlBuilderException; + + +public abstract class IntrospectionModel { + protected static final Boolean DEFAULT_CASE_SENSITIVE = true; + protected static final Boolean DEFAULT_MANAGED = true; + protected static final Boolean DEFAULT_OPTIONAL = false; + + protected final Class classType; + + public List getMethods() { + return null; + } + public List getProperties() { + return null; + } + public Class getClassType() { + return this.classType; + } + + public IntrospectionModel(final Class classType) { + this.classType = classType; + } + + Object createObject(final Map properties, final Map> nodes) throws ExmlBuilderException { + return null; + } + + protected List getNodeAvaillable() { + return null; + } + + public Object getValueFromText(final String text) throws ExmlBuilderException { + return null; + } + + public Object getValue(final String propertyName, final String propertyValue) throws ExmlBuilderException { + return null; + } + + public Class getTypeOfSubNode(final Object data, final String nodeName) throws ExmlBuilderException { + return null; + } + public Class getTypeOfSubNodeList(final Object data, final String nodeName) throws ExmlBuilderException { + return null; + } + public String getTreeNameOfSubNode(final Object data, final String nodeName) throws ExmlBuilderException { + return null; + } + public abstract boolean isEndPoint(); + public boolean isList() { + if (this.classType.isArray()) { + return true; + } + if (List.class.isAssignableFrom(this.classType) ) { + return true; + } + return false; + } + public abstract String toString(final Object data); + public abstract String[] toStringList(final Object data); + +} diff --git a/src/org/atriasoft/exml/builder/IntrospectionModelBaseType.java b/src/org/atriasoft/exml/builder/IntrospectionModelBaseType.java new file mode 100644 index 0000000..c465208 --- /dev/null +++ b/src/org/atriasoft/exml/builder/IntrospectionModelBaseType.java @@ -0,0 +1,50 @@ +package org.atriasoft.exml.builder; + +import java.util.List; +import java.util.Map; + +import org.atriasoft.eStringSerialize.StringSerializer; +import org.atriasoft.exml.exception.ExmlBuilderException; + + +public class IntrospectionModelBaseType extends IntrospectionModel { + + public IntrospectionModelBaseType(final Class classType) { + super(classType); + } + + @Override + Object createObject(final Map properties, final Map> nodes) throws ExmlBuilderException { + throw new ExmlBuilderException("Base type model can not have properties and nodes ... "); + } + + @Override + protected List getNodeAvaillable() { + return null; + } + + @Override + public Object getValueFromText(final String text) throws ExmlBuilderException { + return StringSerializer.valueOf(this.classType, text); + } + + @Override + public Object getValue(final String propertyName, final String propertyValue) throws ExmlBuilderException { + return null; + } + + @Override + public boolean isEndPoint() { + return true; + } + + @Override + public String toString(final Object data) { + return StringSerializer.toString(data); + } + @Override + public String[] toStringList(final Object data) { + return StringSerializer.toStringList(data); + } + +} diff --git a/src/org/atriasoft/exml/builder/IntrospectionData.java b/src/org/atriasoft/exml/builder/IntrospectionModelComplex.java similarity index 84% rename from src/org/atriasoft/exml/builder/IntrospectionData.java rename to src/org/atriasoft/exml/builder/IntrospectionModelComplex.java index 184174e..0fd0abf 100644 --- a/src/org/atriasoft/exml/builder/IntrospectionData.java +++ b/src/org/atriasoft/exml/builder/IntrospectionModelComplex.java @@ -9,12 +9,12 @@ import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; -import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.stream.Collectors; +import org.atriasoft.eStringSerialize.StringSerializer; import org.atriasoft.etk.util.ArraysTools; import org.atriasoft.exml.annotation.XmlCaseSensitive; import org.atriasoft.exml.annotation.XmlDefaultCaseSensitive; @@ -29,173 +29,30 @@ import org.atriasoft.exml.internal.Log; import org.atriasoft.exml.parser.Tools; -public class IntrospectionData { - private static final Boolean DEFAULT_CASE_SENSITIVE = true; - private static final Boolean DEFAULT_MANAGED = true; - private static final Boolean DEFAULT_OPTIONAL = false; - public interface Converter { - Object valueOf(String value); - } - private static final Map, Converter> VALUES_OF = new HashMap<>(); - static { - IntrospectionData.VALUES_OF.put(byte.class, new Converter() { - @Override - public Object valueOf(final String value) { - return Byte.valueOf(value); - } - }); - IntrospectionData.VALUES_OF.put(Byte.class, new Converter() { - @Override - public Object valueOf(final String value) { - return Byte.valueOf(value); - } - }); - IntrospectionData.VALUES_OF.put(int.class, new Converter() { - @Override - public Object valueOf(final String value) { - return Integer.valueOf(value); - } - }); - IntrospectionData.VALUES_OF.put(Integer.class, new Converter() { - @Override - public Object valueOf(final String value) { - return Integer.valueOf(value); - } - }); - IntrospectionData.VALUES_OF.put(long.class, new Converter() { - @Override - public Object valueOf(final String value) { - return Long.valueOf(value); - } - }); - IntrospectionData.VALUES_OF.put(Long.class, new Converter() { - @Override - public Object valueOf(final String value) { - return Long.valueOf(value); - } - }); - IntrospectionData.VALUES_OF.put(short.class, new Converter() { - @Override - public Object valueOf(final String value) { - return Short.valueOf(value); - } - }); - IntrospectionData.VALUES_OF.put(Short.class, new Converter() { - @Override - public Object valueOf(final String value) { - return Short.valueOf(value); - } - }); - IntrospectionData.VALUES_OF.put(boolean.class, new Converter() { - @Override - public Object valueOf(final String value) { - return Boolean.valueOf(value); - } - }); - IntrospectionData.VALUES_OF.put(Boolean.class, new Converter() { - @Override - public Object valueOf(final String value) { - return Boolean.valueOf(value); - } - }); - IntrospectionData.VALUES_OF.put(byte[].class, new Converter() { - @Override - public Object valueOf(final String value) { - return Tools.parseByteStringList(value); - } - }); - IntrospectionData.VALUES_OF.put(Byte[].class, new Converter() { - @Override - public Object valueOf(final String value) { - return Tools.parseByteClassStringList(value); - } - }); - IntrospectionData.VALUES_OF.put(short[].class, new Converter() { - @Override - public Object valueOf(final String value) { - return Tools.parseShortStringList(value); - } - }); - IntrospectionData.VALUES_OF.put(Short[].class, new Converter() { - @Override - public Object valueOf(final String value) { - return Tools.parseShortClassStringList(value); - } - }); - IntrospectionData.VALUES_OF.put(int[].class, new Converter() { - @Override - public Object valueOf(final String value) { - return Tools.parseIntegerStringList(value); - } - }); - IntrospectionData.VALUES_OF.put(Integer[].class, new Converter() { - @Override - public Object valueOf(final String value) { - return Tools.parseIntegerClassStringList(value); - } - }); - IntrospectionData.VALUES_OF.put(long[].class, new Converter() { - @Override - public Object valueOf(final String value) { - return Tools.parseLongStringList(value); - } - }); - IntrospectionData.VALUES_OF.put(Long[].class, new Converter() { - @Override - public Object valueOf(final String value) { - return Tools.parseLongClassStringList(value); - } - }); - IntrospectionData.VALUES_OF.put(boolean[].class, new Converter() { - @Override - public Object valueOf(final String value) { - return Tools.parseBooleanStringList(value); - } - }); - IntrospectionData.VALUES_OF.put(Boolean[].class, new Converter() { - @Override - public Object valueOf(final String value) { - return Tools.parseBooleanClassStringList(value); - } - }); - IntrospectionData.VALUES_OF.put(String.class, new Converter() { - @Override - public Object valueOf(final String value) { - return value; - } - }); - } +public class IntrospectionModelComplex extends IntrospectionModel { - 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<>(); + + @Override public List getMethods() { return this.methods; } + @Override public List getProperties() { return this.properties; } - public Class getClassType() { - return this.classType; - } - public Class getSubClassType() { - return this.subClassType; - } - public IntrospectionData(final Class classType) throws ExmlBuilderException { - this(classType, null); - } - public IntrospectionData(final Class classType, final Class subClassType) throws ExmlBuilderException { + + public IntrospectionModelComplex(final Class classType) throws ExmlBuilderException { + super(classType); try { - this.classType = classType; - this.subClassType = subClassType; - final Boolean isDefaultManaged = getIsDefaultManaged(classType, IntrospectionData.DEFAULT_MANAGED); - final Boolean isDefaultOptional = getIsDefaultOptional(classType, IntrospectionData.DEFAULT_OPTIONAL); - final Boolean isDefaultCaseSensitive = getIsDefaultCaseSensitive(classType, IntrospectionData.DEFAULT_CASE_SENSITIVE); + final Boolean isDefaultManaged = getIsDefaultManaged(classType, IntrospectionModel.DEFAULT_MANAGED); + final Boolean isDefaultOptional = getIsDefaultOptional(classType, IntrospectionModel.DEFAULT_OPTIONAL); + final Boolean isDefaultCaseSensitive = getIsDefaultCaseSensitive(classType, IntrospectionModel.DEFAULT_CASE_SENSITIVE); Log.verbose("Introspect class: '" + classType.getCanonicalName() + "'"); final Constructor[] constructors = this.classType.getConstructors(); Log.verbose(" Constructors: (" + constructors.length + ")"); @@ -446,12 +303,16 @@ public class IntrospectionData { } } + @Override 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) { + // pb here, can not create a primitive object with the correct elements... ==> must be generated with a siblist of elements + + Constructor[] constructors = this.classType.getConstructors(); + Object tmp2 = null; + tmp = constructors[0].newInstance(tmp2); + } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | SecurityException e) { // TODO Auto-generated catch block e.printStackTrace(); return null; @@ -466,6 +327,7 @@ public class IntrospectionData { } + @Override protected List getNodeAvaillable() { List out = new ArrayList<>(); for (final IntrospectionProperty prop : this.methods) { @@ -804,30 +666,13 @@ public class IntrospectionData { throw new ExmlBuilderException("can not find the field '" + name + "'"); } - public void setProperty(final Object data, 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); - if (propMethode != null && propMethode.canSetValue()) { - Log.verbose(" ==> find '" + propMethode.getNames()); - propMethode.setValue(data, propertyValue); - return; - } - // try with direct field - final IntrospectionProperty propField = findPropertyDescription(propertyName); - if (propField != null && propField.canSetValue()) { - Log.verbose(" ==> find '" + propField.getNames()); - propField.setValue(data, propertyValue); - return; - } - throw new ExmlBuilderException("can not find the field '" + propertyName + "'"); - } /** * Detect a subNode, and ask the type of the node at the parent Class * @param nodeName Name of the node * @return Class of the node to create */ + @Override public Class getTypeOfSubNode(final Object data, final String nodeName) throws ExmlBuilderException { Log.error(" nodeType='" + nodeName + "'"); // by default use setter to set the property @@ -845,6 +690,7 @@ public class IntrospectionData { throw new ExmlBuilderException("can not find the field '" + nodeName + "' availlable: " + getNodeAvaillable()); } + @Override public Class getTypeOfSubNodeList(final Object data, final String nodeName) throws ExmlBuilderException { Log.error(" nodeType='" + nodeName + "'"); // by default use setter to set the property @@ -861,6 +707,7 @@ public class IntrospectionData { } throw new ExmlBuilderException("can not find the field '" + nodeName + "' availlable: " + getNodeAvaillable()); } + @Override public String getTreeNameOfSubNode(final Object data, final String nodeName) throws ExmlBuilderException { Log.error(" nodeType='" + nodeName + "'"); // by default use setter to set the property @@ -879,6 +726,7 @@ public class IntrospectionData { } + @Override public Object getValueFromText(final String text) throws ExmlBuilderException { // Note if the type is an Array<>() or a List<>() ==> we parse element by element ... then we need to keep the undertype... Class classTypeLocal = this.classType; @@ -889,9 +737,9 @@ public class IntrospectionData { classTypeLocal = this.classType.getComponentType(); } else if (List.class == this.classType || Collection.class.isAssignableFrom(this.classType)) { // a generic list .... - if (this.subClassType != null) { + /*if (this.subClassType != null) { classTypeLocal = this.subClassType; - } + }*/ //Type[] tmpp = this.classType.getGenericInterfaces(); //Class[] tmpp = this.classType.getNestMembers(); //Class[] tmpp = this.classType.getClasses(); @@ -912,11 +760,10 @@ public class IntrospectionData { Log.warning("======>>>>>>> subElement input type : " + classTypeLocal.getCanonicalName()); if (this.valueof == null) { - Converter con = IntrospectionData.VALUES_OF.get(classTypeLocal); - if (con == null) { + if (StringSerializer.contains(classTypeLocal)) { throw new ExmlBuilderException("function 'valueOf' for '" + classTypeLocal.getCanonicalName() + "' is not defined and not registered for specific type"); } - return con.valueOf(text); + return StringSerializer.valueOf(classTypeLocal, text); } try { return this.valueof.invoke(null, text); @@ -929,6 +776,7 @@ public class IntrospectionData { } } + @Override public Object getValue(final String propertyName, final String propertyValue) throws ExmlBuilderException { Log.error(" propertyName='" + propertyName + "' propertyValue='" + propertyValue + "' "); // by default use setter to set the property @@ -945,6 +793,19 @@ public class IntrospectionData { } throw new ExmlBuilderException("can not find the field '" + propertyName + "'"); } + @Override + public boolean isEndPoint() { + return false; + } + @Override + public String toString(final Object data) { + return null; + } + @Override + public String[] toStringList(final Object data) { + // TODO Auto-generated method stub + return null; + } } diff --git a/src/org/atriasoft/exml/builder/IntrospectionModelFactory.java b/src/org/atriasoft/exml/builder/IntrospectionModelFactory.java new file mode 100644 index 0000000..131e9b3 --- /dev/null +++ b/src/org/atriasoft/exml/builder/IntrospectionModelFactory.java @@ -0,0 +1,17 @@ +package org.atriasoft.exml.builder; + +import org.atriasoft.eStringSerialize.StringSerializer; +import org.atriasoft.exml.exception.ExmlBuilderException; + + +public class IntrospectionModelFactory { + private IntrospectionModelFactory() {} + + public static IntrospectionModel createModel(final Class classType) throws ExmlBuilderException { + if (StringSerializer.contains(classType)) { + return new IntrospectionModelBaseType(classType); + } + return new IntrospectionModelComplex(classType); + } + +} diff --git a/src/org/atriasoft/exml/builder/IntrospectionObject.java b/src/org/atriasoft/exml/builder/IntrospectionObject.java index cf96732..e0cb63a 100644 --- a/src/org/atriasoft/exml/builder/IntrospectionObject.java +++ b/src/org/atriasoft/exml/builder/IntrospectionObject.java @@ -9,7 +9,7 @@ import org.atriasoft.exml.exception.ExmlBuilderException; import org.atriasoft.exml.internal.Log; public class IntrospectionObject { - private final IntrospectionData dataInterface; + private final IntrospectionModel dataInterface; private Object data = null; private final String listNameModel; private final Map properties = new HashMap<>(); @@ -24,12 +24,12 @@ public class IntrospectionObject { this.listNameModel = null; } - public IntrospectionObject(final IntrospectionData dataInterface, final String listNameModel) { + public IntrospectionObject(final IntrospectionModel dataInterface, final String listNameModel) { this.dataInterface = dataInterface; this.listNameModel = listNameModel; } - public IntrospectionObject(final IntrospectionData dataInterface) { + public IntrospectionObject(final IntrospectionModel dataInterface) { this.dataInterface = dataInterface; this.listNameModel = null; } @@ -42,7 +42,7 @@ public class IntrospectionObject { return this.data; } - public IntrospectionData getDataInterface() { + public IntrospectionModel getDataInterface() { return this.dataInterface; } diff --git a/src/org/atriasoft/exml/builder/IntrospectionProperty.java b/src/org/atriasoft/exml/builder/IntrospectionProperty.java index 3b0a7a6..688a4ed 100644 --- a/src/org/atriasoft/exml/builder/IntrospectionProperty.java +++ b/src/org/atriasoft/exml/builder/IntrospectionProperty.java @@ -1,7 +1,11 @@ package org.atriasoft.exml.builder; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import org.atriasoft.eStringSerialize.StringSerializer; import org.atriasoft.exml.exception.ExmlBuilderException; -import org.atriasoft.exml.parser.Tools; public abstract class IntrospectionProperty { protected final Boolean caseSensitive; @@ -47,61 +51,23 @@ public abstract class IntrospectionProperty { if (value == null) { return null; } - if (this.type == byte.class) { - return Byte.toString((byte)value); + if (StringSerializer.contains(this.type)) { + return StringSerializer.toString(value); } - if (this.type == short.class) { - return Short.toString((short)value); - } - if (this.type == int.class) { - return Integer.toString((int)value); - } - if (this.type == long.class) { - return Long.toString((long)value); - } - if (this.type == boolean.class) { - return Boolean.toString((boolean)value); - } - if (this.type == String.class) { - return (String)value; - } - if (this.type == Byte.class) { - return Byte.toString((Byte)value); - } - if (this.type == Short.class) { - return Short.toString((short)value); - } - if (this.type == Integer.class) { - return Integer.toString((Integer)value); - } else if (this.type == Long.class) { - return Long.toString((Long)value); - } else if (this.type == Boolean.class) { - return Boolean.toString((Boolean)value); - } else if (this.type == byte[].class) { - return Tools.toString((byte[])value); - } else if (this.type == Byte[].class) { - return Tools.toString((Byte[])value); - } else if (this.type == short[].class) { - return Tools.toString((short[])value); - } else if (this.type == Short[].class) { - return Tools.toString((Short[])value); - } else if (this.type == int[].class) { - return Tools.toString((int[])value); - } else if (this.type == Integer[].class) { - return Tools.toString((Integer[])value); - } else if (this.type == long[].class) { - return Tools.toString((long[])value); - } else if (this.type == Long[].class) { - return Tools.toString((Long[])value); - } else if (this.type == boolean[].class) { - return Tools.toString((boolean[])value); - } else if (this.type == Boolean[].class) { - return Tools.toString((Boolean[])value); - } else { - //throw new ExmlBuilderException("Can not parse the specific element ... need to introspect and find the 'xxx valueOf(String data);'"); + if (value instanceof Collection) { + ArrayList data = new ArrayList<>((Collection)value); + StringBuilder out = new StringBuilder(); + for (int iii=0; iii out = new ArrayList<>(); + for (String elem : value.split(";")) { + out.add(StringSerializer.valueOf(this.subType, elem)); + } + return out; + } catch (IllegalArgumentException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + throw new ExmlBuilderException("Error in parsing the property value ... " + e.getMessage()); + } + } } \ No newline at end of file diff --git a/src/org/atriasoft/exml/builder/IntrospectionPropertyField.java b/src/org/atriasoft/exml/builder/IntrospectionPropertyField.java index 56d6879..f19ffca 100644 --- a/src/org/atriasoft/exml/builder/IntrospectionPropertyField.java +++ b/src/org/atriasoft/exml/builder/IntrospectionPropertyField.java @@ -5,7 +5,6 @@ import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import org.atriasoft.exml.exception.ExmlBuilderException; -import org.atriasoft.exml.parser.Tools; public class IntrospectionPropertyField extends IntrospectionProperty { private final Field fieldDescription; @@ -53,134 +52,7 @@ public class IntrospectionPropertyField extends IntrospectionProperty { throw new ExmlBuilderException("Can not set value ... " + e.getMessage()); } } - - @Override - public void setValue(final Object object, final String value) throws ExmlBuilderException { - try { - if (this.type == byte.class) { - final byte data = Byte.parseByte(value); - this.fieldDescription.setByte(object, data); - } else if (this.type == short.class) { - final short data = Short.parseShort(value); - this.fieldDescription.setShort(object, data); - } else if (this.type == int.class) { - final int data = Integer.parseInt(value); - this.fieldDescription.setInt(object, data); - } else if (this.type == long.class) { - final long data = Long.parseLong(value); - this.fieldDescription.setLong(object, data); - } else if (this.type == boolean.class) { - final boolean data = Boolean.parseBoolean(value); - this.fieldDescription.setBoolean(object, data); - } else if (this.type == String.class) { - this.fieldDescription.set(object, value); - } else if (this.type == Byte.class) { - final Byte data = Byte.valueOf(value); - this.fieldDescription.set(object, data); - } else if (this.type == Short.class) { - final Short data = Short.valueOf(value); - this.fieldDescription.set(object, data); - } else if (this.type == Integer.class) { - final Integer data = Integer.valueOf(value); - this.fieldDescription.set(object, data); - } else if (this.type == Long.class) { - final Long data = Long.valueOf(value); - this.fieldDescription.set(object, data); - } else if (this.type == Boolean.class) { - final Boolean data = Boolean.valueOf(value); - this.fieldDescription.set(object, data); - } else if (this.type == byte[].class) { - this.fieldDescription.set(object, Tools.parseByteStringList(value)); - } else if (this.type == Byte[].class) { - this.fieldDescription.set(object, Tools.parseByteClassStringList(value)); - } else if (this.type == short[].class) { - this.fieldDescription.set(object, Tools.parseShortStringList(value)); - } else if (this.type == Short[].class) { - this.fieldDescription.set(object, Tools.parseShortClassStringList(value)); - } else if (this.type == int[].class) { - this.fieldDescription.set(object, Tools.parseIntegerStringList(value)); - } else if (this.type == Integer[].class) { - this.fieldDescription.set(object, Tools.parseIntegerClassStringList(value)); - } else if (this.type == long[].class) { - this.fieldDescription.set(object, Tools.parseLongStringList(value)); - } else if (this.type == Long[].class) { - this.fieldDescription.set(object, Tools.parseLongClassStringList(value)); - } else if (this.type == boolean[].class) { - this.fieldDescription.set(object, Tools.parseBooleanStringList(value)); - } else if (this.type == Boolean[].class) { - this.fieldDescription.set(object, Tools.parseBooleanClassStringList(value)); - } else { - throw new ExmlBuilderException("Can not parse the specific element ... need to introspect and find the 'xxx valueOf(String data);'"); - } - } catch (IllegalArgumentException | IllegalAccessException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - throw new ExmlBuilderException("Error in parsing the property value ... " + e.getMessage()); - } - } - @Override - protected Object createValue(final String value) throws ExmlBuilderException { - try { - if (this.type == byte.class) { - return Byte.valueOf(value); - } - if (this.type == short.class) { - return Short.valueOf(value); - } - if (this.type == int.class) { - return Integer.valueOf(value); - } - if (this.type == long.class) { - return Long.valueOf(value); - } - if (this.type == boolean.class) { - return Boolean.valueOf(value); - } - if (this.type == String.class) { - return value; - } - if (this.type == Byte.class) { - return Byte.valueOf(value); - } - if (this.type == Short.class) { - return Short.valueOf(value); - } - if (this.type == Integer.class) { - return Integer.valueOf(value); - } else if (this.type == Long.class) { - return Long.valueOf(value); - } else if (this.type == Boolean.class) { - return Boolean.valueOf(value); - } else if (this.type == byte[].class) { - return Tools.parseByteStringList(value); - } else if (this.type == Byte[].class) { - return Tools.parseByteClassStringList(value); - } else if (this.type == short[].class) { - return Tools.parseShortStringList(value); - } else if (this.type == Short[].class) { - return Tools.parseShortClassStringList(value); - } else if (this.type == int[].class) { - return Tools.parseIntegerStringList(value); - } else if (this.type == Integer[].class) { - return Tools.parseIntegerClassStringList(value); - } else if (this.type == long[].class) { - return Tools.parseLongStringList(value); - } else if (this.type == Long[].class) { - return Tools.parseLongClassStringList(value); - } else if (this.type == boolean[].class) { - return Tools.parseBooleanStringList(value); - } else if (this.type == Boolean[].class) { - return Tools.parseBooleanClassStringList(value); - } else { - throw new ExmlBuilderException("Can not parse the specific element ... need to introspect and find the 'xxx valueOf(String data);'"); - } - } catch (IllegalArgumentException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - throw new ExmlBuilderException("Error in parsing the property value ... " + e.getMessage()); - } - } @Override public void setExistingValue(final Object object, final Object value) throws ExmlBuilderException { diff --git a/src/org/atriasoft/exml/builder/IntrospectionPropertyMethod.java b/src/org/atriasoft/exml/builder/IntrospectionPropertyMethod.java index df10cec..bae1aa5 100644 --- a/src/org/atriasoft/exml/builder/IntrospectionPropertyMethod.java +++ b/src/org/atriasoft/exml/builder/IntrospectionPropertyMethod.java @@ -8,7 +8,6 @@ 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 { @@ -90,139 +89,7 @@ public class IntrospectionPropertyMethod extends IntrospectionProperty { throw new ExmlBuilderException("Can not set value ... " + e.getMessage()); } } - - @Override - public void setValue(final Object object, final String value) throws ExmlBuilderException { - if (this.setter == null) { - throw new ExmlBuilderException("no setter availlable"); - } - try { - if (this.type == byte.class) { - final byte data = Byte.parseByte(value); - this.setter.invoke(object, data); - } else if (this.type == short.class) { - final short data = Short.parseShort(value); - this.setter.invoke(object, data); - } else if (this.type == int.class) { - final int data = Integer.parseInt(value); - this.setter.invoke(object, data); - } else if (this.type == long.class) { - final long data = Long.parseLong(value); - this.setter.invoke(object, data); - } else if (this.type == boolean.class) { - final boolean data = Boolean.parseBoolean(value); - this.setter.invoke(object, data); - } else if (this.type == String.class) { - this.setter.invoke(object, value); - } else if (this.type == Byte.class) { - final Byte data = Byte.valueOf(value); - this.setter.invoke(object, data); - } else if (this.type == Short.class) { - final Short data = Short.valueOf(value); - this.setter.invoke(object, data); - } else if (this.type == Integer.class) { - final Integer data = Integer.valueOf(value); - this.setter.invoke(object, data); - } else if (this.type == Long.class) { - final Long data = Long.valueOf(value); - this.setter.invoke(object, data); - } else if (this.type == Boolean.class) { - final Boolean data = Boolean.valueOf(value); - this.setter.invoke(object, data); - } else if (this.type == byte[].class) { - this.setter.invoke(object, Tools.parseByteStringList(value)); - } else if (this.type == Byte[].class) { - this.setter.invoke(object, (Object) Tools.parseByteClassStringList(value)); - } else if (this.type == short[].class) { - this.setter.invoke(object, Tools.parseShortStringList(value)); - } else if (this.type == Short[].class) { - this.setter.invoke(object, (Object) Tools.parseShortClassStringList(value)); - } else if (this.type == int[].class) { - this.setter.invoke(object, Tools.parseIntegerStringList(value)); - } else if (this.type == Integer[].class) { - this.setter.invoke(object, (Object) Tools.parseIntegerClassStringList(value)); - } else if (this.type == long[].class) { - this.setter.invoke(object, Tools.parseLongStringList(value)); - } else if (this.type == Long[].class) { - this.setter.invoke(object, (Object) Tools.parseLongClassStringList(value)); - } else if (this.type == boolean[].class) { - this.setter.invoke(object, Tools.parseBooleanStringList(value)); - } else if (this.type == Boolean[].class) { - this.setter.invoke(object, (Object) Tools.parseBooleanClassStringList(value)); - } else { - throw new ExmlBuilderException("Can not parse the specific element ... need to introspect and find the 'xxx valueOf(String data);'"); - } - } catch (IllegalArgumentException | IllegalAccessException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - throw new ExmlBuilderException("Error in parsing the property value ... " + e.getMessage()); - } catch (InvocationTargetException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - throw new ExmlBuilderException("Error in invoque setter of the Object ... " + e.getMessage()); - } - } - - @Override - protected Object createValue(final String value) throws ExmlBuilderException { - try { - if (this.type == byte.class) { - return Byte.valueOf(value); - } - if (this.type == short.class) { - return Short.valueOf(value); - } - if (this.type == int.class) { - return Integer.valueOf(value); - } - if (this.type == long.class) { - return Long.valueOf(value); - } - if (this.type == boolean.class) { - return Boolean.valueOf(value); - } - if (this.type == String.class) { - return value; - } else if (this.type == Byte.class) { - return Byte.valueOf(value); - } else if (this.type == Short.class) { - return Short.valueOf(value); - } else if (this.type == Integer.class) { - return Integer.valueOf(value); - } else if (this.type == Long.class) { - return Long.valueOf(value); - } else if (this.type == Boolean.class) { - return Boolean.valueOf(value); - } else if (this.type == byte[].class) { - return Tools.parseByteStringList(value); - } else if (this.type == Byte[].class) { - return Tools.parseByteClassStringList(value); - } else if (this.type == short[].class) { - return Tools.parseShortStringList(value); - } else if (this.type == Short[].class) { - return Tools.parseShortClassStringList(value); - } else if (this.type == int[].class) { - return Tools.parseIntegerStringList(value); - } else if (this.type == Integer[].class) { - return Tools.parseIntegerClassStringList(value); - } else if (this.type == long[].class) { - return Tools.parseLongStringList(value); - } else if (this.type == Long[].class) { - return Tools.parseLongClassStringList(value); - } else if (this.type == boolean[].class) { - return Tools.parseBooleanStringList(value); - } else if (this.type == Boolean[].class) { - return Tools.parseBooleanClassStringList(value); - } else { - throw new ExmlBuilderException("Can not parse the specific element ... need to introspect and find the 'xxx valueOf(String data);'"); - } - } catch (IllegalArgumentException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - throw new ExmlBuilderException("Error in parsing the property value ... " + e.getMessage()); - } - } - + @Override public void setExistingValue(final Object object, final Object value) throws ExmlBuilderException { if (this.setter == null) { diff --git a/src/org/atriasoft/exml/generator/GeneratorIntrospection.java b/src/org/atriasoft/exml/generator/GeneratorIntrospection.java index 730f1c4..c1daa3e 100644 --- a/src/org/atriasoft/exml/generator/GeneratorIntrospection.java +++ b/src/org/atriasoft/exml/generator/GeneratorIntrospection.java @@ -4,14 +4,15 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import org.atriasoft.exml.builder.IntrospectionData; +import org.atriasoft.exml.builder.IntrospectionModel; +import org.atriasoft.exml.builder.IntrospectionModelFactory; import org.atriasoft.exml.builder.IntrospectionProperty; import org.atriasoft.exml.exception.ExmlBuilderException; import org.atriasoft.exml.parser.Tools; public class GeneratorIntrospection implements Generator { // Keep in cach all the object alredy parsed ==> optimize CPU - final Map, IntrospectionData> elements = new HashMap<>(); + final Map, IntrospectionModel> elements = new HashMap<>(); // The root class (need to keep it if we use 2 time the builder, the root class is no more accessible). final Class rootClassType; final String rootNodeName; @@ -19,65 +20,107 @@ public class GeneratorIntrospection implements Generator { public GeneratorIntrospection(final Class classType, final String rootNodeName) throws Exception { this.rootNodeName = rootNodeName; this.rootClassType = classType; - this.elements.put(classType, new IntrospectionData(classType, null)); + this.elements.put(classType, IntrospectionModelFactory.createModel(classType)); } - IntrospectionData findOrCreate(final Class classType) throws ExmlBuilderException { - IntrospectionData out = this.elements.get(classType); + IntrospectionModel findOrCreate(final Class classType) throws ExmlBuilderException { + IntrospectionModel out = this.elements.get(classType); if (out != null) { return out; } - out = new IntrospectionData(classType); + out = IntrospectionModelFactory.createModel(classType); this.elements.put(classType, out); return out; } - public void generateProperties(final Object data, final IntrospectionData introspection, final StringBuilder tmpp) throws ExmlBuilderException { + public void generateProperties(final Object data, final IntrospectionModel introspection, final StringBuilder tmpp) throws ExmlBuilderException { List elements = introspection.getProperties(); + if (elements == null) { + return; + } for (IntrospectionProperty elem : elements) { if (!elem.canGetValue()) { continue; } - String name = elem.getNames()[0]; String dataString=elem.getValueString(data); - tmpp.append(" "); - tmpp.append(name); - tmpp.append("=\""); - tmpp.append(dataString); - tmpp.append("\""); + if (dataString != null) { + String name = elem.getNames()[0]; + tmpp.append(" "); + tmpp.append(name); + tmpp.append("=\""); + tmpp.append(dataString); + tmpp.append("\""); + } } } - public void generateSubNodes(final Object data, final IntrospectionData introspection, final StringBuilder tmpp, int indent) throws ExmlBuilderException { + public void generateSubNodes(final Object data, final IntrospectionModel introspection, final StringBuilder tmpp, final int indent) throws ExmlBuilderException { List elements = introspection.getMethods(); for (IntrospectionProperty elem : elements) { if (!elem.canGetValue()) { continue; } String name = elem.getNames()[0]; - + Object dataObj =elem.getValue(data); - - if (dataObj != null) { + if (dataObj == null) { + continue; + } + Class type = elem.getType(); + generateNode(dataObj, name, tmpp, indent); + /* + if (List.class.isAssignableFrom(type)) { + // special case for List ... + type = elem.getSubType(); + generateNodeList(dataObj, name, tmpp, indent); + } else { generateNode(dataObj, name, tmpp, indent); } + */ } } - public void generateNode(final Object data, final String nodeName, final StringBuilder tmpp, int indent) throws ExmlBuilderException { - IntrospectionData introspection = findOrCreate(data.getClass()); - Tools.addIndent(tmpp, indent); - tmpp.append("<"); - tmpp.append(nodeName); - generateProperties(data, introspection, tmpp); - if (introspection.getMethods().size() != 0) { - tmpp.append(">\n"); - generateSubNodes(data, introspection, tmpp, indent + 1); - Tools.addIndent(tmpp, indent); - tmpp.append("\n"); + + public void generateNode(final Object data, final String nodeName, final StringBuilder tmpp, final int indent) throws ExmlBuilderException { + IntrospectionModel introspection = findOrCreate(data.getClass()); + if (introspection.isEndPoint()) { + if (introspection.isList()) { + String[] listDatas = introspection.toStringList(data); + for (int iii=0; iii"); + tmpp.append(listDatas[iii]); + tmpp.append(""); + } + } else { + Tools.addIndent(tmpp, indent); + tmpp.append("<"); + tmpp.append(nodeName); + tmpp.append(">"); + tmpp.append(introspection.toString(data)); + tmpp.append(""); + } } else { - tmpp.append("/>\n"); + Tools.addIndent(tmpp, indent); + tmpp.append("<"); + tmpp.append(nodeName); + generateProperties(data, introspection, tmpp); + if (introspection.getMethods().size() != 0) { + tmpp.append(">"); + generateSubNodes(data, introspection, tmpp, indent + 1); + Tools.addIndent(tmpp, indent); + tmpp.append(""); + } else { + tmpp.append("/>"); + } } + } public void generate(final Object root, final StringBuilder tmpp) throws ExmlBuilderException { generateNode(root, this.rootNodeName, tmpp, 0); diff --git a/src/org/atriasoft/exml/parser/Tools.java b/src/org/atriasoft/exml/parser/Tools.java index c92c058..e286bca 100644 --- a/src/org/atriasoft/exml/parser/Tools.java +++ b/src/org/atriasoft/exml/parser/Tools.java @@ -7,6 +7,9 @@ public class Tools { * @param indent Number of tab to add at the string. */ public static void addIndent(final StringBuilder data, final int indent) { + if (!data.isEmpty()) { + data.append("\n"); + } for (int iii = 0; iii < indent; iii++) { data.append("\t"); } @@ -159,7 +162,7 @@ public class Tools { } return out; } - public static String toString(Boolean[] data) { + public static String toString(final Boolean[] data) { StringBuilder out = new StringBuilder(); for (int iii=0; iii\n"); + data.append("-->"); } private static void serializeDeclaration(final XmlDeclaration declaration, final StringBuilder data, final int indent) { @@ -54,7 +54,7 @@ public class SerializerXml { data.append("\n"); + data.append("?>"); } @@ -72,7 +72,7 @@ public class SerializerXml { SerializerXml.serialize(nodes.get(0), data, 0); Log.verbose(" generate : '" + data + "'"); } else { - data.append(">\n"); + data.append(">"); for (XmlNode node : nodes) { if (node != null) { SerializerXml.serialize(node, data, indent + 1); @@ -82,9 +82,9 @@ public class SerializerXml { } data.append("\n"); + data.append(">"); } else { - data.append("/>\n"); + data.append("/>"); } } diff --git a/test/src/test/atriasoft/exml/ExmlTestIntrospectionBoolean.java b/test/src/test/atriasoft/exml/ExmlTestIntrospectionBoolean.java new file mode 100644 index 0000000..6ba9d53 --- /dev/null +++ b/test/src/test/atriasoft/exml/ExmlTestIntrospectionBoolean.java @@ -0,0 +1,211 @@ +/** @file + * @author Edouard DUPIN + * @copyright 2021, Edouard DUPIN, all right reserved + * @license MPL v2.0 (see license file) + */ +package test.atriasoft.exml; + +import java.util.List; + +import org.atriasoft.exml.Exml; +import org.atriasoft.exml.annotation.XmlDefaultAttibute; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +public class ExmlTestIntrospectionBoolean { + static final String NODE_NAME = "elem"; + @BeforeAll + public static void beforeClass() { + Log.warning("================================================================"); + } + + @XmlDefaultAttibute + public class TestBoolean { + public Boolean valueA; + public Boolean valueB; + public Boolean valueNull; + } + @Test + public void testModelBoolean() { + TestBoolean elem = new TestBoolean(); + elem.valueA = false; + elem.valueB = true; + elem.valueNull = null; + + StringBuilder builder = new StringBuilder(); + Assertions.assertDoesNotThrow(() -> Exml.generate(elem, ExmlTestIntrospectionBoolean.NODE_NAME, builder)); + String dataTest = builder.toString(); + Log.warning("data generated: " + builder.toString()); + Assertions.assertEquals("", dataTest); + + final TestBoolean root = Assertions.assertDoesNotThrow(() -> Exml.parseOne(dataTest, TestBoolean.class, ExmlTestIntrospectionBoolean.NODE_NAME)); + Assertions.assertEquals(false, root.valueA); + Assertions.assertEquals(true, root.valueB); + Assertions.assertEquals(null, root.valueNull); + } + + @XmlDefaultAttibute + public class TestArrayBoolean { + public Boolean[] values; + } + @Test + public void testModelArrayBoolean() { + TestArrayBoolean elem = new TestArrayBoolean(); + elem.values = new Boolean[] {false, false, true, false, true}; + + StringBuilder builder = new StringBuilder(); + Assertions.assertDoesNotThrow(() -> Exml.generate(elem, ExmlTestIntrospectionBoolean.NODE_NAME, builder)); + String dataTest = builder.toString(); + Log.warning("data generated: " + builder.toString()); + Assertions.assertEquals("", dataTest); + + final TestArrayBoolean root = Assertions.assertDoesNotThrow(() -> Exml.parseOne(dataTest, TestArrayBoolean.class, ExmlTestIntrospectionBoolean.NODE_NAME)); + Assertions.assertEquals(5, root.values.length); + Assertions.assertEquals(false, root.values[0]); + Assertions.assertEquals(false, root.values[1]); + Assertions.assertEquals(true, root.values[2]); + Assertions.assertEquals(false, root.values[3]); + Assertions.assertEquals(true, root.values[4]); + } + + @XmlDefaultAttibute + public class TestListBoolean { + public List values; + } + @Test + public void testModelListBoolean() { + TestListBoolean elem = new TestListBoolean(); + elem.values = List.of(false, false, true, false, true); + + StringBuilder builder = new StringBuilder(); + Assertions.assertDoesNotThrow(() -> Exml.generate(elem, ExmlTestIntrospectionBoolean.NODE_NAME, builder)); + String dataTest = builder.toString(); + Log.warning("data generated: " + builder.toString()); + Assertions.assertEquals("", dataTest); + + final TestListBoolean root = Assertions.assertDoesNotThrow(() -> Exml.parseOne(dataTest, TestListBoolean.class, ExmlTestIntrospectionBoolean.NODE_NAME)); + Assertions.assertEquals(5, root.values.size()); + Assertions.assertEquals(false, root.values.get(0)); + Assertions.assertEquals(false, root.values.get(1)); + Assertions.assertEquals(true, root.values.get(2)); + Assertions.assertEquals(false, root.values.get(3)); + Assertions.assertEquals(true, root.values.get(4)); + } + + + @XmlDefaultAttibute + public class TestBooleanFunc { + private Boolean valueA; + private Boolean valueB; + private Boolean valueNull; + public Boolean getValueA() { + return this.valueA; + } + public void setValueA(final Boolean valueA) { + this.valueA = valueA; + } + public Boolean getValueB() { + return this.valueB; + } + public void setValueB(final Boolean valueB) { + this.valueB = valueB; + } + public Boolean getValueNull() { + return this.valueNull; + } + public void setValueNull(final Boolean valueNull) { + this.valueNull = valueNull; + } + } + + @Test + public void testModelBooleanFunc() { + TestBooleanFunc elem = new TestBooleanFunc(); + elem.setValueA(false); + elem.setValueB(true); + elem.setValueNull(null); + + StringBuilder builder = new StringBuilder(); + Assertions.assertDoesNotThrow(() -> Exml.generate(elem, ExmlTestIntrospectionBoolean.NODE_NAME, builder)); + String dataTest = builder.toString(); + Log.warning("data generated: " + builder.toString()); + Assertions.assertEquals("", dataTest); + + final TestBooleanFunc root = Assertions.assertDoesNotThrow(() -> Exml.parseOne(dataTest, TestBooleanFunc.class, ExmlTestIntrospectionBoolean.NODE_NAME)); + Assertions.assertEquals(false, root.getValueA()); + Assertions.assertEquals(true, root.getValueB()); + Assertions.assertEquals(null, root.getValueNull()); + } + + @XmlDefaultAttibute + public class TestArrayBooleanFunc { + private Boolean[] values; + + public Boolean[] getValues() { + return this.values; + } + + public void setValues(final Boolean[] values) { + this.values = values; + } + + } + @Test + public void testModelArrayBooleanFunc() { + TestArrayBooleanFunc elem = new TestArrayBooleanFunc(); + elem.setValues(new Boolean[] {false, false, true, false, true}); + + StringBuilder builder = new StringBuilder(); + Assertions.assertDoesNotThrow(() -> Exml.generate(elem, ExmlTestIntrospectionBoolean.NODE_NAME, builder)); + String dataTest = builder.toString(); + Log.warning("data generated: " + builder.toString()); + Assertions.assertEquals("", dataTest); + + final TestArrayBooleanFunc root = Assertions.assertDoesNotThrow(() -> Exml.parseOne(dataTest, TestArrayBooleanFunc.class, ExmlTestIntrospectionBoolean.NODE_NAME)); + Assertions.assertEquals(5, root.getValues().length); + Assertions.assertEquals(false, root.getValues()[0]); + Assertions.assertEquals(false, root.getValues()[1]); + Assertions.assertEquals(true, root.getValues()[2]); + Assertions.assertEquals(false, root.getValues()[3]); + Assertions.assertEquals(true, root.getValues()[4]); + } + + @XmlDefaultAttibute + public class TestListBooleanFunc { + private List values; + + public List getValues() { + return this.values; + } + + public void setValues(final List values) { + this.values = values; + } + } + @Test + public void testModelListBooleanFunc() { + TestListBooleanFunc elem = new TestListBooleanFunc(); + elem.setValues(List.of(false, false, true, false, true)); + + StringBuilder builder = new StringBuilder(); + Assertions.assertDoesNotThrow(() -> Exml.generate(elem, ExmlTestIntrospectionBoolean.NODE_NAME, builder)); + String dataTest = builder.toString(); + Log.warning("data generated: " + builder.toString()); + Assertions.assertEquals("", dataTest); + + final TestListBooleanFunc root = Assertions.assertDoesNotThrow(() -> Exml.parseOne(dataTest, TestListBooleanFunc.class, ExmlTestIntrospectionBoolean.NODE_NAME)); + Assertions.assertEquals(5, root.getValues().size()); + Assertions.assertEquals(false, root.getValues().get(0)); + Assertions.assertEquals(false, root.getValues().get(1)); + Assertions.assertEquals(true, root.getValues().get(2)); + Assertions.assertEquals(false, root.getValues().get(3)); + Assertions.assertEquals(true, root.getValues().get(4)); + } + + + + +} + diff --git a/test/src/test/atriasoft/exml/ExmlTestIntrospectionBooleanNative.java b/test/src/test/atriasoft/exml/ExmlTestIntrospectionBooleanNative.java new file mode 100644 index 0000000..8c7843d --- /dev/null +++ b/test/src/test/atriasoft/exml/ExmlTestIntrospectionBooleanNative.java @@ -0,0 +1,49 @@ +/** @file + * @author Edouard DUPIN + * @copyright 2021, Edouard DUPIN, all right reserved + * @license MPL v2.0 (see license file) + */ +package test.atriasoft.exml; + +import org.atriasoft.exml.Exml; +import org.atriasoft.exml.annotation.XmlDefaultAttibute; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +public class ExmlTestIntrospectionBooleanNative { + private static final String NODE_NAME = "elem"; + @BeforeAll + public static void beforeClass() { + Log.verbose("----------------------------------------------------------------"); + } + + @XmlDefaultAttibute + public class TestArrayBooleanNative { + public boolean[] values; + } + @Test + public void testModelArrayBooleanNative() { + TestArrayBooleanNative elem = new TestArrayBooleanNative(); + elem.values = new boolean[] {false, false, true, false, true}; + + StringBuilder builder = new StringBuilder(); + Assertions.assertDoesNotThrow(() -> Exml.generate(elem, ExmlTestIntrospectionBoolean.NODE_NAME, builder)); + final String dataTest = builder.toString(); + Assertions.assertEquals("", dataTest); + Log.warning("data generated: " + builder.toString()); + + final TestArrayBooleanNative root = Assertions.assertDoesNotThrow(() -> Exml.parseOne(dataTest, TestArrayBooleanNative.class, ExmlTestIntrospectionBooleanNative.NODE_NAME)); + Assertions.assertEquals(1, root.values.length); + Assertions.assertEquals(false, root.values[0]); + Assertions.assertEquals(false, root.values[1]); + Assertions.assertEquals(true, root.values[2]); + Assertions.assertEquals(false, root.values[3]); + Assertions.assertEquals(true, root.values[4]); + } + + + +} + diff --git a/test/src/test/atriasoft/exml/ExmlTestIntrospectionGenerate.java b/test/src/test/atriasoft/exml/ExmlTestIntrospectionGenerate.java index 21d18cf..e8efb75 100644 --- a/test/src/test/atriasoft/exml/ExmlTestIntrospectionGenerate.java +++ b/test/src/test/atriasoft/exml/ExmlTestIntrospectionGenerate.java @@ -17,6 +17,7 @@ import test.atriasoft.exml.introspection.ClassPublicMethodOnly; import test.atriasoft.exml.introspection.ClassPublicMethodeNode; public class ExmlTestIntrospectionGenerate { + private static final String NODE_NAME = "elem"; @BeforeAll public static void beforeClass() { Log.verbose("----------------------------------------------------------------");