Refs #11288: Made resource-registry more RESTful
Task-Url: https://support.d4science.org/issues/11288 git-svn-id: https://svn.d4science.research-infrastructures.eu/gcube/trunk/information-system/resource-registry@168973 82a268e6-3cf1-43bd-a215-b396298e98cf
This commit is contained in:
parent
5a8812a5a0
commit
747b64fcfd
|
@ -59,9 +59,6 @@ public class Access {
|
||||||
|
|
||||||
private static Logger logger = LoggerFactory.getLogger(Access.class);
|
private static Logger logger = LoggerFactory.getLogger(Access.class);
|
||||||
|
|
||||||
public static final String ID_PATH_PARAM = "id";
|
|
||||||
public static final String TYPE_PATH_PARAM = "type";
|
|
||||||
|
|
||||||
public static void setCalledMethod(HTTPMETHOD httpMethod, List<String> pathValues, Map<String, String> map) {
|
public static void setCalledMethod(HTTPMETHOD httpMethod, List<String> pathValues, Map<String, String> map) {
|
||||||
StringWriter stringWriter = new StringWriter();
|
StringWriter stringWriter = new StringWriter();
|
||||||
stringWriter.append(httpMethod.name());
|
stringWriter.append(httpMethod.name());
|
||||||
|
@ -118,13 +115,14 @@ public class Access {
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* GET /access/contexts/{UUID}
|
* GET /access/contexts/{CONTEXT_UUID}
|
||||||
* e.g. GET /access/contexts/c0f314e7-2807-4241-a792-2a6c79ed4fd0
|
* e.g. GET /access/contexts/c0f314e7-2807-4241-a792-2a6c79ed4fd0
|
||||||
*/
|
*/
|
||||||
@GET
|
@GET
|
||||||
@Path(AccessPath.CONTEXTS_PATH_PART + "{" + ID_PATH_PARAM + "}")
|
@Path(AccessPath.CONTEXTS_PATH_PART + "{" + AccessPath.UUID_PATH_PARAM + "}")
|
||||||
|
@Consumes({MediaType.TEXT_PLAIN, ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8})
|
||||||
@Produces(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8)
|
@Produces(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8)
|
||||||
public String getContext(@PathParam(ID_PATH_PARAM) String uuid)
|
public String getContext(@PathParam(AccessPath.UUID_PATH_PARAM) String uuid)
|
||||||
throws ContextNotFoundException, ResourceRegistryException {
|
throws ContextNotFoundException, ResourceRegistryException {
|
||||||
ContextManagement contextManagement = new ContextManagement();
|
ContextManagement contextManagement = new ContextManagement();
|
||||||
logger.info("Requested to read {} with id {} ", org.gcube.informationsystem.model.entity.Context.NAME, uuid);
|
logger.info("Requested to read {} with id {} ", org.gcube.informationsystem.model.entity.Context.NAME, uuid);
|
||||||
|
@ -142,9 +140,10 @@ public class Access {
|
||||||
* e.g. GET /access/types/ContactFacet?polymorphic=true
|
* e.g. GET /access/types/ContactFacet?polymorphic=true
|
||||||
*/
|
*/
|
||||||
@GET
|
@GET
|
||||||
@Path(AccessPath.TYPES_PATH_PART + "/{" + TYPE_PATH_PARAM + "}")
|
@Path(AccessPath.TYPES_PATH_PART + "/{" + AccessPath.TYPE_PATH_PARAM + "}")
|
||||||
|
@Consumes({MediaType.TEXT_PLAIN, ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8})
|
||||||
@Produces(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8)
|
@Produces(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8)
|
||||||
public String getType(@PathParam(TYPE_PATH_PARAM) String type,
|
public String getType(@PathParam(AccessPath.TYPE_PATH_PARAM) String type,
|
||||||
@QueryParam(AccessPath.POLYMORPHIC_PARAM) @DefaultValue("false") Boolean polymorphic)
|
@QueryParam(AccessPath.POLYMORPHIC_PARAM) @DefaultValue("false") Boolean polymorphic)
|
||||||
throws SchemaNotFoundException, ResourceRegistryException {
|
throws SchemaNotFoundException, ResourceRegistryException {
|
||||||
logger.info("Requested Schema for type {}", type);
|
logger.info("Requested Schema for type {}", type);
|
||||||
|
@ -167,10 +166,10 @@ public class Access {
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@GET
|
@GET
|
||||||
@Path(AccessPath.INSTANCES_PATH_PART + "/{" + TYPE_PATH_PARAM + "}")
|
@Path(AccessPath.INSTANCES_PATH_PART + "/{" + AccessPath.TYPE_PATH_PARAM + "}")
|
||||||
@Consumes({MediaType.TEXT_PLAIN, ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8})
|
@Consumes({MediaType.TEXT_PLAIN, ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8})
|
||||||
@Produces(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8)
|
@Produces(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8)
|
||||||
public String getAllInstances(@PathParam(TYPE_PATH_PARAM) String type,
|
public String getAllInstances(@PathParam(AccessPath.TYPE_PATH_PARAM) String type,
|
||||||
@QueryParam(InstancePath.POLYMORPHIC_PARAM) @DefaultValue("true") Boolean polymorphic)
|
@QueryParam(InstancePath.POLYMORPHIC_PARAM) @DefaultValue("true") Boolean polymorphic)
|
||||||
throws NotFoundException, ResourceRegistryException {
|
throws NotFoundException, ResourceRegistryException {
|
||||||
|
|
||||||
|
@ -196,17 +195,17 @@ public class Access {
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@HEAD
|
@HEAD
|
||||||
@Path("/{" + TYPE_PATH_PARAM + "}" + "/{" + ID_PATH_PARAM + "}")
|
@Path("/{" + AccessPath.TYPE_PATH_PARAM + "}" + "/{" + AccessPath.UUID_PATH_PARAM + "}")
|
||||||
@Consumes({MediaType.TEXT_PLAIN, ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8})
|
@Consumes({MediaType.TEXT_PLAIN, ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8})
|
||||||
@Produces(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8)
|
@Produces(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8)
|
||||||
public Response instanceExists(@PathParam(TYPE_PATH_PARAM) String type, @PathParam(ID_PATH_PARAM) String uuid)
|
public Response instanceExists(@PathParam(AccessPath.TYPE_PATH_PARAM) String type, @PathParam(AccessPath.UUID_PATH_PARAM) String uuid)
|
||||||
throws NotFoundException, ResourceRegistryException {
|
throws NotFoundException, ResourceRegistryException {
|
||||||
|
|
||||||
logger.info("Requested to check if {} with id {} exists", type, uuid);
|
logger.info("Requested to check if {} with id {} exists", type, uuid);
|
||||||
List<String> pathValues = new ArrayList<>();
|
List<String> pathValues = new ArrayList<>();
|
||||||
pathValues.add(AccessPath.INSTANCES_PATH_PART);
|
pathValues.add(AccessPath.INSTANCES_PATH_PART);
|
||||||
pathValues.add(type);
|
pathValues.add(type);
|
||||||
pathValues.add("{" + ID_PATH_PARAM + "}");
|
pathValues.add("{" + AccessPath.UUID_PATH_PARAM + "}");
|
||||||
setCalledMethodLocal(HTTPMETHOD.HEAD, pathValues);
|
setCalledMethodLocal(HTTPMETHOD.HEAD, pathValues);
|
||||||
|
|
||||||
@SuppressWarnings("rawtypes")
|
@SuppressWarnings("rawtypes")
|
||||||
|
@ -237,16 +236,16 @@ public class Access {
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@GET
|
@GET
|
||||||
@Path("/{" + TYPE_PATH_PARAM + "}" + "/{" + ID_PATH_PARAM + "}")
|
@Path("/{" + AccessPath.TYPE_PATH_PARAM + "}" + "/{" + AccessPath.UUID_PATH_PARAM + "}")
|
||||||
@Consumes({MediaType.TEXT_PLAIN, ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8})
|
@Consumes({MediaType.TEXT_PLAIN, ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8})
|
||||||
@Produces(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8)
|
@Produces(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8)
|
||||||
public String getInstance(@PathParam(TYPE_PATH_PARAM) String type, @PathParam(ID_PATH_PARAM) String uuid)
|
public String getInstance(@PathParam(AccessPath.TYPE_PATH_PARAM) String type, @PathParam(AccessPath.UUID_PATH_PARAM) String uuid)
|
||||||
throws NotFoundException, ResourceRegistryException {
|
throws NotFoundException, ResourceRegistryException {
|
||||||
logger.info("Requested to read {} with id {}", type, uuid);
|
logger.info("Requested to read {} with id {}", type, uuid);
|
||||||
List<String> pathValues = new ArrayList<>();
|
List<String> pathValues = new ArrayList<>();
|
||||||
pathValues.add(AccessPath.INSTANCES_PATH_PART);
|
pathValues.add(AccessPath.INSTANCES_PATH_PART);
|
||||||
pathValues.add(type);
|
pathValues.add(type);
|
||||||
pathValues.add("{" + ID_PATH_PARAM + "}");
|
pathValues.add("{" + AccessPath.UUID_PATH_PARAM + "}");
|
||||||
setCalledMethodLocal(HTTPMETHOD.GET, pathValues);
|
setCalledMethodLocal(HTTPMETHOD.GET, pathValues);
|
||||||
|
|
||||||
@SuppressWarnings("rawtypes")
|
@SuppressWarnings("rawtypes")
|
||||||
|
@ -316,9 +315,9 @@ public class Access {
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings({"rawtypes"})
|
@SuppressWarnings({"rawtypes"})
|
||||||
@GET
|
@GET
|
||||||
@Path(AccessPath.INSTANCES_PATH_PART + "/" + "{" + TYPE_PATH_PARAM + "}")
|
@Path(AccessPath.INSTANCES_PATH_PART + "/" + "{" + AccessPath.TYPE_PATH_PARAM + "}")
|
||||||
@Produces(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8)
|
@Produces(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8)
|
||||||
public String getInstances(@PathParam(TYPE_PATH_PARAM) String type,
|
public String getInstances(@PathParam(AccessPath.TYPE_PATH_PARAM) String type,
|
||||||
@QueryParam(AccessPath.POLYMORPHIC_PARAM) @DefaultValue("false") Boolean polymorphic,
|
@QueryParam(AccessPath.POLYMORPHIC_PARAM) @DefaultValue("false") Boolean polymorphic,
|
||||||
@QueryParam(AccessPath.REFERENCE) String reference,
|
@QueryParam(AccessPath.REFERENCE) String reference,
|
||||||
@QueryParam(AccessPath.DIRECTION) @DefaultValue("both") String direction) throws ResourceRegistryException {
|
@QueryParam(AccessPath.DIRECTION) @DefaultValue("both") String direction) throws ResourceRegistryException {
|
||||||
|
@ -370,10 +369,10 @@ public class Access {
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings({"rawtypes"})
|
@SuppressWarnings({"rawtypes"})
|
||||||
@GET
|
@GET
|
||||||
@Path(AccessPath.RESOURCE_INSTANCES_PATH_PART + "/" + "{" + TYPE_PATH_PARAM + "}" + "/" + "{"
|
@Path(AccessPath.RESOURCE_INSTANCES_PATH_PART + "/" + "{" + AccessPath.TYPE_PATH_PARAM + "}" + "/" + "{"
|
||||||
+ AccessPath.RELATION_TYPE_PATH_PART + "}" + "/" + "{" + AccessPath.FACET_TYPE_PATH_PART + "}")
|
+ AccessPath.RELATION_TYPE_PATH_PART + "}" + "/" + "{" + AccessPath.FACET_TYPE_PATH_PART + "}")
|
||||||
@Produces(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8)
|
@Produces(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8)
|
||||||
public String getFilteredInstances(@PathParam(TYPE_PATH_PARAM) String type,
|
public String getFilteredInstances(@PathParam(AccessPath.TYPE_PATH_PARAM) String type,
|
||||||
@PathParam(AccessPath.RELATION_TYPE_PATH_PART) @DefaultValue(ConsistsOf.NAME) String relationType,
|
@PathParam(AccessPath.RELATION_TYPE_PATH_PART) @DefaultValue(ConsistsOf.NAME) String relationType,
|
||||||
@PathParam(AccessPath.FACET_TYPE_PATH_PART) @DefaultValue(Facet.NAME) String facetType,
|
@PathParam(AccessPath.FACET_TYPE_PATH_PART) @DefaultValue(Facet.NAME) String facetType,
|
||||||
@QueryParam(AccessPath.POLYMORPHIC_PARAM) @DefaultValue("false") Boolean polymorphic,
|
@QueryParam(AccessPath.POLYMORPHIC_PARAM) @DefaultValue("false") Boolean polymorphic,
|
||||||
|
|
|
@ -4,18 +4,21 @@ import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import javax.ws.rs.Consumes;
|
||||||
import javax.ws.rs.DELETE;
|
import javax.ws.rs.DELETE;
|
||||||
import javax.ws.rs.GET;
|
import javax.ws.rs.GET;
|
||||||
import javax.ws.rs.PUT;
|
import javax.ws.rs.PUT;
|
||||||
import javax.ws.rs.Path;
|
import javax.ws.rs.Path;
|
||||||
import javax.ws.rs.PathParam;
|
import javax.ws.rs.PathParam;
|
||||||
import javax.ws.rs.Produces;
|
import javax.ws.rs.Produces;
|
||||||
|
import javax.ws.rs.core.MediaType;
|
||||||
|
|
||||||
import org.gcube.informationsystem.model.entity.Context;
|
import org.gcube.informationsystem.model.entity.Context;
|
||||||
import org.gcube.informationsystem.resourceregistry.ResourceInitializer;
|
import org.gcube.informationsystem.resourceregistry.ResourceInitializer;
|
||||||
import org.gcube.informationsystem.resourceregistry.api.exceptions.NotFoundException;
|
import org.gcube.informationsystem.resourceregistry.api.exceptions.NotFoundException;
|
||||||
import org.gcube.informationsystem.resourceregistry.api.exceptions.ResourceRegistryException;
|
import org.gcube.informationsystem.resourceregistry.api.exceptions.ResourceRegistryException;
|
||||||
import org.gcube.informationsystem.resourceregistry.api.exceptions.context.ContextNotFoundException;
|
import org.gcube.informationsystem.resourceregistry.api.exceptions.context.ContextNotFoundException;
|
||||||
|
import org.gcube.informationsystem.resourceregistry.api.rest.AccessPath;
|
||||||
import org.gcube.informationsystem.resourceregistry.api.rest.ContextPath;
|
import org.gcube.informationsystem.resourceregistry.api.rest.ContextPath;
|
||||||
import org.gcube.informationsystem.resourceregistry.api.rest.httputils.HTTPCall.HTTPMETHOD;
|
import org.gcube.informationsystem.resourceregistry.api.rest.httputils.HTTPCall.HTTPMETHOD;
|
||||||
import org.gcube.informationsystem.resourceregistry.context.ContextManagement;
|
import org.gcube.informationsystem.resourceregistry.context.ContextManagement;
|
||||||
|
@ -33,8 +36,6 @@ public class ContextManager {
|
||||||
*/
|
*/
|
||||||
private static Logger logger = LoggerFactory.getLogger(ContextManager.class);
|
private static Logger logger = LoggerFactory.getLogger(ContextManager.class);
|
||||||
|
|
||||||
public static final String ID_PATH_PARAM = "id";
|
|
||||||
|
|
||||||
protected void setCalledMethod(HTTPMETHOD httpMethod) {
|
protected void setCalledMethod(HTTPMETHOD httpMethod) {
|
||||||
setCalledMethod(httpMethod, null);
|
setCalledMethod(httpMethod, null);
|
||||||
}
|
}
|
||||||
|
@ -53,6 +54,7 @@ public class ContextManager {
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@GET
|
@GET
|
||||||
|
@Consumes({MediaType.TEXT_PLAIN, ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8})
|
||||||
@Produces(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8)
|
@Produces(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8)
|
||||||
public String all() throws ContextNotFoundException, ResourceRegistryException {
|
public String all() throws ContextNotFoundException, ResourceRegistryException {
|
||||||
logger.info("Requested to read all {}s", Context.NAME);
|
logger.info("Requested to read all {}s", Context.NAME);
|
||||||
|
@ -68,9 +70,10 @@ public class ContextManager {
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@GET
|
@GET
|
||||||
@Path("{" + ID_PATH_PARAM + "}")
|
@Path("{" + AccessPath.CONTEXT_UUID_PATH_PARAM + "}")
|
||||||
|
@Consumes({MediaType.TEXT_PLAIN, ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8})
|
||||||
@Produces(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8)
|
@Produces(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8)
|
||||||
public String read(@PathParam(ID_PATH_PARAM) String uuid)
|
public String read(@PathParam(AccessPath.CONTEXT_UUID_PATH_PARAM) String uuid)
|
||||||
throws ContextNotFoundException, ResourceRegistryException {
|
throws ContextNotFoundException, ResourceRegistryException {
|
||||||
logger.info("Requested to read {} with id {} ", Context.NAME, uuid);
|
logger.info("Requested to read {} with id {} ", Context.NAME, uuid);
|
||||||
setCalledMethod(HTTPMETHOD.GET, uuid);
|
setCalledMethod(HTTPMETHOD.GET, uuid);
|
||||||
|
@ -88,9 +91,11 @@ public class ContextManager {
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@PUT
|
@PUT
|
||||||
@Path("{" + ID_PATH_PARAM + "}")
|
@Path("{" + AccessPath.CONTEXT_UUID_PATH_PARAM + "}")
|
||||||
|
@Consumes({MediaType.TEXT_PLAIN, ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8})
|
||||||
@Produces(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8)
|
@Produces(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8)
|
||||||
public String updateCreate(@PathParam(ID_PATH_PARAM) String uuid, String json) throws ResourceRegistryException {
|
public String updateCreate(@PathParam(AccessPath.CONTEXT_UUID_PATH_PARAM) String uuid, String json)
|
||||||
|
throws ResourceRegistryException {
|
||||||
logger.info("Requested to update/create {} with json {} ", Context.NAME, json);
|
logger.info("Requested to update/create {} with json {} ", Context.NAME, json);
|
||||||
setCalledMethod(HTTPMETHOD.PUT, uuid);
|
setCalledMethod(HTTPMETHOD.PUT, uuid);
|
||||||
|
|
||||||
|
@ -117,8 +122,9 @@ public class ContextManager {
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@DELETE
|
@DELETE
|
||||||
@Path("{" + ID_PATH_PARAM + "}")
|
@Consumes({MediaType.TEXT_PLAIN, ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8})
|
||||||
public boolean delete(@PathParam(ID_PATH_PARAM) String uuid)
|
@Path("{" + AccessPath.CONTEXT_UUID_PATH_PARAM + "}")
|
||||||
|
public boolean delete(@PathParam(AccessPath.CONTEXT_UUID_PATH_PARAM) String uuid)
|
||||||
throws ContextNotFoundException, ResourceRegistryException {
|
throws ContextNotFoundException, ResourceRegistryException {
|
||||||
logger.info("Requested to delete {} with id {} ", Context.NAME, uuid);
|
logger.info("Requested to delete {} with id {} ", Context.NAME, uuid);
|
||||||
setCalledMethod(HTTPMETHOD.DELETE, uuid);
|
setCalledMethod(HTTPMETHOD.DELETE, uuid);
|
||||||
|
|
|
@ -24,6 +24,7 @@ import org.gcube.informationsystem.resourceregistry.ResourceInitializer;
|
||||||
import org.gcube.informationsystem.resourceregistry.api.exceptions.AvailableInAnotherContextException;
|
import org.gcube.informationsystem.resourceregistry.api.exceptions.AvailableInAnotherContextException;
|
||||||
import org.gcube.informationsystem.resourceregistry.api.exceptions.NotFoundException;
|
import org.gcube.informationsystem.resourceregistry.api.exceptions.NotFoundException;
|
||||||
import org.gcube.informationsystem.resourceregistry.api.exceptions.ResourceRegistryException;
|
import org.gcube.informationsystem.resourceregistry.api.exceptions.ResourceRegistryException;
|
||||||
|
import org.gcube.informationsystem.resourceregistry.api.rest.AccessPath;
|
||||||
import org.gcube.informationsystem.resourceregistry.api.rest.InstancePath;
|
import org.gcube.informationsystem.resourceregistry.api.rest.InstancePath;
|
||||||
import org.gcube.informationsystem.resourceregistry.api.rest.httputils.HTTPCall.HTTPMETHOD;
|
import org.gcube.informationsystem.resourceregistry.api.rest.httputils.HTTPCall.HTTPMETHOD;
|
||||||
import org.gcube.informationsystem.resourceregistry.er.ERManagement;
|
import org.gcube.informationsystem.resourceregistry.er.ERManagement;
|
||||||
|
@ -39,10 +40,7 @@ public class InstancesManager {
|
||||||
|
|
||||||
private static Logger logger = LoggerFactory.getLogger(InstancesManager.class);
|
private static Logger logger = LoggerFactory.getLogger(InstancesManager.class);
|
||||||
|
|
||||||
public static final String ID_PATH_PARAM = "id";
|
protected void setCalledMethod(HTTPMETHOD httpMethod, String type, Map<String,String> map) {
|
||||||
public static final String TYPE_PATH_PARAM = "type";
|
|
||||||
|
|
||||||
protected void setCalledMethod(HTTPMETHOD httpMethod, String type, Map<String, String> map) {
|
|
||||||
setCalledMethod(httpMethod, type, false, map);
|
setCalledMethod(httpMethod, type, false, map);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,12 +48,12 @@ public class InstancesManager {
|
||||||
setCalledMethod(httpMethod, type, uuid, null);
|
setCalledMethod(httpMethod, type, uuid, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void setCalledMethod(HTTPMETHOD httpMethod, String type, boolean uuid, Map<String, String> map) {
|
protected void setCalledMethod(HTTPMETHOD httpMethod, String type, boolean uuid, Map<String,String> map) {
|
||||||
List<String> list = new ArrayList<>();
|
List<String> list = new ArrayList<>();
|
||||||
list.add(InstancePath.INSTANCES_PATH_PART);
|
list.add(InstancePath.INSTANCES_PATH_PART);
|
||||||
list.add(type);
|
list.add(type);
|
||||||
if(uuid) {
|
if(uuid) {
|
||||||
list.add("{" + ID_PATH_PARAM + "}");
|
list.add("{" + AccessPath.UUID_PATH_PARAM + "}");
|
||||||
}
|
}
|
||||||
Access.setCalledMethod(httpMethod, list, map);
|
Access.setCalledMethod(httpMethod, list, map);
|
||||||
}
|
}
|
||||||
|
@ -66,14 +64,14 @@ public class InstancesManager {
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@GET
|
@GET
|
||||||
@Path("/{" + TYPE_PATH_PARAM + "}")
|
@Path("/{" + AccessPath.TYPE_PATH_PARAM + "}")
|
||||||
@Consumes({MediaType.TEXT_PLAIN, ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8})
|
@Consumes({MediaType.TEXT_PLAIN, ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8})
|
||||||
@Produces(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8)
|
@Produces(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8)
|
||||||
public String readAll(@PathParam(TYPE_PATH_PARAM) String type,
|
public String readAll(@PathParam(AccessPath.TYPE_PATH_PARAM) String type,
|
||||||
@QueryParam(InstancePath.POLYMORPHIC_PARAM) @DefaultValue("true") Boolean polymorphic)
|
@QueryParam(InstancePath.POLYMORPHIC_PARAM) @DefaultValue("true") Boolean polymorphic)
|
||||||
throws NotFoundException, ResourceRegistryException {
|
throws NotFoundException, ResourceRegistryException {
|
||||||
logger.info("Requested all {}instances of {}", polymorphic ? InstancePath.POLYMORPHIC_PARAM + " ": "", type);
|
logger.info("Requested all {}instances of {}", polymorphic ? InstancePath.POLYMORPHIC_PARAM + " " : "", type);
|
||||||
Map<String, String> map = new HashMap<String, String>();
|
Map<String,String> map = new HashMap<String,String>();
|
||||||
map.put(InstancePath.POLYMORPHIC_PARAM, polymorphic.toString());
|
map.put(InstancePath.POLYMORPHIC_PARAM, polymorphic.toString());
|
||||||
setCalledMethod(HTTPMETHOD.GET, type, map);
|
setCalledMethod(HTTPMETHOD.GET, type, map);
|
||||||
|
|
||||||
|
@ -88,11 +86,11 @@ public class InstancesManager {
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@HEAD
|
@HEAD
|
||||||
@Path("/{" + TYPE_PATH_PARAM + "}" + "/{" + ID_PATH_PARAM + "}")
|
@Path("/{" + AccessPath.TYPE_PATH_PARAM + "}" + "/{" + AccessPath.UUID_PATH_PARAM + "}")
|
||||||
@Consumes({MediaType.TEXT_PLAIN, ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8})
|
@Consumes({MediaType.TEXT_PLAIN, ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8})
|
||||||
@Produces(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8)
|
@Produces(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8)
|
||||||
public Response exists(@PathParam(TYPE_PATH_PARAM) String type, @PathParam(ID_PATH_PARAM) String uuid)
|
public Response exists(@PathParam(AccessPath.TYPE_PATH_PARAM) String type,
|
||||||
throws NotFoundException, ResourceRegistryException {
|
@PathParam(AccessPath.UUID_PATH_PARAM) String uuid) throws NotFoundException, ResourceRegistryException {
|
||||||
logger.info("Requested to check if {} with id {} exists", type, uuid);
|
logger.info("Requested to check if {} with id {} exists", type, uuid);
|
||||||
setCalledMethod(HTTPMETHOD.HEAD, type, true);
|
setCalledMethod(HTTPMETHOD.HEAD, type, true);
|
||||||
|
|
||||||
|
@ -124,11 +122,11 @@ public class InstancesManager {
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@GET
|
@GET
|
||||||
@Path("/{" + TYPE_PATH_PARAM + "}" + "/{" + ID_PATH_PARAM + "}")
|
@Path("/{" + AccessPath.TYPE_PATH_PARAM + "}" + "/{" + AccessPath.UUID_PATH_PARAM + "}")
|
||||||
@Consumes({MediaType.TEXT_PLAIN, ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8})
|
@Consumes({MediaType.TEXT_PLAIN, ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8})
|
||||||
@Produces(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8)
|
@Produces(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8)
|
||||||
public String read(@PathParam(TYPE_PATH_PARAM) String type, @PathParam(ID_PATH_PARAM) String uuid)
|
public String read(@PathParam(AccessPath.TYPE_PATH_PARAM) String type,
|
||||||
throws NotFoundException, ResourceRegistryException {
|
@PathParam(AccessPath.UUID_PATH_PARAM) String uuid) throws NotFoundException, ResourceRegistryException {
|
||||||
logger.info("Requested to read {} with id {}", type, uuid);
|
logger.info("Requested to read {} with id {}", type, uuid);
|
||||||
setCalledMethod(HTTPMETHOD.GET, type, true);
|
setCalledMethod(HTTPMETHOD.GET, type, true);
|
||||||
|
|
||||||
|
@ -148,11 +146,11 @@ public class InstancesManager {
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@PUT
|
@PUT
|
||||||
@Path("/{" + TYPE_PATH_PARAM + "}" + "/{" + ID_PATH_PARAM + "}")
|
@Path("/{" + AccessPath.TYPE_PATH_PARAM + "}" + "/{" + AccessPath.UUID_PATH_PARAM + "}")
|
||||||
@Consumes({MediaType.TEXT_PLAIN, ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8})
|
@Consumes({MediaType.TEXT_PLAIN, ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8})
|
||||||
@Produces(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8)
|
@Produces(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8)
|
||||||
public String updateOrCreate(@PathParam(TYPE_PATH_PARAM) String type, @PathParam(ID_PATH_PARAM) String uuid, String json)
|
public String updateOrCreate(@PathParam(AccessPath.TYPE_PATH_PARAM) String type,
|
||||||
throws ResourceRegistryException {
|
@PathParam(AccessPath.UUID_PATH_PARAM) String uuid, String json) throws ResourceRegistryException {
|
||||||
logger.info("Requested to update/create {} with id {}", type, uuid);
|
logger.info("Requested to update/create {} with id {}", type, uuid);
|
||||||
logger.trace("Requested to update/create {} with id {} with json {}", type, uuid, json);
|
logger.trace("Requested to update/create {} with id {} with json {}", type, uuid, json);
|
||||||
setCalledMethod(HTTPMETHOD.PUT, type, true);
|
setCalledMethod(HTTPMETHOD.PUT, type, true);
|
||||||
|
@ -184,9 +182,9 @@ public class InstancesManager {
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@DELETE
|
@DELETE
|
||||||
@Path("/{" + TYPE_PATH_PARAM + "}" + "/{" + ID_PATH_PARAM + "}")
|
@Path("/{" + AccessPath.TYPE_PATH_PARAM + "}" + "/{" + AccessPath.UUID_PATH_PARAM + "}")
|
||||||
public boolean delete(@PathParam(TYPE_PATH_PARAM) String type, @PathParam(ID_PATH_PARAM) String uuid)
|
public boolean delete(@PathParam(AccessPath.TYPE_PATH_PARAM) String type,
|
||||||
throws ResourceRegistryException {
|
@PathParam(AccessPath.UUID_PATH_PARAM) String uuid) throws ResourceRegistryException {
|
||||||
logger.info("Requested to delete {} with id {}", type, uuid);
|
logger.info("Requested to delete {} with id {}", type, uuid);
|
||||||
setCalledMethod(HTTPMETHOD.DELETE, type, true);
|
setCalledMethod(HTTPMETHOD.DELETE, type, true);
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,7 @@ import org.gcube.informationsystem.resourceregistry.ResourceInitializer;
|
||||||
import org.gcube.informationsystem.resourceregistry.api.exceptions.ResourceRegistryException;
|
import org.gcube.informationsystem.resourceregistry.api.exceptions.ResourceRegistryException;
|
||||||
import org.gcube.informationsystem.resourceregistry.api.exceptions.schema.SchemaException;
|
import org.gcube.informationsystem.resourceregistry.api.exceptions.schema.SchemaException;
|
||||||
import org.gcube.informationsystem.resourceregistry.api.exceptions.schema.SchemaNotFoundException;
|
import org.gcube.informationsystem.resourceregistry.api.exceptions.schema.SchemaNotFoundException;
|
||||||
|
import org.gcube.informationsystem.resourceregistry.api.rest.AccessPath;
|
||||||
import org.gcube.informationsystem.resourceregistry.api.rest.InstancePath;
|
import org.gcube.informationsystem.resourceregistry.api.rest.InstancePath;
|
||||||
import org.gcube.informationsystem.resourceregistry.api.rest.TypePath;
|
import org.gcube.informationsystem.resourceregistry.api.rest.TypePath;
|
||||||
import org.gcube.informationsystem.resourceregistry.api.rest.httputils.HTTPCall.HTTPMETHOD;
|
import org.gcube.informationsystem.resourceregistry.api.rest.httputils.HTTPCall.HTTPMETHOD;
|
||||||
|
@ -39,8 +40,6 @@ public class SchemaManager {
|
||||||
|
|
||||||
private static Logger logger = LoggerFactory.getLogger(SchemaManager.class);
|
private static Logger logger = LoggerFactory.getLogger(SchemaManager.class);
|
||||||
|
|
||||||
public static final String TYPE_NAME_PATH_PARAM = "typeName";
|
|
||||||
|
|
||||||
protected void setCalledMethod(HTTPMETHOD httpMethod, String type) {
|
protected void setCalledMethod(HTTPMETHOD httpMethod, String type) {
|
||||||
setCalledMethod(httpMethod, type, null);
|
setCalledMethod(httpMethod, type, null);
|
||||||
}
|
}
|
||||||
|
@ -67,10 +66,10 @@ public class SchemaManager {
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@PUT
|
@PUT
|
||||||
@Path("{" + TYPE_NAME_PATH_PARAM + "}")
|
@Path("{" + AccessPath.TYPE_PATH_PARAM + "}")
|
||||||
@Consumes({MediaType.TEXT_PLAIN, ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8})
|
@Consumes({MediaType.TEXT_PLAIN, ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8})
|
||||||
@Produces(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8)
|
@Produces(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8)
|
||||||
public Response create(@PathParam(TYPE_NAME_PATH_PARAM) String type, String json)
|
public Response create(@PathParam(AccessPath.TYPE_PATH_PARAM) String type, String json)
|
||||||
throws SchemaException, ResourceRegistryException {
|
throws SchemaException, ResourceRegistryException {
|
||||||
logger.info("Requested {} creation with schema {}", type, json);
|
logger.info("Requested {} creation with schema {}", type, json);
|
||||||
setCalledMethod(HTTPMETHOD.PUT, type);
|
setCalledMethod(HTTPMETHOD.PUT, type);
|
||||||
|
@ -96,9 +95,9 @@ public class SchemaManager {
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@GET
|
@GET
|
||||||
@Path("{" + TYPE_NAME_PATH_PARAM + "}")
|
@Path("{" + AccessPath.TYPE_PATH_PARAM + "}")
|
||||||
@Produces(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8)
|
@Produces(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8)
|
||||||
public String read(@PathParam(TYPE_NAME_PATH_PARAM) String type,
|
public String read(@PathParam(AccessPath.TYPE_PATH_PARAM) String type,
|
||||||
@QueryParam(TypePath.POLYMORPHIC_PARAM) @DefaultValue("false") Boolean polymorphic)
|
@QueryParam(TypePath.POLYMORPHIC_PARAM) @DefaultValue("false") Boolean polymorphic)
|
||||||
throws SchemaNotFoundException, ResourceRegistryException {
|
throws SchemaNotFoundException, ResourceRegistryException {
|
||||||
logger.info("Requested Schema for type {}", type);
|
logger.info("Requested Schema for type {}", type);
|
||||||
|
|
|
@ -1,18 +1,25 @@
|
||||||
package org.gcube.informationsystem.resourceregistry.rest;
|
package org.gcube.informationsystem.resourceregistry.rest;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import javax.ws.rs.Consumes;
|
||||||
import javax.ws.rs.DELETE;
|
import javax.ws.rs.DELETE;
|
||||||
import javax.ws.rs.PUT;
|
import javax.ws.rs.PUT;
|
||||||
import javax.ws.rs.Path;
|
import javax.ws.rs.Path;
|
||||||
import javax.ws.rs.PathParam;
|
import javax.ws.rs.PathParam;
|
||||||
|
import javax.ws.rs.Produces;
|
||||||
|
import javax.ws.rs.core.MediaType;
|
||||||
|
|
||||||
import org.gcube.common.authorization.library.provider.CalledMethodProvider;
|
|
||||||
import org.gcube.informationsystem.model.entity.Context;
|
import org.gcube.informationsystem.model.entity.Context;
|
||||||
|
import org.gcube.informationsystem.resourceregistry.ResourceInitializer;
|
||||||
import org.gcube.informationsystem.resourceregistry.api.exceptions.ResourceRegistryException;
|
import org.gcube.informationsystem.resourceregistry.api.exceptions.ResourceRegistryException;
|
||||||
import org.gcube.informationsystem.resourceregistry.api.exceptions.context.ContextNotFoundException;
|
import org.gcube.informationsystem.resourceregistry.api.exceptions.context.ContextNotFoundException;
|
||||||
import org.gcube.informationsystem.resourceregistry.api.exceptions.entity.resource.ResourceNotFoundException;
|
import org.gcube.informationsystem.resourceregistry.api.exceptions.entity.resource.ResourceNotFoundException;
|
||||||
|
import org.gcube.informationsystem.resourceregistry.api.rest.AccessPath;
|
||||||
import org.gcube.informationsystem.resourceregistry.api.rest.SharingPath;
|
import org.gcube.informationsystem.resourceregistry.api.rest.SharingPath;
|
||||||
|
import org.gcube.informationsystem.resourceregistry.api.rest.httputils.HTTPCall.HTTPMETHOD;
|
||||||
import org.gcube.informationsystem.resourceregistry.er.ERManagement;
|
import org.gcube.informationsystem.resourceregistry.er.ERManagement;
|
||||||
import org.gcube.informationsystem.resourceregistry.er.ERManagementUtility;
|
import org.gcube.informationsystem.resourceregistry.er.ERManagementUtility;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
@ -23,11 +30,17 @@ public class SharingManagement {
|
||||||
|
|
||||||
private static Logger logger = LoggerFactory.getLogger(SharingManagement.class);
|
private static Logger logger = LoggerFactory.getLogger(SharingManagement.class);
|
||||||
|
|
||||||
public static final String CONTEXT_ID_PATH_PARAM = "contextId";
|
protected void setCalledMethod(HTTPMETHOD httpMethod, String type) {
|
||||||
public static final String TYPE_PATH_PARAM = "type";
|
List<String> list = new ArrayList<>();
|
||||||
public static final String ID_PATH_PARAM = "id";
|
list.add(SharingPath.SHARING_PATH_PART);
|
||||||
|
list.add("{" + AccessPath.CONTEXT_UUID_PATH_PARAM + "}");
|
||||||
|
list.add(type);
|
||||||
|
list.add("{" + AccessPath.UUID_PATH_PARAM + "}");
|
||||||
|
Access.setCalledMethod(httpMethod, list, null);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/*
|
||||||
|
* PUT /sharing/{CONTEXT_UUID}/{TYPE_NAME}/{UUID}
|
||||||
* e.g PUT
|
* e.g PUT
|
||||||
* /resource-registry/sharing/67062c11-9c3a-4906-870d-7df6a43408b0/HostingNode/16032d09-3823-444e-a1ff-a67de4f350a8
|
* /resource-registry/sharing/67062c11-9c3a-4906-870d-7df6a43408b0/HostingNode/16032d09-3823-444e-a1ff-a67de4f350a8
|
||||||
* Where 67062c11-9c3a-4906-870d-7df6a43408b0/ is the context UUID
|
* Where 67062c11-9c3a-4906-870d-7df6a43408b0/ is the context UUID
|
||||||
|
@ -35,16 +48,16 @@ public class SharingManagement {
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@PUT
|
@PUT
|
||||||
@Path("/{" + CONTEXT_ID_PATH_PARAM + "}" + "/" + TYPE_PATH_PARAM + "/{" + ID_PATH_PARAM + "}")
|
@Path("/{" + AccessPath.CONTEXT_UUID_PATH_PARAM + "}" + "/" + AccessPath.TYPE_PATH_PARAM + "/{"
|
||||||
public boolean add(
|
+ AccessPath.UUID_PATH_PARAM + "}")
|
||||||
@PathParam(CONTEXT_ID_PATH_PARAM) String contextId,
|
@Consumes({MediaType.TEXT_PLAIN, ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8})
|
||||||
@PathParam(TYPE_PATH_PARAM) String type,
|
@Produces(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8)
|
||||||
@PathParam(ID_PATH_PARAM) String id)
|
public boolean add(@PathParam(AccessPath.CONTEXT_UUID_PATH_PARAM) String contextId,
|
||||||
|
@PathParam(AccessPath.TYPE_PATH_PARAM) String type, @PathParam(AccessPath.UUID_PATH_PARAM) String id)
|
||||||
throws ResourceNotFoundException, ContextNotFoundException, ResourceRegistryException {
|
throws ResourceNotFoundException, ContextNotFoundException, ResourceRegistryException {
|
||||||
|
|
||||||
CalledMethodProvider.instance.set("");
|
|
||||||
|
|
||||||
logger.info("Requested to add {} with UUID {} to {} with UUID {}", type, id, Context.NAME, contextId);
|
logger.info("Requested to add {} with UUID {} to {} with UUID {}", type, id, Context.NAME, contextId);
|
||||||
|
setCalledMethod(HTTPMETHOD.PUT, type);
|
||||||
|
|
||||||
@SuppressWarnings("rawtypes")
|
@SuppressWarnings("rawtypes")
|
||||||
ERManagement erManagement = ERManagementUtility.getERManagement(type);
|
ERManagement erManagement = ERManagementUtility.getERManagement(type);
|
||||||
|
@ -66,25 +79,24 @@ public class SharingManagement {
|
||||||
return erManagement.addToContext(contextUUID);
|
return erManagement.addToContext(contextUUID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
/**
|
* DELETE /sharing/{CONTEXT_UUID}/{TYPE_NAME}/{UUID}
|
||||||
* e.g DELETE
|
* e.g DELETE
|
||||||
* /resource-registry/sharing/67062c11-9c3a-4906-870d-7df6a43408b0/HostingNode/16032d09-3823-444e-a1ff-a67de4f350a8
|
* /resource-registry/sharing/67062c11-9c3a-4906-870d-7df6a43408b0/HostingNode/16032d09-3823-444e-a1ff-a67de4f350a8
|
||||||
* Where 67062c11-9c3a-4906-870d-7df6a43408b0/ is the context UUID
|
* Where 67062c11-9c3a-4906-870d-7df6a43408b0/ is the Context UUID
|
||||||
* and 16032d09-3823-444e-a1ff-a67de4f350a8 is the HostingNode UUID
|
* and 16032d09-3823-444e-a1ff-a67de4f350a8 is the HostingNode UUID
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@DELETE
|
@DELETE
|
||||||
@Path("/{" + CONTEXT_ID_PATH_PARAM + "}" + "/" + TYPE_PATH_PARAM + "/{" + ID_PATH_PARAM + "}")
|
@Path("/{" + AccessPath.CONTEXT_UUID_PATH_PARAM + "}" + "/" + AccessPath.TYPE_PATH_PARAM + "/{"
|
||||||
public boolean remove(
|
+ AccessPath.UUID_PATH_PARAM + "}")
|
||||||
@PathParam(CONTEXT_ID_PATH_PARAM) String contextId,
|
@Consumes({MediaType.TEXT_PLAIN, ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8})
|
||||||
@PathParam(TYPE_PATH_PARAM) String type,
|
@Produces(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8)
|
||||||
@PathParam(ID_PATH_PARAM) String id)
|
public boolean remove(@PathParam(AccessPath.CONTEXT_UUID_PATH_PARAM) String contextId,
|
||||||
|
@PathParam(AccessPath.TYPE_PATH_PARAM) String type, @PathParam(AccessPath.UUID_PATH_PARAM) String id)
|
||||||
throws ResourceNotFoundException, ContextNotFoundException, ResourceRegistryException {
|
throws ResourceNotFoundException, ContextNotFoundException, ResourceRegistryException {
|
||||||
|
|
||||||
CalledMethodProvider.instance.set("");
|
|
||||||
|
|
||||||
logger.info("Requested to remove {} with UUID {} to {} with UUID {}", type, id, Context.NAME, contextId);
|
logger.info("Requested to remove {} with UUID {} to {} with UUID {}", type, id, Context.NAME, contextId);
|
||||||
|
setCalledMethod(HTTPMETHOD.DELETE, type);
|
||||||
|
|
||||||
@SuppressWarnings("rawtypes")
|
@SuppressWarnings("rawtypes")
|
||||||
ERManagement erManagement = ERManagementUtility.getERManagement(type);
|
ERManagement erManagement = ERManagementUtility.getERManagement(type);
|
||||||
|
@ -106,5 +118,4 @@ public class SharingManagement {
|
||||||
return erManagement.removeFromContext(contextUUID);
|
return erManagement.removeFromContext(contextUUID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue