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

com.adobe.acs.commons.workflow.process.impl.SyncSmartTagsToXmpMetadataNodeProcess Maven / Gradle / Ivy

There is a newer version: 6.6.0
Show newest version
/*
 * #%L
 * ACS AEM Commons Bundle
 * %%
 * Copyright (C) 2015 Adobe
 * %%
 * 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.
 * #L%
 */

package com.adobe.acs.commons.workflow.process.impl;

import com.adobe.acs.commons.util.ParameterUtil;
import com.adobe.acs.commons.util.WorkflowHelper;
import com.adobe.acs.commons.workflow.WorkflowPackageManager;
import com.adobe.granite.workflow.WorkflowException;
import com.adobe.granite.workflow.WorkflowSession;
import com.adobe.granite.workflow.exec.WorkItem;
import com.adobe.granite.workflow.exec.WorkflowProcess;
import com.adobe.granite.workflow.metadata.MetaDataMap;
import com.day.cq.dam.api.Asset;
import com.day.cq.dam.api.DamConstants;
import com.day.cq.dam.commons.util.DamUtil;
import acscommons.com.google.common.collect.ImmutableMap;
import org.apache.commons.lang3.StringUtils;
import org.apache.jackrabbit.JcrConstants;
import org.apache.sling.api.resource.ModifiableValueMap;
import org.apache.sling.api.resource.PersistenceException;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ValueMap;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.jcr.RepositoryException;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;

@Component(
        service = WorkflowProcess.class,
        property = "process.label=Synchronize Smart Tags to XMP Metadata Node"
)
public class SyncSmartTagsToXmpMetadataNodeProcess implements WorkflowProcess {
    private static final Logger log = LoggerFactory.getLogger(SyncSmartTagsToXmpMetadataNodeProcess.class);

    // OOTB Predicate Tags nodes and properties
    private static final String NN_PREDICTED_TAGS = "predictedTags";
    private static final String PN_SMART_TAG_NAME = "name";
    private static final String PN_SMART_TAG_CONFIDENCE = "confidence";

    // Default nodes and properties to write into
    private static final String DEFAULT_NN_SEQUENCE = "dam:predictedTags";
    private static final String DEFAULT_PN_PREDICATED_TAGS_NAME = "dam:predictedTagName";
    private static final String DEFAULT_PN_PREDICATED_TAGS_CONFIDENCE = "dam:predictedTagConfidence";

    private static final Double DEFAULT_MINIMUM_CONFIDENCE = 0.0;

    @Reference
    private WorkflowHelper workflowHelper;

    @Reference
    private WorkflowPackageManager workflowPackageManager;

    @SuppressWarnings("squid:S1141")
    public final void execute(WorkItem workItem, WorkflowSession workflowSession, MetaDataMap metaDataMap)
            throws WorkflowException {

        log.debug("Invoked syncSmartTagsToMetadata Workflow Process step for payload [ {} ]", workItem.getWorkflowData().getPayload());

        final ProcessArgs processArgs = new ProcessArgs(metaDataMap);

        try (ResourceResolver resourceResolver = workflowHelper.getResourceResolver(workflowSession)) {
            final List payloads = workflowPackageManager.getPaths(resourceResolver,
                    (String) workItem.getWorkflowData().getPayload());

            final List assets = payloads.stream()
                    .map(payload -> DamUtil.resolveToAsset(resourceResolver.getResource(payload)))
                    .filter(Objects::nonNull)
                    .collect(Collectors.toList());

            assets.stream().forEach(asset -> {
                try {
                    syncSmartTagsToMetadata(asset, processArgs);
                } catch (PersistenceException e) {
                    log.error("Unable to sync Smart Tags to XMP Metadata structure for asset [ {} ]", asset.getPath(), e);
                }
            });

        } catch (RepositoryException e) {
            log.error("Could not find the payload", e);
            throw new WorkflowException("Could not find the payload");
        }
    }

    protected void syncSmartTagsToMetadata(final Asset asset, ProcessArgs processArgs) throws PersistenceException {
        final Resource assetResource = asset.adaptTo(Resource.class);
        final ResourceResolver resourceResolver = assetResource.getResourceResolver();

        final Resource metadataResource = assetResource.getChild(JcrConstants.JCR_CONTENT + "/" + DamConstants.METADATA_FOLDER);
        final Resource smartTagsResource = assetResource.getChild(JcrConstants.JCR_CONTENT + "/" + DamConstants.METADATA_FOLDER + "/" + NN_PREDICTED_TAGS);

        if (metadataResource.getChild(processArgs.getSequenceName()) != null) {
            // Remove existing, as they will be re-created
            resourceResolver.delete(metadataResource.getChild(processArgs.getSequenceName()));
        }

        final Resource parentResource = resourceResolver.create(metadataResource, processArgs.getSequenceName(),
                new ImmutableMap.Builder()
                        .put(JcrConstants.JCR_PRIMARYTYPE, JcrConstants.NT_UNSTRUCTURED)
                        .put("xmpArrayType", "rdf:Seq")
                        .put("xmpNodeType", "xmpArray")
                        .put("xmpArraySize", 0L)
                        .build());

        final AtomicInteger count = new AtomicInteger(0);
        if (smartTagsResource != null) {
            StreamSupport.stream(smartTagsResource.getChildren().spliterator(), false)
                    .map(Resource::getValueMap)
                    .filter(properties -> properties.get(PN_SMART_TAG_CONFIDENCE, 0D) >= processArgs.getMinimumConfidence())
                    .filter(properties -> StringUtils.isNotBlank(properties.get(PN_SMART_TAG_NAME, String.class)))
                    .forEach(properties -> {
                        createSequenceItemResource(asset, processArgs, resourceResolver, parentResource, count, properties);
                    });
        }

        parentResource.adaptTo(ModifiableValueMap.class).put("xmpArraySize", count.get());

        log.info("Synced [ {} ] Smart Tags to Asset XMP Metadata structure: [ {} ] ",
                count.get(),
                asset.getPath() + "/jcr:content/metadata/" + processArgs.getSequenceName());
    }

    private void createSequenceItemResource(Asset asset, ProcessArgs processArgs, ResourceResolver resourceResolver,
                                            Resource parentResource, AtomicInteger count, ValueMap properties) {
        try {
            resourceResolver.create(parentResource, String.valueOf(count.incrementAndGet()),
                    new ImmutableMap.Builder()
                            .put(JcrConstants.JCR_PRIMARYTYPE, JcrConstants.NT_UNSTRUCTURED)
                            .put("xmpNodeType", "xmpStruct")
                            .put(processArgs.getNameProperty(), properties.get(PN_SMART_TAG_NAME, String.class))
                            .put(processArgs.getConfidenceProperty(), properties.get(PN_SMART_TAG_CONFIDENCE, Double.class))
                            .build());
        } catch (PersistenceException e) {
            log.error("Unable to sync Smart Tag [ {} ] to XMP Metadata structure for asset [ {} ]",
                    properties.get("name", String.class), asset.getPath(), e);
        }
    }

    protected static class ProcessArgs {
        private static final String ARG_SEQUENCE_NAME = "sequenceName";
        private static final String ARG_NAME_PROPERTY = "nameProperty";
        private static final String ARG_CONFIDENCE_PROPERTY = "confidenceProperty";
        private static final String ARG_MINIMUM_CONFIDENCE = "minimumConfidence";

        private String sequenceName;
        private String nameProperty;
        private String confidenceProperty;
        private Double minimumConfidence;

        public ProcessArgs(MetaDataMap map) {

            String[] lines = org.apache.commons.lang.StringUtils.split(map.get(WorkflowHelper.PROCESS_ARGS, ""), System.lineSeparator());
            final Map data = ParameterUtil.toMap(lines, "=");

            sequenceName = StringUtils.defaultIfEmpty(data.get(ARG_SEQUENCE_NAME), DEFAULT_NN_SEQUENCE);
            nameProperty = StringUtils.defaultIfEmpty(data.get(ARG_NAME_PROPERTY), DEFAULT_PN_PREDICATED_TAGS_NAME);
            confidenceProperty = StringUtils.defaultIfEmpty(data.get(ARG_CONFIDENCE_PROPERTY), DEFAULT_PN_PREDICATED_TAGS_CONFIDENCE);

            try {
                String tmp = data.get(ARG_MINIMUM_CONFIDENCE);
                if (tmp == null) {
                    minimumConfidence = DEFAULT_MINIMUM_CONFIDENCE;
                } else {
                    minimumConfidence = Double.parseDouble(tmp);
                }
            } catch (NumberFormatException | NullPointerException e) {
                log.warn("Could not parse Double from [ {} ] defaulting to [ {} ]", data.get(ARG_MINIMUM_CONFIDENCE), DEFAULT_MINIMUM_CONFIDENCE);
                minimumConfidence = DEFAULT_MINIMUM_CONFIDENCE;
            }

            if (minimumConfidence < 0 || minimumConfidence > 1) {
                log.warn("Minimum confidence score [ {} ] outside of range [ 0 to 1 ] defaulting to [ {} ]", data.get(ARG_MINIMUM_CONFIDENCE), DEFAULT_MINIMUM_CONFIDENCE);
                minimumConfidence = DEFAULT_MINIMUM_CONFIDENCE;
            }
        }

        public double getMinimumConfidence() {
            return minimumConfidence;
        }

        public String getSequenceName() {
            return sequenceName;
        }

        public String getNameProperty() {
            return nameProperty;
        }

        public String getConfidenceProperty() {
            return confidenceProperty;
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy