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

com.day.cq.search.PredicateGroup Maven / Gradle / Ivy

There is a newer version: 2024.11.18598.20241113T125352Z-241000
Show newest version
/*
 * 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;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;

import org.apache.commons.lang.ObjectUtils;
import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;

/**
 * A PredicateGroup is a {@link Predicate} that represents a list
 * of {@link Predicate Predicates} (following the composite pattern). This
 * allows to build predicate trees for reflecting complex queries that include
 * sub-terms.
 * 
 * 

* The predicates in a group are by default all required to match, ie. they will * be combined with "AND" in a lower-level query language, which is indicated by * {@link #allRequired()} returning true. If {@link #setAllRequired(boolean)} is * called with false, or if the parameter or is set to * true, the child predicates will be combined with "OR", ie. only * one must match for the whole group to match. * *

* If the parameter not is set to true, the result of * this group will be negated. See also {@link #isNegated()} and * {@link #setNegated(boolean)}. * *

* This class extends both the {@link Predicate} class and implements the * {@link List} interface, backed by a standard {@link ArrayList} internally. * *

* The standard type name for predicate groups is given by {@link #TYPE} ( * {@value PredicateGroup#TYPE}), which is also used when using the default * constructor. * * @since 5.2 */ public class PredicateGroup extends Predicate implements List { public static final String TYPE = "group"; private List predicates = new ArrayList(); /** * Creates this predicate group with the group type * {@value #TYPE}, and a predicate name of null. * Use this constructor when the name should be deducted automatically (see * {@link #getName()}) or for the root group of a predicate tree, because * the name must be null for that case. */ public PredicateGroup() { super(null, PredicateGroup.TYPE); } /** * Creates this predicate group with the given name and the group type * {@value #TYPE}, using the * {@link Predicate#Predicate(String, String)} constructor. If you create a * root group of a predicate tree, the name must be null (you * can use the default constructor {@link #PredicateGroup()} for that). */ public PredicateGroup(String name) { super(name, PredicateGroup.TYPE); } /** * Converts a map with predicates and their parameters into a predicate * tree. Accepts a map with strings as keys and either simple strings as * values or string arrays as values. In the array case, the first value * will be chosen. * *

* Same as {@link PredicateConverter#createPredicates(Map)}. */ public static PredicateGroup create(Map predicateParameterMap) { return PredicateConverter.createPredicates(predicateParameterMap); } /** * Returns an URL query part containing the given group. This is the same * mapping as used in {@link #createMap(PredicateGroup)} and * {@link #createPredicates(Map)}. For example, the returned value could be: * type=cq:Page&path=/content. Note that this won't be a * complete URL, just a list of parameters for an URL query part. The keys * and values will be properly escaped for use in an URL. * *

* Same as {@link PredicateConverter#toURL(PredicateGroup)}. */ public String toURL() { return PredicateConverter.toURL(this); } /** * Returns whether all predicates are combined with "AND", ie. only nodes * are found that match all predicates in this group. The default value is * true (AND): * * @return true for "AND" (default), false for "OR" */ public boolean allRequired() { // default is AND, hence we use the "inverse" OR flag return !getBool("or"); } /** * Sets whether all predicates are combined with "AND", ie. only nodes are * found that match all predicates in this group, or if they are combined * with "OR". * * @param all * true for "AND", false for "OR" */ public void setAllRequired(boolean all) { // invert since we set "or" here set("or", all ? "false" : "true"); } /** * Returns whether the result of this predicate group should be negated. Ie. * only nodes that do not match this group should be included in the * results. The default value is false. * * @return true for exclusive, false for inclusive * (default) * * @since 5.5 */ public boolean isNegated() { return getBool("not"); } /** * Sets whether the result of this group should be negated. * * @param not * true if the group should be negated, * false if not (default) * * @since 5.5 */ public void setNegated(boolean not) { set("not", not ? "true" : "false"); } /** * Returns a certain predicate by its {@link Predicate#getName() name}. */ public Predicate getByName(String name) { for (Predicate p: predicates) { if (ObjectUtils.equals(p.getName(), name)) { return p; } } return null; } /** * Returns a certain predicate by its {@link Predicate#getPath() path}, * relative to this predicate. */ public Predicate getByPath(String path) { // eg. "group.1_group.type" => "group" + "1_group.type" String[] splits = path.split("\\.", 2); Predicate predicate = getByName(splits[0]); if (predicate != null) { if (predicate instanceof PredicateGroup) { // PredicateGroup if (splits.length > 1) { return ((PredicateGroup) predicate).getByPath(splits[1]); } } else { // Predicate return predicate; } } // path not found return null; } /** * Clones this predicate group so that the returned clone can be used * completely independently from this original. All child predicates * will hence also be cloned. */ @Override public PredicateGroup clone() { return clone(false); } /** * Clones this predicate group so that the returned clone can be used * completely independently from this original. All child predicates will * hence also be cloned. A new name for the clone can be passed. * * @param resetName * whether to reset the name and child predicate names to * null so that they will be automatically * deducted (see {@link #getName()}) */ @Override public PredicateGroup clone(boolean resetName) { PredicateGroup clone = (PredicateGroup) super.clone(resetName); clone.predicates = new ArrayList(); for (Predicate p : predicates) { Predicate pc = p.clone(resetName); pc.setParent(clone); clone.predicates.add(pc); } return clone; } @Override public boolean equals(Object obj) { if (obj == null) return false; if (obj == this) return true; if (!(obj instanceof PredicateGroup)) return false; PredicateGroup other = (PredicateGroup) obj; return new EqualsBuilder() .appendSuper(super.equals(obj)) .append(predicates, other.predicates) .isEquals(); } @Override public int hashCode() { return new HashCodeBuilder(17, 31) .appendSuper(super.hashCode()) .append(predicates) .toHashCode(); } // -------------------------------------------< misc > private static int indent = 0; /** * Overwrites the standard {@link Object#toString()} implementation and * returns a debug-friendly string including all sub predicates (via their * {@link Predicate#toString() toString()} method). The final string is * multi-lined and indented for easy readability of the inherent tree * structure. */ public String toString() { StringBuffer buffer = new StringBuffer(); buffer.append(super.toString()); buffer.append("[\n"); indent += 4; for (Predicate p: this) { appendIndent(buffer); buffer.append("{").append(p.toString()).append("}\n"); } indent = (indent <= 4 ? 0 : indent - 4); appendIndent(buffer); buffer.append("]"); return buffer.toString(); } private void appendIndent(StringBuffer buffer) { for (int i = 0; i < indent; i++) { buffer.append(" "); } } protected void setMeAsParent(Predicate element) { element.setParent(this); } protected void unsetParent(Predicate element) { element.setParent(null); } // ------------------------------------------------< List interface > public boolean add(Predicate o) { setMeAsParent(o); return predicates.add(o); } public void add(int index, Predicate element) { setMeAsParent(element); predicates.add(index, element); } public boolean addAll(Collection c) { for (Predicate p : c) { setMeAsParent(p); } return predicates.addAll(c); } public boolean addAll(int index, Collection c) { for (Predicate p : c) { setMeAsParent(p); } return predicates.addAll(index, c); } public void clear() { for (Predicate p : predicates) { unsetParent(p); } predicates.clear(); } public boolean contains(Object o) { return predicates.contains(o); } public boolean containsAll(Collection c) { return predicates.containsAll(c); } public Predicate get(int index) { return predicates.get(index); } public int indexOf(Object o) { return predicates.indexOf(o); } public boolean isEmpty() { return predicates.isEmpty(); } public Iterator iterator() { return predicates.iterator(); } public int lastIndexOf(Object o) { return predicates.lastIndexOf(o); } public ListIterator listIterator() { return predicates.listIterator(); } public ListIterator listIterator(int index) { return predicates.listIterator(index); } public boolean remove(Object o) { unsetParent((Predicate) o); return predicates.remove(o); } public Predicate remove(int index) { Predicate p = predicates.remove(index); unsetParent(p); return p; } public boolean removeAll(Collection c) { for (Object o : c) { unsetParent((Predicate) o); } return predicates.removeAll(c); } public boolean retainAll(Collection c) { Iterator iter = iterator(); while (iter.hasNext()) { Predicate p = iter.next(); if (!c.contains(p)) { unsetParent(p); } } return predicates.retainAll(c); } public Predicate set(int index, Predicate element) { setMeAsParent(element); return predicates.set(index, element); } public int size() { return predicates.size(); } public List subList(int fromIndex, int toIndex) { return predicates.subList(fromIndex, toIndex); } public Object[] toArray() { return predicates.toArray(); } public T[] toArray(T[] a) { return predicates.toArray(a); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy