239 lines
7.7 KiB
Java
239 lines
7.7 KiB
Java
package org.gcube.informationsystem.resourceregistry.queries.json.base;
|
|
|
|
import java.util.HashSet;
|
|
import java.util.Iterator;
|
|
import java.util.Set;
|
|
|
|
import org.gcube.com.fasterxml.jackson.databind.JsonNode;
|
|
import org.gcube.com.fasterxml.jackson.databind.ObjectMapper;
|
|
import org.gcube.com.fasterxml.jackson.databind.node.ArrayNode;
|
|
import org.gcube.com.fasterxml.jackson.databind.node.ObjectNode;
|
|
import org.gcube.informationsystem.base.reference.AccessType;
|
|
import org.gcube.informationsystem.base.reference.Direction;
|
|
import org.gcube.informationsystem.base.reference.Element;
|
|
import org.gcube.informationsystem.model.reference.ModelElement;
|
|
import org.gcube.informationsystem.resourceregistry.api.exceptions.ResourceRegistryException;
|
|
import org.gcube.informationsystem.resourceregistry.api.exceptions.queries.InvalidQueryException;
|
|
import org.gcube.informationsystem.resourceregistry.api.exceptions.types.SchemaException;
|
|
import org.gcube.informationsystem.resourceregistry.api.exceptions.types.SchemaNotFoundException;
|
|
import org.gcube.informationsystem.resourceregistry.queries.operators.ConditionalOperator;
|
|
import org.gcube.informationsystem.resourceregistry.queries.operators.LogicalOperator;
|
|
import org.gcube.informationsystem.resourceregistry.types.TypesCache;
|
|
import org.gcube.informationsystem.utils.TypeUtility;
|
|
import org.slf4j.Logger;
|
|
import org.slf4j.LoggerFactory;
|
|
|
|
public abstract class JsonQueryERElement {
|
|
|
|
protected Logger logger = LoggerFactory.getLogger(this.getClass());
|
|
|
|
public static void validateType(String type, AccessType requiredAccessType) throws SchemaException, ResourceRegistryException {
|
|
AccessType accessType = TypesCache.getInstance().getCachedType(type).getAccessType();
|
|
if(!accessType.equals(requiredAccessType)) {
|
|
throw new InvalidQueryException(type + "is not an expected " + requiredAccessType.getName() + " type");
|
|
}
|
|
}
|
|
|
|
protected final ObjectMapper objectMapper;
|
|
protected final String type;
|
|
protected final JsonNode jsonNode;
|
|
protected final AccessType accessType;
|
|
|
|
protected final Set<String> fieldNamesToRemove;
|
|
|
|
protected Direction direction;
|
|
protected boolean entryPoint;
|
|
|
|
/**
|
|
* it indicates the number of properties in this.jsonNode
|
|
* This number is manipulated while analyzing the jsonNode
|
|
* to properly create the query.
|
|
*/
|
|
protected int size;
|
|
|
|
protected boolean traverseBack;
|
|
|
|
public JsonQueryERElement(JsonNode jsonQuery, AccessType accessType) throws SchemaException, ResourceRegistryException {
|
|
this.objectMapper = new ObjectMapper();
|
|
this.type = TypeUtility.getTypeName(jsonQuery);
|
|
this.jsonNode = jsonQuery;
|
|
this.size = jsonNode.size();
|
|
this.accessType = accessType;
|
|
this.entryPoint = false;
|
|
this.traverseBack = true;
|
|
|
|
this.fieldNamesToRemove = new HashSet<>();
|
|
this.fieldNamesToRemove.add(Element.TYPE_PROPERTY);
|
|
this.fieldNamesToRemove.add(ModelElement.SUPERTYPES_PROPERTY);
|
|
this.fieldNamesToRemove.add(ModelElement.EXPECTED_TYPE_PROPERTY);
|
|
|
|
validateType(this.type, this.accessType);
|
|
}
|
|
|
|
public String getType() {
|
|
return type;
|
|
}
|
|
|
|
public Direction getDirection() {
|
|
return direction;
|
|
}
|
|
|
|
public void setDirection(Direction direction) {
|
|
this.direction = direction;
|
|
}
|
|
|
|
public boolean isEntryPoint() {
|
|
return entryPoint;
|
|
}
|
|
|
|
public void setEntryPoint(boolean entryPoint) {
|
|
this.entryPoint = entryPoint;
|
|
this.traverseBack = !entryPoint;
|
|
}
|
|
|
|
public boolean isTraverseBack() {
|
|
return traverseBack;
|
|
}
|
|
|
|
public void setTraverseBack(boolean traverseBack) {
|
|
this.traverseBack = traverseBack;
|
|
}
|
|
|
|
public abstract StringBuffer analize(StringBuffer stringBuffer) throws SchemaNotFoundException, InvalidQueryException, SchemaException, ResourceRegistryException;
|
|
|
|
|
|
protected StringBuffer addConstraints(JsonNode jsonNode, LogicalOperator queryLogicalOperator, String fieldNamePrefix) throws InvalidQueryException {
|
|
StringBuffer stringBuffer = new StringBuffer();
|
|
|
|
if(queryLogicalOperator==null) {
|
|
queryLogicalOperator = LogicalOperator.AND;
|
|
}
|
|
|
|
JsonNode copiedJsonNode = jsonNode.deepCopy();
|
|
|
|
if(jsonNode.isObject()) {
|
|
ObjectNode objectNode = (ObjectNode) copiedJsonNode;
|
|
objectNode.remove(fieldNamesToRemove);
|
|
|
|
Iterator<String> iterator = objectNode.fieldNames();
|
|
|
|
boolean first = true;
|
|
|
|
while(iterator.hasNext()) {
|
|
String fieldName = iterator.next();
|
|
if(first) {
|
|
first = false;
|
|
}else {
|
|
stringBuffer.append(queryLogicalOperator.getLogicalOperator());
|
|
}
|
|
JsonNode node = objectNode.get(fieldName);
|
|
stringBuffer.append(evaluateNode(node, fieldName, fieldNamePrefix));
|
|
}
|
|
}
|
|
|
|
if(jsonNode.isArray()) {
|
|
ArrayNode arrayNode = (ArrayNode) copiedJsonNode;
|
|
Iterator<JsonNode> iterator = arrayNode.iterator();
|
|
boolean first = true;
|
|
while(iterator.hasNext()) {
|
|
if(first) {
|
|
first = false;
|
|
}else {
|
|
stringBuffer.append(queryLogicalOperator.getLogicalOperator());
|
|
}
|
|
JsonNode node = iterator.next();
|
|
stringBuffer.append(evaluateNode(node, null, fieldNamePrefix));
|
|
}
|
|
}
|
|
|
|
return stringBuffer;
|
|
}
|
|
|
|
protected StringBuffer evaluateNode(JsonNode jsonNode, String fieldName, String fieldNamePrefix) throws InvalidQueryException {
|
|
StringBuffer stringBuffer = new StringBuffer();
|
|
|
|
if(LogicalOperator.getOperators().contains(fieldName)) {
|
|
LogicalOperator queryLogicalOperator = LogicalOperator.getQueryLogicalOperator(fieldName);
|
|
stringBuffer.append("(");
|
|
stringBuffer.append(addConstraints(jsonNode, queryLogicalOperator, fieldNamePrefix));
|
|
stringBuffer.append(")");
|
|
return stringBuffer;
|
|
}
|
|
|
|
if(ConditionalOperator.getOperators().contains(fieldName)) {
|
|
ConditionalOperator queryConditionalOperator = ConditionalOperator.getQueryComparisonOperator(fieldName);
|
|
|
|
if(queryConditionalOperator == ConditionalOperator.IN) {
|
|
throw new UnsupportedOperationException();
|
|
}
|
|
|
|
StringBuffer key = getKey(null, fieldNamePrefix);
|
|
StringBuffer value = getValue(jsonNode);
|
|
stringBuffer.append(addCondition(queryConditionalOperator, key, value));
|
|
return stringBuffer;
|
|
}
|
|
|
|
if(jsonNode.isObject()) {
|
|
StringBuffer newPrefix = new StringBuffer();
|
|
if(fieldNamePrefix!=null && fieldNamePrefix.compareTo("")!=0) {
|
|
newPrefix.append(fieldNamePrefix);
|
|
if(fieldName!=null && fieldName.compareTo("")!=0) {
|
|
newPrefix.append(".");
|
|
}
|
|
}
|
|
|
|
if(fieldName!=null && fieldName.compareTo("")!=0) {
|
|
newPrefix.append(fieldName);
|
|
}
|
|
|
|
stringBuffer.append(addConstraints(jsonNode, null, newPrefix.length()>0 ? newPrefix.toString() : null));
|
|
return stringBuffer;
|
|
}
|
|
|
|
if(jsonNode.isTextual() || jsonNode.isNumber()) {
|
|
StringBuffer key = getKey(fieldName, fieldNamePrefix);
|
|
StringBuffer value = getValue(jsonNode);
|
|
stringBuffer.append(addCondition(ConditionalOperator.EQ, key, value));
|
|
}
|
|
|
|
return stringBuffer;
|
|
}
|
|
|
|
protected StringBuffer addCondition(ConditionalOperator queryConditionalOperator, StringBuffer key, StringBuffer value) {
|
|
StringBuffer stringBuffer = new StringBuffer();
|
|
stringBuffer.append(key);
|
|
stringBuffer.append(queryConditionalOperator.getConditionalOperator());
|
|
stringBuffer.append(value);
|
|
return stringBuffer;
|
|
}
|
|
|
|
|
|
protected StringBuffer getKey(String fieldName, String fieldNamePrefix) {
|
|
StringBuffer stringBuffer = new StringBuffer();
|
|
if(fieldNamePrefix!=null) {
|
|
stringBuffer.append(fieldNamePrefix);
|
|
if(fieldName!=null && fieldName.compareTo("")!=0) {
|
|
stringBuffer.append(".");
|
|
}
|
|
}
|
|
if(fieldName!=null) {
|
|
stringBuffer.append(fieldName);
|
|
}
|
|
return stringBuffer;
|
|
}
|
|
|
|
protected StringBuffer getValue(JsonNode jsonNode) {
|
|
StringBuffer stringBuffer = new StringBuffer();
|
|
|
|
String value = jsonNode.asText();
|
|
if(jsonNode.isNumber()) {
|
|
stringBuffer.append(value);
|
|
} else {
|
|
stringBuffer.append("\"");
|
|
stringBuffer.append(value);
|
|
stringBuffer.append("\"");
|
|
}
|
|
return stringBuffer;
|
|
}
|
|
}
|