Implementing projection

This commit is contained in:
luca.frosini 2023-11-20 17:34:48 +01:00
parent f2cf0a4f17
commit 9450134790
7 changed files with 119 additions and 25 deletions

View File

@ -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<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();
if(LogicalOperator.getOperators().contains(fieldName)) {
@ -441,7 +468,7 @@ public abstract class JsonQueryERElement {
List<JsonQueryERElement> childrenBreadcrumb = getChildrenBreadcrumb();
if(entryPoint) {
alias = getAlias();
getAlias(true);
}
StringBuffer buffer = getSpecificMatchQuery(childrenBreadcrumb);

View File

@ -95,7 +95,7 @@ public class JsonQueryFacet extends JsonQueryEntity {
protected StringBuffer getSpecificMatchQuery(List<JsonQueryERElement> childrenBreadcrumb)
throws SchemaException, ResourceRegistryException {
// TODO Auto-generated method stub
return null;
return new StringBuffer();
}
}

View File

@ -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;
}
}

View File

@ -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;

View File

@ -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);
}
}

View File

@ -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());

View File

@ -1,5 +1,5 @@
{
"_projection" : {
"type": "EService",
"_emit" : {
"id" : "id"
@ -45,5 +45,5 @@
}
}
]
}
}