Reorganizing code to easily support conditional and logical operators

This commit is contained in:
Luca Frosini 2021-10-19 16:46:00 +02:00
parent e810a6c06d
commit b339c9d49a
10 changed files with 234 additions and 15 deletions

View File

@ -20,6 +20,11 @@ import org.gcube.informationsystem.resourceregistry.contexts.security.SecurityCo
import org.gcube.informationsystem.resourceregistry.contexts.security.SecurityContext.PermissionMode;
import org.gcube.informationsystem.resourceregistry.instances.base.ElementManagement;
import org.gcube.informationsystem.resourceregistry.instances.base.ElementManagementUtility;
import org.gcube.informationsystem.resourceregistry.query.json.base.JsonQueryERElement;
import org.gcube.informationsystem.resourceregistry.query.json.base.entities.JsonQueryFacet;
import org.gcube.informationsystem.resourceregistry.query.json.base.entities.JsonQueryResource;
import org.gcube.informationsystem.resourceregistry.query.json.base.relations.JsonQueryConsistsOf;
import org.gcube.informationsystem.resourceregistry.query.json.base.relations.JsonQueryIsRelatedTo;
import org.gcube.informationsystem.resourceregistry.types.CachedType;
import org.gcube.informationsystem.resourceregistry.types.TypesCache;
import org.gcube.informationsystem.resourceregistry.utils.Utility;

View File

