package er.extensions.eof; import java.util.Enumeration; import java.util.NoSuchElementException; import com.webobjects.eoaccess.EOEntity; import com.webobjects.eocontrol.EOAndQualifier; import com.webobjects.eocontrol.EOKeyValueQualifier; import com.webobjects.eocontrol.EONotQualifier; import com.webobjects.eocontrol.EOOrQualifier; import com.webobjects.eocontrol.EOQualifier; import com.webobjects.foundation.NSArray; import com.webobjects.foundation.NSDictionary; import com.webobjects.foundation.NSMutableArray; import com.webobjects.foundation.NSSelector; import er.extensions.eof.qualifiers.ERXInQualifier; import er.extensions.eof.qualifiers.ERXRegExQualifier; import er.extensions.eof.qualifiers.ERXToManyQualifier; import er.extensions.qualifiers.ERXAndQualifier; import er.extensions.qualifiers.ERXFalseQualifier; import er.extensions.qualifiers.ERXKeyComparisonQualifier; import er.extensions.qualifiers.ERXKeyValueQualifier; import er.extensions.qualifiers.ERXNotQualifier; import er.extensions.qualifiers.ERXOrQualifier; import er.extensions.qualifiers.ERXTrueQualifier; /** * ERXQ provides lots of much shorter methods of constructing EOQualifiers than * the very verbose style that you normally have to use. For instance ... * * <blockquote><pre> EOQualifier qualifier = new ERXAndQualifier( new NSArray(new Object[] { new ERXKeyValueQualifier("name", EOQualifier.QualifierOperatorsEquals, "Mike"), new ERXKeyValueQualifier("admin", EOQualifier.QualifierOperatorsEquals, Boolean.TRUE) })); </pre></blockquote> * * <p> * ... becomes ... * </p> * * <blockquote><code> EOQualifier qualifier = ERXQ.and(ERXQ.equals("name", "Mike"), ERXQ.isTrue("admin")); * </code></blockquote> * * @author mschrag */ public class ERXQ { /** * Equivalent to EOQualifier.QualifierOperatorEqual */ public static final NSSelector EQ = EOQualifier.QualifierOperatorEqual; /** * Equivalent to EOQualifier.QualifierOperatorNotEqual */ public static final NSSelector NE = EOQualifier.QualifierOperatorNotEqual; /** * Equivalent to EOQualifier.QualifierOperatorLessThan */ public static final NSSelector LT = EOQualifier.QualifierOperatorLessThan; /** * Equivalent to EOQualifier.QualifierOperatorGreaterThan */ public static final NSSelector GT = EOQualifier.QualifierOperatorGreaterThan; /** * Equivalent to EOQualifier.QualifierOperatorLessThanOrEqualTo */ public static final NSSelector LTEQ = EOQualifier.QualifierOperatorLessThanOrEqualTo; /** * Equivalent to EOQualifier.QualifierOperatorGreaterThanOrEqualTo */ public static final NSSelector GTEQ = EOQualifier.QualifierOperatorGreaterThanOrEqualTo; /** * Equivalent to EOQualifier.QualifierOperatorContains */ public static final NSSelector CONTAINS = EOQualifier.QualifierOperatorContains; /** * Equivalent to EOQualifier.QualifierOperatorLike */ public static final NSSelector LIKE = EOQualifier.QualifierOperatorLike; /** * Equivalent to EOQualifier.QualifierOperatorCaseInsensitiveLike */ public static final NSSelector ILIKE = EOQualifier.QualifierOperatorCaseInsensitiveLike; /** * Equivalent to EOQualifier.filteredArrayWithQualifier(NSArray, * EOQualifier) * * @param <T> * the type of the array * @param array * the array to filter * @param qualifier * the qualifier to filter with * @return the filtered array */ @SuppressWarnings( { "cast", "unchecked" }) public static <T> NSArray<T> filtered(NSArray<T> array, EOQualifier qualifier) { return (NSArray<T>) EOQualifier.filteredArrayWithQualifier(array, qualifier); } /** * Equivalent to EOQualifier.filterArrayWithQualifier(NSMutableArray, * EOQualifier) * * @param array * the array to filter (in place) * @param qualifier * the qualifier to filter with */ public static void filter(NSMutableArray<?> array, EOQualifier qualifier) { EOQualifier.filterArrayWithQualifier(array, qualifier); } /** * Returns the one object that matches the qualifier in the given array (or * null if there is no match). * * @param <T> * the type of the objects * @param array * the array to filter * @param qualifier * the qualifier to filter on * @return one matching object or null * @throws IllegalStateException if more than one object matched */ public static <T> T one(NSArray<T> array, EOQualifier qualifier) { T object = null; if (array != null && !array.isEmpty()) { NSArray<T> objects = ERXQ.filtered(array, qualifier); int count = objects.count(); if (count == 1) { object = objects.lastObject(); } else if (count > 1) { throw new IllegalStateException("There was more than one object that matched the qualifier '" + qualifier + "'."); } } return object; } /** * Returns the first object that matches the qualifier in the given array * (or null if there is no match). * * @param <T> * the type of the objects * @param array * the array to filter * @param qualifier * the qualifier to filter on * @return one matching object or null */ public static <T> T first(NSArray<T> array, EOQualifier qualifier) { T object = null; if (array != null && !array.isEmpty()) { NSArray<T> objects = ERXQ.filtered(array, qualifier); if (!objects.isEmpty()) { object = objects.objectAtIndex(0); } } return object; } /** * Returns the one object that matches the qualifier in the given array (or * throws if there is no match). * * @param <T> * the type of the objects * @param array * the array to filter * @param qualifier * the qualifier to filter on * @return one matching object * @throws IllegalStateException if more than one object matched * @throws NoSuchElementException if no objects matched */ public static <T> T requiredOne(NSArray<T> array, EOQualifier qualifier) { T object = ERXQ.one(array, qualifier); if (object == null) { throw new NoSuchElementException("There was no object that matched the qualifier '" + qualifier + "'."); } return object; } /** * Equivalent to new ERXOrQualifier(new NSArray(qualifiersArray). Nulls are * skipped. * * @param qualifiersArray * the array of qualifiers to or * @return and EOOrQualifier */ public static ERXOrQualifier or(EOQualifier... qualifiersArray) { NSMutableArray<EOQualifier> qualifiers = new NSMutableArray<>(); for (EOQualifier qualifier : qualifiersArray) { if (qualifier != null) { qualifiers.addObject(qualifier); } } return new ERXOrQualifier(qualifiers); } /** * Equivalent to new ERXOrQualifier(new NSArray(qualifiersArray). * * @param qualifiers * the NSArray of qualifiers to or * @return an ERXOrQualifier */ public static ERXOrQualifier or(NSArray<? extends EOQualifier> qualifiers) { return new ERXOrQualifier(qualifiers); } /** * Equivalent to new ERXAndQualifier(new NSArray(qualifiersArray). Nulls are * skipped. * * @param qualifiersArray * the array of qualifiers to and * @return and EOAndQualifier */ public static ERXAndQualifier and(EOQualifier... qualifiersArray) { NSMutableArray<EOQualifier> qualifiers = new NSMutableArray<>(); for (EOQualifier qualifier : qualifiersArray) { if (qualifier != null) { qualifiers.addObject(qualifier); } } return new ERXAndQualifier(qualifiers); } /** * Equivalent to new ERXAndQualifier(new NSArray(qualifiersArray). * * @param qualifiers * the NSArray of qualifiers to and * @return an ERXAndQualifier */ public static ERXAndQualifier and(NSArray<? extends EOQualifier> qualifiers) { return new ERXAndQualifier(qualifiers); } /** * Equivalent to new ERXKeyValueQualifier(key, * EOQualifier.QualifierOperatorLike, value); * * @param key * the key * @param value * the value * @return an EOKeyValueQualifier */ public static ERXKeyValueQualifier like(String key, Object value) { return new ERXKeyValueQualifier(key, ERXQ.LIKE, value); } /** * Equivalent to new ERXKeyValueQualifier(key, * EOQualifier.QualifierOperatorCaseInsensitiveLike, value); * * @param key * the key * @param value * the value * @return an EOKeyValueQualifier */ public static ERXKeyValueQualifier likeInsensitive(String key, Object value) { return new ERXKeyValueQualifier(key, ERXQ.ILIKE, value); } /** * Equivalent to new ERXRegExQualifier(key, value); * * @param key * the key * @param value * the value * @return an EOKeyValueQualifier */ public static ERXKeyValueQualifier matches(String key, String value) { return new ERXRegExQualifier(key, value); } /** * Equivalent to new ERXInQualifier(key, values); * * @param key * the key * @param values * the values * @return an EOKeyValueQualifier */ public static ERXKeyValueQualifier hasValues(String key, NSArray values) { return new ERXInQualifier(key, values); } /** * Equivalent to new ERXToManyQualifier(key, values); * * @param key * the key * @param values * the values * @return an EOKeyValueQualifier */ public static ERXKeyValueQualifier has(String key, NSArray values) { return hasAtLeast(key, values, 0); } /** * Equivalent to new ERXToManyQualifier(key, values); * * @param key * the key * @param values * the values * @param min * the minimum number of objects from values to match * @return an EOKeyValueQualifier */ public static ERXKeyValueQualifier hasAtLeast(String key, NSArray values, int min) { return new ERXToManyQualifier(key, values, min); } /** * Equivalent to new ERXKeyValueQualifier(key, * EOQualifier.QualifierOperatorEqual, value); * * @param key * the key * @param value * the value * @return an EOKeyValueQualifier */ public static ERXKeyValueQualifier equals(String key, Object value) { return new ERXKeyValueQualifier(key, ERXQ.EQ, value); } /** * Equivalent to new ERXKeyComparisonQualifier(key, * EOQualifier.QualifierOperatorEqual, value); * * @param key * the key * @param value * the value * @return an ERXKeyComparisonQualifier */ public static <T> ERXKeyComparisonQualifier equals(ERXKey<T> key, ERXKey<T> value) { return new ERXKeyComparisonQualifier(key.key(), ERXQ.EQ, value.key()); } /** * Return a OR qualifier of identity qualifiers using each value from the param array * * @param valueArray * the array of values * @return an EOQualifier * * @author Samuel Pelletier * @since May 16, 2016 */ public static EOQualifier isIn(NSArray<? extends ERXGenericRecord> valueArray) { NSMutableArray<EOQualifier> qualifiers = new NSMutableArray<>(); for (ERXGenericRecord value : valueArray) { qualifiers.add(is(value)); } return new ERXOrQualifier(qualifiers); } /** * Return an identity qualifier to use with ERXExistsQualifier for example * * @param value * the value * @return an EOQualifier * * @author Samuel Pelletier * @since May 16, 2016 */ public static EOQualifier is(ERXGenericRecord value) { EOEntity entity = value.entity(); NSDictionary<String, Object> primaryKeyDictionary = value.rawPrimaryKeyDictionary(false /* inTransaction */); EOQualifier thatAreThis = entity.qualifierForPrimaryKey(primaryKeyDictionary); return thatAreThis; } /** * Equivalent to new ERXKeyValueQualifier(key, * EOQualifier.QualifierOperatorEqual, value); * * @param key * the key * @param value * the value * @return an EOKeyValueQualifier */ public static ERXKeyValueQualifier is(String key, Object value) { return ERXQ.equals(key, value); } /** * Returns isNull or isNotNull depending on the value of yesOrNo. * * @param key * the key * @param yesOrNo * if true, returns isNull, if false, returns isNotNull * @return the EOKeyValueQualifier */ public static ERXKeyValueQualifier isNull(String key, boolean yesOrNo) { return (yesOrNo) ? ERXQ.isNull(key) : ERXQ.isNotNull(key); } /** * Equivalent to new ERXKeyValueQualifier(key, * EOQualifier.QualifierOperatorEqual, null); * * @param key * the key * @return an EOKeyValueQualifier */ public static ERXKeyValueQualifier isNull(String key) { return new ERXKeyValueQualifier(key, ERXQ.EQ, null); } /** * Equivalent to new ERXKeyValueQualifier(key, * EOQualifier.QualifierOperatorNotEqual, null); * * @param key * the key * @return an EOKeyValueQualifier */ public static ERXKeyValueQualifier isNotNull(String key) { return new ERXKeyValueQualifier(key, ERXQ.NE, null); } /** * Equivalent to new ERXKeyValueQualifier(key, * EOQualifier.QualifierOperatorEqual, Boolean.TRUE); * * @param key * the key * @return an EOKeyValueQualifier */ public static ERXKeyValueQualifier isTrue(String key) { return new ERXKeyValueQualifier(key, ERXQ.EQ, Boolean.TRUE); } /** * Equivalent to new ERXKeyValueQualifier(key, * EOQualifier.QualifierOperatorEqual, Boolean.FALSE); * * @param key * the key * @return an EOKeyValueQualifier */ public static ERXKeyValueQualifier isFalse(String key) { return new ERXKeyValueQualifier(key, ERXQ.EQ, Boolean.FALSE); } /** * Equivalent to new ERXKeyValueQualifier(key, * EOQualifier.QualifierOperatorNotEqual, value); * * @param key * the key * @param value * the value * @return an EOKeyValueQualifier */ public static ERXKeyValueQualifier notEquals(String key, Object value) { return new ERXKeyValueQualifier(key, ERXQ.NE, value); } /** * Equivalent to new ERXKeyComparisonQualifier(key, * EOQualifier.QualifierOperatorNotEqual, value); * * @param key * the key * @param value * the value * @return an ERXKeyComparisonQualifier */ public static <T >ERXKeyComparisonQualifier notEquals(ERXKey<T> key, ERXKey<T> value) { return new ERXKeyComparisonQualifier(key.key(), ERXQ.NE, value.key()); } /** * Equivalent to new ERXKeyValueQualifier(key, * EOQualifier.QualifierOperatorLessThan, value); * * @param key * the key * @param value * the value * @return an EOKeyValueQualifier */ public static ERXKeyValueQualifier lessThan(String key, Object value) { return new ERXKeyValueQualifier(key, ERXQ.LT, value); } /** * Equivalent to new ERXKeyComparisonQualifier(key, * EOQualifier.QualifierOperatorLessThan, value); * * @param key * the key * @param value * the value * @return an ERXKeyComparisonQualifier */ public static <T> ERXKeyComparisonQualifier lessThan(ERXKey<T> key, ERXKey<T> value) { return new ERXKeyComparisonQualifier(key.key(), ERXQ.LT, value.key()); } /** * Equivalent to new ERXKeyValueQualifier(key, * EOQualifier.QualifierOperatorGreaterThan, value); * * @param key * the key * @param value * the value * @return an EOKeyValueQualifier */ public static ERXKeyValueQualifier greaterThan(String key, Object value) { return new ERXKeyValueQualifier(key, ERXQ.GT, value); } /** * Equivalent to new ERXKeyComparisonQualifier(key, * EOQualifier.QualifierOperatorGreaterThan, value); * * @param key * the key * @param value * the value * @return an ERXKeyComparisonQualifier */ public static <T> ERXKeyComparisonQualifier greaterThan(ERXKey<T> key, ERXKey<T> value) { return new ERXKeyComparisonQualifier(key.key(), ERXQ.GT, value.key()); } /** * Equivalent to new ERXKeyValueQualifier(key, * EOQualifier.QualifierOperatorLessThanOrEqualTo, value); * * @param key * the key * @param value * the value * @return an EOKeyValueQualifier */ public static ERXKeyValueQualifier lessThanOrEqualTo(String key, Object value) { return new ERXKeyValueQualifier(key, ERXQ.LTEQ, value); } /** * Equivalent to new ERXKeyComparisonQualifier(key, * EOQualifier.QualifierOperatorLessThanOrEqualTo, value); * * @param key * the key * @param value * the value * @return an ERXKeyComparisonQualifier */ public static <T> ERXKeyComparisonQualifier lessThanOrEqualTo(ERXKey<T> key, ERXKey<T> value) { return new ERXKeyComparisonQualifier(key.key(), ERXQ.LTEQ, value.key()); } /** * Equivalent to new ERXKeyValueQualifier(key, * EOQualifier.QualifierOperatorGreaterThanOrEqualTo, value); * * @param key * the key * @param value * the value * @return an EOKeyValueQualifier */ public static ERXKeyValueQualifier greaterThanOrEqualTo(String key, Object value) { return new ERXKeyValueQualifier(key, ERXQ.GTEQ, value); } /** * Equivalent to new ERXKeyComparisonQualifier(key, * EOQualifier.QualifierOperatorGreaterThanOrEqualTo, value); * * @param key * the key * @param value * the value * @return an ERXKeyComparisonQualifier */ public static <T> ERXKeyComparisonQualifier greaterThanOrEqualTo(ERXKey<T> key, ERXKey<T> value) { return new ERXKeyComparisonQualifier(key.key(), ERXQ.GTEQ, value.key()); } /** * Equivalent to new ERXNotQualifier(qualifier); * * @param qualifier * the qualifier to not * @return an EONotQualifier */ public static ERXNotQualifier not(EOQualifier qualifier) { return new ERXNotQualifier(qualifier); } /** * Equivalent to new ERXKeyValueQualifier(key, operator, value); * * @param key * the key * @param operator * ERXQ.EQ, NE, GT, LT, etc * @param value * the value * @return an EOKeyValueQualifier */ public static ERXKeyValueQualifier compare(String key, NSSelector operator, Object value) { return new ERXKeyValueQualifier(key, operator, value); } /** * Equivalent to a new ERXOrQualifier of EOKeyValueQualifier with key equals * value for each value. * * @param key * the key * @param values * the values * @return an EOQualifier */ public static ERXOrQualifier inObjects(String key, Object... values) { NSMutableArray<EOQualifier> qualifiers = new NSMutableArray<>(); for (Object value : values) { qualifiers.addObject(ERXQ.equals(key, value)); } return new ERXOrQualifier(qualifiers); } /** * Equivalent to a new ERXAndQualifier of * EONotQualifier(EOKeyValueQualifier) with key equals value for each value. * * @param key * the key * @param values * the values * @return an EOQualifier */ public static ERXAndQualifier notInObjects(String key, Object... values) { NSMutableArray<EOQualifier> qualifiers = new NSMutableArray<>(); for (Object value : values) { qualifiers.addObject(ERXQ.notEquals(key, value)); } return new ERXAndQualifier(qualifiers); } /** * Equivalent to a new ERXOrQualifier of EOKeyValueQualifier with key equals * value for each value. * * @param key * the key * @param values * the values * @return an EOQualifier */ public static ERXOrQualifier in(String key, NSArray<?> values) { if(values.count() == 0) { return new ERXOrQualifier(new NSArray<>(new ERXFalseQualifier())); } NSMutableArray<EOQualifier> qualifiers = new NSMutableArray<>(); Enumeration valuesEnum = values.objectEnumerator(); while (valuesEnum.hasMoreElements()) { Object value = valuesEnum.nextElement(); qualifiers.addObject(ERXQ.equals(key, value)); } return new ERXOrQualifier(qualifiers); } /** * Equivalent to a new ERXAndQualifier of * EONotQualifier(EOKeyValueQualifier) with key equals value for each value. * * @param key * the key * @param values * the values * @return an EOQualifier */ public static ERXAndQualifier notIn(String key, NSArray values) { NSMutableArray<EOQualifier> qualifiers = new NSMutableArray<>(); Enumeration valuesEnum = values.objectEnumerator(); while (valuesEnum.hasMoreElements()) { Object value = valuesEnum.nextElement(); qualifiers.addObject(ERXQ.notEquals(key, value)); } return new ERXAndQualifier(qualifiers); } /** * Equivalent to key > lowerBound and key < upperBound (exclusive). Not that * this does not return an ERXBetweenQualifier. * * @param key * the key * @param lowerBound * the lower bound value * @param upperBound * the upper bound value * @return the qualifier */ public static EOQualifier between(String key, Object lowerBound, Object upperBound) { return ERXQ.between(key, lowerBound, upperBound, false); } /** * Equivalent to key >= lowerBound and key <= upperBound (inclusive). Not * that this does not return an ERXBetweenQualifier. * * @param key * the key * @param lowerBound * the lower bound value * @param upperBound * the upper bound value * @param inclusive * if the lowerBound and upperBound should be inclusive * @return the qualifier */ public static EOQualifier between(String key, Object lowerBound, Object upperBound, boolean inclusive) { EOKeyValueQualifier lowerQ = null; EOKeyValueQualifier upperQ = null; if (inclusive) { if (lowerBound != null) { lowerQ = ERXQ.greaterThanOrEqualTo(key, lowerBound); } if (upperBound != null) { upperQ = ERXQ.lessThanOrEqualTo(key, upperBound); } } else { if (lowerBound != null) { lowerQ = ERXQ.greaterThan(key, lowerBound); } if (upperBound != null) { upperQ = ERXQ.lessThan(key, upperBound); } } if (lowerQ == null && upperQ == null) { return null; } if (lowerQ == null) { return upperQ; } if (upperQ == null) { return lowerQ; } return ERXQ.and(lowerQ, upperQ); } /** * Equivalent to new ERXKeyValueQualifier(key, * EOQualifier.OperatorLike, value + "*"). * * @param key * the key * @param value * the substring value * @return an EOKeyValueQualifier */ public static ERXKeyValueQualifier startsWith(String key, String value) { value = value + "*"; return ERXQ.like(key, value); } /** * Equivalent to new ERXKeyValueQualifier(key, * EOQualifier.OperatorCaseInsensitiveLike, value + "*"). * * @param key * the key * @param value * the substring value * @return an EOKeyValueQualifier */ public static ERXKeyValueQualifier startsWithInsensitive(String key, String value) { value = value + "*"; return ERXQ.likeInsensitive(key, value); } /** * Equivalent to new ERXKeyValueQualifier(key, * EOQualifier.OperatorLike, "*" + value). * * @param key * the key * @param value * the substring value * @return an EOKeyValueQualifier */ public static ERXKeyValueQualifier endsWith(String key, String value) { value = "*" + value; return ERXQ.like(key, value); } /** * Equivalent to new ERXKeyValueQualifier(key, * EOQualifier.OperatorCaseInsensitiveLike, "*" + value). * * @param key * the key * @param value * the substring value * @return an EOKeyValueQualifier */ public static ERXKeyValueQualifier endsWithInsensitive(String key, String value) { value = "*" + value; return ERXQ.likeInsensitive(key, value); } /** * Equivalent to new ERXKeyValueQualifier(key, EOQualifier.OperatorContains, * value). * * @param key * the key * @param value * the value * @return an EOKeyValueQualifier */ public static ERXKeyValueQualifier containsObject(String key, Object value) { return new ERXKeyValueQualifier(key, ERXQ.CONTAINS, value); } /** * Equivalent to new ERXKeyValueQualifier(key, * EOQualifier.OperatorCaseInsensitiveLike, "*" + value + "*"). * * @param key * the key * @param value * the substring value * @return an EOKeyValueQualifier */ public static ERXKeyValueQualifier contains(String key, String value) { value = "*" + value + "*"; return ERXQ.likeInsensitive(key, value); } /** * Returns a qualifier that evalutes to true when the value of any of the * given keys contains any of the given tokens (insensitively) in the search * string. The search string will be tokenized by splitting on space * characters. * * @param keys * the keys * @param tokensWithWhitespace * a whitespace separated list of tokens to search for * @return an ERXOrQualifier */ public static ERXOrQualifier containsAny(NSArray<String> keys, String tokensWithWhitespace) { NSMutableArray<ERXOrQualifier> qualifiers = new NSMutableArray<>(); for (String key : keys) { qualifiers.addObject(ERXQ.containsAny(key, tokensWithWhitespace)); } return new ERXOrQualifier(qualifiers); } /** * Returns a qualifier that evalutes to true when the value of the given key * contains any of the given tokens (insensitively) in the search string. * The search string will be tokenized by splitting on space characters. * * @param key * the key * @param tokensWithWhitespace * a whitespace separated list of tokens to search for * @return an ERXOrQualifier */ public static ERXOrQualifier containsAny(String key, String tokensWithWhitespace) { String[] searchStrings; if (tokensWithWhitespace == null) { searchStrings = new String[0]; } else { searchStrings = tokensWithWhitespace.split("\\s+"); } return ERXQ.containsAny(key, searchStrings); } /** * Returns a qualifier that evalutes to true when the value of the given key * contains any of the given tokens (insensitively). * * @param key * the key * @param tokens * the list of tokens to search for * @return an ERXOrQualifier */ public static ERXOrQualifier containsAny(String key, String[] tokens) { ERXOrQualifier qualifier; if (tokens.length == 0) { qualifier = null; } else { NSMutableArray<EOQualifier> searchQualifiers = new NSMutableArray<>(); for (String token : tokens) { searchQualifiers.addObject(ERXQ.contains(key, token)); } qualifier = new ERXOrQualifier(searchQualifiers); } return qualifier; } /** * Returns a qualifier that evalutes to true when the value of any of the * given keys contains all of the given tokens (insensitively) in the search * string. The search string will be tokenized by splitting on space * characters. * * @param keys * the keys * @param tokensWithWhitespace * a whitespace separated list of tokens to search for * @return an ERXOrQualifier */ public static ERXOrQualifier containsAll(NSArray<String> keys, String tokensWithWhitespace) { NSMutableArray<ERXAndQualifier> qualifiers = new NSMutableArray<>(); for (String key : keys) { qualifiers.addObject(ERXQ.containsAll(key, tokensWithWhitespace)); } return new ERXOrQualifier(qualifiers); } /** * Returns a qualifier that evalutes to true when the value of the given key * contains all of the given tokens (insensitively) in the search string. * The search string will be tokenized by splitting on space characters. * * @param key * the key * @param tokensWithWhitespace * a whitespace separated list of tokens to search for * @return an ERXAndQualifier */ public static ERXAndQualifier containsAll(String key, String tokensWithWhitespace) { String[] searchStrings; if (tokensWithWhitespace == null) { searchStrings = new String[0]; } else { searchStrings = tokensWithWhitespace.split("\\s+"); } return ERXQ.containsAll(key, searchStrings); } /** * Returns a qualifier that evalutes to true when the value of the given key * contains all of the given tokens (insensitively). * * @param key * the key * @param tokens * the list of tokens to search for * @return an ERXAndQualifier */ public static ERXAndQualifier containsAll(String key, String[] tokens) { ERXAndQualifier qualifier; if (tokens.length == 0) { qualifier = null; } else { NSMutableArray<EOQualifier> searchQualifiers = new NSMutableArray<>(); for (String token : tokens) { searchQualifiers.addObject(ERXQ.contains(key, token)); } qualifier = new ERXAndQualifier(searchQualifiers); } return qualifier; } /** * Returns a qualifier that evaluates to true when all values in the given * tokens are found when searching across any of the keypaths. As an example, you * could search for "Mike Schrag" across the keys (firstName, lastName) and it would * find (firstName=Mike or lastName=Mike) and (firstName=Schrag or lastName=Schrag). * Be careful of this one as it permutes quickly. * * @param keys * keypaths to perform search in * @param tokensWithWhitespace * tokens to search for * @return an ERXAndQualifier */ public static ERXAndQualifier containsAllInAny(String[] keys, String tokensWithWhitespace) { String[] searchStrings; if (tokensWithWhitespace == null) { searchStrings = new String[0]; } else { searchStrings = tokensWithWhitespace.split("\\s+"); } return ERXQ.containsAllInAny(keys, searchStrings); } /** * Returns a qualifier that evaluates to true when all values in the given * tokens are found when searching across any of the keypaths. As an example, you * could search for "Mike Schrag" across the keys (firstName, lastName) and it would * find (firstName=Mike or lastName=Mike) and (firstName=Schrag or lastName=Schrag). * Be careful of this one as it permutes quickly. * * @param keys * keypaths to perform search in * @param tokens * tokens to search for * @return an ERXAndQualifier */ public static ERXAndQualifier containsAllInAny(String[] keys, String[] tokens) { ERXAndQualifier qualifier; if (tokens.length == 0) { qualifier = null; } else { NSMutableArray<EOQualifier> searchQualifiers = new NSMutableArray<>(); for (String token : tokens) { NSMutableArray<EOQualifier> tokenQualifiers = new NSMutableArray<>(); for (String key : keys) { tokenQualifiers.addObject(ERXQ.contains(key, token)); } searchQualifiers.addObject(new ERXOrQualifier(tokenQualifiers)); } qualifier = new ERXAndQualifier(searchQualifiers); } return qualifier; } /** * Generates a key path from a var args list of strings. Reduces this mess: * * <pre> * qualifiers.addObject(ERXQ.equals(Distribution.PUBLICATION + "." + Publication.AD + "." + Ad.STATE, DisplayAdStateMachine.ReadyForPrinting)); * </pre> * * to: * * <pre> * qualifiers.addObject(ERXQ.equals(ERXQ.keyPath(Distribution.PUBLICATION, Publication.AD, Ad.STATE, DisplayAdStateMachine.ReadyForPrinting)); * </pre> * * @param elements * one or more string to concatenate into a keyPath * @return elements with "." between them to form a keypath */ public static String keyPath(String... elements) { return new NSArray<>(elements).componentsJoinedByString("."); } /** * Analyzes the given qualifier and returns all found {@link EOKeyValueQualifier} objects * contained within. * * @param qualifier * qualifier to analyze * @return array of found key value qualifiers */ public static NSArray<EOKeyValueQualifier> extractKeyValueQualifiers(EOQualifier qualifier) { if (qualifier == null) { return NSArray.EmptyArray; } NSMutableArray<EOKeyValueQualifier> array = new NSMutableArray<>(); _extractKeyValueQualifiers(array, qualifier); return array; } private static void _extractKeyValueQualifiers(NSMutableArray<EOKeyValueQualifier> array, EOQualifier qualifier) { if (qualifier instanceof EOKeyValueQualifier) { array.add((EOKeyValueQualifier) qualifier); } else if (qualifier instanceof EOAndQualifier || qualifier instanceof EOOrQualifier) { NSArray<EOQualifier> qualifiers; if (qualifier instanceof EOAndQualifier) { qualifiers = ((EOAndQualifier)qualifier).qualifiers(); } else { qualifiers = ((EOOrQualifier)qualifier).qualifiers(); } for (EOQualifier item : qualifiers) { _extractKeyValueQualifiers(array, item); } } else if (qualifier instanceof EONotQualifier) { _extractKeyValueQualifiers(array, ((EONotQualifier)qualifier).qualifier()); } } /** * Takes a qualifier and searches for the given qualifier within to replace it with another one. * * @param qualifier * the qualifier to modify * @param searchFor * the qualifier to replace * @param replaceWith * the qualifier that replaces the searched one * @return modified qualifier */ public static EOQualifier replaceQualifierWithQualifier(EOQualifier qualifier, EOQualifier searchFor, EOQualifier replaceWith) { if (qualifier == null || searchFor == null) { throw new IllegalStateException("The params qualifier and searchFor must not be null!"); } if (replaceWith == null) { replaceWith = new ERXTrueQualifier(); } EOQualifier result = qualifier; if (qualifier.equals(searchFor)) { result = replaceWith; } else if (qualifier instanceof EOAndQualifier) { NSMutableArray<EOQualifier> array = new NSMutableArray<>(); for (EOQualifier item : ((EOAndQualifier)qualifier).qualifiers()) { array.add(replaceQualifierWithQualifier(item, searchFor, replaceWith)); } result = new EOAndQualifier(array); } else if (qualifier instanceof EOOrQualifier) { NSMutableArray<EOQualifier> array = new NSMutableArray<>(); for (EOQualifier item : ((EOOrQualifier)qualifier).qualifiers()) { array.add(replaceQualifierWithQualifier(item, searchFor, replaceWith)); } result = new EOOrQualifier(array); } else if (qualifier instanceof EONotQualifier) { EOQualifier replacedQualifier = replaceQualifierWithQualifier(((EONotQualifier)qualifier).qualifier(), searchFor, replaceWith); result = new EONotQualifier(replacedQualifier); } return result; } /** * Inspired by EOUtilities.objectsWithValues method, creates EOKeyValueQualifiers for a variable-length list of parameters, * combines these qualifier into an EOAndQualifier and returns that qualifier. Values can be a dictionary, in which case the * values are added to the EOQualifier list as EOKeyValueQualifier objects. Values can be an EOQualifier, which just gets included * in the list of EOQualifiers. When String-Object pairs or ERXKey-Object pairs appear in the list, they are turned into an * EOKeyValueQualifier and added to the list. * <p> * An IllegalArgumentException is thrown if objects are not of the right type or if a bad sequence is used, such as a sequence of * String-Object-Object or String-String-String. * <p> * See er.extensions.eof.ERXEOControlUtilitiesTest in the ERXTest project for details. * <p> * @param values a list of objects that can be used to create an EOQualifier. An NSDictionary or EOQualifier can stand alone in the * list. A String or ERXKey must be followed by an Object. * @return an EOQualifier */ public static EOQualifier matchingValues(Object... values) { NSMutableArray<EOQualifier> qualifiers = new NSMutableArray<>(); int idx = 0; while (idx < values.length) { if (values[idx] instanceof NSDictionary) { NSDictionary<String,Object> theseValues = (NSDictionary<String,Object>)values[idx]; for (String aKey : theseValues.allKeys()) { qualifiers.add(new EOKeyValueQualifier(aKey, EOQualifier.QualifierOperatorEqual, theseValues.objectForKey(aKey))); } idx++; continue; } if (values[idx] instanceof EOQualifier) { qualifiers.add((EOQualifier)values[idx]); idx++; continue; } if (values[idx] instanceof String || values[idx] instanceof ERXKey) { if ((idx+1) < values.length) { if (values[idx] instanceof String) qualifiers.add(new EOKeyValueQualifier((String)values[idx], EOQualifier.QualifierOperatorEqual, values[idx+1])); else qualifiers.add(((ERXKey)values[idx]).is(values[idx+1])); } else throw new IllegalArgumentException("Parameters to matchingValues did not match allowed sequence of objects. List of values is length "+values.length+"."); idx += 2; continue; } throw new IllegalArgumentException("Parameters to matchingValues did not match allowed sequence of objects. Incorrect class for parameter # "+idx+"."); } return (qualifiers.size() == 0) ? null : ((qualifiers.size() == 1) ? qualifiers.get(0) : new EOAndQualifier(qualifiers)); } }