Implementing projection
This commit is contained in:
parent
5fe0e5771b
commit
6a1e0e5838
|
@ -22,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.MatemathicsOperator;
|
||||
import org.gcube.informationsystem.resourceregistry.queries.operators.ProjectionOperator;
|
||||
import org.gcube.informationsystem.resourceregistry.types.TypesCache;
|
||||
import org.gcube.informationsystem.utils.TypeUtility;
|
||||
|
@ -187,10 +188,10 @@ public abstract class JsonQueryERElement {
|
|||
protected StringBuffer generateAlias() {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
sb.append(type.toLowerCase());
|
||||
|
||||
// The entry point will have 00 as suffix
|
||||
sb.append(breadcrumb.size());
|
||||
sb.append(position);
|
||||
for(JsonQueryERElement elem : breadcrumb) {
|
||||
sb.append(elem.getPosition());
|
||||
}
|
||||
sb.append(this.position);
|
||||
return sb;
|
||||
}
|
||||
|
||||
|
@ -243,13 +244,11 @@ public abstract class JsonQueryERElement {
|
|||
JsonNode node = objectNode.get(fieldName);
|
||||
StringBuffer evBuffer = evaluateNode(node, fieldName, fieldNamePrefix);
|
||||
|
||||
if(!first) {
|
||||
stringBuffer.append(queryLogicalOperator.getLogicalOperator());
|
||||
}
|
||||
|
||||
if(evBuffer!=null && evBuffer.length()>0) {
|
||||
if(first) {
|
||||
first = false;
|
||||
}else {
|
||||
stringBuffer.append(queryLogicalOperator.getLogicalOperator());
|
||||
}
|
||||
stringBuffer.append(evBuffer);
|
||||
}
|
||||
|
@ -293,13 +292,23 @@ public abstract class JsonQueryERElement {
|
|||
b.append(getAlias(true));
|
||||
b.append(".");
|
||||
b.append(fieldNameToEmit);
|
||||
b.append(" AS ");
|
||||
b.append(" AS `");
|
||||
b.append(nameOfFieldToEmit);
|
||||
b.append("`");
|
||||
addFieldToEmit(b.toString());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
if(MatemathicsOperator.getOperators().contains(fieldName)) {
|
||||
--size;
|
||||
setProjection(true);
|
||||
MatemathicsOperator mo = MatemathicsOperator.getMatemathicsOperator(fieldName);
|
||||
String fieldToEmit = mo.generateFieldToEmit(jsonNode, getAlias(true));
|
||||
addFieldToEmit(fieldToEmit);
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
StringBuffer stringBuffer = new StringBuffer();
|
||||
|
||||
|
@ -347,6 +356,11 @@ public abstract class JsonQueryERElement {
|
|||
stringBuffer.append(addCondition(ConditionalOperator.EQ, key, value));
|
||||
}
|
||||
|
||||
if(jsonNode.isNull()) {
|
||||
StringBuffer key = getKey(fieldName, null);
|
||||
stringBuffer.append(addCondition(ConditionalOperator.IS, key, null));
|
||||
}
|
||||
|
||||
return stringBuffer;
|
||||
}
|
||||
|
||||
|
|
|
@ -5,6 +5,15 @@ import java.util.HashSet;
|
|||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.ws.rs.BadRequestException;
|
||||
|
||||
import org.gcube.com.fasterxml.jackson.databind.JsonNode;
|
||||
import org.gcube.com.fasterxml.jackson.databind.node.ArrayNode;
|
||||
import org.gcube.com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
import org.gcube.com.fasterxml.jackson.databind.node.TextNode;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* @author Luca Frosini (ISTI - CNR)
|
||||
*
|
||||
|
@ -32,46 +41,137 @@ public enum MatemathicsOperator {
|
|||
BITWISE_XOR("_bitxor", " ^ ", ""),
|
||||
ARRAY_CONCATENATION("_arrayconcat", " || ", "");
|
||||
|
||||
protected final String operator;
|
||||
protected final String matemathicsOperator;
|
||||
protected static Logger logger = LoggerFactory.getLogger(MatemathicsOperator.class);
|
||||
|
||||
public static final String VALUES_KEY = "values";
|
||||
public static final String SEPARATOR_KEY = "separator";
|
||||
public static final String AS_KEY = "as";
|
||||
|
||||
protected final String operatorKey;
|
||||
protected final String dbQueryOperator;
|
||||
protected final String description;
|
||||
|
||||
private MatemathicsOperator(String operator, String matemathicsOperator, String description) {
|
||||
this.operator = operator;
|
||||
this.matemathicsOperator = matemathicsOperator;
|
||||
private MatemathicsOperator(String operatorKey, String dbQueryOperator, String description) {
|
||||
this.operatorKey = operatorKey;
|
||||
this.dbQueryOperator = dbQueryOperator;
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public String getOperator() {
|
||||
return operator;
|
||||
public String getOperatorKey() {
|
||||
return operatorKey;
|
||||
}
|
||||
|
||||
public String getMatemathicsOperator() {
|
||||
return matemathicsOperator;
|
||||
public String getDbQueryOperator() {
|
||||
return dbQueryOperator;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
private static Set<String> operators;
|
||||
private static Map<String,MatemathicsOperator> operatorByKey;
|
||||
|
||||
static {
|
||||
MatemathicsOperator.operators = new HashSet<>();
|
||||
MatemathicsOperator.operatorByKey = new HashMap<>();
|
||||
|
||||
for(MatemathicsOperator queryLogicalOperator : MatemathicsOperator.values()) {
|
||||
MatemathicsOperator.operators.add(queryLogicalOperator.getOperator());
|
||||
MatemathicsOperator.operatorByKey.put(queryLogicalOperator.getOperator(), queryLogicalOperator);
|
||||
for(MatemathicsOperator matemathicsOperator : MatemathicsOperator.values()) {
|
||||
MatemathicsOperator.operatorByKey.put(matemathicsOperator.getOperatorKey(), matemathicsOperator);
|
||||
}
|
||||
}
|
||||
|
||||
public static Set<String> getOperators() {
|
||||
return MatemathicsOperator.operators;
|
||||
return new HashSet<>(MatemathicsOperator.operatorByKey.keySet());
|
||||
}
|
||||
|
||||
public static MatemathicsOperator getQueryLogicalOperator(String key) {
|
||||
public static MatemathicsOperator getMatemathicsOperator(String key) {
|
||||
return operatorByKey.get(key);
|
||||
}
|
||||
|
||||
protected String getError(String key, Class<?> clazz, boolean mandatory) {
|
||||
StringBuffer error = new StringBuffer();
|
||||
error.append("Root emitting MatemathicsOperator (i.e. ");
|
||||
error.append(this.operatorKey);
|
||||
error.append(")");
|
||||
error.append(" contains ");
|
||||
if(mandatory) {
|
||||
error.append("mandatory ");
|
||||
}
|
||||
error.append(key);
|
||||
error.append(" which must be a");
|
||||
error.append(clazz.getSimpleName());
|
||||
error.append(". This is a client error. Please fix your query");
|
||||
logger.error(error.toString());
|
||||
throw new BadRequestException(error.toString());
|
||||
}
|
||||
|
||||
public String generateFieldToEmit(JsonNode jsonNode, String fieldPrefix) {
|
||||
JsonNode jn = jsonNode.get(VALUES_KEY);
|
||||
if(jn.isNull() || !jn.isArray()) {
|
||||
getError(VALUES_KEY, ArrayNode.class, true);
|
||||
}
|
||||
String fieldSeparator = null;
|
||||
if(this == MatemathicsOperator.SUM && jsonNode.has(SEPARATOR_KEY)) {
|
||||
JsonNode sep = jsonNode.get(SEPARATOR_KEY);
|
||||
if(!sep.isTextual()) {
|
||||
getError(SEPARATOR_KEY, TextNode.class, false);
|
||||
}
|
||||
fieldSeparator = sep.asText();
|
||||
}
|
||||
StringBuffer sb = new StringBuffer();
|
||||
sb.append("(");
|
||||
sb.append(generateFieldToEmit((ArrayNode) jn, fieldSeparator, fieldPrefix));
|
||||
JsonNode jnAs = jsonNode.get(AS_KEY);
|
||||
if(jnAs.isNull() || !jnAs.isTextual()) {
|
||||
getError(AS_KEY, TextNode.class, true);
|
||||
}
|
||||
sb.append(") AS `");
|
||||
sb.append(jnAs.asText());
|
||||
sb.append("`");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
protected StringBuffer addFieldPrefix(StringBuffer sb, String fieldPrefix) {
|
||||
if(fieldPrefix !=null && fieldPrefix.trim().length()>0) {
|
||||
sb.append(fieldPrefix.trim());
|
||||
sb.append(".");
|
||||
}
|
||||
return sb;
|
||||
}
|
||||
|
||||
protected StringBuffer generateFieldToEmit(ArrayNode arrayNode, String fieldsSeparator, String fieldPrefix) {
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
int size = arrayNode.size();
|
||||
for(int i=0; i<size; i++) {
|
||||
JsonNode jn = arrayNode.get(i);
|
||||
if(jn.isObject()) {
|
||||
ObjectNode on = (ObjectNode) jn;
|
||||
String key = on.fieldNames().next();
|
||||
MatemathicsOperator mo = MatemathicsOperator.getMatemathicsOperator(key);
|
||||
ArrayNode an = (ArrayNode) on.get(key);
|
||||
buffer.append("(");
|
||||
buffer.append(mo.generateFieldToEmit(an, null, fieldPrefix));
|
||||
buffer.append(")");
|
||||
}
|
||||
|
||||
if(jn.isTextual()) {
|
||||
buffer = addFieldPrefix(buffer, fieldPrefix);
|
||||
buffer.append(jn.asText());
|
||||
}
|
||||
|
||||
if(i<(size-1)) {
|
||||
buffer.append(" ");
|
||||
buffer.append(dbQueryOperator);
|
||||
buffer.append(" ");
|
||||
if(fieldsSeparator!=null) {
|
||||
buffer.append("'");
|
||||
buffer.append(fieldsSeparator);
|
||||
buffer.append("' ");
|
||||
buffer.append(dbQueryOperator);
|
||||
buffer.append(" ");
|
||||
}
|
||||
}
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -199,7 +199,7 @@ public class JsonQueryTest extends ContextTest {
|
|||
@Test
|
||||
public void testCreateMatchQuery() throws Exception {
|
||||
File queriesDirectory = getProjectionQueriesDirectory();
|
||||
File jsonQueryFile = new File(queriesDirectory, "EService-query.json");
|
||||
File jsonQueryFile = new File(queriesDirectory, "HostingNode-query.json");
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
JsonNode jsonNode = objectMapper.readTree(jsonQueryFile);
|
||||
logger.info("Going to test the following JSON query {}", jsonNode.toString());
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
package org.gcube.informationsystem.resourceregistry.queries.operators;
|
||||
|
||||
import org.gcube.com.fasterxml.jackson.databind.JsonNode;
|
||||
import org.gcube.com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.junit.Test;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class MathematicsOperatorTest {
|
||||
|
||||
protected static Logger logger = LoggerFactory.getLogger(MathematicsOperatorTest.class);
|
||||
|
||||
public static final String JSON = "{ \n"
|
||||
+ " \"values\" : [\n"
|
||||
+ " {\n"
|
||||
+ " \"_minus\" : [\n"
|
||||
+ " \"size\", \n"
|
||||
+ " \"used\" \n"
|
||||
+ " ]\n"
|
||||
+ " },\n"
|
||||
+ " \"unit\" \n"
|
||||
+ " ],\n"
|
||||
+ " \"separator\" : \" \",\n"
|
||||
+ " \"as\" : \"HD Space Left\"\n"
|
||||
+ "}";
|
||||
|
||||
@Test
|
||||
public void testGenerateFieldToEmit() throws Exception {
|
||||
ObjectMapper om = new ObjectMapper();
|
||||
JsonNode jn = om.readTree(JSON);
|
||||
String s = MatemathicsOperator.SUM.generateFieldToEmit(jn, "haspersistentmemory20");
|
||||
logger.debug(s);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -21,9 +21,9 @@ MATCH
|
|||
.outV('EService') { where: ($matched.eservice00 == $currentMatch)}
|
||||
|
||||
RETURN
|
||||
networkingfacet40.hostName AS Host,
|
||||
softwarefacet20.group AS Group,
|
||||
softwarefacet20.name AS Name,
|
||||
softwarefacet20.version AS Version,
|
||||
statefacet20.value AS Status,
|
||||
eservice00.id AS ID
|
||||
networkingfacet40.hostName AS `Host`,
|
||||
softwarefacet20.group AS `Group`,
|
||||
softwarefacet20.name AS `Name`,
|
||||
softwarefacet20.version AS `Version`,
|
||||
statefacet20.value AS `Status`,
|
||||
eservice00.id AS `ID`
|
|
@ -1,37 +0,0 @@
|
|||
SELECT id AS ID,
|
||||
outE("IsIdentifiedBy").inV("SoftwareFacet").name[0] AS `Name`,
|
||||
outE("IsIdentifiedBy").inV("SoftwareFacet").group[0] AS `Group`,
|
||||
outE("IsIdentifiedBy").inV("SoftwareFacet").version[0] AS `Version`,
|
||||
outE("ConsistsOf").inV("StateFacet").value AS `Status`,
|
||||
inE("Activates").outV("HostingNode").outE("IsIdentifiedBy").inV("NetworkingFacet").hostName[0] AS `Host`
|
||||
FROM (
|
||||
TRAVERSE outV("EService") FROM (
|
||||
TRAVERSE inE("ConsistsOf") FROM (
|
||||
SELECT FROM (
|
||||
TRAVERSE inV("StateFacet") FROM (
|
||||
TRAVERSE outE("ConsistsOf") FROM (
|
||||
TRAVERSE outV("EService") FROM (
|
||||
TRAVERSE inE("IsIdentifiedBy") FROM (
|
||||
SELECT FROM (
|
||||
TRAVERSE inV("SoftwareFacet") FROM (
|
||||
TRAVERSE outE("IsIdentifiedBy") FROM (
|
||||
TRAVERSE inV("EService") FROM (
|
||||
TRAVERSE outE("Activates") FROM (
|
||||
TRAVERSE outV("HostingNode") FROM (
|
||||
TRAVERSE inE("IsIdentifiedBy") FROM (
|
||||
SELECT FROM NetworkingFacet
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
) WHERE @class INSTANCEOF "EService"
|
|
@ -1,66 +1,65 @@
|
|||
{
|
||||
"_projection" : {
|
||||
"type": "HostingNode",
|
||||
"_emit" : {
|
||||
"id" : "Id",
|
||||
},
|
||||
"metadata" : {
|
||||
"_emit" : {
|
||||
"lastUpdateTime" : "Last Update Time"
|
||||
}
|
||||
},
|
||||
"consistsOf": [
|
||||
{
|
||||
"type": "IsIdentifiedBy",
|
||||
"target": {
|
||||
"type": "NetworkingFacet",
|
||||
"_emit" : {
|
||||
"hostName" : "HostName"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "ConsistsOf",
|
||||
"target": {
|
||||
"type": "StateFacet",
|
||||
"_emit" : {
|
||||
"value" : "Status"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "HasPersistentMemory",
|
||||
"target": {
|
||||
"type": "MemoryFacet",
|
||||
"_concat" : {
|
||||
"values" : [
|
||||
{
|
||||
"_sub" : [
|
||||
"size",
|
||||
"used"
|
||||
]
|
||||
},
|
||||
"unit"
|
||||
],
|
||||
"separator" : " ",
|
||||
"as" : "HD Space Left"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "HasVolatileMemory",
|
||||
"target": {
|
||||
"type": "MemoryFacet",
|
||||
"_concat" : {
|
||||
"values" : [
|
||||
"size",
|
||||
"unit"
|
||||
],
|
||||
"separator" : " ",
|
||||
"as" : "Mem. Available."
|
||||
}
|
||||
"type": "HostingNode",
|
||||
"_emit" : {
|
||||
"id" : "ID"
|
||||
},
|
||||
"metadata" : {
|
||||
"_emit" : {
|
||||
"lastUpdateTime" : "Last Update Time"
|
||||
}
|
||||
},
|
||||
"consistsOf": [
|
||||
{
|
||||
"type": "IsIdentifiedBy",
|
||||
"target": {
|
||||
"type": "NetworkingFacet",
|
||||
"_emit" : {
|
||||
"hostName" : "HostName"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "ConsistsOf",
|
||||
"target": {
|
||||
"type": "StateFacet",
|
||||
"_emit" : {
|
||||
"value" : "Status"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "HasPersistentMemory",
|
||||
"target": {
|
||||
"type": "MemoryFacet",
|
||||
"_sum" : {
|
||||
"values" : [
|
||||
{
|
||||
"_minus" : [
|
||||
"size",
|
||||
"used"
|
||||
]
|
||||
},
|
||||
"unit"
|
||||
],
|
||||
"separator" : " ",
|
||||
"as" : "HD Space Left"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "HasVolatileMemory",
|
||||
"target": {
|
||||
"type": "MemoryFacet",
|
||||
"jvmMaxMemory" : null,
|
||||
"_sum" : {
|
||||
"values" : [
|
||||
"size",
|
||||
"unit"
|
||||
],
|
||||
"separator" : " ",
|
||||
"as" : "Mem. Available."
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
MATCH
|
||||
{class: HostingNode, as: hostingnode0, where: ($currentMatch['@class'] INSTANCEOF 'HostingNode')}
|
||||
|
||||
.outE('IsIdentifiedBy') { as: isidentifiedby00, where: ($currentMatch['@class'] INSTANCEOF 'IsIdentifiedBy')}
|
||||
.inV('NetworkingFacet') { as: networkingfacet000, where: ($currentMatch['@class'] INSTANCEOF 'NetworkingFacet')}
|
||||
.inE('IsIdentifiedBy') { where: ($matched.isidentifiedby00 == $currentMatch)}
|
||||
.outV('HostingNode') { where: ($matched.hostingnode0 == $currentMatch)}
|
||||
|
||||
.outE('ConsistsOf') { as: consistsof01, where: ($currentMatch['@class'] INSTANCEOF 'ConsistsOf')}
|
||||
.inV('StateFacet') { as: statefacet010, where: ($currentMatch['@class'] INSTANCEOF 'StateFacet')}
|
||||
.inE('ConsistsOf') { where: ($matched.consistsof01 == $currentMatch)}
|
||||
.outV('HostingNode') { where: ($matched.hostingnode0 == $currentMatch)}
|
||||
|
||||
.outE('HasPersistentMemory') { as: haspersistentmemory02, where: ($currentMatch['@class'] INSTANCEOF 'HasPersistentMemory')}
|
||||
.inV('MemoryFacet') { as: memoryfacet020, where: ($currentMatch['@class'] INSTANCEOF 'MemoryFacet')}
|
||||
.inE('HasPersistentMemory') { where: ($matched.haspersistentmemory02 == $currentMatch)}
|
||||
.outV('HostingNode') { where: ($matched.hostingnode0 == $currentMatch)}
|
||||
|
||||
.outE('HasVolatileMemory') { as: hasvolatilememory03, where: ($currentMatch['@class'] INSTANCEOF 'HasVolatileMemory')}
|
||||
.inV('MemoryFacet') { as: memoryfacet030, where: (($currentMatch['@class'] INSTANCEOF 'MemoryFacet') AND (jvmMaxMemory IS null))}
|
||||
.inE('HasVolatileMemory') { where: ($matched.hasvolatilememory03 == $currentMatch)}
|
||||
.outV('HostingNode') { where: ($matched.hostingnode0 == $currentMatch)}
|
||||
|
||||
RETURN
|
||||
networkingfacet000.hostName AS `HostName`,
|
||||
statefacet010.value AS `Status`,
|
||||
((memoryfacet020.size - memoryfacet020.used) + ' ' + memoryfacet020.unit) AS `HD Space Left`,
|
||||
(memoryfacet030.size + ' ' + memoryfacet030.unit) AS `Mem. Available.`,
|
||||
hostingnode0.id AS `ID`,
|
||||
hostingnode0.lastUpdateTime AS `Last Update Time`
|
Loading…
Reference in New Issue