[DEV] add ignoring missing and default null in record constructor

This commit is contained in:
Edouard DUPIN 2021-10-09 08:27:34 +02:00
parent 4a32ec0b15
commit ce7b909cb0
18 changed files with 305 additions and 105 deletions

View File

@ -99,7 +99,7 @@ public class Exml {
}
return null;
} catch (final ExmlException ex) {
//ex.printStackTrace();
ex.printStackTrace();
throw ex;
}
}
@ -203,7 +203,17 @@ public class Exml {
* @return false : An error occured
* @return true : Parsing is OK
*/
public static void store(final Uri uri, final Object root, final String rootNodeName) throws ExmlException, IOException {
StringBuilder builder = new StringBuilder();
Exml.generate(root, rootNodeName, builder);
Uri.writeAll(uri, builder.toString());
}
public static void store(final Path path, final Object root, final String rootNodeName) throws ExmlException, IOException {
StringBuilder builder = new StringBuilder();
Exml.generate(root, rootNodeName, builder);
Files.writeString(path, builder.toString());
}
/*
* public boolean store( Uri _uri){ String createData; if (generate(createData)
* == false) { Log.error("Error while creating the XML: " + _uri); return false;

View File

@ -0,0 +1,18 @@
package org.atriasoft.exml.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@ExmlAnnotation
public @interface XmlDefaultNullValue {
/**
* Set the default value at true in the constructor if needed (set at 0 for basic type int, long ...).
* @return true if the element are by default at null.
*/
boolean value() default true;
}

View File

@ -0,0 +1,20 @@
package org.atriasoft.exml.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Marker annotation that permit to set the default parsing as attributes.
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@ExmlAnnotation
public @interface XmlIgnoreUnknow {
/**
* Set the element ignore unknown Nodes.
* @return true does not display unknown node.
*/
boolean value() default true;
}

View File