@ -1,8 +1,11 @@
package org.gcube.informationsystem.resourceregistry.query.json;
package org.gcube.informationsystem.resourceregistry.query.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.informationsystem.base.reference.AccessType;
import org.gcube.informationsystem.base.reference.Direction;
import org.gcube.informationsystem.base.reference.Element;
@ -26,18 +29,27 @@ public abstract class JsonQueryERElement {
}
}
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;
public JsonQueryERElement(JsonNode jsonQuery, AccessType accessType) throws SchemaException, ResourceRegistryException {
this.objectMapper = new ObjectMapper();
this.type = jsonQuery.get(Element.CLASS_PROPERTY).asText();
this.jsonNode = jsonQuery;
this.accessType = accessType;
this.entryPoint = false;
this.fieldNamesToRemove = new HashSet<>();
fieldNamesToRemove.add(Element.CLASS_PROPERTY);
fieldNamesToRemove.add(Element.SUPERCLASSES_PROPERTY);
validateType(this.type, this.accessType);
}
@ -61,11 +73,15 @@ public abstract class JsonQueryERElement {
this.entryPoint = entryPoint;
}
protected abstract StringBuffer analize(StringBuffer stringBuffer) throws SchemaNotFoundException, InvalidQueryException, SchemaException, ResourceRegistryException;
public abstract StringBuffer analize(StringBuffer stringBuffer) throws SchemaNotFoundException, InvalidQueryException, SchemaException, ResourceRegistryException;
protected StringBuffer addWhereConstraint(JsonNode jsonNode, StringBuffer stringBuffer, String fieldNamePrefix) throws InvalidQueryException {
Iterator<String> iterator = jsonNode.fieldNames();
// ObjectNode objectNode = jsonNode.deepCopy();
//objectNode.remove(fieldNames);
boolean first = true;
while(iterator.hasNext()) {
@ -100,6 +116,11 @@ public abstract class JsonQueryERElement {
}else {
stringBuffer.append(" AND ");
}
// if(QueryLogicalOperator.getOperators().contains(fieldName)) {
// QueryLogicalOperator queryLogicalOperator = QueryLogicalOperator.getQueryLogicalOperator(fieldName);
// stringBuffer.append(queryLogicalOperator.getLogicalOperator());
// }
stringBuffer.append(getNameValueToMatch(jsonNode, fieldName, fieldNamePrefix));
}
@ -107,16 +128,65 @@ public abstract class JsonQueryERElement {
return stringBuffer;
}
private StringBuffer getNameValueToMatch(JsonNode jsonNode, String fieldName, String fieldNamePrefix) throws InvalidQueryException {
private StringBuffer getExpression(String fieldName, JsonNode jsonNode, String fieldNamePrefix) throws InvalidQueryException {
StringBuffer stringBuffer = new StringBuffer();
JsonNode gotJoJsonNode = jsonNode.get(fieldName);
if(gotJoJsonNode.isContainerNode()) {
if(gotJoJsonNode.isArray()) {
throw new InvalidQueryException("Array not supported for " + fieldName);
}
if(gotJoJsonNode.isObject()) {
for(QueryConditionalOperator queryComparisonOperator : QueryConditionalOperator.values()) {
if(gotJoJsonNode.has(queryComparisonOperator.operator)) {
// TODO
}
}
StringBuffer newPrefix = new StringBuffer();
if(fieldNamePrefix!=null) {
newPrefix.append(fieldNamePrefix);
newPrefix.append(".");
}
newPrefix.append(fieldName);
return addWhereConstraint(gotJoJsonNode, stringBuffer, newPrefix.toString());
}
}
addNameToCompare(stringBuffer, fieldName, fieldNamePrefix);
String value = jsonNode.get(fieldName).asText();
addValueToMatch(stringBuffer, gotJoJsonNode, value);
return stringBuffer;
}
private StringBuffer getNameValueToMatch(JsonNode jsonNode, String fieldName, String fieldNamePrefix) throws InvalidQueryException {
StringBuffer stringBuffer = new StringBuffer();
JsonNode gotJoJsonNode = jsonNode.get(fieldName);
if(gotJoJsonNode.isContainerNode()) {
if(gotJoJsonNode.isArray()) {
throw new InvalidQueryException("Array not supported for " + fieldName);
}
if(gotJoJsonNode.isObject()) {
for(QueryConditionalOperator queryComparisonOperator : QueryConditionalOperator.values()) {
if(gotJoJsonNode.has(queryComparisonOperator.operator)) {
// TODO
}
}
StringBuffer newPrefix = new StringBuffer();
if(fieldNamePrefix!=null) {
newPrefix.append(fieldNamePrefix);

View File

@ -0,0 +1,57 @@
package org.gcube.informationsystem.resourceregistry.query.json.base;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
/**
* @author Luca Frosini (ISTI - CNR)
*/
public enum QueryConditionalOperator {
$EQ("$eq", " = ", "Matches values that are equal to a specified value."),
$GT("$gt", " > ", "Matches values that are greater than a specified value."),
$GTE("$gte", " >= ", "Matches values that are greater than or equal to a specified value."),
$LT("$lt", " < ", "Matches values that are less than a specified value."),
$LTE("$lte", " <= ", "Matches values that are less than or equal to a specified value."),
$NE("$ne", " <> ", "Matches all values that are not equal to a specified value."),
$IN("$in", " IN ", "Matches any of the values specified in an array.");
protected final String operator;
protected final String conditionalOperator;
protected final String description;
private QueryConditionalOperator(String operator, String conditionalOperator, String description) {
this.operator = operator;
this.conditionalOperator = conditionalOperator;
this.description = description;
}
public String getOperator() {
return operator;
}
private static Set<String> operators;
private static Map<String,QueryConditionalOperator> operatorByKey;
static {
QueryConditionalOperator.operators = new HashSet<>();
QueryConditionalOperator.operatorByKey = new HashMap<>();
for(QueryConditionalOperator queryComparisonOperator : QueryConditionalOperator.values()) {
QueryConditionalOperator.operators.add(queryComparisonOperator.getOperator());
QueryConditionalOperator.operatorByKey.put(queryComparisonOperator.getOperator(), queryComparisonOperator);
}
}
public static Set<String> getOperators() {
return QueryConditionalOperator.operators;
}
public static QueryConditionalOperator getQueryComparisonOperator(String key) {
return operatorByKey.get(key);
}
}

View File

@ -0,0 +1,59 @@
package org.gcube.informationsystem.resourceregistry.query.json.base;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
/**
* @author Luca Frosini (ISTI - CNR)
*/
public enum QueryLogicalOperator {
$AND("$and", " AND ", "true if both the conditions are true"),
$OR("$or", " OR ", "true if at least one of the condition is true"),
$NOT("$not", " NOT ", "true if the condition is false.");
protected final String operator;
protected final String logicalOperator;
protected final String description;
private QueryLogicalOperator(String operator, String logicalOperator, String description) {
this.operator = operator;
this.logicalOperator = logicalOperator;
this.description = description;
}
public String getOperator() {
return operator;
}
public String getLogicalOperator() {
return logicalOperator;
}
public String getDescription() {
return description;
}
private static Set<String> operators;
private static Map<String,QueryLogicalOperator> operatorByKey;
static {
QueryLogicalOperator.operators = new HashSet<>();
QueryLogicalOperator.operatorByKey = new HashMap<>();
for(QueryLogicalOperator queryLogicalOperator : QueryLogicalOperator.values()) {
QueryLogicalOperator.operators.add(queryLogicalOperator.getOperator());
QueryLogicalOperator.operatorByKey.put(queryLogicalOperator.getOperator(), queryLogicalOperator);
}
}
public static Set<String> getOperators() {
return QueryLogicalOperator.operators;
}
public static QueryLogicalOperator getQueryLogicalOperator(String key) {
return operatorByKey.get(key);
}
}

View File

@ -1,4 +1,4 @@
package org.gcube.informationsystem.resourceregistry.query.json;
package org.gcube.informationsystem.resourceregistry.query.json.base.entities;
import org.gcube.com.fasterxml.jackson.databind.JsonNode;
import org.gcube.informationsystem.base.reference.AccessType;
@ -6,6 +6,8 @@ import org.gcube.informationsystem.base.reference.Direction;
import org.gcube.informationsystem.resourceregistry.api.exceptions.ResourceRegistryException;
import org.gcube.informationsystem.resourceregistry.api.exceptions.query.InvalidQueryException;
import org.gcube.informationsystem.resourceregistry.api.exceptions.schema.SchemaException;
import org.gcube.informationsystem.resourceregistry.query.json.base.JsonQueryERElement;
import org.gcube.informationsystem.resourceregistry.query.json.base.relations.JsonQueryConsistsOf;
/**
* @author Luca Frosini (ISTI - CNR)
@ -19,7 +21,7 @@ public class JsonQueryFacet extends JsonQueryERElement{
}
@Override
protected StringBuffer analize(StringBuffer stringBuffer) throws SchemaException, ResourceRegistryException {
public StringBuffer analize(StringBuffer stringBuffer) throws SchemaException, ResourceRegistryException {
StringBuffer newBuffer = new StringBuffer();
boolean entry = entryPoint;

View File

@ -1,4 +1,4 @@
package org.gcube.informationsystem.resourceregistry.query.json;
package org.gcube.informationsystem.resourceregistry.query.json.base.entities;
import org.gcube.com.fasterxml.jackson.databind.JsonNode;
import org.gcube.com.fasterxml.jackson.databind.node.ArrayNode;
@ -8,6 +8,9 @@ import org.gcube.informationsystem.base.reference.IdentifiableElement;
import org.gcube.informationsystem.model.reference.entities.Resource;
import org.gcube.informationsystem.resourceregistry.api.exceptions.ResourceRegistryException;
import org.gcube.informationsystem.resourceregistry.api.exceptions.schema.SchemaException;
import org.gcube.informationsystem.resourceregistry.query.json.base.JsonQueryERElement;
import org.gcube.informationsystem.resourceregistry.query.json.base.relations.JsonQueryConsistsOf;
import org.gcube.informationsystem.resourceregistry.query.json.base.relations.JsonQueryIsRelatedTo;
/**
* @author Luca Frosini (ISTI - CNR)
@ -19,7 +22,7 @@ public class JsonQueryResource extends JsonQueryERElement {
}
@Override
protected StringBuffer analize(StringBuffer stringBuffer) throws SchemaException, ResourceRegistryException {
public StringBuffer analize(StringBuffer stringBuffer) throws SchemaException, ResourceRegistryException {
if(!entryPoint) {
StringBuffer newBuffer = new StringBuffer();
newBuffer.append("TRAVERSE ");

View File

@ -1,4 +1,4 @@
package org.gcube.informationsystem.resourceregistry.query.json;
package org.gcube.informationsystem.resourceregistry.query.json.base.relations;
import org.gcube.com.fasterxml.jackson.databind.JsonNode;
import org.gcube.informationsystem.base.reference.AccessType;
@ -6,11 +6,13 @@ import org.gcube.informationsystem.base.reference.Direction;
import org.gcube.informationsystem.model.reference.relations.ConsistsOf;
import org.gcube.informationsystem.resourceregistry.api.exceptions.ResourceRegistryException;
import org.gcube.informationsystem.resourceregistry.api.exceptions.schema.SchemaException;
import org.gcube.informationsystem.resourceregistry.query.json.base.entities.JsonQueryFacet;
import org.gcube.informationsystem.resourceregistry.query.json.base.entities.JsonQueryResource;
/**
* @author Luca Frosini (ISTI - CNR)
*/
public class JsonQueryConsistsOf extends JsonQueryERElement{
public class JsonQueryConsistsOf extends JsonQueryRelation {
protected String requestedResourceType;
@ -28,7 +30,7 @@ public class JsonQueryConsistsOf extends JsonQueryERElement{
}
@Override
protected StringBuffer analize(StringBuffer stringBuffer) throws SchemaException, ResourceRegistryException {
public StringBuffer analize(StringBuffer stringBuffer) throws SchemaException, ResourceRegistryException {
StringBuffer consistsOfBuffer = new StringBuffer();
if(!jsonNode.has(ConsistsOf.SOURCE_PROPERTY)) {

View File

@ -1,4 +1,4 @@
package org.gcube.informationsystem.resourceregistry.query.json;
package org.gcube.informationsystem.resourceregistry.query.json.base.relations;
import org.gcube.com.fasterxml.jackson.databind.JsonNode;
import org.gcube.informationsystem.base.reference.AccessType;
@ -7,11 +7,12 @@ import org.gcube.informationsystem.model.reference.relations.ConsistsOf;
import org.gcube.informationsystem.resourceregistry.api.exceptions.ResourceRegistryException;
import org.gcube.informationsystem.resourceregistry.api.exceptions.query.InvalidQueryException;
import org.gcube.informationsystem.resourceregistry.api.exceptions.schema.SchemaException;
import org.gcube.informationsystem.resourceregistry.query.json.base.entities.JsonQueryResource;
/**
* @author Luca Frosini (ISTI - CNR)
*/
public class JsonQueryIsRelatedTo extends JsonQueryERElement{
public class JsonQueryIsRelatedTo extends JsonQueryRelation {
protected String requestedResourceType;
@ -73,8 +74,7 @@ public class JsonQueryIsRelatedTo extends JsonQueryERElement{
}
@Override
protected StringBuffer analize(StringBuffer stringBuffer) throws SchemaException, ResourceRegistryException {
public StringBuffer analize(StringBuffer stringBuffer) throws SchemaException, ResourceRegistryException {
JsonNode sourceJsonNode = jsonNode.get(ConsistsOf.SOURCE_PROPERTY);
JsonNode targetJsonNode = jsonNode.get(ConsistsOf.TARGET_PROPERTY);

View File

@ -0,0 +1,21 @@
package org.gcube.informationsystem.resourceregistry.query.json.base.relations;
import org.gcube.com.fasterxml.jackson.databind.JsonNode;
import org.gcube.informationsystem.base.reference.AccessType;
import org.gcube.informationsystem.model.reference.relations.Relation;
import org.gcube.informationsystem.resourceregistry.api.exceptions.ResourceRegistryException;
import org.gcube.informationsystem.resourceregistry.api.exceptions.schema.SchemaException;
import org.gcube.informationsystem.resourceregistry.query.json.base.JsonQueryERElement;
/**
* @author Luca Frosini (ISTI - CNR)
*/
public abstract class JsonQueryRelation extends JsonQueryERElement {
public JsonQueryRelation(JsonNode jsonQuery, AccessType accessType) throws SchemaException, ResourceRegistryException {
super(jsonQuery, accessType);
fieldNamesToRemove.add(Relation.TARGET_PROPERTY);
fieldNamesToRemove.add(Relation.SOURCE_PROPERTY);
}
}

View File

@ -54,7 +54,7 @@ public class JsonQueryTest extends ContextTest {
}
}
logger.info("Expected Query from JSON: {}", createdStringBuffer.toString());
logger.info("Expected Query from JSON: {}", expectedStringBuffer.toString());
Assert.assertTrue(createdStringBuffer.toString().compareTo(expectedStringBuffer.toString())==0);