[DEV] add Text interface for injection (concept of pack text and factory Model

This commit is contained in:
Edouard DUPIN 2022-04-24 08:01:52 +02:00
parent 25f149357b
commit 6adc3b3897
15 changed files with 1093 additions and 575 deletions

View File

@ -7,202 +7,192 @@ public class StringSerializer {
private static final Map<Class<?>, Converter> VALUES_OF = new HashMap<>();
static {
StringSerializer.VALUES_OF.put(byte.class, new Converter() {
@Override
public String toString(final Object data) {
return Byte.toString((Byte) data);
}
@Override
public Object valueOf(final String value) {
return Byte.valueOf(value.trim());
}
@Override
public String toString(final Object data) {
return Byte.toString((Byte)data);
}
});
StringSerializer.VALUES_OF.put(Byte.class, new Converter() {
@Override
public String toString(final Object data) {
return Byte.toString((Byte) data);
}
@Override
public Object valueOf(final String value) {
return Byte.valueOf(value.trim());
}
@Override
public String toString(final Object data) {
return Byte.toString((Byte)data);
}
});
StringSerializer.VALUES_OF.put(int.class, new Converter() {
@Override
public String toString(final Object data) {
return Integer.toString((Integer) data);
}
@Override
public Object valueOf(final String value) {
return Integer.valueOf(value.trim());
}
@Override
public String toString(final Object data) {
return Integer.toString((Integer)data);
}
});
StringSerializer.VALUES_OF.put(Integer.class, new Converter() {
@Override
public String toString(final Object data) {
return Integer.toString((Integer) data);
}
@Override
public Object valueOf(final String value) {
return Integer.valueOf(value.trim());
}
@Override
public String toString(final Object data) {
return Integer.toString((Integer)data);
}
});
StringSerializer.VALUES_OF.put(long.class, new Converter() {
@Override
public String toString(final Object data) {
return Long.toString((Long) data);
}
@Override
public Object valueOf(final String value) {
return Long.valueOf(value.trim());
}
@Override
public String toString(final Object data) {
return Long.toString((Long)data);
}
});
StringSerializer.VALUES_OF.put(Long.class, new Converter() {
@Override
public String toString(final Object data) {
return Long.toString((Long) data);
}
@Override
public Object valueOf(final String value) {
return Long.valueOf(value.trim());
}
@Override
public String toString(final Object data) {
return Long.toString((Long)data);
}
});
StringSerializer.VALUES_OF.put(short.class, new Converter() {
@Override
public String toString(final Object data) {
return Short.toString((Short) data);
}
@Override
public Object valueOf(final String value) {
return Short.valueOf(value.trim());
}
@Override
public String toString(final Object data) {
return Short.toString((Short)data);
}
});
StringSerializer.VALUES_OF.put(Short.class, new Converter() {
@Override
public String toString(final Object data) {
return Short.toString((Short) data);
}
@Override
public Object valueOf(final String value) {
return Short.valueOf(value.trim());
}
@Override
public String toString(final Object data) {
return Short.toString((Short)data);
}
});
StringSerializer.VALUES_OF.put(float.class, new Converter() {
@Override
public String toString(final Object data) {
return Float.toString((Float) data);
}
@Override
public Object valueOf(final String value) {
return Float.valueOf(value.trim());
}
@Override
public String toString(final Object data) {
return Float.toString((Float)data);
}
});
StringSerializer.VALUES_OF.put(Float.class, new Converter() {
@Override
public String toString(final Object data) {
return Float.toString((Float) data);
}
@Override
public Object valueOf(final String value) {
return Float.valueOf(value.trim());
}
@Override
public String toString(final Object data) {
return Float.toString((Float)data);
}
});
StringSerializer.VALUES_OF.put(double.class, new Converter() {
@Override
public String toString(final Object data) {
return Double.toString((Double) data);
}
@Override
public Object valueOf(final String value) {
return Double.valueOf(value.trim());
}
@Override
public String toString(final Object data) {
return Double.toString((Double)data);
}
});
StringSerializer.VALUES_OF.put(Double.class, new Converter() {
@Override
public String toString(final Object data) {
return Double.toString((Double) data);
}
@Override
public Object valueOf(final String value) {
return Double.valueOf(value.trim());
}
@Override
public String toString(final Object data) {
return Double.toString((Double)data);
}
});
StringSerializer.VALUES_OF.put(boolean.class, new Converter() {
@Override
public String toString(final Object data) {
return Boolean.toString((Boolean) data);
}
@Override
public Object valueOf(final String value) {
return Boolean.valueOf(value.trim());
}
@Override
public String toString(final Object data) {
return Boolean.toString((Boolean)data);
}
});
StringSerializer.VALUES_OF.put(Boolean.class, new Converter() {
@Override
public String toString(final Object data) {
return Boolean.toString((Boolean) data);
}
@Override
public Object valueOf(final String value) {
return Boolean.valueOf(value.trim());
}
@Override
public String toString(final Object data) {
return Boolean.toString((Boolean)data);
}
});
StringSerializer.VALUES_OF.put(String.class, new Converter() {
@Override
public String toString(final Object data) {
return (String) data;
}
@Override
public Object valueOf(final String value) {
return value;
}
@Override
public String toString(final Object data) {
return (String)data;
}
});
}
public static boolean contains(final Class<?> clazz) {
return StringSerializer.VALUES_OF.containsKey(clazz);
}
/**
* Un-serialize a String in a specified Object
* @param value String to parse
* @return Data generated or Null
*/
public static Object valueOf(final Class<?> clazz, final String value) {
if (value == null) {
return null;
}
Converter conv = StringSerializer.VALUES_OF.get(clazz);
return conv.valueOf(value);
}
public static String toString(final byte data) {
return Byte.toString(data);
}
public static String toString(final boolean data) {
return Boolean.toString(data);
}
public static String toString(final byte data) {
return Byte.toString(data);
}
public static String toString(final int data) {
return Integer.toString(data);
}
public static String toString(final short data) {
return Short.toString(data);
}
public static String toString(final long data) {
return Long.toString(data);
}
/**
* Serialize in a string the require data
* @param data Object to serialize
@ -212,10 +202,27 @@ public class StringSerializer {
if (data == null) {
return null;
}
Class<?> clazz = data.getClass();
Converter conv = StringSerializer.VALUES_OF.get(clazz);
final Class<?> clazz = data.getClass();
final Converter conv = StringSerializer.VALUES_OF.get(clazz);
return conv.toString(data);
}
public static String toString(final short data) {
return Short.toString(data);
}
/**
* Un-serialize a String in a specified Object
* @param value String to parse
* @return Data generated or Null
*/
public static Object valueOf(final Class<?> clazz, final String value) {
if (value == null) {
return null;
}
final Converter conv = StringSerializer.VALUES_OF.get(clazz);
return conv.valueOf(value);
}
private StringSerializer() {}
}

View File

@ -13,6 +13,7 @@ import java.nio.file.Files;
import java.nio.file.Path;
import org.atriasoft.etk.Uri;
import org.atriasoft.exml.annotation.XmlFactory.InterfaceXmlFactoryAccess;
import org.atriasoft.exml.builder.Builder;
import org.atriasoft.exml.builder.BuilderGeneric;
import org.atriasoft.exml.builder.BuilderIntrospection;
@ -133,6 +134,29 @@ public class Exml {
}
}
public static Object[] parse(final String data, final InterfaceXmlFactoryAccess widgetXmlFactory) throws ExmlException, ExmlParserErrorMulti {
Builder builder;
try {
builder = new BuilderIntrospection(widgetXmlFactory);
final ParseXml parser = new ParseXml(builder);
final ParsingProperty property = new ParsingProperty();
property.setDisplayError(true);
final IntrospectionObject introspectionObject = (IntrospectionObject) parser.parse(data, property);
introspectionObject.generateTheObject();
final Object listRet = introspectionObject.getData();
/*
if (listRet != null && listRet.getClass().isArray() && listRet.getClass().componentType() == classType) {
return (T[]) listRet;
}
*/
return (Object[]) listRet;
} catch (final ExmlException ex) {
ex.printStackTrace();
throw ex;
}
}
/**
* Load the file that might contain the xml
*

View File

@ -4,6 +4,7 @@ import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.Map;
/**
* Marker annotation that permit to set the default parsing as attributes.
@ -26,6 +27,8 @@ public @interface XmlFactory {
* @return The xml string to inject (or null).
*/
String generateName(Object object);
Map<String, Class<?>> getConversionMap();
}
/**

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 set the Xml element seen as a property.
*/
@Target({ ElementType.FIELD, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@ExmlAnnotation
public @interface XmlText {
/**
* Set at true to set the element used as text data as a property of the Xml node
* @return property management.
*/
boolean value() default true;
}

View File

@ -10,6 +10,21 @@ import org.atriasoft.exml.exception.ExmlException;
public interface Builder {
/**
* Detect the end of the element : {@code<ELEMENT>}
* @param element Element that is finished
* @throws ExmlBuilderException
*/
void endElement(Object element) throws ExmlException;
/**
* This is called before a text adding, in some case the subData must not be parsed, then all the subData is pack as a single string without managing the XML properties.
* @param parent Parent node of the element that is created
* @return true if the data must be packed.
* @throws ExmlException
*/
boolean isPackText(Object parent) throws ExmlException;
/**
* New comment added on this Element
* @param element Element representing the node of the Comment is added
@ -36,6 +51,14 @@ public interface Builder {
*/
Object newElement(Object parent, String nodeName) throws ExmlException;
/**
* The sub-element is finish (creation done)
* @param parent Parent node of the element that is created
* @param tmpname Name of the node
* @param element Element builder that has been created
*/
void newElementFinished(Object parent, String tmpname, Object element) throws ExmlException;
/**
* Add a property on the Element.
* @param element Element representing the node of the property is added
@ -60,19 +83,4 @@ public interface Builder {
*/
void newText(Object parent, String text) throws ExmlException;
/**
* Detect the end of the element : {@code<ELEMENT>}
* @param element Element that is finished
* @throws ExmlBuilderException
*/
void endElement(Object element) throws ExmlException;
/**
* The sub-element is finish (creation done)
* @param parent Parent node of the element that is created
* @param tmpname Name of the node
* @param element Element builder that has been created
*/
void newElementFinished(Object parent, String tmpname, Object element) throws ExmlException;
}

View File

@ -6,6 +6,7 @@
package org.atriasoft.exml.builder;
import org.atriasoft.exml.exception.ExmlBuilderException;
import org.atriasoft.exml.exception.ExmlException;
import org.atriasoft.exml.model.XmlAttribute;
import org.atriasoft.exml.model.XmlAttributeList;
import org.atriasoft.exml.model.XmlComment;
@ -15,9 +16,19 @@ import org.atriasoft.exml.model.XmlText;
public class BuilderGeneric implements Builder {
@Override
public void endElement(final Object element) {
// Nothing to do...
}
@Override
public boolean isPackText(final Object parent) throws ExmlException {
return false;
}
@Override
public void newComment(final Object element, final String comment) throws ExmlBuilderException {
if (element instanceof XmlElement elem) {
if (element instanceof final XmlElement elem) {
elem.append(new XmlComment(comment));
return;
}
@ -26,7 +37,7 @@ public class BuilderGeneric implements Builder {
@Override
public Object newDeclaration(final Object parent, final String text) throws ExmlBuilderException {
if (parent instanceof XmlElement elem) {
if (parent instanceof final XmlElement elem) {
final XmlDeclaration dec = new XmlDeclaration(text);
elem.append(dec);
return dec;
@ -36,7 +47,7 @@ public class BuilderGeneric implements Builder {
@Override
public Object newElement(final Object parent, final String nodeName) throws ExmlBuilderException {
if (parent instanceof XmlElement elem) {
if (parent instanceof final XmlElement elem) {
final XmlElement eee = new XmlElement(nodeName);
elem.append(eee);
return eee;
@ -44,9 +55,14 @@ public class BuilderGeneric implements Builder {
throw new ExmlBuilderException("can not add Element on something else than Element");
}
@Override
public void newElementFinished(final Object parent, final String tmpname, final Object element) {
// Nothing to do...
}
@Override
public void newProperty(final Object element, final String propertyName, final String propertyValue) throws ExmlBuilderException {
if (element instanceof XmlAttributeList attr) {
if (element instanceof final XmlAttributeList attr) {
attr.appendAttribute(new XmlAttribute(propertyName, propertyValue));
return;
}
@ -60,21 +76,11 @@ public class BuilderGeneric implements Builder {
@Override
public void newText(final Object parent, final String text) throws ExmlBuilderException {
if (parent instanceof XmlElement attr) {
if (parent instanceof final XmlElement attr) {
attr.append(new XmlText(text));
return;
}
throw new ExmlBuilderException("can not add Text on something else than Element or Declaration");
}
@Override
public void endElement(Object element) {
// Nothing to do...
}
@Override
public void newElementFinished(Object parent, String tmpname, Object element) {
// Nothing to do...
}
}

View File

@ -4,6 +4,7 @@ import java.util.ArrayList;
import java.util.List;
import org.atriasoft.eStringSerialize.StringSerializer;
import org.atriasoft.exml.annotation.XmlFactory.InterfaceXmlFactoryAccess;
import org.atriasoft.exml.exception.ExmlAttributeDoesNotExist;
import org.atriasoft.exml.exception.ExmlBuilderException;
import org.atriasoft.exml.exception.ExmlException;
@ -15,8 +16,19 @@ public class BuilderIntrospection implements Builder {
// The root class (need to keep it if we use 2 time the builder, the root class is no more accessible).
final Class<?> rootClassType;
final String rootNodeName;
final InterfaceXmlFactoryAccess factory;
public BuilderIntrospection(final InterfaceXmlFactoryAccess factory) throws ExmlException {
this.factory = factory;
this.rootNodeName = null;
this.rootClassType = null;
for (final String it : this.factory.getConversionMap().keySet()) {
this.cacheModel.findOrCreate(ModelType.NORMAL, it, this.factory.getConversionMap().get(it));
}
}
public BuilderIntrospection(final ModelType model, final Class<?> classType, final String rootNodeName) throws ExmlException {
this.factory = null;
this.rootNodeName = rootNodeName;
this.rootClassType = classType;
this.cacheModel.findOrCreate(model, null, classType);
@ -24,6 +36,7 @@ public class BuilderIntrospection implements Builder {
@Override
public void endElement(final Object element) throws ExmlBuilderException {
Log.error("End of Element: {}", element);
if (element == null) {
return;
}
@ -36,6 +49,19 @@ public class BuilderIntrospection implements Builder {
}
@Override
public boolean isPackText(final Object parent) throws ExmlException {
if (parent == null) {
return false;
}
final IntrospectionObject introspectionObject = (IntrospectionObject) parent;
final IntrospectionModel model = introspectionObject.getModelIntrospection();
if (model.hasTextModel()) {
return true;
}
return false;
}
@Override
public void newComment(final Object element, final String comment) throws ExmlException {}
@ -52,11 +78,11 @@ public class BuilderIntrospection implements Builder {
}
Log.verbose("new element on NodeName=" + nodeName);
final IntrospectionObject introspectionObject = (IntrospectionObject) parent;
IntrospectionModel model = introspectionObject.getModelIntrospection();
final IntrospectionModel model = introspectionObject.getModelIntrospection();
Class<?> typeClass = null;
String listTreeName = null;
if (model.isArray() || model.isList()) {
List<String> nodesAvaillable = model.getNodeAvaillable();
final List<String> nodesAvaillable = model.getNodeAvaillable();
if (nodesAvaillable == null || nodesAvaillable.size() == 0) {
throw new ExmlBuilderException("Model can not have subNode with name: '" + nodeName + "'");
}
@ -76,7 +102,7 @@ public class BuilderIntrospection implements Builder {
if (typeClass != null) {
// specific case for List ==> need to get the subType in introspection ...
if (typeClass.isArray()) {
Class<?> subTypeClass = typeClass.getComponentType();
final Class<?> subTypeClass = typeClass.getComponentType();
Log.verbose("Create array new 'SUB' class: '" + typeClass.getCanonicalName() + "' for node '" + nodeName + "'");
IntrospectionModel inferData = null;
if (listTreeName == null) {
@ -89,7 +115,7 @@ public class BuilderIntrospection implements Builder {
return new IntrospectionObject(inferData);
}
if (List.class.isAssignableFrom(typeClass)) {
Class<?> subTypeClass = introspectionObject.getTypeOfSubNodeSubType(nodeName);
final Class<?> subTypeClass = introspectionObject.getTypeOfSubNodeSubType(nodeName);
Log.verbose("Create List new 'SUB' class: '" + typeClass.getCanonicalName() + "' for node '" + nodeName + "'");
IntrospectionModel inferData = null;
if (listTreeName == null) {
@ -124,10 +150,10 @@ public class BuilderIntrospection implements Builder {
if (introspectionParentObject.getModelIntrospection() == null) {
if (tmpName.equals(this.rootNodeName)) {
// this is the root node ...
Object tmpp = introspectionParentObject.getData();
final Object tmpp = introspectionParentObject.getData();
if (tmpp instanceof List) {
@SuppressWarnings("unchecked")
List<Object> elementsOut = (List<Object>) tmpp;
final List<Object> elementsOut = (List<Object>) tmpp;
elementsOut.add(introspectionElementObject.getData());
}
}
@ -142,11 +168,11 @@ public class BuilderIntrospection implements Builder {
return;
}
final IntrospectionObject introspectionObject = (IntrospectionObject) element;
IntrospectionModel model = introspectionObject.getModelIntrospection();
final IntrospectionModel model = introspectionObject.getModelIntrospection();
if (model.isArray() || model.isList()) {
throw new ExmlBuilderException("Model (List/Array) can not have property with name '" + propertyName + "'");
}
String beanName = model.getBeanName(propertyName);
final String beanName = model.getBeanName(propertyName);
if (beanName == null) {
if (model.isIgnoreUnknown()) {
Log.debug("Ignore node : '" + propertyName + "'");
@ -154,36 +180,37 @@ public class BuilderIntrospection implements Builder {
}
throw new ExmlAttributeDoesNotExist("The node '" + propertyName + "' Does not exist...");
}
Class<?> typeClass = model.getTypeOfProperty(propertyName);
// T O D O: check why we do not use the been name to get the type ..... !!!!!!!!!!!
final Class<?> typeClass = model.getTypeOfProperty(propertyName);
if (typeClass != null) {
// specific case for List ==> need to get the subType in introspection ...
if (typeClass.isPrimitive()) {
Object out = StringSerializer.valueOf(typeClass, propertyValue);
final Object out = StringSerializer.valueOf(typeClass, propertyValue);
introspectionObject.putProperty(propertyName, out);
} else if (typeClass.isArray()) {
String[] elems = propertyValue.split(";");
Class<?> subTypeClass = typeClass.getComponentType();
IntrospectionModel inferData = this.cacheModel.findOrCreate(ModelType.NORMAL, null, subTypeClass);
List<Object> out = new ArrayList<>();
final String[] elems = propertyValue.split(";");
final Class<?> subTypeClass = typeClass.getComponentType();
final IntrospectionModel inferData = this.cacheModel.findOrCreate(ModelType.NORMAL, null, subTypeClass);
final List<Object> out = new ArrayList<>();
for (int iii = 0; iii < elems.length; iii++) {
Object tmp = inferData.getValueFromText(elems[iii]);
final Object tmp = inferData.getValueFromText(elems[iii]);
out.add(tmp);
}
introspectionObject.putProperty(propertyName, out);
} else if (List.class.isAssignableFrom(typeClass)) {
String[] elems = propertyValue.split(";");
Class<?> subTypeClass = introspectionObject.getTypeOfSubProperty(propertyName);
final String[] elems = propertyValue.split(";");
final Class<?> subTypeClass = introspectionObject.getTypeOfSubProperty(propertyName);
Log.verbose("Create List new 'SUB' class: '" + typeClass.getCanonicalName() + "' for property '" + propertyName + "'");
IntrospectionModel inferData = this.cacheModel.findOrCreate(ModelType.NORMAL, null, subTypeClass);
List<Object> out = new ArrayList<>();
final IntrospectionModel inferData = this.cacheModel.findOrCreate(ModelType.NORMAL, null, subTypeClass);
final List<Object> out = new ArrayList<>();
for (int iii = 0; iii < elems.length; iii++) {
Object tmp = inferData.getValueFromText(elems[iii]);
final Object tmp = inferData.getValueFromText(elems[iii]);
out.add(tmp);
}
introspectionObject.putProperty(propertyName, out);
} else {
final IntrospectionModel inferData = this.cacheModel.findOrCreate(ModelType.NORMAL, null, typeClass);
Object out = inferData.getValueFromText(propertyValue);
final Object out = inferData.getValueFromText(propertyValue);
introspectionObject.putProperty(propertyName, out);
}
}
@ -201,21 +228,73 @@ public class BuilderIntrospection implements Builder {
return;
}
final IntrospectionObject introspectionObject = (IntrospectionObject) parent;
IntrospectionModel model = introspectionObject.getModelIntrospection();
final IntrospectionModel model = introspectionObject.getModelIntrospection();
if (model.isArray() || model.isList()) {
List<String> nodesAvaillable = model.getNodeAvaillable();
final List<String> nodesAvaillable = model.getNodeAvaillable();
if (nodesAvaillable != null && nodesAvaillable.size() != 0) {
throw new ExmlBuilderException("Model can not have direct text with model data= '" + text + "'");
}
Class<?> arrayType = model.getClassType();
final Class<?> arrayType = model.getClassType();
final IntrospectionModel inferData = this.cacheModel.findOrCreate(ModelType.NORMAL, null, arrayType);
// Create the data when object is ended created...
IntrospectionObject tmpp = new IntrospectionObject(inferData);
final IntrospectionObject tmpp = new IntrospectionObject(inferData);
newText(tmpp, text);
Object dataLocal = tmpp.getData();
final Object dataLocal = tmpp.getData();
introspectionObject.addObject(IntrospectionObject.STUPID_TOCKEN, dataLocal);
return;
}
introspectionObject.setText(text);
if (model.hasTextModel()) {
final String beanName = model.getTextBeanName();
if (beanName == null) {
if (model.isIgnoreUnknown()) {
Log.debug("Ignore node : **TEXT**");
return;
}
throw new ExmlAttributeDoesNotExist("The node **TEXT** Does not exist...");
}
final Class<?> typeClass = model.getTypeOfText();
if (typeClass != null) {
// specific case for List ==> need to get the subType in introspection ...
if (typeClass.isPrimitive()) {
final Object out = StringSerializer.valueOf(typeClass, text);
introspectionObject.putProperty(beanName, out);
} else if (typeClass.isArray()) {
Log.error("Not managed !!! ");
/*
final String[] elems = propertyValue.split(";");
final Class<?> subTypeClass = typeClass.getComponentType();
final IntrospectionModel inferData = this.cacheModel.findOrCreate(ModelType.NORMAL, null, subTypeClass);
final List<Object> out = new ArrayList<>();
for (int iii = 0; iii < elems.length; iii++) {
final Object tmp = inferData.getValueFromText(elems[iii]);
out.add(tmp);
}
introspectionObject.putProperty(propertyName, out);
*/
} else if (List.class.isAssignableFrom(typeClass)) {
Log.error("Not managed !!! ");
/*
final String[] elems = propertyValue.split(";");
final Class<?> subTypeClass = introspectionObject.getTypeOfSubProperty(propertyName);
Log.verbose("Create List new 'SUB' class: '" + typeClass.getCanonicalName() + "' for property '" + propertyName + "'");
final IntrospectionModel inferData = this.cacheModel.findOrCreate(ModelType.NORMAL, null, subTypeClass);
final List<Object> out = new ArrayList<>();
for (int iii = 0; iii < elems.length; iii++) {
final Object tmp = inferData.getValueFromText(elems[iii]);
out.add(tmp);
}
introspectionObject.putProperty(propertyName, out);
*/
} else {
//Log.error("Not managed !!! ");
final IntrospectionModel inferData = this.cacheModel.findOrCreate(ModelType.NORMAL, null, typeClass);
final Object out = inferData.getValueFromText(text);
introspectionObject.putProperty(IntrospectionObject.PUBLIC_TEXT_NAME, out);
}
}
} else {
introspectionObject.setText(text);
}
}
}

View File

@ -5,7 +5,6 @@ import java.util.Map;
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;
@ -13,21 +12,11 @@ public abstract class IntrospectionModel {
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() {
return null;
}
public List<IntrospectionProperty> getAttributes() {
return null;
}
public Class<?> getClassType() {
return this.classType;
}
public IntrospectionModel(final Class<?> classType) {
this.classType = classType;
@ -37,60 +26,107 @@ public abstract class IntrospectionModel {
return null;
}
public List<IntrospectionProperty> getAttributes() {
return null;
}
public String getBeanName(final String nodeName) {
return nodeName;
}
public String getBeanNameModel(final String nodeName) {
return getBeanName(nodeName);
}
public Class<?> getClassType() {
return this.classType;
}
public List<String> getNodeAvaillable() {
return null;
}
public Object getValueFromText(final String text) throws ExmlBuilderException {
public List<IntrospectionProperty> getNodes() {
return null;
}
public Object getValue(final String propertyName, final String propertyValue) throws ExmlBuilderException {
public String getTextBeanName() {
// TODO Auto-generated method stub
return null;
}
public String getTreeNameOfSubNode(final String nodeName) throws ExmlBuilderException {
return null;
}
public Class<?> getTypeOfProperty(final String nodeName) throws ExmlBuilderException {
return null;
}
public Class<?> getTypeOfSubNode(final String nodeName) throws ExmlBuilderException {
return null;
}
public Class<?> getTypeOfSubNodeList(final String nodeName) throws ExmlBuilderException {
return null;
}
public String getTreeNameOfSubNode(final String nodeName) throws ExmlBuilderException {
return null;
}
public Class<?> getTypeOfProperty(final String nodeName) throws ExmlBuilderException {
return null;
}
public Class<?> getTypeOfSubProperty(final String nodeName) throws ExmlBuilderException {
return null;
}
public boolean isObject(final String propertyName) {
return Object.class.isAssignableFrom(this.classType);
protected Class<?> getTypeOfText() {
return null;
}
public boolean isRecord(final String propertyName) {
return Record.class.isAssignableFrom(this.classType);
public Object getValue(final String propertyName, final String propertyValue) throws ExmlBuilderException {
return null;
}
public boolean isNative() {
public Object getValueFromText(final String text) throws ExmlBuilderException {
return null;
}
/**
* This permit to know if an alement in the property is able to manage the Whole text under (this remove all parsing of xml inside the model...) Annotation @XmlText
* @return true if a parameter manage the text (otherwise the text is sended to the fromString() function.
*/
public boolean hasTextModel() {
return false;
}
public boolean isArray() {
return false;
}
public boolean isList() {
return false;
}
public abstract String toString(final Object data) throws ExmlBuilderException;
public boolean isEnum() {
return this.classType.isEnum();
}
public String getBeanName(final String nodeName) {
return nodeName;
}
protected boolean isIgnoreUnknown() {
return this.ignoreUnknown;
}
protected boolean isDefaultNullValue() {
return this.defaultNullValue;
}
public boolean isEnum() {
return this.classType.isEnum();
}
protected boolean isIgnoreUnknown() {
return this.ignoreUnknown;
}
public boolean isList() {
return false;
}
public boolean isNative() {
return false;
}
public boolean isObject(final String propertyName) {
return Object.class.isAssignableFrom(this.classType);
}
public boolean isRecord(final String propertyName) {
return Record.class.isAssignableFrom(this.classType);
}
public abstract String toString(final Object data) throws ExmlBuilderException;
}

View File

@ -8,21 +8,21 @@ import java.util.Map;
import org.atriasoft.etk.util.ArraysTools;
import org.atriasoft.exml.exception.ExmlBuilderException;
public class IntrospectionModelArray extends IntrospectionModel {
final String nodeName;
public IntrospectionModelArray(final String nodeName, final Class<?> classType) {
super(classType);
this.nodeName = nodeName;
}
@SuppressWarnings("unchecked")
public static <T> T[] convertList(final Class<T> classType, final List<Object> data) {
final List<T> rootList = (List<T>) data;
final T[] strarr = (T[]) Array.newInstance(classType, 0);
return rootList.toArray(strarr);
}
final String nodeName;
public IntrospectionModelArray(final String nodeName, final Class<?> classType) {
super(classType);
this.nodeName = nodeName;
}
@Override
public Object createObject(final Map<String, Object> properties, final Map<String, List<Object>> nodes) throws ExmlBuilderException {
List<Object> tmp = null;
@ -48,14 +48,19 @@ public class IntrospectionModelArray extends IntrospectionModel {
return null;
}
@Override
public Object getValue(final String propertyName, final String propertyValue) throws ExmlBuilderException {
return null;
}
@Override
public Object getValueFromText(final String text) throws ExmlBuilderException {
return new Object[0];
}
@Override
public Object getValue(final String propertyName, final String propertyValue) throws ExmlBuilderException {
return null;
public boolean hasTextModel() {
return false;
}
@Override

View File

@ -54,26 +54,27 @@ public class IntrospectionModelComplex extends IntrospectionModel {
// ------------------------------------------------------------------------
// -- Parse constructor
// ------------------------------------------------------------------------
Log.verbose("Introspect class: '" + classType.getCanonicalName() + "'");
Log.error("Introspect class: '" + classType.getCanonicalName() + "'");
final Constructor<?>[] constructors = this.classType.getConstructors();
Log.verbose(" Constructors: (" + constructors.length + ")");
Constructor<?> emptyConstructorTmp = null;
for (final Constructor<?> elem : constructors) {
Log.error(" Constructor ??? : {}", elem.toGenericString());
// we does not manage private field
if (!Modifier.isPublic(elem.getModifiers())) {
continue;
}
if (elem.getParameterCount() == 0) {
emptyConstructorTmp = elem;
Log.verbose(" >>> " + elem.toGenericString());
Log.error(" >>> " + elem.toGenericString());
} else {
int offsetSubClass = 0;
if (this.isSubClass) {
offsetSubClass = 1;
}
if (elem.getParameterCount() == 1) {
if (elem.getParameterCount() == 1 && offsetSubClass == 1) {
emptyConstructorTmp = elem;
Log.verbose(" >>> " + elem.toGenericString());
Log.error(" >>> " + elem.toGenericString());
} else {
// Retrieve full description in constructor properties...
String[] namesBeans = ReflectTools.getNames(elem, null);
@ -82,23 +83,23 @@ public class IntrospectionModelComplex extends IntrospectionModel {
} else if (elem.getParameterCount() != namesBeans.length + offsetSubClass) {
throw new ExmlBuilderException("Wrong number of parameter in constructor with ne number declared in the @XmlName (for bean name)");
}
Boolean[] isAttributes = new Boolean[elem.getParameterCount() - offsetSubClass];
Boolean[] isCaseSensitives = new Boolean[elem.getParameterCount() - offsetSubClass];
Boolean[] isOptionals = new Boolean[elem.getParameterCount() - offsetSubClass];
Boolean[] isManageds = new Boolean[elem.getParameterCount() - offsetSubClass];
final Boolean[] isAttributes = new Boolean[elem.getParameterCount() - offsetSubClass];
final Boolean[] isCaseSensitives = new Boolean[elem.getParameterCount() - offsetSubClass];
final Boolean[] isOptionals = new Boolean[elem.getParameterCount() - offsetSubClass];
final Boolean[] isManageds = new Boolean[elem.getParameterCount() - offsetSubClass];
Class<?>[][] clazz = new Class<?>[elem.getParameterCount() - offsetSubClass][];
String[][] names = new String[elem.getParameterCount() - offsetSubClass][];
final Class<?>[][] clazz = new Class<?>[elem.getParameterCount() - offsetSubClass][];
final String[][] names = new String[elem.getParameterCount() - offsetSubClass][];
Parameter[] params = elem.getParameters();
final Parameter[] params = elem.getParameters();
for (int iii = offsetSubClass; iii < params.length; iii++) {
Parameter paramElem = params[iii];
final Parameter paramElem = params[iii];
isAttributes[iii - offsetSubClass] = ReflectTools.getIsAttribute(elem, paramElem, null);
isCaseSensitives[iii - offsetSubClass] = ReflectTools.getIsCaseSensitive(elem, paramElem, null);
isOptionals[iii - offsetSubClass] = ReflectTools.getIsOptional(elem, paramElem, null);
isManageds[iii - offsetSubClass] = ReflectTools.getIsManaged(elem, paramElem, null);
String[] namesParam = ReflectTools.getNames(elem, paramElem, null);
Class<?>[] types = ReflectTools.getTypeParameterfunction(elem, iii);
final String[] namesParam = ReflectTools.getNames(elem, paramElem, null);
final Class<?>[] types = ReflectTools.getTypeParameterfunction(elem, iii);
clazz[iii - offsetSubClass] = types;
names[iii - offsetSubClass] = namesParam;
if (namesParam != null && namesParam.length != 0) {
@ -117,15 +118,15 @@ public class IntrospectionModelComplex extends IntrospectionModel {
prop = new IntrospectionProperty(namesBeans[iii], clazz[iii], names[iii]);
this.elements.add(prop);
} else {
Class<?> curentType = prop.getType();
Class<?> curentSubType = prop.getSubType();
final Class<?> curentType = prop.getType();
final Class<?> curentSubType = prop.getSubType();
if (curentType != clazz[iii][0] && curentSubType != clazz[iii][1]) {
throw new ExmlBuilderException("Set 'return type' with a different value previous=" + curentType.getCanonicalName() + " / " + curentSubType.getCanonicalName()
+ " ==> new=" + clazz[iii][0] + " / " + clazz[iii][1] + " in " + elem.toGenericString());
}
String[] names1 = names[iii];
final String[] names1 = names[iii];
if (names1 != null) {
String[] curentValue = prop.getNames();
final String[] curentValue = prop.getNames();
if (curentValue != null) {
// TODO maybe set the value permissive if no change !!! like the others...
throw new ExmlBuilderException("Set 'names' with a (already set!) " + elem.toGenericString());
@ -137,7 +138,7 @@ public class IntrospectionModelComplex extends IntrospectionModel {
prop.setCanBeSetByConstructor(true);
final Boolean isAttribute = isAttributes[iii];
if (isAttribute != null) {
Boolean curentValue = prop.isAttribute();
final Boolean curentValue = prop.isAttribute();
if (curentValue != null && curentValue != isAttribute) {
throw new ExmlBuilderException("Set 'attribute' with a different value previous=" + curentValue + " ==> new=" + isAttribute + " in " + elem.toGenericString());
}
@ -145,7 +146,7 @@ public class IntrospectionModelComplex extends IntrospectionModel {
}
final Boolean isCaseSensitive = isCaseSensitives[iii];
if (isCaseSensitive != null) {
Boolean curentValue = prop.isCaseSensitive();
final Boolean curentValue = prop.isCaseSensitive();
if (curentValue != null && curentValue != isCaseSensitive) {
throw new ExmlBuilderException(
"Set 'caseSensitive' with a different value previous=" + curentValue + " ==> new=" + isCaseSensitive + " in " + elem.toGenericString());
@ -154,7 +155,7 @@ public class IntrospectionModelComplex extends IntrospectionModel {
}
final Boolean isOptional = isOptionals[iii];
if (isOptional != null) {
Boolean curentValue = prop.isOptionnal();
final Boolean curentValue = prop.isOptionnal();
if (curentValue != null && curentValue != isOptional) {
throw new ExmlBuilderException("Set 'optionnal' with a different value previous=" + curentValue + " ==> new=" + isOptional + " in " + elem.toGenericString());
}
@ -162,7 +163,7 @@ public class IntrospectionModelComplex extends IntrospectionModel {
}
final Boolean isManaged = isManageds[iii];
if (isManaged != null) {
Boolean curentValue = prop.isManaged();
final Boolean curentValue = prop.isManaged();
if (curentValue != null && curentValue != isManaged) {
throw new ExmlBuilderException("Set 'managed' with a different value previous=" + curentValue + " ==> new=" + isManaged + " in " + elem.toGenericString());
}
@ -175,12 +176,12 @@ public class IntrospectionModelComplex extends IntrospectionModel {
}
}
this.constructorEmpty = emptyConstructorTmp;
Log.error(" ==> constructor = {}", this.constructorEmpty);
// Order the constructor from the bigger number of element to the lowest...
Collections.sort(this.constructors, (a, b) -> a.values().length - b.values().length);
for (ConstructorModel elem : this.constructors) {
for (final ConstructorModel elem : this.constructors) {
Log.verbose(" * " + elem.constructor().toGenericString());
StringBuilder tmpPrint = new StringBuilder(" ==> (");
final StringBuilder tmpPrint = new StringBuilder(" ==> (");
if (this.isSubClass) {
tmpPrint.append("null, ");
}
@ -196,9 +197,9 @@ public class IntrospectionModelComplex extends IntrospectionModel {
final List<String> recordAllPossibleValues = new ArrayList<>();
final List<String> recordAllPossibleValuesFiltered = new ArrayList<>();
if (this.isRecord) {
for (ConstructorModel elem : this.constructors) {
for (final ConstructorModel elem : this.constructors) {
for (int iii = 0; iii < elem.values().length; iii++) {
String tmpp = elem.values()[iii];
final String tmpp = elem.values()[iii];
if (!recordAllPossibleValues.contains(tmpp)) {
recordAllPossibleValues.add(tmpp);
}
@ -221,22 +222,22 @@ public class IntrospectionModelComplex extends IntrospectionModel {
continue;
}
final String[] names = ReflectTools.getNames(elem, null);
Class<?>[] types = ReflectTools.getTypeField(elem);
final Class<?>[] types = ReflectTools.getTypeField(elem);
IntrospectionProperty prop = findElement(elem.getName());
if (prop == null) {
prop = new IntrospectionProperty(elem.getName(), types, names);
this.elements.add(prop);
} else {
Class<?> curentType = prop.getType();
Class<?> curentSubType = prop.getSubType();
final Class<?> curentType = prop.getType();
final Class<?> curentSubType = prop.getSubType();
if (curentType != types[0] && curentSubType != types[1]) {
throw new ExmlBuilderException("Set 'return type' with a different value previous=" + curentType.getCanonicalName() + " / " + curentSubType.getCanonicalName() + " ==> new="
+ types[0] + " / " + types[1] + " in " + elem.toGenericString());
}
String[] names1 = names;
final String[] names1 = names;
if (names1 != null) {
String[] curentValue = prop.getNames();
final String[] curentValue = prop.getNames();
if (curentValue != null) {
// TODO maybe set the value permissive if no change !!! like the others...
throw new ExmlBuilderException("Set 'names' with a (already set!) " + elem.toGenericString());
@ -265,9 +266,17 @@ public class IntrospectionModelComplex extends IntrospectionModel {
if (isCaseSensitive != null) {
prop.setCaseSensitive(isCaseSensitive);
}
final Boolean isText = ReflectTools.getIsText(elem, null);
if (isText != null) {
prop.setTextMode(isText);
}
final Class<?> factory = ReflectTools.getFactory(elem);
if (factory != null) {
prop.setFactory(factory);
}
// generate getter and setter with field.
IntrospectionPropertyField modifier = new IntrospectionPropertyField(elem);
final IntrospectionPropertyField modifier = new IntrospectionPropertyField(elem);
// if the field is final ==> we can not set the value...
if (Modifier.isFinal(elem.getModifiers())) {
prop.setGetter(modifier);
@ -397,24 +406,24 @@ public class IntrospectionModelComplex extends IntrospectionModel {
// associate methods by pair.
for (final Method method : methodsGet) {
final String name = Tools.decapitalizeFirst(this.isRecord ? method.getName() : method.getName().substring(3));
IntrospectionProperty prop = updateForMethod(name, method, ReflectTools.getTypeReturnFunction(method));
final IntrospectionProperty prop = updateForMethod(name, method, ReflectTools.getTypeReturnFunction(method));
// generate getter and setter with field.
IntrospectionPropertyMethodGetter modifier = new IntrospectionPropertyMethodGetter(method);
final IntrospectionPropertyMethodGetter modifier = new IntrospectionPropertyMethodGetter(method);
prop.setGetter(modifier);
}
if (!this.isRecord) {
for (final Method method : methodsIs) {
final String name = Tools.decapitalizeFirst(method.getName().substring(2));
IntrospectionProperty prop = updateForMethod(name, method, ReflectTools.getTypeReturnFunction(method));
final IntrospectionProperty prop = updateForMethod(name, method, ReflectTools.getTypeReturnFunction(method));
// generate getter and setter with field.
IntrospectionPropertyMethodGetter modifier = new IntrospectionPropertyMethodGetter(method);
final IntrospectionPropertyMethodGetter modifier = new IntrospectionPropertyMethodGetter(method);
prop.setGetter(modifier);
}
for (final Method method : methodsSet) {
final String name = Tools.decapitalizeFirst(method.getName().substring(3));
IntrospectionProperty prop = updateForMethod(name, method, ReflectTools.getTypeParameterfunction(method));
final IntrospectionProperty prop = updateForMethod(name, method, ReflectTools.getTypeParameterfunction(method));
// generate getter and setter with field.
IntrospectionPropertyMethodSetter modifier = new IntrospectionPropertyMethodSetter(method);
final IntrospectionPropertyMethodSetter modifier = new IntrospectionPropertyMethodSetter(method);
prop.setSetter(modifier);
}
}
@ -424,37 +433,37 @@ public class IntrospectionModelComplex extends IntrospectionModel {
// Set only at the end ==> no need before...
final Boolean isDefaultAttribute = ReflectTools.getIsDefaultAttribute(classType, IntrospectionModel.DEFAULT_ATTRIBUTE);
for (IntrospectionProperty prop : this.elements) {
for (final IntrospectionProperty prop : this.elements) {
if (prop.isAttribute() == null) {
prop.setAttribute(isDefaultAttribute);
}
}
final Boolean isDefaultManaged = ReflectTools.getIsDefaultManaged(classType, IntrospectionModel.DEFAULT_MANAGED);
for (IntrospectionProperty prop : this.elements) {
for (final IntrospectionProperty prop : this.elements) {
if (prop.isManaged() == null) {
prop.setManaged(isDefaultManaged);
}
}
final Boolean isDefaultOptional = ReflectTools.getIsDefaultOptional(classType, IntrospectionModel.DEFAULT_OPTIONAL);
for (IntrospectionProperty prop : this.elements) {
for (final IntrospectionProperty prop : this.elements) {
if (prop.isOptionnal() == null) {
prop.setOptionnal(isDefaultOptional);
}
}
final Boolean isDefaultCaseSensitive = ReflectTools.getIsDefaultCaseSensitive(classType, IntrospectionModel.DEFAULT_CASE_SENSITIVE);
for (IntrospectionProperty prop : this.elements) {
for (final IntrospectionProperty prop : this.elements) {
if (prop.isCaseSensitive() == null) {
prop.setCaseSensitive(isDefaultCaseSensitive);
}
}
// set default name in the list:
for (IntrospectionProperty prop : this.elements) {
for (final IntrospectionProperty prop : this.elements) {
if (prop.getNames() == null) {
prop.setNames(new String[] { prop.getBeanName() });
}
}
} catch (Exception ex) {
} catch (final Exception ex) {
ex.printStackTrace();
throw new ExmlBuilderException("Error in creating introspection data ... " + ex.getMessage());
}
@ -462,21 +471,22 @@ public class IntrospectionModelComplex extends IntrospectionModel {
// Sort the parameters to generate all time the same XML..
Collections.sort(this.elements, (a, b) -> a.getNames()[0].compareTo(b.getNames()[0]));
for (IntrospectionProperty prop : this.elements) {
Log.debug("Property/node : " + prop.getBeanName());
Log.debug(" names: " + Arrays.toString(prop.getNames()));
Log.debug(" list: " + prop.getListName());
Log.debug(" managed: " + prop.isManaged());
Log.debug(" attribute: " + prop.isAttribute());
Log.debug(" case-sensitive: " + prop.isCaseSensitive());
Log.debug(" optionnal: " + prop.isOptionnal());
Log.debug(" constructor: " + prop.isCanBeSetByConstructor());
Log.debug(" get/set: " + prop.canGetValue() + " / " + prop.canSetValue());
Log.debug(" type: " + prop.getType().getCanonicalName());
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.debug(" sub-type: " + prop.getSubType().getCanonicalName());
Log.verbose(" sub-type: " + prop.getSubType().getCanonicalName());
} else {
Log.debug(" sub-type: null");
Log.verbose(" sub-type: null");
}
}
@ -484,7 +494,7 @@ public class IntrospectionModelComplex extends IntrospectionModel {
@SuppressWarnings("unchecked")
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()];
final T[] out = (T[]) java.lang.reflect.Array.newInstance(clazz, data.size());// T[data.size()];
for (int iii = 0; iii < data.size(); iii++) {
out[iii] = (T) data.get(iii);
@ -534,15 +544,15 @@ public class IntrospectionModelComplex extends IntrospectionModel {
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[] inputsTmp = new Object[elem.values().length + offset];
for (final ConstructorModel elem : this.constructors) {
final int offset = this.isSubClass ? 1 : 0;
final 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]);
final List<Object> tmppp = nodes.get(elem.values()[iii]);
if (tmppp != null) {
if (List.class == findBeanNodeDescription(elem.values()[iii]).getType()) {
valueToInject = tmppp;
@ -566,7 +576,7 @@ public class IntrospectionModelComplex extends IntrospectionModel {
}
if (betterModel != null) {
if (isDefaultNullValue() || lastEmpty == 0) {
ConstructorModel elem = betterModel;
final ConstructorModel elem = betterModel;
if (inputs != null) {
// here we find our constructor...
try {
@ -625,23 +635,24 @@ public class IntrospectionModelComplex extends IntrospectionModel {
throw new ExmlBuilderException("No constructor accessible for class: " + this.classType.getCanonicalName());
}
try {
Log.error("create class : {} with subClass={}", this.classType.getCanonicalName(), this.isSubClass);
Log.error(" ==> constructor = {}", this.constructorEmpty);
if (this.isSubClass) {
Object tmp2 = null;
final Object tmp2 = null;
tmp = this.constructorEmpty.newInstance(tmp2);
} else {
tmp = this.constructorEmpty.newInstance();
}
} catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return null;
}
}
// STEP 3: set the rest if the parameters...
for (Entry<String, Object> elem : properties.entrySet()) {
for (final Entry<String, Object> elem : properties.entrySet()) {
setValue(tmp, elem.getKey(), elem.getValue());
}
for (Entry<String, List<Object>> elem : nodes.entrySet()) {
for (final Entry<String, List<Object>> elem : nodes.entrySet()) {
setValue(tmp, elem.getKey(), elem.getValue());
}
return tmp;
@ -672,7 +683,7 @@ public class IntrospectionModelComplex extends IntrospectionModel {
}
protected IntrospectionProperty findElement(final String beanName) {
for (IntrospectionProperty elem : this.elements) {
for (final IntrospectionProperty elem : this.elements) {
if (elem.getBeanName().equals(beanName)) {
return elem;
}
@ -706,8 +717,8 @@ public class IntrospectionModelComplex extends IntrospectionModel {
@Override
public List<IntrospectionProperty> getAttributes() {
List<IntrospectionProperty> out = new ArrayList<>();
for (IntrospectionProperty elem : this.elements) {
final List<IntrospectionProperty> out = new ArrayList<>();
for (final IntrospectionProperty elem : this.elements) {
if (elem.isAttribute()) {
out.add(elem);
}
@ -717,7 +728,7 @@ public class IntrospectionModelComplex extends IntrospectionModel {
@Override
public String getBeanName(final String nodeName) {
for (IntrospectionProperty elem : this.elements) {
for (final IntrospectionProperty elem : this.elements) {
if (elem.isCompatible(nodeName)) {
return elem.getBeanName();
}
@ -725,9 +736,22 @@ public class IntrospectionModelComplex extends IntrospectionModel {
return null;
}
@Override
public String getBeanNameModel(final String nodeName) {
for (final IntrospectionProperty elem : this.elements) {
if (elem.isCompatible(nodeName)) {
if (elem.hasFactory()) {
return elem.getBeanName() + "#" + nodeName;
}
return elem.getBeanName();
}
}
return null;
}
@Override
public List<String> getNodeAvaillable() {
List<String> out = new ArrayList<>();
final List<String> out = new ArrayList<>();
for (final IntrospectionProperty prop : this.elements) {
if (prop.isAttribute()) {
continue;
@ -739,8 +763,8 @@ public class IntrospectionModelComplex extends IntrospectionModel {
@Override
public List<IntrospectionProperty> getNodes() {
List<IntrospectionProperty> out = new ArrayList<>();
for (IntrospectionProperty elem : this.elements) {
final List<IntrospectionProperty> out = new ArrayList<>();
for (final IntrospectionProperty elem : this.elements) {
if (!elem.isAttribute()) {
out.add(elem);
}
@ -748,6 +772,17 @@ public class IntrospectionModelComplex extends IntrospectionModel {
return out;
}
@Override
public String getTextBeanName() {
for (final IntrospectionProperty prop : this.elements) {
final Boolean isText = prop.isText();
if (isText != null && isText) {
return prop.getBeanName();
}
}
return null;
}
@Override
public String getTreeNameOfSubNode(final String nodeBeanName) throws ExmlBuilderException {
Log.debug(" nodeType='" + nodeBeanName + "'");
@ -768,7 +803,7 @@ public class IntrospectionModelComplex extends IntrospectionModel {
return propField.getType();
}
throw new ExmlBuilderException("can not find the field '" + nodeName + "' availlable: " + getNodeAvaillable());
throw new ExmlBuilderException("can not find the field '" + nodeName + "' available: " + getNodeAvaillable());
}
/**
@ -777,25 +812,37 @@ public class IntrospectionModelComplex extends IntrospectionModel {
* @return Class of the node to create
*/
@Override
public Class<?> getTypeOfSubNode(final String nodeBeanName) throws ExmlBuilderException {
public Class<?> getTypeOfSubNode(final String nodeBeanNames) throws ExmlBuilderException {
final String[] elemstNames = nodeBeanNames.split("#");
final String nodeBeanName = elemstNames[0];
Log.debug(" nodeType='" + nodeBeanName + "'");
final IntrospectionProperty propMethode = findBeanNodeDescription(nodeBeanName);
if (propMethode != null && propMethode.canSetValue()) {
Log.debug(" ==> find '" + propMethode.getNames());
return propMethode.getType();
if (propMethode.hasFactory()) {
return propMethode.getCompatible(elemstNames[1]);
} else {
return propMethode.getType();
}
}
throw new ExmlBuilderException("can not find the field '" + nodeBeanName + "' availlable: " + getNodeAvaillable());
throw new ExmlBuilderException("can not find the field '" + nodeBeanName + "' available: " + getNodeAvaillable());
}
@Override
public Class<?> getTypeOfSubNodeList(final String nodeBeanName) throws ExmlBuilderException {
public Class<?> getTypeOfSubNodeList(final String nodeBeanNames) throws ExmlBuilderException {
final String[] elemstNames = nodeBeanNames.split("#");
final String nodeBeanName = elemstNames[0];
Log.debug(" nodeType='" + nodeBeanName + "'");
final IntrospectionProperty propMethode = findBeanNodeDescription(nodeBeanName);
if (propMethode != null && propMethode.canSetValue()) {
Log.debug(" ==> find '" + propMethode.getNames());
return propMethode.getSubType();
if (propMethode.hasFactory()) {
return propMethode.getCompatible(elemstNames[1]);
} else {
return propMethode.getSubType();
}
}
throw new ExmlBuilderException("can not find the field '" + nodeBeanName + "' availlable: " + getNodeAvaillable());
throw new ExmlBuilderException("can not find the field '" + nodeBeanName + "' available: " + getNodeAvaillable());
}
@Override
@ -806,7 +853,18 @@ public class IntrospectionModelComplex extends IntrospectionModel {
Log.debug(" ==> find '" + propField.getNames());
return propField.getSubType();
}
throw new ExmlBuilderException("can not find the field '" + nodeName + "' availlable: " + getNodeAvaillable());
throw new ExmlBuilderException("can not find the field '" + nodeName + "' available: " + getNodeAvaillable());
}
@Override
public Class<?> getTypeOfText() {
for (final IntrospectionProperty prop : this.elements) {
final Boolean isText = prop.isText();
if (isText != null && isText) {
return prop.getType();
}
}
return null;
}
@Override
@ -878,6 +936,19 @@ public class IntrospectionModelComplex extends IntrospectionModel {
}
}
@Override
public boolean hasTextModel() {
Log.warning("in {}", this.classType.getCanonicalName());
for (final IntrospectionProperty prop : this.elements) {
Log.warning(" check {}, manage={} cas setValue={} isText={}", prop.getBeanName(), prop.isManaged(), prop.canSetValue(), prop.isText());
final Boolean isText = prop.isText();
if (isText != null && isText) {
return true;
}
}
return false;
}
@Override
public boolean isNative() {
return false;
@ -894,10 +965,10 @@ public class IntrospectionModelComplex extends IntrospectionModel {
propMethode.setExistingValue(data, value);
} else if (value instanceof List) {
@SuppressWarnings("unchecked")
List<Object> tmpp = (List<Object>) value;
final List<Object> tmpp = (List<Object>) value;
if (propMethode.getType().isArray()) {
if (propMethode.getType().componentType().isPrimitive()) {
Object newData = ArraysTools.listToPrimitiveAuto(propMethode.getType().componentType(), tmpp);
final Object newData = ArraysTools.listToPrimitiveAuto(propMethode.getType().componentType(), tmpp);
propMethode.setExistingValue(data, newData);
} else {
Log.verbose(" datas type: " + autoCast(propMethode.getType().componentType(), tmpp).getClass().getCanonicalName());
@ -910,25 +981,25 @@ public class IntrospectionModelComplex extends IntrospectionModel {
// impossible case ...
}
} else if (propMethode.getType() == byte.class) {
byte dataPrimitive = (Byte) value;
final byte dataPrimitive = (Byte) value;
propMethode.setExistingValue(data, dataPrimitive);
} else if (propMethode.getType() == short.class) {
short dataPrimitive = (Short) value;
final short dataPrimitive = (Short) value;
propMethode.setExistingValue(data, dataPrimitive);
} else if (propMethode.getType() == int.class) {
int dataPrimitive = (Integer) value;
final int dataPrimitive = (Integer) value;
propMethode.setExistingValue(data, dataPrimitive);
} else if (propMethode.getType() == long.class) {
long dataPrimitive = (Long) value;
final long dataPrimitive = (Long) value;
propMethode.setExistingValue(data, dataPrimitive);
} else if (propMethode.getType() == boolean.class) {
boolean dataPrimitive = (Boolean) value;
final boolean dataPrimitive = (Boolean) value;
propMethode.setExistingValue(data, dataPrimitive);
} else if (propMethode.getType() == float.class) {
float dataPrimitive = (Float) value;
final float dataPrimitive = (Float) value;
propMethode.setExistingValue(data, dataPrimitive);
} else if (propMethode.getType() == double.class) {
double dataPrimitive = (Double) value;
final double dataPrimitive = (Double) value;
propMethode.setExistingValue(data, dataPrimitive);
} else {
@ -945,50 +1016,50 @@ public class IntrospectionModelComplex extends IntrospectionModel {
propField.setExistingValue(data, value);
// Some specific case for primitives values
} else if (propField.getType() == byte.class) {
byte dataPrimitive = (Byte) value;
final byte dataPrimitive = (Byte) value;
propField.setExistingValue(data, dataPrimitive);
} else if (propField.getType() == short.class) {
short dataPrimitive = (Short) value;
final short dataPrimitive = (Short) value;
propField.setExistingValue(data, dataPrimitive);
} else if (propField.getType() == int.class) {
int dataPrimitive = (Integer) value;
final int dataPrimitive = (Integer) value;
propField.setExistingValue(data, dataPrimitive);
} else if (propField.getType() == long.class) {
long dataPrimitive = (Long) value;
final long dataPrimitive = (Long) value;
propField.setExistingValue(data, dataPrimitive);
} else if (propField.getType() == float.class) {
float dataPrimitive = (Float) value;
final float dataPrimitive = (Float) value;
propField.setExistingValue(data, dataPrimitive);
} else if (propField.getType() == double.class) {
Double dataPrimitive = (Double) value;
final Double dataPrimitive = (Double) value;
propField.setExistingValue(data, dataPrimitive);
} else if (propField.getType() == boolean.class) {
boolean dataPrimitive = (Boolean) value;
final boolean dataPrimitive = (Boolean) value;
propField.setExistingValue(data, dataPrimitive);
} else {
@SuppressWarnings("unchecked")
List<Object> tmpp = (List<Object>) value;
final List<Object> tmpp = (List<Object>) value;
if (propField.getType().isArray()) {
if (propField.getType().componentType() == byte.class) {
byte[] datas = ArraysTools.listByteToPrimitive(tmpp);
final byte[] datas = ArraysTools.listByteToPrimitive(tmpp);
propField.setExistingValue(data, datas);
} else if (propField.getType().componentType() == short.class) {
short[] datas = ArraysTools.listShortToPrimitive(tmpp);
final short[] datas = ArraysTools.listShortToPrimitive(tmpp);
propField.setExistingValue(data, datas);
} else if (propField.getType().componentType() == int.class) {
int[] datas = ArraysTools.listIntegerToPrimitive(tmpp);
final int[] datas = ArraysTools.listIntegerToPrimitive(tmpp);
propField.setExistingValue(data, datas);
} else if (propField.getType().componentType() == long.class) {
long[] datas = ArraysTools.listLongToPrimitive(tmpp);
final long[] datas = ArraysTools.listLongToPrimitive(tmpp);
propField.setExistingValue(data, datas);
} else if (propField.getType().componentType() == boolean.class) {
boolean[] datas = ArraysTools.listBooleanToPrimitive(tmpp);
final boolean[] datas = ArraysTools.listBooleanToPrimitive(tmpp);
propField.setExistingValue(data, datas);
} else if (propField.getType().componentType() == float.class) {
float[] datas = ArraysTools.listFloatToPrimitive(tmpp);
final float[] datas = ArraysTools.listFloatToPrimitive(tmpp);
propField.setExistingValue(data, datas);
} else if (propField.getType().componentType() == double.class) {
double[] datas = ArraysTools.listDoubleToPrimitive(tmpp);
final double[] datas = ArraysTools.listDoubleToPrimitive(tmpp);
propField.setExistingValue(data, datas);
} else {
Log.verbose(" datas type: " + autoCast(propField.getType().componentType(), tmpp).getClass().getCanonicalName());
@ -1030,19 +1101,19 @@ public class IntrospectionModelComplex extends IntrospectionModel {
private IntrospectionProperty updateForMethod(final String name, final Method method, final Class<?>[] types) throws Exception {
IntrospectionProperty prop = findElement(name);
if (prop == null) {
String[] names = ReflectTools.getNames(method, null);
final String[] names = ReflectTools.getNames(method, null);
prop = new IntrospectionProperty(name, types, names);
this.elements.add(prop);
} else {
Class<?> curentType = prop.getType();
Class<?> curentSubType = prop.getSubType();
final Class<?> curentType = prop.getType();
final Class<?> curentSubType = prop.getSubType();
if (curentType != types[0] && curentSubType != types[1]) {
throw new ExmlBuilderException("Set 'return type' with a different value previous=" + curentType.getCanonicalName() + " / " + curentSubType.getCanonicalName() + " ==> new=" + types[0]
+ " / " + types[1] + " in " + method.toGenericString());
}
String[] names = ReflectTools.getNames(method, null);
final String[] names = ReflectTools.getNames(method, null);
if (names != null) {
String[] curentValue = prop.getNames();
final String[] curentValue = prop.getNames();
if (curentValue != null && !checkIdenticalArray(curentValue, names)) {
// TODO maybe set the value permissive if no change !!! like the others...
throw new ExmlBuilderException("Set 'names' with a (already set!) " + method.toGenericString());
@ -1052,7 +1123,7 @@ public class IntrospectionModelComplex extends IntrospectionModel {
}
final String listName = ReflectTools.getListName(method, null);
if (listName != null) {
String curentValue = prop.getListName();
final String curentValue = prop.getListName();
if (curentValue != null && curentValue != listName) {
throw new ExmlBuilderException("Set 'listNAme' with a different value previous=" + curentValue + " ==> new=" + listName + " in " + method.toGenericString());
}
@ -1060,7 +1131,7 @@ public class IntrospectionModelComplex extends IntrospectionModel {
}
final Boolean isAttribute = ReflectTools.getIsAttribute(method, null);
if (isAttribute != null) {
Boolean curentValue = prop.isAttribute();
final Boolean curentValue = prop.isAttribute();
if (curentValue != null && curentValue != isAttribute) {
throw new ExmlBuilderException("Set 'attribute' with a different value previous=" + curentValue + " ==> new=" + isAttribute + " in " + method.toGenericString());
}
@ -1068,7 +1139,7 @@ public class IntrospectionModelComplex extends IntrospectionModel {
}
final Boolean isManaged = ReflectTools.getIsManaged(method, null);
if (isManaged != null) {
Boolean curentValue = prop.isManaged();
final Boolean curentValue = prop.isManaged();
if (curentValue != null && curentValue != isManaged) {
throw new ExmlBuilderException("Set 'managed' with a different value previous=" + curentValue + " ==> new=" + isManaged + " in " + method.toGenericString());
}
@ -1076,7 +1147,7 @@ public class IntrospectionModelComplex extends IntrospectionModel {
}
final Boolean isOptionnal = ReflectTools.getIsOptional(method, null);
if (isOptionnal != null) {
Boolean curentValue = prop.isOptionnal();
final Boolean curentValue = prop.isOptionnal();
if (curentValue != null && curentValue != isOptionnal) {
throw new ExmlBuilderException("Set 'optionnal' with a different value previous=" + curentValue + " ==> new=" + isOptionnal + " in " + method.toGenericString());
}
@ -1084,12 +1155,24 @@ public class IntrospectionModelComplex extends IntrospectionModel {
}
final Boolean isCaseSensitive = ReflectTools.getIsCaseSensitive(method, null);
if (isCaseSensitive != null) {
Boolean curentValue = prop.isCaseSensitive();
final Boolean curentValue = prop.isCaseSensitive();
if (curentValue != null && curentValue != isCaseSensitive) {
throw new ExmlBuilderException("Set 'case sensitive' with a different value previous=" + curentValue + " ==> new=" + isCaseSensitive + " in " + method.toGenericString());
}
prop.setCaseSensitive(isCaseSensitive);
}
final Boolean isText = ReflectTools.getIsText(method, null);
if (isText != null) {
final Boolean curentValue = prop.isText();
if (curentValue != null && curentValue != isText) {
throw new ExmlBuilderException("Set 'case sensitive' with a different value previous=" + curentValue + " ==> new=" + isText + " in " + method.toGenericString());
}
prop.setTextMode(isText);
}
final Class<?> factory = ReflectTools.getFactory(method);
if (factory != null) {
prop.setFactory(factory);
}
return prop;
}
}

View File

@ -11,6 +11,7 @@ import org.atriasoft.exml.exception.ExmlNodeDoesNotExist;
import org.atriasoft.exml.internal.Log;
public class IntrospectionObject {
public static final String PUBLIC_TEXT_NAME = "##<< ** TEXT-ZONE ** >>##";
public static final String STUPID_TOCKEN = "___aé\"'__-è==**ù!^$:;,;AZEARTYUIOPMLKJHGFDSQW>XCVBN?"; // can not exist ....
private final IntrospectionModel modelInterface;
private Object data = null;
@ -63,7 +64,7 @@ public class IntrospectionObject {
Log.error("this is a big problem ...");
Log.error("this is a big problem ...");
} else if (List.class.isAssignableFrom(value.getClass())) {
List<Object> nodeIn = (List<Object>) value;
final List<Object> nodeIn = (List<Object>) value;
node.addAll(nodeIn);
} else {
node.add(value);
@ -112,7 +113,8 @@ public class IntrospectionObject {
* @return Class of the node to create
*/
public Class<?> getTypeOfSubNode(final String nodeName) throws ExmlException {
final String beanName = this.modelInterface.getBeanName(nodeName);
final String beanName = this.modelInterface.getBeanNameModel(nodeName);
if (beanName == null) {
throw new ExmlNodeDoesNotExist("The node '" + nodeName + "' Does not exist...");
}
@ -120,7 +122,7 @@ public class IntrospectionObject {
}
public Class<?> getTypeOfSubNodeSubType(final String nodeName) throws ExmlException {
final String beanName = this.modelInterface.getBeanName(nodeName);
final String beanName = this.modelInterface.getBeanNameModel(nodeName);
if (beanName == null) {
throw new ExmlNodeDoesNotExist("The node '" + nodeName + "' Does not exist...");
}
@ -144,7 +146,12 @@ public class IntrospectionObject {
}
public void putProperty(final String propertyName, final Object propertyValue) throws ExmlException {
final String beanName = this.modelInterface.getBeanName(propertyName);
String beanName = null;
if (propertyName == PUBLIC_TEXT_NAME) {
beanName = this.modelInterface.getTextBeanName();
} else {
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");
}

View File

@ -1,10 +1,13 @@
package org.atriasoft.exml.builder;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map.Entry;
import org.atriasoft.eStringSerialize.StringSerializer;
import org.atriasoft.exml.annotation.XmlFactory.InterfaceXmlFactoryAccess;
import org.atriasoft.exml.exception.ExmlBuilderException;
import org.atriasoft.exml.internal.Log;
@ -17,6 +20,7 @@ public final class IntrospectionProperty {
private Boolean optionnal = null;
// Attribute or Node (set at null while not define by a function attribute, parameter ...)
private Boolean attribute = null;
private Boolean textMode = null;
// name of the field or the function before renaming...
private final String beanName;
// names that can take the Node or the aatibute
@ -24,14 +28,14 @@ public final class IntrospectionProperty {
// if organized in sublist (!= null) then the subNode have this value
private String listName = null;
private boolean canBeSetByConstructor = false;
private Class<?> factory = null;
private InterfaceXmlFactoryAccess factoryCreated = null;
private final Class<?> type;
private final Class<?> subType;
// can get the property, if null not gettable ... ==> TODO need to remove this property ???
// First function call
// second field access
IntrospectionPropertyGetter getter = null;
// can get the property, if null not settable (otherwise use the constructor???)
// First constructor call
// second function call
@ -71,12 +75,12 @@ public final class IntrospectionProperty {
} else if ((this.type != List.class) || !StringSerializer.contains(this.subType)) {
throw new ExmlBuilderException("Can not parse the specific element ... need to introspect and find the 'xxx valueOf(String data);'");
}
ArrayList<Object> out = new ArrayList<>();
for (String elem : value.split(";")) {
final ArrayList<Object> out = new ArrayList<>();
for (final String elem : value.split(";")) {
out.add(StringSerializer.valueOf(this.subType, elem));
}
return out;
} catch (IllegalArgumentException e) {
} catch (final IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
throw new ExmlBuilderException("Error in parsing the property value ... " + e.getMessage());
@ -87,6 +91,58 @@ public final class IntrospectionProperty {
return this.beanName;
}
public Class<?> getCompatible(final String name) {
final InterfaceXmlFactoryAccess factoryGenerator = getFactory();
if (factoryGenerator != null) {
if (this.caseSensitive) {
for (final Entry<String, Class<?>> elem : factoryGenerator.getConversionMap().entrySet()) {
if (elem.getKey().contentEquals(name)) {
return elem.getValue();
}
}
} else {
for (final Entry<String, Class<?>> elem : factoryGenerator.getConversionMap().entrySet()) {
if (elem.getKey().equalsIgnoreCase(name)) {
return elem.getValue();
}
}
}
return null;
}
if (this.caseSensitive) {
for (final String elem : this.names) {
if (elem.contentEquals(name)) {
Log.verbose(" - '{}' ==> true", elem);
return getType();
}
Log.verbose(" - '{}' == false", elem);
}
} else {
for (final String elem : this.names) {
if (elem.equalsIgnoreCase(name)) {
Log.verbose(" - '{}' ==> true", elem);
return getType();
}
Log.verbose(" - '{}' == false", elem);
}
}
return null;
}
public InterfaceXmlFactoryAccess getFactory() {
if (this.factoryCreated == null && this.factory != null) {
try {
this.factoryCreated = (InterfaceXmlFactoryAccess) this.factory.getConstructor().newInstance();
} catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException | SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
this.factoryCreated = null;
this.factory = null;
}
}
return this.factoryCreated;
}
public String getListName() {
return this.listName;
}
@ -128,6 +184,10 @@ public final class IntrospectionProperty {
throw new ExmlBuilderException("Property: " + this.names + " have no getter");
}
public boolean hasFactory() {
return this.factory != null;
}
public Boolean isAttribute() {
return this.attribute;
}
@ -146,22 +206,44 @@ public final class IntrospectionProperty {
* @return true if the element is compatible, false otherwise
*/
public boolean isCompatible(final String name) {
Log.verbose("Check compatible : '" + name + "' in " + Arrays.toString(this.names));
Log.verbose("Check compatible : '{}' in {}", name, Arrays.toString(this.names));
final InterfaceXmlFactoryAccess factoryGenerator = getFactory();
if (factoryGenerator != null) {
Log.verbose(" ===> Detect factory !!!!");
if (this.caseSensitive) {
for (final Entry<String, Class<?>> elem : factoryGenerator.getConversionMap().entrySet()) {
if (elem.getKey().contentEquals(name)) {
Log.verbose(" + '{}' ==> true", elem.getKey());
return true;
}
Log.verbose(" + '{}' == false", elem.getKey());
}
} else {
for (final Entry<String, Class<?>> elem : factoryGenerator.getConversionMap().entrySet()) {
if (elem.getKey().equalsIgnoreCase(name)) {
Log.verbose(" + '{}' ==> true", elem.getKey());
return true;
}
Log.verbose(" + '{}' == false", elem.getKey());
}
}
return false;
}
if (this.caseSensitive) {
for (final String elem : this.names) {
if (elem.contentEquals(name)) {
Log.verbose(" - '" + elem + "' ==> true");
Log.verbose(" - '{}' ==> true", elem);
return true;
}
Log.verbose(" - '" + elem + "' == false");
Log.verbose(" - '{}' == false", elem);
}
} else {
for (final String elem : this.names) {
if (elem.equalsIgnoreCase(name)) {
Log.verbose(" - '" + elem + "' ==> true");
Log.verbose(" - '{}' ==> true", elem);
return true;
}
Log.verbose(" - '" + elem + "' == false");
Log.verbose(" - '{}' == false", elem);
}
}
return false;
@ -175,6 +257,10 @@ public final class IntrospectionProperty {
return this.optionnal;
}
public Boolean isText() {
return this.textMode;
}
public void setAttribute(final Boolean attribute) {
this.attribute = attribute;
}
@ -201,6 +287,10 @@ public final class IntrospectionProperty {
throw new ExmlBuilderException("Property: " + this.names + " have no setter");
}
public void setFactory(final Class<?> factory) {
this.factory = factory;
}
public void setGetter(final IntrospectionPropertyGetter getter) {
this.getter = getter;
}
@ -225,4 +315,8 @@ public final class IntrospectionProperty {
this.setter = setter;
}
public void setTextMode(final Boolean isText) {
this.textMode = isText;
}
}

View File

@ -170,7 +170,7 @@ public class ParseXml {
continue;
}
if (data.charAt(iii) == '>' || data.charAt(iii) == '<') {
// an error occured :
// an error occured :
parsingProperty.createError(new ExmlParserError(Tools.extractLine(data, pos.value), filePos, " find '>' or '<' instead of '?>'"));
return false;
}
@ -264,30 +264,110 @@ public class ParseXml {
return false;
}
protected boolean iParseText(final Object parent, final String data, final PositionParsing pos, final FilePos filePos, final ParsingProperty parsingProperty) throws ExmlException {
Log.verbose("start parse : 'text'");
// search end of the comment :
for (int iii = pos.value; iii < data.length(); iii++) {
Tools.drawElementParsed(data.charAt(iii), filePos);
if (filePos.check(data.charAt(iii))) {
protected int iParseFindEndComment(final String data, final int position) {
for (int iii = position; iii + 2 < data.length(); iii++) {
Log.verbose("iParseFindEndComment : '{}{}{}'", data.charAt(iii), data.charAt(iii + 1), data.charAt(iii + 2));
if (data.charAt(iii) == '-' && data.charAt(iii + 1) == '-' && data.charAt(iii + 2) == '>') {
return iii + 2;
}
}
return data.length();
}
protected int iParseFindEndDeclaration(final String data, final int position) {
for (int iii = position; iii + 1 < data.length(); iii++) {
Log.verbose("iParseFindEndDeclaration : '{}{}'", data.charAt(iii), data.charAt(iii + 1));
if (data.charAt(iii) == '?' && data.charAt(iii + 1) == '>') {
return iii + 1;
}
}
return data.length();
}
protected int iParseFindEndNode(final String data, final int position) {
Log.verbose("iParseFindEndNode : {}", data.charAt(position));
if (position + 3 < data.length() && data.charAt(position) == '!' && data.charAt(position + 1) == '-' && data.charAt(position + 2) == '-') {
// fond comment
return iParseFindEndComment(data, position + 3);
}
if (position < data.length() && data.charAt(position) == '?') {
// simple declaration Node
return iParseFindEndDeclaration(data, position + 1);
}
int newPos = iParseFindEndSingleNode(data, position);
// check <..../>
if (data.charAt(newPos - 1) == '/') {
return newPos;
}
// normal Node
newPos = iParseFindTextPackEnd(data, newPos) + 1;
if (data.charAt(newPos) != '<' || data.charAt(newPos + 1) != '/') {
Log.error("iParseFindEndNode : {}{} ==> wrong end node !!! ", data.charAt(newPos), data.charAt(newPos + 1));
}
newPos = iParseFindEndSingleNode(data, newPos + 1);
return newPos;
}
protected int iParseFindEndSingleNode(final String data, final int position) {
for (int iii = position; iii < data.length(); iii++) {
Log.verbose("iParseFindEndSingleNode : '{}'", data.charAt(iii));
if (data.charAt(iii) == '>') {
return iii;
}
}
return data.length();
}
protected int iParseFindTextPackEnd(final String data, final int position) {
for (int iii = position; iii < data.length(); iii++) {
Log.verbose("iParseFindTextPackEnd : {}", data.charAt(iii));
if (data.charAt(iii) == '<' && data.charAt(iii + 1) == '/') {
Log.verbose("iParseFindTextPackEnd ==> find end of text !!!");
return iii - 1;
}
if (data.charAt(iii) == '<') {
Log.verbose("iParseFindTextPackEnd ==> find new node !!!");
final int endNode = iParseFindEndNode(data, iii + 1);
iii = endNode;
continue;
}
if (data.charAt(iii) == '>' || data.charAt(iii) == '<') {
// search whitespace :
int newEnd = iii;
for (int jjj = iii - 1; jjj > pos.value; --jjj) {
if (!Tools.isWhiteChar(data.charAt(jjj))) {
break;
}
newEnd = jjj;
}
return data.length();
}
protected boolean iParseText(final Object parent, final String data, final PositionParsing pos, final FilePos filePos, final ParsingProperty parsingProperty) throws ExmlException {
Log.verbose("start parse : 'text'");
if (this.builder.isPackText(parent)) {
final int endOfText = iParseFindTextPackEnd(data, pos.value);
final String valueText = data.substring(pos.value, endOfText + 1);
Log.error("find text '{}' ==> new Pos={}", valueText, data.charAt(endOfText + 1));
pos.value = endOfText;
this.builder.newText(parent, valueText);
return true;
} else {
// search end of the comment :
for (int iii = pos.value; iii < data.length(); iii++) {
Tools.drawElementParsed(data.charAt(iii), filePos);
if (filePos.check(data.charAt(iii))) {
continue;
}
if (data.charAt(iii) == '>' || data.charAt(iii) == '<') {
// search whitespace :
int newEnd = iii;
for (int jjj = iii - 1; jjj > pos.value; --jjj) {
if (!Tools.isWhiteChar(data.charAt(jjj))) {
break;
}
newEnd = jjj;
}
// find end of value:
String valueText = data.substring(pos.value, newEnd);
Log.verbose("find text '" + valueText + "'");
pos.value = iii - 1;
valueText = Tools.replaceSpecialChar(valueText);
this.builder.newText(parent, valueText);
return true;
}
// find end of value:
String valueText = data.substring(pos.value, newEnd);
Log.verbose("find text '" + valueText + "'");
pos.value = iii - 1;
valueText = Tools.replaceSpecialChar(valueText);
this.builder.newText(parent, valueText);
return true;
}
}
parsingProperty.createError(new ExmlParserError(Tools.extractLine(data, pos.value), filePos, "Text got end of file without finding end node"));
@ -322,9 +402,10 @@ public class ParseXml {
* @param mainNode if true, this is the first root node
* @return true parsing is done OK
* @return false An error appear in the parsing
* @throws ExmlException
* @throws ExmlException
*/
protected boolean subParseElement(final Object parent, final String nameElement, final String data, final PositionParsing pos, final FilePos filePos, final ParsingProperty parsingProperty) throws ExmlException {
protected boolean subParseElement(final Object parent, final String nameElement, final String data, final PositionParsing pos, final FilePos filePos, final ParsingProperty parsingProperty)
throws ExmlException {
//EXMLPARSEELEMENT(" start subParse ... " << pos << " " << filePos);
for (int iii = pos.value; iii < data.length(); iii++) {
filePos.check(data.charAt(iii));
@ -477,7 +558,7 @@ public class ParseXml {
return false;
}
// find end of node :
// find > element ...
// find > element ...
for (int jjj = endPosName + 1; jjj < data.length(); jjj++) {
Tools.drawElementParsed(data.charAt(jjj), filePos);
if (tmpPos.check(data.charAt(jjj))) {
@ -529,9 +610,9 @@ public class ParseXml {
// find text:
Object element = null;
//try {
element = this.builder.newElement(parent, tmpname);
element = this.builder.newElement(parent, tmpname);
//} catch (final Exception e) {
// TODO Auto-generated catch block
// TODO Auto-generated catch block
// e.printStackTrace();
//}
pos.value = endPosName + 1;
@ -546,7 +627,7 @@ public class ParseXml {
continue;
}
filePos.add(tmpPos);
// here we have an error :
// here we have an error :
parsingProperty.createError(new ExmlParserError(Tools.extractLine(data, pos.value), filePos, "Find an ununderstanding element : '" + data.charAt(iii + white + 1) + "'"));
return false;
}

View File

@ -72,20 +72,20 @@ public class Tools {
}
public static String createPosPointer(final String line, final int pos) {
String out = "";
final StringBuilder out = new StringBuilder();
int iii;
for (iii = 0; iii < pos && iii < line.length(); iii++) {
if (line.charAt(iii) == '\t') {
out += "\t";
out.append("\t");
} else {
out += " ";
out.append(" ");
}
}
for (; iii < pos; iii++) {
out += " ";
out.append(" ");
}
out += "^";
return out;
out.append("^");
return out.toString();
}
// based on this: https://stackoverflow.com/questions/4052840/most-efficient-way-to-make-the-first-character-of-a-string-lower-case
@ -105,11 +105,11 @@ public class Tools {
*/
public static void drawElementParsed(final Character val, final FilePos filePos) {
// if (val == '\n') {
// Log.debug(filePos + " parse '\\n'");
// Log.error(filePos + " parse '\\n'");
// } else if (val == '\t') {
// Log.debug(filePos + " parse '\\t'");
// Log.error(filePos + " parse '\\t'");
// } else {
// Log.debug(filePos + " parse '" + val + "'");
// Log.error(filePos + " parse '" + val + "'");
// }
}
@ -162,16 +162,6 @@ public class Tools {
}
return out;
}
public static String toString(final Boolean[] data) {
StringBuilder out = new StringBuilder();
for (int iii=0; iii<data.length; iii++) {
if (iii != 0) {
out.append(";");
}
out.append(data[iii]);
}
return out.toString();
}
public static boolean[] parseBooleanStringList(String data) {
data = Tools.cleanNumberList(data);
@ -183,16 +173,6 @@ public class Tools {
}
return out;
}
public static String toString(final boolean[] data) {
StringBuilder out = new StringBuilder();
for (int iii=0; iii<data.length; iii++) {
if (iii != 0) {
out.append(";");
}
out.append(data[iii]);
}
return out.toString();
}
public static Byte[] parseByteClassStringList(String data) {
data = Tools.cleanNumberList(data);
@ -204,17 +184,6 @@ public class Tools {
}
return out;
}
public static String toString(final Byte[] data) {
StringBuilder out = new StringBuilder();
for (int iii=0; iii<data.length; iii++) {
if (iii != 0) {
out.append(";");
}
out.append(data[iii]);
}
return out.toString();
}
public static byte[] parseByteStringList(String data) {
data = Tools.cleanNumberList(data);
@ -226,15 +195,49 @@ public class Tools {
}
return out;
}
public static String toString(final byte[] data) {
StringBuilder out = new StringBuilder();
for (int iii=0; iii<data.length; iii++) {
if (iii != 0) {
out.append(";");
}
out.append(data[iii]);
public static Double[] parseDoubleClassStringList(String data) {
data = Tools.cleanNumberList(data);
final String[] dataArray = data.split(";");
final Double[] out = new Double[dataArray.length];
int count = 0;
for (final String str : dataArray) {
out[count++] = Double.parseDouble(str);
}
return out.toString();
return out;
}
public static double[] parseDoubleStringList(String data) {
data = Tools.cleanNumberList(data);
final String[] dataArray = data.split(";");
final double[] out = new double[dataArray.length];
int count = 0;
for (final String str : dataArray) {
out[count++] = Double.parseDouble(str);
}
return out;
}
public static Float[] parseFloatClassStringList(String data) {
data = Tools.cleanNumberList(data);
final String[] dataArray = data.split(";");
final Float[] out = new Float[dataArray.length];
int count = 0;
for (final String str : dataArray) {
out[count++] = Float.parseFloat(str);
}
return out;
}
public static float[] parseFloatStringList(String data) {
data = Tools.cleanNumberList(data);
final String[] dataArray = data.split(";");
final float[] out = new float[dataArray.length];
int count = 0;
for (final String str : dataArray) {
out[count++] = Float.parseFloat(str);
}
return out;
}
public static Integer[] parseIntegerClassStringList(String data) {
@ -247,16 +250,6 @@ public class Tools {
}
return out;
}
public static String toString(final Integer[] data) {
StringBuilder out = new StringBuilder();
for (int iii=0; iii<data.length; iii++) {
if (iii != 0) {
out.append(";");
}
out.append(data[iii]);
}
return out.toString();
}
public static int[] parseIntegerStringList(String data) {
data = Tools.cleanNumberList(data);
@ -268,16 +261,6 @@ public class Tools {
}
return out;
}
public static String toString(final int[] data) {
StringBuilder out = new StringBuilder();
for (int iii=0; iii<data.length; iii++) {
if (iii != 0) {
out.append(";");
}
out.append(data[iii]);
}
return out.toString();
}
public static Long[] parseLongClassStringList(String data) {
data = Tools.cleanNumberList(data);
@ -289,16 +272,6 @@ public class Tools {
}
return out;
}
public static String toString(final Long[] data) {
StringBuilder out = new StringBuilder();
for (int iii=0; iii<data.length; iii++) {
if (iii != 0) {
out.append(";");
}
out.append(data[iii]);
}
return out.toString();
}
public static long[] parseLongStringList(String data) {
data = Tools.cleanNumberList(data);
@ -310,104 +283,6 @@ public class Tools {
}
return out;
}
public static String toString(final long[] data) {
StringBuilder out = new StringBuilder();
for (int iii=0; iii<data.length; iii++) {
if (iii != 0) {
out.append(";");
}
out.append(data[iii]);
}
return out.toString();
}
public static float[] parseFloatStringList(String data) {
data = Tools.cleanNumberList(data);
final String[] dataArray = data.split(";");
final float[] out = new float[dataArray.length];
int count = 0;
for (final String str : dataArray) {
out[count++] = Float.parseFloat(str);
}
return out;
}
public static String toString(final float[] data) {
StringBuilder out = new StringBuilder();
for (int iii=0; iii<data.length; iii++) {
if (iii != 0) {
out.append(";");
}
out.append(data[iii]);
}
return out.toString();
}
public static Float[] parseFloatClassStringList(String data) {
data = Tools.cleanNumberList(data);
final String[] dataArray = data.split(";");
final Float[] out = new Float[dataArray.length];
int count = 0;
for (final String str : dataArray) {
out[count++] = Float.parseFloat(str);
}
return out;
}
public static String toString(final Float[] data) {
StringBuilder out = new StringBuilder();
for (int iii=0; iii<data.length; iii++) {
if (iii != 0) {
out.append(";");
}
out.append(data[iii]);
}
return out.toString();
}
public static double[] parseDoubleStringList(String data) {
data = Tools.cleanNumberList(data);
final String[] dataArray = data.split(";");
final double[] out = new double[dataArray.length];
int count = 0;
for (final String str : dataArray) {
out[count++] = Double.parseDouble(str);
}
return out;
}
public static String toString(final double[] data) {
StringBuilder out = new StringBuilder();
for (int iii=0; iii<data.length; iii++) {
if (iii != 0) {
out.append(";");
}
out.append(data[iii]);
}
return out.toString();
}
public static Double[] parseDoubleClassStringList(String data) {
data = Tools.cleanNumberList(data);
final String[] dataArray = data.split(";");
final Double[] out = new Double[dataArray.length];
int count = 0;
for (final String str : dataArray) {
out[count++] = Double.parseDouble(str);
}
return out;
}
public static String toString(final Double[] data) {
StringBuilder out = new StringBuilder();
for (int iii=0; iii<data.length; iii++) {
if (iii != 0) {
out.append(";");
}
out.append(data[iii]);
}
return out.toString();
}
public static Short[] parseShortClassStringList(String data) {
data = Tools.cleanNumberList(data);
@ -419,17 +294,6 @@ public class Tools {
}
return out;
}
public static String toString(final Short[] data) {
StringBuilder out = new StringBuilder();
for (int iii=0; iii<data.length; iii++) {
if (iii != 0) {
out.append(";");
}
out.append(data[iii]);
}
return out.toString();
}
public static short[] parseShortStringList(String data) {
data = Tools.cleanNumberList(data);
@ -441,16 +305,6 @@ public class Tools {
}
return out;
}
public static String toString(final short[] data) {
StringBuilder out = new StringBuilder();
for (int iii=0; iii<data.length; iii++) {
if (iii != 0) {
out.append(";");
}
out.append(data[iii]);
}
return out.toString();
}
// transform the Text with :
// "&lt;" == "<"
@ -480,6 +334,160 @@ public class Tools {
return out;
}
public static String toString(final boolean[] data) {
final StringBuilder out = new StringBuilder();
for (int iii = 0; iii < data.length; iii++) {
if (iii != 0) {
out.append(";");
}
out.append(data[iii]);
}
return out.toString();
}
public static String toString(final Boolean[] data) {
final StringBuilder out = new StringBuilder();
for (int iii = 0; iii < data.length; iii++) {
if (iii != 0) {
out.append(";");
}
out.append(data[iii]);
}
return out.toString();
}
public static String toString(final byte[] data) {
final StringBuilder out = new StringBuilder();
for (int iii = 0; iii < data.length; iii++) {
if (iii != 0) {
out.append(";");
}
out.append(data[iii]);
}
return out.toString();
}
public static String toString(final Byte[] data) {
final StringBuilder out = new StringBuilder();
for (int iii = 0; iii < data.length; iii++) {
if (iii != 0) {
out.append(";");
}
out.append(data[iii]);
}
return out.toString();
}
public static String toString(final double[] data) {
final StringBuilder out = new StringBuilder();
for (int iii = 0; iii < data.length; iii++) {
if (iii != 0) {
out.append(";");
}
out.append(data[iii]);
}
return out.toString();
}
public static String toString(final Double[] data) {
final StringBuilder out = new StringBuilder();
for (int iii = 0; iii < data.length; iii++) {
if (iii != 0) {
out.append(";");
}
out.append(data[iii]);
}
return out.toString();
}
public static String toString(final float[] data) {
final StringBuilder out = new StringBuilder();
for (int iii = 0; iii < data.length; iii++) {
if (iii != 0) {
out.append(";");
}
out.append(data[iii]);
}
return out.toString();
}
public static String toString(final Float[] data) {
final StringBuilder out = new StringBuilder();
for (int iii = 0; iii < data.length; iii++) {
if (iii != 0) {
out.append(";");
}
out.append(data[iii]);
}
return out.toString();
}
public static String toString(final int[] data) {
final StringBuilder out = new StringBuilder();
for (int iii = 0; iii < data.length; iii++) {
if (iii != 0) {
out.append(";");
}
out.append(data[iii]);
}
return out.toString();
}
public static String toString(final Integer[] data) {
final StringBuilder out = new StringBuilder();
for (int iii = 0; iii < data.length; iii++) {
if (iii != 0) {
out.append(";");
}
out.append(data[iii]);
}
return out.toString();
}
public static String toString(final long[] data) {
final StringBuilder out = new StringBuilder();
for (int iii = 0; iii < data.length; iii++) {
if (iii != 0) {
out.append(";");
}
out.append(data[iii]);
}
return out.toString();
}
public static String toString(final Long[] data) {
final StringBuilder out = new StringBuilder();
for (int iii = 0; iii < data.length; iii++) {
if (iii != 0) {
out.append(";");
}
out.append(data[iii]);
}
return out.toString();
}
public static String toString(final short[] data) {
final StringBuilder out = new StringBuilder();
for (int iii = 0; iii < data.length; iii++) {
if (iii != 0) {
out.append(";");
}
out.append(data[iii]);
}
return out.toString();
}
public static String toString(final Short[] data) {
final StringBuilder out = new StringBuilder();
for (int iii = 0; iii < data.length; iii++) {
if (iii != 0) {
out.append(";");
}
out.append(data[iii]);
}
return out.toString();
}
private Tools() {}
}

View File

@ -16,15 +16,39 @@ 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.XmlFactory;
import org.atriasoft.exml.annotation.XmlIgnoreUnknow;
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.annotation.XmlText;
import org.atriasoft.exml.exception.ExmlBuilderException;
import org.atriasoft.exml.internal.Log;
public class ReflectTools {
public static Class<?> getFactory(final Field element) throws ExmlBuilderException {
final Annotation[] annotation = element.getDeclaredAnnotationsByType(XmlFactory.class);
if (annotation.length == 0) {
return null;
}
if (annotation.length > 1) {
throw new ExmlBuilderException("Must not have more than 1 element @XmlFactory on " + element.getClass().getCanonicalName());
}
return ((XmlFactory) annotation[0]).value();
}
public static Class<?> getFactory(final Method element) throws ExmlBuilderException {
final Annotation[] annotation = element.getDeclaredAnnotationsByType(XmlFactory.class);
if (annotation.length == 0) {
return null;
}
if (annotation.length > 1) {
throw new ExmlBuilderException("Must not have more than 1 element @XmlFactory on " + element.getClass().getCanonicalName());
}
return ((XmlFactory) annotation[0]).value();
}
public static Boolean getIsAttribute(final Constructor<?> constructor, final Parameter element, final Boolean parentValue) throws ExmlBuilderException {
final Annotation[] annotation = element.getDeclaredAnnotationsByType(XmlAttribute.class);
if (annotation.length == 0) {
@ -223,6 +247,39 @@ public class ReflectTools {
return ((XmlOptional) annotation[0]).value();
}
public static Boolean getIsText(final Constructor<?> constructor, final Parameter element, final Boolean parentValue) throws ExmlBuilderException {
final Annotation[] annotation = element.getDeclaredAnnotationsByType(XmlText.class);
if (annotation.length == 0) {
return parentValue;
}
if (annotation.length > 1) {
throw new ExmlBuilderException("Must not have more than 1 element @XmlText on " + constructor.getClass().getCanonicalName());
}
return ((XmlText) annotation[0]).value();
}
public static Boolean getIsText(final Field element, final Boolean parentValue) throws ExmlBuilderException {
final Annotation[] annotation = element.getDeclaredAnnotationsByType(XmlText.class);
if (annotation.length == 0) {
return parentValue;
}
if (annotation.length > 1) {
throw new ExmlBuilderException("Must not have more than 1 element @XmlText on " + element.getClass().getCanonicalName());
}
return ((XmlText) annotation[0]).value();
}
public static Boolean getIsText(final Method element, final Boolean parentValue) throws ExmlBuilderException {
final Annotation[] annotation = element.getDeclaredAnnotationsByType(XmlText.class);
if (annotation.length == 0) {
return parentValue;
}
if (annotation.length > 1) {
throw new ExmlBuilderException("Must not have more than 1 element @XmlText on " + element.getClass().getCanonicalName());
}
return ((XmlText) annotation[0]).value();
}
public static String getListName(final Field element, final String defaultValue) throws Exception {
final Annotation[] annotation = element.getDeclaredAnnotationsByType(XmlList.class);
if (annotation.length == 0) {
@ -370,15 +427,15 @@ public class ReflectTools {
}
public static Class<?>[] getTypeField(final Field fieldDescription) {
Class<?> type = fieldDescription.getType();
final Class<?> type = fieldDescription.getType();
Class<?> subType = null;
Type empppe = fieldDescription.getGenericType();
if (empppe instanceof ParameterizedType plopppppp) {
Type[] realType = plopppppp.getActualTypeArguments();
final Type empppe = fieldDescription.getGenericType();
if (empppe instanceof final ParameterizedType plopppppp) {
final Type[] realType = plopppppp.getActualTypeArguments();
if (realType.length > 0) {
try {
subType = Class.forName(realType[0].getTypeName());
} catch (ClassNotFoundException e) {
} catch (final ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
@ -394,10 +451,10 @@ public class ReflectTools {
type = elem.getParameters()[paramId].getType();
if (List.class.isAssignableFrom(type)) {
Class<?> internalModelClass = null;
Type[] empppe = elem.getGenericParameterTypes();
final Type[] empppe = elem.getGenericParameterTypes();
if (empppe.length > paramId) {
if (empppe[paramId] instanceof ParameterizedType plopppppp) {
Type[] realType = plopppppp.getActualTypeArguments();
if (empppe[paramId] instanceof final ParameterizedType plopppppp) {
final Type[] realType = plopppppp.getActualTypeArguments();
//Log.info("ppplllppp: " + realType.length);
if (realType.length > 0) {
Log.verbose(" -->> " + realType[0]);
@ -417,10 +474,10 @@ public class ReflectTools {
type = setter.getParameters()[0].getType();
if (List.class.isAssignableFrom(type)) {
Class<?> internalModelClass = null;
Type[] empppe = setter.getGenericParameterTypes();
final Type[] empppe = setter.getGenericParameterTypes();
if (empppe.length > 0) {
if (empppe[0] instanceof ParameterizedType plopppppp) {
Type[] realType = plopppppp.getActualTypeArguments();
if (empppe[0] instanceof final ParameterizedType plopppppp) {
final Type[] realType = plopppppp.getActualTypeArguments();
if (realType.length > 0) {
Log.verbose(" -->> " + realType[0]);
internalModelClass = Class.forName(realType[0].getTypeName());
@ -437,9 +494,9 @@ public class ReflectTools {
Class<?> subType = null;
type = getter.getReturnType();
if (!Enum.class.isAssignableFrom(type)) {
Type empppe = getter.getGenericReturnType();
if (empppe instanceof ParameterizedType plopppppp) {
Type[] realType = plopppppp.getActualTypeArguments();
final Type empppe = getter.getGenericReturnType();
if (empppe instanceof final ParameterizedType plopppppp) {
final Type[] realType = plopppppp.getActualTypeArguments();
if (realType.length > 0) {
subType = Class.forName(realType[0].getTypeName());
}