package eu.europeana.cloud.service.mcs.rest; import com.qmino.miredot.annotations.ReturnType; import eu.europeana.cloud.common.model.*; import eu.europeana.cloud.common.response.CloudVersionRevisionResponse; import eu.europeana.cloud.common.response.ResultSlice; import eu.europeana.cloud.common.utils.Tags; import eu.europeana.cloud.service.aas.authentication.SpringUserUtils; import eu.europeana.cloud.service.mcs.DataSetService; import eu.europeana.cloud.service.mcs.exception.AccessDeniedOrObjectDoesNotExistException; import eu.europeana.cloud.service.mcs.exception.DataSetNotExistsException; import eu.europeana.cloud.service.mcs.exception.ProviderNotExistsException; import eu.europeana.cloud.service.mcs.exception.RepresentationNotExistsException; import org.joda.time.DateTime; import org.joda.time.DateTimeZone; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Scope; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.acls.domain.ObjectIdentityImpl; import org.springframework.security.acls.model.MutableAclService; import org.springframework.security.acls.model.ObjectIdentity; import org.springframework.stereotype.Component; import javax.ws.rs.DELETE; import javax.ws.rs.FormParam; import javax.ws.rs.GET; 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.core.MediaType; import javax.ws.rs.core.Response; import java.text.ParseException; import java.util.ArrayList; import java.util.Date; import java.util.Set; import static eu.europeana.cloud.common.web.ParamConstants.*; import static org.apache.commons.lang3.time.DateUtils.parseDate; /** * Resource to manage data sets. */ @Path("/data-providers/{" + P_PROVIDER + "}/data-sets/{" + P_DATASET + "}") @Component @Scope("request") public class DataSetResource { @Autowired private DataSetService dataSetService; @Autowired private MutableAclService mutableAclService; @Value("${numberOfElementsOnPage}") private int numberOfElementsOnPage; private final String DATASET_CLASS_NAME = DataSet.class.getName(); /** * Deletes data set. * <strong>Delete permissions required.</strong> * * @param providerId identifier of the dataset's provider(required). * @param dataSetId identifier of the deleted data set(required). * @throws DataSetNotExistsException data set not exists. */ @DELETE @PreAuthorize("hasPermission(#dataSetId.concat('/').concat(#providerId), 'eu.europeana.cloud.common.model.DataSet', delete)") public void deleteDataSet(@PathParam(P_DATASET) String dataSetId, @PathParam(P_PROVIDER) String providerId) throws DataSetNotExistsException { dataSetService.deleteDataSet(providerId, dataSetId); // let's delete the permissions as well String ownersName = SpringUserUtils.getUsername(); if (ownersName != null) { ObjectIdentity dataSetIdentity = new ObjectIdentityImpl(DATASET_CLASS_NAME, dataSetId + "/" + providerId); mutableAclService.deleteAcl(dataSetIdentity, false); } } /** * Lists representation versions from data set. Result is returned in * slices. * * @param providerId identifier of the dataset's provider (required). * @param dataSetId identifier of a data set (required). * @param startFrom reference to next slice of result. If not provided, * first slice of result will be returned. * @return slice of representation version list. * @throws DataSetNotExistsException no such data set exists. * @summary get representation versions from a data set */ @GET @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON}) @ReturnType("eu.europeana.cloud.common.response.ResultSlice<eu.europeana.cloud.common.model.Representation>") public ResultSlice<Representation> getDataSetContents(@PathParam(P_DATASET) String dataSetId, @PathParam(P_PROVIDER) String providerId, @QueryParam(F_START_FROM) String startFrom) throws DataSetNotExistsException { return dataSetService.listDataSet(providerId, dataSetId, startFrom, numberOfElementsOnPage); } /** * Updates description of a data set. * <p> * <strong>Write permissions required.</strong> * * @param providerId identifier of the dataset's provider (required). * @param dataSetId identifier of a data set (required). * @param description description of data set * @throws DataSetNotExistsException no such data set exists. * @throws AccessDeniedOrObjectDoesNotExistException there is an attempt to access a resource without the proper permissions. * or the resource does not exist at all * @statuscode 204 object has been updated. */ @PUT @PreAuthorize("hasPermission(#dataSetId.concat('/').concat(#providerId), 'eu.europeana.cloud.common.model.DataSet', write)") public void updateDataSet(@PathParam(P_DATASET) String dataSetId, @PathParam(P_PROVIDER) String providerId, @FormParam(F_DESCRIPTION) String description) throws AccessDeniedOrObjectDoesNotExistException, DataSetNotExistsException { dataSetService.updateDataSet(providerId, dataSetId, description); } @Path("/representationsNames") @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}) @GET public RepresentationNames getRepresentationsNames( @PathParam(P_DATASET) String dataSetId, @PathParam(P_PROVIDER) String providerId) throws ProviderNotExistsException, DataSetNotExistsException { RepresentationNames representationNames = new RepresentationNames(); representationNames.setNames(dataSetService.getAllDataSetRepresentationsNames(providerId, dataSetId)); return representationNames; } @Path("/representations/{" + P_REPRESENTATIONNAME + "}") @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON}) @ReturnType("eu.europeana.cloud.common.response.ResultSlice<CloudVersionRevisionResponse>") @GET public ResultSlice<CloudVersionRevisionResponse> getDataSetCloudIdsByRepresentation( @PathParam(P_DATASET) String dataSetId, @PathParam(P_PROVIDER) String providerId, @PathParam(P_REPRESENTATIONNAME) String representationName, @QueryParam(F_DATE_FROM) String dateFrom, @QueryParam(F_TAG) String tag, @QueryParam(F_START_FROM) String startFrom) throws ProviderNotExistsException, DataSetNotExistsException { Tags tags = Tags.valueOf(tag.toUpperCase()); DateTime utc = new DateTime(dateFrom, DateTimeZone.UTC); if (Tags.PUBLISHED.equals(tags)) return dataSetService.getDataSetCloudIdsByRepresentationPublished(dataSetId, providerId, representationName, utc.toDate(), startFrom, numberOfElementsOnPage); throw new IllegalArgumentException("Only PUBLISHED tag is supported for this request."); } /** * get a list of the latest cloud identifiers,revision timestamps that belong to data set of a specified provider for a specific representation and revision. * This list will contain one row per revision per cloudId; * * @param dataSetId data set identifier * @param providerId provider identifier * @param revisionName revision name * @param revisionProvider revision provider * @param representationName representation name * @param startFrom cloudId to start from * @param isDeleted revision marked-deleted * @return slice of the latest cloud identifier,revision timestamp that belong to data set of a specified provider for a specific representation and revision * This list will contain one row per revision per cloudId ; * @throws ProviderNotExistsException * @throws DataSetNotExistsException */ @Path("/revision/{" + P_REVISION_NAME + "}/revisionProvider/{" + REVISION_PROVIDER + "}/representations/{" + P_REPRESENTATIONNAME + "}") @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON}) @ReturnType("eu.europeana.cloud.common.response.ResultSlice<CloudIdAndTimestampResponse>") @GET public ResultSlice<CloudIdAndTimestampResponse> getDataSetCloudIdsByRepresentationAndRevision( @PathParam(P_DATASET) String dataSetId, @PathParam(P_PROVIDER) String providerId, @PathParam(P_REVISION_NAME) String revisionName, @PathParam(REVISION_PROVIDER) String revisionProvider, @PathParam(P_REPRESENTATIONNAME) String representationName, @QueryParam(F_START_FROM) String startFrom, @QueryParam(IS_DELETED) Boolean isDeleted) throws ProviderNotExistsException, DataSetNotExistsException { ResultSlice<CloudIdAndTimestampResponse> cloudIdAndTimestampResponses = dataSetService.getLatestDataSetCloudIdByRepresentationAndRevision(dataSetId, providerId, revisionName, revisionProvider, representationName, startFrom, isDeleted, numberOfElementsOnPage); return cloudIdAndTimestampResponses; } /** * Gives the versionId of specified representation that has the newest revision (by revision timestamp) with given name. * * @param dataSetId dataset identifier * @param providerId dataset owner * @param cloudId representation cloud identifier * @param representationName representation name * @param revisionName revision name * @param revisionProviderId revision owner * @return version identifier of representation * @throws DataSetNotExistsException */ @Path("/latelyRevisionedVersion") @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}) @GET public Response getLatelyTaggedRecords( @PathParam(P_DATASET) String dataSetId, @PathParam(P_PROVIDER) String providerId, @QueryParam(F_CLOUDID) String cloudId, @QueryParam(F_REPRESENTATIONNAME) String representationName, @QueryParam(F_REVISION_NAME) String revisionName, @QueryParam(F_REVISION_PROVIDER_ID) String revisionProviderId) throws DataSetNotExistsException { ParamUtil.require(F_CLOUDID, cloudId); ParamUtil.require(F_REPRESENTATIONNAME, representationName); ParamUtil.require(F_REVISION_NAME, revisionName); ParamUtil.require(F_REVISION_PROVIDER_ID, revisionProviderId); String versionId = dataSetService.getLatestVersionForGivenRevision(dataSetId, providerId, cloudId, representationName, revisionName, revisionProviderId); if (versionId != null) { return Response.ok().entity(versionId).build(); } else { return Response.noContent().build(); } } }