/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE file at the root of the source
* tree and available online at
*
* https://github.com/keeps/roda
*/
package org.roda.wui.api.controllers;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.MissingResourceException;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import javax.ws.rs.core.MultivaluedMap;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.custommonkey.xmlunit.Diff;
import org.custommonkey.xmlunit.XMLUnit;
import org.roda.core.RodaCoreFactory;
import org.roda.core.common.ClassificationPlanUtils;
import org.roda.core.common.ConsumesOutputStream;
import org.roda.core.common.DownloadUtils;
import org.roda.core.common.EntityResponse;
import org.roda.core.common.HandlebarsUtility;
import org.roda.core.common.Messages;
import org.roda.core.common.PremisV3Utils;
import org.roda.core.common.RodaUtils;
import org.roda.core.common.StreamResponse;
import org.roda.core.common.UserUtility;
import org.roda.core.common.iterables.CloseableIterable;
import org.roda.core.common.iterables.CloseableIterables;
import org.roda.core.common.monitor.TransferredResourcesScanner;
import org.roda.core.common.tools.ZipEntryInfo;
import org.roda.core.common.validation.ValidationUtils;
import org.roda.core.data.common.RodaConstants;
import org.roda.core.data.common.RodaConstants.PreservationEventType;
import org.roda.core.data.common.RodaConstants.RODA_TYPE;
import org.roda.core.data.exceptions.AlreadyExistsException;
import org.roda.core.data.exceptions.AuthorizationDeniedException;
import org.roda.core.data.exceptions.GenericException;
import org.roda.core.data.exceptions.InvalidParameterException;
import org.roda.core.data.exceptions.IsStillUpdatingException;
import org.roda.core.data.exceptions.JobAlreadyStartedException;
import org.roda.core.data.exceptions.NotFoundException;
import org.roda.core.data.exceptions.RODAException;
import org.roda.core.data.exceptions.RequestNotValidException;
import org.roda.core.data.utils.JsonUtils;
import org.roda.core.data.v2.LinkingObjectUtils;
import org.roda.core.data.v2.common.ObjectPermission;
import org.roda.core.data.v2.common.ObjectPermissionResult;
import org.roda.core.data.v2.common.OptionalWithCause;
import org.roda.core.data.v2.common.Pair;
import org.roda.core.data.v2.formats.Format;
import org.roda.core.data.v2.index.IndexResult;
import org.roda.core.data.v2.index.IsIndexed;
import org.roda.core.data.v2.index.facet.FacetFieldResult;
import org.roda.core.data.v2.index.facet.FacetValue;
import org.roda.core.data.v2.index.facet.Facets;
import org.roda.core.data.v2.index.facet.SimpleFacetParameter;
import org.roda.core.data.v2.index.filter.EmptyKeyFilterParameter;
import org.roda.core.data.v2.index.filter.Filter;
import org.roda.core.data.v2.index.filter.OneOfManyFilterParameter;
import org.roda.core.data.v2.index.filter.SimpleFilterParameter;
import org.roda.core.data.v2.index.select.SelectedItems;
import org.roda.core.data.v2.index.select.SelectedItemsFilter;
import org.roda.core.data.v2.index.select.SelectedItemsList;
import org.roda.core.data.v2.index.sort.SortParameter;
import org.roda.core.data.v2.index.sort.Sorter;
import org.roda.core.data.v2.index.sublist.Sublist;
import org.roda.core.data.v2.ip.AIP;
import org.roda.core.data.v2.ip.AIPState;
import org.roda.core.data.v2.ip.DIP;
import org.roda.core.data.v2.ip.DIPFile;
import org.roda.core.data.v2.ip.File;
import org.roda.core.data.v2.ip.IndexedAIP;
import org.roda.core.data.v2.ip.IndexedDIP;
import org.roda.core.data.v2.ip.IndexedFile;
import org.roda.core.data.v2.ip.IndexedRepresentation;
import org.roda.core.data.v2.ip.Permissions;
import org.roda.core.data.v2.ip.Representation;
import org.roda.core.data.v2.ip.StoragePath;
import org.roda.core.data.v2.ip.TransferredResource;
import org.roda.core.data.v2.ip.metadata.DescriptiveMetadata;
import org.roda.core.data.v2.ip.metadata.DescriptiveMetadataList;
import org.roda.core.data.v2.ip.metadata.IndexedPreservationAgent;
import org.roda.core.data.v2.ip.metadata.IndexedPreservationEvent;
import org.roda.core.data.v2.ip.metadata.LinkingIdentifier;
import org.roda.core.data.v2.ip.metadata.OtherMetadata;
import org.roda.core.data.v2.ip.metadata.OtherMetadataList;
import org.roda.core.data.v2.ip.metadata.PreservationMetadata;
import org.roda.core.data.v2.ip.metadata.PreservationMetadata.PreservationMetadataType;
import org.roda.core.data.v2.ip.metadata.PreservationMetadataList;
import org.roda.core.data.v2.jobs.IndexedReport;
import org.roda.core.data.v2.jobs.Job;
import org.roda.core.data.v2.jobs.PluginType;
import org.roda.core.data.v2.jobs.Report;
import org.roda.core.data.v2.jobs.Report.PluginState;
import org.roda.core.data.v2.jobs.Reports;
import org.roda.core.data.v2.risks.IndexedRisk;
import org.roda.core.data.v2.risks.Risk;
import org.roda.core.data.v2.risks.Risk.SEVERITY_LEVEL;
import org.roda.core.data.v2.risks.RiskIncidence;
import org.roda.core.data.v2.risks.RiskIncidence.INCIDENCE_STATUS;
import org.roda.core.data.v2.user.User;
import org.roda.core.data.v2.validation.ValidationException;
import org.roda.core.data.v2.validation.ValidationReport;
import org.roda.core.index.IndexService;
import org.roda.core.index.utils.IterableIndexResult;
import org.roda.core.model.ModelService;
import org.roda.core.model.utils.ModelUtils;
import org.roda.core.plugins.plugins.PluginHelper;
import org.roda.core.plugins.plugins.characterization.SiegfriedPlugin;
import org.roda.core.plugins.plugins.ingest.AutoAcceptSIPPlugin;
import org.roda.core.plugins.plugins.internal.DeleteRODAObjectPlugin;
import org.roda.core.plugins.plugins.internal.MovePlugin;
import org.roda.core.plugins.plugins.internal.UpdateAIPPermissionsPlugin;
import org.roda.core.storage.Binary;
import org.roda.core.storage.BinaryVersion;
import org.roda.core.storage.ContentPayload;
import org.roda.core.storage.DefaultStoragePath;
import org.roda.core.storage.Directory;
import org.roda.core.storage.StorageService;
import org.roda.core.storage.fs.FSPathContentPayload;
import org.roda.core.storage.fs.FSUtils;
import org.roda.core.util.IdUtils;
import org.roda.wui.api.v1.utils.ApiUtils;
import org.roda.wui.api.v1.utils.ObjectResponse;
import org.roda.wui.client.browse.MetadataValue;
import org.roda.wui.client.browse.bundle.BinaryVersionBundle;
import org.roda.wui.client.browse.bundle.BrowseAIPBundle;
import org.roda.wui.client.browse.bundle.BrowseFileBundle;
import org.roda.wui.client.browse.bundle.BrowseRepresentationBundle;
import org.roda.wui.client.browse.bundle.DescriptiveMetadataEditBundle;
import org.roda.wui.client.browse.bundle.DescriptiveMetadataVersionsBundle;
import org.roda.wui.client.browse.bundle.DescriptiveMetadataViewBundle;
import org.roda.wui.client.browse.bundle.DipBundle;
import org.roda.wui.client.browse.bundle.PreservationEventViewBundle;
import org.roda.wui.client.browse.bundle.SupportedMetadataTypeBundle;
import org.roda.wui.client.planning.MitigationPropertiesBundle;
import org.roda.wui.client.planning.RiskMitigationBundle;
import org.roda.wui.client.planning.RiskVersionsBundle;
import org.roda.wui.common.HTMLUtils;
import org.roda.wui.common.server.ServerTools;
import org.roda.wui.server.common.XMLSimilarityIgnoreElements;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xml.sax.SAXException;
/**
* @author Luis Faria <lfaria@keep.pt>
*/
public class BrowserHelper {
private static final String HTML_EXT = ".html";
private static final Logger LOGGER = LoggerFactory.getLogger(BrowserHelper.class);
private static final List<String> aipAncestorsFieldsToReturn = Arrays.asList(RodaConstants.INDEX_UUID,
RodaConstants.AIP_GHOST, RodaConstants.AIP_LEVEL, RodaConstants.AIP_TITLE, RodaConstants.AIP_PARENT_ID);
private BrowserHelper() {
// do nothing
}
protected static BrowseAIPBundle retrieveBrowseAipBundle(User user, IndexedAIP aip, Locale locale)
throws GenericException, NotFoundException, RequestNotValidException, AuthorizationDeniedException {
BrowseAIPBundle bundle = new BrowseAIPBundle();
// set aip
bundle.setAIP(aip);
String aipId = aip.getId();
boolean justActive = aip.getState().equals(AIPState.ACTIVE);
// set aip ancestors
try {
List<IndexedAIP> ancestors = retrieveAncestors(aip, aipAncestorsFieldsToReturn);
bundle.setAIPAncestors(ancestors);
} catch (NotFoundException e) {
LOGGER.warn("Found an item with invalid ancestors: {}", aip.getId(), e);
}
// set descriptive metadata
try {
List<DescriptiveMetadataViewBundle> descriptiveMetadataList = retrieveDescriptiveMetadataBundles(aipId, locale);
bundle.setDescriptiveMetadata(descriptiveMetadataList);
} catch (NotFoundException e) {
// do nothing
}
// Count child AIPs
Filter childAIPfilter = new Filter(new SimpleFilterParameter(RodaConstants.AIP_PARENT_ID, aip.getId()));
Long childAIPCount = RodaCoreFactory.getIndexService().count(IndexedAIP.class, childAIPfilter, user, justActive);
bundle.setChildAIPCount(childAIPCount);
// Count representations
Filter repFilter = new Filter(new SimpleFilterParameter(RodaConstants.REPRESENTATION_AIP_ID, aipId));
Long repCount = RodaCoreFactory.getIndexService().count(IndexedRepresentation.class, repFilter, user, justActive);
bundle.setRepresentationCount(repCount);
// Count DIPs
Filter dipsFilter = new Filter(new SimpleFilterParameter(RodaConstants.DIP_AIP_UUIDS, aip.getId()));
Long dipCount = RodaCoreFactory.getIndexService().count(IndexedDIP.class, dipsFilter, user, justActive);
bundle.setDipCount(dipCount);
return bundle;
}
public static BrowseRepresentationBundle retrieveBrowseRepresentationBundle(IndexedAIP aip,
IndexedRepresentation representation, Locale locale)
throws GenericException, RequestNotValidException, AuthorizationDeniedException {
BrowseRepresentationBundle bundle = new BrowseRepresentationBundle();
bundle.setAip(aip);
bundle.setRepresentation(representation);
// set aip ancestors
try {
List<IndexedAIP> ancestors = retrieveAncestors(aip, aipAncestorsFieldsToReturn);
bundle.setAipAncestors(ancestors);
} catch (NotFoundException e) {
LOGGER.warn("Found an item with invalid ancestors: {}", aip.getId(), e);
}
// set representation desc. metadata
try {
bundle.setRepresentationDescriptiveMetadata(
retrieveDescriptiveMetadataBundles(aip.getId(), representation.getId(), locale));
} catch (NotFoundException e) {
// do nothing
}
// Count DIPs
Filter dipsFilter = new Filter(
new SimpleFilterParameter(RodaConstants.DIP_REPRESENTATION_UUIDS, representation.getUUID()));
Long dipCount = RodaCoreFactory.getIndexService().count(IndexedDIP.class, dipsFilter);
bundle.setDipCount(dipCount);
return bundle;
}
public static BrowseFileBundle retrieveBrowseFileBundle(IndexedAIP aip, IndexedRepresentation representation,
IndexedFile file, User user) throws NotFoundException, GenericException, RequestNotValidException {
BrowseFileBundle bundle = new BrowseFileBundle();
bundle.setAip(aip);
bundle.setRepresentation(representation);
bundle.setFile(file);
// set aip ancestors
try {
List<IndexedAIP> ancestors = retrieveAncestors(aip, aipAncestorsFieldsToReturn);
bundle.setAipAncestors(ancestors);
} catch (NotFoundException e) {
LOGGER.warn("Found an item with invalid ancestors: {}", aip.getId(), e);
}
// set sibling count
String parentUUID = bundle.getFile().getParentUUID();
Filter siblingFilter = new Filter(
new SimpleFilterParameter(RodaConstants.FILE_REPRESENTATION_UUID, bundle.getFile().getRepresentationUUID()));
if (parentUUID != null) {
siblingFilter.add(new SimpleFilterParameter(RodaConstants.FILE_PARENT_UUID, parentUUID));
} else {
siblingFilter.add(new EmptyKeyFilterParameter(RodaConstants.FILE_PARENT_UUID));
}
boolean justActive = AIPState.ACTIVE.equals(aip.getState());
bundle.setTotalSiblingCount(count(IndexedFile.class, siblingFilter, justActive, user));
// Count DIPs
Filter dipsFilter = new Filter(new SimpleFilterParameter(RodaConstants.DIP_FILE_UUIDS, file.getUUID()));
Long dipCount = RodaCoreFactory.getIndexService().count(IndexedDIP.class, dipsFilter);
bundle.setDipCount(dipCount);
return bundle;
}
private static List<DescriptiveMetadataViewBundle> retrieveDescriptiveMetadataBundles(String aipId, Locale locale)
throws GenericException, RequestNotValidException, AuthorizationDeniedException, NotFoundException {
return retrieveDescriptiveMetadataBundles(aipId, null, locale);
}
private static List<DescriptiveMetadataViewBundle> retrieveDescriptiveMetadataBundles(String aipId,
String representationId, final Locale locale)
throws GenericException, RequestNotValidException, AuthorizationDeniedException, NotFoundException {
ModelService model = RodaCoreFactory.getModelService();
List<DescriptiveMetadata> listDescriptiveMetadataBinaries;
if (representationId != null) {
listDescriptiveMetadataBinaries = model.retrieveRepresentation(aipId, representationId).getDescriptiveMetadata();
} else {
listDescriptiveMetadataBinaries = model.retrieveAIP(aipId).getDescriptiveMetadata();
}
List<DescriptiveMetadataViewBundle> descriptiveMetadataList = new ArrayList<>();
// Can be null when the AIP is a ghost
if (listDescriptiveMetadataBinaries != null) {
for (DescriptiveMetadata descriptiveMetadata : listDescriptiveMetadataBinaries) {
DescriptiveMetadataViewBundle bundle = retrieveDescriptiveMetadataBundle(aipId, representationId,
descriptiveMetadata, locale);
descriptiveMetadataList.add(bundle);
}
}
return descriptiveMetadataList;
}
private static DescriptiveMetadataViewBundle retrieveDescriptiveMetadataBundle(String aipId, String representationId,
DescriptiveMetadata descriptiveMetadata, final Locale locale)
throws GenericException, RequestNotValidException, NotFoundException, AuthorizationDeniedException {
ModelService model = RodaCoreFactory.getModelService();
Messages messages = RodaCoreFactory.getI18NMessages(locale);
DescriptiveMetadataViewBundle bundle = new DescriptiveMetadataViewBundle();
bundle.setId(descriptiveMetadata.getId());
if (descriptiveMetadata.getType() != null) {
try {
String labelWithoutVersion = messages.getTranslation(
RodaConstants.I18N_UI_BROWSE_METADATA_DESCRIPTIVE_TYPE_PREFIX + descriptiveMetadata.getType().toLowerCase());
if (descriptiveMetadata.getVersion() != null) {
String labelWithVersion = messages.getTranslation(
RodaConstants.I18N_UI_BROWSE_METADATA_DESCRIPTIVE_TYPE_PREFIX + descriptiveMetadata.getType().toLowerCase()
+ RodaConstants.METADATA_VERSION_SEPARATOR + descriptiveMetadata.getVersion().toLowerCase(),
labelWithoutVersion);
bundle.setLabel(labelWithVersion);
} else {
bundle.setLabel(labelWithoutVersion);
}
} catch (MissingResourceException e) {
bundle.setLabel(descriptiveMetadata.getId());
}
}
try {
StoragePath storagePath;
if (representationId != null) {
storagePath = ModelUtils.getDescriptiveMetadataStoragePath(aipId, representationId,
descriptiveMetadata.getId());
} else {
storagePath = ModelUtils.getDescriptiveMetadataStoragePath(aipId, descriptiveMetadata.getId());
}
bundle.setHasHistory(!CloseableIterables.isEmpty(model.getStorage().listBinaryVersions(storagePath)));
} catch (RODAException | RuntimeException t) {
bundle.setHasHistory(false);
}
return bundle;
}
private static DescriptiveMetadataViewBundle retrieveDescriptiveMetadataBundle(String aipId, String representationId,
String descriptiveMetadataId, final Locale locale)
throws GenericException, RequestNotValidException, NotFoundException, AuthorizationDeniedException {
ModelService model = RodaCoreFactory.getModelService();
DescriptiveMetadata descriptiveMetadata = model.retrieveDescriptiveMetadata(aipId, representationId,
descriptiveMetadataId);
return retrieveDescriptiveMetadataBundle(aipId, representationId, descriptiveMetadata, locale);
}
public static DescriptiveMetadataEditBundle retrieveDescriptiveMetadataEditBundle(User user, IndexedAIP aip,
IndexedRepresentation representation, String descriptiveMetadataId, final Locale locale)
throws GenericException, RequestNotValidException, NotFoundException, AuthorizationDeniedException {
String representationId = representation != null ? representation.getId() : null;
DescriptiveMetadata metadata = RodaCoreFactory.getModelService().retrieveDescriptiveMetadata(aip.getId(),
representationId, descriptiveMetadataId);
return retrieveDescriptiveMetadataEditBundle(user, aip, representation, descriptiveMetadataId, metadata.getType(),
metadata.getVersion(), locale);
}
public static DescriptiveMetadataEditBundle retrieveDescriptiveMetadataEditBundle(User user, IndexedAIP aip,
IndexedRepresentation representation, String descriptiveMetadataId, String type, String version,
final Locale locale)
throws GenericException, RequestNotValidException, NotFoundException, AuthorizationDeniedException {
DescriptiveMetadataEditBundle ret;
InputStream inputStream = null;
try {
String representationId = representation != null ? representation.getId() : null;
Binary binary = RodaCoreFactory.getModelService().retrieveDescriptiveMetadataBinary(aip.getId(), representationId,
descriptiveMetadataId);
inputStream = binary.getContent().createInputStream();
String xml = IOUtils.toString(inputStream, "UTF-8");
// Get the supported metadata type with the same type and version
// We need this to try to get get the values for the form
SupportedMetadataTypeBundle metadataTypeBundle = null;
List<SupportedMetadataTypeBundle> supportedMetadataTypeBundles = BrowserHelper.retrieveSupportedMetadata(user,
aip, representation, locale);
for (SupportedMetadataTypeBundle typeBundle : supportedMetadataTypeBundles) {
if (typeBundle.getType() != null && typeBundle.getType().equalsIgnoreCase(type)) {
if (typeBundle.getVersion() != null && typeBundle.getVersion().equalsIgnoreCase(version)) {
metadataTypeBundle = typeBundle;
break;
}
}
}
boolean similar = false;
// Get the values using XPath
Set<MetadataValue> values = null;
String template = null;
if (metadataTypeBundle != null) {
values = metadataTypeBundle.getValues();
template = metadataTypeBundle.getTemplate();
if (values != null) {
for (MetadataValue mv : values) {
// clear the auto-generated values
// mv.set("value", null);
String xpathRaw = mv.get("xpath");
if (xpathRaw != null && xpathRaw.length() > 0) {
String[] xpaths = xpathRaw.split("##%##");
String value;
List<String> allValues = new ArrayList<>();
for (String xpath : xpaths) {
allValues.addAll(ServerTools.applyXpath(xml, xpath));
}
// if any of the values is different, concatenate all values in a
// string, otherwise return the value
boolean allEqual = allValues.stream().allMatch(s -> s.trim().equals(allValues.get(0).trim()));
if (allEqual && !allValues.isEmpty()) {
value = allValues.get(0);
} else {
value = String.join(" / ", allValues);
}
mv.set("value", value.trim());
}
}
// Identity check. Test if the original XML is equal to the result of
// applying the extracted values to the template
metadataTypeBundle.setValues(values);
String templateWithValues = retrieveDescriptiveMetadataPreview(metadataTypeBundle);
try {
XMLUnit.setIgnoreComments(true);
XMLUnit.setIgnoreWhitespace(true);
XMLUnit.setIgnoreAttributeOrder(true);
XMLUnit.setCompareUnmatched(false);
Diff xmlDiff = new Diff(xml, templateWithValues);
xmlDiff.overrideDifferenceListener(new XMLSimilarityIgnoreElements("schemaLocation"));
similar = xmlDiff.identical() || xmlDiff.similar();
} catch (SAXException e) {
LOGGER.warn("Could not check if template can loose info", e);
}
}
}
ret = new DescriptiveMetadataEditBundle(descriptiveMetadataId, type, version, xml, template, values, similar);
} catch (IOException e) {
throw new GenericException("Error getting descriptive metadata edit bundle: " + e.getMessage());
} finally {
IOUtils.closeQuietly(inputStream);
}
return ret;
}
public static DipBundle retrieveDipBundle(String dipUUID, String dipFileUUID, User user)
throws GenericException, NotFoundException, RequestNotValidException {
DipBundle bundle = new DipBundle();
bundle
.setDip(retrieve(IndexedDIP.class, dipUUID,
Arrays.asList(RodaConstants.INDEX_UUID, RodaConstants.DIP_ID, RodaConstants.DIP_TITLE,
RodaConstants.DIP_AIP_IDS, RodaConstants.DIP_AIP_UUIDS, RodaConstants.DIP_FILE_IDS,
RodaConstants.DIP_REPRESENTATION_IDS)));
List<String> dipFileFields = new ArrayList<>();
if (dipFileUUID != null) {
DIPFile dipFile = retrieve(DIPFile.class, dipFileUUID, dipFileFields);
bundle.setDipFile(dipFile);
List<DIPFile> dipFileAncestors = new ArrayList<>();
for (String dipFileAncestor : dipFile.getAncestorsUUIDs()) {
try {
dipFileAncestors.add(retrieve(DIPFile.class, dipFileAncestor,
Arrays.asList(RodaConstants.INDEX_UUID, RodaConstants.DIPFILE_DIP_ID, RodaConstants.DIPFILE_ID)));
} catch (NotFoundException e) {
// ignore
}
}
bundle.setDipFileAncestors(dipFileAncestors);
} else {
// if there is only one DIPFile in the DIP and it is NOT a directory
// then select it
Filter filter = new Filter(new SimpleFilterParameter(RodaConstants.DIPFILE_DIP_ID, dipUUID));
Sublist sublist = new Sublist(0, 1);
IndexResult<DIPFile> dipFiles = find(DIPFile.class, filter, Sorter.NONE, sublist, Facets.NONE, user, false,
dipFileFields);
if (dipFiles.getTotalCount() == 1 && !dipFiles.getResults().get(0).isDirectory()) {
bundle.setDipFile(dipFiles.getResults().get(0));
}
}
List<String> aipFields = Arrays.asList(RodaConstants.INDEX_UUID, RodaConstants.AIP_TITLE, RodaConstants.AIP_LEVEL,
RodaConstants.AIP_DATE_FINAL, RodaConstants.AIP_DATE_INITIAL, RodaConstants.AIP_GHOST);
List<String> representationFields = Arrays.asList(RodaConstants.INDEX_UUID, RodaConstants.REPRESENTATION_TYPE,
RodaConstants.REPRESENTATION_NUMBER_OF_DATA_FILES, RodaConstants.REPRESENTATION_ORIGINAL,
RodaConstants.REPRESENTATION_AIP_ID, RodaConstants.REPRESENTATION_ID);
List<String> fileFields = new ArrayList<>();
// infer from DIP
IndexedDIP dip = bundle.getDip();
if (!dip.getFileIds().isEmpty()) {
IndexedFile file = BrowserHelper.retrieve(IndexedFile.class, IdUtils.getFileId(dip.getFileIds().get(0)),
fileFields);
bundle.setFile(file);
bundle.setRepresentation(
BrowserHelper.retrieve(IndexedRepresentation.class, file.getRepresentationUUID(), representationFields));
bundle.setAip(BrowserHelper.retrieve(IndexedAIP.class, file.getAipId(), aipFields));
} else if (!dip.getRepresentationIds().isEmpty()) {
IndexedRepresentation representation = BrowserHelper.retrieve(IndexedRepresentation.class,
IdUtils.getRepresentationId(dip.getRepresentationIds().get(0)), representationFields);
bundle.setRepresentation(representation);
bundle.setAip(BrowserHelper.retrieve(IndexedAIP.class, representation.getAipId(), aipFields));
} else if (!dip.getAipIds().isEmpty()) {
IndexedAIP aip = BrowserHelper.retrieve(IndexedAIP.class, dip.getAipIds().get(0).getAipId(), aipFields);
bundle.setAip(aip);
}
return bundle;
}
protected static List<IndexedAIP> retrieveAncestors(IndexedAIP aip, List<String> fieldsToReturn)
throws GenericException, NotFoundException {
return RodaCoreFactory.getIndexService().retrieveAncestors(aip, fieldsToReturn);
}
protected static <T extends IsIndexed> IndexResult<T> find(Class<T> returnClass, Filter filter, Sorter sorter,
Sublist sublist, Facets facets, User user, boolean justActive, List<String> fieldsToReturn)
throws GenericException, RequestNotValidException {
return RodaCoreFactory.getIndexService().find(returnClass, filter, sorter, sublist, facets, user, justActive,
fieldsToReturn);
}
protected static <T extends IsIndexed> IterableIndexResult<T> findAll(final Class<T> returnClass, final Filter filter,
final Sorter sorter, final Sublist sublist, final Facets facets, final User user, final boolean justActive,
List<String> fieldsToReturn) {
return RodaCoreFactory.getIndexService().findAll(returnClass, filter, sorter, sublist, facets, user, justActive,
fieldsToReturn);
}
protected static <T extends IsIndexed> Long count(Class<T> returnClass, Filter filter, boolean justActive, User user)
throws GenericException, RequestNotValidException {
return RodaCoreFactory.getIndexService().count(returnClass, filter, user, justActive);
}
protected static <T extends IsIndexed> T retrieve(Class<T> returnClass, String id, List<String> fieldsToReturn)
throws GenericException, NotFoundException {
return RodaCoreFactory.getIndexService().retrieve(returnClass, id, fieldsToReturn);
}
protected static <T extends IsIndexed> void commit(Class<T> returnClass) throws GenericException, NotFoundException {
RodaCoreFactory.getIndexService().commit(returnClass);
}
protected static <T extends IsIndexed> List<T> retrieve(Class<T> returnClass, SelectedItems<T> selectedItems,
List<String> fieldsToReturn) throws GenericException, NotFoundException, RequestNotValidException {
List<T> ret;
if (selectedItems instanceof SelectedItemsList) {
SelectedItemsList<T> selectedList = (SelectedItemsList<T>) selectedItems;
ret = RodaCoreFactory.getIndexService().retrieve(returnClass, selectedList.getIds(), fieldsToReturn);
} else if (selectedItems instanceof SelectedItemsFilter) {
SelectedItemsFilter<T> selectedFilter = (SelectedItemsFilter<T>) selectedItems;
int counter = RodaCoreFactory.getIndexService().count(returnClass, selectedFilter.getFilter()).intValue();
ret = RodaCoreFactory.getIndexService()
.find(returnClass, selectedFilter.getFilter(), Sorter.NONE, new Sublist(0, counter), fieldsToReturn)
.getResults();
} else {
throw new RequestNotValidException(
"Unsupported SelectedItems implementation: " + selectedItems.getClass().getName());
}
return ret;
}
protected static <T extends IsIndexed> List<String> suggest(Class<T> returnClass, String field, String query,
User user, boolean allowPartial) throws GenericException, NotFoundException {
boolean justActive = true;
return RodaCoreFactory.getIndexService().suggest(returnClass, field, query, user, allowPartial, justActive);
}
public static void validateGetFileParams(String acceptFormat) throws RequestNotValidException {
if (!RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_BIN.equals(acceptFormat)
&& !RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_JSON.equals(acceptFormat)
&& !RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_XML.equals(acceptFormat)) {
throw new RequestNotValidException("Invalid '" + RodaConstants.API_QUERY_KEY_ACCEPT_FORMAT
+ "' value. Expected values: " + Arrays.asList(RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_XML,
RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_JSON, RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_BIN));
}
}
protected static void validateGetAIPRepresentationParams(String acceptFormat) throws RequestNotValidException {
if (!RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_ZIP.equals(acceptFormat)
&& !RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_JSON.equals(acceptFormat)
&& !RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_XML.equals(acceptFormat)) {
throw new RequestNotValidException("Invalid '" + RodaConstants.API_QUERY_KEY_ACCEPT_FORMAT
+ "' value. Expected values: " + Arrays.asList(RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_JSON,
RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_XML, RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_ZIP));
}
}
protected static void validateGetDIPParams(String acceptFormat) throws RequestNotValidException {
if (!RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_ZIP.equals(acceptFormat)
&& !RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_JSON.equals(acceptFormat)
&& !RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_XML.equals(acceptFormat)) {
throw new RequestNotValidException("Invalid '" + RodaConstants.API_QUERY_KEY_ACCEPT_FORMAT
+ "' value. Expected values: " + Arrays.asList(RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_JSON,
RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_XML, RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_ZIP));
}
}
protected static EntityResponse retrieveAIPRepresentation(IndexedRepresentation representation, String acceptFormat)
throws GenericException, RequestNotValidException, NotFoundException, AuthorizationDeniedException {
String aipId = representation.getAipId();
String representationId = representation.getId();
if (RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_ZIP.equals(acceptFormat)) {
StoragePath storagePath = ModelUtils.getRepresentationStoragePath(representation.getAipId(),
representation.getId());
Directory directory = RodaCoreFactory.getStorageService().getDirectory(storagePath);
return ApiUtils.download(directory, representationId);
} else if (RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_JSON.equals(acceptFormat)
|| RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_XML.equals(acceptFormat)) {
ModelService model = RodaCoreFactory.getModelService();
Representation rep = model.retrieveRepresentation(aipId, representationId);
return new ObjectResponse<Representation>(acceptFormat, rep);
} else {
throw new GenericException("Unsupported accept format: " + acceptFormat);
}
}
public static StreamResponse retrieveAIPRepresentationPart(IndexedRepresentation representation, String part)
throws RequestNotValidException, NotFoundException, GenericException, AuthorizationDeniedException {
String aipId = representation.getAipId();
String representationId = representation.getId();
if (RodaConstants.STORAGE_DIRECTORY_DATA.equals(part)) {
StoragePath storagePath = ModelUtils.getRepresentationDataStoragePath(aipId, representationId);
Directory directory = RodaCoreFactory.getStorageService().getDirectory(storagePath);
return ApiUtils.download(directory, part);
} else if (RodaConstants.STORAGE_DIRECTORY_METADATA.equals(part)) {
StoragePath storagePath = ModelUtils.getRepresentationMetadataStoragePath(aipId, representationId);
Directory directory = RodaCoreFactory.getStorageService().getDirectory(storagePath);
return ApiUtils.download(directory, part);
} else if (RodaConstants.STORAGE_DIRECTORY_DOCUMENTATION.equals(part)) {
Directory directory = RodaCoreFactory.getModelService().getDocumentationDirectory(aipId, representationId);
return ApiUtils.download(directory, part);
} else if (RodaConstants.STORAGE_DIRECTORY_SCHEMAS.equals(part)) {
Directory directory = RodaCoreFactory.getModelService().getSchemasDirectory(aipId, representationId);
return ApiUtils.download(directory, part);
} else {
throw new GenericException("Unsupported part: " + part);
}
}
protected static void validateListAIPDescriptiveMetadataParams(String acceptFormat) throws RequestNotValidException {
if (!RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_ZIP.equals(acceptFormat)
&& !RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_JSON.equals(acceptFormat)
&& !RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_XML.equals(acceptFormat)) {
throw new RequestNotValidException("Invalid '" + RodaConstants.API_QUERY_KEY_ACCEPT_FORMAT
+ "' value. Expected values: " + Arrays.asList(RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_ZIP,
RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_JSON, RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_XML));
}
}
public static void validateGetOtherMetadataParams(String acceptFormat) throws RequestNotValidException {
if (!RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_BIN.equals(acceptFormat)
&& !RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_JSON.equals(acceptFormat)
&& !RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_XML.equals(acceptFormat)) {
throw new RequestNotValidException("Invalid '" + RodaConstants.API_QUERY_KEY_ACCEPT_FORMAT
+ "' value. Expected values: " + Arrays.asList(RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_XML,
RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_JSON, RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_BIN));
}
}
protected static EntityResponse listAIPDescriptiveMetadata(String aipId, String start, String limit,
String acceptFormat)
throws RequestNotValidException, NotFoundException, GenericException, AuthorizationDeniedException {
ModelService model = RodaCoreFactory.getModelService();
AIP aip = model.retrieveAIP(aipId);
List<DescriptiveMetadata> metadata = aip.getDescriptiveMetadata();
return listDescriptiveMetadata(metadata, aipId, start, limit, acceptFormat);
}
protected static EntityResponse listRepresentationDescriptiveMetadata(String aipId, String representationId,
String start, String limit, String acceptFormat)
throws RequestNotValidException, NotFoundException, GenericException, AuthorizationDeniedException {
ModelService model = RodaCoreFactory.getModelService();
Representation representation = model.retrieveRepresentation(aipId, representationId);
List<DescriptiveMetadata> metadata = representation.getDescriptiveMetadata();
return listDescriptiveMetadata(metadata, aipId, start, limit, acceptFormat);
}
private static EntityResponse listDescriptiveMetadata(List<DescriptiveMetadata> metadata, String aipId, String start,
String limit, String acceptFormat)
throws RequestNotValidException, GenericException, NotFoundException, AuthorizationDeniedException {
StorageService storage = RodaCoreFactory.getStorageService();
Pair<Integer, Integer> pagingParams = ApiUtils.processPagingParams(start, limit);
int startInt = pagingParams.getFirst();
int limitInt = pagingParams.getSecond();
int counter = 0;
if (RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_ZIP.equals(acceptFormat)) {
List<ZipEntryInfo> zipEntries = new ArrayList<>();
for (DescriptiveMetadata dm : metadata) {
if (counter >= startInt && (counter <= limitInt || limitInt == -1)) {
StoragePath storagePath = ModelUtils.getDescriptiveMetadataStoragePath(aipId, dm.getId());
Binary binary = storage.getBinary(storagePath);
ZipEntryInfo info = new ZipEntryInfo(storagePath.getName(), binary.getContent());
zipEntries.add(info);
} else {
break;
}
counter++;
}
return DownloadUtils.createZipStreamResponse(zipEntries, aipId);
} else if (RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_JSON.equals(acceptFormat)
|| RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_XML.equals(acceptFormat)) {
int endInt = limitInt == -1 ? metadata.size() : (limitInt > metadata.size() ? metadata.size() : limitInt);
DescriptiveMetadataList list = new DescriptiveMetadataList(metadata.subList(startInt, endInt));
return new ObjectResponse<DescriptiveMetadataList>(acceptFormat, list);
}
return null;
}
protected static void validateGetPreservationMetadataParams(String acceptFormat) throws RequestNotValidException {
if (!RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_XML.equals(acceptFormat)
&& !RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_HTML.equals(acceptFormat)
&& !RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_JSON.equals(acceptFormat)
&& !RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_BIN.equals(acceptFormat)) {
throw new RequestNotValidException(
"Invalid '" + RodaConstants.API_QUERY_KEY_ACCEPT_FORMAT + "' value. Expected values: "
+ Arrays.asList(RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_XML,
RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_HTML, RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_JSON,
RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_BIN));
}
}
protected static void validateGetAIPDescriptiveMetadataParams(String acceptFormat) throws RequestNotValidException {
if (!RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_XML.equals(acceptFormat)
&& !RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_HTML.equals(acceptFormat)
&& !RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_JSON.equals(acceptFormat)
&& !RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_BIN.equals(acceptFormat)) {
throw new RequestNotValidException(
"Invalid '" + RodaConstants.API_QUERY_KEY_ACCEPT_FORMAT + "' value. Expected values: "
+ Arrays.asList(RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_XML,
RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_HTML, RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_JSON,
RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_BIN));
}
}
public static EntityResponse retrieveAIPDescritiveMetadata(String aipId, String metadataId, String acceptFormat,
String language)
throws GenericException, RequestNotValidException, NotFoundException, AuthorizationDeniedException {
final String filename;
final String mediaType;
final ConsumesOutputStream stream;
StreamResponse ret;
ModelService model = RodaCoreFactory.getModelService();
if (RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_BIN.equals(acceptFormat)) {
Binary descriptiveMetadataBinary = model.retrieveDescriptiveMetadataBinary(aipId, metadataId);
filename = descriptiveMetadataBinary.getStoragePath().getName();
mediaType = RodaConstants.MEDIA_TYPE_TEXT_XML;
stream = new ConsumesOutputStream() {
@Override
public String getMediaType() {
return mediaType;
}
@Override
public String getFileName() {
return filename;
}
@Override
public void consumeOutputStream(OutputStream out) throws IOException {
IOUtils.copy(descriptiveMetadataBinary.getContent().createInputStream(), out);
}
};
ret = new StreamResponse(filename, mediaType, stream);
} else if (RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_HTML.equals(acceptFormat)) {
Binary descriptiveMetadataBinary = model.retrieveDescriptiveMetadataBinary(aipId, metadataId);
filename = descriptiveMetadataBinary.getStoragePath().getName() + HTML_EXT;
DescriptiveMetadata descriptiveMetadata = model.retrieveDescriptiveMetadata(aipId, metadataId);
mediaType = RodaConstants.MEDIA_TYPE_TEXT_HTML;
String htmlDescriptive = HTMLUtils.descriptiveMetadataToHtml(descriptiveMetadataBinary,
descriptiveMetadata.getType(), descriptiveMetadata.getVersion(), ServerTools.parseLocale(language));
stream = new ConsumesOutputStream() {
@Override
public String getMediaType() {
return mediaType;
}
@Override
public String getFileName() {
return filename;
}
@Override
public void consumeOutputStream(OutputStream out) throws IOException {
PrintStream printStream = new PrintStream(out);
printStream.print(htmlDescriptive);
printStream.close();
}
};
ret = new StreamResponse(filename, mediaType, stream);
} else if (RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_JSON.equals(acceptFormat)
|| RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_XML.equals(acceptFormat)) {
AIP aip = model.retrieveAIP(aipId);
List<DescriptiveMetadata> resultList = aip.getDescriptiveMetadata().stream()
.filter(dm -> dm.getId().equals(metadataId)).collect(Collectors.toList());
return new ObjectResponse<DescriptiveMetadata>(acceptFormat, resultList.get(0));
} else {
throw new GenericException("Unsupported accept format: " + acceptFormat);
}
return ret;
}
public static EntityResponse retrieveRepresentationDescriptiveMetadata(String aipId, String representationId,
String metadataId, String acceptFormat, String language)
throws GenericException, RequestNotValidException, NotFoundException, AuthorizationDeniedException {
final String filename;
final String mediaType;
final ConsumesOutputStream stream;
StreamResponse ret;
ModelService model = RodaCoreFactory.getModelService();
if (RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_BIN.equals(acceptFormat)) {
Binary descriptiveMetadataBinary = model.retrieveDescriptiveMetadataBinary(aipId, representationId, metadataId);
filename = descriptiveMetadataBinary.getStoragePath().getName();
mediaType = RodaConstants.MEDIA_TYPE_TEXT_XML;
stream = new ConsumesOutputStream() {
@Override
public String getMediaType() {
return mediaType;
}
@Override
public String getFileName() {
return filename;
}
@Override
public void consumeOutputStream(OutputStream out) throws IOException {
IOUtils.copy(descriptiveMetadataBinary.getContent().createInputStream(), out);
}
};
ret = new StreamResponse(filename, mediaType, stream);
} else if (RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_HTML.equals(acceptFormat)) {
Binary descriptiveMetadataBinary = model.retrieveDescriptiveMetadataBinary(aipId, representationId, metadataId);
filename = descriptiveMetadataBinary.getStoragePath().getName() + HTML_EXT;
DescriptiveMetadata descriptiveMetadata = model.retrieveDescriptiveMetadata(aipId, representationId, metadataId);
mediaType = RodaConstants.MEDIA_TYPE_TEXT_HTML;
String htmlDescriptive = HTMLUtils.descriptiveMetadataToHtml(descriptiveMetadataBinary,
descriptiveMetadata.getType(), descriptiveMetadata.getVersion(), ServerTools.parseLocale(language));
stream = new ConsumesOutputStream() {
@Override
public String getMediaType() {
return mediaType;
}
@Override
public String getFileName() {
return filename;
}
@Override
public void consumeOutputStream(OutputStream out) throws IOException {
PrintStream printStream = new PrintStream(out);
printStream.print(htmlDescriptive);
printStream.close();
}
};
ret = new StreamResponse(filename, mediaType, stream);
} else if (RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_JSON.equals(acceptFormat)
|| RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_XML.equals(acceptFormat)) {
Representation representation = model.retrieveRepresentation(aipId, representationId);
List<DescriptiveMetadata> resultList = representation.getDescriptiveMetadata().stream()
.filter(dm -> dm.getId().equals(metadataId)).collect(Collectors.toList());
return new ObjectResponse<DescriptiveMetadata>(acceptFormat, resultList.get(0));
} else {
throw new GenericException("Unsupported accept format: " + acceptFormat);
}
return ret;
}
public static EntityResponse retrieveAIPDescritiveMetadataVersion(String aipId, String metadataId, String versionId,
String acceptFormat, String language)
throws GenericException, RequestNotValidException, NotFoundException, AuthorizationDeniedException {
final String filename;
final String mediaType;
final ConsumesOutputStream stream;
ModelService model = RodaCoreFactory.getModelService();
StoragePath storagePath = ModelUtils.getDescriptiveMetadataStoragePath(aipId, metadataId);
BinaryVersion binaryVersion = model.getStorage().getBinaryVersion(storagePath, versionId);
Binary binary = binaryVersion.getBinary();
String fileName = binary.getStoragePath().getName();
if (RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_BIN.equals(acceptFormat)) {
mediaType = RodaConstants.MEDIA_TYPE_TEXT_XML;
stream = new ConsumesOutputStream() {
@Override
public String getMediaType() {
return mediaType;
}
@Override
public String getFileName() {
return fileName;
}
@Override
public void consumeOutputStream(OutputStream out) throws IOException {
IOUtils.copy(binary.getContent().createInputStream(), out);
}
};
return new StreamResponse(fileName, mediaType, stream);
} else if (RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_HTML.equals(acceptFormat)) {
filename = fileName + HTML_EXT;
DescriptiveMetadata descriptiveMetadata = model.retrieveDescriptiveMetadata(aipId, metadataId);
mediaType = RodaConstants.MEDIA_TYPE_TEXT_HTML;
String htmlDescriptive = HTMLUtils.descriptiveMetadataToHtml(binary, descriptiveMetadata.getType(),
descriptiveMetadata.getVersion(), ServerTools.parseLocale(language));
stream = new ConsumesOutputStream() {
@Override
public String getMediaType() {
return mediaType;
}
@Override
public String getFileName() {
return filename;
}
@Override
public void consumeOutputStream(OutputStream out) throws IOException {
PrintStream printStream = new PrintStream(out);
printStream.print(htmlDescriptive);
printStream.close();
}
};
return new StreamResponse(filename, mediaType, stream);
} else if (RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_JSON.equals(acceptFormat)
|| RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_XML.equals(acceptFormat)) {
AIP aip = model.retrieveAIP(aipId);
List<DescriptiveMetadata> resultList = aip.getDescriptiveMetadata().stream()
.filter(dm -> dm.getId().equals(metadataId)).collect(Collectors.toList());
return new ObjectResponse<DescriptiveMetadata>(acceptFormat, resultList.get(0));
} else {
throw new GenericException("Unsupported accept format: " + acceptFormat);
}
}
public static EntityResponse retrieveRepresentationDescriptiveMetadataVersion(String aipId, String representationId,
String metadataId, String versionId, String acceptFormat, String language)
throws GenericException, RequestNotValidException, NotFoundException, AuthorizationDeniedException {
final String filename;
final String mediaType;
final ConsumesOutputStream stream;
ModelService model = RodaCoreFactory.getModelService();
StoragePath storagePath = ModelUtils.getDescriptiveMetadataStoragePath(aipId, representationId, metadataId);
BinaryVersion binaryVersion = model.getStorage().getBinaryVersion(storagePath, versionId);
Binary binary = binaryVersion.getBinary();
String fileName = binary.getStoragePath().getName();
if (RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_BIN.equals(acceptFormat)) {
mediaType = RodaConstants.MEDIA_TYPE_TEXT_XML;
stream = new ConsumesOutputStream() {
@Override
public String getMediaType() {
return mediaType;
}
@Override
public String getFileName() {
return binary.getStoragePath().getName();
}
@Override
public void consumeOutputStream(OutputStream out) throws IOException {
IOUtils.copy(binary.getContent().createInputStream(), out);
}
};
return new StreamResponse(fileName, mediaType, stream);
} else if (RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_HTML.equals(acceptFormat)) {
filename = fileName + HTML_EXT;
DescriptiveMetadata descriptiveMetadata = model.retrieveDescriptiveMetadata(aipId, representationId, metadataId);
mediaType = RodaConstants.MEDIA_TYPE_TEXT_HTML;
String htmlDescriptive = HTMLUtils.descriptiveMetadataToHtml(binary, descriptiveMetadata.getType(),
descriptiveMetadata.getVersion(), ServerTools.parseLocale(language));
stream = new ConsumesOutputStream() {
@Override
public String getMediaType() {
return mediaType;
}
@Override
public String getFileName() {
return fileName + HTML_EXT;
}
@Override
public void consumeOutputStream(OutputStream out) throws IOException {
PrintStream printStream = new PrintStream(out);
printStream.print(htmlDescriptive);
printStream.close();
}
};
return new StreamResponse(filename, mediaType, stream);
} else if (RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_JSON.equals(acceptFormat)
|| RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_XML.equals(acceptFormat)) {
AIP aip = model.retrieveAIP(aipId);
List<DescriptiveMetadata> resultList = new ArrayList<>();
for (Representation representation : aip.getRepresentations()) {
if (representation.getId().equals(representationId)) {
resultList = representation.getDescriptiveMetadata().stream().filter(dm -> dm.getId().equals(metadataId))
.collect(Collectors.toList());
}
}
return new ObjectResponse<DescriptiveMetadata>(acceptFormat, resultList.get(0));
} else {
throw new GenericException("Unsupported accept format: " + acceptFormat);
}
}
protected static void validateListAIPMetadataParams(String acceptFormat) throws RequestNotValidException {
if (!RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_ZIP.equals(acceptFormat)
&& !RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_JSON.equals(acceptFormat)
&& !RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_XML.equals(acceptFormat)) {
throw new RequestNotValidException("Invalid '" + RodaConstants.API_QUERY_KEY_ACCEPT_FORMAT
+ "' value. Expected values: " + Arrays.asList(RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_ZIP,
RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_JSON, RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_XML));
}
}
public static EntityResponse listAIPPreservationMetadata(String aipId, String acceptFormat)
throws GenericException, NotFoundException, RequestNotValidException, AuthorizationDeniedException {
if (RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_ZIP.equals(acceptFormat)) {
CloseableIterable<OptionalWithCause<PreservationMetadata>> preservationFiles = RodaCoreFactory.getModelService()
.listPreservationMetadata(aipId, true);
StorageService storage = RodaCoreFactory.getStorageService();
List<ZipEntryInfo> zipEntries = new ArrayList<>();
Map<String, ZipEntryInfo> agents = new HashMap<>();
for (OptionalWithCause<PreservationMetadata> oPreservationFile : preservationFiles) {
if (oPreservationFile.isPresent()) {
PreservationMetadata preservationFile = oPreservationFile.get();
StoragePath storagePath = ModelUtils.getPreservationMetadataStoragePath(preservationFile);
Binary binary = storage.getBinary(storagePath);
ZipEntryInfo info = new ZipEntryInfo(FSUtils.getStoragePathAsString(storagePath, true), binary.getContent());
zipEntries.add(info);
if (preservationFile.getType() == PreservationMetadataType.EVENT) {
try {
List<LinkingIdentifier> agentIDS = PremisV3Utils.extractAgentsFromEvent(binary);
if (!agentIDS.isEmpty()) {
for (LinkingIdentifier li : agentIDS) {
String agentID = li.getValue();
if (!agents.containsKey(agentID)) {
StoragePath agentPath = ModelUtils.getPreservationMetadataStoragePath(agentID,
PreservationMetadataType.AGENT);
Binary agentBinary = storage.getBinary(agentPath);
info = new ZipEntryInfo(
FSUtils.getStoragePathAsString(DefaultStoragePath.parse(preservationFile.getAipId()), false,
agentPath, true),
agentBinary.getContent());
agents.put(agentID, info);
}
}
}
} catch (ValidationException | GenericException e) {
// do nothing
}
}
} else {
LOGGER.error("Cannot get AIP preservation metadata", oPreservationFile.getCause());
}
}
if (agents.size() > 0) {
for (Map.Entry<String, ZipEntryInfo> entry : agents.entrySet()) {
zipEntries.add(entry.getValue());
}
}
IOUtils.closeQuietly(preservationFiles);
return DownloadUtils.createZipStreamResponse(zipEntries, aipId);
} else if (RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_JSON.equals(acceptFormat)
|| RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_XML.equals(acceptFormat)) {
CloseableIterable<OptionalWithCause<PreservationMetadata>> preservationFiles = RodaCoreFactory.getModelService()
.listPreservationMetadata(aipId, true);
PreservationMetadataList metadataList = new PreservationMetadataList();
for (OptionalWithCause<PreservationMetadata> oPreservationFile : preservationFiles) {
if (oPreservationFile.isPresent()) {
metadataList.addObject(oPreservationFile.get());
}
}
IOUtils.closeQuietly(preservationFiles);
return new ObjectResponse<PreservationMetadataList>(acceptFormat, metadataList);
} else {
throw new GenericException("Unsupported accept format: " + acceptFormat);
}
}
protected static void validateGetAIPRepresentationPreservationMetadataParams(String acceptFormat)
throws RequestNotValidException {
if (!RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_ZIP.equals(acceptFormat)
&& !RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_JSON.equals(acceptFormat)
&& !RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_XML.equals(acceptFormat)) {
throw new RequestNotValidException("Invalid '" + RodaConstants.API_QUERY_KEY_ACCEPT_FORMAT
+ "' value. Expected values: " + Arrays.asList(RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_ZIP,
RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_JSON, RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_XML));
}
}
private static EntityResponse getAIPRepresentationPreservationMetadataEntityResponse(String aipId,
String representationId, String startAgent, String limitAgent, String startEvent, String limitEvent,
String startFile, String limitFile, String acceptFormat,
CloseableIterable<OptionalWithCause<PreservationMetadata>> preservationFiles)
throws GenericException, RequestNotValidException, NotFoundException, AuthorizationDeniedException, IOException {
Pair<Integer, Integer> pagingParamsAgent = ApiUtils.processPagingParams(startAgent, limitAgent);
int counterAgent = 0;
Pair<Integer, Integer> pagingParamsEvent = ApiUtils.processPagingParams(startEvent, limitEvent);
int counterEvent = 0;
Pair<Integer, Integer> pagingParamsFile = ApiUtils.processPagingParams(startFile, limitFile);
int counterFile = 0;
List<ZipEntryInfo> zipEntries = new ArrayList<>();
PreservationMetadataList pms = new PreservationMetadataList();
for (OptionalWithCause<PreservationMetadata> oPreservationFile : preservationFiles) {
if (oPreservationFile.isPresent()) {
PreservationMetadata preservationFile = oPreservationFile.get();
boolean add = false;
if (preservationFile.getType().equals(PreservationMetadataType.AGENT)) {
if (counterAgent >= pagingParamsAgent.getFirst()
&& (counterAgent <= pagingParamsAgent.getSecond() || pagingParamsAgent.getSecond() == -1)) {
add = true;
}
counterAgent++;
} else if (preservationFile.getType().equals(PreservationMetadataType.EVENT)) {
if (counterEvent >= pagingParamsEvent.getFirst()
&& (counterEvent <= pagingParamsEvent.getSecond() || pagingParamsEvent.getSecond() == -1)) {
add = true;
}
counterEvent++;
} else if (preservationFile.getType().equals(PreservationMetadataType.FILE)) {
if (counterFile >= pagingParamsFile.getFirst()
&& (counterFile <= pagingParamsFile.getSecond() || pagingParamsFile.getSecond() == -1)) {
add = true;
}
counterFile++;
}
if (add) {
if (RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_ZIP.equals(acceptFormat)) {
StoragePath storagePath = ModelUtils.getPreservationMetadataStoragePath(preservationFile);
Binary binary = RodaCoreFactory.getStorageService().getBinary(storagePath);
ZipEntryInfo info = new ZipEntryInfo(storagePath.getName(), binary.getContent());
zipEntries.add(info);
} else {
pms.addObject(preservationFile);
}
}
} else {
LOGGER.error("Cannot get AIP preservation metadata", oPreservationFile.getCause());
}
}
IOUtils.closeQuietly(preservationFiles);
if (RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_ZIP.equals(acceptFormat)) {
return DownloadUtils.createZipStreamResponse(zipEntries, aipId + "_" + representationId);
} else {
return new ObjectResponse<PreservationMetadataList>(acceptFormat, pms);
}
}
public static EntityResponse retrieveAIPRepresentationPreservationMetadata(String aipId, String representationId,
String startAgent, String limitAgent, String startEvent, String limitEvent, String startFile, String limitFile,
String acceptFormat)
throws GenericException, NotFoundException, RequestNotValidException, AuthorizationDeniedException, IOException {
if (RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_ZIP.equals(acceptFormat)
|| RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_JSON.equals(acceptFormat)
|| RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_XML.equals(acceptFormat)) {
CloseableIterable<OptionalWithCause<PreservationMetadata>> preservationFiles = RodaCoreFactory.getModelService()
.listPreservationMetadata(aipId, representationId);
return getAIPRepresentationPreservationMetadataEntityResponse(aipId, representationId, startAgent, limitAgent,
startEvent, limitEvent, startFile, limitFile, acceptFormat, preservationFiles);
} else {
throw new GenericException("Unsupported accept format: " + acceptFormat);
}
}
public static EntityResponse retrieveAIPRepresentationPreservationMetadataFile(String aipId, String representationId,
List<String> filePath, String fileId, String acceptFormat)
throws NotFoundException, GenericException, RequestNotValidException, AuthorizationDeniedException {
ModelService model = RodaCoreFactory.getModelService();
if (RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_ZIP.equals(acceptFormat)) {
Binary binary = model.retrievePreservationRepresentation(aipId, representationId, filePath, fileId);
String filename = binary.getStoragePath().getName();
ConsumesOutputStream stream = new ConsumesOutputStream() {
@Override
public String getMediaType() {
return acceptFormat;
}
@Override
public String getFileName() {
return filename;
}
@Override
public void consumeOutputStream(OutputStream out) throws IOException {
IOUtils.copy(binary.getContent().createInputStream(), out);
}
};
return new StreamResponse(filename, RodaConstants.MEDIA_TYPE_APPLICATION_OCTET_STREAM, stream);
} else if (RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_JSON.equals(acceptFormat)
|| RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_XML.equals(acceptFormat)) {
PreservationMetadataType type = PreservationMetadataType.REPRESENTATION;
if (fileId != null) {
type = PreservationMetadataType.FILE;
}
PreservationMetadata pm = model.retrievePreservationMetadata(aipId, representationId, filePath, fileId, type);
return new ObjectResponse<PreservationMetadata>(acceptFormat, pm);
} else {
throw new GenericException("Unsupported accept format: " + acceptFormat);
}
}
public static void createOrUpdateAIPRepresentationPreservationMetadataFile(String aipId, String representationId,
List<String> fileDirectoryPath, String fileId, InputStream is, boolean create)
throws GenericException, RequestNotValidException, NotFoundException, AuthorizationDeniedException,
ValidationException, AlreadyExistsException {
Path file = null;
try {
ModelService model = RodaCoreFactory.getModelService();
file = Files.createTempFile("preservation", ".tmp");
Files.copy(is, file, StandardCopyOption.REPLACE_EXISTING);
ContentPayload payload = new FSPathContentPayload(file);
boolean notify = true;
if (create) {
model.createPreservationMetadata(PreservationMetadataType.FILE, aipId, representationId, fileDirectoryPath,
fileId, payload, notify);
} else {
PreservationMetadataType type = PreservationMetadataType.FILE;
String id = IdUtils.getPreservationFileId(fileId);
model.updatePreservationMetadata(id, type, aipId, representationId, fileDirectoryPath, fileId, payload, notify);
}
} catch (IOException e) {
throw new GenericException("Error creating or updating AIP representation preservation metadata file", e);
} finally {
if (FSUtils.exists(file)) {
try {
Files.delete(file);
} catch (IOException e) {
LOGGER.warn("Error while deleting temporary file", e);
}
}
}
}
public static void deletePreservationMetadataFile(PreservationMetadataType type, String aipId,
String representationId, String id, boolean notify)
throws RequestNotValidException, NotFoundException, GenericException, AuthorizationDeniedException {
RodaCoreFactory.getModelService().deletePreservationMetadata(type, aipId, representationId, id, notify);
}
public static EntityResponse retrievePreservationMetadataEvent(String id, String aipId, String representationUUID,
String fileUUID, boolean onlyDetails, String acceptFormat, String language)
throws NotFoundException, GenericException, RequestNotValidException, AuthorizationDeniedException {
ModelService model = RodaCoreFactory.getModelService();
IndexService index = RodaCoreFactory.getIndexService();
String representationId = null;
List<String> filePath = null;
String fileId = null;
if (fileUUID != null) {
IndexedFile file = index.retrieve(IndexedFile.class, fileUUID, RodaConstants.FILE_FIELDS_TO_RETURN);
representationId = file.getRepresentationId();
filePath = file.getPath();
fileId = file.getId();
} else if (representationUUID != null) {
IndexedRepresentation rep = index.retrieve(IndexedRepresentation.class, representationUUID,
Arrays.asList(RodaConstants.REPRESENTATION_ID));
representationId = rep.getId();
}
if (RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_BIN.equals(acceptFormat)) {
final Binary binary = model.retrievePreservationEvent(aipId, representationId, filePath, fileId, id);
final String mediaType = RodaConstants.MEDIA_TYPE_TEXT_XML;
final ConsumesOutputStream stream = new ConsumesOutputStream() {
@Override
public String getMediaType() {
return mediaType;
}
@Override
public String getFileName() {
return binary.getStoragePath().getName();
}
@Override
public void consumeOutputStream(OutputStream out) throws IOException {
IOUtils.copy(binary.getContent().createInputStream(), out);
}
};
return new StreamResponse(stream.getFileName(), mediaType, stream);
} else if (RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_JSON.equals(acceptFormat)
|| RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_XML.equals(acceptFormat)) {
PreservationMetadata pm = model.retrievePreservationMetadata(aipId, representationId, filePath, fileId,
PreservationMetadataType.EVENT);
return new ObjectResponse<PreservationMetadata>(acceptFormat, pm);
} else if (RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_HTML.equals(acceptFormat)) {
final Binary binary = model.retrievePreservationEvent(aipId, representationId, filePath, fileId, id);
final String filename = binary.getStoragePath().getName() + HTML_EXT;
final String mediaType = RodaConstants.MEDIA_TYPE_TEXT_HTML;
final String htmlEvent = HTMLUtils.preservationMetadataEventToHtml(binary, onlyDetails,
ServerTools.parseLocale(language));
final ConsumesOutputStream stream = new ConsumesOutputStream() {
@Override
public String getMediaType() {
return mediaType;
}
@Override
public String getFileName() {
return filename;
}
@Override
public void consumeOutputStream(OutputStream out) throws IOException {
PrintStream printStream = new PrintStream(out);
printStream.print(htmlEvent);
printStream.close();
}
};
return new StreamResponse(filename, mediaType, stream);
} else {
throw new GenericException("Unsupported accept format: " + acceptFormat);
}
}
public static EntityResponse listOtherMetadata(String aipId, String representationId, List<String> filePath,
String fileId, String type, String acceptFormat)
throws GenericException, NotFoundException, RequestNotValidException, AuthorizationDeniedException {
CloseableIterable<OptionalWithCause<OtherMetadata>> otherFiles = RodaCoreFactory.getModelService()
.listOtherMetadata(aipId, representationId, filePath, fileId, type);
if (RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_ZIP.equals(acceptFormat)) {
StorageService storage = RodaCoreFactory.getStorageService();
List<ZipEntryInfo> zipEntries = new ArrayList<>();
for (OptionalWithCause<OtherMetadata> oFile : otherFiles) {
if (oFile.isPresent()) {
OtherMetadata file = oFile.get();
StoragePath storagePath = ModelUtils.getOtherMetadataStoragePath(aipId, representationId, filePath, fileId,
file.getFileSuffix(), file.getType());
Binary binary = storage.getBinary(storagePath);
ZipEntryInfo info = new ZipEntryInfo(FSUtils.getStoragePathAsString(storagePath, true), binary.getContent());
zipEntries.add(info);
} else {
LOGGER.error("Cannot get list other metadata", oFile.getCause());
}
}
IOUtils.closeQuietly(otherFiles);
return DownloadUtils.createZipStreamResponse(zipEntries, aipId);
} else if (RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_JSON.equals(acceptFormat)
|| RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_XML.equals(acceptFormat)) {
OtherMetadataList metadataList = new OtherMetadataList();
for (OptionalWithCause<OtherMetadata> oFile : otherFiles) {
if (oFile.isPresent()) {
metadataList.addObject(oFile.get());
}
}
IOUtils.closeQuietly(otherFiles);
return new ObjectResponse<OtherMetadataList>(acceptFormat, metadataList);
} else {
throw new GenericException("Unsupported accept format: " + acceptFormat);
}
}
public static EntityResponse retrieveOtherMetadata(String aipId, String representationId, List<String> filePath,
String fileId, String type, String suffix, String acceptFormat)
throws GenericException, NotFoundException, RequestNotValidException, AuthorizationDeniedException {
if (RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_BIN.equals(acceptFormat)) {
final ConsumesOutputStream stream;
Binary otherMetadataBinary = RodaCoreFactory.getModelService().retrieveOtherMetadataBinary(aipId,
representationId, filePath, fileId, suffix, type);
String filename = otherMetadataBinary.getStoragePath().getName();
String mediaType = RodaConstants.MEDIA_TYPE_WILDCARD;
stream = new ConsumesOutputStream() {
@Override
public String getMediaType() {
return acceptFormat;
}
@Override
public String getFileName() {
return filename;
}
@Override
public void consumeOutputStream(OutputStream out) throws IOException {
InputStream fileInputStream = null;
try {
fileInputStream = otherMetadataBinary.getContent().createInputStream();
IOUtils.copy(fileInputStream, out);
} finally {
IOUtils.closeQuietly(fileInputStream);
}
}
};
return new StreamResponse(filename, mediaType, stream);
} else if (RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_JSON.equals(acceptFormat)
|| RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_XML.equals(acceptFormat)) {
OtherMetadata other = RodaCoreFactory.getModelService().retrieveOtherMetadata(aipId, representationId, filePath,
fileId, suffix, type);
return new ObjectResponse<OtherMetadata>(acceptFormat, other);
} else {
throw new GenericException("Unsupported accept format: " + acceptFormat);
}
}
public static OtherMetadata createOrUpdateOtherMetadataFile(String aipId, String representationId,
List<String> fileDirectoryPath, String fileId, String type, String fileSuffix, InputStream is)
throws RequestNotValidException, GenericException, NotFoundException, AuthorizationDeniedException {
try {
Path tempFile = Files.createTempFile("descriptive", ".tmp");
Files.copy(is, tempFile, StandardCopyOption.REPLACE_EXISTING);
ContentPayload payload = new FSPathContentPayload(tempFile);
return RodaCoreFactory.getModelService().createOrUpdateOtherMetadata(aipId, representationId, fileDirectoryPath,
fileId, fileSuffix, type, payload, false);
} catch (IOException e) {
throw new GenericException("Error creating or updating other metadata");
}
}
public static void deleteOtherMetadataFile(String aipId, String representationId, List<String> fileDirectoryPath,
String fileId, String fileSuffix, String type)
throws RequestNotValidException, GenericException, NotFoundException, AuthorizationDeniedException {
RodaCoreFactory.getModelService().deleteOtherMetadata(aipId, representationId, fileDirectoryPath, fileId,
fileSuffix, type);
}
public static IndexedAIP moveAIPInHierarchy(User user, SelectedItems<IndexedAIP> selected, String parentId,
String details) throws GenericException, NotFoundException, RequestNotValidException, AuthorizationDeniedException,
AlreadyExistsException, ValidationException {
Job job = new Job();
job.setId(IdUtils.createUUID());
job.setName("Move AIP in hierarchy");
job.setSourceObjects(selected);
job.setPlugin(MovePlugin.class.getCanonicalName());
job.setPluginType(PluginType.INTERNAL);
job.setUsername(user.getName());
Map<String, String> pluginParameters = new HashMap<>();
pluginParameters.put(RodaConstants.PLUGIN_PARAMS_ID, parentId);
pluginParameters.put(RodaConstants.PLUGIN_PARAMS_DETAILS, details);
job.setPluginParameters(pluginParameters);
RodaCoreFactory.getModelService().createJob(job);
try {
RodaCoreFactory.getPluginOrchestrator().executeJob(job, true);
} catch (JobAlreadyStartedException e) {
LOGGER.error("Could not execute move job", e);
}
IndexService index = RodaCoreFactory.getIndexService();
index.commit(IndexedAIP.class);
index.commit(IndexedRepresentation.class);
index.commit(IndexedFile.class);
return (parentId != null) ? index.retrieve(IndexedAIP.class, parentId, Arrays.asList(RodaConstants.INDEX_UUID))
: null;
}
public static AIP createAIP(User user, String parentAipId, String type, Permissions permissions)
throws GenericException, AuthorizationDeniedException, RequestNotValidException, NotFoundException,
AlreadyExistsException {
ModelService model = RodaCoreFactory.getModelService();
return model.createAIP(parentAipId, type, permissions, user.getName());
}
public static AIP updateAIP(User user, AIP aip) throws GenericException, AuthorizationDeniedException,
RequestNotValidException, NotFoundException, AlreadyExistsException {
ModelService model = RodaCoreFactory.getModelService();
return model.updateAIP(aip, user.getName());
}
public static void deleteAIP(User user, SelectedItems<IndexedAIP> selected, String details)
throws AuthorizationDeniedException, GenericException, RequestNotValidException, NotFoundException {
Job job = new Job();
job.setId(IdUtils.createUUID());
job.setName("Delete AIP");
job.setSourceObjects(selected);
job.setPlugin(DeleteRODAObjectPlugin.class.getCanonicalName());
job.setPluginType(PluginType.INTERNAL);
job.setUsername(user.getName());
Map<String, String> pluginParameters = new HashMap<>();
pluginParameters.put(RodaConstants.PLUGIN_PARAMS_DETAILS, details);
job.setPluginParameters(pluginParameters);
try {
RodaCoreFactory.getModelService().createJob(job);
RodaCoreFactory.getPluginOrchestrator().executeJob(job, true);
} catch (JobAlreadyStartedException e) {
LOGGER.error("Could not execute AIP delete action", e);
}
}
public static void deleteRepresentation(User user, SelectedItems<IndexedRepresentation> selected, String details)
throws AuthorizationDeniedException, GenericException, RequestNotValidException, NotFoundException {
Job job = new Job();
job.setId(IdUtils.createUUID());
job.setName("Delete representations");
job.setSourceObjects(selected);
job.setPlugin(DeleteRODAObjectPlugin.class.getCanonicalName());
job.setPluginType(PluginType.INTERNAL);
job.setUsername(user.getName());
Map<String, String> pluginParameters = new HashMap<>();
pluginParameters.put(RodaConstants.PLUGIN_PARAMS_DETAILS, details);
job.setPluginParameters(pluginParameters);
try {
RodaCoreFactory.getModelService().createJob(job);
RodaCoreFactory.getPluginOrchestrator().executeJob(job, true);
} catch (JobAlreadyStartedException e) {
LOGGER.error("Could not execute representations delete action", e);
}
}
public static void deleteFile(User user, SelectedItems<IndexedFile> selected, String details)
throws AuthorizationDeniedException, GenericException, RequestNotValidException, NotFoundException {
Job job = new Job();
job.setId(IdUtils.createUUID());
job.setName("Delete files");
job.setSourceObjects(selected);
job.setPlugin(DeleteRODAObjectPlugin.class.getCanonicalName());
job.setPluginType(PluginType.INTERNAL);
job.setUsername(user.getName());
Map<String, String> pluginParameters = new HashMap<>();
pluginParameters.put(RodaConstants.PLUGIN_PARAMS_DETAILS, details);
job.setPluginParameters(pluginParameters);
try {
RodaCoreFactory.getModelService().createJob(job);
RodaCoreFactory.getPluginOrchestrator().executeJob(job, true);
} catch (JobAlreadyStartedException e) {
LOGGER.error("Could not execute file delete action", e);
}
}
public static DescriptiveMetadata createDescriptiveMetadataFile(String aipId, String descriptiveMetadataId,
String descriptiveMetadataType, String descriptiveMetadataVersion, ContentPayload descriptiveMetadataPayload)
throws GenericException, ValidationException, AuthorizationDeniedException, RequestNotValidException,
AlreadyExistsException, NotFoundException {
return createDescriptiveMetadataFile(aipId, null, descriptiveMetadataId, descriptiveMetadataType,
descriptiveMetadataVersion, descriptiveMetadataPayload);
}
public static DescriptiveMetadata createDescriptiveMetadataFile(String aipId, String representationId,
String descriptiveMetadataId, String descriptiveMetadataType, String descriptiveMetadataVersion,
ContentPayload descriptiveMetadataPayload) throws GenericException, ValidationException,
AuthorizationDeniedException, RequestNotValidException, AlreadyExistsException, NotFoundException {
ValidationReport report = ValidationUtils.validateDescriptiveBinary(descriptiveMetadataPayload,
descriptiveMetadataType, descriptiveMetadataVersion, false);
if (!report.isValid()) {
throw new ValidationException(report);
}
return RodaCoreFactory.getModelService().createDescriptiveMetadata(aipId, representationId, descriptiveMetadataId,
descriptiveMetadataPayload, descriptiveMetadataType, descriptiveMetadataVersion);
}
public static DescriptiveMetadata updateDescriptiveMetadataFile(String aipId, String representationId,
String descriptiveMetadataId, String descriptiveMetadataType, String descriptiveMetadataVersion,
ContentPayload descriptiveMetadataPayload, Map<String, String> properties) throws GenericException,
AuthorizationDeniedException, ValidationException, RequestNotValidException, NotFoundException {
ValidationReport report = ValidationUtils.validateDescriptiveBinary(descriptiveMetadataPayload,
descriptiveMetadataType, descriptiveMetadataVersion, false);
if (!report.isValid()) {
throw new ValidationException(report);
}
return RodaCoreFactory.getModelService().updateDescriptiveMetadata(aipId, representationId, descriptiveMetadataId,
descriptiveMetadataPayload, descriptiveMetadataType, descriptiveMetadataVersion, properties);
}
public static void deleteDescriptiveMetadataFile(String aipId, String representationId, String descriptiveMetadataId)
throws GenericException, RequestNotValidException, NotFoundException, AuthorizationDeniedException {
RodaCoreFactory.getModelService().deleteDescriptiveMetadata(aipId, representationId, descriptiveMetadataId);
}
public static DescriptiveMetadata retrieveMetadataFile(String aipId, String descriptiveMetadataId)
throws GenericException, RequestNotValidException, NotFoundException, AuthorizationDeniedException {
return RodaCoreFactory.getModelService().retrieveDescriptiveMetadata(aipId, descriptiveMetadataId);
}
public static Representation createRepresentation(User user, String aipId, String representationId, String type,
String details) throws GenericException, AuthorizationDeniedException, RequestNotValidException, NotFoundException,
AlreadyExistsException {
String eventDescription = "The process of creating an object of the repository.";
ModelService model = RodaCoreFactory.getModelService();
try {
Representation representation = model.createRepresentation(aipId, representationId, true, type, true);
List<LinkingIdentifier> targets = new ArrayList<>();
targets.add(PluginHelper.getLinkingIdentifier(aipId, representation.getId(),
RodaConstants.PRESERVATION_LINKING_OBJECT_OUTCOME));
String outcomeText = "The representation '" + representationId + "' has been manually created";
model.createEvent(aipId, null, null, null, PreservationEventType.CREATION, eventDescription, null, targets,
PluginState.SUCCESS, outcomeText, details, user.getName(), true);
RodaCoreFactory.getIndexService().commit(IndexedRepresentation.class);
return representation;
} catch (RequestNotValidException | NotFoundException | GenericException | AuthorizationDeniedException
| AlreadyExistsException e) {
String outcomeText = "The representation '" + representationId + "' has not been manually created";
model.createUpdateAIPEvent(aipId, null, null, null, PreservationEventType.CREATION, eventDescription,
PluginState.FAILURE, outcomeText, details, user.getName(), true);
throw e;
}
}
public static Representation updateRepresentation(Representation representation) throws GenericException,
AuthorizationDeniedException, RequestNotValidException, NotFoundException, AlreadyExistsException {
return RodaCoreFactory.getModelService().updateRepresentationInfo(representation);
}
public static void deleteRepresentation(String aipId, String representationId)
throws GenericException, RequestNotValidException, NotFoundException, AuthorizationDeniedException {
RodaCoreFactory.getModelService().deleteRepresentation(aipId, representationId);
}
public static File createFile(User user, String aipId, String representationId, List<String> directoryPath,
String fileId, ContentPayload content, String details) throws GenericException, AuthorizationDeniedException,
RequestNotValidException, NotFoundException, AlreadyExistsException {
String eventDescription = "The process of creating an object of the repository.";
ModelService model = RodaCoreFactory.getModelService();
try {
File file = model.createFile(aipId, representationId, directoryPath, fileId, content);
List<LinkingIdentifier> targets = new ArrayList<>();
targets.add(PluginHelper.getLinkingIdentifier(aipId, file.getRepresentationId(), file.getPath(), file.getId(),
RodaConstants.PRESERVATION_LINKING_OBJECT_OUTCOME));
String outcomeText = "The file '" + file.getId() + "' has been manually created.";
model.createEvent(aipId, representationId, null, null, PreservationEventType.CREATION, eventDescription, null,
targets, PluginState.SUCCESS, outcomeText, details, user.getName(), true);
return file;
} catch (RequestNotValidException | NotFoundException | GenericException | AuthorizationDeniedException
| AlreadyExistsException e) {
String outcomeText = "The file '" + fileId + "' has not been manually created.";
model.createUpdateAIPEvent(aipId, representationId, null, null, PreservationEventType.CREATION, eventDescription,
PluginState.FAILURE, outcomeText, details, user.getName(), true);
throw e;
}
}
public static File updateFile(File file, ContentPayload contentPayload, boolean createIfNotExists, boolean notify)
throws GenericException, AuthorizationDeniedException, RequestNotValidException, NotFoundException,
AlreadyExistsException {
return RodaCoreFactory.getModelService().updateFile(file, contentPayload, createIfNotExists, notify);
}
public static EntityResponse retrieveAIPRepresentationFile(IndexedFile iFile, String acceptFormat)
throws GenericException, RequestNotValidException, NotFoundException, AuthorizationDeniedException {
StoragePath filePath = ModelUtils.getFileStoragePath(iFile.getAipId(), iFile.getRepresentationId(), iFile.getPath(),
iFile.getId());
if (!iFile.isDirectory() && RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_BIN.equals(acceptFormat)) {
final String filename;
final String mediaType;
final ConsumesOutputStream stream;
StorageService storage = RodaCoreFactory.getStorageService();
Binary representationFileBinary = storage.getBinary(filePath);
filename = representationFileBinary.getStoragePath().getName();
mediaType = RodaConstants.MEDIA_TYPE_WILDCARD;
stream = new ConsumesOutputStream() {
@Override
public String getMediaType() {
return acceptFormat;
}
@Override
public String getFileName() {
return filename;
}
@Override
public void consumeOutputStream(OutputStream out) throws IOException {
InputStream fileInputStream = null;
try {
fileInputStream = representationFileBinary.getContent().createInputStream();
IOUtils.copy(fileInputStream, out);
} finally {
IOUtils.closeQuietly(fileInputStream);
}
}
};
return new StreamResponse(filename, mediaType, stream);
} else if (iFile.isDirectory() && (RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_ZIP.equals(acceptFormat)
|| RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_BIN.equals(acceptFormat))) {
Directory directory = RodaCoreFactory.getStorageService().getDirectory(filePath);
return ApiUtils.download(directory);
} else if (RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_JSON.equals(acceptFormat)
|| RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_XML.equals(acceptFormat)) {
File file = RodaCoreFactory.getModelService().retrieveFile(iFile.getAipId(), iFile.getRepresentationId(),
iFile.getPath(), iFile.getId());
return new ObjectResponse<File>(acceptFormat, file);
} else {
throw new GenericException("Unsupported accept format: " + acceptFormat);
}
}
public static DescriptiveMetadata createOrUpdateAIPDescriptiveMetadataFile(String aipId, String representationId,
String metadataId, String metadataType, String metadataVersion, Map<String, String> properties, InputStream is,
boolean create) throws GenericException, RequestNotValidException, NotFoundException, AuthorizationDeniedException,
AlreadyExistsException, ValidationException {
Path file = null;
DescriptiveMetadata dm = null;
try {
ModelService model = RodaCoreFactory.getModelService();
file = Files.createTempFile("descriptive", ".tmp");
Files.copy(is, file, StandardCopyOption.REPLACE_EXISTING);
ContentPayload payload = new FSPathContentPayload(file);
if (create) {
dm = model.createDescriptiveMetadata(aipId, representationId, metadataId, payload, metadataType,
metadataVersion);
} else {
dm = model.updateDescriptiveMetadata(aipId, representationId, metadataId, payload, metadataType,
metadataVersion, properties);
}
} catch (IOException e) {
throw new GenericException("Error creating or updating AIP descriptive metadata file", e);
} finally {
FSUtils.deletePathQuietly(file);
}
return dm;
}
public static TransferredResource createTransferredResourcesFolder(String parentUUID, String folderName,
boolean forceCommit) throws GenericException, RequestNotValidException, NotFoundException {
TransferredResource transferredResource = RodaCoreFactory.getTransferredResourcesScanner().createFolder(parentUUID,
folderName);
if (forceCommit) {
RodaCoreFactory.getTransferredResourcesScanner().commit();
}
return transferredResource;
}
private static <T extends IsIndexed> List<String> consolidate(User user, Class<T> classToReturn,
SelectedItems<T> selected) throws GenericException, AuthorizationDeniedException, RequestNotValidException {
List<String> ret;
if (selected instanceof SelectedItemsList) {
ret = ((SelectedItemsList<T>) selected).getIds();
} else if (selected instanceof SelectedItemsFilter) {
SelectedItemsFilter<T> selectedItemsFilter = (SelectedItemsFilter<T>) selected;
Filter filter = selectedItemsFilter.getFilter();
boolean justActive = selectedItemsFilter.justActive();
Long count = count(classToReturn, filter, justActive, user);
IndexResult<T> find = find(classToReturn, filter, Sorter.NONE, new Sublist(0, count.intValue()), Facets.NONE,
user, justActive, Arrays.asList(RodaConstants.INDEX_UUID));
ret = find.getResults().stream().map(i -> i.getUUID()).collect(Collectors.toList());
} else {
throw new RequestNotValidException("Class not supported: " + selected.getClass().getName());
}
return ret;
}
public static void deleteTransferredResources(SelectedItems<TransferredResource> selected, User user)
throws GenericException, NotFoundException, AuthorizationDeniedException, RequestNotValidException {
List<String> ids = consolidate(user, TransferredResource.class, selected);
// check permissions
UserUtility.checkTransferredResourceAccess(user, ids);
RodaCoreFactory.getTransferredResourcesScanner().deleteTransferredResource(ids);
}
public static TransferredResource createTransferredResourceFile(String parentUUID, String fileName,
InputStream inputStream, boolean forceCommit)
throws GenericException, AlreadyExistsException, RequestNotValidException, NotFoundException {
LOGGER.debug("createTransferredResourceFile(path={}, name={})", parentUUID, fileName);
TransferredResource transferredResource = RodaCoreFactory.getTransferredResourcesScanner().createFile(parentUUID,
fileName, inputStream);
if (forceCommit) {
RodaCoreFactory.getTransferredResourcesScanner().commit();
}
return transferredResource;
}
protected static <T extends IsIndexed> void delete(User user, Class<T> returnClass, SelectedItems<T> ids)
throws GenericException, NotFoundException, RequestNotValidException, AuthorizationDeniedException {
List<String> idList = consolidate(user, returnClass, ids);
RodaCoreFactory.getIndexService().delete(returnClass, idList);
RodaCoreFactory.getIndexService().commit(returnClass);
}
public static boolean retrieveScanUpdateStatus(Optional<String> folderRelativePath) {
return RodaCoreFactory.getTransferredResourcesScannerUpdateStatus(folderRelativePath);
}
public static void updateTransferredResources(Optional<String> folderRelativePath, boolean waitToFinish)
throws IsStillUpdatingException, GenericException {
RodaCoreFactory.getTransferredResourcesScanner().updateTransferredResources(folderRelativePath, waitToFinish);
}
public static void updateTransferredResource(Optional<String> folderRelativePath, ContentPayload payload, String name,
boolean waitToFinish) throws IsStillUpdatingException, GenericException, NotFoundException, IOException {
RodaCoreFactory.getTransferredResourcesScanner().updateTransferredResource(folderRelativePath, payload, name,
waitToFinish);
}
public static ConsumesOutputStream retrieveClassificationPlan(User user, String filename)
throws GenericException, RequestNotValidException, NotFoundException, AuthorizationDeniedException {
return ClassificationPlanUtils.retrieveClassificationPlan(user, filename);
}
public static List<SupportedMetadataTypeBundle> retrieveSupportedMetadata(User user, IndexedAIP aip,
IndexedRepresentation representation, Locale locale) throws GenericException {
Messages messages = RodaCoreFactory.getI18NMessages(locale);
List<String> types = RodaUtils
.copyList(RodaCoreFactory.getRodaConfiguration().getList(RodaConstants.UI_BROWSER_METADATA_DESCRIPTIVE_TYPES));
List<SupportedMetadataTypeBundle> supportedMetadata = new ArrayList<>();
if (types != null) {
for (String id : types) {
String type = id;
String version = null;
if (id.contains(RodaConstants.METADATA_VERSION_SEPARATOR)) {
version = id.substring(id.lastIndexOf(RodaConstants.METADATA_VERSION_SEPARATOR) + 1, id.length());
type = id.substring(0, id.lastIndexOf(RodaConstants.METADATA_VERSION_SEPARATOR));
}
String key = RodaConstants.I18N_UI_BROWSE_METADATA_DESCRIPTIVE_TYPE_PREFIX + type;
if (version != null) {
key += RodaConstants.METADATA_VERSION_SEPARATOR + version.toLowerCase();
}
String label = messages.getTranslation(key, type);
String template = null;
Set<MetadataValue> values = new HashSet<>();
try (InputStream templateStream = RodaCoreFactory
.getConfigurationFileAsStream(RodaConstants.METADATA_TEMPLATE_FOLDER + "/"
+ ((version != null) ? type + RodaConstants.METADATA_VERSION_SEPARATOR + version : type)
+ RodaConstants.METADATA_TEMPLATE_EXTENSION)) {
if (templateStream != null) {
template = IOUtils.toString(templateStream, RodaConstants.DEFAULT_ENCODING);
values = ServerTools.transform(template);
for (MetadataValue mv : values) {
String generator = mv.get("auto-generate");
if (generator != null && generator.length() > 0) {
String value;
if (representation != null) {
value = ServerTools.autoGenerateRepresentationValue(representation, generator);
} else {
value = ServerTools.autoGenerateAIPValue(aip, user, generator);
}
if (value != null) {
mv.set("value", value);
}
}
String labels = mv.get("label");
String labelI18N = mv.get("labeli18n");
if (labels != null && labelI18N != null) {
Map<String, String> labelsMaps = JsonUtils.getMapFromJson(labels);
try {
labelsMaps.put(locale.toString(), RodaCoreFactory.getI18NMessages(locale).getTranslation(labelI18N));
} catch (MissingResourceException e) {
LOGGER.debug("Missing resource: {}", labelI18N);
}
labels = JsonUtils.getJsonFromObject(labelsMaps);
mv.set("label", labels);
}
String i18nPrefix = mv.get("optionsLabelI18nKeyPrefix");
if (i18nPrefix != null) {
Map<String, String> terms = messages.getTranslations(i18nPrefix, String.class, false);
if (terms.size() > 0) {
try {
String options = mv.get("options");
List<String> optionsList = JsonUtils.getListFromJson(options, String.class);
if (optionsList != null) {
Map<String, Map<String, String>> i18nMap = new HashMap<>();
for (int i = 0; i < optionsList.size(); i++) {
String value = optionsList.get(i);
String translation = terms.get(i18nPrefix + "." + value);
if (translation == null) {
translation = value;
}
Map<String, String> term = new HashMap<>();
term.put(locale.toString(), translation);
i18nMap.put(value, term);
}
mv.set("optionsLabels", JsonUtils.getJsonFromObject(i18nMap));
}
} catch (MissingResourceException e) {
LOGGER.error(e.getMessage(), e);
}
}
}
}
}
} catch (IOException e) {
LOGGER.error("Error getting the template from the stream", e);
}
supportedMetadata.add(new SupportedMetadataTypeBundle(id, type, version, label, template, values));
}
}
return supportedMetadata;
}
public static EntityResponse retrieveTransferredResource(final TransferredResource transferredResource,
String acceptFormat) throws NotFoundException, RequestNotValidException, GenericException {
if (RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_BIN.equals(acceptFormat)) {
ConsumesOutputStream stream = new ConsumesOutputStream() {
@Override
public String getMediaType() {
return acceptFormat;
}
@Override
public String getFileName() {
return transferredResource.getName();
}
@Override
public void consumeOutputStream(OutputStream out) throws IOException {
InputStream retrieveFile = null;
try {
retrieveFile = RodaCoreFactory.getTransferredResourcesScanner()
.retrieveFile(transferredResource.getFullPath());
IOUtils.copy(retrieveFile, out);
} catch (NotFoundException | RequestNotValidException | GenericException e) {
// do nothing
} finally {
IOUtils.closeQuietly(retrieveFile);
}
}
};
return new StreamResponse(transferredResource.getName(), RodaConstants.MEDIA_TYPE_APPLICATION_OCTET_STREAM,
stream);
} else if (RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_JSON.equals(acceptFormat)
|| RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_XML.equals(acceptFormat)) {
return new ObjectResponse<TransferredResource>(acceptFormat, transferredResource);
} else {
throw new GenericException("Unsupported accept format: " + acceptFormat);
}
}
public static PreservationEventViewBundle retrievePreservationEventViewBundle(String eventId)
throws NotFoundException, GenericException {
PreservationEventViewBundle eventBundle = new PreservationEventViewBundle();
Map<String, IndexedAIP> aips = new HashMap<>();
Map<String, IndexedRepresentation> representations = new HashMap<>();
Map<String, IndexedFile> files = new HashMap<>();
Map<String, TransferredResource> transferredResources = new HashMap<>();
List<String> eventFields = new ArrayList<>();
IndexedPreservationEvent ipe = retrieve(IndexedPreservationEvent.class, eventId, eventFields);
eventBundle.setEvent(ipe);
if (ipe.getLinkingAgentIds() != null && !ipe.getLinkingAgentIds().isEmpty()) {
Map<String, IndexedPreservationAgent> agents = new HashMap<>();
for (LinkingIdentifier agentID : ipe.getLinkingAgentIds()) {
try {
List<String> agentFields = Arrays.asList(RodaConstants.PRESERVATION_AGENT_ID,
RodaConstants.PRESERVATION_AGENT_NAME, RodaConstants.PRESERVATION_AGENT_TYPE,
RodaConstants.PRESERVATION_AGENT_ROLES, RodaConstants.PRESERVATION_AGENT_VERSION,
RodaConstants.PRESERVATION_AGENT_NOTE, RodaConstants.PRESERVATION_AGENT_EXTENSION);
IndexedPreservationAgent agent = retrieve(IndexedPreservationAgent.class, agentID.getValue(), agentFields);
agents.put(agentID.getValue(), agent);
} catch (NotFoundException | GenericException e) {
LOGGER.error("Error getting agent {}: {}", agentID, e.getMessage());
}
}
eventBundle.setAgents(agents);
}
List<LinkingIdentifier> allLinkingIdentifiers = new ArrayList<>();
if (ipe.getSourcesObjectIds() != null) {
allLinkingIdentifiers.addAll(ipe.getSourcesObjectIds());
}
if (ipe.getOutcomeObjectIds() != null) {
allLinkingIdentifiers.addAll(ipe.getOutcomeObjectIds());
}
for (LinkingIdentifier identifier : allLinkingIdentifiers) {
String idValue = identifier.getValue();
RODA_TYPE linkingType = LinkingObjectUtils.getLinkingIdentifierType(idValue);
try {
if (RODA_TYPE.AIP.equals(linkingType)) {
String uuid = LinkingObjectUtils.getAipIdFromLinkingId(idValue);
List<String> aipFields = Arrays.asList(RodaConstants.AIP_TITLE, RodaConstants.INDEX_UUID);
IndexedAIP aip = retrieve(IndexedAIP.class, uuid, aipFields);
aips.put(idValue, aip);
} else if (RODA_TYPE.REPRESENTATION.equals(linkingType)) {
String uuid = LinkingObjectUtils.getRepresentationIdFromLinkingId(idValue);
List<String> representationFields = Arrays.asList(RodaConstants.REPRESENTATION_ID,
RodaConstants.REPRESENTATION_AIP_ID, RodaConstants.REPRESENTATION_ORIGINAL);
IndexedRepresentation rep = retrieve(IndexedRepresentation.class, uuid, representationFields);
representations.put(idValue, rep);
} else if (RODA_TYPE.FILE.equals(linkingType)) {
List<String> fileFields = new ArrayList<>(RodaConstants.FILE_FIELDS_TO_RETURN);
fileFields.addAll(RodaConstants.FILE_FORMAT_FIELDS_TO_RETURN);
fileFields.addAll(Arrays.asList(RodaConstants.FILE_ORIGINALNAME, RodaConstants.FILE_SIZE,
RodaConstants.FILE_FILEFORMAT, RodaConstants.FILE_FORMAT_VERSION));
IndexedFile file = retrieve(IndexedFile.class, LinkingObjectUtils.getFileIdFromLinkingId(idValue),
fileFields);
files.put(idValue, file);
} else if (RODA_TYPE.TRANSFERRED_RESOURCE.equals(linkingType)) {
String id = LinkingObjectUtils.getTransferredResourceIdFromLinkingId(idValue);
if (id != null) {
List<String> resourceFields = Arrays.asList(RodaConstants.INDEX_UUID,
RodaConstants.TRANSFERRED_RESOURCE_NAME, RodaConstants.TRANSFERRED_RESOURCE_FULLPATH);
TransferredResource tr = retrieve(TransferredResource.class, IdUtils.createUUID(id), resourceFields);
transferredResources.put(idValue, tr);
}
} else {
LOGGER.warn("No support for linking object type: {}", linkingType);
}
} catch (NotFoundException e) {
// nothing to do
}
}
eventBundle.setAips(aips);
eventBundle.setRepresentations(representations);
eventBundle.setFiles(files);
eventBundle.setTransferredResources(transferredResources);
return eventBundle;
}
public static CloseableIterable<BinaryVersion> listDescriptiveMetadataVersions(String aipId, String representationId,
String descriptiveMetadataId)
throws RequestNotValidException, GenericException, NotFoundException, AuthorizationDeniedException {
StoragePath storagePath = ModelUtils.getDescriptiveMetadataStoragePath(aipId, representationId,
descriptiveMetadataId);
return RodaCoreFactory.getStorageService().listBinaryVersions(storagePath);
}
public static DescriptiveMetadataVersionsBundle retrieveDescriptiveMetadataVersionsBundle(String aipId,
String representationId, String metadataId, Locale locale)
throws GenericException, RequestNotValidException, NotFoundException, AuthorizationDeniedException {
DescriptiveMetadataVersionsBundle bundle = new DescriptiveMetadataVersionsBundle();
DescriptiveMetadataViewBundle descriptiveMetadataBundle = retrieveDescriptiveMetadataBundle(aipId, representationId,
metadataId, locale);
bundle.setDescriptiveMetadata(descriptiveMetadataBundle);
List<BinaryVersionBundle> versionBundles = new ArrayList<>();
CloseableIterable<BinaryVersion> it = listDescriptiveMetadataVersions(aipId, representationId, metadataId);
for (BinaryVersion v : it) {
versionBundles.add(new BinaryVersionBundle(v.getId(), v.getCreatedDate(), v.getProperties()));
}
IOUtils.closeQuietly(it);
bundle.setVersions(versionBundles);
return bundle;
}
public static void revertDescriptiveMetadataVersion(String aipId, String representationId,
String descriptiveMetadataId, String versionId, Map<String, String> properties)
throws RequestNotValidException, NotFoundException, GenericException, AuthorizationDeniedException {
RodaCoreFactory.getModelService().revertDescriptiveMetadataVersion(aipId, representationId, descriptiveMetadataId,
versionId, properties);
}
public static void deleteDescriptiveMetadataVersion(String aipId, String representationId,
String descriptiveMetadataId, String versionId)
throws NotFoundException, GenericException, RequestNotValidException {
StoragePath storagePath = ModelUtils.getDescriptiveMetadataStoragePath(aipId, representationId,
descriptiveMetadataId);
RodaCoreFactory.getStorageService().deleteBinaryVersion(storagePath, versionId);
}
public static void updateAIPPermissions(User user, IndexedAIP indexedAIP, Permissions permissions, String details,
boolean recursive) throws GenericException, NotFoundException, RequestNotValidException,
AuthorizationDeniedException, JobAlreadyStartedException {
final String eventDescription = "The process of updating an object of the repository.";
final ModelService model = RodaCoreFactory.getModelService();
AIP aip = model.retrieveAIP(indexedAIP.getId());
aip.setPermissions(permissions);
List<LinkingIdentifier> sources = Arrays
.asList(PluginHelper.getLinkingIdentifier(aip.getId(), RodaConstants.PRESERVATION_LINKING_OBJECT_OUTCOME));
try {
model.updateAIPPermissions(aip, user.getName());
String outcomeText = PluginHelper.createOutcomeTextForAIP(indexedAIP, " permissions has been manually updated");
model.createEvent(aip.getId(), null, null, null, PreservationEventType.UPDATE, eventDescription, sources, null,
PluginState.SUCCESS, outcomeText, details, user.getName(), true);
} catch (RequestNotValidException | NotFoundException | GenericException | AuthorizationDeniedException e) {
String outcomeText = PluginHelper.createOutcomeTextForAIP(indexedAIP,
" permissions has not been manually updated");
model.createEvent(aip.getId(), null, null, null, PreservationEventType.UPDATE, eventDescription, sources, null,
PluginState.FAILURE, outcomeText, details, user.getName(), true);
throw e;
}
if (recursive) {
Filter filter = new Filter(new SimpleFilterParameter(RodaConstants.AIP_ANCESTORS, indexedAIP.getId()));
SelectedItemsFilter<IndexedAIP> selectedItems = new SelectedItemsFilter<>(filter, IndexedAIP.class.getName(),
Boolean.FALSE);
Job job = new Job();
job.setId(IdUtils.createUUID());
job.setName("Update AIP permissions recursively");
job.setSourceObjects(selectedItems);
job.setPlugin(UpdateAIPPermissionsPlugin.class.getCanonicalName());
job.setPluginType(PluginType.INTERNAL);
job.setUsername(user.getName());
Map<String, String> pluginParameters = new HashMap<>();
pluginParameters.put(RodaConstants.PLUGIN_PARAMS_AIP_ID, aip.getId());
pluginParameters.put(RodaConstants.PLUGIN_PARAMS_DETAILS, details);
pluginParameters.put(RodaConstants.PLUGIN_PARAMS_EVENT_DESCRIPTION, eventDescription);
pluginParameters.put(RodaConstants.PLUGIN_PARAMS_OUTCOME_TEXT,
"AIP " + indexedAIP.getId() + " permissions were updated and all sublevels will be too");
job.setPluginParameters(pluginParameters);
RodaCoreFactory.getModelService().createJob(job);
RodaCoreFactory.getPluginOrchestrator().executeJob(job, true);
}
}
public static void updateDIPPermissions(IndexedDIP indexedDIP, Permissions permissions, String details)
throws GenericException, NotFoundException, RequestNotValidException, AuthorizationDeniedException {
// TODO 20170222 nvieira it should create an event associated with DIP
ModelService model = RodaCoreFactory.getModelService();
DIP dip = model.retrieveDIP(indexedDIP.getId());
dip.setPermissions(permissions);
model.updateDIPPermissions(dip);
}
public static Risk createRisk(Risk risk, User user, boolean commit)
throws GenericException, RequestNotValidException {
risk.setCreatedBy(user.getName());
risk.setUpdatedBy(user.getName());
return RodaCoreFactory.getModelService().createRisk(risk, commit);
}
public static void updateRisk(Risk risk, User user, Map<String, String> properties, boolean commit, int incidences)
throws GenericException, RequestNotValidException {
risk.setUpdatedBy(user.getName());
RodaCoreFactory.getModelService().updateRisk(risk, properties, commit, incidences);
}
public static Format createFormat(Format format, boolean commit) throws GenericException, RequestNotValidException {
return RodaCoreFactory.getModelService().createFormat(format, commit);
}
public static void updateFormat(Format format, boolean commit) throws GenericException, RequestNotValidException {
RodaCoreFactory.getModelService().updateFormat(format, commit);
}
public static RiskVersionsBundle retrieveRiskVersions(String riskId)
throws RequestNotValidException, GenericException, NotFoundException, AuthorizationDeniedException, IOException {
StoragePath storagePath = ModelUtils.getRiskStoragePath(riskId);
CloseableIterable<BinaryVersion> iterable = RodaCoreFactory.getStorageService().listBinaryVersions(storagePath);
List<BinaryVersionBundle> versionList = new ArrayList<>();
boolean versionFlag = false;
Date newestDate = new Date();
Binary lastRiskBinary = null;
for (BinaryVersion bv : iterable) {
versionList.add(new BinaryVersionBundle(bv.getId(), bv.getCreatedDate(), bv.getProperties()));
if (!versionFlag) {
lastRiskBinary = bv.getBinary();
newestDate = bv.getCreatedDate();
versionFlag = true;
} else if (newestDate.before(bv.getCreatedDate())) {
lastRiskBinary = bv.getBinary();
newestDate = bv.getCreatedDate();
}
}
iterable.close();
if (lastRiskBinary != null) {
Risk lastRisk = JsonUtils.getObjectFromJson(lastRiskBinary.getContent().createInputStream(), Risk.class);
return new RiskVersionsBundle(lastRisk, versionList);
} else {
return new RiskVersionsBundle();
}
}
public static boolean hasRiskVersions(String id)
throws RequestNotValidException, GenericException, NotFoundException, AuthorizationDeniedException {
StoragePath storagePath = ModelUtils.getRiskStoragePath(id);
CloseableIterable<BinaryVersion> iterable = RodaCoreFactory.getStorageService().listBinaryVersions(storagePath);
boolean hasRiskVersion = iterable.iterator().hasNext();
IOUtils.closeQuietly(iterable);
return hasRiskVersion;
}
public static void revertRiskVersion(String riskId, String versionId, Map<String, String> properties, int incidences)
throws RequestNotValidException, NotFoundException, GenericException, AuthorizationDeniedException {
RodaCoreFactory.getModelService().revertRiskVersion(riskId, versionId, properties, false, incidences);
}
public static void deleteRiskVersion(String riskId, String versionId)
throws NotFoundException, GenericException, RequestNotValidException {
StoragePath storagePath = ModelUtils.getRiskStoragePath(riskId);
RodaCoreFactory.getStorageService().deleteBinaryVersion(storagePath, versionId);
}
public static Risk retrieveRiskVersion(String riskId, String selectedVersion)
throws RequestNotValidException, GenericException, NotFoundException, AuthorizationDeniedException, IOException {
BinaryVersion bv = RodaCoreFactory.getModelService().retrieveVersion(riskId, selectedVersion);
return JsonUtils.getObjectFromJson(bv.getBinary().getContent().createInputStream(), Risk.class);
}
public static void validateExportAIPParams(String acceptFormat) throws RequestNotValidException {
if (!RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_BIN.equals(acceptFormat)) {
throw new RequestNotValidException("Invalid '" + RodaConstants.API_QUERY_KEY_ACCEPT_FORMAT
+ "' value. Expected values: " + Arrays.asList(RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_BIN));
}
}
public static void validateListingParams(String acceptFormat) throws RequestNotValidException {
if (!RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_JSON.equals(acceptFormat)
&& !RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_XML.equals(acceptFormat)) {
throw new RequestNotValidException(
"Invalid '" + RodaConstants.API_QUERY_KEY_ACCEPT_FORMAT + "' value. Expected values: " + Arrays
.asList(RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_JSON, RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_XML));
}
}
public static void validateCreateAndUpdateParams(String acceptFormat) throws RequestNotValidException {
if (!RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_JSON.equals(acceptFormat)
&& !RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_XML.equals(acceptFormat)) {
throw new RequestNotValidException(
"Invalid '" + RodaConstants.API_QUERY_KEY_ACCEPT_FORMAT + "' value. Expected values: " + Arrays
.asList(RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_JSON, RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_XML));
}
}
public static void validateGetAIPParams(String acceptFormat) throws RequestNotValidException {
if (!RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_JSON.equals(acceptFormat)
&& !RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_XML.equals(acceptFormat)
&& !RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_ZIP.equals(acceptFormat)) {
throw new RequestNotValidException("Invalid '" + RodaConstants.API_QUERY_KEY_ACCEPT_FORMAT
+ "' value. Expected values: " + Arrays.asList(RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_JSON,
RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_XML, RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_ZIP));
}
}
public static StreamResponse retrieveAIPPart(IndexedAIP aip, String part)
throws RequestNotValidException, NotFoundException, GenericException, AuthorizationDeniedException {
String aipId = aip.getId();
if (RodaConstants.STORAGE_DIRECTORY_SUBMISSION.equals(part)) {
Directory directory = RodaCoreFactory.getModelService().getSubmissionDirectory(aipId);
return ApiUtils.download(directory, part);
} else if (RodaConstants.STORAGE_DIRECTORY_DOCUMENTATION.equals(part)) {
Directory directory = RodaCoreFactory.getModelService().getDocumentationDirectory(aipId);
return ApiUtils.download(directory, part);
} else if (RodaConstants.STORAGE_DIRECTORY_SCHEMAS.equals(part)) {
Directory directory = RodaCoreFactory.getModelService().getSchemasDirectory(aipId);
return ApiUtils.download(directory, part);
} else {
throw new GenericException("Unsupported part: " + part);
}
}
public static StreamResponse retrieveAIPs(SelectedItems<IndexedAIP> selected, String acceptFormat)
throws GenericException, RequestNotValidException, NotFoundException, AuthorizationDeniedException, IOException {
IndexService index = RodaCoreFactory.getIndexService();
if (RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_BIN.equals(acceptFormat)) {
List<ZipEntryInfo> zipEntries = new ArrayList<>();
if (selected instanceof SelectedItemsFilter) {
SelectedItemsFilter<IndexedAIP> selectedItems = (SelectedItemsFilter<IndexedAIP>) selected;
long count = index.count(IndexedAIP.class, selectedItems.getFilter());
for (int i = 0; i < count; i += RodaConstants.DEFAULT_PAGINATION_VALUE) {
List<IndexedAIP> aips = index.find(IndexedAIP.class, selectedItems.getFilter(), null,
new Sublist(i, RodaConstants.DEFAULT_PAGINATION_VALUE), null).getResults();
zipEntries.addAll(ModelUtils.zipIndexedAIP(aips));
}
} else {
SelectedItemsList<IndexedAIP> selectedItems = (SelectedItemsList<IndexedAIP>) selected;
zipEntries.addAll(ModelUtils.zipIndexedAIP(ModelUtils.getIndexedAIPsFromObjectIds(selectedItems)));
}
return DownloadUtils.createZipStreamResponse(zipEntries, "export");
} else if (RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_JSON.equals(acceptFormat)) {
throw new GenericException("Not yet supported: " + acceptFormat);
} else {
throw new GenericException("Unsupported accept format: " + acceptFormat);
}
}
public static RiskMitigationBundle retrieveShowMitigationTerms(int preMitigationProbability, int preMitigationImpact,
int posMitigationProbability, int posMitigationImpact) {
int lowLimit = RodaCoreFactory.getRodaConfigurationAsInt("ui", "risk", "mitigationSeverity", "lowLimit");
int highLimit = RodaCoreFactory.getRodaConfigurationAsInt("ui", "risk", "mitigationSeverity", "highLimit");
String preProbability = RodaCoreFactory.getRodaConfigurationAsString("ui", "risk", "mitigationProbability",
Integer.toString(preMitigationProbability));
String preImpact = RodaCoreFactory.getRodaConfigurationAsString("ui", "risk", "mitigationImpact",
Integer.toString(preMitigationImpact));
String posProbability = RodaCoreFactory.getRodaConfigurationAsString("ui", "risk", "mitigationProbability",
Integer.toString(posMitigationProbability));
String posImpact = RodaCoreFactory.getRodaConfigurationAsString("ui", "risk", "mitigationImpact",
Integer.toString(posMitigationImpact));
return new RiskMitigationBundle(lowLimit, highLimit, preProbability, preImpact, posProbability, posImpact);
}
public static List<String> retrieveShowMitigationTerms() {
List<String> terms = new ArrayList<>();
terms.add(RodaCoreFactory.getRodaConfigurationAsString("ui", "risk", "mitigationSeverity", "lowLimit"));
terms.add(RodaCoreFactory.getRodaConfigurationAsString("ui", "risk", "mitigationSeverity", "highLimit"));
return terms;
}
public static MitigationPropertiesBundle retrieveAllMitigationProperties() {
int lowLimit = RodaCoreFactory.getRodaConfigurationAsInt("ui", "risk", "mitigationSeverity", "lowLimit");
int highLimit = RodaCoreFactory.getRodaConfigurationAsInt("ui", "risk", "mitigationSeverity", "highLimit");
int probabilityLimit = RodaCoreFactory.getRodaConfigurationAsInt("ui", "risk", "mitigationProbability", "limit");
int impactLimit = RodaCoreFactory.getRodaConfigurationAsInt("ui", "risk", "mitigationImpact", "limit");
// second list contains probability content
List<String> probabilities = new ArrayList<>();
for (int i = 0; i <= probabilityLimit; i++) {
String value = Integer.toString(i);
probabilities.add(RodaCoreFactory.getRodaConfigurationAsString("ui", "risk", "mitigationProbability", value));
}
// third list contains impact content
List<String> impacts = new ArrayList<>();
for (int i = 0; i <= impactLimit; i++) {
String value = Integer.toString(i);
impacts.add(RodaCoreFactory.getRodaConfigurationAsString("ui", "risk", "mitigationImpact", value));
}
return new MitigationPropertiesBundle(lowLimit, highLimit, probabilities, impacts);
}
public static void deleteRisk(User user, SelectedItems<IndexedRisk> selected)
throws GenericException, AuthorizationDeniedException, RequestNotValidException, NotFoundException,
InvalidParameterException, JobAlreadyStartedException {
Job job = new Job();
job.setId(IdUtils.createUUID());
job.setName("Delete risks");
job.setSourceObjects(selected);
job.setPlugin(DeleteRODAObjectPlugin.class.getCanonicalName());
job.setPluginType(PluginType.INTERNAL);
job.setUsername(user.getName());
try {
RodaCoreFactory.getModelService().createJob(job);
RodaCoreFactory.getPluginOrchestrator().executeJob(job, true);
} catch (JobAlreadyStartedException e) {
LOGGER.error("Could not execute risk delete action", e);
}
}
public static void deleteFormat(User user, SelectedItems<Format> selected)
throws GenericException, AuthorizationDeniedException, RequestNotValidException, NotFoundException {
Job job = new Job();
job.setId(IdUtils.createUUID());
job.setName("Delete formats");
job.setSourceObjects(selected);
job.setPlugin(DeleteRODAObjectPlugin.class.getCanonicalName());
job.setPluginType(PluginType.INTERNAL);
job.setUsername(user.getName());
try {
RodaCoreFactory.getModelService().createJob(job);
RodaCoreFactory.getPluginOrchestrator().executeJob(job, true);
} catch (JobAlreadyStartedException e) {
LOGGER.error("Could not execute format delete action", e);
}
}
public static void updateRiskCounters() throws GenericException, RequestNotValidException, NotFoundException {
IndexService index = RodaCoreFactory.getIndexService();
IndexResult<RiskIncidence> findAllRiskIncidences = index.find(RiskIncidence.class, Filter.ALL, Sorter.NONE,
new Sublist(0, 0), new Facets(new SimpleFacetParameter(RodaConstants.RISK_INCIDENCE_RISK_ID)),
Arrays.asList(RodaConstants.INDEX_UUID));
Filter filter = new Filter(
new SimpleFilterParameter(RodaConstants.RISK_INCIDENCE_STATUS, INCIDENCE_STATUS.UNMITIGATED.toString()));
IndexResult<RiskIncidence> findNotMitigatedRiskIncidences = index.find(RiskIncidence.class, filter, Sorter.NONE,
new Sublist(0, 0), new Facets(new SimpleFacetParameter(RodaConstants.RISK_INCIDENCE_RISK_ID)),
Arrays.asList(RodaConstants.INDEX_UUID));
Map<String, IndexedRisk> allRisks = new HashMap<>();
// retrieve risks and set default object count to zero
IterableIndexResult<IndexedRisk> risks = index.findAll(IndexedRisk.class, Filter.ALL, new ArrayList<>());
for (IndexedRisk indexedRisk : risks) {
indexedRisk.setIncidencesCount(0);
indexedRisk.setUnmitigatedIncidencesCount(0);
allRisks.put(indexedRisk.getId(), indexedRisk);
}
// update risks from facets (all incidences)
for (FacetFieldResult fieldResult : findAllRiskIncidences.getFacetResults()) {
for (FacetValue facetValue : fieldResult.getValues()) {
String riskId = facetValue.getValue();
long counter = facetValue.getCount();
IndexedRisk risk = allRisks.get(riskId);
if (risk != null) {
risk.setIncidencesCount((int) counter);
} else {
LOGGER.warn("Updating risk counters found incidences pointing to non-existing risk: {}", riskId);
}
}
}
// update risks from facets (not mitigated incidences)
for (FacetFieldResult fieldResult : findNotMitigatedRiskIncidences.getFacetResults()) {
for (FacetValue facetValue : fieldResult.getValues()) {
String riskId = facetValue.getValue();
long counter = facetValue.getCount();
IndexedRisk risk = allRisks.get(riskId);
if (risk != null) {
risk.setUnmitigatedIncidencesCount((int) counter);
} else {
LOGGER.warn("Updating risk counters found incidences pointing to non-existing risk: {}", riskId);
}
}
}
// update all in index
for (IndexedRisk risk : allRisks.values()) {
index.reindexRisk(risk);
}
index.commit(IndexedRisk.class);
}
public static void appraisal(User user, SelectedItems<IndexedAIP> selected, boolean accept, String rejectReason,
Locale locale) throws GenericException, AuthorizationDeniedException, RequestNotValidException, NotFoundException {
List<String> listOfIds = consolidate(user, IndexedAIP.class, selected);
ModelService model = RodaCoreFactory.getModelService();
IndexService index = RodaCoreFactory.getIndexService();
Date now = new Date();
// map of job id -> (total, accepted)
Map<String, Pair<Integer, Integer>> jobState = new HashMap<>();
List<String> aipsToDelete = new ArrayList<>();
String userAgentId;
try {
boolean notifyAgent = true;
PreservationMetadata pm = PremisV3Utils.createPremisUserAgentBinary(user.getName(), model, index, notifyAgent);
userAgentId = pm.getId();
} catch (AlreadyExistsException e) {
userAgentId = IdUtils.getUserAgentId(user.getName());
} catch (ValidationException e) {
throw new GenericException(e);
}
for (String aipId : listOfIds) {
AIP aip = model.retrieveAIP(aipId);
String jobId = aip.getIngestJobId();
if (accept) {
// Accept AIP
aip.setState(AIPState.ACTIVE);
model.updateAIPState(aip, user.getName());
// create preservation event
String id = IdUtils.createPreservationMetadataId(PreservationMetadataType.EVENT);
PreservationEventType type = PreservationEventType.ACCESSION;
String preservationEventDescription = AutoAcceptSIPPlugin.DESCRIPTION;
List<LinkingIdentifier> sources = new ArrayList<>();
List<LinkingIdentifier> outcomes = Arrays
.asList(PluginHelper.getLinkingIdentifier(aipId, RodaConstants.PRESERVATION_LINKING_OBJECT_OUTCOME));
PluginState outcome = PluginState.SUCCESS;
String outcomeDetailNote = AutoAcceptSIPPlugin.SUCCESS_MESSAGE;
String outcomeDetailExtension = null;
boolean notifyEvent = true;
try {
ContentPayload premisEvent = PremisV3Utils.createPremisEventBinary(id, now, type.toString(),
preservationEventDescription, sources, outcomes, outcome.name(), outcomeDetailNote, outcomeDetailExtension,
Arrays.asList(userAgentId));
model.createPreservationMetadata(PreservationMetadataType.EVENT, id, aipId, null, null, null, premisEvent,
notifyEvent);
} catch (AlreadyExistsException | ValidationException e) {
throw new GenericException(e);
}
} else {
// Reject AIP
model.deleteAIP(aipId);
aipsToDelete.add(aipId);
}
// create job report
Job job = model.retrieveJob(jobId);
Report report = model.retrieveJobReport(jobId, aipId, true);
Report reportItem = new Report();
Messages messages = RodaCoreFactory.getI18NMessages(locale);
reportItem.setTitle(messages.getTranslation(RodaConstants.I18N_UI_APPRAISAL));
reportItem.setPlugin(messages.getTranslation(RodaConstants.I18N_UI_APPRAISAL));
reportItem.setPluginDetails(rejectReason);
reportItem.setPluginState(accept ? PluginState.SUCCESS : PluginState.FAILURE);
reportItem.setOutcomeObjectState(accept ? AIPState.ACTIVE : AIPState.DELETED);
reportItem.setDateCreated(now);
report.addReport(reportItem);
model.createOrUpdateJobReport(report, job);
// save job state
Pair<Integer, Integer> pair = jobState.get(jobId);
if (pair == null) {
jobState.put(jobId, Pair.of(1, accept ? 1 : 0));
} else {
jobState.put(jobId, Pair.of(pair.getFirst() + 1, pair.getSecond() + (accept ? 1 : 0)));
}
}
// update job counters
for (Entry<String, Pair<Integer, Integer>> entry : jobState.entrySet()) {
String jobId = entry.getKey();
int total = entry.getValue().getFirst();
int accepted = entry.getValue().getSecond();
int rejected = total - accepted;
Job job = model.retrieveJob(jobId);
if (rejected > 0) {
// change counter to failure
job.getJobStats()
.setSourceObjectsProcessedWithSuccess(job.getJobStats().getSourceObjectsProcessedWithSuccess() - rejected);
job.getJobStats()
.setSourceObjectsProcessedWithFailure(job.getJobStats().getSourceObjectsProcessedWithFailure() + rejected);
}
// decrement manual interaction counter
job.getJobStats()
.setOutcomeObjectsWithManualIntervention(job.getJobStats().getOutcomeObjectsWithManualIntervention() - total);
model.createOrUpdateJob(job);
}
RodaCoreFactory.getIndexService().commit(IndexedAIP.class, Job.class, IndexedReport.class,
IndexedPreservationEvent.class);
}
public static String retrieveDescriptiveMetadataPreview(SupportedMetadataTypeBundle bundle) throws GenericException {
String rawTemplate = bundle.getTemplate();
String result;
if (StringUtils.isNotBlank(rawTemplate)) {
Map<String, String> data = new HashMap<>();
Set<MetadataValue> values = bundle.getValues();
if (values != null) {
values.forEach(metadataValue -> {
String val = metadataValue.get("value");
if (val != null) {
val = val.replaceAll("\\s", "");
if (!"".equals(val)) {
data.put(metadataValue.get("name"), metadataValue.get("value"));
}
}
});
}
result = HandlebarsUtility.executeHandlebars(rawTemplate, data);
// result = RodaUtils.indentXML(result);
} else {
result = rawTemplate;
}
return result;
}
public static String renameTransferredResource(String transferredResourceId, String newName) throws GenericException,
RequestNotValidException, AlreadyExistsException, IsStillUpdatingException, NotFoundException {
List<String> resourceFields = Arrays.asList(RodaConstants.INDEX_UUID, RodaConstants.TRANSFERRED_RESOURCE_FULLPATH,
RodaConstants.TRANSFERRED_RESOURCE_PARENT_UUID);
Filter filter = new Filter(new SimpleFilterParameter(RodaConstants.INDEX_UUID, transferredResourceId));
IndexResult<TransferredResource> resources = RodaCoreFactory.getIndexService().find(TransferredResource.class,
filter, Sorter.NONE, new Sublist(0, 1), resourceFields);
if (!resources.getResults().isEmpty()) {
TransferredResource resource = resources.getResults().get(0);
return RodaCoreFactory.getTransferredResourcesScanner().renameTransferredResource(resource, newName, true, true);
} else {
return transferredResourceId;
}
}
public static IndexedFile renameFolder(User user, String folderUUID, String newName, String details)
throws GenericException, RequestNotValidException, AlreadyExistsException, NotFoundException,
AuthorizationDeniedException {
String eventDescription = "The process of updating an object of the repository.";
ModelService model = RodaCoreFactory.getModelService();
IndexService index = RodaCoreFactory.getIndexService();
IndexedFile ifolder = index.retrieve(IndexedFile.class, folderUUID, RodaConstants.FILE_FIELDS_TO_RETURN);
String oldName = ifolder.getId();
try {
File folder = model.retrieveFile(ifolder.getAipId(), ifolder.getRepresentationId(), ifolder.getPath(),
ifolder.getId());
File newFolder = model.renameFolder(folder, newName, true, true);
String outcomeText = "The folder '" + oldName + "' has been manually renamed to '" + newName + "'.";
model.createUpdateAIPEvent(ifolder.getAipId(), ifolder.getRepresentationId(), null, null,
PreservationEventType.UPDATE, eventDescription, PluginState.SUCCESS, outcomeText, details, user.getName(),
true);
index.commitAIPs();
return index.retrieve(IndexedFile.class, IdUtils.getFileId(newFolder), RodaConstants.FILE_FIELDS_TO_RETURN);
} catch (RequestNotValidException | NotFoundException | GenericException | AuthorizationDeniedException e) {
String outcomeText = "The folder '" + oldName + "' has not been manually renamed to '" + newName + "'.";
model.createUpdateAIPEvent(ifolder.getAipId(), ifolder.getRepresentationId(), null, null,
PreservationEventType.UPDATE, eventDescription, PluginState.FAILURE, outcomeText, details, user.getName(),
true);
throw e;
}
}
public static void moveFiles(User user, String aipId, String representationId,
SelectedItems<IndexedFile> selectedFiles, IndexedFile toFolder, String details) throws GenericException,
RequestNotValidException, AlreadyExistsException, NotFoundException, AuthorizationDeniedException {
if (toFolder != null
&& (!toFolder.getAipId().equals(aipId) || !toFolder.getRepresentationId().equals(representationId))) {
throw new RequestNotValidException("Cannot move to a file outside defined representation");
}
Job job = new Job();
job.setId(IdUtils.createUUID());
job.setName("Move files");
job.setSourceObjects(selectedFiles);
job.setPlugin(MovePlugin.class.getCanonicalName());
job.setPluginType(PluginType.INTERNAL);
job.setUsername(user.getName());
Map<String, String> pluginParameters = new HashMap<>();
if (toFolder != null) {
pluginParameters.put(RodaConstants.PLUGIN_PARAMS_ID, toFolder.getUUID());
}
pluginParameters.put(RodaConstants.PLUGIN_PARAMS_DETAILS, details);
job.setPluginParameters(pluginParameters);
try {
RodaCoreFactory.getModelService().createJob(job);
RodaCoreFactory.getPluginOrchestrator().executeJob(job, true);
} catch (JobAlreadyStartedException e) {
LOGGER.error("Could not execute move job", e);
}
}
public static String moveTransferredResource(User user, SelectedItems<TransferredResource> selected,
TransferredResource transferredResource) throws GenericException, RequestNotValidException, AlreadyExistsException,
IsStillUpdatingException, NotFoundException {
String resourceRelativePath = "";
String uuid = null;
if (transferredResource != null) {
resourceRelativePath = transferredResource.getRelativePath();
uuid = transferredResource.getUUID();
}
Job job = new Job();
job.setId(IdUtils.createUUID());
job.setName("Move transferred resources");
job.setSourceObjects(selected);
job.setPlugin(MovePlugin.class.getCanonicalName());
job.setPluginType(PluginType.INTERNAL);
job.setUsername(user.getName());
Map<String, String> pluginParameters = new HashMap<>();
pluginParameters.put(RodaConstants.PLUGIN_PARAMS_ID, resourceRelativePath);
job.setPluginParameters(pluginParameters);
try {
RodaCoreFactory.getModelService().createJob(job);
RodaCoreFactory.getPluginOrchestrator().executeJob(job, true);
} catch (JobAlreadyStartedException | AuthorizationDeniedException e) {
LOGGER.error("Could not execute move job", e);
}
return uuid;
}
public static IndexedFile createFolder(User user, String aipId, String representationId, String folderUUID,
String newName, String details) throws GenericException, RequestNotValidException, AlreadyExistsException,
NotFoundException, AuthorizationDeniedException {
String eventDescription = "The process of creating an object of the repository.";
ModelService model = RodaCoreFactory.getModelService();
IndexService index = RodaCoreFactory.getIndexService();
File newFolder;
IndexedRepresentation irep = index.retrieve(IndexedRepresentation.class,
IdUtils.getRepresentationId(aipId, representationId), RodaConstants.REPRESENTATION_FIELDS_TO_RETURN);
try {
if (folderUUID != null) {
IndexedFile ifolder = index.retrieve(IndexedFile.class, folderUUID, RodaConstants.FILE_FIELDS_TO_RETURN);
newFolder = model.createFile(ifolder.getAipId(), ifolder.getRepresentationId(), ifolder.getPath(),
ifolder.getId(), newName, true);
} else {
newFolder = model.createFile(irep.getAipId(), irep.getId(), null, null, newName, true);
}
String outcomeText = "The folder '" + newName + "' has been manually created.";
model.createUpdateAIPEvent(aipId, irep.getId(), null, null, PreservationEventType.CREATION, eventDescription,
PluginState.SUCCESS, outcomeText, details, user.getName(), true);
index.commit(IndexedFile.class);
return index.retrieve(IndexedFile.class, IdUtils.getFileId(newFolder), new ArrayList<>());
} catch (RequestNotValidException | NotFoundException | GenericException | AuthorizationDeniedException e) {
String outcomeText = "The folder '" + newName + "' has not been manually created.";
model.createUpdateAIPEvent(aipId, irep.getId(), null, null, PreservationEventType.CREATION, eventDescription,
PluginState.FAILURE, outcomeText, details, user.getName(), true);
throw e;
}
}
public static List<TransferredResource> retrieveSelectedTransferredResource(
SelectedItems<TransferredResource> selected) throws GenericException, RequestNotValidException {
if (selected instanceof SelectedItemsList) {
SelectedItemsList<TransferredResource> selectedList = (SelectedItemsList<TransferredResource>) selected;
Filter filter = new Filter(new OneOfManyFilterParameter(RodaConstants.INDEX_UUID, selectedList.getIds()));
IndexResult<TransferredResource> iresults = RodaCoreFactory.getIndexService().find(TransferredResource.class,
filter, Sorter.NONE, new Sublist(0, selectedList.getIds().size()), new ArrayList<>());
return iresults.getResults();
} else if (selected instanceof SelectedItemsFilter) {
SelectedItemsFilter<TransferredResource> selectedFilter = (SelectedItemsFilter<TransferredResource>) selected;
Long counter = RodaCoreFactory.getIndexService().count(TransferredResource.class, selectedFilter.getFilter());
IndexResult<TransferredResource> iresults = RodaCoreFactory.getIndexService().find(TransferredResource.class,
selectedFilter.getFilter(), Sorter.NONE, new Sublist(0, counter.intValue()), new ArrayList<>());
return iresults.getResults();
} else {
return new ArrayList<>();
}
}
public static void updateRiskIncidence(RiskIncidence incidence) throws GenericException {
RodaCoreFactory.getModelService().updateRiskIncidence(incidence, true);
}
protected static Reports listReports(int start, int limit)
throws RequestNotValidException, NotFoundException, GenericException, AuthorizationDeniedException {
Sorter sorter = new Sorter(new SortParameter(RodaConstants.JOB_REPORT_DATE_UPDATED, true));
IndexResult<IndexedReport> indexReports = RodaCoreFactory.getIndexService().find(IndexedReport.class, Filter.ALL,
sorter, new Sublist(start, limit), new ArrayList<>());
List<Report> results = indexReports.getResults().stream().map(ireport -> (Report) ireport)
.collect(Collectors.toList());
return new Reports(results);
}
protected static Reports listTransferredResourcesReports(String resourceId, int start, int limit)
throws RequestNotValidException, NotFoundException, GenericException, AuthorizationDeniedException {
Filter filter = new Filter();
filter.add(
new SimpleFilterParameter(RodaConstants.JOB_REPORT_SOURCE_OBJECT_CLASS, TransferredResource.class.getName()));
filter.add(new SimpleFilterParameter(RodaConstants.JOB_REPORT_SOURCE_OBJECT_ID, resourceId));
filter.add(new OneOfManyFilterParameter(RodaConstants.JOB_REPORT_OUTCOME_OBJECT_CLASS,
Arrays.asList(AIP.class.getName(), IndexedAIP.class.getName())));
Sorter sorter = new Sorter(new SortParameter(RodaConstants.JOB_REPORT_DATE_UPDATED, true));
IndexResult<IndexedReport> reports = RodaCoreFactory.getIndexService().find(IndexedReport.class, filter, sorter,
new Sublist(start, limit), new ArrayList<>());
List<Report> results = reports.getResults().stream().map(ireport -> (Report) ireport).collect(Collectors.toList());
return new Reports(results);
}
protected static Reports listTransferredResourcesReportsWithSIP(String sipId, int start, int limit)
throws RequestNotValidException, NotFoundException, GenericException, AuthorizationDeniedException {
Filter filter = new Filter();
filter.add(new OneOfManyFilterParameter(RodaConstants.JOB_REPORT_OUTCOME_OBJECT_CLASS,
Arrays.asList(AIP.class.getName(), IndexedAIP.class.getName())));
filter.add(new SimpleFilterParameter(RodaConstants.JOB_REPORT_SOURCE_OBJECT_ORIGINAL_IDS, sipId));
Sorter sorter = new Sorter(new SortParameter(RodaConstants.JOB_REPORT_DATE_UPDATED, true));
IndexResult<IndexedReport> indexReports = RodaCoreFactory.getIndexService().find(IndexedReport.class, filter,
sorter, new Sublist(start, limit), new ArrayList<>());
List<Report> results = indexReports.getResults().stream().map(ireport -> (Report) ireport)
.collect(Collectors.toList());
return new Reports(results);
}
public static void deleteRiskIncidences(User user, SelectedItems<RiskIncidence> selected)
throws GenericException, AuthorizationDeniedException, RequestNotValidException, NotFoundException,
InvalidParameterException, JobAlreadyStartedException {
List<String> idList = consolidate(user, RiskIncidence.class, selected);
for (String incidenceId : idList) {
RodaCoreFactory.getModelService().deleteRiskIncidence(incidenceId, true);
}
}
public static void updateMultipleIncidences(SelectedItems<RiskIncidence> selected, String status, String severity,
Date mitigatedOn, String mitigatedBy, String mitigatedDescription)
throws RequestNotValidException, GenericException, NotFoundException, AuthorizationDeniedException {
IndexService index = RodaCoreFactory.getIndexService();
ModelService model = RodaCoreFactory.getModelService();
if (selected instanceof SelectedItemsList) {
SelectedItemsList<RiskIncidence> list = (SelectedItemsList<RiskIncidence>) selected;
List<String> ids = list.getIds();
for (String id : ids) {
RiskIncidence incidence = RodaCoreFactory.getModelService().retrieveRiskIncidence(id);
incidence.setStatus(INCIDENCE_STATUS.valueOf(status));
incidence.setSeverity(SEVERITY_LEVEL.valueOf(severity));
incidence.setMitigatedOn(mitigatedOn);
incidence.setMitigatedBy(mitigatedBy);
incidence.setMitigatedDescription(mitigatedDescription);
model.updateRiskIncidence(incidence, false);
}
index.commit(RiskIncidence.class);
} else if (selected instanceof SelectedItemsFilter) {
SelectedItemsFilter<RiskIncidence> filter = (SelectedItemsFilter<RiskIncidence>) selected;
int counter = index.count(RiskIncidence.class, filter.getFilter()).intValue();
IndexResult<RiskIncidence> incidences = index.find(RiskIncidence.class, filter.getFilter(), Sorter.NONE,
new Sublist(0, counter), new ArrayList<>());
for (RiskIncidence incidence : incidences.getResults()) {
incidence.setStatus(INCIDENCE_STATUS.valueOf(status));
incidence.setSeverity(SEVERITY_LEVEL.valueOf(severity));
incidence.setMitigatedOn(mitigatedOn);
incidence.setMitigatedBy(mitigatedBy);
incidence.setMitigatedDescription(mitigatedDescription);
model.updateRiskIncidence(incidence, false);
}
index.commit(RiskIncidence.class);
}
}
public static TransferredResource reindexTransferredResource(String path)
throws IsStillUpdatingException, NotFoundException, GenericException {
TransferredResourcesScanner scanner = RodaCoreFactory.getTransferredResourcesScanner();
scanner.updateTransferredResources(Optional.of(path), true);
return RodaCoreFactory.getIndexService().retrieve(TransferredResource.class,
IdUtils.getTransferredResourceUUID(path), new ArrayList<>());
}
public static DIP createDIP(DIP dip) throws GenericException, AuthorizationDeniedException {
return RodaCoreFactory.getModelService().createDIP(dip, true);
}
public static DIP updateDIP(DIP dip) throws GenericException, AuthorizationDeniedException, NotFoundException {
return RodaCoreFactory.getModelService().updateDIP(dip);
}
public static void deleteDIPs(SelectedItems<IndexedDIP> selected, User user)
throws GenericException, AuthorizationDeniedException, NotFoundException, RequestNotValidException {
for (String dipId : consolidate(user, IndexedDIP.class, selected)) {
RodaCoreFactory.getModelService().deleteDIP(dipId);
}
RodaCoreFactory.getIndexService().commit(IndexedDIP.class);
}
protected static EntityResponse retrieveDIP(String dipId, String acceptFormat)
throws GenericException, RequestNotValidException, NotFoundException, AuthorizationDeniedException {
if (RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_ZIP.equals(acceptFormat)) {
StorageService storage = RodaCoreFactory.getStorageService();
StoragePath storagePath = ModelUtils.getDIPDataStoragePath(dipId);
if (!storage.hasDirectory(storagePath)) {
storagePath = ModelUtils.getDIPStoragePath(dipId);
}
return ApiUtils.download(storage.getDirectory(storagePath), dipId);
} else if (RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_JSON.equals(acceptFormat)
|| RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_XML.equals(acceptFormat)) {
DIP dip = RodaCoreFactory.getModelService().retrieveDIP(dipId);
return new ObjectResponse<DIP>(acceptFormat, dip);
} else {
throw new GenericException("Unsupported accept format: " + acceptFormat);
}
}
public static EntityResponse retrieveDIPFile(String fileUuid, String acceptFormat)
throws GenericException, RequestNotValidException, NotFoundException, AuthorizationDeniedException {
DIPFile iFile = RodaCoreFactory.getIndexService().retrieve(DIPFile.class, fileUuid,
RodaConstants.DIPFILE_FIELDS_TO_RETURN);
if (!iFile.isDirectory() && RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_BIN.equals(acceptFormat)) {
final String filename;
final String mediaType;
final ConsumesOutputStream stream;
StorageService storage = RodaCoreFactory.getStorageService();
Binary representationFileBinary = storage.getBinary(ModelUtils.getDIPFileStoragePath(iFile));
filename = representationFileBinary.getStoragePath().getName();
mediaType = RodaConstants.MEDIA_TYPE_WILDCARD;
stream = new ConsumesOutputStream() {
@Override
public String getMediaType() {
return acceptFormat;
}
@Override
public String getFileName() {
return filename;
}
@Override
public void consumeOutputStream(OutputStream out) throws IOException {
InputStream fileInputStream = null;
try {
fileInputStream = representationFileBinary.getContent().createInputStream();
IOUtils.copy(fileInputStream, out);
} finally {
IOUtils.closeQuietly(fileInputStream);
}
}
};
return new StreamResponse(filename, mediaType, stream);
} else if (iFile.isDirectory() && (RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_ZIP.equals(acceptFormat)
|| RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_BIN.equals(acceptFormat))) {
StoragePath filePath = ModelUtils.getDIPFileStoragePath(iFile);
Directory directory = RodaCoreFactory.getStorageService().getDirectory(filePath);
return ApiUtils.download(directory);
} else if (RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_JSON.equals(acceptFormat)
|| RodaConstants.API_QUERY_VALUE_ACCEPT_FORMAT_XML.equals(acceptFormat)) {
DIPFile file = RodaCoreFactory.getModelService().retrieveDIPFile(iFile.getDipId(), iFile.getPath(),
iFile.getId());
return new ObjectResponse<DIPFile>(acceptFormat, file);
} else {
throw new GenericException("Unsupported accept format: " + acceptFormat);
}
}
public static DIPFile createDIPFile(String dipId, List<String> directoryPath, String fileId, long size,
ContentPayload content, boolean notify) throws GenericException, AuthorizationDeniedException,
RequestNotValidException, NotFoundException, AlreadyExistsException {
return RodaCoreFactory.getModelService().createDIPFile(dipId, directoryPath, fileId, size, content, notify);
}
public static String createDIPFolder(String dipId, String folderUUID, String newName) throws GenericException,
RequestNotValidException, AlreadyExistsException, NotFoundException, AuthorizationDeniedException {
ModelService model = RodaCoreFactory.getModelService();
IndexService index = RodaCoreFactory.getIndexService();
if (folderUUID != null) {
DIPFile ifolder = index.retrieve(DIPFile.class, folderUUID, RodaConstants.DIPFILE_FIELDS_TO_RETURN);
DIPFile newFolder = model.createDIPFile(ifolder.getDipId(), ifolder.getPath(), ifolder.getId(), newName, true);
index.commit(DIPFile.class);
return IdUtils.getDIPFileId(newFolder);
} else {
DIPFile newFolder = model.createDIPFile(dipId, null, null, newName, true);
index.commit(DIPFile.class);
return IdUtils.getDIPFileId(newFolder);
}
}
public static DIPFile updateDIPFile(String dipId, List<String> directoryPath, String oldFileId, String fileId,
long size, ContentPayload content, boolean notify) throws GenericException, AuthorizationDeniedException,
NotFoundException, RequestNotValidException, AlreadyExistsException {
return RodaCoreFactory.getModelService().updateDIPFile(dipId, directoryPath, oldFileId, fileId, size, content, true,
notify);
}
public static void deleteDIPFiles(SelectedItems<DIPFile> selected, User user)
throws AuthorizationDeniedException, GenericException, RequestNotValidException, NotFoundException {
List<String> fileIds = consolidate(user, DIPFile.class, selected);
Filter filter = new Filter();
filter.add(new OneOfManyFilterParameter(RodaConstants.INDEX_UUID, fileIds));
IndexResult<DIPFile> files = RodaCoreFactory.getIndexService().find(DIPFile.class, filter, Sorter.NONE,
new Sublist(0, fileIds.size()), RodaConstants.DIPFILE_FIELDS_TO_RETURN);
for (DIPFile file : files.getResults()) {
RodaCoreFactory.getModelService().deleteDIPFile(file.getDipId(), file.getPath(), file.getId(), true);
}
RodaCoreFactory.getIndexService().commit(DIPFile.class);
}
public static void createFormatIdentificationJob(User user, SelectedItems<?> selected) throws GenericException,
JobAlreadyStartedException, RequestNotValidException, NotFoundException, AuthorizationDeniedException {
Job job = new Job();
job.setId(IdUtils.createUUID());
job.setName("Format identification using Siegfried");
job.setSourceObjects(selected);
job.setPlugin(SiegfriedPlugin.class.getCanonicalName());
job.setPluginType(PluginType.MISC);
job.setUsername(user.getName());
RodaCoreFactory.getModelService().createJob(job);
RodaCoreFactory.getPluginOrchestrator().executeJob(job, true);
}
public static void changeRepresentationType(User user, SelectedItems<IndexedRepresentation> selected, String newType,
String details) throws GenericException, AuthorizationDeniedException, RequestNotValidException, NotFoundException {
String eventDescription = "The process of updating an object of the repository.";
List<String> representationIds = consolidate(user, IndexedRepresentation.class, selected);
ModelService model = RodaCoreFactory.getModelService();
IndexService index = RodaCoreFactory.getIndexService();
Filter filter = new Filter();
filter.add(new OneOfManyFilterParameter(RodaConstants.INDEX_UUID, representationIds));
IndexResult<IndexedRepresentation> reps = index.find(IndexedRepresentation.class, filter, Sorter.NONE,
new Sublist(0, representationIds.size()), Arrays.asList(RodaConstants.REPRESENTATION_ID,
RodaConstants.REPRESENTATION_TYPE, RodaConstants.REPRESENTATION_AIP_ID));
for (IndexedRepresentation irep : reps.getResults()) {
String oldType = irep.getType();
List<LinkingIdentifier> sources = new ArrayList<>();
sources.add(PluginHelper.getLinkingIdentifier(irep.getAipId(), irep.getId(),
RodaConstants.PRESERVATION_LINKING_OBJECT_SOURCE));
try {
model.updateRepresentationType(irep.getAipId(), irep.getId(), newType);
index.commit(IndexedRepresentation.class);
StringBuilder outcomeText = new StringBuilder().append("The representation '").append(irep.getId())
.append("' changed its type from '").append(oldType).append("' to '").append(newType).append("'.");
model.createEvent(irep.getAipId(), irep.getId(), null, null, PreservationEventType.UPDATE, eventDescription,
sources, null, PluginState.SUCCESS, outcomeText.toString(), details, user.getName(), true);
} catch (RequestNotValidException | NotFoundException | GenericException | AuthorizationDeniedException e) {
StringBuilder outcomeText = new StringBuilder().append("The representation '").append(irep.getId())
.append("' did not change its type from '").append(oldType).append("' to '").append(newType).append("'.");
model.createEvent(irep.getAipId(), irep.getId(), null, null, PreservationEventType.UPDATE, eventDescription,
sources, null, PluginState.FAILURE, outcomeText.toString(), details, user.getName(), true);
throw e;
}
}
}
public static ObjectPermissionResult verifyPermissions(String username, String permissionType,
MultivaluedMap<String, String> queryParams)
throws GenericException, NotFoundException, AuthorizationDeniedException, RequestNotValidException {
ObjectPermissionResult result = new ObjectPermissionResult();
for (Entry<String, List<String>> entry : queryParams.entrySet()) {
String queryKey = entry.getKey();
try {
Class.forName(queryKey);
for (String queryValues : entry.getValue()) {
boolean hasPermission = RodaCoreFactory.getModelService().checkObjectPermission(username, permissionType,
queryKey, queryValues);
result.addObject(new ObjectPermission(queryKey, queryValues, hasPermission));
}
} catch (ClassNotFoundException e) {
// do nothing
}
}
return result;
}
public static boolean hasDocumentation(String aipId)
throws RequestNotValidException, AuthorizationDeniedException, GenericException {
StoragePath aipPath = ModelUtils.getAIPStoragePath(aipId);
StoragePath documentationPath = DefaultStoragePath.parse(aipPath, RodaConstants.STORAGE_DIRECTORY_DOCUMENTATION);
try {
Long counter = RodaCoreFactory.getStorageService().countResourcesUnderContainer(documentationPath, false);
return counter > 0;
} catch (NotFoundException e) {
return false;
}
}
}