JcrQueryTaskFinder.java 15.9 KB
/*
 * Decompiled with CFR 0_118.
 * 
 * Could not load the following classes:
 *  com.adobe.granite.taskmanagement.ComparisonOperator
 *  com.adobe.granite.taskmanagement.Condition
 *  com.adobe.granite.taskmanagement.Filter
 *  com.adobe.granite.taskmanagement.Task
 *  com.adobe.granite.taskmanagement.TaskManagerException
 *  com.adobe.granite.taskmanagement.TaskProperty
 *  javax.jcr.Binary
 *  javax.jcr.Node
 *  javax.jcr.NodeIterator
 *  javax.jcr.RepositoryException
 *  javax.jcr.Session
 *  javax.jcr.Value
 *  javax.jcr.ValueFactory
 *  javax.jcr.Workspace
 *  javax.jcr.query.QueryManager
 *  javax.jcr.query.QueryResult
 *  javax.jcr.query.qom.And
 *  javax.jcr.query.qom.Column
 *  javax.jcr.query.qom.Comparison
 *  javax.jcr.query.qom.Constraint
 *  javax.jcr.query.qom.DescendantNode
 *  javax.jcr.query.qom.DynamicOperand
 *  javax.jcr.query.qom.Literal
 *  javax.jcr.query.qom.Not
 *  javax.jcr.query.qom.Or
 *  javax.jcr.query.qom.Ordering
 *  javax.jcr.query.qom.PropertyExistence
 *  javax.jcr.query.qom.PropertyValue
 *  javax.jcr.query.qom.QueryObjectModel
 *  javax.jcr.query.qom.QueryObjectModelFactory
 *  javax.jcr.query.qom.Selector
 *  javax.jcr.query.qom.Source
 *  javax.jcr.query.qom.StaticOperand
 */
package com.adobe.granite.taskmanagement.impl.jcr;

import com.adobe.granite.taskmanagement.ComparisonOperator;
import com.adobe.granite.taskmanagement.Condition;
import com.adobe.granite.taskmanagement.Filter;
import com.adobe.granite.taskmanagement.Task;
import com.adobe.granite.taskmanagement.TaskManagerException;
import com.adobe.granite.taskmanagement.TaskProperty;
import com.adobe.granite.taskmanagement.impl.jcr.TaskFinder;
import com.adobe.granite.taskmanagement.impl.jcr.TaskStorageProvider;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import javax.jcr.Binary;
import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.Value;
import javax.jcr.ValueFactory;
import javax.jcr.Workspace;
import javax.jcr.query.QueryManager;
import javax.jcr.query.QueryResult;
import javax.jcr.query.qom.And;
import javax.jcr.query.qom.Column;
import javax.jcr.query.qom.Comparison;
import javax.jcr.query.qom.Constraint;
import javax.jcr.query.qom.DescendantNode;
import javax.jcr.query.qom.DynamicOperand;
import javax.jcr.query.qom.Literal;
import javax.jcr.query.qom.Not;
import javax.jcr.query.qom.Or;
import javax.jcr.query.qom.Ordering;
import javax.jcr.query.qom.PropertyExistence;
import javax.jcr.query.qom.PropertyValue;
import javax.jcr.query.qom.QueryObjectModel;
import javax.jcr.query.qom.QueryObjectModelFactory;
import javax.jcr.query.qom.Selector;
import javax.jcr.query.qom.Source;
import javax.jcr.query.qom.StaticOperand;

/*
 * This class specifies class file version 49.0 but uses Java 6 signatures.  Assumed Java 6.
 */
