From a2d37bb2415cd3d2c2f5488ea1ce7211d0bd8807 Mon Sep 17 00:00:00 2001 From: Edouard DUPIN Date: Thu, 15 Jul 2021 01:38:22 +0200 Subject: [PATCH] [DEV] lib is worling --- .../builder/IntrospectionModelComplex.java | 119 +++++++------ .../exml/builder/IntrospectionProperty.java | 39 ++--- .../builder/IntrospectionPropertyField.java | 2 - .../IntrospectionPropertyMethodGetter.java | 4 - .../IntrospectionPropertyMethodSetter.java | 4 - ...lTestIntrospectionDecoratorAttribute.java} | 164 +++++++++++++++++- .../exml/ExmlTestIntrospectionRecord.java | 23 +++ 7 files changed, 269 insertions(+), 86 deletions(-) rename test/src/test/atriasoft/exml/{ExmlTestIntrospectionDecorator.java => ExmlTestIntrospectionDecoratorAttribute.java} (65%) diff --git a/src/org/atriasoft/exml/builder/IntrospectionModelComplex.java b/src/org/atriasoft/exml/builder/IntrospectionModelComplex.java index 7a54bdb..e1934ad 100644 --- a/src/org/atriasoft/exml/builder/IntrospectionModelComplex.java +++ b/src/org/atriasoft/exml/builder/IntrospectionModelComplex.java @@ -42,7 +42,7 @@ public class IntrospectionModelComplex extends IntrospectionModel { @Override public List getNodes() { List out = new ArrayList<>(); - for (IntrospectionProperty elem : elements) { + for (IntrospectionProperty elem : this.elements) { if (!elem.isAttribute()) { out.add(elem); } @@ -52,15 +52,15 @@ public class IntrospectionModelComplex extends IntrospectionModel { @Override public List getAttributes() { List out = new ArrayList<>(); - for (IntrospectionProperty elem : elements) { + for (IntrospectionProperty elem : this.elements) { if (elem.isAttribute()) { out.add(elem); } } return out; } - protected IntrospectionProperty findElement(String beanName) { - for (IntrospectionProperty elem : elements) { + protected IntrospectionProperty findElement(final String beanName) { + for (IntrospectionProperty elem : this.elements) { if (elem.getBeanName().equals(beanName)) { return elem; } @@ -104,7 +104,9 @@ public class IntrospectionModelComplex extends IntrospectionModel { if (classType.isPrimitive()) { Log.critical("Detect primitive ==> impossible case !!! "); } - + // ------------------------------------------------------------------------ + // -- Parse constructor + // ------------------------------------------------------------------------ Log.verbose("Introspect class: '" + classType.getCanonicalName() + "'"); final Constructor[] constructors = this.classType.getConstructors(); Log.verbose(" Constructors: (" + constructors.length + ")"); @@ -114,7 +116,14 @@ public class IntrospectionModelComplex extends IntrospectionModel { if (!Modifier.isPublic(elem.getModifiers())) { continue; } - if (this.isSubClass) { + if (elem.getParameterCount() == 0) { + emptyConstructorTmp = elem; + Log.verbose(" >>> " + elem.toGenericString()); + } else { + int offsetSubClass = 0; + if (this.isSubClass) { + offsetSubClass = 1; + } if (elem.getParameterCount() == 1) { emptyConstructorTmp = elem; Log.verbose(" >>> " + elem.toGenericString()); @@ -122,26 +131,26 @@ public class IntrospectionModelComplex extends IntrospectionModel { // Retrieve full description in constructor properties... String[] namesBeans = ReflectTools.getNames(elem, null); if (namesBeans == null) { - namesBeans = new String[elem.getParameterCount()-1]; - } else if (elem.getParameterCount() != namesBeans.length+1) { + namesBeans = new String[elem.getParameterCount() - offsetSubClass]; + } else if (elem.getParameterCount() != namesBeans.length+offsetSubClass) { throw new ExmlBuilderException("Wrong number of parameter in constructor with ne number declared in the @XmlName (for bean name)"); } - Boolean[] isAttributes = new Boolean[elem.getParameterCount()-1]; + Boolean[] isAttributes = new Boolean[elem.getParameterCount()-offsetSubClass]; - Class[][] clazz = new Class[elem.getParameterCount()-1][]; - String[][] names = new String[elem.getParameterCount()-1][]; + Class[][] clazz = new Class[elem.getParameterCount()-offsetSubClass][]; + String[][] names = new String[elem.getParameterCount()-offsetSubClass][]; Parameter[] params = elem.getParameters(); - for (int iii=1; iii[] types = ReflectTools.getTypeParameterfunction(elem, iii); - clazz[iii-1] = types; - names[iii-1] = namesParam; + clazz[iii-offsetSubClass] = types; + names[iii-offsetSubClass] = namesParam; if (namesParam != null && namesParam.length != 0 ) { // TODO maybe do something id name is already set ??? - namesBeans[iii-1] = namesParam[0]; + namesBeans[iii-offsetSubClass] = namesParam[0]; } } if (checkIfOneIsNull(namesBeans,0)) { @@ -149,7 +158,7 @@ public class IntrospectionModelComplex extends IntrospectionModel { Log.verbose(" ==> unmanaged (missing names description: " + Arrays.toString(namesBeans) + ")"); } else { // check default attributes in the global list ... (do it at the end to be sure the constructor is VALID ... - for (int iii=1; iii>> " + elem.toGenericString()); - } else { - // Retrieve full description in constructor properties... - String[] names = ReflectTools.getNames(elem, null); - if (names == null) { - names = new String[elem.getParameterCount()]; - } else if (elem.getParameterCount() != names.length) { - throw new ExmlBuilderException("Wrong number of parameter in constructor with ne number declared in the @XmlName"); - } - Boolean[] isAttributes = new Boolean[elem.getParameterCount()]; - - Parameter[] params = elem.getParameters(); - for (int iii=1; iii unmanaged (missing names description)"); - } else { - this.constructors.add(new ConstructorModel(names, isAttributes, elem)); - } } } this.constructorEmpty = emptyConstructorTmp; @@ -250,6 +232,9 @@ public class IntrospectionModelComplex extends IntrospectionModel { } } } + // ------------------------------------------------------------------------ + // -- Parse Field + // ------------------------------------------------------------------------ final Field[] fields = this.classType.getFields(); Log.verbose(" Fields: (" + fields.length + ")"); for (final Field elem : fields) { @@ -264,8 +249,27 @@ public class IntrospectionModelComplex extends IntrospectionModel { } final String[] names = ReflectTools.getNames(elem, null); Class[] types = ReflectTools.getTypeField(elem); - IntrospectionProperty prop = new IntrospectionProperty(Tools.decapitalizeFirst(elem.getName()), types, names); - this.elements.add(prop); + + IntrospectionProperty prop = findElement(elem.getName()); + if (prop == null) { + prop = new IntrospectionProperty(elem.getName(), types, names); + this.elements.add(prop); + } else { + Class curentType = prop.getType(); + Class curentSubType = prop.getSubType(); + if (curentType != types[0] && curentSubType != types[1]) { + throw new ExmlBuilderException("Set 'return type' with a different value previous=" + curentType.getCanonicalName() + " / " + curentSubType.getCanonicalName() + " ==> new=" + types[0] + " / " + types[1] + " in " + elem.toGenericString()); + } + String[] names1 = names; + if (names1 != null) { + String[] curentValue = prop.getNames(); + if (curentValue != null) { + // TODO maybe set the value permissive if no change !!! like the others... + throw new ExmlBuilderException("Set 'names' with a (already set!) " + elem.toGenericString()); + } + prop.setNames(names1); + } + } final String listName = ReflectTools.getListName(elem, null); if (listName != null) { @@ -502,7 +506,22 @@ public class IntrospectionModelComplex extends IntrospectionModel { } } - private IntrospectionProperty updateForMethod(String name, final Method method, Class[] types) throws Exception { + private boolean checkIdenticalArray(final String[] valA, final String[] valB) { + if (valA == valB) { + return true; + } + if (valA.length != valB.length) { + return false; + } + for (int iii=0; iii[] types) throws Exception { IntrospectionProperty prop = findElement(name); if (prop == null) { String[] names = ReflectTools.getNames(method, null); @@ -517,7 +536,7 @@ public class IntrospectionModelComplex extends IntrospectionModel { String[] names = ReflectTools.getNames(method, null); if (names != null) { String[] curentValue = prop.getNames(); - if (curentValue != null) { + if (curentValue != null && !checkIdenticalArray(curentValue,names)) { // TODO maybe set the value permissive if no change !!! like the others... throw new ExmlBuilderException("Set 'names' with a (already set!) " + method.toGenericString()); } diff --git a/src/org/atriasoft/exml/builder/IntrospectionProperty.java b/src/org/atriasoft/exml/builder/IntrospectionProperty.java index cde3154..065fc1b 100644 --- a/src/org/atriasoft/exml/builder/IntrospectionProperty.java +++ b/src/org/atriasoft/exml/builder/IntrospectionProperty.java @@ -1,7 +1,6 @@ package org.atriasoft.exml.builder; import java.util.ArrayList; -import java.util.Collection; import java.util.List; import org.atriasoft.eStringSerialize.StringSerializer; @@ -55,10 +54,10 @@ public final class IntrospectionProperty { this.names = names; } - public void setSetter(IntrospectionPropertySetter setter) { + public void setSetter(final IntrospectionPropertySetter setter) { this.setter = setter; } - public void setGetter(IntrospectionPropertyGetter getter) { + public void setGetter(final IntrospectionPropertyGetter getter) { this.getter = getter; } @@ -98,11 +97,11 @@ public final class IntrospectionProperty { * @return The generate value of the object * @throws ExmlBuilderException in an error occured */ - public Object getValue(Object object) throws ExmlBuilderException { - if (getter != null) { + public Object getValue(final Object object) throws ExmlBuilderException { + if (this.getter != null) { return this.getter.getValue(object); } - throw new ExmlBuilderException("Property: " + names + " have no getter"); + throw new ExmlBuilderException("Property: " + this.names + " have no getter"); } /** @@ -133,12 +132,12 @@ public final class IntrospectionProperty { * @param value Value to set in the Object * @throws Exception An error occurred */ - public void setExistingValue(Object object, Object value) throws ExmlBuilderException { - if (setter != null) { + public void setExistingValue(final Object object, final Object value) throws ExmlBuilderException { + if (this.setter != null) { this.setter.setValue(object, value); return; } - throw new ExmlBuilderException("Property: " + names + " have no setter"); + throw new ExmlBuilderException("Property: " + this.names + " have no setter"); } /** * Create a value adapted to the property type. @@ -171,36 +170,36 @@ public final class IntrospectionProperty { } public Boolean isCaseSensitive() { - return caseSensitive; + return this.caseSensitive; } - public void setCaseSensitive(Boolean caseSensitive) { + public void setCaseSensitive(final Boolean caseSensitive) { this.caseSensitive = caseSensitive; } public Boolean isOptionnal() { - return optionnal; + return this.optionnal; } - public void setOptionnal(Boolean optionnal) { + public void setOptionnal(final Boolean optionnal) { this.optionnal = optionnal; } public Boolean isAttribute() { - return attribute; + return this.attribute; } - public void setAttribute(Boolean attribute) { + public void setAttribute(final Boolean attribute) { this.attribute = attribute; } public String getBeanName() { - return beanName; + return this.beanName; } - public void setNames(String[] names) { + public void setNames(final String[] names) { this.names = names; } - public void setListName(String listName) { + public void setListName(final String listName) { this.listName = listName; } public Boolean isManaged() { - return managed; + return this.managed; } - public void setManaged(Boolean managed) { + public void setManaged(final Boolean managed) { this.managed = managed; } diff --git a/src/org/atriasoft/exml/builder/IntrospectionPropertyField.java b/src/org/atriasoft/exml/builder/IntrospectionPropertyField.java index bc8fbe8..017211f 100644 --- a/src/org/atriasoft/exml/builder/IntrospectionPropertyField.java +++ b/src/org/atriasoft/exml/builder/IntrospectionPropertyField.java @@ -2,8 +2,6 @@ package org.atriasoft.exml.builder; import java.lang.reflect.Field; import java.lang.reflect.Modifier; -import java.lang.reflect.ParameterizedType; -import java.lang.reflect.Type; import org.atriasoft.exml.exception.ExmlBuilderException; diff --git a/src/org/atriasoft/exml/builder/IntrospectionPropertyMethodGetter.java b/src/org/atriasoft/exml/builder/IntrospectionPropertyMethodGetter.java index 6e3371a..af4aaf7 100644 --- a/src/org/atriasoft/exml/builder/IntrospectionPropertyMethodGetter.java +++ b/src/org/atriasoft/exml/builder/IntrospectionPropertyMethodGetter.java @@ -2,12 +2,8 @@ package org.atriasoft.exml.builder; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; -import java.lang.reflect.ParameterizedType; -import java.lang.reflect.Type; -import java.util.List; import org.atriasoft.exml.exception.ExmlBuilderException; -import org.atriasoft.exml.internal.Log; public class IntrospectionPropertyMethodGetter implements IntrospectionPropertyGetter { // private static Class[] getTypefunction(final Method setter, final Method getter) throws Exception { diff --git a/src/org/atriasoft/exml/builder/IntrospectionPropertyMethodSetter.java b/src/org/atriasoft/exml/builder/IntrospectionPropertyMethodSetter.java index 2fe6c93..ae18dfe 100644 --- a/src/org/atriasoft/exml/builder/IntrospectionPropertyMethodSetter.java +++ b/src/org/atriasoft/exml/builder/IntrospectionPropertyMethodSetter.java @@ -2,12 +2,8 @@ package org.atriasoft.exml.builder; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; -import java.lang.reflect.ParameterizedType; -import java.lang.reflect.Type; -import java.util.List; import org.atriasoft.exml.exception.ExmlBuilderException; -import org.atriasoft.exml.internal.Log; public class IntrospectionPropertyMethodSetter implements IntrospectionPropertySetter { protected Method setter; diff --git a/test/src/test/atriasoft/exml/ExmlTestIntrospectionDecorator.java b/test/src/test/atriasoft/exml/ExmlTestIntrospectionDecoratorAttribute.java similarity index 65% rename from test/src/test/atriasoft/exml/ExmlTestIntrospectionDecorator.java rename to test/src/test/atriasoft/exml/ExmlTestIntrospectionDecoratorAttribute.java index 658c68d..5fa34d8 100644 --- a/test/src/test/atriasoft/exml/ExmlTestIntrospectionDecorator.java +++ b/test/src/test/atriasoft/exml/ExmlTestIntrospectionDecoratorAttribute.java @@ -15,7 +15,7 @@ import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; -public class ExmlTestIntrospectionDecorator { +public class ExmlTestIntrospectionDecoratorAttribute { static final String NODE_NAME = "elem"; @BeforeAll public static void beforeClass() { @@ -172,7 +172,7 @@ public class ExmlTestIntrospectionDecorator { StringBuilder builder = new StringBuilder(); Assertions.assertDoesNotThrow(() -> Exml.generate(elem, ExmlTestIntrospectionObject.NODE_NAME, builder)); String dataTest = builder.toString(); - Log.warning("data generated: " + builder.toString()); + Log.warning("data generated: " + dataTest); Assertions.assertEquals("\n" + " 159\n" + " 182445\n" @@ -226,6 +226,47 @@ public class ExmlTestIntrospectionDecorator { private int valueJ; private int valueK; + + public final int finalValueM; + @XmlAttribute + public final int finalValueN; + @XmlAttribute(true) + public final int finalValueO; + @XmlAttribute(false) + public final int finalValueP; + + // special case for bijectivity with records + public final int finalValueQ; + public final int finalValueR; + public final int finalValueS; + public final int finalValueT; + + private final int pFinalValueQ; + private final int pFinalValueR; + private final int pFinalValueS; + private final int pFinalValueT; + + @XmlName({"finalValueM", "finalValueN", "finalValueO", "finalValueP", + "finalValueQ", "finalValueR", "finalValueS", "finalValueT", + "pFinalValueQ", "pFinalValueR", "pFinalValueS", "pFinalValueT"}) + public TestNodeObjectTrue( + final int finalValueM, final int finalValueN, final int finalValueO, final int finalValueP, + final int finalValueQ, @XmlAttribute final int finalValueR, @XmlAttribute(true) final int finalValueS, @XmlAttribute(false) final int finalValueT, + final int pFinalValueQ, final int pFinalValueR, final int pFinalValueS, final int pFinalValueT) { + this.finalValueM = finalValueM; + this.finalValueN = finalValueN; + this.finalValueO = finalValueO; + this.finalValueP = finalValueP; + this.finalValueQ = finalValueQ; + this.finalValueR = finalValueR; + this.finalValueS = finalValueS; + this.finalValueT = finalValueT; + this.pFinalValueQ = pFinalValueQ; + this.pFinalValueR = pFinalValueR; + this.pFinalValueS = pFinalValueS; + this.pFinalValueT = pFinalValueT; + } + public int getValueE() { return this.valueE; } @@ -274,12 +315,31 @@ public class ExmlTestIntrospectionDecorator { public void setValueK(final int valueK) { this.valueK = valueK; } + + public int getPFinalValueQ() { + return this.pFinalValueQ; + } + + @XmlAttribute + public int getPFinalValueR() { + return this.pFinalValueR; + } + + @XmlAttribute(true) + public int getPFinalValueS() { + return this.pFinalValueS; + } + + @XmlAttribute(false) + public int getPFinalValueT() { + return this.pFinalValueT; + } } @Test public void testDefaultAttributeTrue() { - TestNodeObjectTrue elem = new TestNodeObjectTrue(); + TestNodeObjectTrue elem = new TestNodeObjectTrue(321,654,987,159,267,264,1524,182445, -552, -965, -98885, -8754); elem.valueA = 55; elem.valueB = 78; elem.valueC = 51; @@ -296,7 +356,10 @@ public class ExmlTestIntrospectionDecorator { Assertions.assertDoesNotThrow(() -> Exml.generate(elem, ExmlTestIntrospectionObject.NODE_NAME, builder)); String dataTest = builder.toString(); Log.warning("data generated: " + builder.toString()); - Assertions.assertEquals("\n" + Assertions.assertEquals("\n" + + " 159\n" + + " 182445\n" + + " -8754\n" + " 24\n" + " 8247\n" + " 885522\n" @@ -314,6 +377,18 @@ public class ExmlTestIntrospectionDecorator { Assertions.assertEquals(87465, root.getValueI()); Assertions.assertEquals(8247, root.getValueJ()); Assertions.assertEquals(885522, root.getValueK()); + Assertions.assertEquals(321, root.finalValueM); + Assertions.assertEquals(654, root.finalValueN); + Assertions.assertEquals(987, root.finalValueO); + Assertions.assertEquals(159, root.finalValueP); + Assertions.assertEquals(267, root.finalValueQ); + Assertions.assertEquals(264, root.finalValueR); + Assertions.assertEquals(1524, root.finalValueS); + Assertions.assertEquals(182445, root.finalValueT); + Assertions.assertEquals(-552, root.getPFinalValueQ()); + Assertions.assertEquals(-965, root.getPFinalValueR()); + Assertions.assertEquals(-98885, root.getPFinalValueS()); + Assertions.assertEquals(-8754, root.getPFinalValueT()); } @XmlDefaultAttibute(false) @@ -333,6 +408,46 @@ public class ExmlTestIntrospectionDecorator { private int valueI; private int valueJ; private int valueK; + + public final int finalValueM; + @XmlAttribute + public final int finalValueN; + @XmlAttribute(true) + public final int finalValueO; + @XmlAttribute(false) + public final int finalValueP; + + // special case for bijectivity with records + public final int finalValueQ; + public final int finalValueR; + public final int finalValueS; + public final int finalValueT; + + private final int pFinalValueQ; + private final int pFinalValueR; + private final int pFinalValueS; + private final int pFinalValueT; + + @XmlName({"finalValueM", "finalValueN", "finalValueO", "finalValueP", + "finalValueQ", "finalValueR", "finalValueS", "finalValueT", + "pFinalValueQ", "pFinalValueR", "pFinalValueS", "pFinalValueT"}) + public TestNodeObjectFalse( + final int finalValueM, final int finalValueN, final int finalValueO, final int finalValueP, + final int finalValueQ, @XmlAttribute final int finalValueR, @XmlAttribute(true) final int finalValueS, @XmlAttribute(false) final int finalValueT, + final int pFinalValueQ, final int pFinalValueR, final int pFinalValueS, final int pFinalValueT) { + this.finalValueM = finalValueM; + this.finalValueN = finalValueN; + this.finalValueO = finalValueO; + this.finalValueP = finalValueP; + this.finalValueQ = finalValueQ; + this.finalValueR = finalValueR; + this.finalValueS = finalValueS; + this.finalValueT = finalValueT; + this.pFinalValueQ = pFinalValueQ; + this.pFinalValueR = pFinalValueR; + this.pFinalValueS = pFinalValueS; + this.pFinalValueT = pFinalValueT; + } public int getValueE() { return this.valueE; @@ -382,12 +497,31 @@ public class ExmlTestIntrospectionDecorator { public void setValueK(final int valueK) { this.valueK = valueK; } + + + public int getPFinalValueQ() { + return this.pFinalValueQ; + } + @XmlAttribute + public int getPFinalValueR() { + return this.pFinalValueR; + } + + @XmlAttribute(true) + public int getPFinalValueS() { + return this.pFinalValueS; + } + + @XmlAttribute(false) + public int getPFinalValueT() { + return this.pFinalValueT; + } } @Test public void testDefaultAttributeFalse() { - TestNodeObjectFalse elem = new TestNodeObjectFalse(); + TestNodeObjectFalse elem = new TestNodeObjectFalse(321,654,987,159,267,264,1524,182445, -552, -965, -98885, -8754); elem.valueA = 55; elem.valueB = 78; elem.valueC = 51; @@ -404,7 +538,13 @@ public class ExmlTestIntrospectionDecorator { Assertions.assertDoesNotThrow(() -> Exml.generate(elem, ExmlTestIntrospectionObject.NODE_NAME, builder)); String dataTest = builder.toString(); Log.warning("data generated: " + builder.toString()); - Assertions.assertEquals("\n" + Assertions.assertEquals("\n" + + " 321\n" + + " 159\n" + + " 267\n" + + " 182445\n" + + " -552\n" + + " -8754\n" + " 55\n" + " 24\n" + " 651\n" @@ -424,6 +564,18 @@ public class ExmlTestIntrospectionDecorator { Assertions.assertEquals(87465, root.getValueI()); Assertions.assertEquals(8247, root.getValueJ()); Assertions.assertEquals(885522, root.getValueK()); + Assertions.assertEquals(321, root.finalValueM); + Assertions.assertEquals(654, root.finalValueN); + Assertions.assertEquals(987, root.finalValueO); + Assertions.assertEquals(159, root.finalValueP); + Assertions.assertEquals(267, root.finalValueQ); + Assertions.assertEquals(264, root.finalValueR); + Assertions.assertEquals(1524, root.finalValueS); + Assertions.assertEquals(182445, root.finalValueT); + Assertions.assertEquals(-552, root.getPFinalValueQ()); + Assertions.assertEquals(-965, root.getPFinalValueR()); + Assertions.assertEquals(-98885, root.getPFinalValueS()); + Assertions.assertEquals(-8754, root.getPFinalValueT()); } } diff --git a/test/src/test/atriasoft/exml/ExmlTestIntrospectionRecord.java b/test/src/test/atriasoft/exml/ExmlTestIntrospectionRecord.java index 4bb1782..3646d5e 100644 --- a/test/src/test/atriasoft/exml/ExmlTestIntrospectionRecord.java +++ b/test/src/test/atriasoft/exml/ExmlTestIntrospectionRecord.java @@ -6,6 +6,7 @@ package test.atriasoft.exml; import org.atriasoft.exml.Exml; +import org.atriasoft.exml.annotation.XmlAttribute; import org.atriasoft.exml.annotation.XmlName; import org.junit.jupiter.api.Assertions; @@ -18,10 +19,12 @@ public class ExmlTestIntrospectionRecord { public static void beforeClass() { Log.warning("================================================================"); } + public record TestRecord( @XmlName("valueA") Integer valueA, @XmlName("valueB") double valueB) { } + @Test public void testModelRecord() { TestRecord elem = new TestRecord(66, 18523.0); @@ -40,5 +43,25 @@ public class ExmlTestIntrospectionRecord { } + public record TestRecordProperty ( + @XmlName("valueA") @XmlAttribute Integer valueA, + @XmlName("valueB") @XmlAttribute double valueB) { + } + + @Test + public void testModelRecordProperty() { + TestRecordProperty elem = new TestRecordProperty(66, 18523.0); + 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("", dataTest); + + final TestRecordProperty root = Assertions.assertDoesNotThrow(() -> Exml.parseOne(dataTest, TestRecordProperty.class, ExmlTestIntrospectionObject.NODE_NAME)); + Assertions.assertEquals(66, root.valueA); + Assertions.assertEquals(18523.0f, root.valueB); + } + + }