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 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.
* It accepts idempotent query only..
*
* For query syntax please refer to
* * * https://orientdb.com/docs/last/SQL-Syntax.html
*
* * 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 constraint = new HashMap<>(); MultivaluedMap 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); } }