diff --git a/test/src/test/atriasoft/exml/ExmlTestIntrospectionObject.java b/test/src/test/atriasoft/exml/ExmlTestIntrospectionObject.java
new file mode 100644
index 0000000..b01a181
--- /dev/null
+++ b/test/src/test/atriasoft/exml/ExmlTestIntrospectionObject.java
@@ -0,0 +1,400 @@
+/** @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.XmlAttribute;
+import org.atriasoft.exml.annotation.XmlList;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+
+public class ExmlTestIntrospectionObject {
+ static final String NODE_NAME = "elem";
+ @BeforeAll
+ public static void beforeClass() {
+ Log.warning("================================================================");
+ }
+
+ public class SimpleObject {
+ @XmlAttribute
+ public int value1;
+ public float value2;
+ }
+
+ public class TestNodeObject {
+ public SimpleObject valueA;
+ public SimpleObject valueB;
+ }
+ @Test
+ public void testModelNodeObject() {
+ TestNodeObject elem = new TestNodeObject();
+ elem.valueA = new SimpleObject();
+ elem.valueA.value1 = 55;
+ elem.valueA.value2 = 12568.0f;
+ elem.valueB = new SimpleObject();
+ elem.valueB.value1 = -55;
+ elem.valueB.value2 = -12568.0f;
+
+ StringBuilder builder = new StringBuilder();
+ Assertions.assertDoesNotThrow(() -> Exml.generate(elem, ExmlTestIntrospectionObject.NODE_NAME, builder));
+ String dataTest = builder.toString();
+ Log.warning("data generated: " + builder.toString());
+ Assertions.assertEquals("\n"
+ + " \n"
+ + " 12568.0\n"
+ + " \n"
+ + " \n"
+ + " -12568.0\n"
+ + " \n"
+ + "", dataTest);
+
+ final TestNodeObject root = Assertions.assertDoesNotThrow(() -> Exml.parseOne(dataTest, TestNodeObject.class, ExmlTestIntrospectionObject.NODE_NAME));
+ Assertions.assertEquals(55, root.valueA.value1);
+ Assertions.assertEquals(12568.0f, root.valueA.value2);
+ Assertions.assertEquals(-55, root.valueB.value1);
+ Assertions.assertEquals(-12568.0f, root.valueB.value2);
+ }
+
+ public class TestArrayNodeObject {
+ public SimpleObject[] values;
+ }
+ @Test
+ public void testModelArrayNodeObject() {
+ TestArrayNodeObject elem = new TestArrayNodeObject();
+ elem.values = new SimpleObject[] {new SimpleObject(), new SimpleObject(), new SimpleObject()};
+ elem.values[0].value1 = 55;
+ elem.values[0].value2 = 12568.0f;
+ elem.values[1].value1 = 77;
+ elem.values[1].value2 = 15.0f;
+ elem.values[2].value1 = 152654;
+ elem.values[2].value2 = -75.0f;
+
+ StringBuilder builder = new StringBuilder();
+ Assertions.assertDoesNotThrow(() -> Exml.generate(elem, ExmlTestIntrospectionObject.NODE_NAME, builder));
+ String dataTest = builder.toString();
+ Log.warning("data generated: " + builder.toString());
+ Assertions.assertEquals("\n"
+ + " \n"
+ + " 12568.0\n"
+ + " \n"
+ + " \n"
+ + " 15.0\n"
+ + " \n"
+ + " \n"
+ + " -75.0\n"
+ + " \n"
+ + "", dataTest);
+
+ final TestArrayNodeObject root = Assertions.assertDoesNotThrow(() -> Exml.parseOne(dataTest, TestArrayNodeObject.class, ExmlTestIntrospectionObject.NODE_NAME));
+ Assertions.assertEquals(3, root.values.length);
+ Assertions.assertEquals(55, root.values[0].value1);
+ Assertions.assertEquals(12568.0f, root.values[0].value2);
+ Assertions.assertEquals(77, root.values[1].value1);
+ Assertions.assertEquals(15.0f, root.values[1].value2);
+ Assertions.assertEquals(152654, root.values[2].value1);
+ Assertions.assertEquals(-75.0f, root.values[2].value2);
+ }
+
+ public class TestListNodeObject {
+ public List values;
+ }
+ @Test
+ public void testModelListNodeObject() {
+ TestListNodeObject elem = new TestListNodeObject();
+ elem.values = List.of(new SimpleObject(), new SimpleObject(), new SimpleObject());
+ elem.values.get(0).value1 = 55;
+ elem.values.get(0).value2 = 12568.0f;
+ elem.values.get(1).value1 = 77;
+ elem.values.get(1).value2 = 15.0f;
+ elem.values.get(2).value1 = 152654;
+ elem.values.get(2).value2 = -75.0f;
+
+ StringBuilder builder = new StringBuilder();
+ Assertions.assertDoesNotThrow(() -> Exml.generate(elem, ExmlTestIntrospectionObject.NODE_NAME, builder));
+ String dataTest = builder.toString();
+ Log.warning("data generated: " + builder.toString());
+ Assertions.assertEquals("\n"
+ + " \n"
+ + " 12568.0\n"
+ + " \n"
+ + " \n"
+ + " 15.0\n"
+ + " \n"
+ + " \n"
+ + " -75.0\n"
+ + " \n"
+ + "", dataTest);
+
+ final TestListNodeObject root = Assertions.assertDoesNotThrow(() -> Exml.parseOne(dataTest, TestListNodeObject.class, ExmlTestIntrospectionObject.NODE_NAME));
+ Assertions.assertEquals(3, root.values.size());
+ Assertions.assertEquals(55, root.values.get(0).value1);
+ Assertions.assertEquals(12568.0f, root.values.get(0).value2);
+ Assertions.assertEquals(77, root.values.get(1).value1);
+ Assertions.assertEquals(15.0f, root.values.get(1).value2);
+ Assertions.assertEquals(152654, root.values.get(2).value1);
+ Assertions.assertEquals(-75.0f, root.values.get(2).value2);
+ }
+
+
+ public class TestNodeObjectFunc {
+ private SimpleObject valueA;
+ private SimpleObject valueB;
+ public SimpleObject getValueA() {
+ return this.valueA;
+ }
+ public void setValueA(final SimpleObject valueA) {
+ this.valueA = valueA;
+ }
+ public SimpleObject getValueB() {
+ return this.valueB;
+ }
+ public void setValueB(final SimpleObject valueB) {
+ this.valueB = valueB;
+ }
+ }
+
+ @Test
+ public void testModelNodeObjectFunc() {
+ TestNodeObjectFunc elem = new TestNodeObjectFunc();
+ elem.setValueA(new SimpleObject());
+ elem.getValueA().value1 = 4564;
+ elem.getValueA().value2 = 152.0f;
+ elem.setValueB(new SimpleObject());
+ elem.getValueB().value1 = 454564;
+ elem.getValueB().value2 = 85422.0f;
+
+ StringBuilder builder = new StringBuilder();
+ Assertions.assertDoesNotThrow(() -> Exml.generate(elem, ExmlTestIntrospectionObject.NODE_NAME, builder));
+ String dataTest = builder.toString();
+ Log.warning("data generated: " + builder.toString());
+ Assertions.assertEquals("\n"
+ + " \n"
+ + " 152.0\n"
+ + " \n"
+ + " \n"
+ + " 85422.0\n"
+ + " \n"
+ + "", dataTest);
+
+ final TestNodeObjectFunc root = Assertions.assertDoesNotThrow(() -> Exml.parseOne(dataTest, TestNodeObjectFunc.class, ExmlTestIntrospectionObject.NODE_NAME));
+ Assertions.assertEquals(4564, root.getValueA().value1);
+ Assertions.assertEquals(152.0f, root.getValueA().value2);
+ Assertions.assertEquals(454564, root.getValueB().value1);
+ Assertions.assertEquals(85422.0f, root.getValueB().value2);
+ }
+
+ public class TestArrayNodeObjectFunc {
+ private SimpleObject[] values;
+
+ public SimpleObject[] getValues() {
+ return this.values;
+ }
+
+ public void setValues(final SimpleObject[] values) {
+ this.values = values;
+ }
+
+ }
+ @Test
+ public void testModelArrayNodeObjectFunc() {
+ TestArrayNodeObjectFunc elem = new TestArrayNodeObjectFunc();
+ elem.setValues(new SimpleObject[] {new SimpleObject(), new SimpleObject(), new SimpleObject()});
+ elem.getValues()[0].value1 = 55;
+ elem.getValues()[0].value2 = 12568.0f;
+ elem.getValues()[1].value1 = 77;
+ elem.getValues()[1].value2 = 15.0f;
+ elem.getValues()[2].value1 = 152654;
+ elem.getValues()[2].value2 = -75.0f;
+
+ StringBuilder builder = new StringBuilder();
+ Assertions.assertDoesNotThrow(() -> Exml.generate(elem, ExmlTestIntrospectionObject.NODE_NAME, builder));
+ String dataTest = builder.toString();
+ Log.warning("data generated: " + builder.toString());
+ Assertions.assertEquals("\n"
+ + " \n"
+ + " 12568.0\n"
+ + " \n"
+ + " \n"
+ + " 15.0\n"
+ + " \n"
+ + " \n"
+ + " -75.0\n"
+ + " \n"
+ + "", dataTest);
+
+ final TestArrayNodeObjectFunc root = Assertions.assertDoesNotThrow(() -> Exml.parseOne(dataTest, TestArrayNodeObjectFunc.class, ExmlTestIntrospectionObject.NODE_NAME));
+ Assertions.assertEquals(3, root.getValues().length);
+ Assertions.assertEquals(55, root.getValues()[0].value1);
+ Assertions.assertEquals(12568.0f, root.getValues()[0].value2);
+ Assertions.assertEquals(77, root.getValues()[1].value1);
+ Assertions.assertEquals(15.0f, root.getValues()[1].value2);
+ Assertions.assertEquals(152654, root.getValues()[2].value1);
+ Assertions.assertEquals(-75.0f, root.getValues()[2].value2);
+ }
+
+ // Note this is set in static to test an other part of code...
+ public static class TestListNodeObjectFunc {
+ private List values;
+
+ public List getValues() {
+ return this.values;
+ }
+
+ public void setValues(final List values) {
+ this.values = values;
+ }
+ }
+ @Test
+ public void testModelListNodeObjectFunc() {
+ TestListNodeObjectFunc elem = new TestListNodeObjectFunc();
+ elem.values = List.of(new SimpleObject(), new SimpleObject(), new SimpleObject());
+ elem.getValues().get(0).value1 = 55;
+ elem.getValues().get(0).value2 = 12568.0f;
+ elem.getValues().get(1).value1 = 77;
+ elem.getValues().get(1).value2 = 15.0f;
+ elem.getValues().get(2).value1 = 152654;
+ elem.getValues().get(2).value2 = -75.0f;
+
+ StringBuilder builder = new StringBuilder();
+ Assertions.assertDoesNotThrow(() -> Exml.generate(elem, ExmlTestIntrospectionObject.NODE_NAME, builder));
+ String dataTest = builder.toString();
+ Log.warning("data generated: " + builder.toString());
+ Assertions.assertEquals("\n"
+ + " \n"
+ + " 12568.0\n"
+ + " \n"
+ + " \n"
+ + " 15.0\n"
+ + " \n"
+ + " \n"
+ + " -75.0\n"
+ + " \n"
+ + "", dataTest);
+
+ final TestListNodeObjectFunc root = Assertions.assertDoesNotThrow(() -> Exml.parseOne(dataTest, TestListNodeObjectFunc.class, ExmlTestIntrospectionObject.NODE_NAME));
+ Assertions.assertEquals(3, root.getValues().size());
+ Assertions.assertEquals(55, root.getValues().get(0).value1);
+ Assertions.assertEquals(12568.0f, root.getValues().get(0).value2);
+ Assertions.assertEquals(77, root.getValues().get(1).value1);
+ Assertions.assertEquals(15.0f, root.getValues().get(1).value2);
+ Assertions.assertEquals(152654, root.getValues().get(2).value1);
+ Assertions.assertEquals(-75.0f, root.getValues().get(2).value2);
+ }
+
+
+
+
+
+ public class TestArrayNodeStructuredObjectFunc {
+ private SimpleObject[] values;
+
+ @XmlList(value="elem")
+ public SimpleObject[] getValues() {
+ return this.values;
+ }
+
+ public void setValues(final SimpleObject[] values) {
+ this.values = values;
+ }
+
+ }
+ @Test
+ public void testModelArrayNodeStructuredObjectFunc() {
+ TestArrayNodeStructuredObjectFunc elem = new TestArrayNodeStructuredObjectFunc();
+ elem.setValues(new SimpleObject[] {new SimpleObject(), new SimpleObject(), new SimpleObject()});
+ elem.getValues()[0].value1 = 55;
+ elem.getValues()[0].value2 = 12568.0f;
+ elem.getValues()[1].value1 = 77;
+ elem.getValues()[1].value2 = 15.0f;
+ elem.getValues()[2].value1 = 152654;
+ elem.getValues()[2].value2 = -75.0f;
+
+ StringBuilder builder = new StringBuilder();
+ Assertions.assertDoesNotThrow(() -> Exml.generate(elem, ExmlTestIntrospectionObject.NODE_NAME, builder));
+ String dataTest = builder.toString();
+ Log.warning("data generated: " + builder.toString());
+ Assertions.assertEquals("\n"
+ + " \n"
+ + " \n"
+ + " 12568.0\n"
+ + " \n"
+ + " \n"
+ + " 15.0\n"
+ + " \n"
+ + " \n"
+ + " -75.0\n"
+ + " \n"
+ + " \n"
+ + "", dataTest);
+
+ final TestArrayNodeStructuredObjectFunc root = Assertions.assertDoesNotThrow(() -> Exml.parseOne(dataTest, TestArrayNodeStructuredObjectFunc.class, ExmlTestIntrospectionObject.NODE_NAME));
+ Assertions.assertEquals(3, root.getValues().length);
+ Assertions.assertEquals(55, root.getValues()[0].value1);
+ Assertions.assertEquals(12568.0f, root.getValues()[0].value2);
+ Assertions.assertEquals(77, root.getValues()[1].value1);
+ Assertions.assertEquals(15.0f, root.getValues()[1].value2);
+ Assertions.assertEquals(152654, root.getValues()[2].value1);
+ Assertions.assertEquals(-75.0f, root.getValues()[2].value2);
+ }
+
+ // Note this is set in static to test an other part of code...
+ public static class TestListNodeStructuredObjectFunc {
+ private List values;
+
+ @XmlList(value="elem")
+ public List getValues() {
+ return this.values;
+ }
+
+ public void setValues(final List values) {
+ this.values = values;
+ }
+ }
+ @Test
+ public void testModelListNodeStructuredObjectFunc() {
+ TestListNodeStructuredObjectFunc elem = new TestListNodeStructuredObjectFunc();
+ elem.values = List.of(new SimpleObject(), new SimpleObject(), new SimpleObject());
+ elem.getValues().get(0).value1 = 55;
+ elem.getValues().get(0).value2 = 12568.0f;
+ elem.getValues().get(1).value1 = 77;
+ elem.getValues().get(1).value2 = 15.0f;
+ elem.getValues().get(2).value1 = 152654;
+ elem.getValues().get(2).value2 = -75.0f;
+
+ StringBuilder builder = new StringBuilder();
+ Assertions.assertDoesNotThrow(() -> Exml.generate(elem, ExmlTestIntrospectionObject.NODE_NAME, builder));
+ String dataTest = builder.toString();
+ Log.warning("data generated: " + builder.toString());
+ Assertions.assertEquals("\n"
+ + " \n"
+ + " \n"
+ + " 12568.0\n"
+ + " \n"
+ + " \n"
+ + " 15.0\n"
+ + " \n"
+ + " \n"
+ + " -75.0\n"
+ + " \n"
+ + " \n"
+ + "", dataTest);
+
+ final TestListNodeStructuredObjectFunc root = Assertions.assertDoesNotThrow(() -> Exml.parseOne(dataTest, TestListNodeStructuredObjectFunc.class, ExmlTestIntrospectionObject.NODE_NAME));
+ Assertions.assertEquals(3, root.getValues().size());
+ Assertions.assertEquals(55, root.getValues().get(0).value1);
+ Assertions.assertEquals(12568.0f, root.getValues().get(0).value2);
+ Assertions.assertEquals(77, root.getValues().get(1).value1);
+ Assertions.assertEquals(15.0f, root.getValues().get(1).value2);
+ Assertions.assertEquals(152654, root.getValues().get(2).value1);
+ Assertions.assertEquals(-75.0f, root.getValues().get(2).value2);
+ }
+
+}
+