[DEV] work on introspection generation

This commit is contained in:
Edouard DUPIN 2021-07-02 10:40:27 +02:00
parent e68802010b
commit 7ef59f2f7e
8 changed files with 516 additions and 310 deletions

View File

@ -7,7 +7,7 @@
</attributes> </attributes>
</classpathentry> </classpathentry>
<classpathentry kind="src" path="src"/> <classpathentry kind="src" path="src"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-14"> <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER">
<attributes> <attributes>
<attribute name="module" value="true"/> <attribute name="module" value="true"/>
</attributes> </attributes>

View File

@ -186,10 +186,11 @@ public class IntrospectionData {
public Class<?> getSubClassType() { public Class<?> getSubClassType() {
return this.subClassType; return this.subClassType;
} }
public IntrospectionData(final Class<?> classType) throws Exception { public IntrospectionData(final Class<?> classType) throws ExmlBuilderException {
this(classType, null); this(classType, null);
} }
public IntrospectionData(final Class<?> classType, final Class<?> subClassType) throws Exception { public IntrospectionData(final Class<?> classType, final Class<?> subClassType) throws ExmlBuilderException {
try {
this.classType = classType; this.classType = classType;
this.subClassType = subClassType; this.subClassType = subClassType;
final Boolean isDefaultManaged = getIsDefaultManaged(classType, IntrospectionData.DEFAULT_MANAGED); final Boolean isDefaultManaged = getIsDefaultManaged(classType, IntrospectionData.DEFAULT_MANAGED);
@ -204,6 +205,14 @@ public class IntrospectionData {
final Field[] fields = this.classType.getFields(); final Field[] fields = this.classType.getFields();
Log.verbose(" Fields: (" + fields.length + ")"); Log.verbose(" Fields: (" + fields.length + ")");
for (final Field elem : fields) { 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 isManaged = getIsManaged(elem, isDefaultManaged);
final Boolean isOptionnal = getIsOptional(elem, isDefaultOptional); final Boolean isOptionnal = getIsOptional(elem, isDefaultOptional);
final String[] names = getNames(elem, Tools.decapitalizeFirst(elem.getName())); final String[] names = getNames(elem, Tools.decapitalizeFirst(elem.getName()));
@ -221,6 +230,10 @@ public class IntrospectionData {
if (o.getName().contentEquals("getClass")) { if (o.getName().contentEquals("getClass")) {
return false; return false;
} }
// we does not manage private function
if (!Modifier.isPublic(o.getModifiers())) {
return false;
}
if (Modifier.isStatic(o.getModifiers())) { if (Modifier.isStatic(o.getModifiers())) {
if (o.getName().contentEquals("valueOf") && o.getParameterCount() == 1 && o.getParameters()[0].getType() == String.class) { if (o.getName().contentEquals("valueOf") && o.getParameterCount() == 1 && o.getParameters()[0].getType() == String.class) {
return true; return true;
@ -427,7 +440,10 @@ public class IntrospectionData {
} }
} }
} }
} catch (Exception ex) {
ex.printStackTrace();
throw new ExmlBuilderException("Error in creating introspection data ... " + ex.getMessage());
}
} }
Object createObject(final Map<String, Object> properties, final Map<String, List<Object>> nodes) throws ExmlBuilderException { Object createObject(final Map<String, Object> properties, final Map<String, List<Object>> nodes) throws ExmlBuilderException {

View File

@ -1,6 +1,7 @@
package org.atriasoft.exml.builder; package org.atriasoft.exml.builder;
import org.atriasoft.exml.exception.ExmlBuilderException; import org.atriasoft.exml.exception.ExmlBuilderException;
import org.atriasoft.exml.parser.Tools;
public abstract class IntrospectionProperty { public abstract class IntrospectionProperty {
protected final Boolean caseSensitive; protected final Boolean caseSensitive;
@ -41,7 +42,67 @@ public abstract class IntrospectionProperty {
return this.subType; 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() { public boolean isCaseSensitive() {
return this.caseSensitive; return this.caseSensitive;

View File

@ -43,66 +43,10 @@ public class IntrospectionPropertyField extends IntrospectionProperty {
public boolean canSetValue() { public boolean canSetValue() {
return true; return true;
} }
@Override @Override
public String getValue(final Object object) throws ExmlBuilderException { public Object getValue(final Object object) throws ExmlBuilderException {
try { try {
Object value = this.fieldDescription.get(object); return 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();
} catch (IllegalArgumentException | IllegalAccessException e) { } catch (IllegalArgumentException | IllegalAccessException e) {
// TODO Auto-generated catch block // TODO Auto-generated catch block
e.printStackTrace(); e.printStackTrace();

View File

@ -79,12 +79,16 @@ public class IntrospectionPropertyMethod extends IntrospectionProperty {
} }
@Override @Override
public String getValue(final Object object) throws ExmlBuilderException { public Object getValue(final Object object) throws ExmlBuilderException {
if (this.getter == null) { if (this.getter == null) {
throw new ExmlBuilderException("no getter availlable"); throw new ExmlBuilderException("no getter availlable");
} }
// TODO Auto-generated method stub try {
return null; return this.getter.invoke(object);
} catch (InvocationTargetException | IllegalAccessException | IllegalArgumentException e) {
e.printStackTrace();
throw new ExmlBuilderException("Can not set value ... " + e.getMessage());
}
} }
@Override @Override

View File

@ -6,6 +6,8 @@ import java.util.Map;
import org.atriasoft.exml.builder.IntrospectionData; import org.atriasoft.exml.builder.IntrospectionData;
import org.atriasoft.exml.builder.IntrospectionProperty; import org.atriasoft.exml.builder.IntrospectionProperty;
import org.atriasoft.exml.exception.ExmlBuilderException;
import org.atriasoft.exml.parser.Tools;
public class GeneratorIntrospection implements Generator { public class GeneratorIntrospection implements Generator {
// Keep in cach all the object alredy parsed ==> optimize CPU // 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)); 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); IntrospectionData out = this.elements.get(classType);
if (out != null) { if (out != null) {
return out; return out;
@ -30,40 +32,54 @@ public class GeneratorIntrospection implements Generator {
return out; 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<IntrospectionProperty> elements = introspection.getProperties(); List<IntrospectionProperty> elements = introspection.getProperties();
for (IntrospectionProperty elem : elements) { for (IntrospectionProperty elem : elements) {
if (!elem.canGetValue()) { if (!elem.canGetValue()) {
continue; continue;
} }
String name = elem.getNames()[0]; String name = elem.getNames()[0];
String data=elem.getValue(node); String dataString=elem.getValueString(data);
tmpp.append(" "); tmpp.append(" ");
tmpp.append(name); tmpp.append(name);
tmpp.append("=\""); tmpp.append("=\"");
tmpp.append(data); tmpp.append(dataString);
tmpp.append("\""); 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<IntrospectionProperty> elements = introspection.getMethods(); List<IntrospectionProperty> elements = introspection.getMethods();
for (IntrospectionProperty elem : elements) { 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("<");
tmpp.append(nodeName); tmpp.append(nodeName);
generateProperties(node, introspection, tmpp); generateProperties(data, introspection, tmpp);
if (introspection.getMethods().size() != 0) {
tmpp.append(">\n"); tmpp.append(">\n");
generateSubNodes(node, introspection, tmpp); generateSubNodes(data, introspection, tmpp, indent + 1);
Tools.addIndent(tmpp, indent);
tmpp.append("</"); tmpp.append("</");
tmpp.append(nodeName); tmpp.append(nodeName);
tmpp.append(">\n"); 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);
} }
} }

View File

@ -149,7 +149,7 @@ public class Tools {
return false; return false;
} }
public static Boolean[] parseBooleanClassStringList(String data) { // throws NumberFormatException public static Boolean[] parseBooleanClassStringList(String data) {
data = Tools.cleanNumberList(data); data = Tools.cleanNumberList(data);
final String[] dataArray = data.split(";"); final String[] dataArray = data.split(";");
final Boolean[] out = new Boolean[dataArray.length]; final Boolean[] out = new Boolean[dataArray.length];
@ -159,8 +159,18 @@ public class Tools {
} }
return out; return out;
} }
public static String toString(Boolean[] data) {
StringBuilder out = new StringBuilder();
for (int iii=0; iii<data.length; iii++) {
if (iii != 0) {
out.append(";");
}
out.append(data[iii]);
}
return out.toString();
}
public static boolean[] parseBooleanStringList(String data) { // throws NumberFormatException public static boolean[] parseBooleanStringList(String data) {
data = Tools.cleanNumberList(data); data = Tools.cleanNumberList(data);
final String[] dataArray = data.split(";"); final String[] dataArray = data.split(";");
final boolean[] out = new boolean[dataArray.length]; final boolean[] out = new boolean[dataArray.length];
@ -170,8 +180,18 @@ public class Tools {
} }
return out; return out;
} }
public static String toString(boolean[] data) {
StringBuilder out = new StringBuilder();
for (int iii=0; iii<data.length; iii++) {
if (iii != 0) {
out.append(";");
}
out.append(data[iii]);
}
return out.toString();
}
public static Byte[] parseByteClassStringList(String data) { // throws NumberFormatException public static Byte[] parseByteClassStringList(String data) {
data = Tools.cleanNumberList(data); data = Tools.cleanNumberList(data);
final String[] dataArray = data.split(";"); final String[] dataArray = data.split(";");
final Byte[] out = new Byte[dataArray.length]; final Byte[] out = new Byte[dataArray.length];
@ -182,7 +202,18 @@ public class Tools {
return out; return out;
} }
public static byte[] parseByteStringList(String data) { // throws NumberFormatException public static String toString(Byte[] data) {
StringBuilder out = new StringBuilder();
for (int iii=0; iii<data.length; iii++) {
if (iii != 0) {
out.append(";");
}
out.append(data[iii]);
}
return out.toString();
}
public static byte[] parseByteStringList(String data) {
data = Tools.cleanNumberList(data); data = Tools.cleanNumberList(data);
final String[] dataArray = data.split(";"); final String[] dataArray = data.split(";");
final byte[] out = new byte[dataArray.length]; final byte[] out = new byte[dataArray.length];
@ -192,8 +223,18 @@ public class Tools {
} }
return out; return out;
} }
public static String toString(byte[] data) {
StringBuilder out = new StringBuilder();
for (int iii=0; iii<data.length; iii++) {
if (iii != 0) {
out.append(";");
}
out.append(data[iii]);
}
return out.toString();
}
public static Integer[] parseIntegerClassStringList(String data) { // throws NumberFormatException public static Integer[] parseIntegerClassStringList(String data) {
data = Tools.cleanNumberList(data); data = Tools.cleanNumberList(data);
final String[] dataArray = data.split(";"); final String[] dataArray = data.split(";");
final Integer[] out = new Integer[dataArray.length]; final Integer[] out = new Integer[dataArray.length];
@ -203,8 +244,18 @@ public class Tools {
} }
return out; return out;
} }
public static String toString(Integer[] data) {
StringBuilder out = new StringBuilder();
for (int iii=0; iii<data.length; iii++) {
if (iii != 0) {
out.append(";");
}
out.append(data[iii]);
}
return out.toString();
}
public static int[] parseIntegerStringList(String data) { // throws NumberFormatException public static int[] parseIntegerStringList(String data) {
data = Tools.cleanNumberList(data); data = Tools.cleanNumberList(data);
final String[] dataArray = data.split(";"); final String[] dataArray = data.split(";");
final int[] out = new int[dataArray.length]; final int[] out = new int[dataArray.length];
@ -214,8 +265,18 @@ public class Tools {
} }
return out; return out;
} }
public static String toString(int[] data) {
StringBuilder out = new StringBuilder();
for (int iii=0; iii<data.length; iii++) {
if (iii != 0) {
out.append(";");
}
out.append(data[iii]);
}
return out.toString();
}
public static Long[] parseLongClassStringList(String data) { // throws NumberFormatException public static Long[] parseLongClassStringList(String data) {
data = Tools.cleanNumberList(data); data = Tools.cleanNumberList(data);
final String[] dataArray = data.split(";"); final String[] dataArray = data.split(";");
final Long[] out = new Long[dataArray.length]; final Long[] out = new Long[dataArray.length];
@ -225,8 +286,18 @@ public class Tools {
} }
return out; return out;
} }
public static String toString(Long[] data) {
StringBuilder out = new StringBuilder();
for (int iii=0; iii<data.length; iii++) {
if (iii != 0) {
out.append(";");
}
out.append(data[iii]);
}
return out.toString();
}
public static long[] parseLongStringList(String data) { // throws NumberFormatException public static long[] parseLongStringList(String data) {
data = Tools.cleanNumberList(data); data = Tools.cleanNumberList(data);
final String[] dataArray = data.split(";"); final String[] dataArray = data.split(";");
final long[] out = new long[dataArray.length]; final long[] out = new long[dataArray.length];
@ -236,8 +307,18 @@ public class Tools {
} }
return out; return out;
} }
public static String toString(long[] data) {
StringBuilder out = new StringBuilder();
for (int iii=0; iii<data.length; iii++) {
if (iii != 0) {
out.append(";");
}
out.append(data[iii]);
}
return out.toString();
}
public static Short[] parseShortClassStringList(String data) { // throws NumberFormatException public static Short[] parseShortClassStringList(String data) {
data = Tools.cleanNumberList(data); data = Tools.cleanNumberList(data);
final String[] dataArray = data.split(";"); final String[] dataArray = data.split(";");
final Short[] out = new Short[dataArray.length]; final Short[] out = new Short[dataArray.length];
@ -248,7 +329,18 @@ public class Tools {
return out; return out;
} }
public static short[] parseShortStringList(String data) { // throws NumberFormatException public static String toString(Short[] data) {
StringBuilder out = new StringBuilder();
for (int iii=0; iii<data.length; iii++) {
if (iii != 0) {
out.append(";");
}
out.append(data[iii]);
}
return out.toString();
}
public static short[] parseShortStringList(String data) {
data = Tools.cleanNumberList(data); data = Tools.cleanNumberList(data);
final String[] dataArray = data.split(";"); final String[] dataArray = data.split(";");
final short[] out = new short[dataArray.length]; final short[] out = new short[dataArray.length];
@ -258,6 +350,16 @@ public class Tools {
} }
return out; return out;
} }
public static String toString(short[] data) {
StringBuilder out = new StringBuilder();
for (int iii=0; iii<data.length; iii++) {
if (iii != 0) {
out.append(";");
}
out.append(data[iii]);
}
return out.toString();
}
// transform the Text with : // transform the Text with :
// "&lt;" == "<" // "&lt;" == "<"

