diff --git a/.classpath b/.classpath
index 79118bb..94f2fe7 100644
--- a/.classpath
+++ b/.classpath
@@ -7,7 +7,7 @@
-
+
diff --git a/src/org/atriasoft/exml/builder/IntrospectionData.java b/src/org/atriasoft/exml/builder/IntrospectionData.java
index c16e063..184174e 100644
--- a/src/org/atriasoft/exml/builder/IntrospectionData.java
+++ b/src/org/atriasoft/exml/builder/IntrospectionData.java
@@ -186,248 +186,264 @@ public class IntrospectionData {
public Class> getSubClassType() {
return this.subClassType;
}
- public IntrospectionData(final Class> classType) throws Exception {
+ public IntrospectionData(final Class> classType) throws ExmlBuilderException {
this(classType, null);
}
- public IntrospectionData(final Class> classType, final Class> subClassType) throws Exception {
- 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);
- Log.verbose("Introspect class: '" + classType.getCanonicalName() + "'");
- final Constructor>[] constructors = this.classType.getConstructors();
- Log.verbose(" Constructors: (" + constructors.length + ")");
- for (final Constructor> elem : constructors) {
- Log.verbose(" - " + elem.toGenericString());
- }
- final Field[] fields = this.classType.getFields();
- Log.verbose(" Fields: (" + fields.length + ")");
- for (final Field elem : fields) {
- final Boolean isManaged = getIsManaged(elem, isDefaultManaged);
- final Boolean isOptionnal = getIsOptional(elem, isDefaultOptional);
- final String[] names = getNames(elem, Tools.decapitalizeFirst(elem.getName()));
- final Boolean caseSensitive = getIsCaseSensitive(elem, isDefaultCaseSensitive);
- final String listName = getListName(elem, null);
- // TODO check if property does not already exist ...
- if (isManaged) {
- this.properties.add(new IntrospectionPropertyField(elem, names, listName, caseSensitive, isOptionnal));
+ public IntrospectionData(final Class> classType, final Class> subClassType) throws ExmlBuilderException {
+ 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);
+ Log.verbose("Introspect class: '" + classType.getCanonicalName() + "'");
+ final Constructor>[] constructors = this.classType.getConstructors();
+ Log.verbose(" Constructors: (" + constructors.length + ")");
+ for (final Constructor> elem : constructors) {
+ Log.verbose(" - " + elem.toGenericString());
}
- Log.verbose(" - " + elem.toGenericString());
- }
- final Method[] methodsTmp = this.classType.getMethods();
- // filter getX setX isX
- final List methods = List.of(methodsTmp).stream().filter(o -> {
- if (o.getName().contentEquals("getClass")) {
- return false;
+ final Field[] fields = this.classType.getFields();
+ Log.verbose(" Fields: (" + fields.length + ")");
+ for (final Field elem : fields) {
+ // we does not manage static field
+ if (Modifier.isStatic(elem.getModifiers())) {
+ continue;
+ }
+ // we does not manage private field
+ if (!Modifier.isPublic(elem.getModifiers())) {
+ continue;
+ }
+ final Boolean isManaged = getIsManaged(elem, isDefaultManaged);
+ final Boolean isOptionnal = getIsOptional(elem, isDefaultOptional);
+ final String[] names = getNames(elem, Tools.decapitalizeFirst(elem.getName()));
+ final Boolean caseSensitive = getIsCaseSensitive(elem, isDefaultCaseSensitive);
+ final String listName = getListName(elem, null);
+ // TODO check if property does not already exist ...
+ if (isManaged) {
+ this.properties.add(new IntrospectionPropertyField(elem, names, listName, caseSensitive, isOptionnal));
+ }
+ Log.verbose(" - " + elem.toGenericString());
}
- if (Modifier.isStatic(o.getModifiers())) {
- if (o.getName().contentEquals("valueOf") && o.getParameterCount() == 1 && o.getParameters()[0].getType() == String.class) {
- return true;
+ final Method[] methodsTmp = this.classType.getMethods();
+ // filter getX setX isX
+ final List methods = List.of(methodsTmp).stream().filter(o -> {
+ if (o.getName().contentEquals("getClass")) {
+ return false;
+ }
+ // we does not manage private function
+ if (!Modifier.isPublic(o.getModifiers())) {
+ return false;
+ }
+ if (Modifier.isStatic(o.getModifiers())) {
+ if (o.getName().contentEquals("valueOf") && o.getParameterCount() == 1 && o.getParameters()[0].getType() == String.class) {
+ return true;
+ }
+ return false;
+ }
+ if (o.getName().startsWith("get")) {
+ if (o.getParameterCount() != 0 || o.getReturnType() == void.class || o.getReturnType() == Boolean.class || o.getReturnType() == boolean.class) {
+ return false;
+ }
+ // check name format
+ if (o.getName().length() == 3) {
+ return false;
+ }
+ if (o.getName().charAt(3) >= 'A' && o.getName().charAt(3) <= 'Z') {
+ return true;
+ }
+ return false;
+ }
+ if (o.getName().startsWith("set")) {
+ if (o.getReturnType() != void.class || o.getParameterCount() != 1) {
+ return false;
+ }
+ // check name format
+ if (o.getName().length() == 3) {
+ return false;
+ }
+ if (o.getName().charAt(3) >= 'A' && o.getName().charAt(3) <= 'Z') {
+ return true;
+ }
+
+ return false;
+ }
+ if (o.getName().startsWith("is")) {
+ if (!(o.getReturnType() == Boolean.class || o.getReturnType() == boolean.class) && o.getParameterCount() != 0) {
+ return false;
+ }
+ // check name format
+ if (o.getName().length() == 2) {
+ return false;
+ }
+ if (o.getName().charAt(2) >= 'A' && o.getName().charAt(2) <= 'Z') {
+ return true;
+ }
+
+ return false;
}
return false;
+ }).collect(Collectors.toList());
+ Log.verbose(" Methods: (" + methods.size() + ")");
+ for (final Method elem : methods) {
+ Log.verbose(" - " + elem.toGenericString());
}
- if (o.getName().startsWith("get")) {
- if (o.getParameterCount() != 0 || o.getReturnType() == void.class || o.getReturnType() == Boolean.class || o.getReturnType() == boolean.class) {
- return false;
- }
- // check name format
- if (o.getName().length() == 3) {
- return false;
- }
- if (o.getName().charAt(3) >= 'A' && o.getName().charAt(3) <= 'Z') {
- return true;
- }
- return false;
- }
- if (o.getName().startsWith("set")) {
- if (o.getReturnType() != void.class || o.getParameterCount() != 1) {
- return false;
- }
- // check name format
- if (o.getName().length() == 3) {
- return false;
- }
- if (o.getName().charAt(3) >= 'A' && o.getName().charAt(3) <= 'Z') {
- return true;
- }
-
- return false;
- }
- if (o.getName().startsWith("is")) {
- if (!(o.getReturnType() == Boolean.class || o.getReturnType() == boolean.class) && o.getParameterCount() != 0) {
- return false;
- }
- // check name format
- if (o.getName().length() == 2) {
- return false;
- }
- if (o.getName().charAt(2) >= 'A' && o.getName().charAt(2) <= 'Z') {
- return true;
- }
-
- return false;
- }
- return false;
- }).collect(Collectors.toList());
- Log.verbose(" Methods: (" + methods.size() + ")");
- for (final Method elem : methods) {
- Log.verbose(" - " + elem.toGenericString());
- }
-
-
- // Separate the methods and filer as:
- // XXX GetXxx(); & XXX != boolean
- // void setXxx(XXX elem);
- // [bB]oolean isXxx();
-
- List 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) {
- this.valueof = valueOfString.get(0);
- } else {
- // some specific model:
- this.valueof = null;
- }
- // associate methods by pair.
- final List elements = new ArrayList<>();
- for (final Method method : methodsGet) {
- final String name = method.getName().substring(3);
- final OrderData tmp = new OrderData(name);
- tmp.getter = method;
- elements.add(tmp);
- }
- for (final Method method : methodsIs) {
- final String name = method.getName().substring(2);
- for (final OrderData elem : elements) {
- if (elem.name.contentEquals(name)) {
- Log.error("Can not have a setXXX and isXXX with the same name ... " + method.getName());
- throw new Exception("lmkjlkjlk");
- }
+
+ // Separate the methods and filer as:
+ // XXX GetXxx(); & XXX != boolean
+ // void setXxx(XXX elem);
+ // [bB]oolean isXxx();
+
+ 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 OrderData tmp = new OrderData(name);
- tmp.getter = method;
- elements.add(tmp);
- }
- for (final Method method : methodsSet) {
- final String name = method.getName().substring(3);
- OrderData tmp = null;
- for (final OrderData elem : elements) {
- if (elem.name.contentEquals(name)) {
- tmp = elem;
- break;
- }
+ final List valueOfString = methods.stream().filter(o -> o.getName().startsWith("valueOf")).collect(Collectors.toList());
+ if (valueOfString.size() == 1) {
+ this.valueof = valueOfString.get(0);
+ } else {
+ // some specific model:
+
+ this.valueof = null;
}
- /*
- Class> internalModelClass = null;
- Class>[] tmppp = method.getParameterTypes();
- if (tmppp.length > 0 && (List.class.isAssignableFrom(tmppp[0]))) {
- Log.warning(" * " + method.getName());
- Type[] empppe = method.getGenericParameterTypes();
- if (empppe.length > 0) {
- if (empppe[0] instanceof ParameterizedType plopppppp) {
- Type[] realType = plopppppp.getActualTypeArguments();
- if (realType.length > 0) {
- Log.warning(" -->> " + realType[0]);
- internalModelClass = Class.forName(realType[0].getTypeName());
- }
+ // associate methods by pair.
+ final List elements = new ArrayList<>();
+ for (final Method method : methodsGet) {
+ final String name = method.getName().substring(3);
+ final OrderData tmp = new OrderData(name);
+ tmp.getter = method;
+ elements.add(tmp);
+ }
+ for (final Method method : methodsIs) {
+ final String name = method.getName().substring(2);
+ for (final OrderData elem : elements) {
+ if (elem.name.contentEquals(name)) {
+ Log.error("Can not have a setXXX and isXXX with the same name ... " + method.getName());
+ throw new Exception("lmkjlkjlk");
}
}
- for (int iii=0; iii internalModelClass = null;
+ Class>[] tmppp = method.getParameterTypes();
+ if (tmppp.length > 0 && (List.class.isAssignableFrom(tmppp[0]))) {
+ Log.warning(" * " + method.getName());
+ Type[] empppe = method.getGenericParameterTypes();
+ if (empppe.length > 0) {
+ if (empppe[0] instanceof ParameterizedType plopppppp) {
+ Type[] realType = plopppppp.getActualTypeArguments();
+ if (realType.length > 0) {
+ Log.warning(" -->> " + realType[0]);
+ internalModelClass = Class.forName(realType[0].getTypeName());
+ }
+ }
+ }
+ for (int iii=0; iii properties, final Map> nodes) throws ExmlBuilderException {
diff --git a/src/org/atriasoft/exml/builder/IntrospectionProperty.java b/src/org/atriasoft/exml/builder/IntrospectionProperty.java
index d546f9e..3b0a7a6 100644
--- a/src/org/atriasoft/exml/builder/IntrospectionProperty.java
+++ b/src/org/atriasoft/exml/builder/IntrospectionProperty.java
@@ -1,6 +1,7 @@
package org.atriasoft.exml.builder;
import org.atriasoft.exml.exception.ExmlBuilderException;
+import org.atriasoft.exml.parser.Tools;
public abstract class IntrospectionProperty {
protected final Boolean caseSensitive;
@@ -40,8 +41,68 @@ public abstract class IntrospectionProperty {
public Class> getSubType() {
return this.subType;
}
-
- public abstract String getValue(Object object) throws ExmlBuilderException;
+
+ public String getValueString(final Object object) throws ExmlBuilderException {
+ Object value = getValue(object);
+ if (value == null) {
+ return null;
+ }
+ if (this.type == byte.class) {
+ return Byte.toString((byte)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);'");
+ }
+ return value.toString();
+ }
+ public abstract Object getValue(Object object) throws ExmlBuilderException;
public boolean isCaseSensitive() {
return this.caseSensitive;
diff --git a/src/org/atriasoft/exml/builder/IntrospectionPropertyField.java b/src/org/atriasoft/exml/builder/IntrospectionPropertyField.java
index dd7d3be..56d6879 100644
--- a/src/org/atriasoft/exml/builder/IntrospectionPropertyField.java
+++ b/src/org/atriasoft/exml/builder/IntrospectionPropertyField.java
@@ -43,66 +43,10 @@ public class IntrospectionPropertyField extends IntrospectionProperty {
public boolean canSetValue() {
return true;
}
-
@Override
- public String getValue(final Object object) throws ExmlBuilderException {
+ public Object getValue(final Object object) throws ExmlBuilderException {
try {
- Object value = this.fieldDescription.get(object);
-
- if (this.type == byte.class) {
- return Byte.toString((byte)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.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);'");
- }
- return value.toString();
+ return this.fieldDescription.get(object);
} catch (IllegalArgumentException | IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
diff --git a/src/org/atriasoft/exml/builder/IntrospectionPropertyMethod.java b/src/org/atriasoft/exml/builder/IntrospectionPropertyMethod.java
index b8dbb75..df10cec 100644
--- a/src/org/atriasoft/exml/builder/IntrospectionPropertyMethod.java
+++ b/src/org/atriasoft/exml/builder/IntrospectionPropertyMethod.java
@@ -79,12 +79,16 @@ public class IntrospectionPropertyMethod extends IntrospectionProperty {
}
@Override
- public String getValue(final Object object) throws ExmlBuilderException {
+ public Object getValue(final Object object) throws ExmlBuilderException {
if (this.getter == null) {
throw new ExmlBuilderException("no getter availlable");
}
- // TODO Auto-generated method stub
- return null;
+ try {
+ return this.getter.invoke(object);
+ } catch (InvocationTargetException | IllegalAccessException | IllegalArgumentException e) {
+ e.printStackTrace();
+ throw new ExmlBuilderException("Can not set value ... " + e.getMessage());
+ }
}
@Override
diff --git a/src/org/atriasoft/exml/generator/GeneratorIntrospection.java b/src/org/atriasoft/exml/generator/GeneratorIntrospection.java
index 3576cf1..730f1c4 100644
--- a/src/org/atriasoft/exml/generator/GeneratorIntrospection.java
+++ b/src/org/atriasoft/exml/generator/GeneratorIntrospection.java
@@ -6,6 +6,8 @@ import java.util.Map;
import org.atriasoft.exml.builder.IntrospectionData;
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
@@ -20,7 +22,7 @@ public class GeneratorIntrospection implements Generator {
this.elements.put(classType, new IntrospectionData(classType, null));
}
- IntrospectionData findOrCreate(final Class> classType) throws Exception {
+ IntrospectionData findOrCreate(final Class> classType) throws ExmlBuilderException {
IntrospectionData out = this.elements.get(classType);
if (out != null) {
return out;
@@ -30,40 +32,54 @@ public class GeneratorIntrospection implements Generator {
return out;
}
- public void generateProperties(final Object node, final IntrospectionData introspection, final StringBuilder tmpp) throws Exception {
+ public void generateProperties(final Object data, final IntrospectionData introspection, final StringBuilder tmpp) throws ExmlBuilderException {
List elements = introspection.getProperties();
for (IntrospectionProperty elem : elements) {
if (!elem.canGetValue()) {
continue;
}
String name = elem.getNames()[0];
- String data=elem.getValue(node);
+ String dataString=elem.getValueString(data);
tmpp.append(" ");
tmpp.append(name);
tmpp.append("=\"");
- tmpp.append(data);
+ tmpp.append(dataString);
tmpp.append("\"");
}
}
- public void generateSubNodes(final Object node, final IntrospectionData introspection, final StringBuilder tmpp) {
+ public void generateSubNodes(final Object data, final IntrospectionData introspection, final StringBuilder tmpp, 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) {
+ generateNode(dataObj, name, tmpp, indent);
+ }
}
}
- public void generateNode(final Object node, final String nodeName, final StringBuilder tmpp) throws Exception {
- IntrospectionData introspection = findOrCreate(node.getClass());
+ 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(node, introspection, tmpp);
- tmpp.append(">\n");
- generateSubNodes(node, introspection, tmpp);
- tmpp.append("");
- tmpp.append(nodeName);
- tmpp.append(">\n");
-
+ generateProperties(data, introspection, tmpp);
+ if (introspection.getMethods().size() != 0) {
+ tmpp.append(">\n");
+ generateSubNodes(data, introspection, tmpp, indent + 1);
+ Tools.addIndent(tmpp, indent);
+ tmpp.append("");
+ tmpp.append(nodeName);
+ tmpp.append(">\n");
+ } else {
+ tmpp.append("/>\n");
+ }
}
- public void generate(final Object root, final StringBuilder tmpp) throws Exception {
- generateNode(root, this.rootNodeName, tmpp);
+ 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 1f7081e..c92c058 100644
--- a/src/org/atriasoft/exml/parser/Tools.java
+++ b/src/org/atriasoft/exml/parser/Tools.java
@@ -149,7 +149,7 @@ public class Tools {
return false;
}
- public static Boolean[] parseBooleanClassStringList(String data) { // throws NumberFormatException
+ public static Boolean[] parseBooleanClassStringList(String data) {
data = Tools.cleanNumberList(data);
final String[] dataArray = data.split(";");
final Boolean[] out = new Boolean[dataArray.length];
@@ -159,8 +159,18 @@ public class Tools {
}
return out;
}
+ public static String toString(Boolean[] data) {
+ StringBuilder out = new StringBuilder();
+ for (int iii=0; iii