public class JcrQueryTaskFinder
implements TaskFinder {
    private TaskStorageProvider taskStorageProvider;
    private Session session;
    private String rootPath;
    private static final String TASK_SELECTOR = "tasks";

    public JcrQueryTaskFinder(TaskStorageProvider taskStorageProvider, Session session, String rootPath) {
        this.taskStorageProvider = taskStorageProvider;
        this.session = session;
        this.rootPath = rootPath;
    }

    @Override
    public List<Task> findTasks(Set<String> setOfUserIDs, Filter filter, int startIndex, int maxNumberOfTasks) throws TaskManagerException {
        try {
            Constraint propertyConstraint;
            Constraint taskTypeConstraint;
            Constraint combinedUserConstraint;
            QueryManager qm = this.session.getWorkspace().getQueryManager();
            ValueFactory valueFactory = this.session.getValueFactory();
            QueryObjectModelFactory qf = qm.getQOMFactory();
            Selector source = qf.selector("granite:Task", "tasks");
            DescendantNode pathConstraint = null;
            boolean hasParentTaskId = false;
            if (filter != null && filter.getParentTaskId() != null && filter.getParentTaskId().trim().length() > 0) {
                hasParentTaskId = true;
                pathConstraint = qf.descendantNode("tasks", this.getPath(filter.getParentTaskId()));
            } else {
                pathConstraint = qf.descendantNode("tasks", this.rootPath);
            }
            DescendantNode taskFilterConstraint = pathConstraint;
            if (filter != null && !filter.isReturnFlatStructure()) {
                taskFilterConstraint = hasParentTaskId ? qf.and((Constraint)pathConstraint, (Constraint)qf.comparison((DynamicOperand)qf.propertyValue("tasks", TaskProperty.PARENT_TASK_ID.getPropertyName()), "jcr.operator.equal.to", (StaticOperand)qf.literal(valueFactory.createValue(filter.getParentTaskId())))) : qf.and((Constraint)pathConstraint, (Constraint)qf.not((Constraint)qf.propertyExistence("tasks", TaskProperty.PARENT_TASK_ID.getPropertyName())));
            }
            if ((combinedUserConstraint = this.constructUserConstraint(setOfUserIDs = this.taskStorageProvider.cleanupUserIDs(filter, setOfUserIDs), valueFactory, qf)) != null) {
                taskFilterConstraint = qf.and((Constraint)taskFilterConstraint, combinedUserConstraint);
            }
            if ((propertyConstraint = this.constructPropertyConstraint(filter, valueFactory, qf)) != null) {
                taskFilterConstraint = qf.and((Constraint)taskFilterConstraint, propertyConstraint);
            }
            if ((taskTypeConstraint = this.constructTaskTypeConstraint(filter, valueFactory, qf)) != null) {
                taskFilterConstraint = qf.and((Constraint)taskFilterConstraint, taskTypeConstraint);
            }
            QueryObjectModel query = qf.createQuery((Source)source, (Constraint)taskFilterConstraint, null, null);
            QueryResult queryResult = query.execute();
            ArrayList<Task> listOfTasks = new ArrayList<Task>();
            int taskIndex = 0;
            NodeIterator nodeIterator = queryResult.getNodes();
            while (nodeIterator.hasNext()) {
                Node node = nodeIterator.nextNode();
                if (++taskIndex <= startIndex) continue;
                Task task = this.taskStorageProvider.read(node, filter != null && filter.isReturnTaskStructure());
                listOfTasks.add(task);
                if (maxNumberOfTasks <= 0 || listOfTasks.size() < maxNumberOfTasks) continue;
                break;
            }
            return listOfTasks;
        }
        catch (RepositoryException re) {
            throw new TaskManagerException("Failed to query for tasks", (Throwable)re);
        }
    }

    private Constraint constructTaskTypeConstraint(Filter filter, ValueFactory valueFactory, QueryObjectModelFactory qf) throws RepositoryException {
        Comparison result = null;
        if (filter != null && filter.getTaskTypes() != null && filter.getTaskTypes().length > 0) {
            for (String taskType : filter.getTaskTypes()) {
                if (taskType == null) continue;
                Comparison comparison = this.createComparison(valueFactory, qf, TaskProperty.TASK_TYPE_NAME.getPropertyName(), "jcr.operator.equal.to", taskType);
                result = result == null ? comparison : qf.or((Constraint)result, (Constraint)comparison);
            }
        }
        return result;
    }

    private Constraint constructPropertyConstraint(Filter filter, ValueFactory valueFactory, QueryObjectModelFactory qf) throws RepositoryException, TaskManagerException {
        Constraint propertyConstraint = null;
        if (filter != null) {
            Iterator conditions = filter.getConditions();
            while (conditions.hasNext()) {
                Condition condition = (Condition)conditions.next();
                Constraint constraint = this.createConstraint(valueFactory, qf, condition);
                if (constraint == null) continue;
                if (propertyConstraint == null) {
                    propertyConstraint = constraint;
                    continue;
                }
                propertyConstraint = qf.and(propertyConstraint, constraint);
            }
        }
        return propertyConstraint;
    }

    private Constraint createConstraint(ValueFactory valueFactory, QueryObjectModelFactory qf, Condition condition) throws RepositoryException, TaskManagerException {
        if (condition == null) {
            return null;
        }
        if (condition.getComparisonOperator() == null || condition.getPropertyName() == null) {
            throw new TaskManagerException("Property on filter condition is null");
        }
        switch (condition.getComparisonOperator()) {
            case IN_LIST: {
                return this.constructInListConstraint(valueFactory, qf, condition);
            }
            case BEGINS_WITH: 
            case ENDS_WITH: 
            case CONTAINS: {
                return this.constructLikeConstraint(valueFactory, qf, condition);
            }
        }
        return qf.comparison((DynamicOperand)qf.propertyValue("tasks", condition.getPropertyName()), this.getComparator(condition), (StaticOperand)qf.literal(this.getConditionValue(valueFactory, condition)));
    }

    private Constraint constructLikeConstraint(ValueFactory valueFactory, QueryObjectModelFactory qf, Condition condition) throws RepositoryException, TaskManagerException {
        if (condition == null) {
            return null;
        }
        if (condition.getComparisonOperator() == null || condition.getPropertyName() == null || condition.getComparisonValue() == null) {
            throw new TaskManagerException("Property on filter condition is null");
        }
        if (!(condition.getComparisonValue() instanceof String)) {
            throw new TaskManagerException("Unexpected property value comparison type in 'Like' expression, expected String got " + condition.getComparisonValue());
        }
        String literal = (String)condition.getComparisonValue();
        if (literal == null) {
            literal = "";
        }
        switch (condition.getComparisonOperator()) {
            case BEGINS_WITH: {
                literal = literal + "%";
                break;
            }
            case ENDS_WITH: {
                literal = "%" + literal;
                break;
            }
            case CONTAINS: {
                literal = "%" + literal + "%";
                break;
            }
            default: {
                throw new TaskManagerException("Unepxected comparison operator in 'Like' constraint");
            }
        }
        return qf.comparison((DynamicOperand)qf.propertyValue("tasks", condition.getPropertyName()), this.getComparator(condition), (StaticOperand)qf.literal(valueFactory.createValue(literal)));
    }

    private Constraint constructInListConstraint(ValueFactory valueFactory, QueryObjectModelFactory qf, Condition condition) throws TaskManagerException, RepositoryException {
        if (condition.getComparisonOperator() != ComparisonOperator.IN_LIST) {
            throw new TaskManagerException("Expected IN_LIST operator, got " + (Object)condition.getComparisonOperator());
        }
        if (!(condition.getComparisonValue() instanceof List)) {
            throw new TaskManagerException("Expected List paramter for IN_LIST comparison, got " + condition.getComparisonValue().getClass().getCanonicalName());
        }
        List listOfValues = (List)condition.getComparisonValue();
        if (listOfValues != null) {
            Comparison result = null;
            for (String value : listOfValues) {
                String propertyName = condition.getPropertyName();
                Comparison comparison = this.createComparison(valueFactory, qf, propertyName, "jcr.operator.equal.to", value);
                if (result == null) {
                    result = comparison;
                    continue;
                }
                result = qf.or((Constraint)result, (Constraint)comparison);
            }
            return result;
        }
        return null;
    }

    private Comparison createComparison(ValueFactory valueFactory, QueryObjectModelFactory qf, String propertyName, String comparisonOperator, String propertyValue) throws RepositoryException {
        return qf.comparison((DynamicOperand)qf.propertyValue("tasks", propertyName), comparisonOperator, (StaticOperand)qf.literal(valueFactory.createValue(propertyValue)));
    }

    private String getComparator(Condition condition) throws TaskManagerException {
        switch (condition.getComparisonOperator()) {
            case EQUALS: {
                return "jcr.operator.equal.to";
            }
            case GREATER_THAN: {
                return "jcr.operator.greater.than";
            }
            case LESS_THAN: {
                return "jcr.operator.less.than";
            }
            case NOT_EQUALS: {
                return "jcr.operator.not.equal.to";
            }
            case GREATER_THAN_EQUALS: {
                return "jcr.operator.greater.than.or.equal.to";
            }
            case LESS_THAN_EQUALS: {
                return "jcr.operator.less.than.or.equal.to";
            }
            case BEGINS_WITH: {
                return "jcr.operator.like";
            }
            case ENDS_WITH: {
                return "jcr.operator.like";
            }
            case CONTAINS: {
                return "jcr.operator.like";
            }
        }
        throw new TaskManagerException("Unknown comparison operator in task filter");
    }

    private Value getConditionValue(ValueFactory valueFactory, Condition condition) throws TaskManagerException {
        Object conditionValue = condition.getComparisonValue();
        if (conditionValue instanceof String) {
            return valueFactory.createValue((String)conditionValue);
        }
        if (conditionValue != null && conditionValue.getClass().isEnum()) {
            return valueFactory.createValue(((Enum)conditionValue).name());
        }
        if (conditionValue instanceof BigDecimal) {
            return valueFactory.createValue((BigDecimal)conditionValue);
        }
        if (conditionValue instanceof Binary) {
            return valueFactory.createValue((Binary)conditionValue);
        }
        if (conditionValue instanceof Boolean) {
            return valueFactory.createValue(((Boolean)conditionValue).booleanValue());
        }
        if (conditionValue instanceof Date) {
            Calendar cal = Calendar.getInstance();
            cal.setTime((Date)conditionValue);
            return valueFactory.createValue(cal);
        }
        if (conditionValue instanceof Calendar) {
            return valueFactory.createValue((Calendar)conditionValue);
        }
        if (conditionValue instanceof Double) {
            return valueFactory.createValue(((Double)conditionValue).doubleValue());
        }
        if (conditionValue instanceof Long) {
            return valueFactory.createValue(((Long)conditionValue).longValue());
        }
        return valueFactory.createValue(conditionValue.toString());
    }

    private Constraint constructUserConstraint(Set<String> setOfUserIDs, ValueFactory valueFactory, QueryObjectModelFactory qf) throws RepositoryException {
        Comparison resultingConstraint = null;
        if (setOfUserIDs != null && setOfUserIDs.size() > 0) {
            for (String userId : setOfUserIDs) {
                Comparison userConstraint = qf.comparison((DynamicOperand)qf.propertyValue("tasks", TaskProperty.OWNER_ID.getPropertyName()), "jcr.operator.equal.to", (StaticOperand)qf.literal(valueFactory.createValue(userId)));
                if (resultingConstraint == null) {
                    resultingConstraint = userConstraint;
                    continue;
                }
                resultingConstraint = qf.or((Constraint)resultingConstraint, (Constraint)userConstraint);
            }
        }
        return resultingConstraint;
    }

    private String getPath(String id) {
        return this.rootPath + '/' + id;
    }

}