package eu.europeana.cloud.service.mcs.rest;
import eu.europeana.cloud.common.model.DataSet;
import eu.europeana.cloud.common.model.Representation;
import eu.europeana.cloud.common.model.Revision;
import eu.europeana.cloud.common.utils.RevisionUtils;
import eu.europeana.cloud.common.utils.Tags;
import eu.europeana.cloud.service.mcs.DataSetService;
import eu.europeana.cloud.service.mcs.RecordService;
import eu.europeana.cloud.service.mcs.exception.ProviderNotExistsException;
import eu.europeana.cloud.service.mcs.exception.RepresentationNotExistsException;
import eu.europeana.cloud.service.mcs.exception.RevisionIsNotValidException;
import jersey.repackaged.com.google.common.collect.Sets;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Component;
import javax.ws.rs.Consumes;
import javax.ws.rs.FormParam;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import static eu.europeana.cloud.common.web.ParamConstants.*;
/**
* Created by Tarek on 8/2/2016.
*/
@Path("/records/{" + P_CLOUDID + "}/representations/{" + P_REPRESENTATIONNAME
+ "}/versions/{" + P_VER + "}/revisions")
@Component
@Scope("request")
public class RevisionResource {
private static final Logger LOGGER = LoggerFactory.getLogger("RequestsLogger");
@Autowired
private RecordService recordService;
@Autowired
private DataSetService dataSetService;
/**
* Adds a new revision to representation version.
* <strong>Read permissions required.</strong>
*
* @param globalId cloud id of the record (required).
* @param schema schema of representation (required).
* @param version a specific version of the representation(required).
* @param revisionName the name of revision (required).
* @param revisionProviderId revision provider id (required).
* @param tag tag flag (acceptance,published,deleted)
* @return URI to specific revision with specific tag inside a version.TODO
* @throws RepresentationNotExistsException representation does not exist in specified version
* @throws RevisionIsNotValidException if the added revision was not valid
* @statuscode 201 object has been created.
*/
@POST
@Path("/{" + P_REVISION_NAME + "}/revisionProvider/{" + P_REVISION_PROVIDER_ID + "}/tag/{" + P_TAG + "}")
@PreAuthorize("hasPermission(#globalId.concat('/').concat(#schema).concat('/').concat(#version),"
+ " 'eu.europeana.cloud.common.model.Representation', read)")
public Response addRevision(@Context UriInfo uriInfo,
@PathParam(P_CLOUDID) final String globalId,
@PathParam(P_REPRESENTATIONNAME) final String schema,
@PathParam(P_VER) final String version,
@PathParam(P_REVISION_NAME) String revisionName,
@PathParam(P_TAG) String tag,
@PathParam(P_REVISION_PROVIDER_ID) String revisionProviderId
)
throws RepresentationNotExistsException, RevisionIsNotValidException, ProviderNotExistsException {
ParamUtil.validate(P_TAG, tag, Arrays.asList(Tags.ACCEPTANCE.getTag(), Tags.PUBLISHED.getTag(), Tags.DELETED.getTag()));
Revision revision = new Revision(revisionName, revisionProviderId);
setRevisionTags(revision, new HashSet<>(Arrays.asList(tag)));
addRevision(globalId, schema, version, revision);
// insert information in extra table
recordService.insertRepresentationRevision(globalId, schema, revisionProviderId, revisionName, version, revision.getCreationTimeStamp());
return Response.created(uriInfo.getAbsolutePath()).build();
}
private void addRevision(String globalId, String schema, String version, Revision revision) throws RevisionIsNotValidException, ProviderNotExistsException, RepresentationNotExistsException {
createAssignmentToRevisionOnDataSets(globalId, schema, version, revision);
recordService.addRevision(globalId, schema, version, revision);
dataSetService.updateProviderDatasetRepresentation(globalId, schema, version, revision);
// insert information in extra table
recordService.insertRepresentationRevision(globalId, schema, revision.getRevisionProviderId(), revision.getRevisionName(), version, revision.getCreationTimeStamp());
dataSetService.updateAllRevisionDatasetsEntries(globalId, schema, version, revision);
}
private void createAssignmentToRevisionOnDataSets(String globalId, String schema,
String version, Revision revision)
throws ProviderNotExistsException, RepresentationNotExistsException {
Map<String, Set<String>> dataSets = dataSetService.getDataSets(globalId, schema, version);
for (Map.Entry<String, Set<String>> entry : dataSets.entrySet()) {
for (String dataset : entry.getValue()) {
dataSetService.addDataSetsRevisions(entry.getKey(), dataset, revision, schema, globalId);
}
}
}
/**
* Adds a new revision to representation version.
* <strong>Read permissions required.</strong>
*
* @param revision Revision (required).
* @return URI to revisions inside a version. TODO
* @throws RepresentationNotExistsException representation does not exist in specified version
* @statuscode 201 object has been created.
*/
@POST
@PreAuthorize("hasPermission(#globalId.concat('/').concat(#schema).concat('/').concat(#version),"
+ " 'eu.europeana.cloud.common.model.Representation', read)")
@Consumes(MediaType.APPLICATION_JSON)
public Response addRevision(@Context UriInfo uriInfo,
@PathParam(P_CLOUDID) final String globalId,
@PathParam(P_REPRESENTATIONNAME) final String schema,
@PathParam(P_VER) final String version,
Revision revision
)
throws RevisionIsNotValidException, ProviderNotExistsException, RepresentationNotExistsException {
addRevision(globalId, schema, version, revision);
// insert information in extra table
recordService.insertRepresentationRevision(globalId, schema, revision.getRevisionProviderId(), revision.getRevisionName(), version, revision.getCreationTimeStamp());
return Response.created(uriInfo.getAbsolutePath()).build();
}
/**
* Adds a new revision to representation version.
* <strong>Read permissions required.</strong>
*
* @param globalId cloud id of the record (required).
* @param schema schema of representation (required).
* @param version a specific version of the representation(required).
* @param revisionName the name of revision (required).
* @param revisionProviderId revision provider id (required).
* @param tags set of tags (acceptance,published,deleted)
* @return URI to a revision tags inside a version.TODO
* @throws RepresentationNotExistsException representation does not exist in specified version
* @throws RevisionIsNotValidException if the added revision was not valid
* @statuscode 201 object has been created.
*/
@POST
@Path("/{" + P_REVISION_NAME + "}/revisionProvider/{" + P_REVISION_PROVIDER_ID + "}/tags")
@PreAuthorize("hasPermission(#globalId.concat('/').concat(#schema).concat('/').concat(#version),"
+ " 'eu.europeana.cloud.common.model.Representation', read)")
public Response addRevision(@Context UriInfo uriInfo,
@PathParam(P_CLOUDID) final String globalId,
@PathParam(P_REPRESENTATIONNAME) final String schema,
@PathParam(P_VER) final String version,
@PathParam(P_REVISION_NAME) String revisionName,
@PathParam(P_REVISION_PROVIDER_ID) String revisionProviderId,
@FormParam(F_TAGS) Set<String> tags
)
throws RepresentationNotExistsException, RevisionIsNotValidException, ProviderNotExistsException {
ParamUtil.validateTags(tags, new HashSet<>(Sets.newHashSet(Tags.ACCEPTANCE.getTag(), Tags.PUBLISHED.getTag(), Tags.DELETED.getTag())));
Revision revision = new Revision(revisionName, revisionProviderId);
setRevisionTags(revision, tags);
addRevision(globalId, schema, version, revision);
// insert information in extra table
recordService.insertRepresentationRevision(globalId, schema, revisionProviderId, revisionName, version, revision.getCreationTimeStamp());
return Response.created(uriInfo.getAbsolutePath()).entity(revision).build();
}
private Revision setRevisionTags(Revision revision, Set<String> tags) {
if (tags == null || tags.isEmpty())
return revision;
if (tags.contains(Tags.ACCEPTANCE.getTag()))
revision.setAcceptance(true);
if (tags.contains(Tags.PUBLISHED.getTag()))
revision.setPublished(true);
if (tags.contains(Tags.DELETED.getTag()))
revision.setDeleted(true);
return revision;
}
}