[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(); 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 { public static Boolean getIsManaged(final Constructor<?> constructor, final Parameter element, final Boolean parentValue) throws AknotException {
final Annotation[] annotation = element.getDeclaredAnnotationsByType(AknotManaged.class); final Annotation[] annotation = element.getDeclaredAnnotationsByType(AknotManaged.class);
if (annotation.length == 0) { if (annotation.length == 0) {
@ -383,6 +394,35 @@ public class ReflectTools {
return tmp; 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 { public static String[] getNames(final Constructor<?> constructor, final Parameter element, final String defaultValue) throws Exception {
final Annotation[] annotation = element.getDeclaredAnnotationsByType(AknotName.class); final Annotation[] annotation = element.getDeclaredAnnotationsByType(AknotName.class);
if (annotation.length == 0) { 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). * 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) @Retention(RetentionPolicy.RUNTIME)
@AknotAnnotation @AknotAnnotation
public @interface AknotManaged { 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. * @return true if the element is managed.
*/ */
boolean value() default true; 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. * 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) @Retention(RetentionPolicy.RUNTIME)
@AknotAnnotation @AknotAnnotation
public @interface AknotName { public @interface AknotName {

View File

@ -18,9 +18,12 @@ public abstract class IntrospectionModel {
protected boolean ignoreUnknown = false; protected boolean ignoreUnknown = false;
protected final Class<?> classType; protected final Class<?> classType;
protected String[] names;
public IntrospectionModel(final Class<?> classType) { public IntrospectionModel(final Class<?> classType) {
this.classType = 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 { 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; return this.classType;
} }
public String[] getNames() {
return this.names;
}
public List<String> getNodeAvaillable() { public List<String> getNodeAvaillable() {
return null; return null;
} }
@ -132,6 +139,10 @@ public abstract class IntrospectionModel {
return Record.class.isAssignableFrom(this.classType); return Record.class.isAssignableFrom(this.classType);
} }
public void setNames(final String[] names) {
this.names = names;
}
public abstract String toString(final Object data) throws AknotException; 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.List;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.stream.Collectors;
import org.atriasoft.aknot.ReflectClass; import org.atriasoft.aknot.ReflectClass;
import org.atriasoft.aknot.ReflectTools; 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 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<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 { public IntrospectionModelComplex(final Class<?> classType) throws AknotException {
super(classType); super(classType);
try { try {
final String[] className = ReflectTools.getNames(classType, null);
if (className != null) {
this.names = className;
}
if (classType.getNestHost() == classType) { if (classType.getNestHost() == classType) {
this.isSubClass = false; this.isSubClass = false;
} else if (!Modifier.isStatic(classType.getModifiers())) { } else if (!Modifier.isStatic(classType.getModifiers())) {
@ -48,12 +55,13 @@ public class IntrospectionModelComplex extends IntrospectionModel {
if (classType.isPrimitive()) { if (classType.isPrimitive()) {
Log.critical("Detect primitive ==> impossible case !!! "); Log.critical("Detect primitive ==> impossible case !!! ");
} }
final Boolean isDefaultManaged = ReflectTools.getIsDefaultManaged(classType, IntrospectionModel.DEFAULT_MANAGED);
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
// -- Parse constructor // -- Parse constructor
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
Log.error("Introspect class: '" + classType.getCanonicalName() + "'"); Log.error("Introspect class: '" + classType.getCanonicalName() + "'");
final Constructor<?>[] constructors = this.classType.getConstructors(); final Constructor<?>[] constructors = this.classType.getConstructors();
Log.verbose(" Constructors: (" + constructors.length + ")"); Log.warning(" Constructors: (" + constructors.length + ")");
Constructor<?> emptyConstructorTmp = null; Constructor<?> emptyConstructorTmp = null;
for (final Constructor<?> elem : constructors) { for (final Constructor<?> elem : constructors) {
Log.error(" Constructor ??? : {}", elem.toGenericString()); Log.error(" Constructor ??? : {}", elem.toGenericString());
@ -61,6 +69,11 @@ public class IntrospectionModelComplex extends IntrospectionModel {
if (!Modifier.isPublic(elem.getModifiers())) { if (!Modifier.isPublic(elem.getModifiers())) {
continue; continue;
} }
// check if the constructor is rejected !
final Boolean managedConstructor = ReflectTools.getIsManaged(elem, isDefaultManaged);
if (managedConstructor != null && !managedConstructor) {
continue;
}
if (elem.getParameterCount() == 0) { if (elem.getParameterCount() == 0) {
emptyConstructorTmp = elem; emptyConstructorTmp = elem;
Log.error(" >>> " + elem.toGenericString()); Log.error(" >>> " + elem.toGenericString());
@ -104,6 +117,17 @@ public class IntrospectionModelComplex extends IntrospectionModel {
namesBeans[iii - offsetSubClass] = namesParam[0]; 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)) { if (checkIfOneIsNull(namesBeans, 0)) {
Log.verbose(" - " + elem.toGenericString()); Log.verbose(" - " + elem.toGenericString());
Log.verbose(" ==> unmanaged (missing names description: " + Arrays.toString(namesBeans) + ")"); Log.verbose(" ==> unmanaged (missing names description: " + Arrays.toString(namesBeans) + ")");
@ -346,7 +370,6 @@ public class IntrospectionModelComplex extends IntrospectionModel {
prop.setAttribute(isDefaultAttribute); prop.setAttribute(isDefaultAttribute);
} }
} }
final Boolean isDefaultManaged = ReflectTools.getIsDefaultManaged(classType, IntrospectionModel.DEFAULT_MANAGED);
for (final IntrospectionProperty prop : this.elements) { for (final IntrospectionProperty prop : this.elements) {
if (prop.isManaged() == null) { if (prop.isManaged() == null) {
prop.setManaged(isDefaultManaged); prop.setManaged(isDefaultManaged);
@ -375,29 +398,12 @@ public class IntrospectionModelComplex extends IntrospectionModel {
ex.printStackTrace(); ex.printStackTrace();
throw new AknotException("Error in creating introspection data ... " + ex.getMessage()); throw new AknotException("Error in creating introspection data ... " + ex.getMessage());
} }
// Sort the parameters to generate all time the same XML.. // Sort the parameters to generate all time the same XML..
Collections.sort(this.elements, (a, b) -> a.getNames()[0].compareTo(b.getNames()[0])); Collections.sort(this.elements, (a, b) -> a.getNames()[0].compareTo(b.getNames()[0]));
// separate managed and unmanaged to optimize performances...
for (final IntrospectionProperty prop : this.elements) { this.elementUnManaged = this.elements.stream().filter(o -> !o.isManaged()).collect(Collectors.toList());
Log.verbose("Property/node : " + prop.getBeanName()); this.elements = this.elements.stream().filter(o -> o.isManaged()).collect(Collectors.toList());
Log.verbose(" names: " + Arrays.toString(prop.getNames())); //display();
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");
}
}
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@ -566,6 +572,48 @@ public class IntrospectionModelComplex extends IntrospectionModel {
return tmp; 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 { protected IntrospectionProperty findBeanNodeDescription(final String propertyBeanName) throws AknotException {
for (final IntrospectionProperty prop : this.elements) { for (final IntrospectionProperty prop : this.elements) {
if (prop.isAttribute()) { if (prop.isAttribute()) {

View File

@ -75,10 +75,10 @@ public class IntrospectionObject {
// nothing to do ... ==> element already created // nothing to do ... ==> element already created
return; 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]" : "")); + (this.modelInterface.isList() ? "[List]" : ""));
Log.debug(" Properties : " + this.properties.keySet()); Log.warning(" Properties : " + this.properties.keySet());
Log.debug(" Nodes : " + this.nodes.keySet()); Log.warning(" Nodes : " + this.nodes.keySet());
this.data = this.modelInterface.createObject(this.properties, this.nodes); this.data = this.modelInterface.createObject(this.properties, this.nodes);
} }