Implementing projection
This commit is contained in:
parent
f2cf0a4f17
commit
9450134790
|
@ -6,6 +6,8 @@ import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import javax.ws.rs.InternalServerErrorException;
|
||||||
|
|
||||||
import org.gcube.com.fasterxml.jackson.databind.JsonNode;
|
import org.gcube.com.fasterxml.jackson.databind.JsonNode;
|
||||||
import org.gcube.com.fasterxml.jackson.databind.ObjectMapper;
|
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.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.api.exceptions.types.SchemaNotFoundException;
|
||||||
import org.gcube.informationsystem.resourceregistry.queries.operators.ConditionalOperator;
|
import org.gcube.informationsystem.resourceregistry.queries.operators.ConditionalOperator;
|
||||||
import org.gcube.informationsystem.resourceregistry.queries.operators.LogicalOperator;
|
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.resourceregistry.types.TypesCache;
|
||||||
import org.gcube.informationsystem.utils.TypeUtility;
|
import org.gcube.informationsystem.utils.TypeUtility;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
@ -113,6 +116,8 @@ public abstract class JsonQueryERElement {
|
||||||
this.caller = null;
|
this.caller = null;
|
||||||
this.breadcrumb = new ArrayList<>();
|
this.breadcrumb = new ArrayList<>();
|
||||||
this.position = 0;
|
this.position = 0;
|
||||||
|
this.alias = null;
|
||||||
|
this.fieldsToEmit = new ArrayList<>();
|
||||||
|
|
||||||
|
|
||||||
this.fieldNamesToRemove = new HashSet<>();
|
this.fieldNamesToRemove = new HashSet<>();
|
||||||
|
@ -149,9 +154,13 @@ public abstract class JsonQueryERElement {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setProjection(boolean projection) {
|
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;
|
this.projection = projection;
|
||||||
if(projection && !entryPoint) {
|
if(!entryPoint) {
|
||||||
breadcrumb.get(0).setEntryPoint(projection);
|
// Set the projection in the parent
|
||||||
|
breadcrumb.get(breadcrumb.size()-2).setProjection(projection);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -205,12 +214,11 @@ public abstract class JsonQueryERElement {
|
||||||
* @param fieldToEmit
|
* @param fieldToEmit
|
||||||
*/
|
*/
|
||||||
protected void addFieldToEmit(String fieldToEmit) {
|
protected void addFieldToEmit(String fieldToEmit) {
|
||||||
if(entryPoint) {
|
|
||||||
fieldsToEmit.add(fieldToEmit);
|
fieldsToEmit.add(fieldToEmit);
|
||||||
logger.trace("The field to emit ({}) has been added to entry point, i.e. {} with alias {}", fieldToEmit, this.type, this.alias);
|
logger.trace("The field to emit ({}) has been added to {} with alias {}", fieldToEmit, this.type, this.alias);
|
||||||
}else {
|
if(!entryPoint) {
|
||||||
logger.trace("The field to emit ({}) will be added to entry point", fieldToEmit);
|
logger.trace("The field to emit ({}) will be added to the parent too", fieldToEmit);
|
||||||
breadcrumb.get(0).addFieldToEmit(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 {
|
protected StringBuffer evaluateNode(JsonNode jsonNode, String fieldName, String fieldNamePrefix) throws InvalidQueryException {
|
||||||
|
|
||||||
|
if(ProjectionOperator.getOperators().contains(fieldName)) {
|
||||||
|
setProjection(true);
|
||||||
|
Iterator<String> 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();
|
StringBuffer stringBuffer = new StringBuffer();
|
||||||
|
|
||||||
if(LogicalOperator.getOperators().contains(fieldName)) {
|
if(LogicalOperator.getOperators().contains(fieldName)) {
|
||||||
|
@ -441,7 +468,7 @@ public abstract class JsonQueryERElement {
|
||||||
List<JsonQueryERElement> childrenBreadcrumb = getChildrenBreadcrumb();
|
List<JsonQueryERElement> childrenBreadcrumb = getChildrenBreadcrumb();
|
||||||
|
|
||||||
if(entryPoint) {
|
if(entryPoint) {
|
||||||
alias = getAlias();
|
getAlias(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
StringBuffer buffer = getSpecificMatchQuery(childrenBreadcrumb);
|
StringBuffer buffer = getSpecificMatchQuery(childrenBreadcrumb);
|
||||||
|
|
|
@ -95,7 +95,7 @@ public class JsonQueryFacet extends JsonQueryEntity {
|
||||||
protected StringBuffer getSpecificMatchQuery(List<JsonQueryERElement> childrenBreadcrumb)
|
protected StringBuffer getSpecificMatchQuery(List<JsonQueryERElement> childrenBreadcrumb)
|
||||||
throws SchemaException, ResourceRegistryException {
|
throws SchemaException, ResourceRegistryException {
|
||||||
// TODO Auto-generated method stub
|
// TODO Auto-generated method stub
|
||||||
return null;
|
return new StringBuffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -123,7 +123,7 @@ public class JsonQueryResource extends JsonQueryEntity {
|
||||||
StringBuffer buffer = new StringBuffer();
|
StringBuffer buffer = new StringBuffer();
|
||||||
|
|
||||||
if(!entryPoint) {
|
if(!entryPoint) {
|
||||||
buffer.append("\n\t");
|
buffer.append("\n\t.");
|
||||||
buffer.append(direction.name().toLowerCase());
|
buffer.append(direction.name().toLowerCase());
|
||||||
buffer.append("V('");
|
buffer.append("V('");
|
||||||
buffer.append(type);
|
buffer.append(type);
|
||||||
|
@ -160,13 +160,14 @@ public class JsonQueryResource extends JsonQueryEntity {
|
||||||
buffer = jsonQueryIsRelatedTo.createMatchQuery(buffer);
|
buffer = jsonQueryIsRelatedTo.createMatchQuery(buffer);
|
||||||
|
|
||||||
if(traverseBack) {
|
if(traverseBack) {
|
||||||
buffer.append(jsonQueryIsRelatedTo.getDirection().opposite().name().toLowerCase());
|
buffer.append("\n\t.");
|
||||||
|
buffer.append(jsonQueryIsRelatedTo.getDirection().name().toLowerCase());
|
||||||
buffer.append("V('");
|
buffer.append("V('");
|
||||||
buffer.append(type);
|
buffer.append(type);
|
||||||
buffer.append("') ");
|
buffer.append("') ");
|
||||||
if(alias!=null || entryPoint) {
|
if(getAlias()!=null || entryPoint) {
|
||||||
buffer.append("{ where: ($matched.");
|
buffer.append("{ where: ($matched.");
|
||||||
buffer.append(alias);
|
buffer.append(getAlias());
|
||||||
buffer.append(" == $currentMatch)}\n");
|
buffer.append(" == $currentMatch)}\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -194,13 +195,14 @@ public class JsonQueryResource extends JsonQueryEntity {
|
||||||
buffer = jsonQueryConsistsOf.createMatchQuery(buffer);
|
buffer = jsonQueryConsistsOf.createMatchQuery(buffer);
|
||||||
|
|
||||||
if(traverseBack) {
|
if(traverseBack) {
|
||||||
buffer.append(jsonQueryConsistsOf.getDirection().opposite().name().toLowerCase());
|
buffer.append("\n\t.");
|
||||||
|
buffer.append(jsonQueryConsistsOf.getDirection().name().toLowerCase());
|
||||||
buffer.append("V('");
|
buffer.append("V('");
|
||||||
buffer.append(type);
|
buffer.append(type);
|
||||||
buffer.append("') ");
|
buffer.append("') ");
|
||||||
if(alias!=null || entryPoint) {
|
if(getAlias()!=null || entryPoint) {
|
||||||
buffer.append("{ where: ($matched.");
|
buffer.append("{ where: ($matched.");
|
||||||
buffer.append(alias);
|
buffer.append(getAlias());
|
||||||
buffer.append(" == $currentMatch)}\n");
|
buffer.append(" == $currentMatch)}\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -210,5 +212,4 @@ public class JsonQueryResource extends JsonQueryEntity {
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -167,14 +167,20 @@ public class JsonQueryConsistsOf extends JsonQueryRelation {
|
||||||
buffer.append(direction.name().toLowerCase());
|
buffer.append(direction.name().toLowerCase());
|
||||||
buffer.append("E('");
|
buffer.append("E('");
|
||||||
buffer.append(type);
|
buffer.append(type);
|
||||||
buffer.append("'");
|
buffer.append("')");
|
||||||
|
|
||||||
if(size>0) {
|
if(size>0) {
|
||||||
alias = getAlias(true);
|
alias = getAlias(true);
|
||||||
buffer.append("{ where: ($matched.");
|
buffer.append("{ where: ($matched.");
|
||||||
buffer.append(alias);
|
buffer.append(alias);
|
||||||
buffer.append(" == $currentMatch)");
|
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");
|
buffer.append("}\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -187,7 +193,7 @@ public class JsonQueryConsistsOf extends JsonQueryRelation {
|
||||||
buffer.append(direction.opposite().name().toLowerCase());
|
buffer.append(direction.opposite().name().toLowerCase());
|
||||||
buffer.append("E('");
|
buffer.append("E('");
|
||||||
buffer.append(type);
|
buffer.append(type);
|
||||||
buffer.append("'");
|
buffer.append("')");
|
||||||
}
|
}
|
||||||
|
|
||||||
return buffer;
|
return buffer;
|
||||||
|
|
|
@ -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<String> operators;
|
||||||
|
private static Map<String,ProjectionOperator> 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<String> getOperators() {
|
||||||
|
return ProjectionOperator.operators;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ProjectionOperator getQueryLogicalOperator(String key) {
|
||||||
|
return operatorByKey.get(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -35,6 +35,13 @@ public class JsonQueryTest extends ContextTest {
|
||||||
return new File(resourcesDirectory, "queries");
|
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
|
@Test
|
||||||
public void testJsonQueries() throws Exception {
|
public void testJsonQueries() throws Exception {
|
||||||
ContextTest.setContextByName(DEVVRE);
|
ContextTest.setContextByName(DEVVRE);
|
||||||
|
@ -191,8 +198,8 @@ public class JsonQueryTest extends ContextTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCreateMatchQuery() throws Exception {
|
public void testCreateMatchQuery() throws Exception {
|
||||||
File queriesDirectory = getQueriesDirectory();
|
File queriesDirectory = getProjectionQueriesDirectory();
|
||||||
File jsonQueryFile = new File(queriesDirectory, "query6.json");
|
File jsonQueryFile = new File(queriesDirectory, "EService-query.json");
|
||||||
ObjectMapper objectMapper = new ObjectMapper();
|
ObjectMapper objectMapper = new ObjectMapper();
|
||||||
JsonNode jsonNode = objectMapper.readTree(jsonQueryFile);
|
JsonNode jsonNode = objectMapper.readTree(jsonQueryFile);
|
||||||
logger.info("Going to test the following JSON query {}", jsonNode.toString());
|
logger.info("Going to test the following JSON query {}", jsonNode.toString());
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"_projection" : {
|
|
||||||
"type": "EService",
|
"type": "EService",
|
||||||
"_emit" : {
|
"_emit" : {
|
||||||
"id" : "id"
|
"id" : "id"
|
||||||
|
@ -45,5 +45,5 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
|
||||||
}
|
}
|
Loading…
Reference in New Issue