package com.bagri.core.server.api.df.json;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.StringReader;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import javax.json.Json;
import javax.json.JsonArray;
import javax.json.JsonObject;
import javax.json.JsonReader;
import javax.json.JsonReaderFactory;
import javax.xml.xquery.XQItemType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.bagri.core.api.BagriException;
import com.bagri.core.model.NodeKind;
import com.bagri.core.model.Occurrence;
import com.bagri.core.model.Path;
import com.bagri.core.server.api.ContentModeler;
import com.bagri.core.server.api.ModelManagement;
public class JsonpModeler implements ContentModeler {
private static final transient Logger logger = LoggerFactory.getLogger(JsonpModeler.class);
private JsonReaderFactory factory = Json.createReaderFactory(null);
protected ModelManagement modelMgr;
/**
*
* @param modelMgr the model management component
*/
JsonpModeler(ModelManagement modelMgr) {
//super(model);
this.modelMgr = modelMgr;
}
@Override
public void init(Properties properties) {
// process/convert any specific properties here
Map<String, Object> params = new HashMap<>();
for (Map.Entry prop: properties.entrySet()) {
//String name = (String) prop.getKey();
params.put((String) prop.getKey(), prop.getValue());
}
factory = Json.createReaderFactory(params);
}
@Override
public void registerModel(String model) throws BagriException {
JsonReader reader = factory.createReader(new StringReader(model));
JsonObject schema = reader.readObject();
processModel(schema);
reader.close();
}
@Override
public void registerModelUri(String modelUri) throws BagriException {
try {
JsonReader reader = factory.createReader(new FileInputStream(modelUri));
JsonObject schema = reader.readObject();
processModel(schema);
reader.close();
} catch (IOException ex) {
throw new BagriException(ex, BagriException.ecInOut);
}
}
private void processModel(JsonObject model) throws BagriException {
String root = "/";
Path xp = modelMgr.translatePath(root, "/", NodeKind.document, 0, XQItemType.XQBASETYPE_UNTYPED, Occurrence.onlyOne);
processObject(xp, "", model);
}
private void processObject(Path parent, String path, JsonObject object) throws BagriException {
logger.debug("processObject; got object: {}", object);
JsonArray mandatory = object.getJsonArray("required");
JsonObject fields = object.getJsonObject("properties");
//NodeKind kind = parent.getNodeKind() == NodeKind.array ? NodeKind.text : NodeKind.attribute;
for (String field: fields.keySet()) {
JsonObject value = fields.getJsonObject(field);
Occurrence occ = mandatory.contains(field) ? Occurrence.onlyOne : Occurrence.zeroOrOne;
processField(parent, path, field, value, occ);
// it can be an array also!
//String type = value.getString("type", null);
//if (type != null) {
// String next = path + "/" + field;
// switch (type) {
// case "array":
// Path array = modelMgr.translatePath(parent.getRoot(), next, NodeKind.array, parent.getPathId(), XQItemType.XQBASETYPE_ANYTYPE, occ);
// JsonObject items = value.getJsonObject("items");
// process array items..
// break;
// case "boolean":
// modelMgr.translatePath(parent.getRoot(), next, NodeKind.attribute, parent.getPathId(), XQItemType.XQBASETYPE_BOOLEAN, occ);
// break;
// case "integer":
// modelMgr.translatePath(parent.getRoot(), next, NodeKind.attribute, parent.getPathId(), XQItemType.XQBASETYPE_LONG, occ);
// break;
// case "number":
// modelMgr.translatePath(parent.getRoot(), next, NodeKind.attribute, parent.getPathId(), XQItemType.XQBASETYPE_DECIMAL, occ);
// break;
// case "object":
// Path element = modelMgr.translatePath(parent.getRoot(), next, NodeKind.element, parent.getPathId(), XQItemType.XQBASETYPE_ANYTYPE, occ);
// processObject(element, next, value);
// break;
// case "string":
// modelMgr.translatePath(parent.getRoot(), next, NodeKind.attribute, parent.getPathId(), XQItemType.XQBASETYPE_STRING, occ);
// break;
// }
//}
}
}
private void processField(Path parent, String path, String field, JsonObject object, Occurrence occ) throws BagriException {
// it can be an array also!
String type = object.getString("type", null);
if (type != null) {
if (!path.endsWith("/")) {
path += "/";
}
String next = path + field;
switch (type) {
case "array":
Path array = modelMgr.translatePath(parent.getRoot(), next, NodeKind.array, parent.getPathId(), XQItemType.XQBASETYPE_ANYTYPE, occ);
JsonObject items = object.getJsonObject("items");
processField(array, path, field + "/", items, occ);
break;
case "boolean":
modelMgr.translatePath(parent.getRoot(), next, NodeKind.attribute, parent.getPathId(), XQItemType.XQBASETYPE_BOOLEAN, occ);
break;
case "integer":
modelMgr.translatePath(parent.getRoot(), next, NodeKind.attribute, parent.getPathId(), XQItemType.XQBASETYPE_LONG, occ);
break;
case "number":
modelMgr.translatePath(parent.getRoot(), next, NodeKind.attribute, parent.getPathId(), XQItemType.XQBASETYPE_DECIMAL, occ);
break;
case "object":
Path element = modelMgr.translatePath(parent.getRoot(), next, NodeKind.element, parent.getPathId(), XQItemType.XQBASETYPE_ANYTYPE, occ);
processObject(element, next, object);
break;
case "string":
modelMgr.translatePath(parent.getRoot(), next, NodeKind.attribute, parent.getPathId(), XQItemType.XQBASETYPE_STRING, occ);
break;
}
}
}
}