diff --git a/src/org/atriasoft/exml/Exml.java b/src/org/atriasoft/exml/Exml.java index 341e544..3798d8b 100644 --- a/src/org/atriasoft/exml/Exml.java +++ b/src/org/atriasoft/exml/Exml.java @@ -19,6 +19,7 @@ import org.atriasoft.exml.builder.Builder; import org.atriasoft.exml.builder.BuilderGeneric; 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.ExmlParserErrorMulti; import org.atriasoft.exml.generator.GeneratorIntrospection; @@ -42,7 +43,7 @@ public class Exml { public static void generate(final Object root, final String rootNodeName, final StringBuilder data) throws ExmlBuilderException { GeneratorIntrospection generator; try { - generator = new GeneratorIntrospection(root.getClass(), rootNodeName); + generator = new GeneratorIntrospection(ModelType.NORMAL, root.getClass(), rootNodeName); generator.generate(root, data); /* final SerializerXmlIntrospection serializer = new SerializerXmlIntrospection(generator); diff --git a/src/org/atriasoft/exml/builder/BuilderIntrospection.java b/src/org/atriasoft/exml/builder/BuilderIntrospection.java index 62ac2a0..1d494d9 100644 --- a/src/org/atriasoft/exml/builder/BuilderIntrospection.java +++ b/src/org/atriasoft/exml/builder/BuilderIntrospection.java @@ -9,24 +9,27 @@ import org.atriasoft.exml.internal.Log; public class BuilderIntrospection implements Builder { // Keep in cach all the object alredy parsed ==> optimize CPU - final Map, IntrospectionModel> elements = new HashMap<>(); + final Map elements = new HashMap<>(); // The root class (need to keep it if we use 2 time the builder, the root class is no more accessible). final Class rootClassType; final String rootNodeName; - public BuilderIntrospection(final Class classType, final String rootNodeName) throws Exception { + public BuilderIntrospection(final ModelType model, final Class classType, final String rootNodeName) throws Exception { this.rootNodeName = rootNodeName; this.rootClassType = classType; - this.elements.put(classType, IntrospectionModelFactory.createModel(classType)); + MapKey key = new MapKey(model, classType); + // TODO pb if it is a List or an Array ... + this.elements.put(key, IntrospectionModelFactory.createModelPlop(key)); } - IntrospectionModel findOrCreate(final Class classType) throws Exception { - IntrospectionModel out = this.elements.get(classType); + 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; } - out = IntrospectionModelFactory.createModel(classType); - this.elements.put(classType, out); + out = IntrospectionModelFactory.createModelPlop(key); + this.elements.put(key, out); return out; } @@ -44,49 +47,43 @@ public class BuilderIntrospection implements Builder { public Object newElement(final Object parent, final String nodeName) throws ExmlBuilderException, Exception { Log.warning("new element on NodeName=" + nodeName); final IntrospectionObject introspectionObject = (IntrospectionObject) parent; - // special case of user request parsing of element with ... - if (nodeName.equals(introspectionObject.getListNameModel())) { - IntrospectionModel inferData = introspectionObject.getDataInterface(); - if (inferData.getClassType().isArray()) { - inferData = findOrCreate(inferData.getClassType().getComponentType()); - } else if (List.class.isAssignableFrom(inferData.getClassType())) { - Log.critical("inferData = findOrCreate(inferData.getSubClassType());"); + IntrospectionModel model = introspectionObject.getModelIntrospection(); + Class typeClass = null; + String listTreeName = null; + if (model.isArray() || model.isList()) { + List nodesAvaillable = model.getNodeAvaillable(); + if (nodesAvaillable == null || nodesAvaillable.size() == 0) { + throw new ExmlBuilderException("Model can not have subNode with name: '" + nodeName + "'"); } - return new IntrospectionObject(inferData); - } - - // TODO here try to remove this condition (see): YYYYYYYYYYYYYYYYYYYYYYYYYYYY - if (introspectionObject.getDataInterface() == null) { - if (nodeName.contentEquals(this.rootNodeName)) { - Log.verbose("Create new class: " + this.rootClassType.getCanonicalName()); - final IntrospectionModel inferData = findOrCreate(this.rootClassType); - return new IntrospectionObject(inferData); + + if (!nodesAvaillable.get(0).equals(nodeName)) { + throw new ExmlBuilderException("Model can not have subNode with name: '" + nodeName + "'. Must be " + nodesAvaillable.get(0)); } - // need to add a throw on the node... - return null; // ==> disable the parsing.. (node is not parsed...) + typeClass = model.getClassType(); + } else { + typeClass = introspectionObject.getTypeOfSubNode(nodeName); + listTreeName = introspectionObject.getTreeNameOfSubNode(nodeName); } - Class typeClass = introspectionObject.getTypeOfSubNode(nodeName); - String listTreeName = introspectionObject.getTreeNameOfSubNode(nodeName); if (typeClass != null) { // specific case for List ==> need to get the subType in introspection ... if (typeClass.isArray()) { Class subTypeClass = typeClass.getComponentType(); Log.verbose("Create array new 'SUB' class: '" + typeClass.getCanonicalName() + "' for node '" + nodeName + "'"); - final IntrospectionModel inferData = findOrCreate(subTypeClass); + final IntrospectionModel inferData = findOrCreate(ModelType.ARRAY, listTreeName, subTypeClass); // Create the data when object is ended created... - return new IntrospectionObject(inferData, listTreeName); + return new IntrospectionObject(inferData); } if (List.class.isAssignableFrom(typeClass)) { Class subTypeClass = introspectionObject.getTypeOfSubNodeSubType(nodeName); Log.verbose("Create List new 'SUB' class: '" + typeClass.getCanonicalName() + "' for node '" + nodeName + "'"); - final IntrospectionModel inferData = findOrCreate(subTypeClass); + final IntrospectionModel inferData = findOrCreate(ModelType.LIST, listTreeName, subTypeClass); // Create the data when object is ended created... - return new IntrospectionObject(inferData, listTreeName); + return new IntrospectionObject(inferData); } Log.verbose("Create new class: '" + typeClass.getCanonicalName() + "' for node '" + nodeName + "'"); - final IntrospectionModel inferData = findOrCreate(typeClass); + final IntrospectionModel inferData = findOrCreate(ModelType.NORMAL, listTreeName, typeClass); // Create the data when object is ended created... - return new IntrospectionObject(inferData, listTreeName); + return new IntrospectionObject(inferData); } return null; @@ -95,30 +92,30 @@ public class BuilderIntrospection implements Builder { @Override public void newProperty(final Object element, final String propertyName, final String propertyValue) throws ExmlBuilderException, Exception { final IntrospectionObject introspectionObject = (IntrospectionObject) element; - if (introspectionObject.getDataInterface() == null) { - // property on nothing ??? - return; + IntrospectionModel model = introspectionObject.getModelIntrospection(); + if (model.isArray() || model.isList()) { + throw new ExmlBuilderException("Model (List/Array) can not have property with name '" + propertyName + "'"); } + // TODO Check here, maybe a big problem with the custum object in properties ... !!!!! introspectionObject.setProperty(propertyName, propertyValue); } @Override public Object newRoot() throws ExmlBuilderException { - // TODO here try to set : YYYYYYYYYYYYYYYYYYYYYYYYYYYY - /* - final IntrospectionData inferData = findOrCreate(this.rootClassType); - return new IntrospectionObject(inferData, rootNodeName); - */ - return new IntrospectionObject(); + final IntrospectionModel inferData = findOrCreate(ModelType.ARRAY, this.rootNodeName, this.rootClassType); + return new IntrospectionObject(inferData); } @Override public void newText(final Object parent, final String text) throws ExmlBuilderException { final IntrospectionObject introspectionObject = (IntrospectionObject) parent; - if (introspectionObject.getDataInterface() == null) { - // property on nothing ??? - return; + IntrospectionModel model = introspectionObject.getModelIntrospection(); + if (model.isArray() || model.isList()) { + List nodesAvaillable = model.getNodeAvaillable(); + if (nodesAvaillable != null && nodesAvaillable.size() != 0) { + throw new ExmlBuilderException("Model can not have direct text with model data= '" + text + "'"); + } } introspectionObject.setText(text); } @@ -126,7 +123,7 @@ public class BuilderIntrospection implements Builder { @Override public void endElement(final Object element) throws ExmlBuilderException { final IntrospectionObject introspectionObject = (IntrospectionObject) element; - if (introspectionObject.getDataInterface() == null) { + if (introspectionObject.getModelIntrospection() == null) { // property on nothing ??? return; } @@ -137,12 +134,12 @@ public class BuilderIntrospection implements Builder { @Override public void newElementFinished(final Object parent, final String tmpName, final Object element) { final IntrospectionObject introspectionElementObject = (IntrospectionObject) element; - if (introspectionElementObject.getDataInterface() == null) { + if (introspectionElementObject.getModelIntrospection() == null) { // property on nothing ??? return; } final IntrospectionObject introspectionParentObject = (IntrospectionObject) parent; - if (introspectionParentObject.getDataInterface() == null) { + if (introspectionParentObject.getModelIntrospection() == null) { if (tmpName.equals(this.rootNodeName)) { // this is the root node ... Object tmpp = introspectionParentObject.getData(); diff --git a/src/org/atriasoft/exml/builder/IntrospectionModel.java b/src/org/atriasoft/exml/builder/IntrospectionModel.java index daf2d24..c8e8837 100644 --- a/src/org/atriasoft/exml/builder/IntrospectionModel.java +++ b/src/org/atriasoft/exml/builder/IntrospectionModel.java @@ -53,14 +53,13 @@ public abstract class IntrospectionModel { public String getTreeNameOfSubNode(final Object data, final String nodeName) throws ExmlBuilderException { return null; } - public abstract boolean isEndPoint(); + public boolean isEndPoint() { + return false; + } + public boolean isArray() { + return false; + } public boolean isList() { - if (this.classType.isArray()) { - return true; - } - if (List.class.isAssignableFrom(this.classType) ) { - return true; - } return false; } public abstract String toString(final Object data); diff --git a/src/org/atriasoft/exml/builder/IntrospectionModelArray.java b/src/org/atriasoft/exml/builder/IntrospectionModelArray.java new file mode 100644 index 0000000..6e57bf3 --- /dev/null +++ b/src/org/atriasoft/exml/builder/IntrospectionModelArray.java @@ -0,0 +1,51 @@ +package org.atriasoft.exml.builder; + +import java.util.List; +import java.util.Map; + +import org.atriasoft.exml.exception.ExmlBuilderException; + + +public class IntrospectionModelArray extends IntrospectionModel { + final String nodeName; + + public IntrospectionModelArray(final String nodeName, final Class classType) { + super(classType); + this.nodeName = nodeName; + } + + @Override + Object createObject(final Map properties, final Map> nodes) throws ExmlBuilderException { + return null; + } + + @Override + protected List getNodeAvaillable() { + return null; + } + + @Override + public Object getValueFromText(final String text) throws ExmlBuilderException { + return new Object[0]; + } + + @Override + public Object getValue(final String propertyName, final String propertyValue) throws ExmlBuilderException { + return null; + } + + @Override + public boolean isArray() { + return true; + } + + @Override + public String toString(final Object data) { + return null; + } + @Override + public String[] toStringList(final Object data) { + return null; + } + +} diff --git a/src/org/atriasoft/exml/builder/IntrospectionModelFactory.java b/src/org/atriasoft/exml/builder/IntrospectionModelFactory.java index 131e9b3..ffbae85 100644 --- a/src/org/atriasoft/exml/builder/IntrospectionModelFactory.java +++ b/src/org/atriasoft/exml/builder/IntrospectionModelFactory.java @@ -7,11 +7,33 @@ import org.atriasoft.exml.exception.ExmlBuilderException; public class IntrospectionModelFactory { private IntrospectionModelFactory() {} - public static IntrospectionModel createModel(final Class classType) throws ExmlBuilderException { - if (StringSerializer.contains(classType)) { - return new IntrospectionModelBaseType(classType); + public static IntrospectionModel createModelsssss(final MapKey modelType) throws ExmlBuilderException { + /* + if (modelType.model() == ModelType.ARRAY) { + return new IntrospectionModelArray(modelType.type()); } - return new IntrospectionModelComplex(classType); + if (modelType.model() == ModelType.LIST) { + return new IntrospectionModelList(modelType.type()); + } + */ + if (StringSerializer.contains(modelType.type())) { + return new IntrospectionModelBaseType(modelType.type()); + } + return new IntrospectionModelComplex(modelType.type()); } + 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 createModelPlop(final MapKey modelType) throws ExmlBuilderException { + if (StringSerializer.contains(modelType.type())) { + return new IntrospectionModelBaseType(modelType.type()); + } + return new IntrospectionModelComplex(modelType.type()); + } } diff --git a/src/org/atriasoft/exml/builder/IntrospectionModelList.java b/src/org/atriasoft/exml/builder/IntrospectionModelList.java new file mode 100644 index 0000000..6ca9c5b --- /dev/null +++ b/src/org/atriasoft/exml/builder/IntrospectionModelList.java @@ -0,0 +1,51 @@ +package org.atriasoft.exml.builder; + +import java.util.ArrayList; +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 + Object createObject(final Map properties, final Map> nodes) throws ExmlBuilderException { + return null; + } + + @Override + protected List getNodeAvaillable() { + return null; + } + + @Override + public Object getValueFromText(final String text) throws ExmlBuilderException { + return new ArrayList(); + } + + @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; + } + @Override + public String[] toStringList(final Object data) { + return null; + } + +} diff --git a/src/org/atriasoft/exml/builder/IntrospectionObject.java b/src/org/atriasoft/exml/builder/IntrospectionObject.java index cb50b87..6d0474a 100644 --- a/src/org/atriasoft/exml/builder/IntrospectionObject.java +++ b/src/org/atriasoft/exml/builder/IntrospectionObject.java @@ -11,6 +11,7 @@ import org.atriasoft.exml.internal.Log; public class IntrospectionObject { private final IntrospectionModel modelInterface; private Object data = null; + @Deprecated private final String listNameModel; private final Map properties = new HashMap<>(); private final Map> nodes = new HashMap<>(); @@ -24,6 +25,7 @@ public class IntrospectionObject { this.listNameModel = null; } + @Deprecated public IntrospectionObject(final IntrospectionModel dataInterface, final String listNameModel) { this.modelInterface = dataInterface; this.listNameModel = listNameModel; @@ -33,7 +35,8 @@ public class IntrospectionObject { this.modelInterface = dataInterface; this.listNameModel = null; } - + + @Deprecated public String getListNameModel() { return this.listNameModel; } @@ -42,7 +45,7 @@ public class IntrospectionObject { return this.data; } - public IntrospectionModel getDataInterface() { + public IntrospectionModel getModelIntrospection() { return this.modelInterface; } diff --git a/src/org/atriasoft/exml/builder/MapKey.java b/src/org/atriasoft/exml/builder/MapKey.java new file mode 100644 index 0000000..4e0f6b4 --- /dev/null +++ b/src/org/atriasoft/exml/builder/MapKey.java @@ -0,0 +1,14 @@ +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); + } +} \ No newline at end of file diff --git a/src/org/atriasoft/exml/builder/ModelType.java b/src/org/atriasoft/exml/builder/ModelType.java new file mode 100644 index 0000000..360df8d --- /dev/null +++ b/src/org/atriasoft/exml/builder/ModelType.java @@ -0,0 +1,7 @@ +package org.atriasoft.exml.builder; + +public enum ModelType { + NORMAL, + ARRAY, + LIST +} \ No newline at end of file diff --git a/src/org/atriasoft/exml/generator/GeneratorIntrospection.java b/src/org/atriasoft/exml/generator/GeneratorIntrospection.java index 4559334..2d8a3e8 100644 --- a/src/org/atriasoft/exml/generator/GeneratorIntrospection.java +++ b/src/org/atriasoft/exml/generator/GeneratorIntrospection.java @@ -7,30 +7,41 @@ import java.util.Map; 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.internal.Log; import org.atriasoft.exml.parser.Tools; public class GeneratorIntrospection implements Generator { // Keep in cach all the object alredy parsed ==> optimize CPU - final Map, IntrospectionModel> elements = new HashMap<>(); + final Map elements = new HashMap<>(); // The root class (need to keep it if we use 2 time the builder, the root class is no more accessible). final Class rootClassType; final String rootNodeName; - public GeneratorIntrospection(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.rootClassType = classType; - this.elements.put(classType, IntrospectionModelFactory.createModel(classType)); + MapKey key = new MapKey(model, classType); + // TODO pb if it is a List or an Array ... + this.elements.put(key, IntrospectionModelFactory.createModelPlop(key)); } - IntrospectionModel findOrCreate(final Class classType) throws ExmlBuilderException { - IntrospectionModel out = this.elements.get(classType); + 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; } - out = IntrospectionModelFactory.createModel(classType); - this.elements.put(classType, out); + if (model == ModelType.ARRAY) { + out = IntrospectionModelFactory.createModelArray(key.nodeName(), key); + } else if (model == ModelType.LIST) { + out = IntrospectionModelFactory.createModelList(key.nodeName(), key); + } else { + out = IntrospectionModelFactory.createModelPlop(key); + } + this.elements.put(key, out); return out; } @@ -60,33 +71,32 @@ public class GeneratorIntrospection implements Generator { if (!elem.canGetValue()) { continue; } - String name = elem.getNames()[0]; - - Object dataObj =elem.getValue(data); + Object dataObj = elem.getValue(data); if (dataObj == null) { continue; } - Class type = elem.getType(); - Class subType = elem.getSubType(); - - generateNode(dataObj, name, tmpp, indent); - /* - if (List.class.isAssignableFrom(type)) { - // special case for List ... - type = elem.getSubType(); - generateNodeList(dataObj, name, tmpp, indent); + String name = elem.getNames()[0]; + Class type = elem.getType(); + IntrospectionModel introspectionSub = null; + if (type.isArray()) { + Class typeClass = elem.getSubType(); + 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 { - generateNode(dataObj, name, tmpp, indent); + introspectionSub = findOrCreate(ModelType.NORMAL, null, data.getClass()); } - */ + generateNode(dataObj, introspectionSub, name, tmpp, indent); } } - public void generateNode(final Object data, final String nodeName, final StringBuilder tmpp, final int indent) throws ExmlBuilderException { - IntrospectionModel introspection = findOrCreate(data.getClass()); - if (introspection.isEndPoint()) { - if (introspection.isList()) { - String[] listDatas = introspection.toStringList(data); + public void generateNode(final Object data, final IntrospectionModel model, final String nodeName, final StringBuilder tmpp, final int indent) throws ExmlBuilderException { + if (model.isEndPoint()) { + if (model.isList()) { + String[] listDatas = model.toStringList(data); for (int iii=0; iii"); - tmpp.append(introspection.toString(data)); + tmpp.append(model.toString(data)); tmpp.append(""); } - } else if (introspection.isList()) { + } else if (model.isArray()) { + List baseName = model.getNodes(); + if (baseName == null || baseName.size() == 0) { + // mode render : aaabbb + } else { + // mode render : aaabbb + + } + Log.error("lkjlk"); + } else if (model.isList()) { + List baseName = model.getNodes(); + if (baseName == null || baseName.size() == 0) { + // mode render : aaabbb + } else { + // mode render : aaabbb + + } Log.error("lkjlk"); } else { Tools.addIndent(tmpp, indent); tmpp.append("<"); tmpp.append(nodeName); - generateProperties(data, introspection, tmpp); - if (introspection.getNodes().size() != 0) { + generateProperties(data, model, tmpp); + if (model.getNodes().size() != 0) { tmpp.append(">"); - generateSubNodes(data, introspection, tmpp, indent + 1); + generateSubNodes(data, model, tmpp, indent + 1); Tools.addIndent(tmpp, indent); tmpp.append("