resource-registry/src/main/java/org/gcube/informationsystem/resourceregistry/queries/templates/QueryTemplateManagement.java

326 lines
11 KiB
Java

package org.gcube.informationsystem.resourceregistry.queries.templates;
import java.util.HashMap;
import org.gcube.com.fasterxml.jackson.core.JsonProcessingException;
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.com.fasterxml.jackson.databind.node.ObjectNode;
import org.gcube.informationsystem.base.reference.AccessType;
import org.gcube.informationsystem.queries.templates.reference.entities.QueryTemplate;
import org.gcube.informationsystem.resourceregistry.api.exceptions.AlreadyPresentException;
import org.gcube.informationsystem.resourceregistry.api.exceptions.NotFoundException;
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.SchemaViolationException;
import org.gcube.informationsystem.resourceregistry.contexts.security.QueryTemplatesSecurityContext;
import org.gcube.informationsystem.resourceregistry.contexts.security.SecurityContext;
import org.gcube.informationsystem.resourceregistry.instances.base.ElementManagementUtility;
import org.gcube.informationsystem.resourceregistry.instances.base.entities.EntityElementManagement;
import org.gcube.informationsystem.resourceregistry.queries.json.JsonQuery;
import org.gcube.informationsystem.resourceregistry.utils.DBUtility;
import org.gcube.informationsystem.serialization.ElementMapper;
import org.gcube.informationsystem.types.reference.entities.EntityType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.orientechnologies.orient.core.db.document.ODatabaseDocument;
import com.orientechnologies.orient.core.record.OVertex;
import com.orientechnologies.orient.core.record.impl.ODocument;
import com.orientechnologies.orient.core.sql.executor.OResult;
import com.orientechnologies.orient.core.sql.executor.OResultSet;
/**
* @author Luca Frosini (ISTI - CNR)
*/
public class QueryTemplateManagement extends EntityElementManagement<QueryTemplate, EntityType> {
private static Logger logger = LoggerFactory.getLogger(QueryTemplateManagement.class);
protected String name;
protected JsonNode params;
public QueryTemplateManagement() {
super(AccessType.QUERY_TEMPLATE);
this.typeName = QueryTemplate.NAME;
}
public QueryTemplateManagement(ODatabaseDocument oDatabaseDocument) throws ResourceRegistryException {
this();
this.oDatabaseDocument = oDatabaseDocument;
getWorkingContext();
}
protected void checkERMatch() throws ResourceRegistryException {
getDocumentType();
}
protected void checkNameMatch() throws ResourceRegistryException {
if(jsonNode!=null && name!=null) {
String jsonName = jsonNode.get(QueryTemplate.NAME_PROPERTY).asText();
if(name.compareTo(jsonName)!=0) {
String error = String.format(
"Name provided in json (%s) differs from the one (%s) used to identify the %s instance",
jsonName, name, typeName);
throw new ResourceRegistryException(error);
}
}
}
public void setName(String name) throws ResourceRegistryException {
this.name = name;
checkNameMatch();
}
protected void checkJsonNode() throws ResourceRegistryException {
super.checkJsonNode();
checkNameMatch();
}
public String getName() {
if (name == null) {
if (element == null) {
if (jsonNode != null) {
name = jsonNode.get(QueryTemplate.NAME_PROPERTY).asText();
}
} else {
name = element.getProperty(QueryTemplate.NAME_PROPERTY);
}
}
return name;
}
@Override
protected SecurityContext getWorkingContext() throws ResourceRegistryException {
if (workingContext == null) {
workingContext = QueryTemplatesSecurityContext.getInstance();
}
return workingContext;
}
@Override
protected JsonNode createCompleteJsonNode() throws ResourceRegistryException {
try {
JsonNode queryTemplate = serializeSelfAsJsonNode();
ObjectMapper objectMapper = new ObjectMapper();
String templateString = element.getProperty(QueryTemplate.TEMPLATE_PROPERTY);
JsonNode templateJsonNode = objectMapper.readTree(templateString);
((ObjectNode) queryTemplate).replace(QueryTemplate.TEMPLATE_PROPERTY, templateJsonNode);
return queryTemplate;
}catch (ResourceRegistryException e) {
throw e;
}catch (Exception e) {
throw new ResourceRegistryException(e);
}
}
protected StringBuffer getSelectQuery() {
StringBuffer select = new StringBuffer();
select.append("SELECT FROM ");
select.append(QueryTemplate.NAME);
select.append(" WHERE ");
select.append(QueryTemplate.NAME_PROPERTY);
select.append(" = ");
select.append("\"");
select.append(getName());
select.append("\"");
return select;
}
protected void checkIfNameAlreadyExists() throws AlreadyPresentException {
StringBuffer select = getSelectQuery();
StringBuffer errorMessage = new StringBuffer();
errorMessage.append("A ");
errorMessage.append(QueryTemplate.NAME);
errorMessage.append(" with ");
errorMessage.append(this.getName());
errorMessage.append(" already exists");
logger.trace("Checking if {} -> {}", errorMessage, select);
OResultSet resultSet = oDatabaseDocument.command(select.toString(), new HashMap<>());
if (resultSet != null) {
try {
if(resultSet.hasNext()) {
throw new AlreadyPresentException(errorMessage.toString());
}
}finally {
resultSet.close();
}
}
}
protected void tryTemplate() throws Exception {
QueryTemplate queryTemplate = ElementMapper.unmarshal(QueryTemplate.class, jsonNode.toString());
JsonNode jsonQueryNode = queryTemplate.getJsonQuery();
JsonQuery jsonQuery = new JsonQuery();
jsonQuery.setJsonQuery(jsonQueryNode);
try {
jsonQuery.query();
}catch (ResourceRegistryException e) {
throw e;
}catch (Exception e) {
throw new ResourceRegistryException(e);
}
}
@Override
public OVertex retrieveElement() throws NotFoundException, ResourceRegistryException {
try {
StringBuffer select = getSelectQuery();
OResultSet resultSet = oDatabaseDocument.query(select.toString(), new HashMap<>());
if(resultSet == null || !resultSet.hasNext()) {
if(resultSet!=null) {
resultSet.close();
}
throw new NotFoundException("Error retrieving " + QueryTemplate.NAME + " with name " + getName());
}
OResult oResult = resultSet.next();
OVertex queryTemplate = ElementManagementUtility.getElementFromOptional(oResult.getVertex());
logger.trace("{} representing vertex is {}", QueryTemplate.NAME, DBUtility.getAsStringForLogging(queryTemplate));
if(resultSet.hasNext()) {
resultSet.close();
throw new NotFoundException("Found more than one " + QueryTemplate.NAME + " with name " + name + ". This should not occur, please contact the administrator");
}
resultSet.close();
return queryTemplate;
} catch(NotFoundException e) {
throw getSpecificNotFoundException(e);
} catch(ResourceRegistryException e) {
throw e;
} catch(Exception e) {
throw new ResourceRegistryException(e);
}
}
@Override
protected OVertex reallyCreate() throws AlreadyPresentException, InvalidQueryException, ResourceRegistryException {
try {
checkIfNameAlreadyExists();
tryTemplate();
createVertex();
return getElement();
} catch(ResourceRegistryException e) {
throw e;
} catch(Exception e) {
logger.trace("Error while creating {} for {} ({}) using {}", OVertex.class.getSimpleName(),
accessType.getName(), typeName, jsonNode, e);
throw new ResourceRegistryException("Error Creating " + typeName + " with " + jsonNode, e.getCause());
}
}
@Override
protected OVertex reallyUpdate() throws NotFoundException, ResourceRegistryException {
try {
tryTemplate();
OVertex queryTemplate = getElement();
queryTemplate = (OVertex) updateProperties(oClass, queryTemplate, jsonNode, ignoreKeys, ignoreStartWithKeys);
return getElement();
} catch(ResourceRegistryException e) {
throw e;
} catch(Exception e) {
logger.trace("Error while creating {} for {} ({}) using {}", OVertex.class.getSimpleName(),
accessType.getName(), typeName, jsonNode, e);
throw new ResourceRegistryException("Error Creating " + typeName + " with " + jsonNode, e.getCause());
}
}
@Override
protected void reallyDelete() throws NotFoundException, ResourceRegistryException {
logger.debug("Going to delete {} with name {}", accessType.getName(), name);
getElement().delete();
}
@Override
protected NotFoundException getSpecificNotFoundException(NotFoundException e) {
return new NotFoundException(e);
}
@Override
protected AlreadyPresentException getSpecificAlreadyPresentException(String message) {
return new AlreadyPresentException(message);
}
@Override
public String reallyGetAll(boolean polymorphic) throws ResourceRegistryException {
ObjectMapper objectMapper = new ObjectMapper();
ArrayNode arrayNode = objectMapper.createArrayNode();
Iterable<ODocument> iterable = oDatabaseDocument.browseClass(typeName, polymorphic);
for (ODocument vertex : iterable) {
QueryTemplateManagement queryTemplateManagement = new QueryTemplateManagement();
queryTemplateManagement.setElement((OVertex) vertex);
try {
JsonNode jsonObject = queryTemplateManagement.serializeAsJsonNode();
arrayNode.add(jsonObject);
} catch (ResourceRegistryException e) {
logger.error("Unable to correctly serialize {}. It will be excluded from results. {}",
vertex.toString(), DBUtility.SHOULD_NOT_OCCUR_ERROR_MESSAGE);
}
}
try {
return objectMapper.writeValueAsString(arrayNode);
} catch (JsonProcessingException e) {
throw new ResourceRegistryException(e);
}
}
public void setParams(String params) throws ResourceRegistryException {
try {
if(params!=null && params.compareTo("")!=0) {
ObjectMapper objectMapper = new ObjectMapper();
JsonNode jsonNode = objectMapper.readTree(params);
setParams(jsonNode);
}
} catch (ResourceRegistryException e) {
throw e;
} catch (Exception e) {
throw new ResourceRegistryException(e);
}
}
public void setParams(JsonNode params) throws ResourceRegistryException {
this.params = params;
}
/**
* Run the query after having replaced query parameter with the provided values
* @return the result as JSON string
* @throws Exception
*/
public String run() throws ResourceRegistryException {
try {
String read = read();
QueryTemplate queryTemplate = ElementMapper.unmarshal(QueryTemplate.class, read);
JsonNode query = null;
if(params!=null) {
query = queryTemplate.getJsonQuery(params);
}else {
query = queryTemplate.getJsonQuery();
}
JsonQuery jsonQuery = new JsonQuery();
jsonQuery.setJsonQuery(query);
return jsonQuery.query();
} catch (ResourceRegistryException e) {
throw e;
} catch (Exception e) {
throw new ResourceRegistryException(e);
}
}
public void sanityCheck() throws SchemaViolationException, ResourceRegistryException {
// No sanity check required
}
}