resource-registry/src/main/java/org/gcube/informationsystem/resourceregistry/rest/Access.java

431 lines
17 KiB
Java

package org.gcube.informationsystem.resourceregistry.rest;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import javax.ws.rs.DefaultValue;
import javax.ws.rs.GET;
import javax.ws.rs.HEAD;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import javax.ws.rs.core.UriInfo;
import org.gcube.common.authorization.library.provider.CalledMethodProvider;
import org.gcube.informationsystem.model.reference.entities.Resource;
import org.gcube.informationsystem.resourceregistry.ResourceInitializer;
import org.gcube.informationsystem.resourceregistry.api.exceptions.AvailableInAnotherContextException;
import org.gcube.informationsystem.resourceregistry.api.exceptions.NotFoundException;
import org.gcube.informationsystem.resourceregistry.api.exceptions.ResourceRegistryException;
import org.gcube.informationsystem.resourceregistry.api.exceptions.contexts.ContextNotFoundException;
import org.gcube.informationsystem.resourceregistry.api.exceptions.queries.InvalidQueryException;
import org.gcube.informationsystem.resourceregistry.api.exceptions.types.SchemaNotFoundException;
import org.gcube.informationsystem.resourceregistry.api.rest.AccessPath;
import org.gcube.informationsystem.resourceregistry.api.rest.ContextPath;
import org.gcube.informationsystem.resourceregistry.api.rest.InstancePath;
import org.gcube.informationsystem.resourceregistry.api.rest.TypePath;
import org.gcube.informationsystem.resourceregistry.contexts.ContextUtility;
import org.gcube.informationsystem.resourceregistry.contexts.entities.ContextManagement;
import org.gcube.informationsystem.resourceregistry.instances.base.ElementManagement;
import org.gcube.informationsystem.resourceregistry.instances.base.ElementManagementUtility;
import org.gcube.informationsystem.resourceregistry.instances.model.entities.ResourceManagement;
import org.gcube.informationsystem.resourceregistry.queries.Query;
import org.gcube.informationsystem.resourceregistry.queries.QueryImpl;
import org.gcube.informationsystem.resourceregistry.queries.json.JsonQuery;
import org.gcube.informationsystem.resourceregistry.requests.ServerRequestInfo;
import org.gcube.informationsystem.resourceregistry.types.TypeManagement;
import org.gcube.informationsystem.types.TypeMapper;
import org.gcube.informationsystem.types.reference.Type;
import com.arcadedb.graph.Vertex.DIRECTION;
/**
* @author Luca Frosini (ISTI - CNR)
*/
@Path(AccessPath.ACCESS_PATH_PART)
public class Access extends BaseRest {
public static final String RESOURCE_TYPE_PATH_PARAMETER = "RESOURCE_TYPE_NAME";
public static final String RELATION_TYPE_PATH_PARAMETER = "RELATION_TYPE_NAME";
public static final String REFERENCE_TYPE_PATH_PARAMETER = "REFERENCE_TYPE_NAME";
public Access() {
super();
}
/*
* e.g. GET /access/contexts
*/
@GET
@Path(AccessPath.CONTEXTS_PATH_PART)
@Produces(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8)
public String getAllContexts() throws ResourceRegistryException {
logger.info("Requested to read all {}s", org.gcube.informationsystem.contexts.reference.entities.Context.NAME);
CalledMethodProvider.instance.set("listContexts");
ServerRequestInfo serverRequestInfo = initRequestInfo();
serverRequestInfo.checkIncludeAllMetaQueryParameters();
ContextManagement contextManagement = new ContextManagement();
return contextManagement.all(false);
}
/*
* GET /access/contexts/{CONTEXT_UUID}
* e.g. GET /access/contexts/c0f314e7-2807-4241-a792-2a6c79ed4fd0
*/
@GET
@Path(AccessPath.CONTEXTS_PATH_PART + "/{" + InstancesManager.UUID_PATH_PARAMETER + "}")
@Produces(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8)
public String getContext(@PathParam(InstancesManager.UUID_PATH_PARAMETER) String uuid)
throws ContextNotFoundException, ResourceRegistryException {
if(uuid.compareTo(ContextPath.CURRENT_CONTEXT_PATH_PART)==0){
uuid = ContextUtility.getCurrentSecurityContext().getUUID().toString();
}
logger.info("Requested to read {} with id {} ", org.gcube.informationsystem.contexts.reference.entities.Context.NAME, uuid);
CalledMethodProvider.instance.set("readContext");
ServerRequestInfo serverRequestInfo = initRequestInfo();
serverRequestInfo.checkIncludeAllMetaQueryParameters();
ContextManagement contextManagement = new ContextManagement();
contextManagement.setUUID(UUID.fromString(uuid));
return contextManagement.readAsString();
}
/*
* GET /access/types/{TYPE_NAME}[?polymorphic=false]
* e.g. GET /access/types/ContactFacet?polymorphic=true
*/
@GET
@Path(AccessPath.TYPES_PATH_PART + "/{" + TypeManager.TYPE_PATH_PARAMETER + "}")
@Produces(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8)
public String getType(@PathParam(TypeManager.TYPE_PATH_PARAMETER) String type,
@QueryParam(TypePath.POLYMORPHIC_QUERY_PARAMETER) @DefaultValue("false") Boolean polymorphic)
throws SchemaNotFoundException, ResourceRegistryException {
logger.info("Requested Schema for type {}", type);
CalledMethodProvider.instance.set("readType");
ServerRequestInfo serverRequestInfo = initRequestInfo();
serverRequestInfo.checkIncludeAllMetaQueryParameters();
TypeManagement typeManagement = new TypeManagement();
typeManagement.setTypeName(type);
List<Type> types = typeManagement.read(polymorphic);
try {
return TypeMapper.serializeTypeDefinitions(types);
}catch (Exception e) {
throw new ResourceRegistryException(e);
}
}
/*
* GET /access/instances/{TYPE_NAME}[?polymorphic=true]
* e.g. GET /access/instances/ContactFacet?polymorphic=true
*
*/
@GET
@Path(AccessPath.INSTANCES_PATH_PART + "/{" + TypeManager.TYPE_PATH_PARAMETER + "}")
@Produces(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8)
public String getAllInstances(@PathParam(TypeManager.TYPE_PATH_PARAMETER) String type,
@QueryParam(InstancePath.POLYMORPHIC_QUERY_PARAMETER) @DefaultValue("true") Boolean polymorphic)
throws NotFoundException, ResourceRegistryException {
logger.info("Requested all {}instances of {}", polymorphic ? InstancePath.POLYMORPHIC_QUERY_PARAMETER + " " : "", type);
CalledMethodProvider.instance.set("listInstances");
ServerRequestInfo serverRequestInfo = initRequestInfo();
serverRequestInfo.checkAllQueryParameters();
ElementManagement<?,?> erManagement = ElementManagementUtility.getERManagement(type);
return erManagement.all(polymorphic);
}
/*
* HEAD /access/instances/{TYPE_NAME}/{UUID}
* e.g. HEAD /access/instances/ContactFacet/4023d5b2-8601-47a5-83ef-49ffcbfc7d86
*
*/
@HEAD
@Path(AccessPath.INSTANCES_PATH_PART + "/{" + TypeManager.TYPE_PATH_PARAMETER + "}" + "/{" + InstancesManager.UUID_PATH_PARAMETER + "}")
@Produces(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8)
public Response instanceExists(@PathParam(TypeManager.TYPE_PATH_PARAMETER) String type,
@PathParam(InstancesManager.UUID_PATH_PARAMETER) String uuid) throws NotFoundException, ResourceRegistryException {
logger.info("Requested to check if {} with id {} exists", type, uuid);
CalledMethodProvider.instance.set("existInstance");
ServerRequestInfo serverRequestInfo = initRequestInfo();
serverRequestInfo.checkQueryParameter(InstancePath.HIERARCHICAL_MODE_QUERY_PARAMETER);
ElementManagement<?,?> erManagement = ElementManagementUtility.getERManagement(type);
try {
erManagement.setUUID(UUID.fromString(uuid));
boolean found = erManagement.exists();
if(found) {
return Response.status(Status.NO_CONTENT).build();
} else {
// This code should never be reached due to exception management
// anyway adding it for safety reason
return Response.status(Status.NOT_FOUND).build();
}
} catch(NotFoundException e) {
return Response.status(Status.NOT_FOUND).build();
} catch(AvailableInAnotherContextException e) {
return Response.status(Status.FORBIDDEN).build();
} catch(ResourceRegistryException e) {
throw e;
}
}
/*
* GET /access/instances/{TYPE_NAME}/{UUID}
* e.g. GET /access/instances/ContactFacet/4023d5b2-8601-47a5-83ef-49ffcbfc7d86
*
*/
@GET
@Path(AccessPath.INSTANCES_PATH_PART + "/{" + TypeManager.TYPE_PATH_PARAMETER + "}" + "/{" + InstancesManager.UUID_PATH_PARAMETER + "}")
@Produces(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8)
public String getInstance(@PathParam(TypeManager.TYPE_PATH_PARAMETER) String type,
@PathParam(InstancesManager.UUID_PATH_PARAMETER) String uuid) throws NotFoundException, ResourceRegistryException {
logger.info("Requested to read {} with id {}", type, uuid);
CalledMethodProvider.instance.set("readInstance");
ServerRequestInfo serverRequestInfo = initRequestInfo();
serverRequestInfo.checkAllQueryParameters();
@SuppressWarnings("rawtypes")
ElementManagement erManagement = ElementManagementUtility.getERManagement(type);
erManagement.setElementType(type);
erManagement.setUUID(UUID.fromString(uuid));
return erManagement.read().toString();
}
/*
* GET /access/instances/{TYPE_NAME}/{UUID}/contexts
* e.g. GET /access/instances/ContactFacet/4023d5b2-8601-47a5-83ef-49ffcbfc7d86/contexts
*
*/
@GET
@Path(AccessPath.INSTANCES_PATH_PART + "/{" + TypeManager.TYPE_PATH_PARAMETER + "}" + "/{" + InstancesManager.UUID_PATH_PARAMETER + "}/" + AccessPath.CONTEXTS_PATH_PART)
@Produces(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8)
public String getInstanceContexts(@PathParam(TypeManager.TYPE_PATH_PARAMETER) String type,
@PathParam(InstancesManager.UUID_PATH_PARAMETER) String instanceId) throws NotFoundException, ResourceRegistryException {
logger.info("Requested to get contexts of {} with UUID {}", type, instanceId);
CalledMethodProvider.instance.set("getInstanceContexts");
ElementManagement<?,?> erManagement = ElementManagementUtility.getERManagement(type);
erManagement.setUUID(UUID.fromString(instanceId));
return erManagement.getContexts();
}
/**
* It includeSubtypes to query Entities and Relations in the current Context.<br />
* It accepts idempotent query only.. <br />
* <br />
* For query syntax please refer to<br />
*
* <a href="https://orientdb.com/docs/last/SQL-Syntax.html" target="_blank">
* https://orientdb.com/docs/last/SQL-Syntax.html </a> <br />
* <br />
*
* e.g. GET /access/query?q=SELECT FROM V
*
* @param query Defines the query to send to the backend.
* @param raw request a raw response (not a Element based response)
* @return The JSON representation of the result
* @throws InvalidQueryException if the query is invalid or not idempotent
*/
@GET
@Path(AccessPath.QUERY_PATH_PART)
@Produces(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8)
public String graphQuery(@QueryParam(AccessPath.Q_QUERY_PARAMETER) String query,
@QueryParam(AccessPath.RAW_QUERY_PARAMETER) @DefaultValue(AccessPath.RAW_QUERY_PARAMETER_DEFAULT_VALUE) Boolean raw)
throws InvalidQueryException {
logger.info("Requested query (Raw {}):\n{}", raw, query);
CalledMethodProvider.instance.set("graphQuery");
ServerRequestInfo serverRequestInfo = initRequestInfo();
if(raw) {
// TODO Check if the role allow to request raw data
serverRequestInfo.checkQueryParameter(InstancePath.HIERARCHICAL_MODE_QUERY_PARAMETER);
}else {
serverRequestInfo.checkAllQueryParameters();
}
Query queryManager = new QueryImpl();
return queryManager.query(query, raw);
}
/**
* POST /access/query
*
* Content Body example:
*
* {
* "": "EService",
* "consistsOf": [
* {
* "": "ConsistsOf",
* "propagationConstraint" : {
* "add": "propagate"
* },
* "target": {
* "": "StateFacet",
* "value": "down"
* }
* },
* {
* "": "IsIdentifiedBy",
* "target": {
* "": "SoftwareFacet",
* "name": "data-transfer-service",
* "group": "DataTransfer"
* }
* },
* {
* "": "ConsistsOf",
* "target": {
* "": "AccessPointFacet",
* "endpoint": "http://pc-frosini.isti.cnr.it:8080/data-transfer-service/gcube/service"
* }
* }
* ]
* }
*
* @param jsonQuery
* @return the result as JSON String
* @throws InvalidQueryException
* @throws ResourceRegistryException
*/
@POST
@Path(AccessPath.QUERY_PATH_PART)
public String jsonQuery(String jsonQuery) throws InvalidQueryException, ResourceRegistryException {
logger.info("Requested json query \n{}", jsonQuery);
CalledMethodProvider.instance.set("jsonQuery");
ServerRequestInfo serverRequestInfo = initRequestInfo();
serverRequestInfo.checkAllQueryParameters();
JsonQuery jsonQueryManager = new JsonQuery();
jsonQueryManager.setJsonQuery(jsonQuery);
return jsonQueryManager.query();
}
/*
* /access/query/{RESOURCE_TYPE_NAME}/{RELATION_TYPE_NAME}/{ENTITY_TYPE_NAME}[?_reference={REFERENCE_ENTITY_UUID}&_polymorphic=true&_direction=out]
*
* e.g.
* All the EService identified By a SoftwareFacet :
* GET /access/query/EService/isIdentifiedBy/SoftwareFacet?_polymorphic=true&_direction=out
*
* All the EService identified By the SoftwareFacet with UUID 7bc997c3-d005-40ff-b9ed-c4b6a35851f1 :
* GET /access/query/EService/isIdentifiedBy/SoftwareFacet?_reference=7bc997c3-d005-40ff-b9ed-c4b6a35851f1&_polymorphic=true&_direction=out
*
* All the Resources identified By a ContactFacet :
* GET /access/query/Resource/isIdentifiedBy/ContactFacet?_polymorphic=true&_direction=out
*
* All the Resources with a ContactFacet :
* /access/query/Resource/ConsistsOf/ContactFacet?_polymorphic=true&_direction=out
*
* All the Eservice having an incoming (IN) Hosts relation with an HostingNode (i.e. all smartgears services)
* GET /access/query/EService/Hosts/HostingNode?_polymorphic=true&_direction=in
*
* All the Eservice having an incoming (IN) Hosts relation (i.e. hosted by) the HostingNode with UUID
* 16032d09-3823-444e-a1ff-a67de4f350a
* * GET /access/query/EService/hosts/HostingNode?_reference=16032d09-3823-444e-a1ff-a67de4f350a8&_polymorphic=true&_direction=in
*
*/
@SuppressWarnings({"rawtypes"})
@GET
@Path(AccessPath.QUERY_PATH_PART + "/" + "{" + Access.RESOURCE_TYPE_PATH_PARAMETER + "}" + "/" + "{"
+ Access.RELATION_TYPE_PATH_PARAMETER + "}" + "/" + "{" + Access.REFERENCE_TYPE_PATH_PARAMETER + "}")
@Produces(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8)
public String getAllResourcesHavingFacet(@PathParam(Access.RESOURCE_TYPE_PATH_PARAMETER) String resourcetype,
@PathParam(Access.RELATION_TYPE_PATH_PARAMETER) String relationType,
@PathParam(Access.REFERENCE_TYPE_PATH_PARAMETER) String referenceType,
@QueryParam(AccessPath._REFERENCE_QUERY_PARAMETER) String reference,
@QueryParam(AccessPath._POLYMORPHIC_QUERY_PARAMETER) @DefaultValue("false") Boolean polymorphic,
@QueryParam(AccessPath._DIRECTION_QUERY_PARAMETER) @DefaultValue("out") String direction,
/*@QueryParam(AccessPath._INCLUDE_RELATION_PARAM) @DefaultValue("false") Boolean includeRelation,*/
@Context UriInfo uriInfo) throws ResourceRegistryException {
logger.info("Requested {} instances having a(n) {} ({}={}} with {} ({}={}). Request URI is {})", resourcetype, relationType,
AccessPath._DIRECTION_QUERY_PARAMETER, direction, referenceType, AccessPath._POLYMORPHIC_QUERY_PARAMETER, polymorphic, uriInfo.getRequestUri());
CalledMethodProvider.instance.set("query");
ServerRequestInfo serverRequestInfo = initRequestInfo();
serverRequestInfo.checkAllQueryParameters();
ElementManagement erManagement = ElementManagementUtility.getERManagement(resourcetype);
if(erManagement instanceof ResourceManagement) {
UUID refereceUUID = null;
DIRECTION directionEnum = DIRECTION.OUT;
Map<String,String> constraint = new HashMap<>();
MultivaluedMap<String,String> multivaluedMap = uriInfo.getQueryParameters();
for(String key : multivaluedMap.keySet()) {
switch (key) {
case AccessPath._POLYMORPHIC_QUERY_PARAMETER:
break;
case AccessPath._DIRECTION_QUERY_PARAMETER:
break;
case AccessPath._REFERENCE_QUERY_PARAMETER:
break;
/*
case AccessPath._INCLUDE_RELATION_PARAM:
break;
*/
case "gcube-token":
break;
case "gcube-scope":
break;
default:
constraint.put(key, multivaluedMap.getFirst(key));
break;
}
}
if(reference != null) {
try {
refereceUUID = UUID.fromString(reference);
} catch(Exception e) {
String error = String.format("%s is not a valid %s", reference, UUID.class.getSimpleName());
throw new InvalidQueryException(error);
}
}
try {
directionEnum = DIRECTION.valueOf(direction.toUpperCase());
} catch(Exception e) {
String error = String.format("%s is not a valid. Allowed values are %s", direction, DIRECTION.values());
throw new InvalidQueryException(error);
}
return ((ResourceManagement) erManagement).query(relationType, referenceType, refereceUUID, directionEnum,
polymorphic, constraint); /*, includeRelation*/
}
String error = String.format("%s is not a %s type", resourcetype, Resource.NAME);
throw new InvalidQueryException(error);
}
}