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

com.day.cq.dam.commons.util.AssetReferenceRecursiveSearch Maven / Gradle / Ivy

package com.day.cq.dam.commons.util;

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.collection.SmartCollection;
import com.day.cq.dam.api.s7dam.constants.S7damConstants;
import org.apache.sling.api.resource.ValueMap;
import org.apache.sling.resource.collection.ResourceCollection;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ResourceUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.jcr.*;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * The AssetReferenceRecursiveSearch searches in a specified path for referenced assets recursively.
* If it encounters a SmartCollection, ResourceCollection or a S7Set it iterates * over its children and looks for the referenced assets within their children and their children's children and so on. */ public class AssetReferenceRecursiveSearch { /** * The logging facility. */ private static final Logger log = LoggerFactory.getLogger(AssetReferenceRecursiveSearch.class); private final Node node; private final String searchPath; private final ResourceResolver resolver; /** * Maintain a list of recursion traversal history to prevent cyclic references and infinite recursion */ private List pathsTraversed = new ArrayList(); /** * List of nodes which contain phantom references. Better to skip them. */ private final List ignoredNodes = new ArrayList(){{ this.add(DamConstants.THUMBNAIL_NODE); //ignore any references to assets in thumbnail. traverse list of children instead this.add(DamConstants.RENDITIONS_FOLDER); }}; /** * The constructor. * * @param node node to start search for references * @param searchPath search for assets starting with searchPath * @param resolver resource resolver */ public AssetReferenceRecursiveSearch(Node node, String searchPath, ResourceResolver resolver) { this.node = node; this.searchPath = searchPath; this.resolver = resolver; } /** * Search all asset references * * @return map containing all asset refs */ public Map search() { Map assetRefs = new HashMap(); Pattern pattern = getPattern(searchPath); search(node, assetRefs, pattern); return assetRefs; } /** * Search method with recursive functionality. * Searches recursively within items which are DAM asset containers. * * @param node node to start search for references * @param resourceRefs map to store the references found * @param pattern pattern to look for */ protected void search(Node node, Map resourceRefs, Pattern pattern) { try { if(node.hasProperty("sling:resource")) { Resource referencedResource = resolver.resolve(node.getProperty("sling:resource").getString()); if(referencedResource != null && !ResourceUtil.isNonExistingResource(referencedResource)) { if(S7SetHelper.isS7Set(referencedResource) || S7SetHelper.isS7Video(referencedResource) || isS7Preset(referencedResource) || referencedResource.adaptTo(ResourceCollection.class) != null || referencedResource.adaptTo(SmartCollection.class) != null || referencedResource.adaptTo(Node.class).isNodeType(JcrConstants.NT_FOLDER)) { if(!pathsTraversed.contains(referencedResource.getPath())) { pathsTraversed.add(referencedResource.getPath()); search(referencedResource.adaptTo(Node.class), resourceRefs, pattern); } } } } if(!ignoredNodes.contains(node.getName()) && !node.getPath().equals(this.node.getPath())) { locateMatch(pattern, node.getPath(), true, resourceRefs); searchPresets(node.getPath(), resourceRefs, true); } if(!ignoredNodes.contains(node.getName())) { searchInProps(node, resourceRefs, pattern); searchInChildren(node, resourceRefs, pattern); } } catch (RepositoryException re) { log.warn("Error occurred while reading properties", re); } } /** * ViewerPreset is a special type that is not an Asset and is not in the /content/dam area, * but it is still associated with a viewer or asset, and needs to be included as a reference. * * @param resource The actual resource referenced by the reference node. * @return True if the resource is a ViewerPreset type. */ private boolean isS7Preset(Resource resource) { Resource contentResource = resource.getChild(JcrConstants.JCR_CONTENT); if (contentResource != null) { ValueMap vm = contentResource.adaptTo(ValueMap.class); String s7Type = vm.get(S7damConstants.PN_S7_TYPE, ""); if (S7damConstants.S7_VIEWER_PRESET.equals(s7Type)) { return true; } } return false; } /** * Add presets to related resource list. These may exist outside DAM asset containers. * * @param value Path to inspect. * @param resourceRefs Found resources. * @param decode Decode before searching. * @throws RepositoryException */ private void searchPresets(String value, Map resourceRefs, boolean decode) throws RepositoryException { Set refs = new HashSet(); if (value.startsWith("/")) { // looks like just a single path refs.add(decode? tryDecode(value) : value); } else { // ref might be somewhere in the string getRefs(value, refs, decode); } for (String ref : refs) { Resource resource = resolver.getResource(ref); if (resource != null && !ResourceUtil.isNonExistingResource(resource)) { if (isS7Preset(resource)) { resourceRefs.put(ref, resource); } } } } protected void searchInProps(Node node, Map resourceRefs, Pattern pattern) { try { for (PropertyIterator pIter = node.getProperties(); pIter.hasNext();) { Property p = pIter.nextProperty(); // only check string and name properties if (p.getType() == PropertyType.STRING || p.getType() == PropertyType.NAME) { boolean decode = p.getType() == PropertyType.STRING; if (p.getDefinition().isMultiple()) { for (Value v : p.getValues()) { locateMatch(pattern, v.getString(), decode, resourceRefs); } } else { locateMatch(pattern, p.getString(), decode, resourceRefs); } } } } catch (RepositoryException re) { log.warn("Error occured while reading properties"); } } protected void searchInChildren(Node node, Map resourceRefs, Pattern pattern) { try { for (NodeIterator nItr = node.getNodes(); nItr.hasNext();) { Node n = nItr.nextNode(); search(n, resourceRefs, pattern); } } catch (RepositoryException re) { log.warn("Error occured while reading nodes"); } } private void locateMatch(Pattern pattern, String value, boolean decode, Map resourceRefs) throws RepositoryException { Matcher matcher = pattern.matcher(value); if (matcher.find()) { Set refs = new HashSet(); if (value.startsWith("/")) { // looks like just a single path refs.add(decode? tryDecode(value) : value); } else { // ref might be somewhere in the string getRefs(value, refs, decode); } for (String ref : refs) { Resource resource = resolver.getResource(ref); if (resource != null && !ResourceUtil.isNonExistingResource(resource)) { if (resource.adaptTo(Asset.class) != null || S7SetHelper.isS7Set(resource) || S7SetHelper.isS7Video(resource) || isS7Preset(resource) || resource.adaptTo(ResourceCollection.class) != null || resource.adaptTo(Node.class).isNodeType(JcrConstants.NT_FOLDER)) { resourceRefs.put(ref, resolver.getResource(ref)); } } } } } private String tryDecode(String url) { try { return new URI(url).getPath(); } catch(URISyntaxException e) { return url; } } /** * Search for asset paths in text * * @param value text as string * @param refs set to which found asset paths are added */ private void getRefs(String value, Set refs, boolean decode) { int startPos = value.indexOf(searchPath, 1); while (startPos != -1) { char charBeforeStartPos = value.charAt(startPos - 1); if (charBeforeStartPos == '\'' || charBeforeStartPos == '"') { int endPos = value.indexOf(charBeforeStartPos, startPos); if (endPos > startPos) { String ref = value.substring(startPos, endPos); refs.add(decode? tryDecode(ref) : ref); startPos = endPos; } } startPos = value.indexOf(searchPath, startPos + 1); } } /** * Returns the replacement pattern for the rewrite method. * * @param path source path * @return replacement pattern */ protected Pattern getPattern(String path) { return Pattern.compile("(.[\"']|^|^[\"'])(" + path + ")\\b"); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy