All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.day.cq.dam.commons.metadata.XmpToJcrMetadataBuilder 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 com.adobe.xmp.XMPMeta;
import com.adobe.xmp.XMPIterator;
import com.adobe.xmp.XMPException;
import com.adobe.xmp.XMPMetaFactory;
import com.adobe.xmp.XMPDateTime;
import com.adobe.xmp.XMPDateTimeFactory;
import com.adobe.xmp.properties.XMPPropertyInfo;
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 javax.jcr.Node;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.NodeIterator;
import javax.jcr.Property;
import javax.jcr.PropertyType;
import javax.jcr.NamespaceException;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.commons.io.IOUtils;
import org.apache.jackrabbit.util.Text;

import java.util.Set;
import java.util.Calendar;
import java.util.Date;
import java.io.ByteArrayInputStream;
import java.io.IOException;

/**
 * The XmpToJcrMetadataBuilder class ...
 * not in use
 */
public class XmpToJcrMetadataBuilder {

    /**
     * the default logger
     */
    private static final Logger log = LoggerFactory.getLogger(XmpToJcrMetadataBuilder.class);

    public static final String VALUE_NODE_NAME = "value";
    public static final String PN_NAMESPACE = "namespace";
    public static final String PN_VALUE = "value";
    public static final String NT_XMP_PROPERTY = "xmp:Property";
    public static final String NT_XMP_STRUCT = "xmp:Struct";
    public static final String NT_XMP_SIMPLE = "xmp:Simple";
    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";

    public void storeXmp(Node metadataRoot, XMPMeta meta) throws XMPException, RepositoryException {
        XMPIterator itr = meta.iterator();

        String rootPath = metadataRoot.getPath();

        String parent = null;

        while (itr.hasNext()) {
            XMPPropertyInfo prop = (XMPPropertyInfo) itr.next();

            if (!prop.getOptions().isSchemaNode()) {
                parent = (parent != null && prop.getPath().startsWith(parent) ? parent : null);
                if (prop.getOptions().isQualifier() || prop.getOptions().isSimple()) {
                    String p = rootPath + getPath(prop, parent);
                    // check namespace TODO: correct here?
                    checkNamespace(prop, metadataRoot);

                    Node node = getOrCreateNode(metadataRoot.getSession(), p, NT_XMP_PROPERTY);
                    node.setProperty(PN_NAMESPACE, prop.getNamespace());
                    log.debug("PATH: " + node.getPath() + " (" + NT_XMP_PROPERTY + ") namespace:" + prop.getNamespace() );
                    p = p + "/" + VALUE_NODE_NAME;
                    Node vnode = getOrCreateNode(metadataRoot.getSession(), p, NT_XMP_SIMPLE);
                    setProperty(vnode, prop);
                    log.debug("PATH: " + vnode.getPath() + " (" + NT_XMP_SIMPLE + ") value:" + prop.getValue());
                } else if (prop.getOptions().isArray()) {
                    parent = prop.getPath();
                    checkNamespace(prop, metadataRoot);
                    String p = rootPath + "/" + prop.getPath();
                    Node node = getOrCreateNode(metadataRoot.getSession(), p, NT_XMP_PROPERTY);
                    log.debug("PATH: " + node.getPath() + " (" + NT_XMP_PROPERTY + ")");
                    String name = NT_RDF_BAG;
                    if (prop.getOptions().isArrayOrdered()) {
                        name = NT_RDF_SEQ;
                    } else if (prop.getOptions().isArrayAlternate()) {
                        name = NT_RDF_ALT;
                    }
                    p = rootPath + "/" + prop.getPath() + "/" + VALUE_NODE_NAME;
                    Node anode = getOrCreateNode(metadataRoot.getSession(), p, name);
                    log.debug("PATH: " + anode.getPath() + name);
                } else if (prop.getOptions().isStruct()) {
                    parent = prop.getPath();
                    checkNamespace(prop, metadataRoot);
                    String p = rootPath + "/" + prop.getPath();
                    Node node = getOrCreateNode(metadataRoot.getSession(), p, NT_XMP_PROPERTY);
                    log.debug("PATH: " + node.getPath() + " (" + NT_XMP_PROPERTY + ")");
                    p = rootPath + "/" + prop.getPath() + "/" + VALUE_NODE_NAME;
                    Node snode = getOrCreateNode(metadataRoot.getSession(), p, NT_XMP_STRUCT);
                    log.debug("PATH: " + snode.getPath() + " (" + NT_XMP_STRUCT + ")");
                }
            }
        }
        metadataRoot.getSession().save();
    }

