[DEV] externalize the introspection in aknot

# Conflicts:
#	src/org/atriasoft/exml/builder/BuilderIntrospection.java
#	src/org/atriasoft/exml/builder/IntrospectionModelComplex.java
This commit is contained in:
Edouard DUPIN 2022-05-11 00:49:00 +02:00
parent 80a9db1f25
commit e268e655a4
32 changed files with 208 additions and 3237 deletions

View File

@ -5,7 +5,6 @@
*/ */
open module org.atriasoft.exml { open module org.atriasoft.exml {
exports org.atriasoft.eStringSerialize;
exports org.atriasoft.exml; exports org.atriasoft.exml;
exports org.atriasoft.exml.model; exports org.atriasoft.exml.model;
exports org.atriasoft.exml.exception; exports org.atriasoft.exml.exception;

View File

@ -1,16 +0,0 @@
package org.atriasoft.eStringSerialize;
public interface Converter {
/**
* Un-serialize a String in a specified Object
* @param value String to parse
* @return Data generated or Null
*/
Object valueOf(final String value);
/**
* Serialize in a string the require data
* @param data Object to serialize
* @return The new data...
*/
String toString(final Object data);
}

View File

@ -1,228 +0,0 @@
package org.atriasoft.eStringSerialize;
import java.util.HashMap;
import java.util.Map;
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());
}
});
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());
}
});
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());
}
});
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());
}
});
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());
}
});
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());
}
});
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());
}
});
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());
}
});
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());
}
});
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());
}
});
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());
}
});
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());
}
});
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());
}
});
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());
}
});
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;
}
});
}
public static boolean contains(final Class<?> clazz) {
return StringSerializer.VALUES_OF.containsKey(clazz);
}
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 long data) {
return Long.toString(data);
}
/**
* Serialize in a string the require data
* @param data Object to serialize
* @return The new data...
*/
public static String toString(final Object data) {
if (data == null) {
return null;
}
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

@ -12,13 +12,14 @@ import java.nio.charset.StandardCharsets;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import org.atriasoft.aknot.exception.AknotException;
import org.atriasoft.aknot.model.InterfaceFactoryAccess; import org.atriasoft.aknot.model.InterfaceFactoryAccess;
import org.atriasoft.aknot.model.ModelType;
import org.atriasoft.aknot.pojo.IntrospectionObject;
import org.atriasoft.etk.Uri; import org.atriasoft.etk.Uri;
import org.atriasoft.exml.builder.Builder; import org.atriasoft.exml.builder.Builder;
import org.atriasoft.exml.builder.BuilderGeneric; import org.atriasoft.exml.builder.BuilderGeneric;
import org.atriasoft.exml.builder.BuilderIntrospection; import org.atriasoft.exml.builder.BuilderIntrospection;
import org.atriasoft.exml.builder.IntrospectionObject;
import org.atriasoft.exml.builder.ModelType;
import org.atriasoft.exml.exception.ExmlBuilderException; import org.atriasoft.exml.exception.ExmlBuilderException;
import org.atriasoft.exml.exception.ExmlException; import org.atriasoft.exml.exception.ExmlException;
import org.atriasoft.exml.exception.ExmlParserErrorMulti; import org.atriasoft.exml.exception.ExmlParserErrorMulti;
@ -74,7 +75,7 @@ public class Exml {
// return iGenerate(_data, 0); // return iGenerate(_data, 0);
} }
public static XmlElement parse(final Path data) throws ExmlException, ExmlParserErrorMulti { public static XmlElement parse(final Path data) throws ExmlException, ExmlParserErrorMulti, AknotException {
final Builder builder = new BuilderGeneric(); final Builder builder = new BuilderGeneric();
final ParseXml parser = new ParseXml(builder); final ParseXml parser = new ParseXml(builder);
final ParsingProperty property = new ParsingProperty(); final ParsingProperty property = new ParsingProperty();
@ -94,7 +95,7 @@ public class Exml {
return (XmlElement) parser.parse(dataToParse, property); return (XmlElement) parser.parse(dataToParse, property);
} }
public static <T> T[] parse(final Path path, final Class<T> classType, final String rootNodeName) throws ExmlException, ExmlParserErrorMulti { public static <T> T[] parse(final Path path, final Class<T> classType, final String rootNodeName) throws ExmlException, ExmlParserErrorMulti, AknotException {
String content = null; String content = null;
try { try {
content = Exml.readFile(path, StandardCharsets.UTF_8); content = Exml.readFile(path, StandardCharsets.UTF_8);
@ -104,7 +105,7 @@ public class Exml {
return Exml.parse(content, classType, rootNodeName); return Exml.parse(content, classType, rootNodeName);
} }
public static XmlElement parse(final String data) throws ExmlException, ExmlParserErrorMulti { public static XmlElement parse(final String data) throws ExmlException, ExmlParserErrorMulti, AknotException {
final Builder builder = new BuilderGeneric(); final Builder builder = new BuilderGeneric();
final ParseXml parser = new ParseXml(builder); final ParseXml parser = new ParseXml(builder);
final ParsingProperty property = new ParsingProperty(); final ParsingProperty property = new ParsingProperty();
@ -113,7 +114,7 @@ public class Exml {
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public static <T> T[] parse(final String data, final Class<T> classType, final String rootNodeName) throws ExmlException, ExmlParserErrorMulti { public static <T> T[] parse(final String data, final Class<T> classType, final String rootNodeName) throws ExmlException, ExmlParserErrorMulti, AknotException {
Builder builder; Builder builder;
try { try {
builder = new BuilderIntrospection(ModelType.ARRAY, classType, rootNodeName); builder = new BuilderIntrospection(ModelType.ARRAY, classType, rootNodeName);
@ -134,7 +135,7 @@ public class Exml {
} }
} }
public static Object[] parse(final String data, final InterfaceFactoryAccess widgetXmlFactory) throws ExmlException, ExmlParserErrorMulti { public static Object[] parse(final String data, final InterfaceFactoryAccess widgetXmlFactory) throws ExmlException, ExmlParserErrorMulti, AknotException {
Builder builder; Builder builder;
try { try {
builder = new BuilderIntrospection(widgetXmlFactory); builder = new BuilderIntrospection(widgetXmlFactory);
@ -176,7 +177,7 @@ public class Exml {
* parse(tmpDataUnicode); //Display(); return ret; } * parse(tmpDataUnicode); //Display(); return ret; }
*/ */
public static XmlElement parse(final Uri data) throws ExmlException { public static XmlElement parse(final Uri data) throws ExmlException, AknotException {
final Builder builder = new BuilderGeneric(); final Builder builder = new BuilderGeneric();
final ParseXml parser = new ParseXml(builder); final ParseXml parser = new ParseXml(builder);
final ParsingProperty property = new ParsingProperty(); final ParsingProperty property = new ParsingProperty();
@ -190,7 +191,7 @@ public class Exml {
return (XmlElement) parser.parse(dataToParse, property); return (XmlElement) parser.parse(dataToParse, property);
} }
public static <T> T parseOne(final Path path, final Class<T> classType, final String rootNodeName) throws ExmlException, ExmlParserErrorMulti { public static <T> T parseOne(final Path path, final Class<T> classType, final String rootNodeName) throws ExmlException, ExmlParserErrorMulti, AknotException {
final T[] elements = Exml.parse(path, classType, rootNodeName); final T[] elements = Exml.parse(path, classType, rootNodeName);
if (elements == null || elements.length == 0) { if (elements == null || elements.length == 0) {
throw new ExmlBuilderException("Error in parsing the file, no node find ..."); throw new ExmlBuilderException("Error in parsing the file, no node find ...");
@ -201,7 +202,7 @@ public class Exml {
return elements[0]; return elements[0];
} }
public static <T> T parseOne(final String data, final Class<T> classType, final String rootNodeName) throws ExmlException, ExmlParserErrorMulti { public static <T> T parseOne(final String data, final Class<T> classType, final String rootNodeName) throws ExmlException, ExmlParserErrorMulti, AknotException {
final T[] elements = Exml.parse(data, classType, rootNodeName); final T[] elements = Exml.parse(data, classType, rootNodeName);
if (elements == null || elements.length == 0) { if (elements == null || elements.length == 0) {
throw new ExmlBuilderException("Error in parsing the file, no node find ..."); throw new ExmlBuilderException("Error in parsing the file, no node find ...");

View File

@ -5,6 +5,7 @@
*/ */
package org.atriasoft.exml.builder; package org.atriasoft.exml.builder;
import org.atriasoft.aknot.exception.AknotException;
import org.atriasoft.exml.exception.ExmlBuilderException; import org.atriasoft.exml.exception.ExmlBuilderException;
import org.atriasoft.exml.exception.ExmlException; import org.atriasoft.exml.exception.ExmlException;
@ -15,7 +16,7 @@ public interface Builder {
* @param element Element that is finished * @param element Element that is finished
* @throws ExmlBuilderException * @throws ExmlBuilderException
*/ */
void endElement(Object element) throws ExmlException; void endElement(Object element) throws ExmlException, AknotException;
/** /**
* 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. * 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.
@ -23,7 +24,7 @@ public interface Builder {
* @return true if the data must be packed. * @return true if the data must be packed.
* @throws ExmlException * @throws ExmlException
*/ */
boolean isPackText(Object parent) throws ExmlException; boolean isPackText(Object parent) throws ExmlException, AknotException;
/** /**
* New comment added on this Element * New comment added on this Element
@ -31,7 +32,7 @@ public interface Builder {
* @param comment Comment value * @param comment Comment value
* @throws ExmlBuilderException Error with this node or element. * @throws ExmlBuilderException Error with this node or element.
*/ */
void newComment(Object element, String comment) throws ExmlException; void newComment(Object element, String comment) throws ExmlException, AknotException;
/** /**
* New comment added on this Element * New comment added on this Element
@ -40,7 +41,7 @@ public interface Builder {
* @return Declaration object value * @return Declaration object value
* @throws ExmlBuilderException Error with this node or element. * @throws ExmlBuilderException Error with this node or element.
*/ */
Object newDeclaration(Object parent, String text) throws ExmlException; Object newDeclaration(Object parent, String text) throws ExmlException, AknotException;
/** /**
* Add a new sub-element on the current parent element: {@code<ELEMENT>} * Add a new sub-element on the current parent element: {@code<ELEMENT>}
@ -49,7 +50,7 @@ public interface Builder {
* @return the object representing the Element. * @return the object representing the Element.
* @throws ExmlBuilderException Error with this node or element. * @throws ExmlBuilderException Error with this node or element.
*/ */
Object newElement(Object parent, String nodeName) throws ExmlException; Object newElement(Object parent, String nodeName) throws ExmlException, AknotException;
/** /**
* The sub-element is finish (creation done) * The sub-element is finish (creation done)
@ -57,7 +58,7 @@ public interface Builder {
* @param tmpname Name of the node * @param tmpname Name of the node
* @param element Element builder that has been created * @param element Element builder that has been created
*/ */
void newElementFinished(Object parent, String tmpname, Object element) throws ExmlException; void newElementFinished(Object parent, String tmpname, Object element) throws ExmlException, AknotException;
/** /**
* Add a property on the Element. * Add a property on the Element.
@ -66,14 +67,14 @@ public interface Builder {
* @param propertyValue Value of the property * @param propertyValue Value of the property
* @throws ExmlBuilderException Error with this node or element. * @throws ExmlBuilderException Error with this node or element.
*/ */
void newProperty(Object element, String propertyName, String propertyValue) throws ExmlException; void newProperty(Object element, String propertyName, String propertyValue) throws ExmlException, AknotException;
/** /**
* Create or get the root element of the document * Create or get the root element of the document
* @return An object that id a root element. * @return An object that id a root element.
* @throws ExmlBuilderException Error with this node or element. * @throws ExmlBuilderException Error with this node or element.
*/ */
Object newRoot() throws ExmlBuilderException; Object newRoot() throws ExmlBuilderException, AknotException;
/** /**
* Add a text value on the current Element * Add a text value on the current Element
@ -81,6 +82,6 @@ public interface Builder {
* @param text Test to add. * @param text Test to add.
* @throws ExmlBuilderException Error with this node or element. * @throws ExmlBuilderException Error with this node or element.
*/ */
void newText(Object parent, String text) throws ExmlException; void newText(Object parent, String text) throws ExmlException, AknotException;
} }

View File

@ -3,8 +3,13 @@ package org.atriasoft.exml.builder;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.atriasoft.aknot.StringSerializer;
import org.atriasoft.aknot.exception.AknotException;
import org.atriasoft.aknot.model.InterfaceFactoryAccess; import org.atriasoft.aknot.model.InterfaceFactoryAccess;
import org.atriasoft.eStringSerialize.StringSerializer; import org.atriasoft.aknot.model.IntrospectionModel;
import org.atriasoft.aknot.model.ModelType;
import org.atriasoft.aknot.pojo.CacheIntrospectionModel;
import org.atriasoft.aknot.pojo.IntrospectionObject;
import org.atriasoft.exml.exception.ExmlAttributeDoesNotExist; import org.atriasoft.exml.exception.ExmlAttributeDoesNotExist;
import org.atriasoft.exml.exception.ExmlBuilderException; import org.atriasoft.exml.exception.ExmlBuilderException;
import org.atriasoft.exml.exception.ExmlException; import org.atriasoft.exml.exception.ExmlException;
@ -18,7 +23,7 @@ public class BuilderIntrospection implements Builder {
final String rootNodeName; final String rootNodeName;
final InterfaceFactoryAccess factory; final InterfaceFactoryAccess factory;
public BuilderIntrospection(final InterfaceFactoryAccess factory) throws ExmlException { public BuilderIntrospection(final InterfaceFactoryAccess factory) throws ExmlException, AknotException {
this.factory = factory; this.factory = factory;
this.rootNodeName = null; this.rootNodeName = null;
this.rootClassType = null; this.rootClassType = null;
@ -27,7 +32,7 @@ public class BuilderIntrospection implements Builder {
} }
} }
public BuilderIntrospection(final ModelType model, final Class<?> classType, final String rootNodeName) throws ExmlException { public BuilderIntrospection(final ModelType model, final Class<?> classType, final String rootNodeName) throws ExmlException, AknotException {
this.factory = null; this.factory = null;
this.rootNodeName = rootNodeName; this.rootNodeName = rootNodeName;
this.rootClassType = classType; this.rootClassType = classType;
@ -35,7 +40,7 @@ public class BuilderIntrospection implements Builder {
} }
@Override @Override
public void endElement(final Object element) throws ExmlBuilderException { public void endElement(final Object element) throws ExmlBuilderException, AknotException {
Log.verbose("End of Element: {}", element); Log.verbose("End of Element: {}", element);
if (element == null) { if (element == null) {
return; return;
@ -63,16 +68,16 @@ public class BuilderIntrospection implements Builder {
} }
@Override @Override
public void newComment(final Object element, final String comment) throws ExmlException {} public void newComment(final Object element, final String comment) {}
@Override @Override
public Object newDeclaration(final Object parent, final String text) throws ExmlException { public Object newDeclaration(final Object parent, final String text) {
// we drop all declaration, no need of it too. // we drop all declaration, no need of it too.
return null; return null;
} }
@Override @Override
public Object newElement(final Object parent, final String nodeName) throws ExmlException { public Object newElement(final Object parent, final String nodeName) throws ExmlException, AknotException {
if (parent == null) { if (parent == null) {
return null; return null;
} }
@ -136,7 +141,7 @@ public class BuilderIntrospection implements Builder {
} }
@Override @Override
public void newElementFinished(final Object parent, final String tmpName, final Object element) throws ExmlException { public void newElementFinished(final Object parent, final String tmpName, final Object element) throws ExmlException, AknotException {
Log.debug("new element fionished : ==> " + tmpName); Log.debug("new element fionished : ==> " + tmpName);
if (parent == null || element == null) { if (parent == null || element == null) {
return; return;
@ -163,7 +168,7 @@ public class BuilderIntrospection implements Builder {
} }
@Override @Override
public void newProperty(final Object element, final String propertyName, final String propertyValue) throws ExmlException { public void newProperty(final Object element, final String propertyName, final String propertyValue) throws ExmlException, AknotException {
if (element == null) { if (element == null) {
return; return;
} }
@ -217,13 +222,13 @@ public class BuilderIntrospection implements Builder {
} }
@Override @Override
public Object newRoot() throws ExmlBuilderException { public Object newRoot() throws ExmlBuilderException, AknotException {
final IntrospectionModel inferData = this.cacheModel.findOrCreate(ModelType.ARRAY, this.rootNodeName, this.rootClassType); final IntrospectionModel inferData = this.cacheModel.findOrCreate(ModelType.ARRAY, this.rootNodeName, this.rootClassType);
return new IntrospectionObject(inferData); return new IntrospectionObject(inferData);
} }
@Override @Override
public void newText(final Object parent, final String text) throws ExmlException { public void newText(final Object parent, final String text) throws ExmlException, AknotException {
if (parent == null) { if (parent == null) {
return; return;
} }

View File

@ -1,34 +0,0 @@
package org.atriasoft.exml.builder;
import java.util.HashMap;
import java.util.Map;
import org.atriasoft.exml.exception.ExmlBuilderException;
public class CacheIntrospectionModel {
final Map<MapKey, IntrospectionModel> elements = new HashMap<>();
IntrospectionModel findOrCreate(final ModelType model, final String name, final Class<?> classType) throws ExmlBuilderException {
MapKey key = new MapKey(model, name, classType);
IntrospectionModel out = this.elements.get(key);
if (out != null) {
return out;
}
if (model == ModelType.ARRAY) {
out = IntrospectionModelFactory.createModelArray(key.nodeName(), key);
} else if (model == ModelType.LIST) {
out = IntrospectionModelFactory.createModelList(key.nodeName(), key);
} else if (classType.isEnum()) {
out = IntrospectionModelFactory.createModelEnum(key);
} else {
out = IntrospectionModelFactory.createModel(key);
}
this.elements.put(key, out);
return out;
}
public CacheIntrospectionModel() {
}
}

View File

@ -1,132 +0,0 @@
package org.atriasoft.exml.builder;
import java.util.List;
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;
protected static final Boolean DEFAULT_DEFAULT_NULL_VALUE = false;
protected static final Boolean DEFAULT_CASE_SENSITIVE = true;
protected static final Boolean DEFAULT_MANAGED = true;
protected static final Boolean DEFAULT_OPTIONAL = false;
protected boolean defaultNullValue = false;
protected boolean ignoreUnknown = false;
protected final Class<?> classType;
public IntrospectionModel(final Class<?> classType) {
this.classType = classType;
}
public Object createObject(final Map<String, Object> properties, final Map<String, List<Object>> nodes) throws ExmlBuilderException {
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 List<IntrospectionProperty> getNodes() {
return null;
}
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 Class<?> getTypeOfSubProperty(final String nodeName) throws ExmlBuilderException {
return null;
}
protected Class<?> getTypeOfText() {
return null;
}
public Object getValue(final String propertyName, final String propertyValue) throws ExmlBuilderException {
return null;
}
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;
}
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

@ -1,76 +0,0 @@
package org.atriasoft.exml.builder;
import java.lang.reflect.Array;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import org.atriasoft.etk.util.ArraysTools;
import org.atriasoft.exml.exception.ExmlBuilderException;
public class IntrospectionModelArray extends IntrospectionModel {
@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;
if (this.nodeName == null) {
tmp = nodes.get(IntrospectionObject.STUPID_TOCKEN);
} else {
tmp = nodes.get(this.nodeName);
}
if (tmp == null) {
return null;
}
if (this.classType.isPrimitive()) {
return ArraysTools.listToPrimitiveAuto(this.classType, tmp);
}
return IntrospectionModelArray.convertList(this.classType, tmp);
}
@Override
public List<String> getNodeAvaillable() {
if (this.nodeName != null) {
return Arrays.asList(this.nodeName);
}
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 boolean hasTextModel() {
return false;
}
@Override
public boolean isArray() {
return true;
}
@Override
public String toString(final Object data) {
return null;
}
}

View File

@ -1,47 +0,0 @@
package org.atriasoft.exml.builder;
import java.util.List;
import java.util.Map;
import org.atriasoft.eStringSerialize.StringSerializer;
import org.atriasoft.exml.exception.ExmlBuilderException;
public class IntrospectionModelBaseType extends IntrospectionModel {
public IntrospectionModelBaseType(final Class<?> classType) {
super(classType);
}
@Override
public Object createObject(final Map<String, Object> properties, final Map<String, List<Object>> nodes) throws ExmlBuilderException {
throw new ExmlBuilderException("Base type model can not have properties and nodes ... ");
}
@Override
public List<String> getNodeAvaillable() {
return null;
}
@Override
public Object getValueFromText(final String text) throws ExmlBuilderException {
//il y a un bug ici ...
return StringSerializer.valueOf(this.classType, text);
}
@Override
public Object getValue(final String propertyName, final String propertyValue) throws ExmlBuilderException {
return null;
}
@Override
public boolean isNative() {
return true;
}
@Override
public String toString(final Object data) {
return StringSerializer.toString(data);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,27 +0,0 @@
package org.atriasoft.exml.builder;
import org.atriasoft.eStringSerialize.StringSerializer;
import org.atriasoft.exml.exception.ExmlBuilderException;
public class IntrospectionModelFactory {
private IntrospectionModelFactory() {}
public static IntrospectionModel createModelArray(final String nodeName, final MapKey modelType) throws ExmlBuilderException {
return new IntrospectionModelArray(nodeName, modelType.type());
}
public static IntrospectionModel createModelList(final String nodeName, final MapKey modelType) throws ExmlBuilderException {
return new IntrospectionModelList(nodeName, modelType.type());
}
public static IntrospectionModel createModelEnum(final MapKey modelType) throws ExmlBuilderException {
return new IntrospectionModelComplex(modelType.type());
}
public static IntrospectionModel createModel(final MapKey modelType) throws ExmlBuilderException {
if (StringSerializer.contains(modelType.type())) {
return new IntrospectionModelBaseType(modelType.type());
}
return new IntrospectionModelComplex(modelType.type());
}
}

View File

@ -1,54 +0,0 @@
package org.atriasoft.exml.builder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import org.atriasoft.exml.exception.ExmlBuilderException;
public class IntrospectionModelList extends IntrospectionModel {
final String nodeName;
public IntrospectionModelList(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 {
if (this.nodeName == null) {
return nodes.get(IntrospectionObject.STUPID_TOCKEN);
}
return nodes.get(this.nodeName);
}
@Override
public List<String> getNodeAvaillable() {
if (this.nodeName != null) {
return Arrays.asList(this.nodeName);
}
return null;
}
@Override
public Object getValueFromText(final String text) throws ExmlBuilderException {
return new ArrayList<Object>();
}
@Override
public Object getValue(final String propertyName, final String propertyValue) throws ExmlBuilderException {
return null;
}
@Override
public boolean isList() {
return true;
}
@Override
public String toString(final Object data) {
return null;
}
}

View File

@ -1,168 +0,0 @@
package org.atriasoft.exml.builder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.atriasoft.exml.exception.ExmlBuilderException;
import org.atriasoft.exml.exception.ExmlException;
import org.atriasoft.exml.exception.ExmlNodeDoesNotExist;
import org.atriasoft.exml.internal.Log;
public class 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;
private final Map<String, Object> properties = new HashMap<>();
private final Map<String, List<Object>> nodes = new HashMap<>();
public IntrospectionObject(final IntrospectionModel dataInterface) {
this.modelInterface = dataInterface;
}
@SuppressWarnings("unchecked")
public void addObject(final String nodeName, final Object value) throws ExmlException {
if (value == null) {
// specific case when a List is empty <links></links> but define for a specific list ==> need no action
return;
}
final String beanName = this.modelInterface.getBeanName(nodeName);
if (beanName == null) {
throw new ExmlNodeDoesNotExist("The node '" + nodeName + "' Does not exist...");
}
List<Object> node = this.nodes.get(beanName);
if (node == null) {
if (List.class.isAssignableFrom(value.getClass())) {
node = (List<Object>) value;
} else if (value.getClass().isArray()) {
Log.error("this is a big problem ...");
Log.error("this is a big problem ...");
Log.error("this is a big problem ...");
Log.error("this is a big problem ...");
Log.error("this is a big problem ...");
Log.error("this is a big problem ...");
Log.error("this is a big problem ...");
Log.error("this is a big problem ...");
Log.error("this is a big problem ...");
Log.error("this is a big problem ...");
} else {
node = new ArrayList<>();
node.add(value);
}
this.nodes.put(beanName, node);
} else if (value.getClass().isArray()) {
Log.error("this is a big problem ...");
Log.error("this is a big problem ...");
Log.error("this is a big problem ...");
Log.error("this is a big problem ...");
Log.error("this is a big problem ...");
Log.error("this is a big problem ...");
Log.error("this is a big problem ...");
Log.error("this is a big problem ...");
Log.error("this is a big problem ...");
Log.error("this is a big problem ...");
} else if (List.class.isAssignableFrom(value.getClass())) {
final List<Object> nodeIn = (List<Object>) value;
node.addAll(nodeIn);
} else {
node.add(value);
}
}
public void generateTheObject() throws ExmlBuilderException {
if (this.data != null) {
// nothing to do ... ==> element already created
return;
}
Log.debug("Create the element for the Specific node ... type = " + this.modelInterface.getClassType().getCanonicalName() + (this.modelInterface.isArray() ? "[array]" : "")
+ (this.modelInterface.isList() ? "[List]" : ""));
Log.debug(" Properties : " + this.properties.keySet());
Log.debug(" Nodes : " + this.nodes.keySet());
this.data = this.modelInterface.createObject(this.properties, this.nodes);
}
public Object getData() {
return this.data;
}
public IntrospectionModel getModelIntrospection() {
return this.modelInterface;
}
public String getTreeNameOfSubNode(final String nodeName) throws ExmlException {
final String beanName = this.modelInterface.getBeanName(nodeName);
if (beanName == null) {
throw new ExmlNodeDoesNotExist("The node '" + nodeName + "' Does not exist...");
}
return this.modelInterface.getTreeNameOfSubNode(beanName);
}
public Class<?> getTypeOfProperty(final String nodeName) throws ExmlException {
final String beanName = this.modelInterface.getBeanName(nodeName);
if (beanName == null) {
throw new ExmlNodeDoesNotExist("The node '" + nodeName + "' Does not exist...");
}
return this.modelInterface.getTypeOfProperty(beanName);
}
/**
* Detect a subNode, and ask the type of the node at the parent Class
* @param nodeName Name of the node
* @return Class of the node to create
*/
public Class<?> getTypeOfSubNode(final String nodeName) throws ExmlException {
final String beanName = this.modelInterface.getBeanNameModel(nodeName);
if (beanName == null) {
throw new ExmlNodeDoesNotExist("The node '" + nodeName + "' Does not exist...");
}
return this.modelInterface.getTypeOfSubNode(beanName);
}
public Class<?> getTypeOfSubNodeSubType(final String nodeName) throws ExmlException {
final String beanName = this.modelInterface.getBeanNameModel(nodeName);
if (beanName == null) {
throw new ExmlNodeDoesNotExist("The node '" + nodeName + "' Does not exist...");
}
return this.modelInterface.getTypeOfSubNodeList(beanName);
}
public Class<?> getTypeOfSubProperty(final String nodeName) throws ExmlException {
final String beanName = this.modelInterface.getBeanName(nodeName);
if (beanName == null) {
throw new ExmlNodeDoesNotExist("The node '" + nodeName + "' Does not exist...");
}
return this.modelInterface.getTypeOfSubProperty(beanName);
}
public boolean isSubNodeOrPropertyExist(final String nodeName) {
final String beanName = this.modelInterface.getBeanName(nodeName);
if (beanName == null) {
return false;
}
return true;
}
public void putProperty(final String propertyName, final Object propertyValue) throws ExmlException {
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");
}
this.properties.put(beanName, propertyValue);
}
public void setText(final String text) throws ExmlBuilderException {
if (this.data != null) {
throw new ExmlBuilderException("Can not set multiple text value in a single NODE ...");
}
this.data = this.modelInterface.getValueFromText(text);
}
}

View File

@ -1,322 +0,0 @@
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.aknot.model.InterfaceFactoryAccess;
import org.atriasoft.eStringSerialize.StringSerializer;
import org.atriasoft.exml.exception.ExmlBuilderException;
import org.atriasoft.exml.internal.Log;
public final class IntrospectionProperty {
// if the element is not managed by us (set at null while not define by a function attribute, parameter ...)
private Boolean managed = null;
// Case sensitive in parsing XML or not (set at null while not define by a function attribute, parameter ...)
private Boolean caseSensitive = null;
// Optional or not (set at null while not define by a function attribute, parameter ...)
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
private String[] names = null;
// if organized in sublist (!= null) then the subNode have this value
private String listName = null;
private boolean canBeSetByConstructor = false;
private Class<?> factory = null;
private InterfaceFactoryAccess 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
// third field access
IntrospectionPropertySetter setter = null;
public IntrospectionProperty(final String beanName, final Class<?>[] type, final String[] names) {
this.beanName = beanName;
this.type = type[0];
this.subType = type[1];
this.names = names;
}
public boolean canGetValue() {
return this.getter != null;
}
public boolean canSetValue() {
return this.canBeSetByConstructor || this.setter != null;
}
/**
* Create a value adapted to the property type.
* @apiNote generic type is transformed byte -> Byte, int -> Integer ...
* @param value Value to set in the Object
* @throws Exception An error occurred
* @return The object created
*/
public Object createValue(final String value) throws ExmlBuilderException {
try {
if (StringSerializer.contains(this.type)) {
// TODO This might be a deprecated code ....
return StringSerializer.valueOf(this.type, value);
}
if (this.type.isEnum()) {
} 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);'");
}
final ArrayList<Object> out = new ArrayList<>();
for (final String elem : value.split(";")) {
out.add(StringSerializer.valueOf(this.subType, elem));
}
return out;
} catch (final IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
throw new ExmlBuilderException("Error in parsing the property value ... " + e.getMessage());
}
}
public String getBeanName() {
return this.beanName;
}
public Class<?> getCompatible(final String name) {
final InterfaceFactoryAccess 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 InterfaceFactoryAccess getFactory() {
if (this.factoryCreated == null && this.factory != null) {
try {
this.factoryCreated = (InterfaceFactoryAccess) 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;
}
/**
* Get list of all names of the property/node (minimal 1 name)
* @return Array of names available
*/
public String[] getNames() {
return this.names;
}
/**
* Get the type of the property (if list ==> need to be get on method otherwise it is an Object...)
* @return Type of the list element.
*/
public Class<?> getSubType() {
return this.subType;
}
/**
* Get basic type of the property
* @return property type detected.
*/
public Class<?> getType() {
return this.type;
}
/**
* Get the value in the object.
* @param object Object that is invoke to get the value.
* @return The generate value of the object
* @throws ExmlBuilderException in an error occured
*/
public Object getValue(final Object object) throws ExmlBuilderException {
if (this.getter != null) {
return this.getter.getValue(object);
}
throw new ExmlBuilderException("Property: " + this.names + " have no getter");
}
public boolean hasFactory() {
return this.factory != null;
}
public Boolean isAttribute() {
return this.attribute;
}
public boolean isCanBeSetByConstructor() {
return this.canBeSetByConstructor;
}
public Boolean isCaseSensitive() {
return this.caseSensitive;
}
/**
* Check if the input name is compatible win an element in the list availlable (respect case sensitive if needed)
* @param name Name to check
* @return true if the element is compatible, false otherwise
*/
public boolean isCompatible(final String name) {
Log.verbose("Check compatible : '{}' in {}", name, Arrays.toString(this.names));
final InterfaceFactoryAccess 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(" - '{}' ==> true", elem);
return true;
}
Log.verbose(" - '{}' == false", elem);
}
} else {
for (final String elem : this.names) {
if (elem.equalsIgnoreCase(name)) {
Log.verbose(" - '{}' ==> true", elem);
return true;
}
Log.verbose(" - '{}' == false", elem);
}
}
return false;
}
public Boolean isManaged() {
return this.managed;
}
public Boolean isOptionnal() {
return this.optionnal;
}
public Boolean isText() {
return this.textMode;
}
public void setAttribute(final Boolean attribute) {
this.attribute = attribute;
}
public void setCanBeSetByConstructor(final boolean canBeSetByConstructor) {
this.canBeSetByConstructor = canBeSetByConstructor;
}
public void setCaseSensitive(final Boolean caseSensitive) {
this.caseSensitive = caseSensitive;
}
/**
* set the specific string value in the specified object
* @param object Object to add the value
* @param value Value to set in the Object
* @throws Exception An error occurred
*/
public void setExistingValue(final Object object, final Object value) throws ExmlBuilderException {
if (this.setter != null) {
this.setter.setValue(object, value);
return;
}
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;
}
public void setListName(final String listName) {
this.listName = listName;
}
public void setManaged(final Boolean managed) {
this.managed = managed;
}
public void setNames(final String[] names) {
this.names = names;
}
public void setOptionnal(final Boolean optionnal) {
this.optionnal = optionnal;
}
public void setSetter(final IntrospectionPropertySetter setter) {
this.setter = setter;
}
public void setTextMode(final Boolean isText) {
this.textMode = isText;
}
}

View File

@ -1,43 +0,0 @@
package org.atriasoft.exml.builder;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import org.atriasoft.exml.exception.ExmlBuilderException;
public class IntrospectionPropertyField implements IntrospectionPropertyGetter, IntrospectionPropertySetter {
private final Field fieldDescription;
private final boolean finalValue;
public IntrospectionPropertyField(final Field fieldDescription) {
this.fieldDescription = fieldDescription;
this.finalValue = Modifier.isFinal(fieldDescription.getModifiers());
}
@Override
public Object getValue(final Object object) throws ExmlBuilderException {
try {
return this.fieldDescription.get(object);
} catch (IllegalArgumentException | IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
throw new ExmlBuilderException("Can not set value ... " + e.getMessage());
}
}
@Override
public void setValue(final Object object, final Object value) throws ExmlBuilderException {
if (this.finalValue) {
throw new ExmlBuilderException("Can not set value The value is FINAL!!!");
}
try {
this.fieldDescription.set(object, value);
} catch (IllegalArgumentException | IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
throw new ExmlBuilderException("Can not set value ... " + e.getMessage());
}
}
}

View File

@ -1,7 +0,0 @@
package org.atriasoft.exml.builder;
import org.atriasoft.exml.exception.ExmlBuilderException;
public interface IntrospectionPropertyGetter {
Object getValue(Object object) throws ExmlBuilderException;
}

View File

@ -1,74 +0,0 @@
package org.atriasoft.exml.builder;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import org.atriasoft.exml.exception.ExmlBuilderException;
public class IntrospectionPropertyMethodGetter implements IntrospectionPropertyGetter {
// private static Class<?>[] getTypefunction(final Method setter, final Method getter) throws Exception {
// Class<?> type = null;
// Class<?> subType = null;
// if (setter == null && getter == null) {
// // impossible case...
// throw new Exception("kjhkhjkj");
// }
// if (getter != null) {
// type = getter.getReturnType();
// if (Enum.class.isAssignableFrom(type)) {
// Log.verbose("Find an enum ...");
// } else {
// Type empppe = getter.getGenericReturnType();
// if (empppe instanceof ParameterizedType plopppppp) {
// Type[] realType = plopppppp.getActualTypeArguments();
// if (realType.length > 0) {
// subType = Class.forName(realType[0].getTypeName());
// }
// }
// }
// }
// if (setter != null) {
// if (type != null && setter.getParameters()[0].getType() != type) {
// throw new Exception("The type of the setter ands the type return by the getter are not the same ...");
// }
// type = setter.getParameters()[0].getType();
// if (List.class.isAssignableFrom(type)) {
// Class<?> internalModelClass = null;
// Type[] empppe = setter.getGenericParameterTypes();
// if (empppe.length > 0) {
// if (empppe[0] instanceof ParameterizedType plopppppp) {
// Type[] realType = plopppppp.getActualTypeArguments();
// if (realType.length > 0) {
// Log.warning(" -->> " + realType[0]);
// internalModelClass = Class.forName(realType[0].getTypeName());
// }
// }
// }
// if (getter!=null && internalModelClass != subType) {
// throw new Exception("The type of the setter and the type return by the getter are not the same ...");
// }
// subType = internalModelClass;
// }
// }
// return new Class<?>[] {type, subType};
// }
//
protected Method getter;
public IntrospectionPropertyMethodGetter(final Method getter) throws Exception {
this.getter = getter;
}
@Override
public Object getValue(final Object object) throws ExmlBuilderException {
if (this.getter == null) {
throw new ExmlBuilderException("no getter availlable");
}
try {
return this.getter.invoke(object);
} catch (InvocationTargetException | IllegalAccessException | IllegalArgumentException e) {
e.printStackTrace();
throw new ExmlBuilderException("Can not set value ... " + e.getMessage());
}
}
}

View File

@ -1,28 +0,0 @@
package org.atriasoft.exml.builder;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import org.atriasoft.exml.exception.ExmlBuilderException;
public class IntrospectionPropertyMethodSetter implements IntrospectionPropertySetter {
protected Method setter;
public IntrospectionPropertyMethodSetter(final Method setter) throws Exception {
this.setter = setter;
}
@Override
public void setValue(final Object object, final Object value) throws ExmlBuilderException {
if (this.setter == null) {
throw new ExmlBuilderException("no setter availlable");
}
try {
this.setter.invoke(object, value);
} catch (InvocationTargetException | IllegalAccessException | IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
throw new ExmlBuilderException("Can not set value ... " + e.getMessage());
}
}
}

View File

@ -1,13 +0,0 @@
package org.atriasoft.exml.builder;
import org.atriasoft.exml.exception.ExmlBuilderException;
public interface IntrospectionPropertySetter {
/**
* set the specific string value in the specified object
* @param object Object to add the value
* @param value Value to set in the Object
* @throws Exception An error occurred
*/
void setValue(Object object, Object value) throws ExmlBuilderException;
}

View File

@ -1,14 +0,0 @@
package org.atriasoft.exml.builder;
public record MapKey (ModelType model,
String nodeName,
Class<?> type) {
public MapKey(final ModelType model, final String nodeName, final Class<?> type) {
this.model = model;
this.nodeName = nodeName;
this.type = type;
}
public MapKey(final ModelType model, final Class<?> type) {
this(model, null, type);
}
}

View File

@ -1,7 +0,0 @@
package org.atriasoft.exml.builder;
public enum ModelType {
NORMAL,
ARRAY,
LIST
}

View File

@ -1,6 +1,6 @@
package org.atriasoft.exml.exception; package org.atriasoft.exml.exception;
import org.atriasoft.exml.parser.FilePos; import org.atriasoft.etk.util.FilePos;
public class ExmlParserError extends ExmlBuilderException { public class ExmlParserError extends ExmlBuilderException {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;

View File

@ -4,15 +4,16 @@ import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import org.atriasoft.aknot.exception.AknotException;
import org.atriasoft.aknot.model.IntrospectionModel;
import org.atriasoft.aknot.model.MapKey;
import org.atriasoft.aknot.model.ModelType;
import org.atriasoft.aknot.pojo.IntrospectionModelFactory;
import org.atriasoft.aknot.pojo.IntrospectionProperty;
import org.atriasoft.etk.Tools;
import org.atriasoft.etk.util.ArraysTools; import org.atriasoft.etk.util.ArraysTools;
import org.atriasoft.exml.builder.IntrospectionModel;
import org.atriasoft.exml.builder.IntrospectionModelFactory;
import org.atriasoft.exml.builder.IntrospectionProperty;
import org.atriasoft.exml.builder.MapKey;
import org.atriasoft.exml.builder.ModelType;
import org.atriasoft.exml.exception.ExmlBuilderException; import org.atriasoft.exml.exception.ExmlBuilderException;
import org.atriasoft.exml.internal.Log; import org.atriasoft.exml.internal.Log;
import org.atriasoft.exml.parser.Tools;
public class GeneratorIntrospection implements Generator { public class GeneratorIntrospection implements Generator {
// Keep in cache all the object already parsed ==> optimize CPU // Keep in cache all the object already parsed ==> optimize CPU
@ -24,13 +25,39 @@ public class GeneratorIntrospection implements Generator {
public GeneratorIntrospection(final ModelType model, final Class<?> classType, final String rootNodeName) throws Exception { public GeneratorIntrospection(final ModelType model, final Class<?> classType, final String rootNodeName) throws Exception {
this.rootNodeName = rootNodeName; this.rootNodeName = rootNodeName;
this.rootClassType = classType; this.rootClassType = classType;
MapKey key = new MapKey(model, classType); final MapKey key = new MapKey(model, classType);
// TODO pb if it is a List or an Array ... // TODO pb if it is a List or an Array ...
this.elements.put(key, IntrospectionModelFactory.createModel(key)); this.elements.put(key, IntrospectionModelFactory.createModel(key));
} }
IntrospectionModel findOrCreate(final ModelType model, final String name, final Class<?> classType) throws ExmlBuilderException { private <T> String autoArrayToString(final Class<T> clazz, final Object inData, final IntrospectionModel model) throws ExmlBuilderException, AknotException {
MapKey key = new MapKey(model, name, classType); @SuppressWarnings("unchecked")
final T[] datas = (T[]) inData;
final StringBuilder out = new StringBuilder();
for (int iii = 0; iii < datas.length; iii++) {
if (!out.isEmpty()) {
out.append(";");
}
out.append(model.toString(datas[iii]));
}
return out.toString();
}
private <T> String autoListToString(final Class<T> clazz, final Object inData, final IntrospectionModel model) throws ExmlBuilderException, AknotException {
@SuppressWarnings("unchecked")
final List<T> elements1 = (List<T>) inData;
final StringBuilder out = new StringBuilder();
for (final Object elem1 : elements1) {
if (!out.isEmpty()) {
out.append(";");
}
out.append(model.toString(elem1));
}
return out.toString();
}
IntrospectionModel findOrCreate(final ModelType model, final String name, final Class<?> classType) throws ExmlBuilderException, AknotException {
final MapKey key = new MapKey(model, name, classType);
IntrospectionModel out = this.elements.get(key); IntrospectionModel out = this.elements.get(key);
if (out != null) { if (out != null) {
return out; return out;
@ -46,151 +73,61 @@ public class GeneratorIntrospection implements Generator {
return out; return out;
} }
private <T> String autoArrayToString(final Class<T> clazz, final Object inData, final IntrospectionModel model) throws ExmlBuilderException { public void generate(final Object root, final StringBuilder tmpp) throws ExmlBuilderException, AknotException {
@SuppressWarnings("unchecked") final IntrospectionModel introspection = findOrCreate(ModelType.NORMAL, null, root.getClass());
T[] datas = (T[])inData; generateNode(root, introspection, this.rootNodeName, tmpp, 0);
StringBuilder out = new StringBuilder();
for(int iii=0; iii<datas.length; iii++) {
if (!out.isEmpty()) {
out.append(";");
}
out.append(model.toString(datas[iii]));
}
return out.toString();
} }
private <T> String autoListToString(final Class<T> clazz, final Object inData, final IntrospectionModel model) throws ExmlBuilderException { public <T> void generateArrayNode(final Class<T> clazz, final Object data, final IntrospectionModel model, final String nodeName, final StringBuilder tmpp, final int indent)
@SuppressWarnings("unchecked") throws ExmlBuilderException, AknotException {
List<T> elements1 = (List<T>)inData;
StringBuilder out = new StringBuilder();
for (Object elem1: elements1) {
if (!out.isEmpty()) {
out.append(";");
}
out.append(model.toString(elem1));
}
return out.toString();
}
public void generateProperties(final Object data, final IntrospectionModel introspection, final StringBuilder tmpp) throws ExmlBuilderException {
List<IntrospectionProperty> elements = introspection.getAttributes();
if (elements == null) {
return;
}
for (IntrospectionProperty elem : elements) {
if (!elem.canGetValue()) {
continue;
}
Object dataObj = elem.getValue(data);
if (dataObj == null) {
continue;
}
String name = elem.getNames()[0];
Class<?> type = elem.getType();
String dataString = null;
if (type.isArray()) {
Class<?> typeClass = elem.getType().componentType();
if (typeClass.isPrimitive()) {
dataString = ArraysTools.primitivaArrayToSting(dataObj);
} else {
IntrospectionModel introspectionSub = findOrCreate(ModelType.NORMAL, null, typeClass);
dataString = autoArrayToString(typeClass, dataObj, introspectionSub);
}
} else if (List.class.isAssignableFrom(type)) {
Class<?> typeClass = elem.getSubType();
IntrospectionModel introspectionSub = findOrCreate(ModelType.NORMAL, null, typeClass);
dataString = autoListToString(typeClass, dataObj, introspectionSub);
} else {
IntrospectionModel introspectionSub = findOrCreate(ModelType.NORMAL, null, dataObj.getClass());
dataString = introspectionSub.toString(dataObj);
}
if (dataString != null) {
tmpp.append(" ");
tmpp.append(name);
tmpp.append("=\"");
tmpp.append(dataString);
tmpp.append("\"");
}
}
}
public void generateSubNodes(final Object data, final IntrospectionModel introspection, final StringBuilder tmpp, final int indent) throws ExmlBuilderException {
List<IntrospectionProperty> elements = introspection.getNodes();
for (IntrospectionProperty elem : elements) {
if (!elem.canGetValue()) {
continue;
}
Object dataObj = elem.getValue(data);
if (dataObj == null) {
continue;
}
String name = elem.getNames()[0];
Class<?> type = elem.getType();
IntrospectionModel introspectionSub = null;
if (type.isArray()) {
Class<?> typeClass = elem.getType().componentType();
String listTreeName = elem.getListName();
introspectionSub = findOrCreate(ModelType.ARRAY, listTreeName, typeClass);
} else if (List.class.isAssignableFrom(type)) {
Class<?> typeClass = elem.getSubType();
String listTreeName = elem.getListName();
introspectionSub = findOrCreate(ModelType.LIST, listTreeName, typeClass);
} else {
introspectionSub = findOrCreate(ModelType.NORMAL, null, dataObj.getClass());
}
generateNode(dataObj, introspectionSub, name, tmpp, indent);
}
}
public <T> void generateArrayNode(final Class<T> clazz, final Object data, final IntrospectionModel model, final String nodeName, final StringBuilder tmpp, final int indent) throws ExmlBuilderException {
//Class<?> clazzData = data.getClass(); //Class<?> clazzData = data.getClass();
if (clazz.isPrimitive()) { if (clazz.isPrimitive()) {
if (clazz == byte.class) { if (clazz == byte.class) {
byte[] datas = (byte[]) data; final byte[] datas = (byte[]) data;
for (int iii=0; iii<datas.length; iii++) { for (int iii = 0; iii < datas.length; iii++) {
generateNode(datas[iii], model, nodeName, tmpp, indent); generateNode(datas[iii], model, nodeName, tmpp, indent);
} }
} else if (clazz == boolean.class) { } else if (clazz == boolean.class) {
boolean[] datas = (boolean[]) data; final boolean[] datas = (boolean[]) data;
for (int iii=0; iii<datas.length; iii++) { for (int iii = 0; iii < datas.length; iii++) {
generateNode(datas[iii], model, nodeName, tmpp, indent); generateNode(datas[iii], model, nodeName, tmpp, indent);
} }
} else if (clazz == short.class) { } else if (clazz == short.class) {
short[] datas = (short[]) data; final short[] datas = (short[]) data;
for (int iii=0; iii<datas.length; iii++) { for (int iii = 0; iii < datas.length; iii++) {
generateNode(datas[iii], model, nodeName, tmpp, indent); generateNode(datas[iii], model, nodeName, tmpp, indent);
} }
} else if (clazz == int.class) { } else if (clazz == int.class) {
int[] datas = (int[]) data; final int[] datas = (int[]) data;
for (int iii=0; iii<datas.length; iii++) { for (int iii = 0; iii < datas.length; iii++) {
generateNode(datas[iii], model, nodeName, tmpp, indent); generateNode(datas[iii], model, nodeName, tmpp, indent);
} }
} else if (clazz == long.class) { } else if (clazz == long.class) {
long[] datas = (long[]) data; final long[] datas = (long[]) data;
for (int iii=0; iii<datas.length; iii++) { for (int iii = 0; iii < datas.length; iii++) {
generateNode(datas[iii], model, nodeName, tmpp, indent); generateNode(datas[iii], model, nodeName, tmpp, indent);
} }
} else if (clazz == float.class) { } else if (clazz == float.class) {
float[] datas = (float[]) data; final float[] datas = (float[]) data;
for (int iii=0; iii<datas.length; iii++) { for (int iii = 0; iii < datas.length; iii++) {
generateNode(datas[iii], model, nodeName, tmpp, indent); generateNode(datas[iii], model, nodeName, tmpp, indent);
} }
} else if (clazz == double.class) { } else if (clazz == double.class) {
double[] datas = (double[]) data; final double[] datas = (double[]) data;
for (int iii=0; iii<datas.length; iii++) { for (int iii = 0; iii < datas.length; iii++) {
generateNode(datas[iii], model, nodeName, tmpp, indent); generateNode(datas[iii], model, nodeName, tmpp, indent);
} }
} }
return; return;
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
T[] datas = (T[]) data; final T[] datas = (T[]) data;
for (int iii=0; iii<datas.length; iii++) { for (int iii = 0; iii < datas.length; iii++) {
generateNode(datas[iii], model, nodeName, tmpp, indent); generateNode(datas[iii], model, nodeName, tmpp, indent);
} }
} }
public void generateNode(final Object data, final IntrospectionModel model, final String nodeName, final StringBuilder tmpp, final int indent) throws ExmlBuilderException, AknotException {
public void generateNode(final Object data, final IntrospectionModel model, final String nodeName, final StringBuilder tmpp, final int indent) throws ExmlBuilderException {
if (model.isNative()) { if (model.isNative()) {
Tools.addIndent(tmpp, indent); Tools.addIndent(tmpp, indent);
tmpp.append("<"); tmpp.append("<");
@ -201,8 +138,8 @@ public class GeneratorIntrospection implements Generator {
tmpp.append(nodeName); tmpp.append(nodeName);
tmpp.append(">"); tmpp.append(">");
} else if (model.isArray()) { } else if (model.isArray()) {
List<String> baseName = model.getNodeAvaillable(); final List<String> baseName = model.getNodeAvaillable();
IntrospectionModel introspectionSub = findOrCreate(ModelType.NORMAL, null, model.getClassType()); final IntrospectionModel introspectionSub = findOrCreate(ModelType.NORMAL, null, model.getClassType());
if (baseName == null || baseName.size() == 0) { if (baseName == null || baseName.size() == 0) {
// mode render : <nodeName>aaa</nodeName><nodeName>bbb</nodeName> // mode render : <nodeName>aaa</nodeName><nodeName>bbb</nodeName>
generateArrayNode(model.getClassType(), data, introspectionSub, nodeName, tmpp, indent); generateArrayNode(model.getClassType(), data, introspectionSub, nodeName, tmpp, indent);
@ -212,7 +149,7 @@ public class GeneratorIntrospection implements Generator {
tmpp.append("<"); tmpp.append("<");
tmpp.append(nodeName); tmpp.append(nodeName);
tmpp.append(">"); tmpp.append(">");
generateArrayNode(model.getClassType(), data, introspectionSub, baseName.get(0), tmpp, indent+1); generateArrayNode(model.getClassType(), data, introspectionSub, baseName.get(0), tmpp, indent + 1);
Tools.addIndent(tmpp, indent); Tools.addIndent(tmpp, indent);
tmpp.append("</"); tmpp.append("</");
tmpp.append(nodeName); tmpp.append(nodeName);
@ -220,14 +157,14 @@ public class GeneratorIntrospection implements Generator {
} }
Log.error("lkjlk"); Log.error("lkjlk");
} else if (model.isList()) { } else if (model.isList()) {
List<String> baseName = model.getNodeAvaillable(); final List<String> baseName = model.getNodeAvaillable();
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
List<Object> datas = (List<Object>)data; final List<Object> datas = (List<Object>) data;
if (baseName == null || baseName.size() == 0) { if (baseName == null || baseName.size() == 0) {
// mode render : <nodeName>aaa</nodeName><nodeName>bbb</nodeName> // mode render : <nodeName>aaa</nodeName><nodeName>bbb</nodeName>
for (Object elem : datas) { for (final Object elem : datas) {
// note the type can change in List ... // note the type can change in List ...
IntrospectionModel introspectionSub = findOrCreate(ModelType.NORMAL, null, elem.getClass()); final IntrospectionModel introspectionSub = findOrCreate(ModelType.NORMAL, null, elem.getClass());
generateNode(elem, introspectionSub, nodeName, tmpp, indent); generateNode(elem, introspectionSub, nodeName, tmpp, indent);
} }
} else { } else {
@ -236,10 +173,10 @@ public class GeneratorIntrospection implements Generator {
tmpp.append("<"); tmpp.append("<");
tmpp.append(nodeName); tmpp.append(nodeName);
tmpp.append(">"); tmpp.append(">");
for (Object elem : datas) { for (final Object elem : datas) {
// note the type can change in List ... // note the type can change in List ...
IntrospectionModel introspectionSub = findOrCreate(ModelType.NORMAL, null, elem.getClass()); final IntrospectionModel introspectionSub = findOrCreate(ModelType.NORMAL, null, elem.getClass());
generateNode(elem, introspectionSub, baseName.get(0), tmpp, indent+1); generateNode(elem, introspectionSub, baseName.get(0), tmpp, indent + 1);
} }
//tmpp.append(model.toString(data)); //tmpp.append(model.toString(data));
Tools.addIndent(tmpp, indent); Tools.addIndent(tmpp, indent);
@ -274,8 +211,74 @@ public class GeneratorIntrospection implements Generator {
} }
} }
public void generate(final Object root, final StringBuilder tmpp) throws ExmlBuilderException {
IntrospectionModel introspection = findOrCreate(ModelType.NORMAL, null, root.getClass()); public void generateProperties(final Object data, final IntrospectionModel introspection, final StringBuilder tmpp) throws ExmlBuilderException, AknotException {
generateNode(root, introspection, this.rootNodeName, tmpp, 0); final List<IntrospectionProperty> elements = introspection.getAttributes();
if (elements == null) {
return;
}
for (final IntrospectionProperty elem : elements) {
if (!elem.canGetValue()) {
continue;
}
final Object dataObj = elem.getValue(data);
if (dataObj == null) {
continue;
}
final String name = elem.getNames()[0];
final Class<?> type = elem.getType();
String dataString = null;
if (type.isArray()) {
final Class<?> typeClass = elem.getType().componentType();
if (typeClass.isPrimitive()) {
dataString = ArraysTools.primitivaArrayToSting(dataObj);
} else {
final IntrospectionModel introspectionSub = findOrCreate(ModelType.NORMAL, null, typeClass);
dataString = autoArrayToString(typeClass, dataObj, introspectionSub);
}
} else if (List.class.isAssignableFrom(type)) {
final Class<?> typeClass = elem.getSubType();
final IntrospectionModel introspectionSub = findOrCreate(ModelType.NORMAL, null, typeClass);
dataString = autoListToString(typeClass, dataObj, introspectionSub);
} else {
final IntrospectionModel introspectionSub = findOrCreate(ModelType.NORMAL, null, dataObj.getClass());
dataString = introspectionSub.toString(dataObj);
}
if (dataString != null) {
tmpp.append(" ");
tmpp.append(name);
tmpp.append("=\"");
tmpp.append(dataString);
tmpp.append("\"");
}
}
}
public void generateSubNodes(final Object data, final IntrospectionModel introspection, final StringBuilder tmpp, final int indent) throws ExmlBuilderException, AknotException {
final List<IntrospectionProperty> elements = introspection.getNodes();
for (final IntrospectionProperty elem : elements) {
if (!elem.canGetValue()) {
continue;
}
final Object dataObj = elem.getValue(data);
if (dataObj == null) {
continue;
}
final String name = elem.getNames()[0];
final Class<?> type = elem.getType();
IntrospectionModel introspectionSub = null;
if (type.isArray()) {
final Class<?> typeClass = elem.getType().componentType();
final String listTreeName = elem.getListName();
introspectionSub = findOrCreate(ModelType.ARRAY, listTreeName, typeClass);
} else if (List.class.isAssignableFrom(type)) {
final Class<?> typeClass = elem.getSubType();
final String listTreeName = elem.getListName();
introspectionSub = findOrCreate(ModelType.LIST, listTreeName, typeClass);
} else {
introspectionSub = findOrCreate(ModelType.NORMAL, null, dataObj.getClass());
}
generateNode(dataObj, introspectionSub, name, tmpp, indent);
}
} }
} }

View File

@ -5,7 +5,7 @@
*/ */
package org.atriasoft.exml.model; package org.atriasoft.exml.model;
import org.atriasoft.exml.parser.FilePos; import org.atriasoft.etk.util.FilePos;
/** /**
* Single attribute element * Single attribute element

View File

@ -1,185 +0,0 @@
/** @file
* @author Edouard DUPIN
* @copyright 2021, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
package org.atriasoft.exml.parser;
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
/**
* Position in the file of the original data.
*/
public class FilePos {
private int col; //!< source text colomn
private int line; //!< source Line colomn
/**
* default contructor (set line and col at 0)
*/
public FilePos() {
this.col = 0;
this.line = 0;
}
/**
* initialize constructor
* @param line Line in the file
* @param col Colomn in the file
*/
public FilePos(final int line, final int col) {
this.col = col;
this.line = line;
}
/**
* Addition operator
* @param obj Addition object..
* @return Reference on this
*/
public FilePos add(final FilePos obj) {
if (obj.line == 0) {
this.col += obj.col;
} else {
this.col = obj.col;
this.line += obj.line;
}
return this;
}
/**
* Colomn addition operator
* @param col Number of colomn to add
* @return Reference on this
*/
public FilePos add(final int col) {
this.col += col;
return this;
}
/**
* Check if the value is a new line and update internal property
* @param val Char value to check
* @return true We find a new line
* @return false We NOT find a new line
*/
public boolean check(final Character val) {
this.col++;
if (val == '\n') {
newLine();
return true;
}
return false;
}
/**
* Reset position at 0,0
*/
public void clear() {
this.col = 0;
this.line = 0;
}
@Override
public FilePos clone() {
final FilePos out = new FilePos();
out.col = this.col;
out.line = this.line;
return out;
}
/**
* Decrement the colomn position
* @return Reference on this
*/
public FilePos decrement() {
this.col--;
return this;
}
@Override
public boolean equals(final Object obj) {
if (obj == null) {
return false;
}
if (!(obj instanceof FilePos)) {
return false;
}
final FilePos other = (FilePos) obj;
return this.col == other.col && this.line == other.line;
}
/**
* Get the colomn position
* @return Colomn in number of utf8-char
*/
public int getCol() {
return this.col;
}
/**
* Get the line number position
* @return line ID (start at 0)
*/
public int getLine() {
return this.line;
}
@Override
public int hashCode() {
return super.hashCode() + this.line + this.col;
}
/**
* Increment the colomn position
* @return Reference on this
*/
public FilePos increment() {
this.col++;
return this;
}
/**
* Find a new line & reset colomn at 0
*/
public void newLine() {
this.col = 0;
this.line++;
}
/**
* Asignment operator
* @param obj Object to copy
* @return Reference on this
*/
public FilePos set(final FilePos obj) {
this.col = obj.col;
this.line = obj.line;
return this;
}
/**
* Setter of specific data
* @param line Line in the file
* @param col Colomn in the file
*/
public void set(final int line, final int col) {
this.col = col;
this.line = line;
}
@Override
public String toString() {
String out = "(l=";
out += this.line;
out += ",c=";
out += this.col;
out += ")";
return out;
}
}

View File

@ -1,5 +1,8 @@
package org.atriasoft.exml.parser; package org.atriasoft.exml.parser;
import org.atriasoft.aknot.exception.AknotException;
import org.atriasoft.etk.Tools;
import org.atriasoft.etk.util.FilePos;
import org.atriasoft.exml.builder.Builder; import org.atriasoft.exml.builder.Builder;
import org.atriasoft.exml.exception.ExmlException; import org.atriasoft.exml.exception.ExmlException;
import org.atriasoft.exml.exception.ExmlParserError; import org.atriasoft.exml.exception.ExmlParserError;
@ -14,7 +17,8 @@ public class ParseXml {
this.builder = builder; this.builder = builder;
} }
protected boolean iParseAttribute(final Object parent, final String data, final PositionParsing pos, final FilePos filePos, final ParsingProperty parsingProperty) throws ExmlException { protected boolean iParseAttribute(final Object parent, final String data, final PositionParsing pos, final FilePos filePos, final ParsingProperty parsingProperty)
throws ExmlException, AknotException {
Log.verbose("start parse : 'attribute'"); Log.verbose("start parse : 'attribute'");
// search end of the comment : // search end of the comment :
int lastElementName = pos.value; int lastElementName = pos.value;
@ -105,7 +109,8 @@ public class ParseXml {
return true; return true;
} }
protected boolean iParseCDATA(final Object parent, final String data, final PositionParsing pos, final FilePos filePos, final ParsingProperty parsingProperty) throws ExmlException { protected boolean iParseCDATA(final Object parent, final String data, final PositionParsing pos, final FilePos filePos, final ParsingProperty parsingProperty)
throws ExmlException, AknotException {
Log.verbose("start parse : 'text::CDATA'"); Log.verbose("start parse : 'text::CDATA'");
// search end of the comment : // search end of the comment :
for (int iii = pos.value; iii + 2 < data.length(); iii++) { for (int iii = pos.value; iii + 2 < data.length(); iii++) {
@ -128,7 +133,8 @@ public class ParseXml {
return false; return false;
} }
protected boolean iParseComment(final Object parent, final String data, final PositionParsing pos, final FilePos filePos, final ParsingProperty parsingProperty) throws ExmlException { protected boolean iParseComment(final Object parent, final String data, final PositionParsing pos, final FilePos filePos, final ParsingProperty parsingProperty)
throws ExmlException, AknotException {
Log.verbose("start parse : 'comment'"); Log.verbose("start parse : 'comment'");
final FilePos tmpPos = new FilePos(); final FilePos tmpPos = new FilePos();
final int white = Tools.countWhiteChar(data, pos.value, tmpPos); final int white = Tools.countWhiteChar(data, pos.value, tmpPos);
@ -162,7 +168,8 @@ public class ParseXml {
return false; return false;
} }
protected boolean iParseDeclaration(final Object parent, final String data, final PositionParsing pos, final FilePos filePos, final ParsingProperty parsingProperty) throws ExmlException { protected boolean iParseDeclaration(final Object parent, final String data, final PositionParsing pos, final FilePos filePos, final ParsingProperty parsingProperty)
throws ExmlException, AknotException {
// search end of the comment : // search end of the comment :
for (int iii = pos.value; iii + 1 < data.length(); iii++) { for (int iii = pos.value; iii + 1 < data.length(); iii++) {
Tools.drawElementParsed(data.charAt(iii), filePos); Tools.drawElementParsed(data.charAt(iii), filePos);
@ -217,7 +224,7 @@ public class ParseXml {
} }
protected boolean iParseElement(final Object parent, final String nameElement, final String data, final PositionParsing pos, final FilePos filePos, final ParsingProperty parsingProperty) protected boolean iParseElement(final Object parent, final String nameElement, final String data, final PositionParsing pos, final FilePos filePos, final ParsingProperty parsingProperty)
throws ExmlException { throws ExmlException, AknotException {
// note : When start parsing the upper element must have set the value of the element and set the position after this one // note : When start parsing the upper element must have set the value of the element and set the position after this one
// find a normal node ... // find a normal node ...
for (int iii = pos.value; iii < data.length(); iii++) { for (int iii = pos.value; iii < data.length(); iii++) {
@ -335,7 +342,7 @@ public class ParseXml {
return data.length(); return data.length();
} }
protected boolean iParseText(final Object parent, final String data, final PositionParsing pos, final FilePos filePos, final ParsingProperty parsingProperty) throws ExmlException { protected boolean iParseText(final Object parent, final String data, final PositionParsing pos, final FilePos filePos, final ParsingProperty parsingProperty) throws ExmlException, AknotException {
Log.verbose("start parse : 'text'"); Log.verbose("start parse : 'text'");
if (this.builder.isPackText(parent)) { if (this.builder.isPackText(parent)) {
final int endOfText = iParseFindTextPackEnd(data, pos.value); final int endOfText = iParseFindTextPackEnd(data, pos.value);
@ -375,7 +382,7 @@ public class ParseXml {
return false; return false;
} }
public Object parse(final String data, final ParsingProperty property) throws ExmlException { public Object parse(final String data, final ParsingProperty property) throws ExmlException, AknotException {
Log.verbose("Start parsing document (type: string) size=" + data.length()); Log.verbose("Start parsing document (type: string) size=" + data.length());
// came from char == > force in utf8 ... // came from char == > force in utf8 ...
final FilePos pos = new FilePos(1, 0); final FilePos pos = new FilePos(1, 0);
@ -405,7 +412,7 @@ public class ParseXml {
* @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) protected boolean subParseElement(final Object parent, final String nameElement, final String data, final PositionParsing pos, final FilePos filePos, final ParsingProperty parsingProperty)
throws ExmlException { throws ExmlException, AknotException {
//EXMLPARSEELEMENT(" start subParse ... " << pos << " " << filePos); //EXMLPARSEELEMENT(" start subParse ... " << pos << " " << filePos);
for (int iii = pos.value; iii < data.length(); iii++) { for (int iii = pos.value; iii < data.length(); iii++) {
filePos.check(data.charAt(iii)); filePos.check(data.charAt(iii));

View File

@ -4,6 +4,7 @@ import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import org.atriasoft.etk.Tools;
import org.atriasoft.exml.exception.ExmlParserError; import org.atriasoft.exml.exception.ExmlParserError;
import org.atriasoft.exml.internal.Log; import org.atriasoft.exml.internal.Log;

View File

@ -1,493 +0,0 @@
package org.atriasoft.exml.parser;
public class Tools {
/**
* add indentation of the string input.
* @param data String where the indentation is done.
* @param indent Number of tab to add at the string.
*/
public static void addIndent(final StringBuilder data, final int indent) {
if (!data.isEmpty()) {
data.append("\n");
}
for (int iii = 0; iii < indent; iii++) {
data.append("\t");
}
}
/**
* check if an element or attribute is availlable (not : !"#$%&'()*+,/;<=>?@[\]^`{|}~ \\n\\t\\r and for first char : not -.0123456789).
* @param val Value to check the conformity.
* @param firstChar True if the element check is the first char.
* @return true The value can be a part of attribute name
* @return false The value can NOT be a part of attribute name
*/
public static boolean checkAvaillable(final Character val, final boolean firstChar) {
if (val == '!' || val == '"' || val == '#' || val == '$' || val == '%' || val == '&' || val == '\'' || val == '(' || val == ')' || val == '*' || val == '+' || val == ',' || val == '/'
|| val == ';' || val == '<' || val == '=' || val == '>' || val == '?' || val == '@' || val == '[' || val == '\\' || val == ']' || val == '^' || val == '`' || val == '{' || val == '|'
|| val == '}' || val == '~' || val == ' ' || val == '\n' || val == '\t' || val == '\r') {
return false;
}
if (firstChar) {
if (val == '-' || val == '.' || (val >= '0' && val <= '9')) {
return false;
}
}
return true;
}
public static boolean checkNumber(final Character val, final boolean firstChar) {
if (val == '.' || (val >= '0' && val <= '9')) {
return true;
}
if (firstChar && val == '-') {
return true;
}
return false;
}
public static String cleanNumberList(final String data) {
return data.replaceAll("[ \t\n\r]", "").replaceAll(",", ";");
}
/**
* count the number of white char in the string from the specify position (stop at the first element that is not a white char)
* @param data Data to parse.
* @param pos Start position in the string.
* @param filePos new poistion of te file to add.
* @return number of white element.
*/
public static int countWhiteChar(final String data, final int pos, final FilePos filePos) {
filePos.clear();
int white = 0;
for (int iii = pos; iii < data.length(); iii++) {
filePos.check(data.charAt(iii));
if (!Tools.isWhiteChar(data.charAt(iii))) {
break;
}
white++;
}
filePos.decrement();
return white;
}
public static String createPosPointer(final String line, final int pos) {
final StringBuilder out = new StringBuilder();
int iii;
for (iii = 0; iii < pos && iii < line.length(); iii++) {
if (line.charAt(iii) == '\t') {
out.append("\t");
} else {
out.append(" ");
}
}
for (; iii < pos; iii++) {
out.append(" ");
}
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
public static String decapitalizeFirst(final String string) {
if (string == null || string.length() == 0) {
return string;
}
final char[] c = string.toCharArray();
c[0] = Character.toLowerCase(c[0]);
return new String(c);
}
/**
* Display the cuurent element that is curently parse.
* @param val Char that is parsed.
* @param filePos Position of the char in the file.
*/
public static void drawElementParsed(final Character val, final FilePos filePos) {
// if (val == '\n') {
// Log.error(filePos + " parse '\\n'");
// } else if (val == '\t') {
// Log.error(filePos + " parse '\\t'");
// } else {
// Log.error(filePos + " parse '" + val + "'");
// }
}
public static String extractLine(final String data, final int pos) {
// search back : '\n'
int startPos = data.lastIndexOf('\n', pos);
if (startPos == pos) {
startPos = 0;
} else {
startPos++;
}
// search forward : '\n'
int stopPos = pos;
if (data.length() == pos) {
stopPos = pos;
} else if (data.charAt(pos) != '\n') {
stopPos = data.indexOf('\n', pos);
if (stopPos == pos) {
stopPos = data.length();
}
}
if (startPos == -1) {
startPos = 0;
} else if (startPos >= data.length()) {
return "";
}
if (stopPos == -1) {
return "";
}
if (stopPos >= data.length()) {
stopPos = data.length();
}
return data.substring(startPos, stopPos);
}
public static boolean isWhiteChar(final Character val) {
if (val == ' ' || val == '\t' || val == '\n' || val == '\r') {
return true;
}
return false;
}
public static Boolean[] parseBooleanClassStringList(String data) {
data = Tools.cleanNumberList(data);
final String[] dataArray = data.split(";");
final Boolean[] out = new Boolean[dataArray.length];
int count = 0;
for (final String str : dataArray) {
out[count++] = Boolean.valueOf(str);
}
return out;
}
public static boolean[] parseBooleanStringList(String data) {
data = Tools.cleanNumberList(data);
final String[] dataArray = data.split(";");
final boolean[] out = new boolean[dataArray.length];
int count = 0;
for (final String str : dataArray) {
out[count++] = Boolean.parseBoolean(str);
}
return out;
}
public static Byte[] parseByteClassStringList(String data) {
data = Tools.cleanNumberList(data);
final String[] dataArray = data.split(";");
final Byte[] out = new Byte[dataArray.length];
int count = 0;
for (final String str : dataArray) {
out[count++] = Byte.parseByte(str);
}
return out;
}
public static byte[] parseByteStringList(String data) {
data = Tools.cleanNumberList(data);
final String[] dataArray = data.split(";");
final byte[] out = new byte[dataArray.length];
int count = 0;
for (final String str : dataArray) {
out[count++] = Byte.parseByte(str);
}
return out;
}
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 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) {
data = Tools.cleanNumberList(data);
final String[] dataArray = data.split(";");
final Integer[] out = new Integer[dataArray.length];
int count = 0;
for (final String str : dataArray) {
out[count++] = Integer.parseInt(str);
}
return out;
}
public static int[] parseIntegerStringList(String data) {
data = Tools.cleanNumberList(data);
final String[] dataArray = data.split(";");
final int[] out = new int[dataArray.length];
int count = 0;
for (final String str : dataArray) {
out[count++] = Integer.parseInt(str);
}
return out;
}
public static Long[] parseLongClassStringList(String data) {
data = Tools.cleanNumberList(data);
final String[] dataArray = data.split(";");
final Long[] out = new Long[dataArray.length];
int count = 0;
for (final String str : dataArray) {
out[count++] = Long.parseLong(str);
}
return out;
}
public static long[] parseLongStringList(String data) {
data = Tools.cleanNumberList(data);
final String[] dataArray = data.split(";");
final long[] out = new long[dataArray.length];
int count = 0;
for (final String str : dataArray) {
out[count++] = Long.parseLong(str);
}
return out;
}
public static Short[] parseShortClassStringList(String data) {
data = Tools.cleanNumberList(data);
final String[] dataArray = data.split(";");
final Short[] out = new Short[dataArray.length];
int count = 0;
for (final String str : dataArray) {
out[count++] = Short.parseShort(str);
}
return out;
}
public static short[] parseShortStringList(String data) {
data = Tools.cleanNumberList(data);
final String[] dataArray = data.split(";");
final short[] out = new short[dataArray.length];
int count = 0;
for (final String str : dataArray) {
out[count++] = Short.parseShort(str);
}
return out;
}
// transform the Text with :
// "&lt;" == "<"
// "&gt;" == ">"
// "&amp;" == "&"
// "&apos;" == "'"
// "&quot;" == """
public static String replaceSpecialChar(final String inval) {
String out = inval;
out = out.replace("&lt;", "<");
out = out.replace("&gt;", ">");
out = out.replace("&apos;", "'");
out = out.replace("&quot;", "\"");
out = out.replace("&amp;", "&");
//EXMLERROR("INNN '"<< inval << "' => '" << out << "'");
return out;
}
public static String replaceSpecialCharOut(final String inval) {
String out = inval;
out = out.replace("<", "&lt;");
out = out.replace(">", "&gt;");
out = out.replace("'", "&apos;");
out = out.replace("\"", "&quot;");
out = out.replace("&", "&amp;");
//EXMLERROR("OUTTT '"<< inval << "' => '" << out << "'");
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

@ -2,6 +2,7 @@ package org.atriasoft.exml.serializer;
import java.util.List; import java.util.List;
import org.atriasoft.etk.Tools;
import org.atriasoft.exml.internal.Log; import org.atriasoft.exml.internal.Log;
import org.atriasoft.exml.model.XmlAttribute; import org.atriasoft.exml.model.XmlAttribute;
import org.atriasoft.exml.model.XmlAttributeList; import org.atriasoft.exml.model.XmlAttributeList;
@ -11,7 +12,6 @@ import org.atriasoft.exml.model.XmlElement;
import org.atriasoft.exml.model.XmlNode; import org.atriasoft.exml.model.XmlNode;
import org.atriasoft.exml.model.XmlNodeType; import org.atriasoft.exml.model.XmlNodeType;
import org.atriasoft.exml.model.XmlText; import org.atriasoft.exml.model.XmlText;
import org.atriasoft.exml.parser.Tools;
public class SerializerXml { public class SerializerXml {
public static void serialize(final XmlNode node, final StringBuilder data, final int indent) { public static void serialize(final XmlNode node, final StringBuilder data, final int indent) {
@ -45,7 +45,7 @@ public class SerializerXml {
private static void serializeComment(final XmlComment comment, final StringBuilder data, final int indent) { private static void serializeComment(final XmlComment comment, final StringBuilder data, final int indent) {
Tools.addIndent(data, indent); Tools.addIndent(data, indent);
data.append("<!--"); data.append("<!--");
String commentData = comment.getValue(); final String commentData = comment.getValue();
if (commentData != null) { if (commentData != null) {
data.append(comment.getValue()); data.append(comment.getValue());
} }
@ -76,7 +76,7 @@ public class SerializerXml {
Log.verbose(" generate : '" + data + "'"); Log.verbose(" generate : '" + data + "'");
} else { } else {
data.append(">"); data.append(">");
for (XmlNode node : nodes) { for (final XmlNode node : nodes) {
if (node != null) { if (node != null) {
SerializerXml.serialize(node, data, indent + 1); SerializerXml.serialize(node, data, indent + 1);
} }

View File

@ -2,6 +2,7 @@ package org.atriasoft.exml.serializer;
import java.util.List; import java.util.List;
import org.atriasoft.etk.Tools;
import org.atriasoft.exml.generator.Generator; import org.atriasoft.exml.generator.Generator;
import org.atriasoft.exml.internal.Log; import org.atriasoft.exml.internal.Log;
import org.atriasoft.exml.model.XmlAttribute; import org.atriasoft.exml.model.XmlAttribute;
@ -13,7 +14,6 @@ import org.atriasoft.exml.model.XmlNode;
import org.atriasoft.exml.model.XmlNodeType; import org.atriasoft.exml.model.XmlNodeType;
import org.atriasoft.exml.model.XmlText; import org.atriasoft.exml.model.XmlText;
import org.atriasoft.exml.parser.ParsingProperty; import org.atriasoft.exml.parser.ParsingProperty;
import org.atriasoft.exml.parser.Tools;
public class SerializerXmlIntrospection { public class SerializerXmlIntrospection {
public static void serialize(final XmlNode node, final StringBuilder data, final int indent) { public static void serialize(final XmlNode node, final StringBuilder data, final int indent) {
@ -75,7 +75,7 @@ public class SerializerXmlIntrospection {
Log.verbose(" generate : '" + data + "'"); Log.verbose(" generate : '" + data + "'");
} else { } else {
data.append(">\n"); data.append(">\n");
for (XmlNode node : nodes) { for (final XmlNode node : nodes) {
if (node != null) { if (node != null) {
SerializerXmlIntrospection.serialize(node, data, indent + 1); SerializerXmlIntrospection.serialize(node, data, indent + 1);
} }
@ -103,6 +103,7 @@ public class SerializerXmlIntrospection {
} }
private final Generator generator; private final Generator generator;
public SerializerXmlIntrospection(final Generator generator) { public SerializerXmlIntrospection(final Generator generator) {
this.generator = generator; this.generator = generator;
} }
@ -110,7 +111,5 @@ public class SerializerXmlIntrospection {
public void generate(final Object root, final ParsingProperty property, final StringBuilder tmpp) { public void generate(final Object root, final ParsingProperty property, final StringBuilder tmpp) {
//property.append(Tools.replaceSpecialCharOut(root.getValue())); //property.append(Tools.replaceSpecialCharOut(root.getValue()));
} }
} }

View File

@ -5,10 +5,10 @@
*/ */
package test.atriasoft.exml; package test.atriasoft.exml;
import org.atriasoft.aknot.exception.AknotException;
import org.atriasoft.exml.Exml; import org.atriasoft.exml.Exml;
import org.atriasoft.exml.exception.ExmlException; import org.atriasoft.exml.exception.ExmlException;
import org.atriasoft.exml.model.XmlNode; import org.atriasoft.exml.model.XmlNode;
import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Assertions;
class ExmlLocal { class ExmlLocal {
@ -25,13 +25,17 @@ class ExmlLocal {
root = Exml.parse(input); root = Exml.parse(input);
if (errorPos == 1) { if (errorPos == 1) {
Assertions.fail("Must have detected an error"); Assertions.fail("Must have detected an error");
}
} catch (final AknotException e) {
if (errorPos == 1) {
return; return;
} }
Assertions.fail("Must have NOT detected an AknotException error");
} catch (final ExmlException e) { } catch (final ExmlException e) {
if (errorPos == 1) { if (errorPos == 1) {
return; return;
} }
Assertions.fail("Must have NOT detected an error"); Assertions.fail("Must have NOT detected an ExmlException error");
} }
final StringBuilder out = new StringBuilder(); final StringBuilder out = new StringBuilder();
// TODO 2 is for failing in generate ... // TODO 2 is for failing in generate ...