
com.day.cq.dam.commons.metadata.SimpleXmpToJcrMetadataBuilder Maven / Gradle / Ivy
/*
* Copyright 1997-2008 Day Management AG
* Barfuesserplatz 6, 4001 Basel, Switzerland
* All Rights Reserved.
*
* This software is the confidential and proprietary information of
* Day Management AG, ("Confidential Information"). You shall not
* disclose such Confidential Information and shall use it only in
* accordance with the terms of the license agreement you entered into
* with Day.
*/
package com.day.cq.dam.commons.metadata;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.jcr.Binary;
import javax.jcr.Item;
import javax.jcr.NamespaceException;
import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.PathNotFoundException;
import javax.jcr.Property;
import javax.jcr.PropertyIterator;
import javax.jcr.PropertyType;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.Value;
import com.adobe.granite.asset.api.AssetMetadata;
import com.adobe.xmp.XMPConst;
import com.adobe.xmp.XMPDateTime;
import com.adobe.xmp.XMPDateTimeFactory;
import com.adobe.xmp.XMPException;
import com.adobe.xmp.XMPIterator;
import com.adobe.xmp.XMPMeta;
import com.adobe.xmp.XMPMetaFactory;
import com.adobe.xmp.XMPPathFactory;
import com.adobe.xmp.core.XMPArray;
import com.adobe.xmp.core.XMPMetadata;
import com.adobe.xmp.core.parser.RDFXMLParser;
import com.adobe.xmp.core.parser.RDFXMLParserContext;
import com.adobe.xmp.options.PropertyOptions;
import com.adobe.xmp.path.XMPPath;
import com.adobe.xmp.properties.XMPProperty;
import com.adobe.xmp.properties.XMPPropertyInfo;
import com.day.cq.commons.jcr.JcrConstants;
import com.day.cq.dam.api.Asset;
import com.day.cq.dam.api.DamConstants;
import com.day.cq.dam.api.metadata.ExtractedMetadata;
import com.day.cq.dam.api.metadata.xmp.XmpMappings;
import com.day.cq.dam.commons.util.DateParser;
import com.day.cq.tagging.JcrTagManagerFactory;
import com.day.cq.tagging.Tag;
import com.day.cq.tagging.TagManager;
import org.apache.commons.imaging.common.RationalNumber;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.Service;
import org.apache.jackrabbit.util.Text;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ValueMap;
import org.apache.sling.jcr.api.SlingRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xml.sax.ErrorHandler;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import static com.day.cq.dam.api.DamConstants.DC_DESCRIPTION;
import static com.day.cq.dam.api.DamConstants.DC_FORMAT;
/**
* The XmpToJcrMetadataBuilder
class ...
*/
@Component(metatype = false, label = "SimpleXmpToJcrMetadataBuilder Handler", description = "SimpleXmpToJcrMetadataBuilder Handler")
@Service(value = SimpleXmpToJcrMetadataBuilder.class)
public class SimpleXmpToJcrMetadataBuilder {
private static final String METADATA_PROPERTY_NAME_ADOBE_KEYWORDS = "lr:hierarchicalSubject";
private static final String XMP_ARRAY_TYPE = "xmpArrayType";
private static final String IS_XMP_ARRAY = "isXMPArray";
/**
* the default logger
*/
private static final Logger log = LoggerFactory.getLogger(SimpleXmpToJcrMetadataBuilder.class);
public static final String NT_RDF_BAG = "rdf:Bag";
public static final String NT_RDF_SEQ = "rdf:Seq";
public static final String NT_RDF_ALT = "rdf:Alt";
private static final String INGREDIENT_TAG = "xmpMM:Ingredients";
private static final String SYNC_FLAG = "newRendition";
private static final String DAM_NS_URI = "http://www.day.com/dam/1.0";
private static final String CQ_NS_URI = "http://www.day.com/jcr/cq/1.0";
// sub-service for adding new namespace mappings from XMP to JCR
private static final String NAMESPACE_UPDATE_HELPER = "namespaceupdatehelper";
private String defaultFormats[] = new String[] { "application/octet-stream" };
//initalize the list of properties that can have alternative texts
private static final List altArrayProps = new ArrayList(8);
private static final int MAX_ITEM_SIZE = 1000;
//initialize the list
static {
altArrayProps.add(DamConstants.DC_DESCRIPTION);
altArrayProps.add(DamConstants.DC_TITLE);
altArrayProps.add(DamConstants.DC_RIGHTS);
altArrayProps.add("xmpRights:UsageTerms");
altArrayProps.add("exif:UserComment");
altArrayProps.add("tiff:Copyright");
altArrayProps.add("tiff:ImageDescription");
}
private static final List ignoreHierarchy = new ArrayList();
static {
ignoreHierarchy.add(DamConstants.DC_DESCRIPTION);
ignoreHierarchy.add(DamConstants.DC_TITLE);
ignoreHierarchy.add(DamConstants.DC_RIGHTS);
ignoreHierarchy.add("xmpRights:UsageTerms");
ignoreHierarchy.add("exif:UserComment");
ignoreHierarchy.add("tiff:Copyright");
ignoreHierarchy.add("tiff:ImageDescription");
ignoreHierarchy.add("cq:tags");
ignoreHierarchy.add("dc:creator");
ignoreHierarchy.add("creator");
ignoreHierarchy.add("dc:contributor");
ignoreHierarchy.add("dc:language");
ignoreHierarchy.add("dc:subject");
ignoreHierarchy.add("photoshop:SupplementalCategories");
}
public SimpleXmpToJcrMetadataBuilder() {
// priortise "Image Length" over "ImageLength".
// priortise "Image Width" over "ImageWidth".
conflictPropMap.put("ImageLength", "Image Length");
conflictPropMap.put("ImageWidth", "Image Width");
conflictPropMap.put(DamConstants.TIFF_IMAGEWIDTH, "Image Width");
conflictPropMap.put(DamConstants.TIFF_IMAGELENGTH, "Image Length");
conflictPropMap.put(DC_DESCRIPTION, "description");
conflictPropMap.put(DC_DESCRIPTION, "Caption/Abstract");
}
//prioritize properties
public final MapconflictPropMap = new HashMap(5);
@Reference
private XmpFilter xmpFilter;
@Reference
private JcrTagManagerFactory tagManagerFactory;
@Reference
private SlingRepository repository;
/*
* FIXME: which method should be used instead?
*/
@Deprecated
public void storeXmp(Node metadataRoot, XMPMeta meta, boolean doSave)
throws XMPException, RepositoryException {
XMPIterator itr = meta.iterator();
String rootPath = metadataRoot.getPath();
Map> arrayMap = new HashMap>();
while (itr.hasNext()) {
XMPPropertyInfo prop = (XMPPropertyInfo) itr.next();
if (!prop.getOptions().isSchemaNode()) {
if (prop.getOptions().isQualifier()
|| prop.getOptions().isSimple()) {
// check namespace TODO: correct here?
checkNamespace(prop, metadataRoot);
String path = (Text.getRelativeParent(prop.getPath(), 1).equals(""))
? rootPath
: rootPath + "/"
+ Text.getRelativeParent(prop.getPath(), 1);
if (isArrayMember(arrayMap, prop.getPath())) {
if (prop.getOptions().isQualifier()) {
log.debug("Qualifier detected (noop): "
+ prop.toString());
} else if (prop.getOriValue() != null) {
String p = prop.getPath();
p = p.substring(0, p.lastIndexOf("["));
arrayMap.get(p).add(prop);
}
} else {
if (prop.getOptions().isQualifier()) {
log.debug("Qualifier detected (noop): "
+ prop.toString());
} else if (prop.getOriValue() != null) {
Node node = getOrCreateNode(
metadataRoot.getSession(), path,
JcrConstants.NT_UNSTRUCTURED);
if (node != null) {
setProperty(node, prop);
}
log.debug("PATH: " + rootPath + "/" + prop.getPath()
+ ":" + prop.getValue());
} else {
log.debug(prop.getPath() + " is NULL");
}
}
} else if (prop.getOptions().isArray()) {
checkNamespace(prop, metadataRoot);
ArrayList members = new ArrayList();
members.add(prop); //add array node as first element
arrayMap.put(prop.getPath(),
members);
} else if (prop.getOptions().isStruct()) {
// struct can be member of array
if (isArrayMember(arrayMap, prop.getPath())) {
log.debug("Struct as member of array");
if (prop.getOptions().isQualifier()) {
log.debug("Qualifier detected (noop): "
+ prop.toString());
} else if (prop.getOriValue() != null) {
String p = prop.getPath();
int arrayIndexStrt = p.lastIndexOf("[");
if (arrayIndexStrt > -1) {
p = p.substring(0, arrayIndexStrt);
}
arrayMap.get(p).add(prop);
}
} else {
checkNamespace(prop, metadataRoot);
String path = rootPath + "/" + prop.getPath();
getOrCreateNode(metadataRoot.getSession(), path,
JcrConstants.NT_UNSTRUCTURED);
}
}
}
}
// add arrays
for (String path : arrayMap.keySet()) {
String parentPath = Text.getRelativeParent(path, 1);
List arrayMembers = arrayMap.get(path);
if (arrayMembers.size() > 1) { //first element is array itself
//normalize the parent path for array indexes in case of array of struct
//create the parent node
Node node = getOrCreateNode(metadataRoot.getSession(),
rootPath + "/" + normalizeArrayPath(parentPath), JcrConstants.NT_UNSTRUCTURED);
if (node != null) {
//array first member is the array prop itself, so remove it
// this was added to propagate the type of array
XMPPropertyInfo arrayProp = arrayMembers.remove(0);
//check the type
String name = NT_RDF_BAG;
if (arrayProp.getOptions().isArrayOrdered()) {
name = NT_RDF_SEQ;
} else if (arrayProp.getOptions().isArrayAlternate()) {
name = NT_RDF_ALT;
}
XMPPropertyInfo firstMember = arrayMembers.get(0);
//if first member is struct then it is an array of struct
if (firstMember.getOptions().isStruct() && !INGREDIENT_TAG.equalsIgnoreCase(Text.getName(path))) {
//create the array node
/*
* FIXME: the method getOrCreateNode returns NULL on errors in the underlying persistence
* and using the return value unchecked will generate NullPointerExceptions
*/
Node arrayNode = getOrCreateNode(metadataRoot.getSession(),
node.getPath() + "/" + Text.getName(path), JcrConstants.NT_UNSTRUCTURED);
arrayNode.setProperty(XMP_ARRAY_TYPE, name); //set the type of array
arrayNode.setProperty(IS_XMP_ARRAY, true);
//clean member nodes
NodeIterator nodes = arrayNode.getNodes();
while (nodes.hasNext()) {
Node childNode = (Node) nodes.next();
childNode.remove();
}
//handle simple properties/as well as struct (may be array)
for (XMPPropertyInfo prop:arrayMembers) {
if (prop.getOptions().isStruct()) {
//create the struct node with normalized path
getOrCreateNode(metadataRoot.getSession(),
rootPath + "/" + normalizeArrayPath(prop.getPath()), JcrConstants.NT_UNSTRUCTURED);
} else if (prop.getOptions().isSimple()) {
String parentStructPath = Text.getRelativeParent(prop.getPath(), 1);
Node parentStructNode = getOrCreateNode(metadataRoot.getSession(),
rootPath + "/" + normalizeArrayPath(parentStructPath), JcrConstants.NT_UNSTRUCTURED);
//set simple property
setProperty(parentStructNode, prop);
}
}
} else {
setMvProperty(node, arrayMembers, Text.getName(path));
}
}
}
}
if (doSave) {
metadataRoot.getSession().save();
}
}
/**
* Normalizes the XMP property path i.e. xmpTPg:SwatchGroups/xmpTPg:SwatchGroups[1]
* will be converted to xmpTPg:SwatchGroups/1
* xmpTPg:SwatchGroups/xmpTPg:SwatchGroups[1]/xmpG:Colorants/xmpG:Colorants[1]
* will be converted to
* xmpTPg:SwatchGroups/1/xmpG:Colorants/1
* @param xmpPath xpath to property
* @return normalized path
*/
private String normalizeArrayPath(String xmpPath) {
xmpPath = xmpPath.replace("[", "/");
return xmpPath.replace("]", "");
}
public void storeXmp(Node metadataRoot, XMPMeta meta) throws XMPException,
RepositoryException {
storeXmp(metadataRoot, meta, true);
}
private boolean isArrayMember(Map> arrayMap,
String path) {
if (path.lastIndexOf("[") > 0) {
String parentPath = path.substring(0, path.lastIndexOf("["));
return arrayMap.containsKey(parentPath);
}
return false;
}
@Deprecated
public XMPMeta getXmpFromJcr(Node metadataRoot) throws RepositoryException,
XMPException {
XMPMeta meta = XMPMetaFactory.create();
// simple props and arrays
PropertyIterator props = metadataRoot.getProperties();
while (props.hasNext()) {
try {
Property prop = props.nextProperty();
String name = prop.getName();
// try to get namespace...
if (name.indexOf(":") < 0) {
log.debug(
"property [{}] doesn't have namespace prefix, skipping. metadata node: [{}].",
name, metadataRoot.getPath());
continue;
}
String splits[] = name.split(":");
String nsPrefix = splits[0];
String namespace = metadataRoot.getSession().getWorkspace().getNamespaceRegistry().getURI(
nsPrefix);
String regPrefix = registerNs(nsPrefix, namespace);
// Bug 42205 : if namespace is registered with some other prefix
// then replace it.
if (!regPrefix.equals(nsPrefix) && splits.length > 1) {
nsPrefix = regPrefix;
name = nsPrefix + ":" + splits[1];
}
// simple props
if (name.indexOf("jcr:") < 0 && !prop.isMultiple()) {
Object val = getValue(prop);
try {
registerNs(nsPrefix, namespace);
if (altArrayProps.contains(name) && val instanceof String ) {
meta.setLocalizedText(namespace, name, XMPConst.X_DEFAULT, XMPConst.X_DEFAULT, (String) val);
} else {
meta.setProperty(namespace, name, val);
}
} catch (XMPException xmpe) {
if(log.isDebugEnabled())
log.debug("Cannot set xmp property: "
+ xmpe.getMessage(), xmpe);
else
log.warn("Cannot set xmp property: "
+ xmpe.getMessage());
}
} else if (name.indexOf("jcr:") < 0 && prop.isMultiple()) {
Object vals[] = getMultiValues(prop);
try {
registerNs(nsPrefix, namespace);
//if there is only single value, then use x-default to write back
//we can not handle lang alternatives yet but still trying to make simpler cases work
if (altArrayProps.contains(name) && vals.length == 1) {
if (vals[0] instanceof String) {
meta.setLocalizedText(namespace, name, XMPConst.X_DEFAULT, XMPConst.X_DEFAULT, (String) vals[0]);
}
} else {
for (Object v : vals) {
if (v instanceof String) {
meta.appendArrayItem(namespace, name,
new PropertyOptions().setArray(true),
(String) v, null);
}
}
}
} catch (XMPException xmpe) {
if(log.isDebugEnabled())
log.debug("Cannot set xmp property: "
+ xmpe.getMessage(), xmpe);
else
log.warn("Cannot set xmp property: "
+ xmpe.getMessage());
}
}
} catch (RepositoryException re) {
log.error("Cannot set xmp property: "
+ re.getMessage(), re);
}
}
try {
// Structs
checkForComplexMetadata(metadataRoot, meta, null, null, new HashMap());
} catch (PathNotFoundException e) {
log.info("Complex Metadata extraction is not applicable for the binary");
} catch (Exception e) { // error in complex metadata extraction should
// not block normal metadata processing
log.error("Unable to extract the complex metadata "
+ e.getMessage() , e);
}
return meta;
}
/**
* To process the complex metadata. It parses properties & structure of
* child nodes of 'jcr:content/metadata' as well as their subsequent
* hierarchy. Name of all the direct child as well as subsequent ones should
* be namespace qualified.
* @param metadataRoot root node (always points to jcr:content/metadata in current impl)
* @param xmpMeta XMPMeta Object
* @param nodeName
* @param nsRootURI
* @throws XMPException
* @throws RepositoryException
*/
private void checkForComplexMetadata(Node metadataRoot, XMPMeta xmpMeta,
String nodeName, String nsRootURI, Map arrOfStructMap)
throws XMPException, RepositoryException {
String pNodeName = nodeName;
// child nodes iteration
for (NodeIterator iter = metadataRoot.getNodes(); iter.hasNext();) {
String childRootURI = nsRootURI;
final Node childMetadataNode = iter.nextNode();
final PropertyIterator dpi = childMetadataNode.getProperties();
final PropertyOptions dpropertyOption = new PropertyOptions();
dpropertyOption.setArray(true);
// For subsequent child nodes
nodeName = (pNodeName == null)
? childMetadataNode.getName(): pNodeName + "/" + childMetadataNode.getName();
// nsSchema remain same for all the subsequent child nodes
if (childRootURI == null ) {
// try to get namespace...
if (childMetadataNode.getName().indexOf(":") < 0) {
log.warn(
"property [{}] doesn't have namespace prefix, skipping. metadata node: [{}].",
childMetadataNode.getName(),
childMetadataNode.getPath());
return;
}
childRootURI = registerPrefix(childMetadataNode);
}
//check the if node represents an array of struct
if (childMetadataNode.hasProperty(IS_XMP_ARRAY) || (childMetadataNode.hasProperty("xmpNodeType") && "xmpArray".equals(childMetadataNode.getProperty("xmpNodeType").getString()) )) {
//it is an array of struct
//create array item
PropertyOptions arrayOptions = new PropertyOptions();
if (childMetadataNode.hasProperty(XMP_ARRAY_TYPE)) {
String arrayType = childMetadataNode.getProperty(XMP_ARRAY_TYPE).getString();
if (NT_RDF_BAG.equals(arrayType)) {
arrayOptions.setArray(true);
} else if (NT_RDF_SEQ.equals(arrayType)) {
arrayOptions.setArrayOrdered(true);
} else if (NT_RDF_ALT.equals(arrayType)) {
arrayOptions.setArrayAlternate(true);
}
} else {
arrayOptions.setArray(true);
}
arrOfStructMap.put(childMetadataNode.getPath(), arrayOptions);
} else {
//if current node's parent (metadataRoot) is part of array of struct
if (arrOfStructMap.containsKey(metadataRoot.getPath())) {
//add array of struct
xmpMeta.appendArrayItem(childRootURI, pNodeName,
arrOfStructMap.get(metadataRoot.getPath()), null,
new PropertyOptions().setStruct(true));
int index = xmpMeta.countArrayItems(childRootURI, pNodeName);
//call handle complex metadata
nodeName = pNodeName + "[" + index + "]";
}
// ToDo: Add empty node structure to support nodes which doesn't
// have properties.
// Iterating & writing back all the properties
while (dpi.hasNext()) {
Property p = dpi.nextProperty();
// try to get namespace...
if (p.getName().indexOf(":") < 0) {
log.debug(
"property [{}] doesn't have namespace prefix, skipping. metadata node: [{}].",
p.getName(), childMetadataNode.getPath());
continue;
}
//register property prefix
registerPrefix(p);
if (childRootURI != null && p.getName() != null) {
if ((p.getName().indexOf("jcr:") < 0 && p.isMultiple())) {
log.debug(
"Multiple value metadata property {}, creating String[] in XMP",
p.getName());
try {
Value values[] = p.getValues();
for (Value value : values) {
xmpMeta.appendArrayItem(childRootURI, nodeName
+ "/" + p.getName(), dpropertyOption,
value.getString(), null);
}
} catch (XMPException xmpe) {
if(log.isDebugEnabled())
log.debug("Cannot set xmp property: "
+ xmpe.getMessage(), xmpe);
else
log.warn("Cannot set xmp property: "
+ xmpe.getMessage());
}
} else if ((p.getName().indexOf("jcr:") < 0 && !p.isMultiple())) {
log.debug("Writing {} with value: {}", p.getName(),
p.getString());
try {
// ToDO: Used setProperty in place of setStructField
// due to bug in parsing xpath expression
xmpMeta.setProperty(childRootURI,
nodeName + "/" + p.getName(), p.getString());
// xmpMeta.setStructField(nsUriChild,derivedMetadataNode.getName(),nsUri,p.getName(),p.getString());
} catch (XMPException xmpe) {
if(log.isDebugEnabled())
log.debug("Cannot set xmp property: "
+ xmpe.getMessage(), xmpe);
else
log.warn("Cannot set xmp property: "
+ xmpe.getMessage());
}
}
}
}
}
// Recursively child nodes extraction
if (childMetadataNode.getNodes().getSize() > 0) {
checkForComplexMetadata(childMetadataNode, xmpMeta, nodeName,
childRootURI, arrOfStructMap);
}
}
}
private String registerPrefix(final Item jcrItem)
throws RepositoryException {
final String childPrefix = jcrItem.getName().substring(
0, jcrItem.getName().indexOf(":"));
final String nsUriChild = jcrItem.getSession().getWorkspace().getNamespaceRegistry().getURI(
childPrefix);
try {
registerNs(childPrefix, nsUriChild);
} catch (XMPException xmpe) {
log.warn("Cannot process the xmp structure: "
+ xmpe.getMessage());
}
return nsUriChild;
}
/**
* @param metadata - map of properties extracted by asset handler
* @param metadataRoot - metadata node of asset
* @param doSave - whether the repository changes are saved or not
* @throws XMPException
* @throws RepositoryException
* @deprecated use {@link SimpleXmpToJcrMetadataBuilder#storeAsXmp(ExtractedMetadata, Asset, boolean)} instead
*/
@Deprecated
public void storeAsXmp(ExtractedMetadata metadata, Node metadataRoot, boolean doSave) throws XMPException, RepositoryException {
XMPMeta meta = XMPMetaFactory.create();
convertToXmp( metadata, metadataRoot, meta, doSave);
storeXmp(metadataRoot, meta, doSave);
}
/**
* @param metadata - map of properties extracted by asset handler
* @param asset - asset to which metadata is to be save
* @param doSave - whether the repository changes are saved or not
* @throws XMPException
* @throws RepositoryException
*/
/* FIXME: this seems never be used outside this class, should be private */
public void storeAsXmp(ExtractedMetadata metadata, Asset asset,
boolean doSave) throws XMPException, RepositoryException {
Node assetNode = asset.adaptTo(Node.class);
Node metadataRoot = assetNode.getNode(JcrConstants.JCR_CONTENT+'/'+DamConstants.METADATA_FOLDER);
InputStream is = metadata.getXmp();
XMPMeta xmpMeta = null;
try {
if (is != null) {
if (xmpFilter != null) {
is = xmpFilter.filter(is);
}
xmpMeta = XMPMetaFactory.parse(is);
resolvePropConflict(metadata, conflictPropMap);
resolvePropConflict(metadata, xmpMeta, conflictPropMap);
convertToXmp(metadata, metadataRoot, xmpMeta, doSave);
if (metadataRoot.hasProperty(DC_FORMAT)
&& !isDefaultFormat(metadataRoot.getProperty(DC_FORMAT).getValue().getString())
&& xmpMeta.getPropertyString(XMPConst.NS_DC, DC_FORMAT) != null) {
xmpMeta.deleteProperty(XMPConst.NS_DC, DC_FORMAT);
}
}
else {
xmpMeta = XMPMetaFactory.create();
convertToXmp( metadata, metadataRoot, xmpMeta, doSave);
}
XMPMetadata xmpMetadata=null;
final byte[] xmpBytes = XMPMetaFactory.serializeToBuffer(xmpMeta, null);
RDFXMLParserContext parserContext = new RDFXMLParserContext();
xmpMetadata = (new RDFXMLParser()).parse(xmpBytes,parserContext);
Set nss = parserContext.getPrefixDefinitions().keySet();
for (String ns : nss){
checkNamespace(parserContext.getPrefixDefinitions().get(ns), metadataRoot);
}
validateTags(xmpMetadata,asset);
AssetMetadata assetMetadata = ((asset.adaptTo(Resource.class)).adaptTo((com.adobe.granite.asset.api.Asset.class))).getAssetMetadata();
assetMetadata.setXMP(xmpMetadata, null, ignoreHierarchy);
extractHierarchicalSubjects(asset,metadataRoot.getSession());
} catch (com.adobe.xmp.core.XMPException e) {
log.info("cannot convert extractedmetadata to XMPMetadata",e);
} catch (IOException e) {
log.info("cannot convert extractedmetadata to XMPMetadata", e);
}
}
/**
* ignore the cq:tags which are not available in the system - Refer:- CQ-106710
* @param xmpMetadata
* @param asset
*/
private void validateTags(XMPMetadata xmpMetadata, Asset asset){
XMPArray tagsArray = xmpMetadata.getArray( CQ_NS_URI,"tags");
if(tagManagerFactory == null){
return;
}
final ResourceResolver resolver = asset.adaptTo(Resource.class).getResourceResolver();
final TagManager tagManager = tagManagerFactory
.getTagManager(resolver);
ArrayList listIndexRemoval = new ArrayList();
if(tagsArray != null ){
for ( int i = 0; i< tagsArray.size(); i++)
{
String tagValue = tagsArray.getSimple(i).getValue();
if(tagValue!= null){
final Tag tag = tagManager.resolve(tagValue);
if (null == tag) {
listIndexRemoval.add(tagsArray.get(i).getXMPPath());
}
}
}
for (XMPPath path : listIndexRemoval) {
try {
xmpMetadata.remove(path);
} catch (com.adobe.xmp.core.XMPException e) {
log.debug("unable to delete the tag from path "+ xmpMetadata.get(path).getName() );
}
}
}
}
private boolean isDefaultFormat(String format) {
for (String defFormat : defaultFormats) {
if (defFormat.equals(format)) {
return true;
}
}
return false;
}
private void convertToXmp(ExtractedMetadata metadata, Node metadataRoot, XMPMeta meta,
boolean doSave) throws XMPException, RepositoryException {
/*
* FIXME: this assigns a java.util.Set to a Set. Either cast explicitly or convert otherwise.
*/
Set keys = metadata.getMetaDataProperties().keySet();
for (String mkey : keys) {
// remove the "(" and ")" char
String key = mkey.replaceAll("\\(", "").replaceAll("\\)", "");
if (XmpMappings.defaultSimpleXmpMappings.containsKey(key)) {
String xmpKeys[] = getXmpKeys(XmpMappings.defaultSimpleXmpMappings.get(key));
for (String xmpKey : xmpKeys) {
try {
setXmpProperty(meta, xmpKey,
metadata.getMetaDataProperties().get(key),metadataRoot.getSession());
} catch (XMPException e) {
log.debug("Cannot create xmp property: "
+ e.getMessage(), e);
}
}
} else if (XmpMappings.defaultBagXmpMappings.containsKey(key)
|| XmpMappings.defaultSeqXmpMappings.containsKey(key)
|| XmpMappings.defaultAltXmpMappings.containsKey(key)) {
String xmpKeys[] = new String[0];
if (XmpMappings.defaultBagXmpMappings.containsKey(key)) {
// CQ-4215741 : in case of pdf asset, dc:subject must store only the pdf keywords metadata and not any other subject key
if(!metadata.getMetaDataProperties().get(DC_FORMAT).equals("application/pdf") || !key.equalsIgnoreCase("subject")) {
xmpKeys = getXmpKeys(XmpMappings.defaultBagXmpMappings.get(key));
}
} else if (XmpMappings.defaultSeqXmpMappings.containsKey(key)) {
xmpKeys = getXmpKeys(XmpMappings.defaultSeqXmpMappings.get(key));
} else if (XmpMappings.defaultAltXmpMappings.containsKey(key)) {
xmpKeys = getXmpKeys(XmpMappings.defaultAltXmpMappings.get(key));
}
for (String xmpKey : xmpKeys) {
try {
String namespace = getNamespace(xmpKey);
Object val = metadata.getMetaDataProperties().get(key);
if (val instanceof List>) {
List> valList = (List>) val;
insertIntoXMPMeta(meta, xmpKey, valList, namespace);
}
else if (val instanceof Object[]) {
List
© 2015 - 2025 Weber Informatics LLC | Privacy Policy