/**
* Copyright 2008 The University of North Carolina at Chapel Hill
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package edu.unc.lib.dl.cdr.services.imaging;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.jdom2.Document;
import org.jdom2.Element;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import edu.unc.lib.dl.cdr.services.AbstractFedoraEnhancement;
import edu.unc.lib.dl.cdr.services.AbstractIrodsObjectEnhancementService;
import edu.unc.lib.dl.cdr.services.exception.EnhancementException;
import edu.unc.lib.dl.cdr.services.exception.EnhancementException.Severity;
import edu.unc.lib.dl.cdr.services.model.EnhancementMessage;
import edu.unc.lib.dl.fedora.FedoraException;
import edu.unc.lib.dl.fedora.FileSystemException;
import edu.unc.lib.dl.fedora.NotFoundException;
import edu.unc.lib.dl.fedora.PID;
import edu.unc.lib.dl.util.ContentModelHelper;
import edu.unc.lib.dl.util.ContentModelHelper.CDRProperty;
import edu.unc.lib.dl.util.ContentModelHelper.Datastream;
import edu.unc.lib.dl.xml.FOXMLJDOMUtil;
import edu.unc.lib.dl.xml.JDOMNamespaceUtil;
/**
* Enhancement class for the construction of a jp2 derived datastream based off of all image data_file datastreams
* attached to the specified object.
*
* @author bbpennel
*/
public class ImageEnhancement extends AbstractFedoraEnhancement {
private static final Logger LOG = LoggerFactory.getLogger(ImageEnhancement.class);
@Override
public Element call() throws EnhancementException {
Element result = null;
LOG.debug("Called image enhancement service for {}", pid);
String dsid = null;
try {
Document foxml = this.retrieveFoxml();
// get sourceData data stream IDs
List<String> srcDSURIs = this.getSourceData(foxml);
// get current DS version paths in iRODS
for (String srcURI : srcDSURIs) {
dsid = srcURI.substring(srcURI.lastIndexOf("/") + 1);
Element newestSourceDS = FOXMLJDOMUtil.getMostRecentDatastream(
ContentModelHelper.Datastream.getDatastream(dsid), foxml);
if (newestSourceDS == null)
throw new EnhancementException("Specified source datastream " + srcURI + " was not found, the object "
+ this.pid.getPid() + " is most likely invalid", Severity.UNRECOVERABLE);
String dsLocation = null;
String dsIrodsPath = null;
dsLocation = newestSourceDS.getChild("contentLocation", JDOMNamespaceUtil.FOXML_NS).getAttributeValue(
"REF");
LOG.debug("Image DS location: {}", dsLocation);
if (dsLocation != null) {
dsIrodsPath = client.getIrodsPath(dsLocation);
// Ask irods to make the jp2 object
LOG.debug("Convert to JP2");
String convertResultPath = runConvertJP2(dsIrodsPath);
String convertResultURI = ((AbstractIrodsObjectEnhancementService) service)
.makeIrodsURIFromPath(convertResultPath);
LOG.debug("attempting to ingest conversion result: " + convertResultPath);
boolean exists = service.getManagementClient()
.dataStreamExists(pid, Datastream.IMAGE_JP2000.getName());
if (exists) {
LOG.debug("Replacing managed datastream for JP2");
String message = "Replacing derived JP2000 image datastream.";
client.modifyDatastreamByReference(pid,
Datastream.IMAGE_JP2000.getName(), false, message,
new ArrayList<String>(), "Derived JP2000 image", "image/jp2", null, null, convertResultURI);
} else {
LOG.debug("Adding managed datastream for JP2");
String message = "Adding derived JP2000 image datastream.";
client.addManagedDatastream(pid,
Datastream.IMAGE_JP2000.getName(), false, message,
new ArrayList<String>(), "Derived JP2000 image", false, "image/jp2", convertResultURI);
}
// Add DATA_JP2, cdr-base:derivedJP2 relation triple
LOG.debug("Adding JP2 relationship");
PID newDSPID = new PID(pid.getPid() + "/" + ContentModelHelper.Datastream.IMAGE_JP2000.getName());
Map<String, List<String>> rels = service.getTripleStoreQueryService().fetchAllTriples(pid);
List<String> jp2rel = rels.get(ContentModelHelper.CDRProperty.derivedJP2.toString());
if (jp2rel == null || !jp2rel.contains(newDSPID.getURI())) {
client.setExclusiveTripleRelation(pid, CDRProperty.derivedJP2.getPredicate(),
CDRProperty.derivedJP2.getNamespace(), newDSPID);
}
// Clean up the temporary irods file
LOG.debug("Deleting temporary jp2 Irods file");
((AbstractIrodsObjectEnhancementService) service).deleteIRODSFile(convertResultPath);
LOG.debug("Finished JP2 processing");
}
}
} catch (FileSystemException e) {
throw new EnhancementException(e, Severity.FATAL);
} catch (NotFoundException e) {
throw new EnhancementException(e, Severity.UNRECOVERABLE);
} catch (FedoraException e) {
throw new EnhancementException("Image Enhancement failed to process " + dsid, e, Severity.RECOVERABLE);
} catch (Exception e) {
throw new EnhancementException("Image Enhancement failed to process " + dsid, e, Severity.UNRECOVERABLE);
}
return result;
}
private String runConvertJP2(String dsIrodsPath) throws Exception {
LOG.debug("Run (image magick) convertjp2 {}", dsIrodsPath);
// execute irods image magick rule
InputStream response = ((AbstractIrodsObjectEnhancementService) service).remoteExecuteWithPhysicalLocation(
"convertjp2", dsIrodsPath);
try(BufferedReader r = new BufferedReader(new InputStreamReader(response))) {
return r.readLine().trim();
} catch (Exception e) {
throw e;
}
}
public ImageEnhancement(ImageEnhancementService service, EnhancementMessage message) {
super(service, message);
}
}