+ * @param Object type to parse
+ * @param data Data String to Parse
+ * @param classType Object Class to introspect data (POJO)
+ * @return The Object parsed or null
+ */
+ @SuppressWarnings("unchecked")
+ public T parse(final String data, final Class classType) throws EjsonException, EjsonNodeDoesNotExist, AknotException {
+ BuilderGeneric builder;
+ try {
+ builder = new BuilderIntrospection(ModelType.NORMAL, classType);
+ final ParseJson parser = new ParseJson(builder);
+ final ParsingProperty property = new org.atriasoft.ejson.parser.ParsingProperty();
+ property.setDisplayError(true);
+
+ final IntrospectionObject introspectionObject = (IntrospectionObject) parser.parse(data, property);
+ introspectionObject.generateTheObject();
+ final Object listRet = introspectionObject.getData();
+ if (listRet != null && !listRet.getClass().isArray() && listRet.getClass().componentType() == classType) {
+ return (T) listRet;
+ } else if (listRet != null && listRet.getClass().isArray() && listRet.getClass().componentType() == classType) {
+ final T[] tmp = (T[]) listRet;
+ if (tmp.length >= 1) {
+ return tmp[0];
+ }
+ }
+ return null;
+ } catch (final EjsonException ex) {
+ ex.printStackTrace();
+ throw ex;
+ }
+ }
+
+ public T read(final Class classType, final Path path) throws EjsonException, AknotException, IOException {
+ String content = null;
+ try {
+ content = readFile(path, StandardCharsets.UTF_8);
+ } catch (final IOException e) {
+ e.printStackTrace();
+ }
+ return parse(content, classType);
+ }
+
+ public T read(final Class classType, final Uri uri) throws EjsonException, AknotException, IOException {
+
+ final byte[] elemData = Uri.getAllData(uri);
+ if (elemData == null) {
+ Log.error("Can not read the Stream : " + uri);
+ return null;
+ }
+ final String content = new String(elemData);
+ return parse(content, classType);
+ }
+
+ public void store(final Object root, final Path path) throws EjsonException, AknotException, IOException {
+ final StringBuilder builder = new StringBuilder();
+ generate(root, builder);
+ Files.writeString(path, builder.toString());
+ }
+
+ public void store(final Object root, final Uri uri) throws EjsonException, AknotException, IOException {
+ final StringBuilder builder = new StringBuilder();
+ generate(root, builder);
+ Uri.writeAll(uri, builder.toString());
+ }
+
+}
diff --git a/src/org/atriasoft/ejson/annotation/EjsonAnnotation.java b/src/org/atriasoft/ejson/annotation/EjsonAnnotation.java
deleted file mode 100644
index 42e2377..0000000
--- a/src/org/atriasoft/ejson/annotation/EjsonAnnotation.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package org.atriasoft.ejson.annotation;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Meta-annotation (annotations used on other annotations)
- * used for marking all annotations that are
- * part of Ejson package. Can be used for recognizing all
- * Ejson annotations generically, and in future also for
- * passing other generic annotation configuration.
- */
-@Target(ElementType.ANNOTATION_TYPE)
-@Retention(RetentionPolicy.RUNTIME)
-public @interface EjsonAnnotation {
- // for now, a pure tag annotation, no parameters
-}
\ No newline at end of file
diff --git a/src/org/atriasoft/ejson/annotation/JsonDefaultManaged.java b/src/org/atriasoft/ejson/annotation/JsonDefaultManaged.java
deleted file mode 100644
index 14587c1..0000000
--- a/src/org/atriasoft/ejson/annotation/JsonDefaultManaged.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package org.atriasoft.ejson.annotation;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Marker annotation that set the element are not managed by default. Need to add @JsonManaged to be enable.
- *
- */
-@Target(ElementType.TYPE)
-@Retention(RetentionPolicy.RUNTIME)
-@EjsonAnnotation
-public @interface JsonDefaultManaged {
- /**
- * Set this at false to remove all the field and the function from Json introspection
- * @return true if the element are by default managed.
- */
- boolean value() default true;
-}
\ No newline at end of file
diff --git a/src/org/atriasoft/ejson/annotation/JsonDefaultOptional.java b/src/org/atriasoft/ejson/annotation/JsonDefaultOptional.java
deleted file mode 100644
index e7e68d2..0000000
--- a/src/org/atriasoft/ejson/annotation/JsonDefaultOptional.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package org.atriasoft.ejson.annotation;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Marker annotation that set the element not found are ignored.
- *
- */
-@Target(ElementType.TYPE)
-@Retention(RetentionPolicy.RUNTIME)
-@EjsonAnnotation
-public @interface JsonDefaultOptional {
- /**
- * Set this at true to set all the element optional.
- * @return true if the element are by default optional.
- */
- boolean value() default false;
-}
\ No newline at end of file
diff --git a/src/org/atriasoft/ejson/annotation/JsonManaged.java b/src/org/atriasoft/ejson/annotation/JsonManaged.java
deleted file mode 100644
index 25c9e81..0000000
--- a/src/org/atriasoft/ejson/annotation/JsonManaged.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package org.atriasoft.ejson.annotation;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Marker annotation that force the json Parser to manage this element (used when the class is mark as @JsondefaultNotManaged).
- *
- */
-@Target({ ElementType.FIELD, ElementType.METHOD })
-@Retention(RetentionPolicy.RUNTIME)
-@EjsonAnnotation
-public @interface JsonManaged {
- /**
- * Set this at false to remove this function or this field form the XML parsing system
- * @return true if the element is managed.
- */
- boolean value() default true;
-}
\ No newline at end of file
diff --git a/src/org/atriasoft/ejson/annotation/JsonName.java b/src/org/atriasoft/ejson/annotation/JsonName.java
deleted file mode 100644
index 6a85fe5..0000000
--- a/src/org/atriasoft/ejson/annotation/JsonName.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package org.atriasoft.ejson.annotation;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Marker annotation that can be used to define an other name of the attribute or the Element name.
- *
- */
-@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER })
-@Retention(RetentionPolicy.RUNTIME)
-@EjsonAnnotation
-public @interface JsonName {
-
- /**
- * Names of the property of the Element name
- * @note The first name if the default generated in serialization.
- * @return The list the the possible names
- */
- String[] value();
-}
\ No newline at end of file
diff --git a/src/org/atriasoft/ejson/annotation/JsonOptional.java b/src/org/atriasoft/ejson/annotation/JsonOptional.java
deleted file mode 100644
index 9ed6e19..0000000
--- a/src/org/atriasoft/ejson/annotation/JsonOptional.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package org.atriasoft.ejson.annotation;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Marker annotation that to ignore the element if not present in the XML, the default case the parser throw a missing error.
- *
- */
-@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER })
-@Retention(RetentionPolicy.RUNTIME)
-@EjsonAnnotation
-public @interface JsonOptional {
- /**
- * Set if the element is optional or not. If optional, the parser does not throw error if the element is not declared.
- * @return thru if optional
- */
- boolean value() default true;
-}
\ No newline at end of file
diff --git a/src/org/atriasoft/ejson/builder/Builder.java b/src/org/atriasoft/ejson/builder/Builder.java
index 4532c20..55b61d0 100644
--- a/src/org/atriasoft/ejson/builder/Builder.java
+++ b/src/org/atriasoft/ejson/builder/Builder.java
@@ -9,6 +9,13 @@ import org.atriasoft.ejson.exception.EjsonBuilderException;
public interface Builder {
+ /**
+ * End of parsing element
+ * @param parent Element representing the end of declaration
+ * @throws EjsonBuilderException Error with this node or element.
+ */
+ void endParsing(Object parent) throws EjsonBuilderException;
+
/**
* New comment added on this Element (For an Array)
* @param parent Element representing the node of the Declaration is added
diff --git a/src/org/atriasoft/ejson/builder/BuilderGeneric.java b/src/org/atriasoft/ejson/builder/BuilderGeneric.java
index a6e3235..c30f61d 100644
--- a/src/org/atriasoft/ejson/builder/BuilderGeneric.java
+++ b/src/org/atriasoft/ejson/builder/BuilderGeneric.java
@@ -15,9 +15,14 @@ import org.atriasoft.ejson.model.JsonString;
public class BuilderGeneric implements Builder {
+ @Override
+ public void endParsing(final Object parent) throws EjsonBuilderException {
+ // nothing to do ... this is for revert build.
+ }
+
@Override
public Object newArray(final Object parent) throws EjsonBuilderException {
- if (parent instanceof JsonArray elem) {
+ if (parent instanceof final JsonArray elem) {
final JsonArray out = new JsonArray();
elem.add(out);
return out;
@@ -27,7 +32,7 @@ public class BuilderGeneric implements Builder {
@Override
public Object newArray(final Object parent, final String nodeName) throws EjsonBuilderException {
- if (parent instanceof JsonObject elem) {
+ if (parent instanceof final JsonObject elem) {
final JsonArray out = new JsonArray();
elem.put(nodeName, out);
return out;
@@ -37,7 +42,7 @@ public class BuilderGeneric implements Builder {
@Override
public void newBoolean(final Object parent, final boolean value) throws EjsonBuilderException, Exception {
- if (parent instanceof JsonArray elem) {
+ if (parent instanceof final JsonArray elem) {
final JsonBoolean out = new JsonBoolean(value);
elem.add(out);
return;
@@ -48,7 +53,7 @@ public class BuilderGeneric implements Builder {
@Override
public void newBoolean(final Object parent, final String nodeName, final boolean value) throws EjsonBuilderException, Exception {
- if (parent instanceof JsonObject elem) {
+ if (parent instanceof final JsonObject elem) {
final JsonBoolean out = new JsonBoolean(value);
elem.put(nodeName, out);
return;
@@ -58,7 +63,7 @@ public class BuilderGeneric implements Builder {
@Override
public void newNull(final Object parent) throws EjsonBuilderException, Exception {
- if (parent instanceof JsonArray elem) {
+ if (parent instanceof final JsonArray elem) {
final JsonNull out = new JsonNull();
elem.add(out);
return;
@@ -69,7 +74,7 @@ public class BuilderGeneric implements Builder {
@Override
public void newNull(final Object parent, final String nodeName) throws EjsonBuilderException, Exception {
- if (parent instanceof JsonObject elem) {
+ if (parent instanceof final JsonObject elem) {
final JsonNull out = new JsonNull();
elem.put(nodeName, out);
return;
@@ -79,7 +84,7 @@ public class BuilderGeneric implements Builder {
@Override
public void newNumber(final Object parent, final double value) throws EjsonBuilderException, Exception {
- if (parent instanceof JsonArray elem) {
+ if (parent instanceof final JsonArray elem) {
final JsonNumber out = new JsonNumber(value);
elem.add(out);
return;
@@ -90,7 +95,7 @@ public class BuilderGeneric implements Builder {
@Override
public void newNumber(final Object parent, final long value) throws EjsonBuilderException, Exception {
- if (parent instanceof JsonArray elem) {
+ if (parent instanceof final JsonArray elem) {
final JsonNumber out = new JsonNumber(value);
elem.add(out);
return;
@@ -101,7 +106,7 @@ public class BuilderGeneric implements Builder {
@Override
public void newNumber(final Object parent, final String nodeName, final double value) throws EjsonBuilderException, Exception {
- if (parent instanceof JsonObject elem) {
+ if (parent instanceof final JsonObject elem) {
final JsonNumber out = new JsonNumber(value);
elem.put(nodeName, out);
return;
@@ -111,7 +116,7 @@ public class BuilderGeneric implements Builder {
@Override
public void newNumber(final Object parent, final String nodeName, final long value) throws EjsonBuilderException, Exception {
- if (parent instanceof JsonObject elem) {
+ if (parent instanceof final JsonObject elem) {
final JsonNumber out = new JsonNumber(value);
elem.put(nodeName, out);
return;
@@ -121,7 +126,7 @@ public class BuilderGeneric implements Builder {
@Override
public Object newObject(final Object parent) throws EjsonBuilderException, Exception {
- if (parent instanceof JsonArray elem) {
+ if (parent instanceof final JsonArray elem) {
final JsonObject out = new JsonObject();
elem.add(out);
return out;
@@ -131,7 +136,7 @@ public class BuilderGeneric implements Builder {
@Override
public Object newObject(final Object parent, final String nodeName) throws EjsonBuilderException, Exception {
- if (parent instanceof JsonObject elem) {
+ if (parent instanceof final JsonObject elem) {
final JsonObject out = new JsonObject();
elem.put(nodeName, out);
return out;
@@ -146,7 +151,7 @@ public class BuilderGeneric implements Builder {
@Override
public void newString(final Object parent, final String value) throws EjsonBuilderException, Exception {
- if (parent instanceof JsonArray elem) {
+ if (parent instanceof final JsonArray elem) {
final JsonString out = new JsonString(value);
elem.add(out);
return;
@@ -157,7 +162,7 @@ public class BuilderGeneric implements Builder {
@Override
public void newString(final Object parent, final String nodeName, final String value) throws EjsonBuilderException, Exception {
- if (parent instanceof JsonObject elem) {
+ if (parent instanceof final JsonObject elem) {
final JsonString out = new JsonString(value);
elem.put(nodeName, out);
return;
diff --git a/src/org/atriasoft/ejson/builder/BuilderIntrospection.java b/src/org/atriasoft/ejson/builder/BuilderIntrospection.java
new file mode 100644
index 0000000..19b9415
--- /dev/null
+++ b/src/org/atriasoft/ejson/builder/BuilderIntrospection.java
@@ -0,0 +1,189 @@
+/** @file
+ * @author Edouard DUPIN
+ * @copyright 2021, Edouard DUPIN, all right reserved
+ * @license MPL v2.0 (see license file)
+ */
+package org.atriasoft.ejson.builder;
+
+import org.atriasoft.aknot.exception.AknotException;
+import org.atriasoft.aknot.model.IntrospectionModel;
+import org.atriasoft.aknot.model.ModelType;
+import org.atriasoft.aknot.pojo.CacheIntrospectionModel;
+import org.atriasoft.ejson.exception.EjsonBuilderException;
+import org.atriasoft.ejson.exception.EjsonException;
+import org.atriasoft.ejson.model.JsonArray;
+import org.atriasoft.ejson.model.JsonBoolean;
+import org.atriasoft.ejson.model.JsonNull;
+import org.atriasoft.ejson.model.JsonNumber;
+import org.atriasoft.ejson.model.JsonObject;
+import org.atriasoft.ejson.model.JsonString;
+
+public class BuilderIntrospection implements Builder {
+ // Keep in cach all the object alredy parsed ==> optimize CPU
+ CacheIntrospectionModel cacheModel = new CacheIntrospectionModel();
+ // 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 ModelType model, final Class> classType) throws EjsonException, AknotException {
+ this.rootClassType = classType;
+ final IntrospectionModel typeModel = this.cacheModel.findOrCreate(model, null, classType);
+ this.rootNodeName = typeModel.getNames()[0];
+ }
+
+ @Override
+ public void endParsing(final Object parent) throws EjsonBuilderException {
+ // nothing to do ... this is for revert build.
+ }
+
+ @Override
+ public Object newArray(final Object parent) throws EjsonBuilderException {
+ if (parent instanceof final JsonArray elem) {
+ final JsonArray out = new JsonArray();
+ elem.add(out);
+ return out;
+ }
+ throw new EjsonBuilderException("can not add Comment on something else than array");
+ }
+
+ @Override
+ public Object newArray(final Object parent, final String nodeName) throws EjsonBuilderException {
+ if (parent instanceof final JsonObject elem) {
+ final JsonArray out = new JsonArray();
+ elem.put(nodeName, out);
+ return out;
+ }
+ throw new EjsonBuilderException("can not add Comment on something else than Object");
+ }
+
+ @Override
+ public void newBoolean(final Object parent, final boolean value) throws EjsonBuilderException, Exception {
+ if (parent instanceof final JsonArray elem) {
+ final JsonBoolean out = new JsonBoolean(value);
+ elem.add(out);
+ return;
+ }
+ throw new EjsonBuilderException("can not add Comment on something else than array");
+
+ }
+
+ @Override
+ public void newBoolean(final Object parent, final String nodeName, final boolean value) throws EjsonBuilderException, Exception {
+ if (parent instanceof final JsonObject elem) {
+ final JsonBoolean out = new JsonBoolean(value);
+ elem.put(nodeName, out);
+ return;
+ }
+ throw new EjsonBuilderException("can not add Comment on something else than Object");
+ }
+
+ @Override
+ public void newNull(final Object parent) throws EjsonBuilderException, Exception {
+ if (parent instanceof final JsonArray elem) {
+ final JsonNull out = new JsonNull();
+ elem.add(out);
+ return;
+ }
+ throw new EjsonBuilderException("can not add Comment on something else than array");
+
+ }
+
+ @Override
+ public void newNull(final Object parent, final String nodeName) throws EjsonBuilderException, Exception {
+ if (parent instanceof final JsonObject elem) {
+ final JsonNull out = new JsonNull();
+ elem.put(nodeName, out);
+ return;
+ }
+ throw new EjsonBuilderException("can not add Comment on something else than Object");
+ }
+
+ @Override
+ public void newNumber(final Object parent, final double value) throws EjsonBuilderException, Exception {
+ if (parent instanceof final JsonArray elem) {
+ final JsonNumber out = new JsonNumber(value);
+ elem.add(out);
+ return;
+ }
+ throw new EjsonBuilderException("can not add Comment on something else than array");
+
+ }
+
+ @Override
+ public void newNumber(final Object parent, final long value) throws EjsonBuilderException, Exception {
+ if (parent instanceof final JsonArray elem) {
+ final JsonNumber out = new JsonNumber(value);
+ elem.add(out);
+ return;
+ }
+ throw new EjsonBuilderException("can not add Comment on something else than array");
+
+ }
+
+ @Override
+ public void newNumber(final Object parent, final String nodeName, final double value) throws EjsonBuilderException, Exception {
+ if (parent instanceof final JsonObject elem) {
+ final JsonNumber out = new JsonNumber(value);
+ elem.put(nodeName, out);
+ return;
+ }
+ throw new EjsonBuilderException("can not add Comment on something else than Object");
+ }
+
+ @Override
+ public void newNumber(final Object parent, final String nodeName, final long value) throws EjsonBuilderException, Exception {
+ if (parent instanceof final JsonObject elem) {
+ final JsonNumber out = new JsonNumber(value);
+ elem.put(nodeName, out);
+ return;
+ }
+ throw new EjsonBuilderException("can not add Comment on something else than Object");
+ }
+
+ @Override
+ public Object newObject(final Object parent) throws EjsonBuilderException, Exception {
+ if (parent instanceof final JsonArray elem) {
+ final JsonObject out = new JsonObject();
+ elem.add(out);
+ return out;
+ }
+ throw new EjsonBuilderException("can not add Comment on something else than array");
+ }
+
+ @Override
+ public Object newObject(final Object parent, final String nodeName) throws EjsonBuilderException, Exception {
+ if (parent instanceof final JsonObject elem) {
+ final JsonObject out = new JsonObject();
+ elem.put(nodeName, out);
+ return out;
+ }
+ throw new EjsonBuilderException("can not add Comment on something else than Object");
+ }
+
+ @Override
+ public Object newRoot() throws EjsonBuilderException {
+ return new JsonObject();
+ }
+
+ @Override
+ public void newString(final Object parent, final String value) throws EjsonBuilderException, Exception {
+ if (parent instanceof final JsonArray elem) {
+ final JsonString out = new JsonString(value);
+ elem.add(out);
+ return;
+ }
+ throw new EjsonBuilderException("can not add Comment on something else than array");
+
+ }
+
+ @Override
+ public void newString(final Object parent, final String nodeName, final String value) throws EjsonBuilderException, Exception {
+ if (parent instanceof final JsonObject elem) {
+ final JsonString out = new JsonString(value);
+ elem.put(nodeName, out);
+ return;
+ }
+ throw new EjsonBuilderException("can not add Comment on something else than Object");
+ }
+
+}
diff --git a/src/org/atriasoft/ejson/builder/IntrospectionObject.java b/src/org/atriasoft/ejson/builder/IntrospectionObject.java
new file mode 100644
index 0000000..6da15f2
--- /dev/null
+++ b/src/org/atriasoft/ejson/builder/IntrospectionObject.java
@@ -0,0 +1,168 @@
+package org.atriasoft.ejson.builder;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.atriasoft.aknot.exception.AknotException;
+import org.atriasoft.aknot.model.IntrospectionModel;
+import org.atriasoft.ejson.exception.EjsonException;
+import org.atriasoft.ejson.exception.EjsonNodeDoesNotExist;
+import org.atriasoft.ejson.internal.Log;
+
+public class IntrospectionObject {
+ public static final String PUBLIC_TEXT_NAME = "##<< ** TEXT-ZONE ** >>##";
+ private final IntrospectionModel modelInterface;
+ private Object data = null;
+ private final Map properties = new HashMap<>();
+ private final Map> nodes = new HashMap<>();
+
+ public IntrospectionObject(final IntrospectionModel dataInterface) {
+ this.modelInterface = dataInterface;
+ }
+
+ @SuppressWarnings("unchecked")
+ public void addObject(final String nodeName, final Object value) throws EjsonException {
+ if (value == null) {
+ // specific case when a List is empty but define for a specific list ==> need no action
+ return;
+ }
+ final String beanName = this.modelInterface.getBeanName(nodeName);
+ if (beanName == null) {
+ throw new EjsonNodeDoesNotExist("The node '" + nodeName + "' Does not exist...");
+ }
+ List