/**
* 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.core.plugins.misc;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.roda.core.RodaCoreFactory;
import org.roda.core.data.common.RodaConstants;
import org.roda.core.data.common.RodaConstants.PreservationEventType;
import org.roda.core.data.exceptions.RODAException;
import org.roda.core.data.v2.LiteOptionalWithCause;
import org.roda.core.data.v2.ip.AIP;
import org.roda.core.data.v2.ip.AIPState;
import org.roda.core.data.v2.jobs.Job;
import org.roda.core.data.v2.jobs.PluginParameter;
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.index.IndexService;
import org.roda.core.model.ModelService;
import org.roda.core.model.utils.ModelUtils;
import org.roda.core.plugins.AbstractPlugin;
import org.roda.core.plugins.Plugin;
import org.roda.core.plugins.PluginException;
import org.roda.core.plugins.RODAObjectProcessingLogic;
import org.roda.core.plugins.orchestrate.JobPluginInfo;
import org.roda.core.plugins.orchestrate.SimpleJobPluginInfo;
import org.roda.core.plugins.plugins.PluginHelper;
import org.roda.core.storage.StorageService;
import org.roda.core.storage.fs.FSUtils;
import org.roda_project.commons_ip.model.ParseException;
import org.roda_project.commons_ip.model.impl.eark.EARKAIP;
import org.roda_project.commons_ip.utils.IPException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Plugin that generates E-ARK AIP manifest files (METS.xml) from the exiting
* AIP information in the storage layer.
*
* @author Rui Castro <rui.castro@gmail.com>
*/
public class CreateMetsPlugin extends AbstractPlugin<AIP> {
/** Logger. */
private static final Logger LOGGER = LoggerFactory.getLogger(CreateMetsPlugin.class);
/** Plugin version. */
private static final String VERSION = "1.0";
@Override
public void init() throws PluginException {
// do nothing
}
@Override
public void shutdown() {
// do nothing
}
@Override
public String getName() {
return "Create E-ARK AIP manifest files (METS.xml)";
}
@Override
public String getDescription() {
return "Plugin that generates E-ARK AIP manifest files (\"METS.xml\") from "
+ "existing AIP information in the storage layer. This plugin only works with filesystem as the storage service.";
}
@Override
public String getVersionImpl() {
return VERSION;
}
@Override
public Plugin<AIP> cloneMe() {
return new CreateMetsPlugin();
}
@Override
public PluginType getType() {
return PluginType.MISC;
}
@Override
public List<PluginParameter> getParameters() {
return new ArrayList<>();
}
@Override
public boolean areParameterValuesValid() {
return true;
}
@Override
public PreservationEventType getPreservationEventType() {
return PreservationEventType.RISK_MANAGEMENT;
}
@Override
public String getPreservationEventDescription() {
return "TODO: Preservation event description";
}
@Override
public String getPreservationEventSuccessMessage() {
return "Success";
}
@Override
public String getPreservationEventFailureMessage() {
return "Failure";
}
@Override
public Report beforeAllExecute(final IndexService index, final ModelService model, final StorageService storage)
throws PluginException {
// do nothing
return null;
}
@Override
public Report afterAllExecute(final IndexService index, final ModelService model, final StorageService storage)
throws PluginException {
// do nothing
return null;
}
@Override
public List<String> getCategories() {
return Collections.singletonList(RodaConstants.PLUGIN_CATEGORY_MISC);
}
@Override
public List<Class<AIP>> getObjectClasses() {
return Collections.singletonList(AIP.class);
}
@Override
public Report execute(final IndexService index, final ModelService model, final StorageService storage,
final List<LiteOptionalWithCause> liteList) throws PluginException {
return PluginHelper.processObjects(this, new RODAObjectProcessingLogic<AIP>() {
@Override
public void process(IndexService index, ModelService model, StorageService storage, Report report, Job cachedJob,
SimpleJobPluginInfo jobPluginInfo, Plugin<AIP> plugin, AIP object) {
executeOnAip(object, index, model, jobPluginInfo, report, cachedJob);
}
}, index, model, storage, liteList);
}
/**
* Execute on a single {@link AIP}.
*
* @param aip
* the {@link AIP}.
* @param index
* the {@link IndexService}.
* @param model
* the {@link ModelService}.
* @param storage
* the {@link StorageService}.
* @param jobPluginInfo
* the {@link JobPluginInfo}
* @param report
* the {@link Report}.
*/
private void executeOnAip(final AIP aip, final IndexService index, final ModelService model,
final JobPluginInfo jobPluginInfo, final Report report, final Job job) {
LOGGER.debug("Processing AIP {}", aip.getId());
final Report reportItem = PluginHelper.initPluginReportItem(this, aip.getId(), AIP.class, AIPState.ACTIVE);
PluginHelper.updatePartialJobReport(this, model, reportItem, false, job);
try {
final Path aipPath = FSUtils.getEntityPath(RodaCoreFactory.getStoragePath(),
ModelUtils.getAIPStoragePath(aip.getId()));
LOGGER.debug("aipPath = {}", aipPath);
new EARKAIP(RodaFolderAIP.parse(aipPath)).build(aipPath.getParent(), true);
jobPluginInfo.incrementObjectsProcessedWithSuccess();
reportItem.setPluginState(PluginState.SUCCESS);
} catch (final RODAException | ParseException | IPException | InterruptedException e) {
final String message = String.format("Error creating manifest files for AIP %s. Cause: %s.", aip.getId(),
e.getMessage());
LOGGER.debug(message, e);
jobPluginInfo.incrementObjectsProcessedWithFailure();
reportItem.setPluginState(PluginState.FAILURE);
reportItem.setPluginDetails(message);
}
report.addReport(reportItem);
PluginHelper.updatePartialJobReport(this, model, reportItem, true, job);
}
}