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

com.day.cq.search.facets.extractors.PropertyFacetExtractor 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.search.facets.extractors;

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

import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.Property;
import javax.jcr.PropertyIterator;
import javax.jcr.PropertyType;
import javax.jcr.RepositoryException;
import javax.jcr.Value;
import javax.jcr.ValueFactory;

import com.day.cq.search.facets.FacetExtractor;

/**
 * PropertyFacetExtractor is a base class for facet extractors that
 * work on a certain property (incl. relative paths to properties in sub-nodes),
 * specified by the parameter propertyRelPath in the constructor.
 * In addition, subclasses can implement {@link #filter(List, ValueFactory)} for
 * further filtering of the list of values.
 * 
 * @since 5.2
 */
public abstract class PropertyFacetExtractor implements FacetExtractor {

    /**
     * Empty list of properties.
     */
    protected static final List EMPTY_PROPERTY_LIST = Collections.emptyList();
    
    /**
     * Relative path to the property that provides the value for the facet.
     */
    protected final String propertyRelPath;

    public PropertyFacetExtractor(String propertyRelPath) {
        this.propertyRelPath = propertyRelPath;
    }
    
    /**
     * Called for each value found in a node of the result and that matches the
     * relative property path. This can be multiple values per node as it could
     * be a multi-value property or if multiple properties match the relative
     * property path pattern. 
     * 
     * @param value a value to check in which bucket it fits
     * @throws RepositoryException
     */
    protected abstract void handleValue(Value value) throws RepositoryException;

    /**
     * Filters the values by applying the filter of the definition
     * associated with this facet.
     *
     * @param values the values to filter.
     * @param vf the value factory.
     * @return the filtered values.
     * @throws RepositoryException if an error occurs while reading the values.
     */
    protected abstract List filter(List values, ValueFactory vf) throws RepositoryException;
    
    public void handleNode(Node node) throws RepositoryException {
        List values = getValues(node);
        for (Value value : values) {
            handleValue(value);
        }
    }
    
    /**
     * Gets the values of this facet for the provided node.
     *
     * @param node the node.
     * @return the values of this facet.
     * @throws RepositoryException if an error occurs while reading from the node.
     */
    protected List getValues(Node node) throws RepositoryException {
        ValueFactory vf = node.getSession().getValueFactory();
        List values = null;
        Iterator props = getProperties(node, propertyRelPath);
        if (props.hasNext()) {
            boolean isBinary = false;
            values = new ArrayList();
            while (props.hasNext()) {
                Property p = props.next();
                if (p.getType() == PropertyType.BINARY) {
                    isBinary = true;
                    long[] lengths;
                    if (p.getDefinition().isMultiple()) {
                        lengths = p.getLengths();
                    } else {
                        lengths = new long[]{p.getLength()};
                    }
                    for (long len : lengths) {
                        values.add(vf.createValue(len));
                    }
                } else if (p.getDefinition().isMultiple()) {
                    values.addAll(Arrays.asList(p.getValues()));
                } else {
                    values.add(p.getValue());
                }
            }
            // special case for binaries, always return lengths
            if (isBinary) {
                return values;
            }
        } else {
            // properties are empty when we only look at node paths (for using the nodePathFilter)
            try {
                if (node.hasNode(propertyRelPath)) {
                    values = new ArrayList();
                    values.add(node.getSession().getValueFactory().createValue(
                            node.getNode(propertyRelPath).getPath()));
                }
            } catch (RepositoryException e) {
                // ignore
            }
        }
        if (values == null) {
            values = Collections.emptyList();
        }
        return filter(values, vf);
    }

    /**
     * Returns the properties below node that match the
     * pathPattern.
     *
     * @param node the start node.
     * @param pathPattern a relative path pattern. See
     *          {@link Node#getProperties(String)} for a definition of a pattern.
     *
     * @return the properties that match the path pattern.
     * @throws RepositoryException if an error occurs while reading from the
     *          repository.
     */
    private static Iterator getProperties(Node node, String pathPattern)
            throws RepositoryException {
        if (pathPattern == null || pathPattern.equals(".")) {
            return EMPTY_PROPERTY_LIST.iterator();
        }
        List nodes = new ArrayList();
        List properties = new ArrayList();
        nodes.add(node);
        String[] namePattern = pathPattern.split("/");
        for (int i = 0; i < namePattern.length; i++) {
            if (i == namePattern.length - 1) {
                for (Node n : nodes) {
                    for (PropertyIterator pIt = n.getProperties(namePattern[i]); pIt.hasNext();) {
                        properties.add(pIt.nextProperty());
                    }
                }
            } else {
                List children = new ArrayList();
                for (Node n : nodes) {
                    for (NodeIterator nIt = n.getNodes(namePattern[i]); nIt.hasNext();) {
                        children.add(nIt.nextNode());
                    }
                }
                nodes = children;
            }
        }
        return properties.iterator();
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy