179 lines
6.6 KiB
Java
179 lines
6.6 KiB
Java
package org.gcube.informationsystem.resourceregistry.queries.json;
|
|
|
|
import java.io.IOException;
|
|
import java.util.HashMap;
|
|
import java.util.Map;
|
|
|
|
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;
|
|
import org.gcube.informationsystem.base.reference.AccessType;
|
|
import org.gcube.informationsystem.base.reference.Direction;
|
|
import org.gcube.informationsystem.base.reference.Element;
|
|
import org.gcube.informationsystem.resourceregistry.api.exceptions.ResourceRegistryException;
|
|
import org.gcube.informationsystem.resourceregistry.api.exceptions.queries.InvalidQueryException;
|
|
import org.gcube.informationsystem.resourceregistry.api.exceptions.types.SchemaException;
|
|
import org.gcube.informationsystem.resourceregistry.api.exceptions.types.SchemaNotFoundException;
|
|
import org.gcube.informationsystem.resourceregistry.contexts.ContextUtility;
|
|
import org.gcube.informationsystem.resourceregistry.contexts.security.SecurityContext;
|
|
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.queries.json.base.JsonQueryERElement;
|
|
import org.gcube.informationsystem.resourceregistry.queries.json.base.entities.JsonQueryFacet;
|
|
import org.gcube.informationsystem.resourceregistry.queries.json.base.entities.JsonQueryResource;
|
|
import org.gcube.informationsystem.resourceregistry.queries.json.base.relations.JsonQueryConsistsOf;
|
|
import org.gcube.informationsystem.resourceregistry.queries.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;
|
|
import org.slf4j.Logger;
|
|
import org.slf4j.LoggerFactory;
|
|
|
|
import com.orientechnologies.orient.core.db.document.ODatabaseDocument;
|
|
import com.orientechnologies.orient.core.record.OElement;
|
|
import com.orientechnologies.orient.core.sql.executor.OResult;
|
|
import com.orientechnologies.orient.core.sql.executor.OResultSet;
|
|
|
|
/**
|
|
* @author Luca Frosini (ISTI - CNR)
|
|
*/
|
|
public class JsonQuery {
|
|
|
|
private static Logger logger = LoggerFactory.getLogger(JsonQuery.class);
|
|
|
|
private static final Integer UNBOUNDED_LIMIT = -1;
|
|
|
|
protected ObjectMapper objectMapper;
|
|
protected JsonNode jsonQuery;
|
|
protected JsonQueryERElement entryPoint;
|
|
protected ODatabaseDocument oDatabaseDocument;
|
|
|
|
public JsonQuery() {
|
|
this.objectMapper = new ObjectMapper();
|
|
}
|
|
|
|
public void setJsonQuery(JsonNode jsonQuery) {
|
|
this.jsonQuery = jsonQuery;
|
|
}
|
|
|
|
public void setJsonQuery(String jsonQuery) throws InvalidQueryException {
|
|
try {
|
|
this.jsonQuery = objectMapper.readTree(jsonQuery);
|
|
} catch (IOException e) {
|
|
throw new InvalidQueryException(e);
|
|
}
|
|
|
|
}
|
|
|
|
public static JsonQueryERElement getJsonQueryERElement(JsonNode jsonQuery) throws SchemaNotFoundException, SchemaException, ResourceRegistryException {
|
|
String type = jsonQuery.get(Element.CLASS_PROPERTY).asText();
|
|
|
|
AccessType accessType = TypesCache.getInstance().getCachedType(type).getAccessType();
|
|
|
|
JsonQueryERElement jsonQueryERElement = null;
|
|
|
|
switch (accessType) {
|
|
case RESOURCE:
|
|
jsonQueryERElement = new JsonQueryResource(jsonQuery);
|
|
jsonQueryERElement.setDirection(Direction.OUT);
|
|
break;
|
|
|
|
case FACET:
|
|
jsonQueryERElement = new JsonQueryFacet(jsonQuery);
|
|
break;
|
|
|
|
case IS_RELATED_TO:
|
|
jsonQueryERElement = new JsonQueryIsRelatedTo(jsonQuery);
|
|
break;
|
|
|
|
case CONSISTS_OF:
|
|
jsonQueryERElement = new JsonQueryConsistsOf(jsonQuery);
|
|
break;
|
|
|
|
default:
|
|
throw new InvalidQueryException(String.format("%s is not querable", type.toString()));
|
|
}
|
|
|
|
return jsonQueryERElement;
|
|
}
|
|
|
|
|
|
public StringBuffer createQuery() throws SchemaException, InvalidQueryException, ResourceRegistryException {
|
|
entryPoint = getJsonQueryERElement(jsonQuery);
|
|
entryPoint.setEntryPoint(true);
|
|
return entryPoint.analize(new StringBuffer());
|
|
}
|
|
|
|
public String query() throws InvalidQueryException, ResourceRegistryException {
|
|
ODatabaseDocument current = ContextUtility.getCurrentODatabaseDocumentFromThreadLocal();
|
|
oDatabaseDocument = null;
|
|
try {
|
|
SecurityContext securityContext = ContextUtility.getCurrentSecurityContext();
|
|
|
|
oDatabaseDocument = securityContext.getDatabaseDocument(PermissionMode.READER);
|
|
oDatabaseDocument.begin();
|
|
|
|
StringBuffer stringBuffer = createQuery();
|
|
stringBuffer.append(" limit :limit");
|
|
|
|
Map<String, Object> map = new HashMap<>();
|
|
map.put("limit", JsonQuery.UNBOUNDED_LIMIT);
|
|
|
|
String query = stringBuffer.toString();
|
|
logger.trace("Going to execute the following query:\n{} \n from the JSONQuery\n{}", query, objectMapper.writeValueAsString(jsonQuery));
|
|
|
|
OResultSet resultSet = oDatabaseDocument.query(query, map);
|
|
|
|
ArrayNode arrayNode = objectMapper.createArrayNode();
|
|
|
|
while(resultSet.hasNext()) {
|
|
OResult oResult = resultSet.next();
|
|
OElement element = ElementManagementUtility.getElementFromOptional(oResult.getElement());
|
|
|
|
try {
|
|
JsonNode jsonNodeResult = null;
|
|
ElementManagement<?,?> erManagement = ElementManagementUtility.getERManagement(securityContext, oDatabaseDocument,
|
|
element);
|
|
|
|
// To support polymorphism we do not include @class="TypeName" in query. So we need post processing filtering of results
|
|
|
|
String requestedType = entryPoint.getType();
|
|
String gotType = erManagement.getTypeName();
|
|
|
|
if(requestedType.compareTo(gotType)==0) {
|
|
jsonNodeResult = erManagement.serializeAsJsonNode();
|
|
arrayNode.add(jsonNodeResult);
|
|
continue;
|
|
}
|
|
|
|
CachedType<?> cachedType = TypesCache.getInstance().getCachedType(gotType);
|
|
if(cachedType.getSuperTypes().contains(requestedType)) {
|
|
jsonNodeResult = erManagement.serializeAsJsonNode();
|
|
arrayNode.add(jsonNodeResult);
|
|
continue;
|
|
}
|
|
|
|
|
|
} catch(ResourceRegistryException e) {
|
|
logger.error("Unable to correctly serialize {}. It will be excluded from results. {}",
|
|
element.toString(), Utility.SHOULD_NOT_OCCUR_ERROR_MESSAGE);
|
|
}
|
|
}
|
|
|
|
return objectMapper.writeValueAsString(arrayNode);
|
|
|
|
} catch(Exception e) {
|
|
throw new InvalidQueryException(e.getMessage());
|
|
} finally {
|
|
if(oDatabaseDocument != null) {
|
|
oDatabaseDocument.close();
|
|
}
|
|
if(current!=null) {
|
|
current.activateOnCurrentThread();
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|