[DEV] set it work for imutable and basic records

This commit is contained in:
Edouard DUPIN 2021-07-09 00:04:54 +02:00
parent c8ff65615f
commit 3ad74f0fb1
9 changed files with 679 additions and 373 deletions

View File

@ -9,7 +9,7 @@ import java.lang.annotation.Target;
* Marker annotation that can be used to define an other name of the attribute or the Element name. * Marker annotation that can be used to define an other name of the attribute or the Element name.
* *
*/ */
@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER }) @Target({ ElementType.FIELD, ElementType.METHOD, ElementType.CONSTRUCTOR, ElementType.PARAMETER })
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@ExmlAnnotation @ExmlAnnotation
public @interface XmlName { public @interface XmlName {

View File

@ -1,14 +1,16 @@
package org.atriasoft.exml.builder; package org.atriasoft.exml.builder;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.lang.reflect.Modifier; import java.lang.reflect.Modifier;
import java.lang.reflect.Parameter;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
@ -16,21 +18,16 @@ import java.util.stream.Collectors;
import org.atriasoft.eStringSerialize.StringSerializer; import org.atriasoft.eStringSerialize.StringSerializer;
import org.atriasoft.etk.util.ArraysTools; import org.atriasoft.etk.util.ArraysTools;
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.XmlDefaultManaged;
import org.atriasoft.exml.annotation.XmlDefaultOptional;
import org.atriasoft.exml.annotation.XmlList;
import org.atriasoft.exml.annotation.XmlManaged;
import org.atriasoft.exml.annotation.XmlName;
import org.atriasoft.exml.annotation.XmlOptional;
import org.atriasoft.exml.exception.ExmlBuilderException; import org.atriasoft.exml.exception.ExmlBuilderException;
import org.atriasoft.exml.internal.Log; import org.atriasoft.exml.internal.Log;
import org.atriasoft.exml.parser.Tools; import org.atriasoft.exml.parser.Tools;
import org.atriasoft.exml.reflect.ReflectTools;
record ConstructorModel(String[] values,
Constructor<?> constructor) {
}
public class IntrospectionModelComplex extends IntrospectionModel { public class IntrospectionModelComplex extends IntrospectionModel {
// TODO Optimize this with external object for basic types.... // TODO Optimize this with external object for basic types....
@ -38,6 +35,7 @@ public class IntrospectionModelComplex extends IntrospectionModel {
private final Method tostring; // used for the set Text if the object is an end point... private final Method tostring; // used for the set Text if the object is an end point...
private final boolean isSubClass; // if true, the constructor must be called with a null first object. private final boolean isSubClass; // if true, the constructor must be called with a null first object.
private final Constructor<?> constructorEmpty; private final Constructor<?> constructorEmpty;
private final List<ConstructorModel> constructors = new ArrayList<>();
private final List<IntrospectionProperty> nodes = new ArrayList<>(); private final List<IntrospectionProperty> nodes = new ArrayList<>();
private final List<IntrospectionProperty> attributes = new ArrayList<>(); private final List<IntrospectionProperty> attributes = new ArrayList<>();
@ -62,11 +60,18 @@ public class IntrospectionModelComplex extends IntrospectionModel {
} else { } else {
this.isSubClass = false; this.isSubClass = false;
} }
final boolean isRecord = Record.class.isAssignableFrom(classType);
if (isRecord) {
Log.error("Detect record !!! ");
}
if (classType.isPrimitive()) {
Log.critical("Detect primitive ==> impossible case !!! ");
}
final Boolean isDefaultAttribute = getIsDefaultAttribute(classType, IntrospectionModel.DEFAULT_ATTRIBUTE); final Boolean isDefaultAttribute = ReflectTools.getIsDefaultAttribute(classType, IntrospectionModel.DEFAULT_ATTRIBUTE);
final Boolean isDefaultManaged = getIsDefaultManaged(classType, IntrospectionModel.DEFAULT_MANAGED); final Boolean isDefaultManaged = ReflectTools.getIsDefaultManaged(classType, IntrospectionModel.DEFAULT_MANAGED);
final Boolean isDefaultOptional = getIsDefaultOptional(classType, IntrospectionModel.DEFAULT_OPTIONAL); final Boolean isDefaultOptional = ReflectTools.getIsDefaultOptional(classType, IntrospectionModel.DEFAULT_OPTIONAL);
final Boolean isDefaultCaseSensitive = getIsDefaultCaseSensitive(classType, IntrospectionModel.DEFAULT_CASE_SENSITIVE); final Boolean isDefaultCaseSensitive = ReflectTools.getIsDefaultCaseSensitive(classType, IntrospectionModel.DEFAULT_CASE_SENSITIVE);
Log.verbose("Introspect class: '" + classType.getCanonicalName() + "'"); Log.verbose("Introspect class: '" + classType.getCanonicalName() + "'");
final Constructor<?>[] constructors = this.classType.getConstructors(); final Constructor<?>[] constructors = this.classType.getConstructors();
Log.verbose(" Constructors: (" + constructors.length + ")"); Log.verbose(" Constructors: (" + constructors.length + ")");
@ -81,16 +86,113 @@ public class IntrospectionModelComplex extends IntrospectionModel {
emptyConstructorTmp = elem; emptyConstructorTmp = elem;
Log.verbose(" >>> " + elem.toGenericString()); Log.verbose(" >>> " + elem.toGenericString());
} else { } else {
String[] names = ReflectTools.getNames(elem, null);
if (names == null) {
// Search in the parameters ...
List<String> restoredElementNames = new ArrayList<>();
Parameter[] params = elem.getParameters();
for (int iii=1; iii<params.length; iii++) {
Parameter paramElem = params[iii];
String[] namesParam = ReflectTools.getNames(elem, paramElem, null);
if (namesParam == null) {
break;
}
if (namesParam.length != 1) {
throw new ExmlBuilderException("the @XmlName in constructor parameter must not exceed 1 element");
}
restoredElementNames.add(namesParam[0]);
}
if (restoredElementNames.size() == 0) {
Log.verbose(" - " + elem.toGenericString()); Log.verbose(" - " + elem.toGenericString());
Log.verbose(" ==> unmanaged");
} else if (restoredElementNames.size() != params.length-1) {
throw new ExmlBuilderException("the @XmlName in constructor parameter must set for every one");
} else {
this.constructors.add(new ConstructorModel(restoredElementNames.toArray(new String[restoredElementNames.size()]), elem));
}
} else {
if (elem.getParameterCount() != names.length+1) {
throw new ExmlBuilderException("Wrong number of parameter in constructor with ne number declared in the @XmlName");
}
this.constructors.add(new ConstructorModel(names, elem));
}
} }
} else if (elem.getParameterCount() == 0) { } else if (elem.getParameterCount() == 0) {
emptyConstructorTmp = elem; emptyConstructorTmp = elem;
Log.verbose(" >>> " + elem.toGenericString()); Log.verbose(" >>> " + elem.toGenericString());
} else { } else {
String[] names = ReflectTools.getNames(elem, null);
if (names == null) {
// Search in the parameters ...
List<String> restoredElementNames = new ArrayList<>();
Parameter[] params = elem.getParameters();
for (int iii=0; iii<params.length; iii++) {
Parameter paramElem = params[iii];
String[] namesParam = ReflectTools.getNames(elem, paramElem, null);
if (namesParam == null) {
break;
}
if (namesParam.length != 1) {
throw new ExmlBuilderException("the @XmlName in constructor parameter must not exceed 1 element");
}
restoredElementNames.add(namesParam[0]);
}
if (restoredElementNames.size() == 0) {
Log.verbose(" - " + elem.toGenericString()); Log.verbose(" - " + elem.toGenericString());
Log.verbose(" ==> unmanaged");
} else if (restoredElementNames.size() != params.length) {
throw new ExmlBuilderException("the @XmlName in constructor parameter must set for every one");
} else {
this.constructors.add(new ConstructorModel(restoredElementNames.toArray(new String[restoredElementNames.size()]), elem));
}
} else {
if (elem.getParameterCount() != names.length) {
throw new ExmlBuilderException("Wrong number of parameter in constructor with ne number declared in the @XmlName");
}
this.constructors.add(new ConstructorModel(names, elem));
}
} }
} }
this.constructorEmpty = emptyConstructorTmp; this.constructorEmpty = emptyConstructorTmp;
// Order the constructor from the bigger number of element to the lowest...
Collections.sort(this.constructors, new Comparator<ConstructorModel>() {
@Override
public
int compare(final ConstructorModel a, final ConstructorModel b) {
return a.values().length - b.values().length;
}
});
for (ConstructorModel elem : this.constructors) {
Log.verbose(" * " + elem.constructor().toGenericString());
StringBuilder tmpPrint = new StringBuilder(" ==> (");
if (this.isSubClass) {
tmpPrint.append("null, ");
}
for (int iii=0; iii<elem.values().length; iii++) {
if (iii != 0) {
tmpPrint.append(", ");
}
tmpPrint.append(elem.values()[iii]);
}
tmpPrint.append(")");
Log.verbose(tmpPrint.toString());
}
final List<String> recordAllPossibleValues = new ArrayList<>();
final List<String> recordAllPossibleValuesFiltered = new ArrayList<>();
if (isRecord) {
for (ConstructorModel elem : this.constructors) {
for (int iii=0; iii<elem.values().length; iii++) {
String tmpp = elem.values()[iii];
if (!recordAllPossibleValues.contains(tmpp)) {
recordAllPossibleValues.add(tmpp);
}
}
}
}
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) {
@ -102,12 +204,12 @@ public class IntrospectionModelComplex extends IntrospectionModel {
if (!Modifier.isPublic(elem.getModifiers())) { if (!Modifier.isPublic(elem.getModifiers())) {
continue; continue;
} }
final Boolean isAttribute = getIsAttribute(elem, isDefaultAttribute); final Boolean isAttribute = ReflectTools.getIsAttribute(elem, isDefaultAttribute);
final Boolean isManaged = getIsManaged(elem, isDefaultManaged); final Boolean isManaged = ReflectTools.getIsManaged(elem, isDefaultManaged);
final Boolean isOptionnal = getIsOptional(elem, isDefaultOptional); final Boolean isOptionnal = ReflectTools.getIsOptional(elem, isDefaultOptional);
final String[] names = getNames(elem, Tools.decapitalizeFirst(elem.getName())); final String[] names = ReflectTools.getNames(elem, Tools.decapitalizeFirst(elem.getName()));
final Boolean caseSensitive = getIsCaseSensitive(elem, isDefaultCaseSensitive); final Boolean caseSensitive = ReflectTools.getIsCaseSensitive(elem, isDefaultCaseSensitive);
final String listName = getListName(elem, null); final String listName = ReflectTools.getListName(elem, null);
// TODO check if property does not already exist ... // TODO check if property does not already exist ...
if (isManaged) { if (isManaged) {
if (isAttribute) { if (isAttribute) {
@ -140,6 +242,13 @@ public class IntrospectionModelComplex extends IntrospectionModel {
} }
return true; return true;
} }
if (isRecord) {
if (recordAllPossibleValues.contains(o.getName())) {
// This list is the real list of record members
recordAllPossibleValuesFiltered.add(o.getName());
return true;
}
} else {
if (o.getName().startsWith("get")) { if (o.getName().startsWith("get")) {
if (o.getParameterCount() != 0 || o.getReturnType() == void.class || o.getReturnType() == Boolean.class || o.getReturnType() == boolean.class) { if (o.getParameterCount() != 0 || o.getReturnType() == void.class || o.getReturnType() == Boolean.class || o.getReturnType() == boolean.class) {
return false; return false;
@ -164,7 +273,6 @@ public class IntrospectionModelComplex extends IntrospectionModel {
if (o.getName().charAt(3) >= 'A' && o.getName().charAt(3) <= 'Z') { if (o.getName().charAt(3) >= 'A' && o.getName().charAt(3) <= 'Z') {
return true; return true;
} }
return false; return false;
} }
if (o.getName().startsWith("is")) { if (o.getName().startsWith("is")) {
@ -178,9 +286,9 @@ public class IntrospectionModelComplex extends IntrospectionModel {
if (o.getName().charAt(2) >= 'A' && o.getName().charAt(2) <= 'Z') { if (o.getName().charAt(2) >= 'A' && o.getName().charAt(2) <= 'Z') {
return true; return true;
} }
return false; return false;
} }
}
return false; return false;
}).collect(Collectors.toList()); }).collect(Collectors.toList());
Log.verbose(" Methods: (" + methods.size() + ")"); Log.verbose(" Methods: (" + methods.size() + ")");
@ -198,9 +306,15 @@ public class IntrospectionModelComplex extends IntrospectionModel {
List<Method> methodsSet; List<Method> methodsSet;
List<Method> methodsIs; List<Method> methodsIs;
if (!Enum.class.isAssignableFrom(classType)) { if (!Enum.class.isAssignableFrom(classType)) {
if (isRecord) {
methodsGet = methods.stream().filter(o -> recordAllPossibleValues.contains(o.getName())).collect(Collectors.toList());
methodsSet = new ArrayList<>();
methodsIs = new ArrayList<>();
} else {
methodsGet = methods.stream().filter(o -> o.getName().startsWith("get")).collect(Collectors.toList()); methodsGet = methods.stream().filter(o -> o.getName().startsWith("get")).collect(Collectors.toList());
methodsSet = methods.stream().filter(o -> o.getName().startsWith("set")).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()); methodsIs = methods.stream().filter(o -> o.getName().startsWith("is")).collect(Collectors.toList());
}
} else { } else {
methodsGet = new ArrayList<>(); methodsGet = new ArrayList<>();
methodsSet = new ArrayList<>(); methodsSet = new ArrayList<>();
@ -225,11 +339,12 @@ public class IntrospectionModelComplex extends IntrospectionModel {
// associate methods by pair. // associate methods by pair.
final List<OrderData> elements = new ArrayList<>(); final List<OrderData> elements = new ArrayList<>();
for (final Method method : methodsGet) { for (final Method method : methodsGet) {
final String name = method.getName().substring(3); final String name = isRecord?method.getName():method.getName().substring(3);
final OrderData tmp = new OrderData(name); final OrderData tmp = new OrderData(name);
tmp.getter = method; tmp.getter = method;
elements.add(tmp); elements.add(tmp);
} }
if (!isRecord) {
for (final Method method : methodsIs) { for (final Method method : methodsIs) {
final String name = method.getName().substring(2); final String name = method.getName().substring(2);
for (final OrderData elem : elements) { for (final OrderData elem : elements) {
@ -251,26 +366,6 @@ public class IntrospectionModelComplex extends IntrospectionModel {
break; break;
} }
} }
/*
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());
}
}
}
for (int iii=0; iii<tmppp.length; iii++) {
Log.warning(" -- " + tmppp[iii].getCanonicalName());
}
}
*/
if (tmp == null) { if (tmp == null) {
tmp = new OrderData(name); tmp = new OrderData(name);
tmp.setter = method; tmp.setter = method;
@ -279,49 +374,53 @@ public class IntrospectionModelComplex extends IntrospectionModel {
tmp.setter = method; tmp.setter = method;
} }
} }
}
// Add it in the engine // Add it in the engine
for (final OrderData elem : elements) { for (final OrderData elem : elements) {
Log.info("find methode : '" + elem.name + "' :"); Log.info("find methode : '" + elem.name + "' :");
if (elem.setter != null && elem.getter != null) { if (elem.setter != null && elem.getter != null) {
Log.info(" setter: " + elem.setter.toGenericString()); Log.info(" setter: " + elem.setter.toGenericString());
if (recordAllPossibleValuesFiltered.contains(elem.name)) {
Log.info(" and by constructor");
}
Log.info(" getter: " + elem.getter.toGenericString()); Log.info(" getter: " + elem.getter.toGenericString());
final Boolean isAttributeSet = getIsAttribute(elem.setter, null); final Boolean isAttributeSet = ReflectTools.getIsAttribute(elem.setter, null);
final Boolean isAttributeGet = getIsAttribute(elem.getter, null); final Boolean isAttributeGet = ReflectTools.getIsAttribute(elem.getter, null);
if (isAttributeSet != null && isAttributeGet != null && isAttributeSet != isAttributeGet) { if (isAttributeSet != null && isAttributeGet != null && isAttributeSet != isAttributeGet) {
throw new Exception("Can net set oposite information on getter and setter"); throw new Exception("Can net set oposite information on getter and setter");
} }
final Boolean isAttribute = isAttributeSet != null ? isAttributeSet : isAttributeGet != null ? isAttributeGet : isDefaultAttribute; final Boolean isAttribute = isAttributeSet != null ? isAttributeSet : isAttributeGet != null ? isAttributeGet : isDefaultAttribute;
final Boolean isManagedSet = getIsManaged(elem.setter, null); final Boolean isManagedSet = ReflectTools.getIsManaged(elem.setter, null);
final Boolean isManagedGet = getIsManaged(elem.getter, null); final Boolean isManagedGet = ReflectTools.getIsManaged(elem.getter, null);
if (isManagedSet != null && isManagedGet != null && isManagedSet != isManagedGet) { if (isManagedSet != null && isManagedGet != null && isManagedSet != isManagedGet) {
throw new Exception("Can net set oposite information on getter and setter"); throw new Exception("Can net set oposite information on getter and setter");
} }
final Boolean isManaged = isManagedSet != null ? isManagedSet : isManagedGet != null ? isManagedGet : isDefaultManaged; final Boolean isManaged = isManagedSet != null ? isManagedSet : isManagedGet != null ? isManagedGet : isDefaultManaged;
final Boolean isOptionnalSet = getIsOptional(elem.setter, null); final Boolean isOptionnalSet = ReflectTools.getIsOptional(elem.setter, null);
final Boolean isOptionnalGet = getIsOptional(elem.getter, null); final Boolean isOptionnalGet = ReflectTools.getIsOptional(elem.getter, null);
if (isOptionnalSet != null && isOptionnalGet != null && isOptionnalSet != isOptionnalGet) { if (isOptionnalSet != null && isOptionnalGet != null && isOptionnalSet != isOptionnalGet) {
throw new Exception("Can net set oposite information on getter and setter"); throw new Exception("Can net set oposite information on getter and setter");
} }
final Boolean isOptional = isOptionnalSet != null ? isOptionnalSet : isOptionnalGet != null ? isOptionnalGet : isDefaultOptional; final Boolean isOptional = isOptionnalSet != null ? isOptionnalSet : isOptionnalGet != null ? isOptionnalGet : isDefaultOptional;
final Boolean caseSensitiveSet = getIsCaseSensitive(elem.setter, null); final Boolean caseSensitiveSet = ReflectTools.getIsCaseSensitive(elem.setter, null);
final Boolean caseSensitiveGet = getIsCaseSensitive(elem.getter, null); final Boolean caseSensitiveGet = ReflectTools.getIsCaseSensitive(elem.getter, null);
if (caseSensitiveSet != null && caseSensitiveGet != null && caseSensitiveSet != caseSensitiveGet) { if (caseSensitiveSet != null && caseSensitiveGet != null && caseSensitiveSet != caseSensitiveGet) {
throw new Exception("Can net set oposite information on getter and setter"); throw new Exception("Can net set oposite information on getter and setter");
} }
final Boolean isCaseSensitive = caseSensitiveSet != null ? caseSensitiveSet : caseSensitiveGet != null ? caseSensitiveGet : isDefaultCaseSensitive; final Boolean isCaseSensitive = caseSensitiveSet != null ? caseSensitiveSet : caseSensitiveGet != null ? caseSensitiveGet : isDefaultCaseSensitive;
final String[] namesSet = getNames(elem.setter, null); final String[] namesSet = ReflectTools.getNames(elem.setter, null);
final String[] namesGet = getNames(elem.getter, null); final String[] namesGet = ReflectTools.getNames(elem.getter, null);
if (namesSet != null && namesGet != null && namesSet.equals(namesGet)) { if (namesSet != null && namesGet != null && namesSet.equals(namesGet)) {
throw new Exception("Can net set oposite information on getter and setter"); throw new Exception("Can net set oposite information on getter and setter");
} }
final String[] names = namesSet != null ? namesSet : namesGet != null ? namesGet : new String[] { Tools.decapitalizeFirst(elem.name) }; final String[] names = namesSet != null ? namesSet : namesGet != null ? namesGet : new String[] { Tools.decapitalizeFirst(elem.name) };
final String listNameSet = getListName(elem.setter, null); final String listNameSet = ReflectTools.getListName(elem.setter, null);
final String listNameGet = getListName(elem.getter, null); final String listNameGet = ReflectTools.getListName(elem.getter, null);
final String listName = listNameSet != null? listNameSet: listNameGet; final String listName = listNameSet != null? listNameSet: listNameGet;
if (isAttribute) { if (isAttribute) {
this.attributes.add(new IntrospectionPropertyMethod(elem.setter, elem.getter, names, listName, isCaseSensitive, isOptional)); this.attributes.add(new IntrospectionPropertyMethod(elem.setter, elem.getter, names, listName, isCaseSensitive, isOptional));
@ -337,31 +436,35 @@ public class IntrospectionModelComplex extends IntrospectionModel {
Boolean isAttribute = isDefaultAttribute; Boolean isAttribute = isDefaultAttribute;
if (elem.setter != null) { if (elem.setter != null) {
Log.info(" setter: " + elem.setter.toGenericString()); Log.info(" setter: " + elem.setter.toGenericString());
isAttribute = getIsAttribute(elem.setter, isDefaultAttribute); isAttribute = ReflectTools.getIsAttribute(elem.setter, isDefaultAttribute);
isManaged = getIsManaged(elem.setter, isDefaultManaged); isManaged = ReflectTools.getIsManaged(elem.setter, isDefaultManaged);
isOptionnal = getIsOptional(elem.setter, isDefaultOptional); isOptionnal = ReflectTools.getIsOptional(elem.setter, isDefaultOptional);
names = getNames(elem.setter, Tools.decapitalizeFirst(elem.name)); names = ReflectTools.getNames(elem.setter, Tools.decapitalizeFirst(elem.name));
isCaseSensitive = getIsCaseSensitive(elem.setter, isDefaultCaseSensitive); isCaseSensitive = ReflectTools.getIsCaseSensitive(elem.setter, isDefaultCaseSensitive);
listName= getListName(elem.setter, null); listName= ReflectTools.getListName(elem.setter, null);
} else { } else {
Log.info(" setter: null"); Log.info(" setter: null");
} }
if (elem.getter != null) { if (elem.getter != null) {
Log.info(" getter: " + elem.getter.toGenericString()); Log.info(" getter: " + elem.getter.toGenericString());
isAttribute = getIsAttribute(elem.getter, isDefaultAttribute); isAttribute = ReflectTools.getIsAttribute(elem.getter, isDefaultAttribute);
isManaged = getIsManaged(elem.getter, isDefaultManaged); isManaged = ReflectTools.getIsManaged(elem.getter, isDefaultManaged);
isOptionnal = getIsOptional(elem.getter, isDefaultOptional); isOptionnal = ReflectTools.getIsOptional(elem.getter, isDefaultOptional);
names = getNames(elem.getter, Tools.decapitalizeFirst(elem.name)); names = ReflectTools.getNames(elem.getter, Tools.decapitalizeFirst(elem.name));
isCaseSensitive = getIsCaseSensitive(elem.getter, isDefaultCaseSensitive); isCaseSensitive = ReflectTools.getIsCaseSensitive(elem.getter, isDefaultCaseSensitive);
listName= getListName(elem.getter, null); listName= ReflectTools.getListName(elem.getter, null);
} else { } else {
Log.info(" getter: null"); Log.info(" getter: null");
} }
if (isManaged) { if (isManaged) {
if (isAttribute) { if (isAttribute) {
this.attributes.add(new IntrospectionPropertyMethod(elem.setter, elem.getter, names, listName, isCaseSensitive, isOptionnal)); IntrospectionPropertyMethod tmpp = new IntrospectionPropertyMethod(elem.setter, elem.getter, names, listName, isCaseSensitive, isOptionnal);
tmpp.setCanBeSetByConstructor(recordAllPossibleValuesFiltered.contains(elem.name));
this.attributes.add(tmpp);
} else { } else {
this.nodes.add(new IntrospectionPropertyMethod(elem.setter, elem.getter, names, listName, isCaseSensitive, isOptionnal)); IntrospectionPropertyMethod tmpp = new IntrospectionPropertyMethod(elem.setter, elem.getter, names, listName, isCaseSensitive, isOptionnal);
tmpp.setCanBeSetByConstructor(recordAllPossibleValuesFiltered.contains(elem.name));
this.nodes.add(tmpp);
} }
} }
} }
@ -374,7 +477,66 @@ public class IntrospectionModelComplex extends IntrospectionModel {
@Override @Override
public Object createObject(final Map<String, Object> properties, final Map<String, List<Object>> nodes) throws ExmlBuilderException { public Object createObject(final Map<String, Object> properties, final Map<String, List<Object>> nodes) throws ExmlBuilderException {
Object tmp; Object tmp = null;
// STEP 1: try to create the object with provided parameter (if a constructor exist....)
if (!this.constructors.isEmpty()) {
// 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;
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) {
valueToInject = tmppp.get(0);
}
}
if (valueToInject == null) {
inputs = null;
break;
}
inputs[iii+offset] = valueToInject;
}
if (inputs != null) {
// here we find our constructor...
try {
switch(inputs.length) {
case 0: tmp = elem.constructor().newInstance(); break;
case 1: tmp = elem.constructor().newInstance(inputs[0]); break;
case 2: tmp = elem.constructor().newInstance(inputs[0],inputs[1]); break;
case 3: tmp = elem.constructor().newInstance(inputs[0],inputs[1],inputs[2]); break;
case 4: tmp = elem.constructor().newInstance(inputs[0],inputs[1],inputs[2],inputs[3]); break;
case 5: tmp = elem.constructor().newInstance(inputs[0],inputs[1],inputs[2],inputs[3],inputs[4]); break;
case 6: tmp = elem.constructor().newInstance(inputs[0],inputs[1],inputs[2],inputs[3],inputs[4],inputs[5]); break;
case 7: tmp = elem.constructor().newInstance(inputs[0],inputs[1],inputs[2],inputs[3],inputs[4],inputs[5],inputs[6]); break;
case 8: tmp = elem.constructor().newInstance(inputs[0],inputs[1],inputs[2],inputs[3],inputs[4],inputs[5],inputs[6],inputs[7]); break;
case 9: tmp = elem.constructor().newInstance(inputs[0],inputs[1],inputs[2],inputs[3],inputs[4],inputs[5],inputs[6],inputs[7],inputs[8]); break;
case 10: tmp = elem.constructor().newInstance(inputs[0],inputs[1],inputs[2],inputs[3],inputs[4],inputs[5],inputs[6],inputs[7],inputs[8],inputs[9]); break;
case 11: tmp = elem.constructor().newInstance(inputs[0],inputs[1],inputs[2],inputs[3],inputs[4],inputs[5],inputs[6],inputs[7],inputs[8],inputs[9],inputs[10]); break;
case 12: tmp = elem.constructor().newInstance(inputs[0],inputs[1],inputs[2],inputs[3],inputs[4],inputs[5],inputs[6],inputs[7],inputs[8],inputs[9],inputs[10],inputs[11]); break;
case 13: tmp = elem.constructor().newInstance(inputs[0],inputs[1],inputs[2],inputs[3],inputs[4],inputs[5],inputs[6],inputs[7],inputs[8],inputs[9],inputs[10],inputs[11],inputs[12]); break;
default:
throw new ExmlBuilderException("to much parameter in the constructor... " + inputs.length);
}
//tmp = elem.constructor().newInstance(inputs);
} catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
throw new ExmlBuilderException("Error when creating the Object ..." + this.classType.getCanonicalName());
}
// Remove all previously added parameters
for (int iii=0; iii<elem.values().length; iii++) {
properties.remove(elem.values()[iii]);
nodes.remove(elem.values()[iii]);
}
break;
}
}
}
// STEP 2: If we do not create the object ==> try with empty constructor...
if (tmp == null) {
if (this.constructorEmpty == null) { if (this.constructorEmpty == null) {
throw new ExmlBuilderException("No constructor accessible for class: " + this.classType.getCanonicalName()); throw new ExmlBuilderException("No constructor accessible for class: " + this.classType.getCanonicalName());
} }
@ -390,6 +552,8 @@ public class IntrospectionModelComplex extends IntrospectionModel {
e.printStackTrace(); e.printStackTrace();
return null; return null;
} }
}
// STEP 3: set the rest if the parameters...
for (Entry<String, Object> elem : properties.entrySet()) { for (Entry<String, Object> elem : properties.entrySet()) {
setValue(tmp, elem.getKey(), elem.getValue()); setValue(tmp, elem.getKey(), elem.getValue());
} }
@ -429,224 +593,6 @@ public class IntrospectionModelComplex extends IntrospectionModel {
return null; return null;
} }
protected Boolean getIsCaseSensitive(final Field element, final Boolean defaultValue) throws ExmlBuilderException {
final Annotation[] annotation = element.getDeclaredAnnotationsByType(XmlCaseSensitive.class);
if (annotation.length == 0) {
return defaultValue;
}
if (annotation.length > 1) {
throw new ExmlBuilderException("Must not have more that ");
}
return ((XmlCaseSensitive) annotation[0]).value();
}
protected Boolean getIsCaseSensitive(final Method element, final Boolean defaultValue) throws ExmlBuilderException {
final Annotation[] annotation = element.getDeclaredAnnotationsByType(XmlCaseSensitive.class);
if (annotation.length == 0) {
return defaultValue;
}
if (annotation.length > 1) {
throw new ExmlBuilderException("Must not have more that ");
}
return ((XmlCaseSensitive) annotation[0]).value();
}
private Boolean getIsDefaultCaseSensitive(final Class<?> classType, final Boolean defaultValue) throws ExmlBuilderException {
final Annotation[] annotation = classType.getDeclaredAnnotationsByType(XmlDefaultCaseSensitive.class);
if (annotation.length == 0) {
return defaultValue;
}
if (annotation.length > 1) {
throw new ExmlBuilderException("Must not have more that ");
}
return ((XmlDefaultCaseSensitive) annotation[0]).value();
}
private Boolean getIsDefaultAttribute(final Class<?> classType, final Boolean defaultValue) throws ExmlBuilderException {
final Annotation[] annotation = classType.getDeclaredAnnotationsByType(XmlDefaultAttibute.class);
if (annotation.length == 0) {
return defaultValue;
}
if (annotation.length > 1) {
throw new ExmlBuilderException("Must not have more that ");
}
return ((XmlDefaultAttibute) annotation[0]).value();
}
private Boolean getIsDefaultManaged(final Class<?> classType, final Boolean defaultValue) throws ExmlBuilderException {
final Annotation[] annotation = classType.getDeclaredAnnotationsByType(XmlDefaultManaged.class);
if (annotation.length == 0) {
return defaultValue;
}
if (annotation.length > 1) {
throw new ExmlBuilderException("Must not have more that ");
}
return ((XmlDefaultManaged) annotation[0]).value();
}
private Boolean getIsDefaultOptional(final Class<?> classType, final Boolean defaultValue) throws ExmlBuilderException {
final Annotation[] annotation = classType.getDeclaredAnnotationsByType(XmlDefaultOptional.class);
if (annotation.length == 0) {
return defaultValue;
}
if (annotation.length > 1) {
throw new ExmlBuilderException("Must not have more that ");
}
return ((XmlDefaultOptional) annotation[0]).value();
}
protected Boolean getIsAttribute(final Field element, final Boolean parentValue) throws ExmlBuilderException {
final Annotation[] annotation = element.getDeclaredAnnotationsByType(XmlAttribute.class);
if (annotation.length == 0) {
return parentValue;
}
if (annotation.length > 1) {
throw new ExmlBuilderException("Must not have more that ");
}
return ((XmlAttribute) annotation[0]).value();
}
protected Boolean getIsAttribute(final Method element, final Boolean parentValue) throws ExmlBuilderException {
final Annotation[] annotation = element.getDeclaredAnnotationsByType(XmlAttribute.class);
if (annotation.length == 0) {
return parentValue;
}
if (annotation.length > 1) {
throw new ExmlBuilderException("Must not have more that ");
}
return ((XmlAttribute) annotation[0]).value();
}
protected Boolean getIsManaged(final Field element, final Boolean parentValue) throws ExmlBuilderException {
final Annotation[] annotation = element.getDeclaredAnnotationsByType(XmlManaged.class);
if (annotation.length == 0) {
return parentValue;
}
if (annotation.length > 1) {
throw new ExmlBuilderException("Must not have more that ");
}
return ((XmlManaged) annotation[0]).value();
}
protected Boolean getIsManaged(final Method element, final Boolean parentValue) throws ExmlBuilderException {
final Annotation[] annotation = element.getDeclaredAnnotationsByType(XmlManaged.class);
if (annotation.length == 0) {
return parentValue;
}
if (annotation.length > 1) {
throw new ExmlBuilderException("Must not have more that ");
}
return ((XmlManaged) annotation[0]).value();
}
protected Boolean getIsOptional(final Field element, final Boolean parentValue) throws Exception {
final Annotation[] annotation = element.getDeclaredAnnotationsByType(XmlOptional.class);
if (annotation.length == 0) {
return parentValue;
}
if (annotation.length > 1) {
throw new Exception("Must not have more that ");
}
return ((XmlOptional) annotation[0]).value();
}
protected Boolean getIsOptional(final Method element, final Boolean parentValue) throws Exception {
final Annotation[] annotation = element.getDeclaredAnnotationsByType(XmlOptional.class);
if (annotation.length == 0) {
return parentValue;
}
if (annotation.length > 1) {
throw new Exception("Must not have more that ");
}
return ((XmlOptional) annotation[0]).value();
}
protected String[] getNames(final Field element, final String defaultValue) throws Exception {
final Annotation[] annotation = element.getDeclaredAnnotationsByType(XmlName.class);
if (annotation.length == 0) {
if (defaultValue == null) {
return null;
}
return new String[] { defaultValue };
}
if (annotation.length > 1) {
throw new Exception("Must not have more that ");
}
final String[] tmp = ((XmlName) annotation[0]).value();
if (tmp == null) {
throw new Exception("Set null value in decorator @XmlName is not availlable on: " + element.toGenericString());
}
if (tmp.length == 0) {
throw new Exception("Set empty list value in decorator @XmlName is not availlable on: " + element.toGenericString());
}
for (final String elem : tmp) {
if (elem == null) {
throw new Exception("Set null String in list of value in decorator @XmlName is not availlable on: " + element.toGenericString());
}
if (elem.isEmpty()) {
throw new Exception("Set empty String in list of value in decorator @XmlName is not availlable on: " + element.toGenericString());
}
}
return tmp;
}
protected String[] getNames(final Method element, final String defaultValue) throws Exception {
final Annotation[] annotation = element.getDeclaredAnnotationsByType(XmlName.class);
if (annotation.length == 0) {
if (defaultValue == null) {
return null;
}
return new String[] { defaultValue };
}
if (annotation.length > 1) {
throw new Exception("Must not have more that ");
}
final String[] tmp = ((XmlName) annotation[0]).value();
if (tmp == null) {
throw new Exception("Set null value in decorator @XmlName is not availlable on: " + element.toGenericString());
}
if (tmp.length == 0) {
throw new Exception("Set empty list value in decorator @XmlName is not availlable on: " + element.toGenericString());
}
for (final String elem : tmp) {
if (elem == null) {
throw new Exception("Set null String in list of value in decorator @XmlName is not availlable on: " + element.toGenericString());
}
if (elem.isEmpty()) {
throw new Exception("Set empty String in list of value in decorator @XmlName is not availlable on: " + element.toGenericString());
}
}
return tmp;
}
protected String getListName(final Field element, final String defaultValue) throws Exception {
final Annotation[] annotation = element.getDeclaredAnnotationsByType(XmlList.class);
if (annotation.length == 0) {
return defaultValue;
}
if (annotation.length > 1) {
throw new Exception("Must not have more that ");
}
final String tmp = ((XmlList) annotation[0]).value();
if (tmp == null) {
throw new Exception("Set null value in decorator @XmlList is not availlable on: " + element.toGenericString());
}
return tmp;
}
protected String getListName(final Method element, final String defaultValue) throws Exception {
final Annotation[] annotation = element.getDeclaredAnnotationsByType(XmlList.class);
if (annotation.length == 0) {
return defaultValue;
}
if (annotation.length > 1) {
throw new Exception("Must not have more that ");
}
final String tmp = ((XmlList) annotation[0]).value();
if (tmp == null) {
throw new Exception("Set null value in decorator @XmlList is not availlable on: " + element.toGenericString());
}
return tmp;
}
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private <T> T[] autoCast(final Class<T> clazz, final List<Object> data) { private <T> T[] autoCast(final Class<T> clazz, final List<Object> data) {
T[] out = (T[]) java.lang.reflect.Array.newInstance(clazz, data.size());// T[data.size()]; T[] out = (T[]) java.lang.reflect.Array.newInstance(clazz, data.size());// T[data.size()];

View File

@ -17,7 +17,15 @@ public abstract class IntrospectionProperty {
public String getListName() { public String getListName() {
return this.listName; return this.listName;
} }
protected boolean canBeSetByConstructor = false;
public boolean isCanBeSetByConstructor() {
return this.canBeSetByConstructor;
}
public void setCanBeSetByConstructor(final boolean canBeSetByConstructor) {
this.canBeSetByConstructor = canBeSetByConstructor;
}
protected final Class<?> type; protected final Class<?> type;
protected final Class<?> subType; protected final Class<?> subType;

View File

@ -1,6 +1,7 @@
package org.atriasoft.exml.builder; package org.atriasoft.exml.builder;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType; import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type; import java.lang.reflect.Type;
@ -8,6 +9,7 @@ import org.atriasoft.exml.exception.ExmlBuilderException;
public class IntrospectionPropertyField extends IntrospectionProperty { public class IntrospectionPropertyField extends IntrospectionProperty {
private final Field fieldDescription; private final Field fieldDescription;
private final boolean finalValue;
private static Class<?>[] getTypeField(final Field fieldDescription) { private static Class<?>[] getTypeField(final Field fieldDescription) {
@ -31,6 +33,7 @@ public class IntrospectionPropertyField extends IntrospectionProperty {
public IntrospectionPropertyField(final Field fieldDescription, final String[] names, final String listName, final Boolean caseSensitive, final Boolean isOptionnal) { public IntrospectionPropertyField(final Field fieldDescription, final String[] names, final String listName, final Boolean caseSensitive, final Boolean isOptionnal) {
super(IntrospectionPropertyField.getTypeField(fieldDescription), names, listName, caseSensitive, isOptionnal); super(IntrospectionPropertyField.getTypeField(fieldDescription), names, listName, caseSensitive, isOptionnal);
this.fieldDescription = fieldDescription; this.fieldDescription = fieldDescription;
this.finalValue = Modifier.isFinal(fieldDescription.getModifiers());
} }
@Override @Override
@ -40,7 +43,7 @@ public class IntrospectionPropertyField extends IntrospectionProperty {
@Override @Override
public boolean canSetValue() { public boolean canSetValue() {
return true; return this.canBeSetByConstructor || !this.finalValue;
} }
@Override @Override
public Object getValue(final Object object) throws ExmlBuilderException { public Object getValue(final Object object) throws ExmlBuilderException {

View File

@ -74,7 +74,7 @@ public class IntrospectionPropertyMethod extends IntrospectionProperty {
@Override @Override
public boolean canSetValue() { public boolean canSetValue() {
return this.setter != null; return this.canBeSetByConstructor || this.setter != null;
} }
@Override @Override

View File

@ -0,0 +1,299 @@
package org.atriasoft.exml.reflect;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
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.XmlDefaultManaged;
import org.atriasoft.exml.annotation.XmlDefaultOptional;
import org.atriasoft.exml.annotation.XmlList;
import org.atriasoft.exml.annotation.XmlManaged;
import org.atriasoft.exml.annotation.XmlName;
import org.atriasoft.exml.annotation.XmlOptional;
import org.atriasoft.exml.exception.ExmlBuilderException;
public class ReflectTools {
private ReflectTools() {}
public static Boolean getIsCaseSensitive(final Field element, final Boolean defaultValue) throws ExmlBuilderException {
final Annotation[] annotation = element.getDeclaredAnnotationsByType(XmlCaseSensitive.class);
if (annotation.length == 0) {
return defaultValue;
}
if (annotation.length > 1) {
throw new ExmlBuilderException("Must not have more that ");
}
return ((XmlCaseSensitive) annotation[0]).value();
}
public static Boolean getIsCaseSensitive(final Method element, final Boolean defaultValue) throws ExmlBuilderException {
final Annotation[] annotation = element.getDeclaredAnnotationsByType(XmlCaseSensitive.class);
if (annotation.length == 0) {
return defaultValue;
}
if (annotation.length > 1) {
throw new ExmlBuilderException("Must not have more that ");
}
return ((XmlCaseSensitive) annotation[0]).value();
}
public static Boolean getIsDefaultCaseSensitive(final Class<?> classType, final Boolean defaultValue) throws ExmlBuilderException {
final Annotation[] annotation = classType.getDeclaredAnnotationsByType(XmlDefaultCaseSensitive.class);
if (annotation.length == 0) {
return defaultValue;
}
if (annotation.length > 1) {
throw new ExmlBuilderException("Must not have more that ");
}
return ((XmlDefaultCaseSensitive) annotation[0]).value();
}
public static Boolean getIsDefaultAttribute(final Class<?> classType, final Boolean defaultValue) throws ExmlBuilderException {
final Annotation[] annotation = classType.getDeclaredAnnotationsByType(XmlDefaultAttibute.class);
if (annotation.length == 0) {
return defaultValue;
}
if (annotation.length > 1) {
throw new ExmlBuilderException("Must not have more that ");
}
return ((XmlDefaultAttibute) annotation[0]).value();
}
public static Boolean getIsDefaultManaged(final Class<?> classType, final Boolean defaultValue) throws ExmlBuilderException {
final Annotation[] annotation = classType.getDeclaredAnnotationsByType(XmlDefaultManaged.class);
if (annotation.length == 0) {
return defaultValue;
}
if (annotation.length > 1) {
throw new ExmlBuilderException("Must not have more that ");
}
return ((XmlDefaultManaged) annotation[0]).value();
}
public static Boolean getIsDefaultOptional(final Class<?> classType, final Boolean defaultValue) throws ExmlBuilderException {
final Annotation[] annotation = classType.getDeclaredAnnotationsByType(XmlDefaultOptional.class);
if (annotation.length == 0) {
return defaultValue;
}
if (annotation.length > 1) {
throw new ExmlBuilderException("Must not have more that ");
}
return ((XmlDefaultOptional) annotation[0]).value();
}
public static Boolean getIsAttribute(final Field element, final Boolean parentValue) throws ExmlBuilderException {
final Annotation[] annotation = element.getDeclaredAnnotationsByType(XmlAttribute.class);
if (annotation.length == 0) {
return parentValue;
}
if (annotation.length > 1) {
throw new ExmlBuilderException("Must not have more that ");
}
return ((XmlAttribute) annotation[0]).value();
}
public static Boolean getIsAttribute(final Method element, final Boolean parentValue) throws ExmlBuilderException {
final Annotation[] annotation = element.getDeclaredAnnotationsByType(XmlAttribute.class);
if (annotation.length == 0) {
return parentValue;
}
if (annotation.length > 1) {
throw new ExmlBuilderException("Must not have more that ");
}
return ((XmlAttribute) annotation[0]).value();
}
public static Boolean getIsManaged(final Field element, final Boolean parentValue) throws ExmlBuilderException {
final Annotation[] annotation = element.getDeclaredAnnotationsByType(XmlManaged.class);
if (annotation.length == 0) {
return parentValue;
}
if (annotation.length > 1) {
throw new ExmlBuilderException("Must not have more that ");
}
return ((XmlManaged) annotation[0]).value();
}
public static Boolean getIsManaged(final Method element, final Boolean parentValue) throws ExmlBuilderException {
final Annotation[] annotation = element.getDeclaredAnnotationsByType(XmlManaged.class);
if (annotation.length == 0) {
return parentValue;
}
if (annotation.length > 1) {
throw new ExmlBuilderException("Must not have more that ");
}
return ((XmlManaged) annotation[0]).value();
}
public static Boolean getIsOptional(final Field element, final Boolean parentValue) throws Exception {
final Annotation[] annotation = element.getDeclaredAnnotationsByType(XmlOptional.class);
if (annotation.length == 0) {
return parentValue;
}
if (annotation.length > 1) {
throw new Exception("Must not have more that ");
}
return ((XmlOptional) annotation[0]).value();
}
public static Boolean getIsOptional(final Method element, final Boolean parentValue) throws Exception {
final Annotation[] annotation = element.getDeclaredAnnotationsByType(XmlOptional.class);
if (annotation.length == 0) {
return parentValue;
}
if (annotation.length > 1) {
throw new Exception("Must not have more that ");
}
return ((XmlOptional) annotation[0]).value();
}
public static String[] getNames(final Field element, final String defaultValue) throws Exception {
final Annotation[] annotation = element.getDeclaredAnnotationsByType(XmlName.class);
if (annotation.length == 0) {
if (defaultValue == null) {
return null;
}
return new String[] { defaultValue };
}
if (annotation.length > 1) {
throw new Exception("Must not have more that ");
}
final String[] tmp = ((XmlName) annotation[0]).value();
if (tmp == null) {
throw new Exception("Set null value in decorator @XmlName is not availlable on: " + element.toGenericString());
}
if (tmp.length == 0) {
throw new Exception("Set empty list value in decorator @XmlName is not availlable on: " + element.toGenericString());
}
for (final String elem : tmp) {
if (elem == null) {
throw new Exception("Set null String in list of value in decorator @XmlName is not availlable on: " + element.toGenericString());
}
if (elem.isEmpty()) {
throw new Exception("Set empty String in list of value in decorator @XmlName is not availlable on: " + element.toGenericString());
}
}
return tmp;
}
public static String[] getNames(final Method element, final String defaultValue) throws Exception {
final Annotation[] annotation = element.getDeclaredAnnotationsByType(XmlName.class);
if (annotation.length == 0) {
if (defaultValue == null) {
return null;
}
return new String[] { defaultValue };
}
if (annotation.length > 1) {
throw new Exception("Must not have more that ");
}
final String[] tmp = ((XmlName) annotation[0]).value();
if (tmp == null) {
throw new Exception("Set null value in decorator @XmlName is not availlable on: " + element.toGenericString());
}
if (tmp.length == 0) {
throw new Exception("Set empty list value in decorator @XmlName is not availlable on: " + element.toGenericString());
}
for (final String elem : tmp) {
if (elem == null) {
throw new Exception("Set null String in list of value in decorator @XmlName is not availlable on: " + element.toGenericString());
}
if (elem.isEmpty()) {
throw new Exception("Set empty String in list of value in decorator @XmlName is not availlable on: " + element.toGenericString());
}
}
return tmp;
}
public static String[] getNames(final Constructor<?> element, final String defaultValue) throws Exception {
final Annotation[] annotation = element.getDeclaredAnnotationsByType(XmlName.class);
if (annotation.length == 0) {
if (defaultValue == null) {
return null;
}
return new String[] { defaultValue };
}
if (annotation.length > 1) {
throw new Exception("Must not have more that ");
}
final String[] tmp = ((XmlName) annotation[0]).value();
if (tmp == null) {
throw new Exception("Set null value in decorator @XmlName is not availlable on: " + element.toGenericString());
}
if (tmp.length == 0) {
throw new Exception("Set empty list value in decorator @XmlName is not availlable on: " + element.toGenericString());
}
for (final String elem : tmp) {
if (elem == null) {
throw new Exception("Set null String in list of value in decorator @XmlName is not availlable on: " + element.toGenericString());
}
if (elem.isEmpty()) {
throw new Exception("Set empty String in list of value in decorator @XmlName is not availlable on: " + element.toGenericString());
}
}
return tmp;
}
public static String[] getNames(final Constructor<?> constructor, final Parameter element, final String defaultValue) throws Exception {
final Annotation[] annotation = element.getDeclaredAnnotationsByType(XmlName.class);
if (annotation.length == 0) {
if (defaultValue == null) {
return null;
}
return new String[] { defaultValue };
}
if (annotation.length > 1) {
throw new Exception("Must not have more that ");
}
final String[] tmp = ((XmlName) annotation[0]).value();
if (tmp == null) {
throw new Exception("Set null value in decorator @XmlName is not availlable on: " + constructor.toGenericString());
}
if (tmp.length == 0) {
throw new Exception("Set empty list value in decorator @XmlName is not availlable on: " + constructor.toGenericString());
}
for (final String elem : tmp) {
if (elem == null) {
throw new Exception("Set null String in list of value in decorator @XmlName is not availlable on: " + constructor.toGenericString());
}
if (elem.isEmpty()) {
throw new Exception("Set empty String in list of value in decorator @XmlName is not availlable on: " + constructor.toGenericString());
}
}
return tmp;
}
public static String getListName(final Field element, final String defaultValue) throws Exception {
final Annotation[] annotation = element.getDeclaredAnnotationsByType(XmlList.class);
if (annotation.length == 0) {
return defaultValue;
}
if (annotation.length > 1) {
throw new Exception("Must not have more that ");
}
final String tmp = ((XmlList) annotation[0]).value();
if (tmp == null) {
throw new Exception("Set null value in decorator @XmlList is not availlable on: " + element.toGenericString());
}
return tmp;
}
public static String getListName(final Method element, final String defaultValue) throws Exception {
final Annotation[] annotation = element.getDeclaredAnnotationsByType(XmlList.class);
if (annotation.length == 0) {
return defaultValue;
}
if (annotation.length > 1) {
throw new Exception("Must not have more that ");
}
final String tmp = ((XmlList) annotation[0]).value();
if (tmp == null) {
throw new Exception("Set null value in decorator @XmlList is not availlable on: " + element.toGenericString());
}
return tmp;
}
}

View File

@ -7,6 +7,7 @@ package test.atriasoft.exml;
import org.atriasoft.exml.Exml; import org.atriasoft.exml.Exml;
import org.atriasoft.exml.annotation.XmlAttribute; import org.atriasoft.exml.annotation.XmlAttribute;
import org.atriasoft.exml.annotation.XmlName;
import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeAll;
@ -45,5 +46,55 @@ public class ExmlTestIntrospectionObjectConstructor {
Assertions.assertEquals(18523.0f, root.valueB); Assertions.assertEquals(18523.0f, root.valueB);
} }
public class TestConstructorSpecificParameter {
@XmlAttribute
public Integer valueA;
public double valueB;
public TestConstructorSpecificParameter(@XmlName("valueA") final Integer valueA, @XmlName("valueB") final double valueB) {
this.valueA = valueA;
this.valueB = valueB;
}
}
@Test
public void testModelConstructorSpecificParameter() {
TestConstructorSpecificParameter elem = new TestConstructorSpecificParameter(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("<elem valueA=\"66\">\n"
+ " <valueB>18523.0</valueB>\n"
+ "</elem>", dataTest);
final TestConstructorSpecificParameter root = Assertions.assertDoesNotThrow(() -> Exml.parseOne(dataTest, TestConstructorSpecificParameter.class, ExmlTestIntrospectionObject.NODE_NAME));
Assertions.assertEquals(66, root.valueA);
Assertions.assertEquals(18523.0f, root.valueB);
}
public class TestConstructorSpecific {
@XmlAttribute
public Integer valueA;
public double valueB;
@XmlName({"valueA", "valueB"})
public TestConstructorSpecific(final Integer valueA, final double valueB) {
this.valueA = valueA;
this.valueB = valueB;
}
}
@Test
public void testModelConstructorSpecific() {
TestConstructorSpecific elem = new TestConstructorSpecific(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("<elem valueA=\"66\">\n"
+ " <valueB>18523.0</valueB>\n"
+ "</elem>", dataTest);
final TestConstructorSpecific root = Assertions.assertDoesNotThrow(() -> Exml.parseOne(dataTest, TestConstructorSpecific.class, ExmlTestIntrospectionObject.NODE_NAME));
Assertions.assertEquals(66, root.valueA);
Assertions.assertEquals(18523.0f, root.valueB);
}
} }

View File

@ -6,6 +6,7 @@
package test.atriasoft.exml; package test.atriasoft.exml;
import org.atriasoft.exml.Exml; import org.atriasoft.exml.Exml;
import org.atriasoft.exml.annotation.XmlName;
import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeAll;
@ -18,12 +19,8 @@ public class ExmlTestIntrospectionRecord {
Log.warning("================================================================"); Log.warning("================================================================");
} }
public record TestRecord( public record TestRecord(
Integer valueA, @XmlName("valueA") Integer valueA,
double valueB) { @XmlName("valueB") double valueB) {
public TestRecord(final Integer valueA, final double valueB) {
this.valueA = valueA;
this.valueB = valueB;
}
} }
@Test @Test
public void testModelRecord() { public void testModelRecord() {
@ -32,7 +29,8 @@ public class ExmlTestIntrospectionRecord {
Assertions.assertDoesNotThrow(() -> Exml.generate(elem, ExmlTestIntrospectionObject.NODE_NAME, builder)); Assertions.assertDoesNotThrow(() -> Exml.generate(elem, ExmlTestIntrospectionObject.NODE_NAME, builder));
String dataTest = builder.toString(); String dataTest = builder.toString();
Log.warning("data generated: " + builder.toString()); Log.warning("data generated: " + builder.toString());
Assertions.assertEquals("<elem valueA=\"66\">\n" Assertions.assertEquals("<elem>\n"
+ " <valueA>66</valueA>\n"
+ " <valueB>18523.0</valueB>\n" + " <valueB>18523.0</valueB>\n"
+ "</elem>", dataTest); + "</elem>", dataTest);
@ -41,5 +39,6 @@ public class ExmlTestIntrospectionRecord {
Assertions.assertEquals(18523.0f, root.valueB); Assertions.assertEquals(18523.0f, root.valueB);
} }
} }