gcat/src/main/java/org/gcube/gcat/rest/Profile.java

244 lines
8.4 KiB
Java

package org.gcube.gcat.rest;
import javax.ws.rs.BadRequestException;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.DefaultValue;
import javax.ws.rs.GET;
import javax.ws.rs.HttpMethod;
import javax.ws.rs.InternalServerErrorException;
import javax.ws.rs.NotAllowedException;
//import javax.ws.rs.NotAuthorizedException;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.ResponseBuilder;
import javax.ws.rs.core.Response.Status;
import org.gcube.com.fasterxml.jackson.databind.node.ArrayNode;
//import org.gcube.common.authorization.control.annotations.AuthorizationControl;
import org.gcube.datacatalogue.metadatadiscovery.DataCalogueMetadataFormatReader;
import org.gcube.gcat.api.GCatConstants;
//import org.gcube.gcat.api.roles.Role;
import org.gcube.gcat.profile.ISProfile;
import org.xml.sax.SAXException;
import com.webcohesion.enunciate.metadata.rs.ResourceGroup;
import com.webcohesion.enunciate.metadata.rs.ResourceLabel;
import com.webcohesion.enunciate.metadata.rs.ResponseCode;
import com.webcohesion.enunciate.metadata.rs.StatusCodes;
/**
* A Profile must comply with the defined <a href="../profiles/SCHEMA">XSD schema</a> .
*
* Please find the documentation of profile schema at:
* at <a href="https://wiki.gcube-system.org/gcube/GCat_Background#Metadata_Profile_v.4">Metadata Profile</>
*
* @author Luca Frosini (ISTI - CNR)
*/
@Path(Profile.PROFILES)
@ResourceGroup("Item Related APIs")
@ResourceLabel("Profile APIs")
public class Profile extends BaseREST implements org.gcube.gcat.api.interfaces.Profile<Response,Response> {
public static final String PROFILE_NAME_PARAMETER = "PROFILE_NAME";
public static final String PROFILE_VALIDATION_ERROR;
public static final String CANNOT_MANAGE_PROFILE_SCHEMA = "You cannot manage the profile schema";
static {
StringBuilder validationError = new StringBuilder();
validationError.append("The Profile is not valid because of the following error at validation time:\n%s\n\n");
validationError.append("The XSD used to validate the profile is available at %s\n\n");
validationError.append(
"To check your profile you can use a tool such as Oxygen XML Editor or an online service such as the one available at:\n");
validationError.append("- http://www.utilities-online.info/xsdvalidation/\n");
validationError.append("- https://www.freeformatter.com/xml-validator-xsd.html\n");
PROFILE_VALIDATION_ERROR = validationError.toString();
}
/*
* Not used as REST method, implemented to respect {@link org.gcube.gcat.api.interfaces.Item} interface
*/
@Override
public int count() {
setCalledMethod("GET /" + PROFILES);
try {
ISProfile isProfile = new ISProfile();
return isProfile.count();
} catch(WebApplicationException e) {
throw e;
} catch(Exception e) {
throw new InternalServerErrorException(e);
}
}
/**
* Returns the list of profiles name available for the
* context of the request
* (i.e. the context where the token has been generated).
*
* @param count (<em>Default:false</em>) If <code>count=true</code> the API returns total number of profile instead of the list.
* @return a JSON Array.
*
* @pathExample /profiles
* @responseExample application/json;charset=UTF-8 ["EmptyProfile","TestProfile",...,"ComplexProfile"]
*
* @pathExample /profiles?count=true
* @responseExample application/json;charset=UTF-8 {"count":5}
*
*/
@GET
@Produces(MediaType.APPLICATION_JSON)
public String listOrCount(@QueryParam(GCatConstants.COUNT_QUERY_PARAMETER) @DefaultValue("false") Boolean count) {
setCalledMethod("GET /" + PROFILES);
try {
ISProfile isProfile = new ISProfile();
if(count) {
return createCountJson(isProfile.count());
}else{
ArrayNode arrayNode = isProfile.list();
return isProfile.getMapper().writeValueAsString(arrayNode);
}
} catch(WebApplicationException e) {
throw e;
} catch(Exception e) {
throw new InternalServerErrorException(e);
}
}
/*
* Not used as REST method, implemented to respect {@link org.gcube.gcat.api.interfaces.Item} interface
*/
@Override
public String list() {
try {
ISProfile isProfile = new ISProfile();
ArrayNode arrayNode = isProfile.list();
return isProfile.getMapper().writeValueAsString(arrayNode);
} catch(WebApplicationException e) {
throw e;
} catch(Exception e) {
throw new InternalServerErrorException(e);
}
}
public static int PRETTY_PRINT_INDENT_FACTOR = 4;
/**
* This API allow to read a profile definition.<br/>
*
* This API return by default the content in XML.
* <p>
* It is possible reading a profile in JSON by specifing the HTTP Header:<br/>
* <code>Accept: application/json</code>
* </p>
*
* @param name the name of the profile
* @return the profile definition
*
* @pathExample /profiles/EmptyProfile
* @responseExample application/xml classpath:/api-docs-examples/profile/read-profile-response.xml
*
*/
@GET
@Path("/{" + PROFILE_NAME_PARAMETER + "}")
@Produces({MediaType.APPLICATION_XML})
@StatusCodes ({
@ResponseCode ( code = 200, condition = "The pprofile exists.")
})
@Override
public String read(@PathParam(PROFILE_NAME_PARAMETER) String name) {
setCalledMethod("GET /" + PROFILES + "/{" + PROFILE_NAME_PARAMETER + "}");
try {
// If the name is SCHEMA
if(name.compareToIgnoreCase(SCHEMA) == 0) {
return DataCalogueMetadataFormatReader.getProfileSchemaString();
}
String accept = httpHeaders.getHeaderString("Accept");
ISProfile isProfile = new ISProfile();
boolean xml = true;
if(accept.startsWith(MediaType.APPLICATION_JSON)) {
xml = false;
}
return isProfile.read(name, xml);
} catch(WebApplicationException e) {
throw e;
} catch(Exception e) {
throw new InternalServerErrorException(e);
}
}
@PUT
@Path("/{" + PROFILE_NAME_PARAMETER + "}")
@Consumes(MediaType.APPLICATION_XML)
@Produces(MediaType.APPLICATION_XML)
// @AuthorizationControl(allowedRoles={Role.CATALOGUE_EDITOR, Role.CATALOGUE_ADMIN, Role.CATALOGUE_MANAGER}, exception=NotAuthorizedException.class)
public Response createOrUpdate(@PathParam(PROFILE_NAME_PARAMETER) String name, String xml) {
setCalledMethod("PUT /" + PROFILES + "/{" + PROFILE_NAME_PARAMETER + "}");
try {
if(name.compareToIgnoreCase(SCHEMA) == 0) {
throw new NotAllowedException(CANNOT_MANAGE_PROFILE_SCHEMA, new Throwable(CANNOT_MANAGE_PROFILE_SCHEMA),
HttpMethod.GET.toString(), HttpMethod.HEAD.toString());
}
ISProfile isProfile = new ISProfile();
boolean created = isProfile.createOrUpdate(name, xml);
ResponseBuilder responseBuilder = null;
if(created) {
responseBuilder = Response.status(Status.CREATED);
responseBuilder.header(LOCATION_HEADER, uriInfo.getAbsolutePath());
} else {
responseBuilder = Response.status(Status.OK);
}
responseBuilder.entity(xml);
return responseBuilder.type(MediaType.APPLICATION_XML).build();
} catch(WebApplicationException e) {
throw e;
} catch(SAXException e) {
String schemaURL = uriInfo.getRequestUri().toString().replace(name, SCHEMA);
throw new BadRequestException(String.format(PROFILE_VALIDATION_ERROR, e.getMessage(), schemaURL));
} catch(Exception e) {
throw new InternalServerErrorException(e);
}
}
@DELETE
@Path("/{" + PROFILE_NAME_PARAMETER + "}")
// @AuthorizationControl(allowedRoles={Role.CATALOGUE_EDITOR, Role.CATALOGUE_ADMIN, Role.CATALOGUE_MANAGER}, exception=NotAuthorizedException.class)
public Response delete(@PathParam(PROFILE_NAME_PARAMETER) String name) {
setCalledMethod("DELETE /" + PROFILES + "/{" + PROFILE_NAME_PARAMETER + "}");
try {
if(name.compareToIgnoreCase(SCHEMA) == 0) {
throw new NotAllowedException(CANNOT_MANAGE_PROFILE_SCHEMA, new Throwable(CANNOT_MANAGE_PROFILE_SCHEMA),
HttpMethod.GET.toString(), HttpMethod.HEAD.toString());
}
ISProfile isProfile = new ISProfile();
isProfile.delete(name);
return Response.status(Status.NO_CONTENT).build();
} catch(WebApplicationException e) {
throw e;
} catch(Exception e) {
throw new InternalServerErrorException(e);
}
}
@Override
public Response create(String name, String xml) {
return createOrUpdate(name, xml);
}
@Override
public String update(String name, String xml) {
return createOrUpdate(name, xml).getEntity().toString();
}
}