@ -9,7 +9,7 @@ import java.lang.annotation.Target;
* Marker annotation that force the xml Parser to manage this element (used when the class is mark as @XmldefaultNotManaged).
*
*/
@Target({ ElementType.FIELD, ElementType.METHOD})
@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@ExmlAnnotation
public @interface XmlManaged {

View File

@ -7,7 +7,6 @@ import org.atriasoft.eStringSerialize.StringSerializer;
import org.atriasoft.exml.exception.ExmlAttributeDoesNotExist;
import org.atriasoft.exml.exception.ExmlBuilderException;
import org.atriasoft.exml.exception.ExmlException;
import org.atriasoft.exml.exception.ExmlNodeDoesNotExist;
import org.atriasoft.exml.internal.Log;
public class BuilderIntrospection implements Builder {
@ -55,6 +54,10 @@ public class BuilderIntrospection implements Builder {
}
typeClass = model.getClassType();
} else {
if (!introspectionObject.isSubNodeOrPropertyExist(nodeName) && model.isIgnoreUnknown()) {
Log.debug("Ignore node: '" + nodeName + "' Does not exist...");
return null;
}
typeClass = introspectionObject.getTypeOfSubNode(nodeName);
listTreeName = introspectionObject.getTreeNameOfSubNode(nodeName);
}
@ -106,6 +109,10 @@ public class BuilderIntrospection implements Builder {
}
String beanName = model.getBeanName(propertyName);
if (beanName == null) {
if (model.isIgnoreUnknown()) {
Log.debug("Ignore node : '" + propertyName + "'");
return;
}
throw new ExmlAttributeDoesNotExist("The node '" + propertyName + "' Does not exist...");
}
Class<?> typeClass = model.getTypeOfProperty(propertyName);
@ -189,6 +196,7 @@ public class BuilderIntrospection implements Builder {
@Override
public void newElementFinished(final Object parent, final String tmpName, final Object element) throws ExmlException {
Log.debug("new element fionished : ==> " + tmpName);
if (parent == null || element == null) {
return;
}

View File

@ -8,10 +8,15 @@ import org.atriasoft.exml.exception.ExmlBuilderException;
public abstract class IntrospectionModel {
protected static final Boolean DEFAULT_ATTRIBUTE = false;
protected static final Boolean DEFAULT_IGNORE_UNBKNOWN = false;
protected static final Boolean DEFAULT_DEFAULT_NULL_VALUE = false;
protected static final Boolean DEFAULT_CASE_SENSITIVE = true;
protected static final Boolean DEFAULT_MANAGED = true;
protected static final Boolean DEFAULT_OPTIONAL = false;
protected boolean defaultNullValue = false;
protected boolean ignoreUnknown = false;
protected final Class<?> classType;
public List<IntrospectionProperty> getNodes() {
@ -78,8 +83,14 @@ public abstract class IntrospectionModel {
public boolean isEnum() {
return this.classType.isEnum();
}
public String getBeanName(String nodeName) {
public String getBeanName(final String nodeName) {
return nodeName;
}
protected boolean isIgnoreUnknown() {
return this.ignoreUnknown;
}
protected boolean isDefaultNullValue() {
return this.defaultNullValue;
}
}

View File

@ -39,7 +39,8 @@ public class IntrospectionModelComplex extends IntrospectionModel {
private final List<ConstructorModel> constructors = new ArrayList<>();
private final List<IntrospectionProperty> elements = new ArrayList<>();
public String getBeanName(String nodeName) {
@Override
public String getBeanName(final String nodeName) {
for (IntrospectionProperty elem : this.elements) {
if (elem.isCompatible(nodeName)) {
return elem.getBeanName();
@ -483,6 +484,10 @@ public class IntrospectionModelComplex extends IntrospectionModel {
prop.setSetter(modifier);
}
}
this.ignoreUnknown = ReflectTools.getIsIgnoreUnknown(classType, IntrospectionModel.DEFAULT_IGNORE_UNBKNOWN);
this.defaultNullValue = ReflectTools.getIsDefaultNullValue(classType, IntrospectionModel.DEFAULT_DEFAULT_NULL_VALUE);
// Set only at the end ==> no need before...
final Boolean isDefaultAttribute = ReflectTools.getIsDefaultAttribute(classType, IntrospectionModel.DEFAULT_ATTRIBUTE);
for (IntrospectionProperty prop : this.elements) {
@ -540,6 +545,12 @@ public class IntrospectionModelComplex extends IntrospectionModel {
Log.warning(" optionnal: " + prop.isOptionnal());
Log.warning(" constructor: " + prop.isCanBeSetByConstructor());
Log.warning(" get/set: " + prop.canGetValue() + " / " + prop.canSetValue());
Log.warning(" type: " + prop.getType().getCanonicalName());
if (prop.getSubType() != null) {
Log.warning(" sub-type: " + prop.getSubType().getCanonicalName());
} else {
Log.warning(" sub-type: null");
}
}
}
@ -629,25 +640,43 @@ public class IntrospectionModelComplex extends IntrospectionModel {
Object tmp = null;
// STEP 1: try to create the object with provided parameter (if a constructor exist....)
if (!this.constructors.isEmpty()) {
Object[] inputs = null;
ConstructorModel betterModel = null;
int lastEmpty = Integer.MAX_VALUE;
// try to find the constructor that fit with parameters ...
for (ConstructorModel elem : this.constructors) {
int offset = this.isSubClass?1:0;
Object[] inputs = new Object[elem.values().length+offset];
inputs[0] = null;
Object[] inputsTmp = new Object[elem.values().length+offset];
inputsTmp[0] = null;
int empty = 0;
for (int iii=0; iii<elem.values().length; iii++) {
Object valueToInject = properties.get(elem.values()[iii]);
if (valueToInject == null) {
List<Object> tmppp = nodes.get(elem.values()[iii]);
if (tmppp != null && tmppp.size() >=1) {
if (tmppp != null) {
if (List.class == findBeanNodeDescription(elem.values()[iii]).getType() ) {
valueToInject = tmppp;
} else if (tmppp.size() >=1) {
valueToInject = tmppp.get(0);
}
}
}
if (valueToInject == null) {
inputs = null;
break;
empty++;
inputsTmp[iii+offset] = null;
continue;
}
inputs[iii+offset] = valueToInject;
inputsTmp[iii+offset] = valueToInject;
}
if (lastEmpty > empty) {
inputs = inputsTmp;
betterModel = elem;
lastEmpty = empty;
}
}
if (betterModel != null) {
if (isDefaultNullValue() || lastEmpty == 0) {
ConstructorModel elem = betterModel;
if (inputs != null) {
// here we find our constructor...
try {
@ -689,7 +718,7 @@ public class IntrospectionModelComplex extends IntrospectionModel {
properties.remove(elem.values()[iii]);
nodes.remove(elem.values()[iii]);
}
break;
}
}
}
}
@ -733,6 +762,29 @@ public class IntrospectionModelComplex extends IntrospectionModel {
}
return out;
}
protected IntrospectionProperty findBeanNodeDescription(final String propertyBeanName) throws ExmlBuilderException {
for (final IntrospectionProperty prop : this.elements) {
if (prop.isAttribute()) {
continue;
}
if (prop.getBeanName().equals(propertyBeanName)) {
return prop;
}
}
return null;
}
protected IntrospectionProperty findBeanPropertyDescription(final String propertyBeanName) throws ExmlBuilderException {
for (final IntrospectionProperty prop : this.elements) {
if (!prop.isAttribute()) {
continue;
}
if (prop.getBeanName().equals(propertyBeanName)) {
return prop;
}
}
return null;
}
protected IntrospectionProperty findNodeDescription(final String propertyName) throws ExmlBuilderException {
for (final IntrospectionProperty prop : this.elements) {
if (prop.isAttribute()) {
@ -768,11 +820,11 @@ public class IntrospectionModelComplex extends IntrospectionModel {
//return data.stream().map(clazz::cast).toArray(new T[data.size()]);//java.lang.reflect.Array.newInstance((propMethode.getSubType(), tmpp.size()));
}
private void setValue(final Object data, final String name, final Object value) throws ExmlBuilderException {
Log.error(" Set value ='" + name + "' propertyValue='" + value + "' " + value.getClass().getCanonicalName());
private void setValue(final Object data, final String beanName, final Object value) throws ExmlBuilderException {
Log.error(" Set value ='" + beanName + "' propertyValue='" + value + "' " + value.getClass().getCanonicalName());
{
// by default use setter to set the property
final IntrospectionProperty propMethode = findNodeDescription(name);
final IntrospectionProperty propMethode = findBeanNodeDescription(beanName);
if (propMethode != null && propMethode.canSetValue()) {
Log.verbose(" ==> find '" + Arrays.toString(propMethode.getNames()) + " type=" + propMethode.getType() + " sub-type=" + propMethode.getSubType() );
if (propMethode.getType().isAssignableFrom(value.getClass())) {
@ -823,7 +875,7 @@ public class IntrospectionModelComplex extends IntrospectionModel {
}
// try with direct field
{
final IntrospectionProperty propField = findPropertyDescription(name);
final IntrospectionProperty propField = findBeanPropertyDescription(beanName);
if (propField != null && propField.canSetValue()) {
Log.verbose(" ==> find '" + Arrays.toString(propField.getNames()) + " type=" + propField.getType() + " sub-type=" + propField.getSubType() );
if (propField.getType().isAssignableFrom(value.getClass())) {
@ -889,43 +941,43 @@ public class IntrospectionModelComplex extends IntrospectionModel {
return;
}
}
throw new ExmlBuilderException("can not find the field '" + name + "'");
throw new ExmlBuilderException("can not find the field '" + beanName + "'");
}
/**
* Detect a subNode, and ask the type of the node at the parent Class
* @param nodeName Name of the node
* @param nodeBeanName Name of the node (bean name access ==> not the XML name)
* @return Class of the node to create
*/
@Override
public Class<?> getTypeOfSubNode(final String nodeName) throws ExmlBuilderException {
Log.error(" nodeType='" + nodeName + "'");
final IntrospectionProperty propMethode = findNodeDescription(nodeName);
public Class<?> getTypeOfSubNode(final String nodeBeanName) throws ExmlBuilderException {
Log.error(" nodeType='" + nodeBeanName + "'");
final IntrospectionProperty propMethode = findBeanNodeDescription(nodeBeanName);
if (propMethode != null && propMethode.canSetValue()) {
Log.error(" ==> find '" + propMethode.getNames());
return propMethode.getType();
}
throw new ExmlBuilderException("can not find the field '" + nodeName + "' availlable: " + getNodeAvaillable());
throw new ExmlBuilderException("can not find the field '" + nodeBeanName + "' availlable: " + getNodeAvaillable());
}
@Override
public Class<?> getTypeOfSubNodeList(final String nodeName) throws ExmlBuilderException {
Log.error(" nodeType='" + nodeName + "'");
final IntrospectionProperty propMethode = findNodeDescription(nodeName);
public Class<?> getTypeOfSubNodeList(final String nodeBeanName) throws ExmlBuilderException {
Log.error(" nodeType='" + nodeBeanName + "'");
final IntrospectionProperty propMethode = findBeanNodeDescription(nodeBeanName);
if (propMethode != null && propMethode.canSetValue()) {
Log.error(" ==> find '" + propMethode.getNames());
return propMethode.getSubType();
}
throw new ExmlBuilderException("can not find the field '" + nodeName + "' availlable: " + getNodeAvaillable());
throw new ExmlBuilderException("can not find the field '" + nodeBeanName + "' availlable: " + getNodeAvaillable());
}
@Override
public String getTreeNameOfSubNode(final String nodeName) throws ExmlBuilderException {
Log.error(" nodeType='" + nodeName + "'");
final IntrospectionProperty propMethode = findNodeDescription(nodeName);
public String getTreeNameOfSubNode(final String nodeBeanName) throws ExmlBuilderException {
Log.error(" nodeType='" + nodeBeanName + "'");
final IntrospectionProperty propMethode = findBeanNodeDescription(nodeBeanName);
if (propMethode != null && propMethode.canSetValue()) {
Log.error(" ==> find '" + propMethode.getNames());
return propMethode.getListName();
}
throw new ExmlBuilderException("can not find the field '" + nodeName + "'");
throw new ExmlBuilderException("can not find the field '" + nodeBeanName + "'");
}

View File

@ -30,48 +30,57 @@ public class IntrospectionObject {
}
public void putProperty(final String propertyName, final Object propertyValue) throws ExmlException {
final String beanName = modelInterface.getBeanName(propertyName);
final String beanName = this.modelInterface.getBeanName(propertyName);
if (this.properties.containsKey(beanName)) {
throw new ExmlBuilderException("Property have multiple values ==> impossible case; A Node must contain only 1 attibutes");
}
this.properties.put(beanName, propertyValue);
}
public boolean isSubNodeOrPropertyExist(final String nodeName) {
final String beanName = this.modelInterface.getBeanName(nodeName);
if (beanName == null) {
return false;
}
return true;
}
/**
* 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
*/
public Class<?> getTypeOfSubNode(final String nodeName) throws ExmlException {
final String beanName = modelInterface.getBeanName(nodeName);
final String beanName = this.modelInterface.getBeanName(nodeName);
if (beanName == null) {
throw new ExmlNodeDoesNotExist("The node '" + nodeName + "' Does not exist...");
}
return this.modelInterface.getTypeOfSubNode(beanName);
}
public Class<?> getTypeOfSubNodeSubType(final String nodeName) throws ExmlException {
final String beanName = modelInterface.getBeanName(nodeName);
final String beanName = this.modelInterface.getBeanName(nodeName);
if (beanName == null) {
throw new ExmlNodeDoesNotExist("The node '" + nodeName + "' Does not exist...");
}
return this.modelInterface.getTypeOfSubNodeList(beanName);
}
public String getTreeNameOfSubNode(final String nodeName) throws ExmlException {
final String beanName = modelInterface.getBeanName(nodeName);
final String beanName = this.modelInterface.getBeanName(nodeName);
if (beanName == null) {
throw new ExmlNodeDoesNotExist("The node '" + nodeName + "' Does not exist...");
}
return this.modelInterface.getTreeNameOfSubNode(beanName);
}
public Class<?> getTypeOfProperty(final String nodeName) throws ExmlException {
final String beanName = modelInterface.getBeanName(nodeName);
final String beanName = this.modelInterface.getBeanName(nodeName);
if (beanName == null) {
throw new ExmlNodeDoesNotExist("The node '" + nodeName + "' Does not exist...");
}
return this.modelInterface.getTypeOfProperty(beanName);
}
public Class<?> getTypeOfSubProperty(final String nodeName) throws ExmlException {
final String beanName = modelInterface.getBeanName(nodeName);
final String beanName = this.modelInterface.getBeanName(nodeName);
if (beanName == null) {
throw new ExmlNodeDoesNotExist("The node '" + nodeName + "' Does not exist...");
}
@ -87,7 +96,11 @@ public class IntrospectionObject {
@SuppressWarnings("unchecked")
public void addObject(final String nodeName, final Object value) throws ExmlException {
final String beanName = modelInterface.getBeanName(nodeName);
if (value == null) {
// specific case when a List is empty <links></links> but define for a specific list ==> need no action
return;
}
final String beanName = this.modelInterface.getBeanName(nodeName);
if (beanName == null) {
throw new ExmlNodeDoesNotExist("The node '" + nodeName + "' Does not exist...");
}

View File

@ -1,6 +1,7 @@
package org.atriasoft.exml.builder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.atriasoft.eStringSerialize.StringSerializer;
@ -111,17 +112,22 @@ public final class IntrospectionProperty {
* @return true if the element is compatible, false otherwise
*/
public boolean isCompatible(final String name) {
Log.warning("Check compatible : '" + name + "' in " + Arrays.toString(this.names));
if (this.caseSensitive) {
for (final String elem : this.names) {
if (elem.contentEquals(name)) {
Log.warning(" - '" + elem + "' ==> true");
return true;
}
Log.warning(" - '" + elem + "' == false");
}
} else {
for (final String elem : this.names) {
if (elem.equalsIgnoreCase(name)) {
Log.warning(" - '" + elem + "' ==> true");
return true;
}
Log.warning(" - '" + elem + "' == false");
}
}
return false;

View File

@ -9,7 +9,7 @@ import io.scenarium.logger.LogLevel;
import io.scenarium.logger.Logger;
public class Log {
private static final boolean FORCE = true;
private static final boolean FORCE = false;
private static final String LIB_NAME = "exml";
private static final String LIB_NAME_DRAW = Logger.getDrawableName(Log.LIB_NAME);
private static final boolean PRINT_CRITICAL = Logger.getNeedPrint(Log.LIB_NAME, LogLevel.CRITICAL);

View File

@ -1,7 +1,6 @@
package org.atriasoft.exml.parser;
import org.atriasoft.exml.builder.Builder;
import org.atriasoft.exml.exception.ExmlBuilderException;
import org.atriasoft.exml.exception.ExmlException;
import org.atriasoft.exml.exception.ExmlParserError;
import org.atriasoft.exml.exception.ExmlParserErrorMulti;
@ -487,7 +486,6 @@ public class ParseXml {
if (data.charAt(jjj) == '>') {
pos.value = jjj;
filePos.add(tmpPos);
Log.todo("End of node: '" + nameElement + "' ==> need add build result to parent and create object ...");
this.builder.endElement(parent);
return true;
}

View File

@ -14,7 +14,9 @@ import org.atriasoft.exml.annotation.XmlCaseSensitive;
import org.atriasoft.exml.annotation.XmlDefaultAttibute;
import org.atriasoft.exml.annotation.XmlDefaultCaseSensitive;
import org.atriasoft.exml.annotation.XmlDefaultManaged;
import org.atriasoft.exml.annotation.XmlDefaultNullValue;
import org.atriasoft.exml.annotation.XmlDefaultOptional;
import org.atriasoft.exml.annotation.XmlIgnoreUnknow;
import org.atriasoft.exml.annotation.XmlList;
import org.atriasoft.exml.annotation.XmlManaged;
import org.atriasoft.exml.annotation.XmlName;
@ -82,7 +84,7 @@ public class ReflectTools {
return new Class<?>[] {type, subType};
}
public static Class<?>[] getTypeParameterfunction(Constructor<?> elem, int paramId) throws ClassNotFoundException {
public static Class<?>[] getTypeParameterfunction(final Constructor<?> elem, final int paramId) throws ClassNotFoundException {
Class<?> type = null;
Class<?> subType = null;
@ -90,12 +92,13 @@ public class ReflectTools {
if (List.class.isAssignableFrom(type)) {
Class<?> internalModelClass = null;
Type[] empppe = elem.getGenericParameterTypes();
if (empppe.length > 0) {
if (empppe[0] instanceof ParameterizedType plopppppp) {
if (empppe.length > paramId) {
if (empppe[paramId] instanceof ParameterizedType plopppppp) {
Type[] realType = plopppppp.getActualTypeArguments();
if (realType.length > paramId) {
Log.warning(" -->> " + realType[paramId]);
internalModelClass = Class.forName(realType[paramId].getTypeName());
//Log.info("ppplllppp: " + realType.length);
if (realType.length > 0) {
Log.warning(" -->> " + realType[0]);
internalModelClass = Class.forName(realType[0].getTypeName());
}
}
}
@ -157,6 +160,26 @@ public class ReflectTools {
}
return ((XmlDefaultAttibute) annotation[0]).value();
}
public static Boolean getIsIgnoreUnknown(final Class<?> classType, final Boolean defaultValue) throws ExmlBuilderException {
final Annotation[] annotation = classType.getDeclaredAnnotationsByType(XmlIgnoreUnknow.class);
if (annotation.length == 0) {
return defaultValue;
}
if (annotation.length > 1) {
throw new ExmlBuilderException("Must not have more than 1 element @XmlIgnoreUnknow on " + classType.getClass().getCanonicalName());
}
return ((XmlIgnoreUnknow) annotation[0]).value();
}
public static Boolean getIsDefaultNullValue(final Class<?> classType, final Boolean defaultValue) throws ExmlBuilderException {
final Annotation[] annotation = classType.getDeclaredAnnotationsByType(XmlDefaultNullValue.class);
if (annotation.length == 0) {
return defaultValue;
}
if (annotation.length > 1) {
throw new ExmlBuilderException("Must not have more than 1 element @XmlDefaultNullValue on " + classType.getClass().getCanonicalName());
}
return ((XmlDefaultNullValue) annotation[0]).value();
}
public static Boolean getIsDefaultManaged(final Class<?> classType, final Boolean defaultValue) throws ExmlBuilderException {
final Annotation[] annotation = classType.getDeclaredAnnotationsByType(XmlDefaultManaged.class);

View File

@ -6,8 +6,9 @@
package test.atriasoft.exml;
import org.atriasoft.exml.Exml;
import org.atriasoft.exml.exception.ExmlBuilderException;
import org.atriasoft.exml.exception.ExmlException;
import org.atriasoft.exml.model.XmlNode;
import org.junit.jupiter.api.Assertions;
class ExmlLocal {
@ -26,7 +27,7 @@ class ExmlLocal {
Assertions.fail("Must have detected an error");
return;
}
} catch (final ExmlBuilderException e) {
} catch (final ExmlException e) {
if (errorPos == 1) {
return;
}

View File

@ -12,9 +12,8 @@ import org.atriasoft.exml.annotation.XmlDefaultAttibute;
import org.atriasoft.exml.annotation.XmlDefaultCaseSensitive;
import org.atriasoft.exml.annotation.XmlName;
import org.atriasoft.exml.exception.ExmlAttributeDoesNotExist;
import org.atriasoft.exml.exception.ExmlException;
import org.atriasoft.exml.exception.ExmlNodeDoesNotExist;
import org.atriasoft.exml.exception.ExmlParserErrorMulti;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;

View File

@ -7,10 +7,6 @@ package test.atriasoft.exml;
import org.atriasoft.exml.Exml;
import org.atriasoft.exml.annotation.XmlManaged;
import org.atriasoft.exml.annotation.XmlCaseSensitive;
import org.atriasoft.exml.annotation.XmlDefaultAttibute;
import org.atriasoft.exml.annotation.XmlDefaultCaseSensitive;
import org.atriasoft.exml.annotation.XmlDefaultManaged;
import org.atriasoft.exml.annotation.XmlManaged;
import org.atriasoft.exml.annotation.XmlName;

View File

@ -9,7 +9,6 @@ package test.atriasoft.exml;
import org.atriasoft.exml.Exml;
import org.atriasoft.exml.annotation.XmlAttribute;
import org.atriasoft.exml.annotation.XmlCaseSensitive;
import org.atriasoft.exml.annotation.XmlDefaultAttibute;
import org.atriasoft.exml.annotation.XmlDefaultCaseSensitive;
import org.atriasoft.exml.annotation.XmlName;
@ -579,6 +578,55 @@ public class ExmlTestIntrospectionDecoratorNames {
Assertions.assertEquals(-98885, root.getPFinalValueS());
Assertions.assertEquals(-8754, root.getPFinalValueT());
}
public class ChangingNames {
private String value1RataPlouf;
@XmlName("value2")
public String value2Ballet;
private String value3RataPlouf;
@XmlAttribute
@XmlName("value4")
public String value4Ballet;
@XmlName("value1")
public String getValue1RataPlouf() {
return this.value1RataPlouf;
}
public void setValue1RataPlouf(final String value1RataPlouf) {
this.value1RataPlouf = value1RataPlouf;
}
@XmlAttribute
@XmlName("value3")
public String getValue3RataPlouf() {
return this.value3RataPlouf;
}
public void setValue3RataPlouf(final String value3RataPlouf) {
this.value3RataPlouf = value3RataPlouf;
}
}
@Test
public void testChangingNames() {
ChangingNames elem = new ChangingNames();
elem.value2Ballet = "55";
elem.value4Ballet = "78";
elem.setValue1RataPlouf("51");
elem.setValue3RataPlouf("24");
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("<elem value3=\"24\" value4=\"78\">\n"
+ " <value1>51</value1>\n"
+ " <value2>55</value2>\n"
+ "</elem>", dataTest);
final ChangingNames root = Assertions.assertDoesNotThrow(() -> Exml.parseOne(dataTest, ChangingNames.class, ExmlTestIntrospectionObject.NODE_NAME));
Assertions.assertEquals("55", root.value2Ballet);
Assertions.assertEquals("78", root.value4Ballet);
Assertions.assertEquals("51", root.getValue1RataPlouf());
Assertions.assertEquals("24", root.getValue3RataPlouf());
}
}

View File

@ -7,13 +7,10 @@ package test.atriasoft.exml;
import org.atriasoft.exml.Exml;
import org.atriasoft.exml.annotation.XmlAttribute;
import org.atriasoft.exml.annotation.XmlCaseSensitive;
import org.atriasoft.exml.annotation.XmlDefaultAttibute;
import org.atriasoft.exml.annotation.XmlDefaultCaseSensitive;
import org.atriasoft.exml.annotation.XmlDefaultOptional;
import org.atriasoft.exml.annotation.XmlName;
import org.atriasoft.exml.annotation.XmlOptional;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;

View File

@ -6,7 +6,7 @@
package test.atriasoft.exml;
import org.atriasoft.exml.Exml;
import org.atriasoft.exml.exception.ExmlBuilderException;
import org.atriasoft.exml.exception.ExmlException;
import org.atriasoft.exml.exception.ExmlParserErrorMulti;
import org.junit.jupiter.api.BeforeAll;
@ -24,7 +24,7 @@ public class ExmlTestIntrospectionGenerate {
}
@Test
public void test1() throws ExmlParserErrorMulti, ExmlBuilderException {
public void test1() throws ExmlParserErrorMulti, ExmlException {
ClassPublicMemberOnly elem = new ClassPublicMemberOnly();
elem.memberArrayBoolean = new boolean[] {false, true};
elem.memberArrayBooleanClass = new Boolean[] {false, true, true};
@ -54,7 +54,7 @@ public class ExmlTestIntrospectionGenerate {
}
@Test
public void test2() throws ExmlParserErrorMulti, ExmlBuilderException {
public void test2() throws ExmlParserErrorMulti, ExmlException {
ClassPublicMethodOnly elem = new ClassPublicMethodOnly();
elem.setMemberArrayBoolean ( new boolean[] {false, true});
elem.setMemberArrayBooleanClass ( new Boolean[] {false, true, true});
@ -85,7 +85,7 @@ public class ExmlTestIntrospectionGenerate {
@Test
public void test3() throws ExmlParserErrorMulti, ExmlBuilderException {
public void test3() throws ExmlParserErrorMulti, ExmlException {
ClassPublicMethodeNode elem = new ClassPublicMethodeNode();
elem.setMemberArrayBoolean ( new boolean[] {false, true});
elem.setMemberArrayBooleanClass ( new Boolean[] {false, true, true});