[DEV] correct managed elements

This commit is contained in:
Edouard DUPIN 2022-05-16 23:42:31 +02:00
parent 4badf7d29e
commit 32eb062784
6 changed files with 129 additions and 30 deletions

View File

@ -243,6 +243,17 @@ public class ReflectTools {
return ((AknotIgnoreUnknown) annotation[0]).value();
}
public static Boolean getIsManaged(final Constructor<?> element, final Boolean parentValue) throws AknotException {
final Annotation[] annotation = element.getDeclaredAnnotationsByType(AknotManaged.class);
if (annotation.length == 0) {
return parentValue;
}
if (annotation.length > 1) {
throw new AknotException("Must not have more than 1 element @ on " + element.getClass().getCanonicalName());
}
return ((AknotManaged) annotation[0]).value();
}
public static Boolean getIsManaged(final Constructor<?> constructor, final Parameter element, final Boolean parentValue) throws AknotException {
final Annotation[] annotation = element.getDeclaredAnnotationsByType(AknotManaged.class);
if (annotation.length == 0) {
@ -383,6 +394,35 @@ public class ReflectTools {
return tmp;
}
public static String[] getNames(final Class<?> element, final String defaultValue) throws Exception {
final Annotation[] annotation = element.getDeclaredAnnotationsByType(AknotName.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 than 1 element @AknotName on " + element.getClass().getCanonicalName());
}
final String[] tmp = ((AknotName) annotation[0]).value();
if (tmp == null) {
throw new Exception("Set null value in decorator @AknotName is not availlable on: " + element.toGenericString());
}
if (tmp.length == 0) {
throw new Exception("Set empty list value in decorator @AknotName 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 @AknotName is not availlable on: " + element.toGenericString());
}
if (elem.isEmpty()) {
throw new Exception("Set empty String in list of value in decorator @AknotName 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(AknotName.class);
if (annotation.length == 0) {

View File

@ -9,12 +9,12 @@ 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, ElementType.PARAMETER})
@Target({ ElementType.FIELD, ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER })
@Retention(RetentionPolicy.RUNTIME)
@AknotAnnotation
public @interface AknotManaged {
/**
* Set this at false to remove this function or this field form the XML parsing system
* Set this at false to remove this function or this field form the XML parsing system
* @return true if the element is managed.
*/
boolean value() default true;

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.
*
*/
@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.CONSTRUCTOR, ElementType.PARAMETER })
@Target({ ElementType.FIELD, ElementType.TYPE, ElementType.METHOD, ElementType.CONSTRUCTOR, ElementType.PARAMETER })
@Retention(RetentionPolicy.RUNTIME)
@AknotAnnotation
public @interface AknotName {

View File

@ -18,9 +18,12 @@ public abstract class IntrospectionModel {
protected boolean ignoreUnknown = false;
protected final Class<?> classType;
protected String[] names;
public IntrospectionModel(final Class<?> classType) {
this.classType = classType;
this.names = new String[1];
this.names[0] = classType.getSimpleName();
}
public Object createObject(final Map<String, Object> properties, final Map<String, List<Object>> nodes) throws AknotException {
@ -43,6 +46,10 @@ public abstract class IntrospectionModel {
return this.classType;
}
public String[] getNames() {
return this.names;
}
public List<String> getNodeAvaillable() {
return null;
}
@ -132,6 +139,10 @@ public abstract class IntrospectionModel {
return Record.class.isAssignableFrom(this.classType);
}
public void setNames(final String[] names) {
this.names = names;
}
public abstract String toString(final Object data) throws AknotException;
}

View File

@ -13,6 +13,7 @@ import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.stream.Collectors;
import org.atriasoft.aknot.ReflectClass;
import org.atriasoft.aknot.ReflectTools;
@ -32,11 +33,17 @@ public class IntrospectionModelComplex extends IntrospectionModel {
private final boolean isSubClass; // if true, the constructor must be called with a null first object.
private final Constructor<?> constructorEmpty;
private final List<ConstructorModel> constructors = new ArrayList<>();
private final List<IntrospectionProperty> elements = new ArrayList<>();
private List<IntrospectionProperty> elements = new ArrayList<>();
private List<IntrospectionProperty> elementUnManaged = new ArrayList<>();
public IntrospectionModelComplex(final Class<?> classType) throws AknotException {
super(classType);
try {
final String[] className = ReflectTools.getNames(classType, null);
if (className != null) {
this.names = className;
}
if (classType.getNestHost() == classType) {
this.isSubClass = false;
} else if (!Modifier.isStatic(classType.getModifiers())) {
@ -48,12 +55,13 @@ public class IntrospectionModelComplex extends IntrospectionModel {
if (classType.isPrimitive()) {
Log.critical("Detect primitive ==> impossible case !!! ");
}
final Boolean isDefaultManaged = ReflectTools.getIsDefaultManaged(classType, IntrospectionModel.DEFAULT_MANAGED);
// ------------------------------------------------------------------------
// -- Parse constructor
// ------------------------------------------------------------------------
Log.error("Introspect class: '" + classType.getCanonicalName() + "'");
final Constructor<?>[] constructors = this.classType.getConstructors();
Log.verbose(" Constructors: (" + constructors.length + ")");
Log.warning(" Constructors: (" + constructors.length + ")");
Constructor<?> emptyConstructorTmp = null;
for (final Constructor<?> elem : constructors) {
Log.error(" Constructor ??? : {}", elem.toGenericString());
@ -61,6 +69,11 @@ public class IntrospectionModelComplex extends IntrospectionModel {
if (!Modifier.isPublic(elem.getModifiers())) {
continue;
}
// check if the constructor is rejected !
final Boolean managedConstructor = ReflectTools.getIsManaged(elem, isDefaultManaged);
if (managedConstructor != null && !managedConstructor) {
continue;
}
if (elem.getParameterCount() == 0) {
emptyConstructorTmp = elem;
Log.error(" >>> " + elem.toGenericString());
@ -104,6 +117,17 @@ public class IntrospectionModelComplex extends IntrospectionModel {
namesBeans[iii - offsetSubClass] = namesParam[0];
}
}
// The constructor can not be managed if One of the element is mark as unmanaged...
boolean managedParameters = true;
for (int iii = 0; iii < isManageds.length; iii++) {
if (isManageds[iii] != null && !isManageds[iii]) {
managedParameters = false;
break;
}
}
if (!managedParameters) {
continue;
}
if (checkIfOneIsNull(namesBeans, 0)) {
Log.verbose(" - " + elem.toGenericString());
Log.verbose(" ==> unmanaged (missing names description: " + Arrays.toString(namesBeans) + ")");
@ -346,7 +370,6 @@ public class IntrospectionModelComplex extends IntrospectionModel {
prop.setAttribute(isDefaultAttribute);
}
}
final Boolean isDefaultManaged = ReflectTools.getIsDefaultManaged(classType, IntrospectionModel.DEFAULT_MANAGED);
for (final IntrospectionProperty prop : this.elements) {
if (prop.isManaged() == null) {
prop.setManaged(isDefaultManaged);
@ -375,29 +398,12 @@ public class IntrospectionModelComplex extends IntrospectionModel {
ex.printStackTrace();
throw new AknotException("Error in creating introspection data ... " + ex.getMessage());
}
// Sort the parameters to generate all time the same XML..
Collections.sort(this.elements, (a, b) -> a.getNames()[0].compareTo(b.getNames()[0]));
for (final IntrospectionProperty prop : this.elements) {
Log.verbose("Property/node : " + prop.getBeanName());
Log.verbose(" names: " + Arrays.toString(prop.getNames()));
Log.verbose(" list: " + prop.getListName());
Log.verbose(" managed: " + prop.isManaged());
Log.verbose(" attribute: " + prop.isAttribute());
Log.verbose(" text: " + prop.isText());
Log.verbose(" case-sensitive: " + prop.isCaseSensitive());
Log.verbose(" optionnal: " + prop.isOptionnal());
Log.verbose(" constructor: " + prop.isCanBeSetByConstructor());
Log.verbose(" get/set: " + prop.canGetValue() + " / " + prop.canSetValue());
Log.verbose(" type: " + prop.getType().getCanonicalName());
if (prop.getSubType() != null) {
Log.verbose(" sub-type: " + prop.getSubType().getCanonicalName());
} else {
Log.verbose(" sub-type: null");
}
}
// separate managed and unmanaged to optimize performances...
this.elementUnManaged = this.elements.stream().filter(o -> !o.isManaged()).collect(Collectors.toList());
this.elements = this.elements.stream().filter(o -> o.isManaged()).collect(Collectors.toList());
//display();
}
@SuppressWarnings("unchecked")
@ -566,6 +572,48 @@ public class IntrospectionModelComplex extends IntrospectionModel {
return tmp;
}
public void display() {
Log.print("Class: {} nbProperty:{}", this.classType.getCanonicalName(), this.elements.size());
Log.print("Managed:");
for (final IntrospectionProperty prop : this.elements) {
Log.print(" * Property/node : {}", prop.getBeanName());
Log.print(" names: {}", Arrays.toString(prop.getNames()));
Log.print(" list: {}", prop.getListName());
//Log.print(" managed: {}", prop.isManaged());
Log.print(" attribute: {}", prop.isAttribute());
Log.print(" text: {}", prop.isText());
Log.print(" case-sensitive: {}", prop.isCaseSensitive());
Log.print(" optionnal: {}", prop.isOptionnal());
Log.print(" constructor: {}", prop.isCanBeSetByConstructor());
Log.print(" get/set: {} / {}", prop.canGetValue(), prop.canSetValue());
Log.print(" type: {}", prop.getType().getCanonicalName());
if (prop.getSubType() != null) {
Log.print(" sub-type: {}", prop.getSubType().getCanonicalName());
} else {
Log.print(" sub-type: null");
}
}
Log.info("Un-Managed:");
for (final IntrospectionProperty prop : this.elementUnManaged) {
Log.print(" * Property/node : {}", prop.getBeanName());
Log.print(" names: {}", Arrays.toString(prop.getNames()));
Log.print(" list: {}", prop.getListName());
//Log.print(" managed: {}", prop.isManaged());
Log.print(" attribute: {}", prop.isAttribute());
Log.print(" text: {}", prop.isText());
Log.print(" case-sensitive: {}", prop.isCaseSensitive());
Log.print(" optionnal: {}", prop.isOptionnal());
Log.print(" constructor: {}", prop.isCanBeSetByConstructor());
Log.print(" get/set: {} / {}", prop.canGetValue(), prop.canSetValue());
Log.print(" type: {}", prop.getType().getCanonicalName());
if (prop.getSubType() != null) {
Log.print(" sub-type: {}", prop.getSubType().getCanonicalName());
} else {
Log.print(" sub-type: null");
}
}
}
protected IntrospectionProperty findBeanNodeDescription(final String propertyBeanName) throws AknotException {
for (final IntrospectionProperty prop : this.elements) {
if (prop.isAttribute()) {

View File

@ -75,10 +75,10 @@ public class IntrospectionObject {
// nothing to do ... ==> element already created
return;
}
Log.debug("Create the element for the Specific node ... type = " + this.modelInterface.getClassType().getCanonicalName() + (this.modelInterface.isArray() ? "[array]" : "")
Log.warning("Create the element for the Specific node ... type = " + this.modelInterface.getClassType().getCanonicalName() + (this.modelInterface.isArray() ? "[array]" : "")
+ (this.modelInterface.isList() ? "[List]" : ""));
Log.debug(" Properties : " + this.properties.keySet());
Log.debug(" Nodes : " + this.nodes.keySet());
Log.warning(" Properties : " + this.properties.keySet());
Log.warning(" Nodes : " + this.nodes.keySet());
this.data = this.modelInterface.createObject(this.properties, this.nodes);
}