View File

@ -13,6 +13,8 @@ import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import test.atriasoft.exml.introspection.ClassPublicMemberOnly; import test.atriasoft.exml.introspection.ClassPublicMemberOnly;
import test.atriasoft.exml.introspection.ClassPublicMethodOnly;
import test.atriasoft.exml.introspection.ClassPublicMethodeNode;
public class ExmlTestIntrospectionGenerate { public class ExmlTestIntrospectionGenerate {
@BeforeAll @BeforeAll
@ -50,5 +52,66 @@ public class ExmlTestIntrospectionGenerate {
Log.warning("data generated: " + builder.toString()); Log.warning("data generated: " + builder.toString());
} }
@Test
public void test2() throws ExmlParserErrorMulti, ExmlBuilderException {
ClassPublicMethodOnly elem = new ClassPublicMethodOnly();
elem.setMemberArrayBoolean ( new boolean[] {false, true});
elem.setMemberArrayBooleanClass ( new Boolean[] {false, true, true});
elem.setMemberArrayByte ( new byte[] {21,21,58});
elem.setMemberArrayByteClass ( new Byte[] {54,21,65,32});
elem.setMemberArrayInteger ( new int[] { 1521,2151,2156,216354});
elem.setMemberArrayIntegerClass ( new Integer[] {5564,6546321,654564,231321,54654});
elem.setMemberArrayLong ( new long[] {6546544L,654654651L,5646546541L,5465465163L} );
elem.setMemberArrayLongClass ( new Long[] {561651L, 6541321L, 651351L});
elem.setMemberArrayShort ( new short[] {4564, -54,-564});
elem.setMemberArrayShortClass ( new Short[] {-54, 5646, -8465, 852});
elem.setMemberBoolean ( false);
elem.setMemberBooleanClass ( true);
elem.setMemberByte ( (byte)12);
elem.setMemberByteClass ( (byte)54);
elem.setMemberInteger ( 6543524);
elem.setMemberIntegerClass ( 545666);
elem.setMemberLong ( 400000055L);
elem.setMemberLongClass ( 54654546L);
elem.setMemberShort ( (short)31252);
elem.setMemberShortClass ((short)-25212);
elem.setMemberStringClass ("lkjhlkjlkjlkj");
StringBuilder builder = new StringBuilder();
Exml.generate(elem, "elem", builder);
Log.warning("data generated: " + builder.toString());
}
@Test
public void test3() throws ExmlParserErrorMulti, ExmlBuilderException {
ClassPublicMethodeNode elem = new ClassPublicMethodeNode();
elem.setMemberArrayBoolean ( new boolean[] {false, true});
elem.setMemberArrayBooleanClass ( new Boolean[] {false, true, true});
elem.setMemberArrayByte ( new byte[] {21,21,58});
elem.setMemberArrayByteClass ( new Byte[] {54,21,65,32});
elem.setMemberArrayInteger ( new int[] { 1521,2151,2156,216354});
elem.setMemberArrayIntegerClass ( new Integer[] {5564,6546321,654564,231321,54654});
elem.setMemberArrayLong ( new long[] {6546544L,654654651L,5646546541L,5465465163L} );
elem.setMemberArrayLongClass ( new Long[] {561651L, 6541321L, 651351L});
elem.setMemberArrayShort ( new short[] {4564, -54,-564});
elem.setMemberArrayShortClass ( new Short[] {-54, 5646, -8465, 852});
elem.setMemberBoolean ( false);
elem.setMemberBooleanClass ( true);
elem.setMemberByte ( (byte)12);
elem.setMemberByteClass ( (byte)54);
elem.setMemberInteger ( 6543524);
elem.setMemberIntegerClass ( 545666);
elem.setMemberLong ( 400000055L);
elem.setMemberLongClass ( 54654546L);
elem.setMemberShort ( (short)31252);
elem.setMemberShortClass ((short)-25212);
elem.setMemberStringClass ("lkjhlkjlkjlkj");
StringBuilder builder = new StringBuilder();
Exml.generate(elem, "elem", builder);
Log.warning("data generated: " + builder.toString());
}
} }