diff --git a/src/main/java/org/gcube/informationsystem/resourceregistry/queries/json/base/JsonQueryERElement.java b/src/main/java/org/gcube/informationsystem/resourceregistry/queries/json/base/JsonQueryERElement.java index 0933276..aa46049 100644 --- a/src/main/java/org/gcube/informationsystem/resourceregistry/queries/json/base/JsonQueryERElement.java +++ b/src/main/java/org/gcube/informationsystem/resourceregistry/queries/json/base/JsonQueryERElement.java @@ -6,6 +6,8 @@ import java.util.Iterator; import java.util.List; import java.util.Set; +import javax.ws.rs.InternalServerErrorException; + 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; @@ -20,6 +22,7 @@ import org.gcube.informationsystem.resourceregistry.api.exceptions.types.SchemaE 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.queries.operators.ProjectionOperator; import org.gcube.informationsystem.resourceregistry.types.TypesCache; import org.gcube.informationsystem.utils.TypeUtility; import org.slf4j.Logger; @@ -113,6 +116,8 @@ public abstract class JsonQueryERElement { this.caller = null; this.breadcrumb = new ArrayList<>(); this.position = 0; + this.alias = null; + this.fieldsToEmit = new ArrayList<>(); this.fieldNamesToRemove = new HashSet<>(); @@ -149,9 +154,13 @@ public abstract class JsonQueryERElement { } public void setProjection(boolean projection) { + if(!projection) { + throw new InternalServerErrorException("Projection can only be set to true from code. This is a server side bug. Please contact the administrator."); + } this.projection = projection; - if(projection && !entryPoint) { - breadcrumb.get(0).setEntryPoint(projection); + if(!entryPoint) { + // Set the projection in the parent + breadcrumb.get(breadcrumb.size()-2).setProjection(projection); } } @@ -205,12 +214,11 @@ public abstract class JsonQueryERElement { * @param fieldToEmit */ protected void addFieldToEmit(String fieldToEmit) { - if(entryPoint) { - fieldsToEmit.add(fieldToEmit); - logger.trace("The field to emit ({}) has been added to entry point, i.e. {} with alias {}", fieldToEmit, this.type, this.alias); - }else { - logger.trace("The field to emit ({}) will be added to entry point", fieldToEmit); - breadcrumb.get(0).addFieldToEmit(fieldToEmit); + fieldsToEmit.add(fieldToEmit); + logger.trace("The field to emit ({}) has been added to {} with alias {}", fieldToEmit, this.type, this.alias); + if(!entryPoint) { + logger.trace("The field to emit ({}) will be added to the parent too", fieldToEmit); + breadcrumb.get(breadcrumb.size()-2).addFieldToEmit(fieldToEmit); } } @@ -288,6 +296,25 @@ public abstract class JsonQueryERElement { } protected StringBuffer evaluateNode(JsonNode jsonNode, String fieldName, String fieldNamePrefix) throws InvalidQueryException { + + if(ProjectionOperator.getOperators().contains(fieldName)) { + setProjection(true); + Iterator iterator = jsonNode.fieldNames(); + while(iterator.hasNext()) { + String fieldNameToEmit = iterator.next(); + String nameOfFieldToEmit = jsonNode.get(fieldNameToEmit).asText(); + StringBuffer b = new StringBuffer(); + b.append(getAlias(true)); + b.append("."); + b.append(fieldNameToEmit); + b.append(" AS "); + b.append(nameOfFieldToEmit); + addFieldToEmit(b.toString()); + } + return null; + } + + StringBuffer stringBuffer = new StringBuffer(); if(LogicalOperator.getOperators().contains(fieldName)) { @@ -441,7 +468,7 @@ public abstract class JsonQueryERElement { List childrenBreadcrumb = getChildrenBreadcrumb(); if(entryPoint) { - alias = getAlias(); + getAlias(true); } StringBuffer buffer = getSpecificMatchQuery(childrenBreadcrumb); diff --git a/src/main/java/org/gcube/informationsystem/resourceregistry/queries/json/base/entities/JsonQueryFacet.java b/src/main/java/org/gcube/informationsystem/resourceregistry/queries/json/base/entities/JsonQueryFacet.java index 7899b2b..6d4369d 100644 --- a/src/main/java/org/gcube/informationsystem/resourceregistry/queries/json/base/entities/JsonQueryFacet.java +++ b/src/main/java/org/gcube/informationsystem/resourceregistry/queries/json/base/entities/JsonQueryFacet.java @@ -95,7 +95,7 @@ public class JsonQueryFacet extends JsonQueryEntity { protected StringBuffer getSpecificMatchQuery(List childrenBreadcrumb) throws SchemaException, ResourceRegistryException { // TODO Auto-generated method stub - return null; + return new StringBuffer(); } } diff --git a/src/main/java/org/gcube/informationsystem/resourceregistry/queries/json/base/entities/JsonQueryResource.java b/src/main/java/org/gcube/informationsystem/resourceregistry/queries/json/base/entities/JsonQueryResource.java index 65dfd46..d62271e 100644 --- a/src/main/java/org/gcube/informationsystem/resourceregistry/queries/json/base/entities/JsonQueryResource.java +++ b/src/main/java/org/gcube/informationsystem/resourceregistry/queries/json/base/entities/JsonQueryResource.java @@ -123,7 +123,7 @@ public class JsonQueryResource extends JsonQueryEntity { StringBuffer buffer = new StringBuffer(); if(!entryPoint) { - buffer.append("\n\t"); + buffer.append("\n\t."); buffer.append(direction.name().toLowerCase()); buffer.append("V('"); buffer.append(type); @@ -160,13 +160,14 @@ public class JsonQueryResource extends JsonQueryEntity { buffer = jsonQueryIsRelatedTo.createMatchQuery(buffer); if(traverseBack) { - buffer.append(jsonQueryIsRelatedTo.getDirection().opposite().name().toLowerCase()); + buffer.append("\n\t."); + buffer.append(jsonQueryIsRelatedTo.getDirection().name().toLowerCase()); buffer.append("V('"); buffer.append(type); buffer.append("') "); - if(alias!=null || entryPoint) { + if(getAlias()!=null || entryPoint) { buffer.append("{ where: ($matched."); - buffer.append(alias); + buffer.append(getAlias()); buffer.append(" == $currentMatch)}\n"); } } @@ -194,13 +195,14 @@ public class JsonQueryResource extends JsonQueryEntity { buffer = jsonQueryConsistsOf.createMatchQuery(buffer); if(traverseBack) { - buffer.append(jsonQueryConsistsOf.getDirection().opposite().name().toLowerCase()); + buffer.append("\n\t."); + buffer.append(jsonQueryConsistsOf.getDirection().name().toLowerCase()); buffer.append("V('"); buffer.append(type); buffer.append("') "); - if(alias!=null || entryPoint) { + if(getAlias()!=null || entryPoint) { buffer.append("{ where: ($matched."); - buffer.append(alias); + buffer.append(getAlias()); buffer.append(" == $currentMatch)}\n"); } } @@ -210,5 +212,4 @@ public class JsonQueryResource extends JsonQueryEntity { return buffer; } - } diff --git a/src/main/java/org/gcube/informationsystem/resourceregistry/queries/json/base/relations/JsonQueryConsistsOf.java b/src/main/java/org/gcube/informationsystem/resourceregistry/queries/json/base/relations/JsonQueryConsistsOf.java index 6dd75a8..664b4ae 100644 --- a/src/main/java/org/gcube/informationsystem/resourceregistry/queries/json/base/relations/JsonQueryConsistsOf.java +++ b/src/main/java/org/gcube/informationsystem/resourceregistry/queries/json/base/relations/JsonQueryConsistsOf.java @@ -167,14 +167,20 @@ public class JsonQueryConsistsOf extends JsonQueryRelation { buffer.append(direction.name().toLowerCase()); buffer.append("E('"); buffer.append(type); - buffer.append("'"); + buffer.append("')"); if(size>0) { alias = getAlias(true); buffer.append("{ where: ($matched."); buffer.append(alias); buffer.append(" == $currentMatch)"); - buffer.append(addConstraints(jsonNode, null, alias)); + + StringBuffer sb = addConstraints(jsonNode, null, alias); + if(sb!=null && sb.length()>0) { + buffer.append(" AND "); + buffer.append(sb); + } + buffer.append("}\n"); } @@ -187,7 +193,7 @@ public class JsonQueryConsistsOf extends JsonQueryRelation { buffer.append(direction.opposite().name().toLowerCase()); buffer.append("E('"); buffer.append(type); - buffer.append("'"); + buffer.append("')"); } return buffer; diff --git a/src/main/java/org/gcube/informationsystem/resourceregistry/queries/operators/ProjectionOperator.java b/src/main/java/org/gcube/informationsystem/resourceregistry/queries/operators/ProjectionOperator.java new file mode 100644 index 0000000..d452798 --- /dev/null +++ b/src/main/java/org/gcube/informationsystem/resourceregistry/queries/operators/ProjectionOperator.java @@ -0,0 +1,53 @@ +package org.gcube.informationsystem.resourceregistry.queries.operators; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +/** + * @author Luca Frosini (ISTI - CNR) + * See https://www.orientdb.com/docs/3.0.x/sql/SQL-Where.html + */ +public enum ProjectionOperator { + + EMIT("_emit", ""); + + protected final String operator; + protected final String description; + + private ProjectionOperator(String operator, String description) { + this.operator = operator; + this.description = description; + } + + public String getOperator() { + return operator; + } + + public String getDescription() { + return description; + } + + private static Set operators; + private static Map operatorByKey; + + static { + ProjectionOperator.operators = new HashSet<>(); + ProjectionOperator.operatorByKey = new HashMap<>(); + + for(ProjectionOperator po : ProjectionOperator.values()) { + ProjectionOperator.operators.add(po.getOperator()); + ProjectionOperator.operatorByKey.put(po.getOperator(), po); + } + } + + public static Set getOperators() { + return ProjectionOperator.operators; + } + + public static ProjectionOperator getQueryLogicalOperator(String key) { + return operatorByKey.get(key); + } + +} \ No newline at end of file diff --git a/src/test/java/org/gcube/informationsystem/resourceregistry/queries/JsonQueryTest.java b/src/test/java/org/gcube/informationsystem/resourceregistry/queries/JsonQueryTest.java index 1c14b33..e0f6401 100644 --- a/src/test/java/org/gcube/informationsystem/resourceregistry/queries/JsonQueryTest.java +++ b/src/test/java/org/gcube/informationsystem/resourceregistry/queries/JsonQueryTest.java @@ -35,6 +35,13 @@ public class JsonQueryTest extends ContextTest { return new File(resourcesDirectory, "queries"); } + public File getProjectionQueriesDirectory() throws Exception { + URL logbackFileURL = JsonQueryTest.class.getClassLoader().getResource("logback-test.xml"); + File logbackFile = new File(logbackFileURL.toURI()); + File resourcesDirectory = logbackFile.getParentFile(); + return new File(resourcesDirectory, "projection-queries"); + } + @Test public void testJsonQueries() throws Exception { ContextTest.setContextByName(DEVVRE); @@ -191,8 +198,8 @@ public class JsonQueryTest extends ContextTest { @Test public void testCreateMatchQuery() throws Exception { - File queriesDirectory = getQueriesDirectory(); - File jsonQueryFile = new File(queriesDirectory, "query6.json"); + File queriesDirectory = getProjectionQueriesDirectory(); + File jsonQueryFile = new File(queriesDirectory, "EService-query.json"); ObjectMapper objectMapper = new ObjectMapper(); JsonNode jsonNode = objectMapper.readTree(jsonQueryFile); logger.info("Going to test the following JSON query {}", jsonNode.toString()); diff --git a/src/test/resources/projection-queries/EService-query.json b/src/test/resources/projection-queries/EService-query.json index 21970e2..b697e85 100644 --- a/src/test/resources/projection-queries/EService-query.json +++ b/src/test/resources/projection-queries/EService-query.json @@ -1,5 +1,5 @@ { - "_projection" : { + "type": "EService", "_emit" : { "id" : "id" @@ -45,5 +45,5 @@ } } ] - } + } \ No newline at end of file