181 lines
6.5 KiB
Java
181 lines
6.5 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.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.DBUtility;
|
|
import org.gcube.informationsystem.utils.TypeUtility;
|
|
import org.slf4j.Logger;
|
|
import org.slf4j.LoggerFactory;
|
|
|
|
import com.arcadedb.database.Document;
|
|
import com.arcadedb.query.sql.executor.Result;
|
|
import com.arcadedb.query.sql.executor.ResultSet;
|
|
import com.arcadedb.remote.RemoteDatabase;
|
|
|
|
/**
|
|
* @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 RemoteDatabase database;
|
|
|
|
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 = TypeUtility.getTypeName(jsonQuery);
|
|
|
|
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 {
|
|
RemoteDatabase current = ContextUtility.getCurrentODatabaseDocumentFromThreadLocal();
|
|
database = null;
|
|
try {
|
|
SecurityContext securityContext = ContextUtility.getCurrentSecurityContext();
|
|
|
|
database = securityContext.getRemoteDatabase(PermissionMode.READER);
|
|
database.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));
|
|
|
|
ResultSet resultSet = database.command("sql", query, map);
|
|
|
|
ArrayNode arrayNode = objectMapper.createArrayNode();
|
|
|
|
while(resultSet.hasNext()) {
|
|
Result oResult = resultSet.next();
|
|
Document element = ElementManagementUtility.getElementFromOptional(oResult.getElement());
|
|
|
|
try {
|
|
JsonNode jsonNodeResult = null;
|
|
ElementManagement<?,?> erManagement = ElementManagementUtility.getERManagement(securityContext, database,
|
|
element);
|
|
|
|
// To support polymorphism we do not include ="TypeName" in query. So we need post processing filtering of results
|
|
|
|
String requestedType = entryPoint.getType();
|
|
String gotType = erManagement.getTypeName();
|
|
|
|
if(requestedType.compareTo(gotType)==0) {
|
|
erManagement.setAsEntryPoint();
|
|
jsonNodeResult = erManagement.serializeAsJsonNode();
|
|
arrayNode.add(jsonNodeResult);
|
|
continue;
|
|
}
|
|
|
|
CachedType<?> cachedType = TypesCache.getInstance().getCachedType(gotType);
|
|
if(cachedType.getSuperTypes().contains(requestedType)) {
|
|
erManagement.setAsEntryPoint();
|
|
jsonNodeResult = erManagement.serializeAsJsonNode();
|
|
arrayNode.add(jsonNodeResult);
|
|
continue;
|
|
}
|
|
|
|
|
|
} catch(ResourceRegistryException e) {
|
|
logger.error("Unable to correctly serialize {}. It will be excluded from results. {}",
|
|
element.toString(), DBUtility.SHOULD_NOT_OCCUR_ERROR_MESSAGE);
|
|
}
|
|
}
|
|
|
|
return objectMapper.writeValueAsString(arrayNode);
|
|
|
|
} catch(Exception e) {
|
|
throw new InvalidQueryException(e.getMessage());
|
|
} finally {
|
|
if(database != null) {
|
|
database.close();
|
|
}
|
|
// if(current!=null) {
|
|
// current.activateOnCurrentThread();
|
|
// }
|
|
}
|
|
}
|
|
|
|
}
|