    public XMPMeta getXmpFromJcr(Node metadataRoot) throws RepositoryException, XMPException {
        XMPMeta meta = XMPMetaFactory.create();

        NodeIterator itr = metadataRoot.getNodes();
        while (itr.hasNext()) {
            Node n = itr.nextNode();
            if (n.isNodeType(NT_XMP_PROPERTY)) {
                Node value = n.getNode(VALUE_NODE_NAME);
                String namespace;
                if (n.hasProperty(PN_NAMESPACE)) {
                    namespace = n.getProperty(PN_NAMESPACE).getString();
                } else {
                    // try to get namespace...
                    String nsPrefix = n.getName().substring(0, n.getName().indexOf(":"));
                    namespace = XMPMetaFactory.getSchemaRegistry().getNamespaceURI(nsPrefix);
                }
                Object val = getValue(value);
                try {
                    String key = n.getName();
                    String nsPrefix = key.substring(0, key.indexOf(":"));
                    if (XMPMetaFactory.getSchemaRegistry().getNamespacePrefix(namespace) == null) {
                        // register ns
                        XMPMetaFactory.getSchemaRegistry().registerNamespace(namespace, nsPrefix);
                    }
                    meta.setProperty(namespace, key, val);
                } catch (XMPException xmpe) {
                    log.warn("Cannot set xmp property: " + xmpe.getMessage());
                }
                // todo qualifier

            }
        }
        return meta;
    }

    public void storeAsXmp(ExtractedMetadata metadata, Node metadataRoot) throws XMPException, RepositoryException {
        XMPMeta meta = XMPMetaFactory.create();
        Set keys = metadata.getMetaDataProperties().keySet();

        for (String key: keys) {
            if (XmpMappings.defaultSimpleXmpMappings.containsKey(key)) {
                String xmpKeys[] = getXmpKeys(XmpMappings.defaultSimpleXmpMappings.get(key));
                for (String xmpKey: xmpKeys) {
                    try {
                        setXmpProperty(meta, xmpKey, metadata.getMetaDataProperties().get(key));
                    } catch (XMPException e) {
                        log.debug("Cannot create xmp property: " + e.getMessage());
                    }
                }
            } else if (XmpMappings.defaultBagXmpMappings.containsKey(key)) {

            } else if (XmpMappings.defaultSeqXmpMappings.containsKey(key)) {

            } else {
                // fallback
                // use dam namespace
                if (key.indexOf(":") < 0) {
                    // no namespace at all
	                XMPMetaFactory.getSchemaRegistry().registerNamespace("http://www.day.com/dam/1.0", "dam");
                    try {
                        meta.setProperty("http://www.day.com/dam/1.0", "dam:" + key.replace(" ", "").trim(), metadata.getMetaDataProperties().get(key));
                    } catch (XMPException e) {
                        log.warn("Cannot set xmp property:" + e.getMessage());
                    }
                } else {
                    try {
                        // already prefixed key
                        // check if namespace exists
                        String nsPrefix = key.substring(0, key.indexOf(":"));
                        String nsUri = metadataRoot.getSession().getNamespaceURI(nsPrefix);  // TODO: better taken from ws
                        if (XMPMetaFactory.getSchemaRegistry().getNamespacePrefix(nsUri) == null) {
                            // register ns
                            XMPMetaFactory.getSchemaRegistry().registerNamespace(nsUri, nsPrefix);
                        }

                        setXmpProperty(meta, key, metadata.getMetaDataProperties().get(key));
                    } catch (XMPException e) {
                        log.debug("Cannot create xmp property: " + e.getMessage());
                    }
                }
            }
        }
        storeXmp(metadataRoot, meta);
    }

    private void setXmpProperty(XMPMeta meta, String xmpKey, Object value) throws XMPException {
        if (value instanceof Boolean) {
            meta.setPropertyBoolean(getNamespace(xmpKey), xmpKey, (Boolean) value);
        } else if (value instanceof Calendar) {
            meta.setPropertyCalendar(getNamespace(xmpKey), xmpKey, (Calendar) value);
        } else if (value instanceof Date) {
            Calendar cal = Calendar.getInstance();
            cal.setTime((Date) value);
            meta.setPropertyDate(getNamespace(xmpKey), xmpKey, XMPDateTimeFactory.createFromCalendar(cal));
        } else if (value instanceof Double) {
            meta.setPropertyDouble(getNamespace(xmpKey), xmpKey, (Double) value);
        } else if (value instanceof Integer) {
            meta.setPropertyInteger(getNamespace(xmpKey), xmpKey, (Integer) value);
        } else if (value instanceof Long) {
            meta.setPropertyLong(getNamespace(xmpKey), xmpKey, (Long) value);
        } else {
            meta.setProperty(getNamespace(xmpKey), xmpKey, value);
        }
    }

    private String[] getXmpKeys(String keyString) {
        if (keyString.indexOf(",") > 0) {
            return keyString.split(",");
        } else {
            return new String[] {keyString};
        }
    }

    private String getNamespace(String xmpKey) {
        if (xmpKey.indexOf(":") > 0) {
            String nsPrefix = xmpKey.substring(0, xmpKey.indexOf(":"));
            return XMPMetaFactory.getSchemaRegistry().getNamespaceURI(nsPrefix);
        }
        return null;
    }

    private Node getOrCreateNode(Session session, String path, String nodetype) throws RepositoryException {
        if (session.itemExists(path)) {
            return (Node) session.getItem(path);
        } else {
            return session.getRootNode().addNode(path.substring(1), nodetype);
        }
    }

    private static String getPath(XMPPropertyInfo prop, String parent) {
        if (parent != null) {
            String postPath = prop.getPath().substring(parent.length());
            postPath = (postPath.startsWith("/")) ? postPath.substring(1) : postPath;
            if (postPath.indexOf(":") > 0) {
                String name[] = postPath.split(":");
                if (XMPMetaFactory.getSchemaRegistry().getNamespaceURI(name[0]) != null &&
                        XMPMetaFactory.getSchemaRegistry().getNamespaceURI(name[0]).equals(prop.getNamespace())) {
                    postPath = name[0] + ":" + Text.escapeIllegalJcrChars(name[1]);
                } else {
                    postPath = Text.escapeIllegalJcrChars(postPath);
                }
            } else {
                postPath = Text.escapeIllegalJcrChars(postPath);
            }
            String path = parent + "/" + VALUE_NODE_NAME + (postPath.startsWith("/") ? "" : "/") + postPath;
            return path.startsWith("/") ? path : "/" + path;
        } else {
            return "/" + prop.getPath();
        }
    }

    private void setProperty(Node node, XMPPropertyInfo prop) {
        try {
            Object val = prop.getOriValue();
            if (node.hasProperty(PN_VALUE)) {
                // existing string values that have to be converted into the correct type
                int type = node.getProperty(PN_VALUE).getType();
                switch (type) {
                    case PropertyType.DATE:
                        Object v = checkForDate(val);
                        if (v instanceof Date) {
                            Calendar cal = Calendar.getInstance();
                            cal.setTime((Date)v);
                            node.setProperty(PN_VALUE, cal);
                        }
                        break;
                    case PropertyType.BOOLEAN:
                        node.setProperty(PN_VALUE, Boolean.valueOf((String) val));
                        break;
                    case PropertyType.DOUBLE:
                        node.setProperty(PN_VALUE, Double.valueOf((String) val));
                        break;
                    case PropertyType.LONG:
                        node.setProperty(PN_VALUE, Long.valueOf((String) val));
                        break;
                    default:
                        node.setProperty(PN_VALUE, (String) val);
                }
            } else {
                // new value
                val = checkForDate(val);
                if (val instanceof Boolean) {
                    node.setProperty(PN_VALUE, (Boolean) val);
                } else if (val instanceof Integer) {
                    node.setProperty(PN_VALUE, (Integer) val);
                } else if (val instanceof Long) {
                    node.setProperty(PN_VALUE, (Long) val);
                } else if (val instanceof Double) {
                    node.setProperty(PN_VALUE, (Double) val);
                } else if (val instanceof XMPDateTime) {
                    node.setProperty(PN_VALUE, ((XMPDateTime) val).getCalendar());
                } else if (val instanceof byte[]) {
                    node.setProperty(PN_VALUE,
                            node.getSession().getValueFactory().createBinary(new ByteArrayInputStream((byte[]) val)));
                } else if (val instanceof Date) {
                    Calendar cal = Calendar.getInstance();
                    cal.setTime((Date) val);
                    node.setProperty(PN_VALUE, cal);
                }else {
                    node.setProperty(PN_VALUE, (String) prop.getValue());
                }
            }
        } catch (Throwable re) {
            log.warn("Cannot set xmp property (" + prop.getPath() + "): " + re.getMessage());
        }
    }

    private Object checkForDate(Object val) {
        if (val instanceof String) {
            Date date = DateParser.parseDate((String) val);
            return (date == null) ? val : date;
        } else {
            return val;
        }
    }

    private Object getValue(Node value) {
        Object val = null;
        try {
            Property prop = value.getProperty(PN_VALUE);
            switch (prop.getType()) {
                case PropertyType.BINARY:
                    val = IOUtils.toByteArray(prop.getBinary().getStream());
                    break;
                case PropertyType.DATE:
                    val = XMPDateTimeFactory.createFromCalendar(prop.getDate());
                    break;
                case PropertyType.BOOLEAN:
                    val = prop.getBoolean();
                    break;
                case PropertyType.DOUBLE:
                    val = prop.getDouble();
                    break;
                case PropertyType.LONG:
                    val = prop.getLong();
                    break;
                default:
                    val = prop.getString();
            }
        } catch (RepositoryException re) {
            log.warn("Problem while getting xmp value from jcr property: "
                    + re.getMessage());
        } catch (IOException ioe) {
            log.warn("Problem while getting binary xmp value from jcr property: "
                    + ioe.getMessage());
        }
        return val;
    }

    private void checkNamespace(XMPPropertyInfo prop, Node metadataRoot) throws RepositoryException {
        try {
            String prefix = metadataRoot.getSession().getWorkspace().getNamespaceRegistry().getPrefix(prop.getNamespace());
        } catch (NamespaceException e) {
            String prefix = XMPMetaFactory.getSchemaRegistry().getNamespacePrefix(prop.getNamespace());
            prefix = prefix.substring(0, prefix.indexOf(":"));
            try {
                metadataRoot.getSession().getWorkspace().getNamespaceRegistry().registerNamespace(prefix, prop.getNamespace());
            } catch (RepositoryException re) {}
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy