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

com.day.cq.dam.core.process.ProcessingProfileApplier Maven / Gradle / Ivy

/*************************************************************************
 *
 * ADOBE CONFIDENTIAL
 * __________________
 *
 *  Copyright 2014 Adobe Systems Incorporated
 *  All Rights Reserved.
 *
 * NOTICE:  All information contained herein is, and remains
 * the property of Adobe Systems Incorporated and its suppliers,
 * if any.  The intellectual and technical concepts contained
 * herein are proprietary to Adobe Systems Incorporated and its
 * suppliers and are protected by trade secret or copyright law.
 * Dissemination of this information or reproduction of this material
 * is strictly forbidden unless prior written permission is obtained
 * from Adobe Systems Incorporated.
 **************************************************************************/

package com.day.cq.dam.core.process;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.PathNotFoundException;
import javax.jcr.PropertyIterator;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.Value;

import org.apache.jackrabbit.JcrConstants;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceUtil;
import org.apache.sling.tenant.Tenant;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.day.cq.dam.api.Asset;
import com.day.cq.dam.api.DamConstants;
import com.adobe.granite.confmgr.Conf;
import com.day.cq.dam.commons.util.DamUtil;
import com.day.cq.workflow.metadata.MetaDataMap;
import com.day.cq.dam.commons.util.DamConfigurationConstants;

/**
 * The ProcessingProfileApplier is used in multiple workflow steps. At the time of
 * writing this comment it is used in Metadata Processor step and Apply Processing Profile step.
 *
 */
public class ProcessingProfileApplier {

    /**
     * Logger instance for this class.
     */
    private static final Logger log = LoggerFactory.getLogger(ProcessingProfileApplier.class);

    private static final String JCR_CONTENT_METADATA = JcrConstants.JCR_CONTENT + "/" + DamConstants.METADATA_FOLDER;

    private static final String JCR_CONTENT_TEMPLATE_METADATA = JcrConstants.JCR_CONTENT + "/template-metadata";

    /**
     * Applies processing profile on the given asset.
     * @param session JCR Session.
     * @param asset Asset on which processing profile is to be applied.
     * @throws RepositoryException if some repository error occurs during application.
     */
    public void applyProcessingProfile(Session session, final Asset asset) throws RepositoryException {
        String metadataProfilePath;
        Node metadataProfileNode = DamUtil.getApplicableProfile(asset, DamConstants.METADATA_PROFILE, session);
        Node folderMetadataSchemaNode = DamUtil.getApplicableProfile(asset, "folderMetadataSchema", session);

        if (metadataProfileNode != null) {
            metadataProfilePath = metadataProfileNode.getPath();
            if (isMetadataProfileValid(metadataProfilePath, asset)) {
                applyMetadataProfile(session, asset, metadataProfilePath);
            }
        } else if(folderMetadataSchemaNode == null){
            // check for legacy metadata template
            // NPR-19716: now also ignores this metadata copy process if a folder metadata
            //            schema is set on any of the parent folders
            Node folderNode = null;
            Node assetNode = asset.adaptTo(Node.class);
            Node iterNode = assetNode;
            while (!iterNode.getPath().equals("/content")) {
                iterNode = iterNode.getParent();
                if (!iterNode.getPrimaryNodeType().getName().equals(DamConstants.NT_DAM_ASSET)
                        && iterNode.hasNode(JCR_CONTENT_TEMPLATE_METADATA)) {
                    folderNode = iterNode;
                    break;
                }
            }
            if (null != folderNode) {
                if (!assetNode.hasNode(JCR_CONTENT_METADATA)) {
                    createAssetMetadataNode(assetNode);
                }
                copyProperties(folderNode.getNode(JCR_CONTENT_TEMPLATE_METADATA), assetNode.getNode(JCR_CONTENT_METADATA));
            }
        }
    	
    }

	private boolean isMetadataProfileValid(String metadataProfilePath, Asset asset) {
	    String normalizedPath = ResourceUtil.normalize(metadataProfilePath);
	    Resource assetRes = asset.adaptTo(Resource.class);
	    Tenant tenant = assetRes.adaptTo(Tenant.class);
	    if(null != tenant){
	        if(null == normalizedPath || !normalizedPath.startsWith(assetRes.adaptTo(Conf.class).getItem(DamConfigurationConstants.ADMIN_UI_EXTENSION_CONF_RELPATH).
                    get(DamConfigurationConstants.METADATA_PROFILE_HOME, DamConfigurationConstants.DEFAULT_METADATA_PROFILE_HOME))) {
	            return false;
	        }
	    }
	    return true;
    }

    private Node createAssetMetadataNode(Node assetNode) throws RepositoryException {
        Node _jcr_content;
        if (assetNode.hasNode(JcrConstants.JCR_CONTENT)) {
            _jcr_content = assetNode.getNode(JcrConstants.JCR_CONTENT);
        } else {
            _jcr_content = assetNode.addNode(JcrConstants.JCR_CONTENT);
        }

        return _jcr_content.addNode(DamConstants.METADATA_FOLDER);
    }

    private void applyMetadataProfile(final Session session, final Asset asset, final String path) throws RepositoryException {
        Node metadataProfileNode = session.getNode(path);
        Node assetNode = asset.adaptTo(Node.class);
        Node assetMetadataNode = assetNode.getNode(JCR_CONTENT_METADATA);

        if (null == metadataProfileNode) {
            return;
        }

        if (null == assetMetadataNode) {
            assetMetadataNode = createAssetMetadataNode(assetNode);
        }

        copyMetadataProfileValues(metadataProfileNode, assetNode);
        // assetNode.getSession().save();   // Saving at the end of execute method. 
    }
    
    private void copyMetadataProfileValues(Node metadataProfileNode, Node assetNode) throws PathNotFoundException, RepositoryException {

        List formItems = getFormItems(metadataProfileNode);

        for (Node item : formItems) {
            if (!item.hasProperty("name")) {
                continue;
            }
            javax.jcr.Property property = item.getProperty("name");
            String mapsTo = property.getString();
            if (mapsTo == null || "".equals(mapsTo)) {
                continue;
            }
            
            if (!item.hasProperty("value")) {
                continue;
            }
            
            javax.jcr.Property value = item.getProperty("value");
            
            mapsTo = mapsTo.substring(2);

            String relPathDataNode = mapsTo.substring(0, mapsTo.lastIndexOf("/") + 1);
            String propertyName = mapsTo.substring(mapsTo.lastIndexOf("/") + 1);
            log.debug("Metadata profile property name: " + propertyName);
            Node dataNode = assetNode.getNode(relPathDataNode);

            if (dataNode.hasProperty(propertyName)) {
                javax.jcr.Property prop = dataNode.getProperty(propertyName);
                if (value.isMultiple() && prop.isMultiple()) {
                    Value[] vals = prop.getValues();
                    List updatedVals = new ArrayList();
                    updatedVals.addAll(Arrays.asList(vals));
                    for (Value val : value.getValues()) {
                        if (!updatedVals.contains(val)) updatedVals.add(val);
                    }
                    dataNode.setProperty(propertyName, updatedVals.toArray(new Value[updatedVals.size()]), prop.getType());

                } else if (!value.isMultiple() && prop.isMultiple()) {
                    Value[] vals = prop.getValues();
                    List updatedVals = new ArrayList();
                    updatedVals.addAll(Arrays.asList(vals));
                    if (!updatedVals.contains(value.getValue())) updatedVals.add(value.getValue());
                    dataNode.setProperty(propertyName, updatedVals.toArray(new Value[updatedVals.size()]), prop.getType());
                } else if (value.isMultiple() && !prop.isMultiple()) {
                    Value val = prop.getValue();
                    List updatedVals = new ArrayList();
                    updatedVals.addAll(Arrays.asList(value.getValues()));
                    if (!updatedVals.contains(val)) {
                        updatedVals.add(val);
                    }
                    dataNode.setProperty(propertyName, (Value) null);
                    dataNode.setProperty(propertyName, (Value[]) updatedVals.toArray(new Value[updatedVals.size()]), value.getType());
                } else if (!value.isMultiple() && !prop.isMultiple()) {
                    dataNode.setProperty(propertyName, value.getValue());
                }

            } else {
                if (!value.isMultiple()) {
                    dataNode.setProperty(propertyName, value.getValue());
                } else {
                    dataNode.setProperty(propertyName, value.getValues(), value.getType());
                }
            }
        }
    }
    
    private void copyProperties(Node metadataProfileNode, Node assetMetadataNode) throws RepositoryException {

        PropertyIterator dpi = metadataProfileNode.getProperties();
        while (dpi.hasNext()) {
            javax.jcr.Property p = dpi.nextProperty();
            if (!p.getName().startsWith("jcr:")) {
                log.debug("Metadata profile property name: " + p.getName());
                /*
                 * There are cases where we have single valued form items but the metadata information
                 * extracted from the asset have multi valued attribute for the same, so in a case of
                 * multivalued default metadata value for the asset, we append metadata values to list of
                 * default values present in the asset.
                 */
                if (assetMetadataNode.hasProperty(p.getName())) {
                    javax.jcr.Property prop = assetMetadataNode.getProperty(p.getName());
                    Value[] vals;
                    List updatedVals;

                    if (p.isMultiple() && prop.isMultiple()) {
                        vals = prop.getValues();
                        updatedVals = new ArrayList();
                        updatedVals.addAll(Arrays.asList(vals));
                        for (Value val : p.getValues()) {
                            if (!updatedVals.contains(val))
                                updatedVals.add(val);
                        }
                        assetMetadataNode.setProperty(
                                prop.getName(),
                                updatedVals.toArray(new Value[updatedVals.size()]),
                                prop.getType());

                    } else if (!p.isMultiple()
                            && prop.isMultiple()) {
                        vals = prop.getValues();
                        updatedVals = new ArrayList();
                        updatedVals.addAll(Arrays.asList(vals));
                        if (!updatedVals.contains(p.getValue()))
                            updatedVals.add(p.getValue());
                        assetMetadataNode.setProperty(
                                prop.getName(),
                                updatedVals.toArray(new Value[updatedVals.size()]),
                                prop.getType());
                    } else if (!p.isMultiple() && !prop.isMultiple()) {
                        assetMetadataNode.setProperty(
                                p.getName(), p.getValue());
                    }
                } else {
                    if (!p.isMultiple()) {
                        assetMetadataNode.setProperty(
                                p.getName(), p.getValue());
                    } else {
                        assetMetadataNode.setProperty(
                                p.getName(),
                                p.getValues(),
                                p.getType());
                    }
                }
            }
        }
    }
    
    // TODO Remove duplicate code in metadatainstance.jsp
    private List getFormItems(Node metadataProfileNode) throws PathNotFoundException, RepositoryException {
        List formItems = new ArrayList();
        NodeIterator iter = metadataProfileNode.getNode("items/tabs/items").getNodes();

        while (iter.hasNext()) {
            Node tab = iter.nextNode();
            if (tab.hasNode("items")) {
                NodeIterator clmns = tab.getNode("items").getNodes();
                while (clmns.hasNext()) {
                    Node clm = clmns.nextNode();
                    if (clm.hasNode("items")) {
                        NodeIterator fields = clm.getNode("items").getNodes();
                        while (fields.hasNext()) {
                            formItems.add(fields.nextNode());
                        }
                    }
                }
            }
        }
        return formItems;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy