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

com.day.cq.dam.commons.util.GQLConverter 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.commons.util;


import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.jcr.RepositoryException;

import com.day.cq.commons.jcr.JcrUtil;
import com.day.cq.search.Predicate;
import com.day.cq.search.PredicateConverter;
import com.day.cq.search.PredicateGroup;
import com.day.cq.search.eval.FulltextPredicateEvaluator;
import com.day.cq.search.eval.JcrPropertyPredicateEvaluator;

import com.day.cq.search.eval.RangePropertyPredicateEvaluator;
import com.day.cq.tagging.impl.search.TagSearchPredicateEvaluator;
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.apache.sling.tenant.Tenant;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


public class GQLConverter {

    private static final String OR_OP               = " OR ";
    private static final String TAGS_PROP           = "tags";
    private static final String DATERANGE_PRED      = "daterange";
    private static final String RANGEPROP_PRED      = "rangeproperty";
    private static final String JCR_PROPERTIES_PATH = "/var/dam/content/formitems";

    private static final Logger log = LoggerFactory.getLogger(GQLConverter.class);

    /**
     * Parse and converts GQL statement from fulltext in conditions to QueryBuilder PredicateGroup.
     *
     * @param conditions the map containing initial conditions and fulltext to be processed
     * @param resolver   to resolve node containing gql to jcr properties mapping
     * @return PredicateGroup containing conditions merged with new conditions formed from fulltext
     * @throws RepositoryException
     */
    public static PredicateGroup buildQuery(Map conditions, ResourceResolver resolver) throws RepositoryException {
        PredicateGroup rootGrp = PredicateConverter.createPredicates(conditions);
        List gqlExpressions = getValidGQLStatements(rootGrp);
        if (!gqlExpressions.isEmpty()) {
            for (String expression : gqlExpressions) {
                PredicateGroup gqlPredicateGroup = PredicateConverter.createPredicatesFromGQL(expression.replace("*", "%"));
                transformPredicates(gqlPredicateGroup, getJcrPropertyMapping(resolver));
                rootGrp.addAll(gqlPredicateGroup);
            }
        }
        return rootGrp;
    }

    /**
     * populates and saves all valid schema editor formitems which can be used as gql facets
     * @param sourceNode source for schema editor formitems
     * @param destinationNode location to save found gql facets
     */
    public static void populateGqlfacets(Resource sourceNode, Resource destinationNode) {
        if (sourceNode == null) {
            log.error("source node null, skipping GQL facets extraction");
            return;
        }
        try {
            findGqlFacets(sourceNode, destinationNode);
        } catch(PersistenceException e) {
            log.error("Error while GQL facets extraction" + e.getMessage(), e);
        }

    }

    /**
     * Collects fulltext from all fulltext predicates in predicateGroup which are valid GQL expressions
     * and also removes such predicates from predicateGroup
     * @param predicateGroup PredicateGroup to be processed
     * @return List of valid gql expressions
     *
     */
    private static List getValidGQLStatements(PredicateGroup predicateGroup) {
        List gqlExpressions = new ArrayList();
        if (predicateGroup == null)
            return gqlExpressions;
        for (int i = 0; i < predicateGroup.size(); i++) {
            if (predicateGroup.get(i) instanceof PredicateGroup) {
                gqlExpressions.addAll(getValidGQLStatements((PredicateGroup) predicateGroup.get(i)));
            } else if (predicateGroup.get(i) instanceof Predicate) {
                Predicate predicate = predicateGroup.get(i);
                if (FulltextPredicateEvaluator.FULLTEXT.equals(predicate.getType())) {
                    String fulltext = predicate.get(FulltextPredicateEvaluator.FULLTEXT, "");
                    if (fulltext != null && (fulltext.contains(":") || fulltext.contains(OR_OP))) {
                        gqlExpressions.add(fulltext);
                        predicateGroup.remove(i);
                    }
                }
            }
        }
        return gqlExpressions;
    }

    /**
     * @param resolver to resolve node containing jcr properties mapping
     * @return map containing gql to jcr properties mapping
     * @throws RepositoryException
     */
    private static Map getJcrPropertyMapping(ResourceResolver resolver) throws RepositoryException {
        Map jcrPropertyMap = new HashMap();
        if (resolver == null) {
            log.warn("Resource resolver is null, skipping property name conversion");
            return jcrPropertyMap;
        }
        Resource formItemsNode = resolver.getResource(getGqlFacetsDir(resolver));
        for (Iterator itr = formItemsNode.listChildren(); itr.hasNext(); ) {
            ValueMap prop = itr.next().adaptTo(ValueMap.class);
            if (prop != null && prop.containsKey("fieldLabel") && prop.containsKey("name")) {
                jcrPropertyMap.put(prop.get("fieldLabel").toString().toLowerCase().trim().replace(" ", ""),
                        prop.get("name").toString());
            }
        }
        return jcrPropertyMap;
    }

    private static String getGqlFacetsDir(ResourceResolver resolver) {
        String gqlFacetsDir = JCR_PROPERTIES_PATH;
        Tenant tenant = resolver.adaptTo(Tenant.class);
        if (tenant != null) {
            if (tenant.getProperty(DamConfigurationConstants.DAM_GQL_FACETS_ROOT) != null) {
                gqlFacetsDir = tenant.getProperty(DamConfigurationConstants.DAM_GQL_FACETS_ROOT).toString();
            }
        }
        return gqlFacetsDir;
    }

    /**
     * DAM level customization for different conditions
     *
     * @param predicateGroup PredicateGroup to be transformed
     * @param jcrPropertyMap mapping of properties to jcr properties
     */
    private static void transformPredicates(PredicateGroup predicateGroup, Map jcrPropertyMap) {
        if (predicateGroup == null) {
            return;
        }
        for (int i = 0; i < predicateGroup.size(); i++) {
            if (predicateGroup.get(i) instanceof PredicateGroup) {
                PredicateGroup optionalGrp = (PredicateGroup) predicateGroup.get(i);
                transformPredicates(optionalGrp, jcrPropertyMap);
                predicateGroup.set(i, optionalGrp);
            } else if (predicateGroup.get(i) instanceof Predicate) {
                Predicate predicate = predicateGroup.get(i);
                modifyPredicate(predicateGroup, predicate, i, jcrPropertyMap);
            }
        }
    }

    private static void modifyPredicate(PredicateGroup parentGroup, Predicate predicate, int index, Map jcrPropertyMap) {
        String property = predicate.get("property");
        if (JcrPropertyPredicateEvaluator.PROPERTY.equals(predicate.getType())) {
            String value = predicate.get("value");
            if (property.equals(TAGS_PROP)) {
                property = jcrPropertyMap.containsKey(property.toLowerCase()) ?
                        jcrPropertyMap.get(property.toLowerCase()) : property;
                predicate = new Predicate(TagSearchPredicateEvaluator.TYPE);
                predicate.set(JcrPropertyPredicateEvaluator.PROPERTY, property);
                predicate.set(TagSearchPredicateEvaluator.TYPE, value);
            } else {
                property = jcrPropertyMap.containsKey(property.toLowerCase()) ?
                        jcrPropertyMap.get(property.toLowerCase()) : property;
                predicate.set(JcrPropertyPredicateEvaluator.PROPERTY,  property);
                predicate.set(JcrPropertyPredicateEvaluator.VALUE, value);
                predicate.set(JcrPropertyPredicateEvaluator.OPERATION, JcrPropertyPredicateEvaluator.OP_LIKE);
            }
        } else if (DATERANGE_PRED.equals(predicate.getType()) || RANGEPROP_PRED.equals(predicate.getType())) {
            property = jcrPropertyMap.containsKey(property) ? jcrPropertyMap.get(property) : property;
            predicate.set(JcrPropertyPredicateEvaluator.PROPERTY, property);
            predicate.set(RangePropertyPredicateEvaluator.LOWER_OPERATION, ">=");
            predicate.set(RangePropertyPredicateEvaluator.UPPER_OPERATION, "<=");
        }
        parentGroup.set(index,predicate);
    }

    private static void findGqlFacets(Resource sourceNode, Resource destinationNode) throws PersistenceException {
        if (sourceNode == null) {
            return;
        }
        for (Iterator itr = sourceNode.listChildren(); itr.hasNext();) {
            Resource childNode = itr.next();
            ValueMap childProps = childNode != null ? childNode.adaptTo(ValueMap.class) : null;
            if (childProps != null) {
                String jcrProperty = childProps.get("name", String.class);
                String facetName = childProps.get("fieldLabel", String.class);
                if (jcrProperty != null && facetName != null) {
                    String desNodeName = JcrUtil.createValidName(facetName);
                    if (destinationNode.getChild(desNodeName) == null) {
                        jcrProperty = (jcrProperty.length() > 2 && jcrProperty.startsWith("./")) ?
                                jcrProperty.substring(2) : jcrProperty;
                        Map props = new HashMap();
                        props.put("fieldLabel", facetName);
                        props.put("name", jcrProperty);
                        destinationNode.getResourceResolver().create(destinationNode, desNodeName, props);
                    }
                }
            }
            findGqlFacets(childNode, destinationNode);
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy