package er.extensions.eof;
import java.math.BigDecimal;
import java.util.Locale;
import com.webobjects.eoaccess.EOAttribute;
import com.webobjects.eoaccess.EOModel;
import com.webobjects.eoaccess.EORelationship;
import com.webobjects.eocontrol.EOEnterpriseObject;
import com.webobjects.eocontrol.EOQualifier;
import com.webobjects.eocontrol.EOSortOrdering;
import com.webobjects.foundation.NSArray;
import com.webobjects.foundation.NSKeyValueCodingAdditions;
import com.webobjects.foundation.NSRange;
import com.webobjects.foundation.NSSelector;
import com.webobjects.foundation.NSTimestamp;
import er.extensions.eof.ERXSortOrdering.ERXSortOrderings;
import er.extensions.eof.qualifiers.ERXExistsQualifier;
import er.extensions.foundation.ERXArrayUtilities;
import er.extensions.qualifiers.ERXAndQualifier;
import er.extensions.qualifiers.ERXKeyComparisonQualifier;
import er.extensions.qualifiers.ERXKeyValueQualifier;
import er.extensions.qualifiers.ERXNotQualifier;
import er.extensions.qualifiers.ERXOrQualifier;
import er.extensions.qualifiers.ERXPrefixQualifierTraversal;
import er.extensions.qualifiers.ERXTrueQualifier;
/**
* ERXKey provides a rich wrapper around a keypath. When combined with chainable
* qualifiers, ERXKey provides a starting point for the qualifier chain. As an
* example:
*
* <pre><code>
* public class Person extends ERXGenericRecord {
* ...
* public static final ERXKey<Country> country = new ERXKey<Country>(Person.COUNTRY_KEY);
* public static final ERXKey<NSTimestamp> birthDate = new ERXKey<NSTimestamp>(Person.BIRTH_DATE_KEY);
* ...
* }
*
* Country germany = ...;
* NSTimestamp someRandomDate = ...;
* EOQualifier qualifier = Person.country.is(germany).and(Person.birthDate.after(someRandomDate));
* </code></pre>
*
* @param <T> the type of the value of this key
*
* @author mschrag
*/
public class ERXKey<T> {
/* Constants for known NSArray keypath operators */
private static final ERXKey<BigDecimal> AVG = new ERXKey<BigDecimal>("@avg");
private static final ERXKey<BigDecimal> SUM = new ERXKey<BigDecimal>("@sum");
private static final ERXKey<?> MIN = new ERXKey<Object>("@min");
private static final ERXKey<?> MAX = new ERXKey<Object>("@max");
private static final ERXKey<Integer> COUNT = new ERXKey<Integer>("@count");
/* Constants for Wonder keypath operators */
private static final ERXKey<BigDecimal> AVG_NON_NULL = new ERXKey<BigDecimal>("@avgNonNull");
private static final ERXKey<?> FETCH_SPEC = new ERXKey<Object>("@fetchSpec");
private static final ERXKey<?> FLATTEN = new ERXKey<Object>("@flatten");
private static final ERXKey<Boolean> IS_EMPTY = new ERXKey<Boolean>("@isEmpty");
private static final ERXKey<?> LIMIT = new ERXKey<Object>("@limit");
private static final ERXKey<BigDecimal> MEDIAN = new ERXKey<BigDecimal>("@median");
private static final ERXKey<?> OBJECT_AT_INDEX = new ERXKey<Object>("@objectAtIndex");
private static final ERXKey<BigDecimal> POP_STD_DEV = new ERXKey<BigDecimal>("@popStdDev");
private static final ERXKey<?> REMOVE_NULL_VALUES = new ERXKey<Object>("@removeNullValues");
private static final ERXKey<?> REVERSE = new ERXKey<Object>("@reverse");
private static final ERXKey<?> SORT = new ERXKey<Object>("@sort");
private static final ERXKey<?> SORT_ASC = new ERXKey<Object>("@sortAsc");
private static final ERXKey<?> SORT_DESC = new ERXKey<Object>("@sortDesc");
private static final ERXKey<?> SORT_INSENSITIVE_ASC = new ERXKey<Object>("@sortInsensitiveAsc");
private static final ERXKey<?> SORT_INSENSITIVE_DESC = new ERXKey<Object>("@sortInsensitiveDesc");
private static final ERXKey<BigDecimal> STD_DEV = new ERXKey<BigDecimal>("@stdDev");
private static final ERXKey<?> SUBARRAY_WITH_RANGE = new ERXKey<Object>("@subarrayWithRange");
private static final ERXKey<?> UNIQUE = new ERXKey<Object>("@unique");
/**
* Creates a new ERXKey that prepends the given {@code key} with
* ERXArrayUtilities' {@code @avgNonNull} aggregate operator.
*
* @param key
* the key(path) to the value to be averaged
*
* @return an {@code ERXKey<BigDecimal>} wrapping the
* {@code @avgNonNull.key} keypath
*
* @see er.extensions.foundation.ERXArrayUtilities.AvgNonNullOperator
* AvgNonNullOperator
*/
public static ERXKey<BigDecimal> avgNonNull(ERXKey<?> key) {
return (ERXKey<BigDecimal>) avgNonNull().append(key);
}
/**
* Creates a new ERXKey that wraps ERXArrayUtilities' {@code @avgNonNull}
* aggregate operator.
*
* @return an {@code ERXKey<BigDecimal>} wrapping the {@code @avgNonNull}
* key
*
* @see er.extensions.foundation.ERXArrayUtilities.AvgNonNullOperator
* AvgNonNullOperator
*/
public static ERXKey<BigDecimal> avgNonNull() {
return AVG_NON_NULL;
}
/**
* Creates a new ERXKey that appends ERXArrayUtilities' {@code @avgNonNull}
* aggregate operator and the given {@code key} to this key.
*
* @param key
* the key(path) to the value to be averaged
*
* @return an {@code ERXKey<BigDecimal>} wrapping the
* {@code thisKey.@avgNonNull.key} keypath
*
* @see er.extensions.foundation.ERXArrayUtilities.AvgNonNullOperator
* AvgNonNullOperator
*/
public ERXKey<BigDecimal> atAvgNonNull(ERXKey<?> key) {
return append(ERXKey.avgNonNull(key));
}
/**
* Creates a new ERXKey that appends ERXArrayUtilities' {@code @avgNonNull}
* aggregate operator to this key
*
* @return an {@code ERXKey<BigDecimal>} wrapping the
* {@code thisKey.@avgNonNull} keypath
*
* @see er.extensions.foundation.ERXArrayUtilities.AvgNonNullOperator
* AvgNonNullOperator
*/
public ERXKey<BigDecimal> atAvgNonNull() {
return append(ERXKey.avgNonNull());
}
/**
* Creates a new ERXKey that prepends the {@code key} with
* ERXArrayUtilities' {@code @fetchSpec} operator and the
* {@code fetchSpecName}.
* <p>
* This ERXKey does not perform a fetch itself. It simply makes use of an
* EOFetchSpecification that is defined on the {@code key}'s Entity for its
* qualifier(s) and sortOrdering(s) and uses them to filter and sort the
* values for {@code key}
* <p>
* For example, if the {@code fetchSpecName} is "newHomes" and the
* {@code key} is "price" this will return a new ERXKey wrapping
* "@fetchSpec.newHomes.price".
*
* @param <U>
* the type of the next key
* @param fetchSpecName
* the name of the fetchSpec
* @param key
* the key(path) to the values to be filtered and sorted
* @return an {@code ERXKey<U>} wrapping the
* {@code @fetchSpec.fetchSpecName.key} keypath
*
* @see er.extensions.foundation.ERXArrayUtilities.FetchSpecOperator
* FetchSpecOperator
*/
public static <U> ERXKey<NSArray<U>> fetchSpec(String fetchSpecName, ERXKey<U> key) {
return FETCH_SPEC.append(fetchSpecName).appendAsArray(key);
}
/**
* Creates a new ERXKey that appends ERXArrayUtilities'
* {@code @fetchSpec} operator, the {@code fetchSpecName} and
* the {@code key} to this key.
* <p>
* This ERXKey does not perform a fetch itself. It simply makes use of an
* EOFetchSpecification that is defined on the {@code key}'s Entity for its
* qualifier(s) and sortOrdering(s) and uses them to filter and sort the
* values for {@code key}
* <p>
* For example, if the {@code fetchSpecName} is "newHomes" and the
* {@code key} is "price" this will return a new ERXKey wrapping
* "thisKey.@fetchSpec.newHomes.price".
*
* @param fetchSpecName
* the fetchSpec name
* @param <U>
* the type of the next key
* @param key
* the key to use for this keypath
*
* @return an {@code ERXKey<NSArray<U>>} wrapping the
* {@code thisKey.@fetchSpec.fetchSpecName.key} keypath
*
* @see er.extensions.foundation.ERXArrayUtilities.FetchSpecOperator
* FetchSpecOperator
*/
public <U> ERXKey<NSArray<U>> atFetchSpec(String fetchSpecName, ERXKey<U> key) {
return append(ERXKey.fetchSpec(fetchSpecName, key));
}
/**
* Creates a new ERXKey that appends the {@code fetchSpecName} to
* ERXArrayUtilities' {@code @fetchSpec} operator.
* <p>
* This ERXKey does not perform a fetch itself. It simply makes use of an
* EOFetchSpecification that is defined on the {@code key}'s Entity for its
* qualifier(s) and sortOrdering(s) and uses them to filter and sort the
* values for {@code key}
* <p>
* For example, if the {@code fetchSpecName} is "newHomes" this will return
* a new ERXKey wrapping "@fetchSpec.newHomes".
*
* @param fetchSpecName
* the fetchSpec name
* @param <U>
* the type of the next key
*
* @return an {@code ERXKey<U>} wrapping the
* {@code @fetchSpec.fetchSpecName} keypath
*
* @see er.extensions.foundation.ERXArrayUtilities.FetchSpecOperator
* FetchSpecOperator
*/
public static <U> ERXKey<U> fetchSpec(String fetchSpecName) {
return FETCH_SPEC.append(fetchSpecName);
}
/**
* Creates a new ERXKey that appends ERXArrayUtilities' {@code @fetchSpec}
* operator and the {@code fetchSpecName} to this key.
* <p>
* This ERXKey does not perform a fetch itself. It simply makes use of an
* EOFetchSpecification that is defined on the {@code key}'s Entity for its
* qualifier(s) and sortOrdering(s) and uses them to filter and sort the
* values for {@code key}
* <p>
* For example, if the {@code fetchSpecName} is "newHomes" this will return
* a new ERXKey wrapping {@code thisKey.@fetchSpec.newHomes} keypath
*
* @param fetchSpecName
* the fetchSpec name
* @param <U>
* the type of the next key
*
* @return an {@code ERXKey<U>} wrapping the
* {@code thisKey.@fetchSpec.fetchSpecName} keypath
*
* @see er.extensions.foundation.ERXArrayUtilities.FetchSpecOperator
* FetchSpecOperator
*/
public <U> ERXKey<U> atFetchSpec(String fetchSpecName) {
return (ERXKey<U>) append(ERXKey.fetchSpec(fetchSpecName));
}
/**
* <b>Will flatten an array of arrays or a key it is appended to</b>
* <p>
* Creates a new ERXKey that prepends the {@code key} with
* ERXArrayUtilities' {@code @flatten} operator. The {@code key} should
* resolve to an {@code NSArray<U>} when used.
* <p>
* <b>Note:</b> the {@code @flatten} operator is applied to the array it is
* called on or the key immediately preceding it, not the key (if any)
* following it. This method is useful for flattening an existing array or
* key that is already included in a keypath.
* <p>
* For example, if you are chaining ERXKeys such as
* {@code Customer.ORDERS.dot(Order.ORDER_LINES)} which if called on a
* Customer would return an {@code NSArray<NSArray<OrderLine>>}, you can add
* dot(ERXKey.flatten(OrderLine.PRICE) to get a new ERXKey wrapping the
* {@code orders.orderlines.@flatten.price}, which will return an array of
* prices when called on any Customer object.
*
* @param <U>
* the type of the next key
* @param key
* the key <b>following</b> the key to be flattened
*
* @return an {@code ERXKey<U>} wrapping the {@code @flatten.key} keypath
*
* @see er.extensions.foundation.ERXArrayUtilities.FlattenOperator
* FlattenOperator
*/
public static <U> ERXKey<NSArray<U>> flatten(ERXKey<U> key) {
return FLATTEN.appendAsArray(key);
}
/**
* <b>Flattens this key</b>
* <p>
* Creates a new ERXKey that appends ERXArrayUtilities' {@code @flatten}
* operator and the {@code key} to this key. The {@code key} should resolve
* to an {@code NSArray<U>} when used.
* <p>
* <b>Note:</b> the {@code @flatten} operator will be applied to this key,
* not the key specified by the {@code key} parameter.
* <p>
* For example, if the {@code key} is "price" this will return a new ERXKey
* wrapping the {@code thisKey.@flatten.price} keypath.
*
* @param <U>
* the type of the next key
* @param key
* the following key
*
* @return an {@code ERXKey<U>} wrapping the {@code thisKey.@flatten.key}
* keypath
*
* @see er.extensions.foundation.ERXArrayUtilities.FlattenOperator
* FlattenOperator
*/
public <U> ERXKey<NSArray<U>> atFlatten(ERXKey<U> key) {
return append(ERXKey.flatten(key));
}
/**
* <b>Will flatten an array of arrays or a key it is appended to</b>
* <p>
* Creates a new ERXKey that wraps ERXArrayUtilities' {@code @flatten}
* aggregate operator.
*
* @param <U>
* the type of the next key
*
* @return an ERXKey wrapping the {@code @flatten} key
*
* @see er.extensions.foundation.ERXArrayUtilities.FlattenOperator
* FlattenOperator
*/
public static <U> ERXKey<U> flatten() {
return (ERXKey<U>) FLATTEN;
}
/**
* <b>Flattens this key</b>
* <p>
* Creates a new ERXKey that appends ERXArrayUtilities'
* {@code @flatten} operator to this key.
*
* @return an {@code ERXKey<U>} wrapping the {@code thisKey.@flatten}
* keypath
*
* @see er.extensions.foundation.ERXArrayUtilities.FlattenOperator
* FlattenOperator
*/
public ERXKey<T> atFlatten() {
return append(ERXKey.flatten());
}
/**
* <b>Checks an array or a key it is appended to to</b>
* <p>
* Creates a new ERXKey that wraps ERXArrayUtilities' {@code @isEmpty}
* aggregate operator.
* <p>
* <b>Note:</b> any key(path) following {@code @isEmpty} is ignored.
*
* @return an {@code ERXKey<Boolean>} wrapping the {@code @isEmpty} key
*
* @see er.extensions.foundation.ERXArrayUtilities.IsEmptyOperator
* IsEmptyOperator
*/
public static ERXKey<Boolean> isEmpty() {
return IS_EMPTY;
}
/**
* <b>Checks this key.</b>
* <p>
* Creates a new ERXKey that appends this key with ERXArrayUtilities'
* {@code @isEmpty} operator.
* <p>
* <b>Note:</b> any key(path) following {@code @isEmpty} is ignored.
*
* @return an {@code ERXKey<Boolean>} wrapping the {@code thisKey.@isEmpty}
* keypath
*
* @see er.extensions.foundation.ERXArrayUtilities.IsEmptyOperator
* IsEmptyOperator
*/
public ERXKey<Boolean> atIsEmpty() {
return append(ERXKey.isEmpty());
}
/**
* <b>Limits the size of the array it is called on or the key it is appended
* to.</b>
* <p>
* Creates a new ERXKey that appends ERXArrayUtilities' {@code @limit}
* operator and then the {@code limit} quantity and then the {@code key},
* which should resolve to an {@code NSArray<U>} when used.
* <p>
* <b>Note:</b> the {@code @limit} operator will be applied to the array it
* is called on or the key immediately preceding it, not the key specified
* by the {@code key} parameter.
* <p>
* For example, if the {@code key} is "price" and limit is 3 this will
* return a new ERXKey {@code @limit.3.price}.
*
* @param <U>
* the type of the next key
* @param limit
* the maximum number of objects allowed by the limit
* @param key
* the key following the key to be limited
*
* @return an {@code ERXKey<NSArray<U>>} wrapping the
* {@code @limit.quantity.key} keypath
*
* @see er.extensions.foundation.ERXArrayUtilities.LimitOperator
* LimitOperator
*/
public static <U> ERXKey<NSArray<U>> limit(Integer limit, ERXKey<U> key) {
return LIMIT.append(limit.toString()).appendAsArray(key);
}
/**
* Creates a new ERXKey that appends this key with ERXArrayUtilities'
* {@code @limit} operator and then the {@code limit} quantity and then the
* {@code key}, which should resolve to an {@code NSArray<U>} when used.
* <p>
* <b>Note:</b> the {@code @limit} operator will be applied to this key not
* the key specified by the {@code key} parameter.
* <p>
* For example, if the {@code key} is "price" and limit is 3 this will
* return a new ERXKey {@code thiskey.@limit.3.price}.
*
* @param <U>
* the type of the next key
* @param limit
* the maximum number of objects allowed by the limit
* @param key
* the key following the key to be limited
*
* @return an {@code ERXKey<NSArray<U>>} wrapping the
* {@code thisKey.@limit.quantity.key} keypath
*
* @see er.extensions.foundation.ERXArrayUtilities.LimitOperator
* LimitOperator
*/
public <U> ERXKey<NSArray<U>> atLimit(Integer limit, ERXKey<U> key) {
return append(ERXKey.limit(limit , key));
}
/**
* <b>Limits the size of the array it is called on or the key it is appended
* to.</b>
* <p>
* Creates a new ERXKey that appends ERXArrayUtilities' {@code @limit}
* operator and then the {@code limit} quantity.
* <p>
* <b>Note:</b> the {@code @limit} operator will be applied to the array it
* is called on or the key immediately preceding it, not the key (if any)
* following it.
* <p>
* For example, if the {@code key} is "price" and limit is 3 this will
* return a new ERXKey {@code @limit.3}.
*
* @param limit
* the maximum number of objects allowed by the limit
* @param <U>
* the type of the next key
*
* @return an {@code ERXKey<NSArray<U>>} wrapping the
* {@code @limit.quantity} keypath
*
* @see er.extensions.foundation.ERXArrayUtilities.LimitOperator
* LimitOperator
*/
public static <U> ERXKey<U> limit(Integer limit) {
return LIMIT.append(limit.toString());
}
/**
* Creates a new ERXKey that appends this key with ERXArrayUtilities'
* {@code @limit} operator and then the {@code limit} quantity.
* <p>
* <b>Note:</b> the {@code @limit} operator will be applied to this key not
* the key specified by the {@code key} parameter.
* <p>
* For example, if the {@code key} is "price" and limit is 3 this will
* return a new ERXKey {@code thiskey.@limit.3}.
*
* @param limit
* the maximum number of objects allowed by the limit
*
* @return an {@code ERXKey<NSArray<U>>} wrapping the
* {@code thisKey.@limit.quantity} keypath
*
* @see er.extensions.foundation.ERXArrayUtilities.LimitOperator
* LimitOperator
*/
public ERXKey<T> atLimit(Integer limit) {
return append(ERXKey.limit(limit));
}
/**
* Creates a new ERXKey that wraps ERXArrayUtilities' {@code @median}
* aggregate operator.
*
* @return an {@code ERXKey<BigDecimal>} wrapping the {@code @median}
* key
*
* @see er.extensions.foundation.ERXArrayUtilities.MedianOperator
* MedianOperator
*/
public static ERXKey<BigDecimal> median() {
return MEDIAN;
}
/**
* Creates a new ERXKey that appends the given {@code key} to
* ERXArrayUtilities' {@code @median} aggregate operator.
*
* @param key
* the key(path) to the value to be averaged
*
* @return an {@code ERXKey<BigDecimal>} wrapping the {@code @median.key}
* keypath
*
* @see er.extensions.foundation.ERXArrayUtilities.MedianOperator
* MedianOperator
*/
public static ERXKey<BigDecimal> median(ERXKey<?> key) {
return (ERXKey<BigDecimal>) MEDIAN.append(key);
}
/**
* Creates a new ERXKey that appends this key with ERXArrayUtilities'
* {@code @median} aggregate operator
*
* @return an {@code ERXKey<BigDecimal>} wrapping the
* {@code thisKey.@median} keypath
*
* @see er.extensions.foundation.ERXArrayUtilities.MedianOperator
* MedianOperator
*/
public ERXKey<BigDecimal> atMedian() {
return append(ERXKey.median());
}
/**
* Creates a new ERXKey that appends this key with ERXArrayUtilities'
* {@code @median} aggregate operator and then appends the given
* {@code key}.
*
* @param key
* the key(path) to the value to be averaged
*
* @return an {@code ERXKey<BigDecimal>} wrapping the
* {@code thisKey.@median.key} keypath
*
* @see er.extensions.foundation.ERXArrayUtilities.MedianOperator MedianOperator
*/
public ERXKey<BigDecimal> atMedian(ERXKey<?> key) {
return append(ERXKey.median(key));
}
/**
* Return a new ERXKey that prepends the given key with ERXArrayUtilities'
* objectAtIndex operator {@code @objectAtIndex}. For instance, if the index is 3
* and the key is "price" then this will return a new ERXKey "@objectAtIndex.3.price".
*
* @param <U> the type of the next key
* @param index The index of the object to return from the array
* @param key the key following the operator
* @return the new appended key
*
* @see er.extensions.foundation.ERXArrayUtilities.ObjectAtIndexOperator ObjectAtIndexOperator
*/
public static <U> ERXKey<U> objectAtIndex(Integer index, ERXKey<U> key) {
return OBJECT_AT_INDEX.append(index.toString()).append(key);
}
/**
* Return a new ERXKey that prepends the given key with ERXArrayUtilities'
* objectAtIndex operator {@code @objectAtIndex}. For instance, if the index is 3
* and the key is "price" then this will return a new ERXKey "@objectAtIndex.3.price".
*
* @param <U> the type of the next key
* @param index The index of the object to return from the array
* @param key the key following the operator
* @return the new appended key
*
* @see er.extensions.foundation.ERXArrayUtilities.ObjectAtIndexOperator ObjectAtIndexOperator
*/
public <U> ERXKey<U> atObjectAtIndex(Integer index, ERXKey<U> key) {
return append(ERXKey.objectAtIndex(index , key));
}
/**
* Return a new ERXKey that prepends the given key with ERXArrayUtilities'
* objectAtIndex operator {@code @objectAtIndex}. For instance, if the index is 3
* then this will return a new ERXKey "@objectAtIndex.3".
*
* @param <U> the type of the next key
* @param index The index of the object to return from the array
* @return the new appended key
*
* @see er.extensions.foundation.ERXArrayUtilities.ObjectAtIndexOperator ObjectAtIndexOperator
*/
public static <U> ERXKey<U> objectAtIndex(Integer index) {
return OBJECT_AT_INDEX.append(index.toString());
}
/**
* Return a new ERXKey that prepends the given key with ERXArrayUtilities'
* objectAtIndex operator {@code @objectAtIndex}. For instance, if the index is 3
* then this will return a new ERXKey "@objectAtIndex.3".
*
* @param index The index of the object to return from the array
* @return the new appended key
*
* @see er.extensions.foundation.ERXArrayUtilities.ObjectAtIndexOperator ObjectAtIndexOperator
*/
public ERXKey<T> atObjectAtIndex(Integer index) {
return append(ERXKey.objectAtIndex(index));
}
/**
* Return a new ERXKey that prepends the given key with ERXArrayUtilities'
* RemoveNullValues operator {@code @removeNullValues}. For instance, if the key is "price"
* this will return a new ERXKey "@removeNullValues.price".
* @param key the key to use for this keypath
* @param <U> the type of the next key
*
* @return the new appended key
*
* @see er.extensions.foundation.ERXArrayUtilities.RemoveNullValuesOperator RemoveNullValuesOperator
*/
public static <U> ERXKey<U> removeNullValues(ERXKey<U> key) {
return REMOVE_NULL_VALUES.append(key);
}
/**
* Return a new ERXKey that prepends the given key with ERXArrayUtilities'
* RemoveNullValues operator {@code @removeNullValue}s. For instance, if the key is "price"
* this will return a new ERXKey "@removeNullValues.price".
* @param key the key to use for this keypath
* @param <U> the type of the next key
*
* @return the new appended key
*
* @see er.extensions.foundation.ERXArrayUtilities.RemoveNullValuesOperator RemoveNullValuesOperator
*/
public <U> ERXKey<U> atRemoveNullValues(ERXKey<U> key) {
return append(ERXKey.removeNullValues(key));
}
/**
* Return a new ERXKey that uses ERXArrayUtilities' remove null values operator {@code @removeNullValues}.
*
* @param <U> the type of the next key
*
* @return the new appended key
*
* @see er.extensions.foundation.ERXArrayUtilities.RemoveNullValuesOperator RemoveNullValuesOperator
*/
public static <U> ERXKey<U> removeNullValues() {
return (ERXKey<U>) REMOVE_NULL_VALUES;
}
/**
* Return a new ERXKey that prepends the given key with ERXArrayUtilities'
* RemoveNullValues operator {@code @removeNullValues}.
*
* @return the new appended key
*
* @see er.extensions.foundation.ERXArrayUtilities.RemoveNullValuesOperator RemoveNullValuesOperator
*/
public ERXKey<T> atRemoveNullValues() {
return append(ERXKey.removeNullValues());
}
/**
* Return a new ERXKey that prepends the given key with ERXArrayUtilities'
* Reverse operator @reverse. For instance, if the key is "price"
* this will return a new ERXKey "@reverse.price".
* @param key the key to use for this keypath
* @param <U> the type of the next key
*
* @return the new appended key
*
* @see er.extensions.foundation.ERXArrayUtilities.ReverseOperator ReverseOperator
*/
public static <U> ERXKey<NSArray<U>> reverse(ERXKey<U> key) {
return REVERSE.appendAsArray(key);
}
/**
* Return a new ERXKey that prepends the given key with ERXArrayUtilities'
* Reverse operator {@code @reverse}. For instance, if the key is "price"
* this will return a new ERXKey "@reverse.price".
* @param key the key to use for this keypath
* @param <U> the type of the next key
*
* @return the new appended key
*
* @see er.extensions.foundation.ERXArrayUtilities.ReverseOperator ReverseOperator
*/
public <U> ERXKey<NSArray<U>> atReverse(ERXKey<U> key) {
return append(ERXKey.reverse(key));
}
/**
* Return a new ERXKey that uses ERXArrayUtilities' reverse operator {@code @reverse}.
*
* @param <U> the type of the next key
*
* @return the new appended key
*
* @see er.extensions.foundation.ERXArrayUtilities.ReverseOperator ReverseOperator
*/
public static <U> ERXKey<U> reverse() {
return (ERXKey<U>) REVERSE;
}
/**
* Return a new ERXKey that prepends the given key with ERXArrayUtilities'
* Reverse operator @reverse.
*
* @return the new appended key
*
* @see er.extensions.foundation.ERXArrayUtilities.ReverseOperator ReverseOperator
*/
public ERXKey<T> atReverse() {
return append(ERXKey.reverse());
}
/**
* Return a new ERXKey that prepends the given key with ERXArrayUtilities'
* Sort operator {@code @sort}. For instance,
* <code>sort(Employee.FIRST_NAME, Employee.LAST_NAME)</code>
* would return a key like {@code @sort.firstName,lastname}.
*
* @param sortKeys the ERXKeys to append for sorting
* @param <U> the type of the next key
*
* @return the new appended key
*
* @see er.extensions.foundation.ERXArrayUtilities.SortOperator SortOperator
*/
public static <U> ERXKey<U> sort(ERXKey<?> ... sortKeys) {
NSArray<String> keyArray = (NSArray<String>) new NSArray<ERXKey<?>>(sortKeys).valueForKey("key");
return SORT.append(keyArray.componentsJoinedByString(","));
}
/**
* Return a new ERXKey that prepends the given key with ERXArrayUtilities'
* Sort operator {@code @sort}. For instance,
* <code>atSort(Employee.FIRST_NAME, Employee.LAST_NAME)</code>
* would return a key like {@code @sort.firstName,lastname}.
*
* @param sortKeys the ERXKeys to append for sorting
*
* @return the new appended key
*
* @see er.extensions.foundation.ERXArrayUtilities.SortOperator SortOperator
*/
public ERXKey<T> atSort(ERXKey<?> ... sortKeys) {
return append(ERXKey.sort(sortKeys));
}
/**
* Return a new ERXKey that prepends the given key with ERXArrayUtilities'
* SortAscending operator {@code @sortAsc}. For instance,
* <code>sortAsc(Employee.FIRST_NAME, Employee.LAST_NAME)</code>
* would return a key like {@code @sortAsc.firstName,lastname}.
*
* @param sortKeys the ERXKeys to append for sorting
* @param <U> the type of the next key
*
* @return the new appended key
*
* @see er.extensions.foundation.ERXArrayUtilities.SortOperator SortOperator
*/
public static <U> ERXKey<U> sortAsc(ERXKey<?> ... sortKeys) {
NSArray<String> keyArray = (NSArray<String>) new NSArray<ERXKey<?>>(sortKeys).valueForKey("key");
return SORT_ASC.append(keyArray.componentsJoinedByString(","));
}
/**
* Return a new ERXKey that prepends the given key with ERXArrayUtilities'
* SortAsc operator {@code @sortAsc}. For instance,
* <code>atSortAsc(Employee.FIRST_NAME, Employee.LAST_NAME)</code>
* would return a key like {@code @sortAsc.firstName,lastname}.
*
* @param sortKeys the ERXKeys to append for sorting
*
* @return the new appended key
*
* @see er.extensions.foundation.ERXArrayUtilities.SortOperator SortOperator
*/
public ERXKey<T> atSortAsc(ERXKey<?> ... sortKeys) {
return append(ERXKey.sortAsc(sortKeys));
}
/**
* Return a new ERXKey that prepends the given key with ERXArrayUtilities'
* SortDescending operator {@code @sortDesc}. For instance,
* <code>sortDesc(Employee.FIRST_NAME, Employee.LAST_NAME)</code>
* would return a key like {@code @sortDesc.firstName,lastname}.
*
* @param sortKeys the ERXKeys to append for sorting
* @param <U> the type of the next key
*
* @return the new appended key
*
* @see er.extensions.foundation.ERXArrayUtilities.SortOperator SortOperator
*/
public static <U> ERXKey<U> sortDesc(ERXKey<?> ... sortKeys) {
NSArray<String> keyArray = (NSArray<String>) new NSArray<ERXKey<?>>(sortKeys).valueForKey("key");
return SORT_DESC.append(keyArray.componentsJoinedByString(","));
}
/**
* Return a new ERXKey that prepends the given key with ERXArrayUtilities'
* SortDescending operator {@code @sortDesc}. For instance,
* <code>atSortDesc(Employee.FIRST_NAME, Employee.LAST_NAME)</code>
* would return a key like {@code @sortDesc.firstName,lastname}.
*
* @param sortKeys the ERXKeys to append for sorting
*
* @return the new appended key
*
* @see er.extensions.foundation.ERXArrayUtilities.SortOperator SortOperator
*/
public ERXKey<T> atSortDesc(ERXKey<?> ... sortKeys) {
return append(ERXKey.sortDesc(sortKeys));
}
/**
* Return a new ERXKey that prepends the given key with ERXArrayUtilities'
* SortInsensitiveAscending operator {@code @sortInsensitiveAsc}. For instance,
* <code>sortInsensitiveAsc(Employee.FIRST_NAME, Employee.LAST_NAME)</code>
* would return a key like {@code @sortInsensitiveAsc.firstName,lastname}.
*
* @param sortKeys the ERXKeys to append for sorting
* @param <U> the type of the next key
*
* @return the new appended key
*
* @see er.extensions.foundation.ERXArrayUtilities.SortOperator SortOperator
*/
public static <U> ERXKey<U> sortInsensitiveAsc(ERXKey<?> ... sortKeys) {
NSArray<String> keyArray = (NSArray<String>) new NSArray<ERXKey<?>>(sortKeys).valueForKey("key");
return SORT_INSENSITIVE_ASC.append(keyArray.componentsJoinedByString(","));
}
/**
* Return a new ERXKey that prepends the given key with ERXArrayUtilities'
* SortInsensitiveAscending operator {@code @sortInsensitiveAsc}. For instance,
* <code>atSortInsensitiveAsc(Employee.FIRST_NAME, Employee.LAST_NAME)</code>
* would return a key like {@code @sortInsensitiveAsc.firstName,lastname}.
*
* @param sortKeys the ERXKeys to append for sorting
*
* @return the new appended key
*
* @see er.extensions.foundation.ERXArrayUtilities.SortOperator SortOperator
*/
public ERXKey<T> atSortInsensitiveAsc(ERXKey<?> ... sortKeys) {
return append(ERXKey.sortInsensitiveAsc(sortKeys));
}
/**
* Return a new ERXKey that prepends the given key with ERXArrayUtilities'
* SortInsensitiveDescending operator {@code @sortInsensitiveDesc}. For instance,
* <code>sortInsensitiveDesc(Employee.FIRST_NAME, Employee.LAST_NAME)</code>
* would return a key like {@code @sortInsensitiveDesc.firstName,lastname}.
*
* @param sortKeys the ERXKeys to append for sorting
* @param <U> the type of the next key
*
* @return the new appended key
*
* @see er.extensions.foundation.ERXArrayUtilities.SortOperator SortOperator
*/
public static <U> ERXKey<U> sortInsensitiveDesc(ERXKey<?> ... sortKeys) {
NSArray<String> keyArray = (NSArray<String>) new NSArray<ERXKey<?>>(sortKeys).valueForKey("key");
return SORT_INSENSITIVE_DESC.append(keyArray.componentsJoinedByString(","));
}
/**
* Return a new ERXKey that prepends the given key with ERXArrayUtilities'
* SortInsensitiveDescending operator {@code sortInsensitiveDesc}. For instance,
* <code>atSortInsensitiveDesc(Employee.FIRST_NAME, Employee.LAST_NAME)</code>
* would return a key like {@code sortInsensitiveDesc.firstName,lastname}
*
* @param sortKeys the ERXKeys to append for sorting
*
* @return the new appended key
*
* @see er.extensions.foundation.ERXArrayUtilities.SortOperator SortOperator
*/
public ERXKey<T> atSortInsensitiveDesc(ERXKey<?> ... sortKeys) {
return append(ERXKey.sortInsensitiveDesc(sortKeys));
}
/**
* Return a new ERXKey that prepends the given key with ERXArrayUtilities'
* SubarrayWithRange operator {@code subarrayWithRange}. For instance, if the key is "price"
* and the range is <code>new NSRange(4,2)</code> this will return a new ERXKey {@code @subarrayWithRange.4-2.price}.
*
* @param key the key to use for this keypath
* @param range the range for the operator
* @param <U> the type of the next key
*
* @return the new appended key
*
* @see er.extensions.foundation.ERXArrayUtilities.SubarrayWithRangeOperator SubarrayWithRangeOperator
*/
public static <U> ERXKey<NSArray<U>> subarrayWithRange(NSRange range, ERXKey<U> key) {
return SUBARRAY_WITH_RANGE.append(range.location() + "-" + range.length()).appendAsArray(key);
}
/**
* Return a new ERXKey that prepends the given key with ERXArrayUtilities'
* SubarrayWithRange operator {@code subarrayWithRange}. For instance, if the key is "price"
* and the range is <code>new NSRange(4,2)</code> this will return a new ERXKey {@code subarrayWithRange.4-2.price}.
*
* @param key the key to use for this keypath
* @param range the range for the operator
* @param <U> the type of the next key
*
* @return the new appended key
*
* @see er.extensions.foundation.ERXArrayUtilities.SubarrayWithRangeOperator SubarrayWithRangeOperator
*/
public <U> ERXKey<NSArray<U>> atSubarrayWithRange(NSRange range, ERXKey<U> key) {
return append(ERXKey.subarrayWithRange(range , key));
}
/**
* Return a new ERXKey that prepends the given key with ERXArrayUtilities'
* SubarrayWithRange operator {@code subarrayWithRange}. For instance, if the range
* is <code>new NSRange(4,2)</code> this will return a new ERXKey {@code subarrayWithRange.4-2.price}.
*
* @param range the range for the operator
* @param <U> the type of the next key
*
* @return the new appended key
*
* @see er.extensions.foundation.ERXArrayUtilities.SubarrayWithRangeOperator SubarrayWithRangeOperator
*/
public static <U> ERXKey<U> subarrayWithRange(NSRange range) {
return SUBARRAY_WITH_RANGE.append(range.location() + "-" + range.length());
}
/**
* Return a new ERXKey that prepends the given key with ERXArrayUtilities'
* SubarrayWithRange operator {@code subarrayWithRange}. For instance, if the range
* is <code>new NSRange(4,2)</code> this will return a new ERXKey {@code subarrayWithRange.4-2.price}.
*
* @param range the range for the operator
*
* @return the new appended key
*
* @see er.extensions.foundation.ERXArrayUtilities.SubarrayWithRangeOperator SubarrayWithRangeOperator
*/
public ERXKey<T> atSubarrayWithRange(NSRange range) {
return append(ERXKey.subarrayWithRange(range));
}
/**
* <b>Will filter an array or a key it is appended to</b>
* <p>
* Creates a new ERXKey that appends ERXArrayUtilities' {@code @unique}
* operator with the {@code key}, which should resolve to an NSArray<U> when
* used.
* <p>
* <b>Note:</b> the {@code @unique} operator is applied to the array it is
* called on or the key immediately preceding it, not the key (if any)
* following it. This method is useful for flattening an existing array or
* key that is already included in a keypath.
* <p>
* For example, if the {@code key} is "price" this will return a new ERXKey
* wrapping the {@code @unique.price} keypath.
*
* @param <U>
* the type of the next key
* @param key
* the key <b>following</b> the key to be flattened
*
* @return an {@code ERXKey<U>} wrapping the {@code @unique.key} keypath
*
* @see er.extensions.foundation.ERXArrayUtilities.FlattenOperator
* FlattenOperator
*/
public static <U> ERXKey<NSArray<U>> unique(ERXKey<U> key) {
return UNIQUE.appendAsArray(key);
}
/**
* <b>Filters for unique values for this key</b>
* <p>
* Creates a new ERXKey that appends this key with ERXArrayUtilities'
* {@code @unique} operator and then with the {@code key}, which should
* resolve to an {@code NSArray<U>} when used.
* <p>
* <b>Note:</b> the {@code @unique} operator will be applied to this key,
* not the key specified by the {@code key} parameter.
* <p>
* For example, if the {@code key} is "price" this will return a new ERXKey
* wrapping the {@code thisKey.@unique.price} keypath.
*
* @param <U>
* the type of the next key
* @param key
* the key following the key to be flattened
*
* @return an {@code ERXKey<U>} wrapping the {@code thisKey.@flatten.key}
* keypath
*
* @see er.extensions.foundation.ERXArrayUtilities.FlattenOperator
* FlattenOperator
*/
public <U> ERXKey<NSArray<U>> atUnique(ERXKey<U> key) {
return append(ERXKey.unique(key));
}
/**
* <b>Filters the array it is called on or the key it is appended
* to.</b>
* <p>
* Creates a new ERXKey that wraps ERXArrayUtilities' {@code @unique}
* aggregate operator.
*
* @param <U>
* the type of the next key
*
* @return an ERXKey wrapping the {@code @unique} key
*
* @see er.extensions.foundation.ERXArrayUtilities.UniqueOperator
* UniqueOperator
*/
public static <U> ERXKey<U> unique() {
return (ERXKey<U>) UNIQUE;
}
/**
* <b>Filters for unique values for this key</b>
* <p>
* Creates a new ERXKey that appends this key with ERXArrayUtilities'
* {@code @unique} operator.
*
* @return an {@code ERXKey<U>} wrapping the {@code thisKey.@unique}
* keypath
*
* @see er.extensions.foundation.ERXArrayUtilities.UniqueOperator
* UniqueOperator
*/
public ERXKey<T> atUnique() {
return append(ERXKey.unique());
}
/**
* Creates a new ERXKey that appends the given {@code key} to NSArray's
* {@code @sum} aggregate operator.
*
* @param key
* the key(path) to the value to be summed
*
* @return an {@code ERXKey<BigDecimal>} wrapping the {@code @sum.key}
* keypath
*/
public static ERXKey<BigDecimal> sum(ERXKey<?> key) {
return (ERXKey<BigDecimal>) SUM.append(key);
}
/**
* Creates a new ERXKey that appends this key with NSArray's {@code @sum}
* aggregate operator and then appends the given {@code key}.
*
* @param key
* the key(path) to the value to be summed
*
* @return an {@code ERXKey<BigDecimal>} wrapping the
* {@code thisKey.@sum.key} keypath
*/
public ERXKey<BigDecimal> atSum(ERXKey<?> key) {
return append(ERXKey.sum(key));
}
/**
* Creates a new ERXKey that appends this key with NSArray's {@code @sum}
* aggregate operator
*
* @return an {@code ERXKey<BigDecimal>} wrapping the {@code thisKey.@sum}
* keypath
*/
public ERXKey<BigDecimal> atSum() {
return append(ERXKey.sum());
}
/**
* Creates a new ERXKey that wraps NSArray's {@code @sum} aggregate
* operator.
*
* @return an {@code ERXKey<BigDecimal>} wrapping the {@code @sum} key
*/
public static ERXKey<BigDecimal> sum() {
return SUM;
}
/**
* Creates a new ERXKey that wraps ERXArrayUtilities' {@code @popStdDev}
* aggregate operator.
*
* @return an {@code ERXKey<BigDecimal>} wrapping the {@code @popStdDev} key
*
* @see er.extensions.foundation.ERXArrayUtilities.StandardDeviationOperator
* StandardDeviationOperator
*/
public static ERXKey<BigDecimal> popStdDev() {
return POP_STD_DEV;
}
/**
* Creates a new ERXKey that appends this key with ERXArrayUtilities'
* {@code @popStdDev} aggregate operator
*
* @return an {@code ERXKey<BigDecimal>} wrapping the
* {@code thisKey.@popStdDev} keypath
*
* @see er.extensions.foundation.ERXArrayUtilities.StandardDeviationOperator
* StandardDeviationOperator
*/
public ERXKey<BigDecimal> atPopStdDev() {
return append(ERXKey.popStdDev());
}
/**
* Creates a new ERXKey that appends the given {@code key} to
* ERXArrayUtilities' {@code @popStdDev} aggregate operator.
*
* @param key
* the key(path) to the values used to derive the standard deviation
*
* @return an {@code ERXKey<BigDecimal>} wrapping the {@code @popStdDev.key}
* keypath
*
* @see er.extensions.foundation.ERXArrayUtilities.StandardDeviationOperator
* StandardDeviationOperator
*/
public static ERXKey<BigDecimal> popStdDev(ERXKey<?> key) {
return (ERXKey<BigDecimal>) popStdDev().append(key);
}
/**
* Creates a new ERXKey that appends this key with ERXArrayUtilities'
* {@code @popStdDev} aggregate operator and then appends the given {@code key}
* .
*
* @param key
* the key(path) to the values used to derive the standard deviation
*
* @return an {@code ERXKey<BigDecimal>} wrapping the
* {@code thisKey.@popStdDev.key} keypath
*
* @see er.extensions.foundation.ERXArrayUtilities.StandardDeviationOperator
* StandardDeviationOperator
*/
public ERXKey<BigDecimal> atPopStdDev(ERXKey<?> key) {
return append(ERXKey.popStdDev(key));
}
/**
* Creates a new ERXKey that wraps ERXArrayUtilities' {@code @stdDev}
* aggregate operator.
*
* @return an {@code ERXKey<BigDecimal>} wrapping the {@code @stdDev} key
*
* @see er.extensions.foundation.ERXArrayUtilities.StandardDeviationOperator
* StandardDeviationOperator
*/
public static ERXKey<BigDecimal> stdDev() {
return STD_DEV;
}
/**
* Creates a new ERXKey that appends this key with ERXArrayUtilities'
* {@code @stdDev} aggregate operator
*
* @return an {@code ERXKey<BigDecimal>} wrapping the
* {@code thisKey.@stdDev} keypath
*
* @see er.extensions.foundation.ERXArrayUtilities.StandardDeviationOperator
* StandardDeviationOperator
*/
public ERXKey<BigDecimal> atStdDev() {
return append(ERXKey.stdDev());
}
/**
* Creates a new ERXKey that appends the given {@code key} to
* ERXArrayUtilities' {@code @stdDev} aggregate operator.
*
* @param key
* the key(path) to the values used to derive the standard deviation
*
* @return an {@code ERXKey<BigDecimal>} wrapping the {@code @stdDev.key}
* keypath
*
* @see er.extensions.foundation.ERXArrayUtilities.StandardDeviationOperator
* StandardDeviationOperator
*/
public static ERXKey<BigDecimal> stdDev(ERXKey<?> key) {
return (ERXKey<BigDecimal>)stdDev().append(key);
}
/**
* Creates a new ERXKey that appends this key with ERXArrayUtilities'
* {@code @stdDev} aggregate operator and then appends the given {@code key}
* .
*
* @param key
* the key(path) to the values used to derive the standard deviation
*
* @return an {@code ERXKey<BigDecimal>} wrapping the
* {@code thisKey.@stdDev.key} keypath
*
* @see er.extensions.foundation.ERXArrayUtilities.StandardDeviationOperator
* StandardDeviationOperator
*/
public ERXKey<BigDecimal> atStdDev(ERXKey<?> key) {
return append(ERXKey.stdDev(key));
}
/**
* Creates a new ERXKey that appends the given {@code key} to NSArray's
* {@code @avg} aggregate operator.
*
* @param key
* the key(path) to the value to be averaged
*
* @return an {@code ERXKey<BigDecimal>} wrapping the {@code @avg.key}
* keypath
*/
public static ERXKey<BigDecimal> avg(ERXKey<?> key) {
return (ERXKey<BigDecimal>) AVG.append(key);
}
/**
* Creates a new ERXKey that appends this key with NSArray's {@code @avg}
* aggregate operator and then appends the given {@code key}.
*
* @param key
* the key(path) to the value to be averaged
*
* @return an {@code ERXKey<BigDecimal>} wrapping the
* {@code thisKey.@avg.key} keypath
*/
public ERXKey<BigDecimal> atAvg(ERXKey<?> key) {
return append(ERXKey.avg(key));
}
/**
* Creates a new ERXKey that wraps NSArray's {@code @avg} aggregate
* operator.
*
* @return an {@code ERXKey<BigDecimal>} wrapping the {@code @avg} key
*/
public static ERXKey<BigDecimal> avg() {
return AVG;
}
/**
* Creates a new ERXKey that appends this key with NSArray's {@code @avg}
* aggregate operator
*
* @return an {@code ERXKey<BigDecimal>} wrapping the {@code thisKey.@avg}
* keypath
*/
public ERXKey<BigDecimal> atAvg() {
return append(ERXKey.avg());
}
/**
* Creates a new ERXKey that appends the given {@code key} to NSArray's
* {@code @min} aggregate operator.
*
* @param <U>
* the type of the next key
* @param key
* the key(path) to the values to be filtered for the minimum
* value
*
* @return an {@code ERXKey<BigDecimal>} wrapping the {@code @min.key}
* keypath
*/
public static <U> ERXKey<U> min(ERXKey<U> key) {
return MIN.append(key);
}
/**
* Creates a new ERXKey that appends this key with NSArray's {@code @min}
* aggregate operator and then appends the given {@code key}.
*
* @param <U>
* the type of the next key
* @param key
* the key(path) to the values to be filtered for the minimum
* value
*
* @return an {@code ERXKey<U>} wrapping the {@code thisKey.@min.key}
* keypath
*/
public <U> ERXKey<U> atMin(ERXKey<U> key) {
return append(ERXKey.min(key));
}
/**
* Creates a new ERXKey that wraps NSArray's {@code @min} aggregate
* operator.
*
* @param <U>
* the type of the next key
*
* @return an {@code ERXKey<BigDecimal>} wrapping the {@code @min} key
*/
public static <U> ERXKey<U> min() {
return (ERXKey<U>) MIN;
}
/**
* Creates a new ERXKey that appends this key with NSArray's {@code @min}
* aggregate operator
*
* @param <U>
* the type of the next key
*
* @return an {@code ERXKey<BigDecimal>} wrapping the {@code thisKey.@min}
* keypath
*/
public <U> ERXKey<U> atMin() {
return (ERXKey<U>) append(ERXKey.min());
}
/**
* Creates a new ERXKey that appends the given {@code key} to NSArray's
* {@code @max} aggregate operator.
*
* @param <U>
* the type of the next key
* @param key
* the key(path) to the values to be filtered for the maximum
* value
*
* @return an {@code ERXKey<U>} wrapping the {@code @max.key}
* keypath
*/
public static <U> ERXKey<U> max(ERXKey<U> key) {
return MAX.append(key);
}
/**
* Creates a new ERXKey that appends this key with NSArray's {@code @max}
* aggregate operator and then appends the given {@code key}.
*
* @param <U>
* the type of the next key
* @param key
* the key(path) to the values to be filtered for the maximum
* value
*
* @return an {@code ERXKey<U>} wrapping the
* {@code thisKey.@max.key} keypath
*/
public <U> ERXKey<U> atMax(ERXKey<U> key) {
return append(ERXKey.max(key));
}
/**
* Creates a new ERXKey that wraps NSArray's {@code @max} aggregate
* operator.
*
* @param <U>
* the type of the next key
*
* @return an {@code ERXKey<U>} wrapping the {@code @max} key
*/
public static <U> ERXKey<U> max() {
return (ERXKey<U>) MAX;
}
/**
* Creates a new ERXKey that appends this key with NSArray's {@code @max}
* aggregate operator
*
* @param <U>
* the type of the next key
*
* @return an {@code ERXKey<U>} wrapping the {@code thisKey.@max}
* keypath
*/
public <U> ERXKey<U> atMax() {
return (ERXKey<U>) append(ERXKey.max());
}
/**
* Creates a new ERXKey that wraps NSArray's {@code @count} aggregate
* operator.
* <p>
* <b>Note:</b> any key(path) following {@code @count} is ignored.
*
* @return an {@code ERXKey<BigDecimal>} wrapping the {@code @count} key
*/
public static ERXKey<Integer> count() {
return COUNT;
}
/**
* Creates a new ERXKey that appends this key with NSArray's {@code @count}
* aggregate operator
* <p>
* <b>Note:</b> any key(path) following {@code @count} is ignored.
*
* @return an {@code ERXKey<Integer>} wrapping the {@code thisKey.@count}
* keypath
*/
public ERXKey<Integer> atCount() {
return append(ERXKey.count());
}
/**
* Enums to describe the type of key this represents.
*
* @author mschrag
*/
public static enum Type {
/**
* Indicates that this key represents an {@link EOAttribute} defined in
* the {@link EOModel}. Since it is defined in the model it can be used
* when instantiating Objects that impact SQL generation, e.g.,
* {@link EOQualifier} and {@link EOSortOrdering}.
*/
Attribute,
/**
* Indicates that this key represents an {@link EORelationship} defined
* in the {@link EOModel} that will return <code>false</code> for
* {@link EORelationship#isToMany()}. Since it is defined in the model
* it can be used when instantiating Objects that impact SQL generation,
* e.g., {@link EOQualifier} and {@link EOSortOrdering}.
*/
ToOneRelationship,
/**
* Indicates that this key represents an {@link EORelationship} defined
* in the {@link EOModel} that will return <code>true</code> for
* {@link EORelationship#isToMany()}. Since it is defined in the model
* it can be used when instantiating Objects that impact SQL generation,
* e.g., {@link EOQualifier} and {@link EOSortOrdering}.
*/
ToManyRelationship,
/**
* Indicates that this key represents an {@link NSArray.Operator}, e.g.,
* {@link NSArray._SumNumberOperator @sum},
* {@link ERXArrayUtilities.FlattenOperator @flatten},
* {@link ERXArrayUtilities.FlattenOperator @fetchSpec},
* {@link NSArray._MinOperator @min}
* <p>
* <em>Note:</em> this Type is not recognized by the
* {@link ERXKeyFilter#matches(ERXKey, Type)} and will not be included
* in {@link ERXKeyFilter#includeAll()},
* {@link ERXKeyFilter#includeAttributes()} nor
* {@link ERXKeyFilter#includeAttributesAndToOneRelationships()} because
* {@link ERXKeyFilter} can only be used with {@link ERXKey}s that
* represent a single key {@link NSArray.Operator}s represent a keypath.
*/
Operator,
/**
* Indicates that this key represents a visible method or ivar that
* returns an object of type T, but does not have a corresponding
* relationship entry in the {@link EOModel} and therefore cannot be
* used to instantiate objects that will impact SQL generation. e.g.,
* {@link EOQualifier} and {@link EOSortOrdering}.
* <p>
* <em>Note:</em> this ERXKey.Type is not recognized by the
* {@link ERXKeyFilter#matches(ERXKey, Type)} and will not be included
* in {@link ERXKeyFilter#includeAll()},
* {@link ERXKeyFilter#includeAttributes()} nor
* {@link ERXKeyFilter#includeAttributesAndToOneRelationships()}.
* <p>
* TODO: Additional work needs to be done to validate that ERRest's use
* of ERXKeyFilter is compatible with this ERXKey.Type.
*/
NonModelAttribute,
/**
* Indicates that this key represents a visible instance member that
* returns an instance of {@link EOEnterpriseObject} of type T, but does
* not have a corresponding relationship entry in the {@link EOModel}
* and therefore cannot be used to instantiate objects that will impact
* SQL generation. e.g., {@link EOQualifier} and {@link EOSortOrdering}.
* <p>
* <em>Note:</em> this ERXKey.Type is not recognized by the
* {@link ERXKeyFilter#matches(ERXKey, Type)} and will not be included
* in {@link ERXKeyFilter#includeAll()},
* {@link ERXKeyFilter#includeAttributes()} nor
* {@link ERXKeyFilter#includeAttributesAndToOneRelationships()}.
* <p>
* TODO: Additional work needs to be done to validate that ERRest's use
* of ERXKeyFilter is compatible with this ERXKey.Type.
*/
NonModelToOneRelationship,
/**
* Indicates that this key represents a visible instance member that
* returns an array of {@link EOEnterpriseObject} instances of type T,
* but does not have a corresponding relationship entry in the
* {@link EOModel} and therefore cannot be used to instantiate objects
* that will impact SQL generation. e.g., {@link EOQualifier} and
* {@link EOSortOrdering}.
* <p>
* <em>Note:</em> this ERXKey.Type is not recognized by the
* {@link ERXKeyFilter#matches(ERXKey, Type)} and will not be included
* in {@link ERXKeyFilter#includeAll()},
* {@link ERXKeyFilter#includeAttributes()} nor
* {@link ERXKeyFilter#includeAttributesAndToOneRelationships()}.
* <p>
* TODO: Additional work needs to be done to validate that ERRest's use
* of ERXKeyFilter is compatible with this ERXKey.Type.
*/
NonModelToManyRelationship
}
public interface ValueCoding {
public <T> T valueForKey(ERXKey<T> key);
public <T> void takeValueForKey(Object value, ERXKey<T> key);
}
private String _key;
private Type _type;
/**
* Constructs an ERXKey.
*
* @param key
* the underlying keypath
*/
public ERXKey(String key) {
_key = key;
}
/**
* Constructs an ERXKey, specifying what {@link Type} it is.
*
* You can have EOGenerator use this constructor by using the following code
* in the EOGenerator template that generates your _Entity.java files.
* Replace the existing code that creates the ERXKeys declarations for the
* Entity's attributes, to-one relationships and to-many relationships.
*
* <pre><code>
* public static final ERXKey<$attribute.javaClassName> ${attribute.uppercaseUnderscoreName} = new ERXKey<$attribute.javaClassName>("$attribute.name", ERXKey.Type.Attribute);
*
* public static final ERXKey<$relationship.actualDestination.classNameWithDefault> ${relationship.uppercaseUnderscoreName} = new ERXKey<$relationship.actualDestination.classNameWithDefault>("$relationship.name", ERXKey.Type.ToOneRelationship);
*
* public static final ERXKey<$relationship.actualDestination.classNameWithDefault> ${relationship.uppercaseUnderscoreName} = new ERXKey<$relationship.actualDestination.classNameWithDefault>("$relationship.name", ERXKey.Type.ToManyRelationship);
* </code></pre>
*
* @param key
* the underlying key or keypath
* @param type
* the {@link Type}
*/
public ERXKey(String key, Type type) {
_key = key;
_type = type;
}
/**
* Constructs a localized ERXKey.
*
* @param key
* the underlying keypath
* @param locale
* the locale for the key
*/
public ERXKey(String key, String locale) {
_key = key + "_" + locale;
}
/**
* Constructs a localized ERXKey, specifying what {@link Type} it is.
*
* @param key
* the underlying keypath
* @param locale
* the locale for the key
* @param type
* the {@link Type}
*
* @see #ERXKey(String, Type)
*/
public ERXKey(String key, String locale, Type type) {
_key = key + "_" + locale;
_type = type;
}
/**
* Equivalent to ERXS.asc(key())
*
* @return asc sort ordering for key
*/
public ERXSortOrdering asc() {
return ERXS.asc(key());
}
/**
* Equivalent to ERXS.ascs(key())
*
* @return asc sort ordering for key
*/
public ERXSortOrdering.ERXSortOrderings ascs() {
return ERXS.ascs(key());
}
/**
* Equivalent to ERXS.desc(key())
*
* @return desc sort ordering for key
*/
public ERXSortOrdering desc() {
return ERXS.desc(key());
}
/**
* Equivalent to ERXS.descs(key())
*
* @return desc sort ordering for key
*/
public ERXSortOrdering.ERXSortOrderings descs() {
return ERXS.descs(key());
}
/**
* Equivalent to ERXS.ascInsensitive(key())
*
* @return ascInsensitive sort ordering for key
*/
public ERXSortOrdering ascInsensitive() {
return ERXS.ascInsensitive(key());
}
/**
* Equivalent to ERXS.ascInsensitives(key())
*
* @return ascInsensitive sort ordering for key
*/
public ERXSortOrdering.ERXSortOrderings ascInsensitives() {
return ERXS.ascInsensitives(key());
}
/**
* Equivalent to ERXS.descInsensitive(key())
*
* @return descInsensitive sort ordering for key
*/
public ERXSortOrdering descInsensitive() {
return ERXS.descInsensitive(key());
}
/**
* Equivalent to ERXS.descInsensitives(key())
*
* @return descInsensitive sort ordering for key
*/
public ERXSortOrdering.ERXSortOrderings descInsensitives() {
return ERXS.descInsensitives(key());
}
/**
* Return the keypath that this ERXKey represents.
*
* @return the keypath that this ERXKey represents
*/
public String key() {
return _key;
}
/**
* Returns a localized key.
*
* @param locale
* locale for the new key.
*
* @return localized key
*/
public ERXKey<T> loc(String locale) {
return new ERXKey(key(), locale);
}
/**
* Returns a localized key.
*
* @param locale
* locale for the new key.
*
* @return localized key
*/
public ERXKey<T> loc(Locale locale) {
return new ERXKey(key(), locale.getLanguage().toLowerCase());
}
/**
* Equivalent to new ERXKeyValueQualifier(key,
* EOQualifier.QualifierOperatorEqual, Boolean.TRUE);
*
* @return an ERXKeyValueQualifier
*/
public ERXKeyValueQualifier isTrue() {
return ERXQ.isTrue(_key);
}
/**
* Equivalent to new ERXKeyValueQualifier(key,
* EOQualifier.QualifierOperatorEqual, Boolean.FALSE);
*
* @return an ERXKeyValueQualifier
*/
public ERXKeyValueQualifier isFalse() {
return ERXQ.isFalse(_key);
}
/**
* Equivalent to new ERXKeyValueQualifier(key,
* EOQualifier.QualifierOperatorEqual, value) only if the value is not null.
* If the value is null, this will return null, allowing you to
* conditionally chain an equals only if the value is non-null.
*
* @param value
* the value
* @return an ERXKeyValueQualifier or null
*/
public ERXKeyValueQualifier isUnlessNull(T value) {
return (value == null) ? null : is(value);
}
/**
* Equivalent to new ERXKeyValueQualifier(key,
* EOQualifier.QualifierOperatorEqual, value);
*
* @param value
* the value
* @return an ERXKeyValueQualifier
*/
public ERXKeyValueQualifier is(T value) {
return ERXQ.equals(_key, value);
}
/**
* Equivalent to new ERXKeyComparisonQualifier(key,
* EOQualifier.QualifierOperatorEqual, value);
*
* @param value
* the value
* @return an ERXKeyComparisonQualifier
*/
public ERXKeyComparisonQualifier is(ERXKey<T> value) {
return ERXQ.equals(this, value);
}
/**
* Equivalent to new ERXKeyValueQualifier(key,
* EOQualifier.QualifierOperatorEqual, value);
*
* @param value
* the value
* @return an ERXKeyValueQualifier
*/
public ERXKeyValueQualifier eq(T value) {
return ERXQ.equals(_key, value);
}
/**
* Equivalent to new ERXKeyComparisonQualifier(key,
* EOQualifier.QualifierOperatorEqual, value);
*
* @param value
* the value
* @return an ERXKeyComparisonQualifier
*/
public ERXKeyComparisonQualifier eq(ERXKey<T> value) {
return ERXQ.equals(this, value);
}
/**
* Equivalent to new ERXKeyValueQualifier(key,
* EOQualifier.QualifierOperatorNotEqual, value);
*
* @param value
* the value
* @return an ERXKeyValueQualifier
*/
public ERXKeyValueQualifier isNot(T value) {
return ERXQ.notEquals(_key, value);
}
/**
* Equivalent to new ERXKeyComparisonQualifier(key,
* EOQualifier.QualifierOperatorNotEqual, value);
*
* @param value
* the value
* @return an ERXKeyComparisonQualifier
*/
public ERXKeyComparisonQualifier isNot(ERXKey<T> value) {
return ERXQ.notEquals(this, value);
}
/**
* Equivalent to new ERXKeyValueQualifier(key,
* EOQualifier.QualifierOperatorNotEqual, value);
*
* @param value
* the value
* @return an ERXKeyValueQualifier
*/
public ERXKeyValueQualifier ne(T value) {
return ERXQ.notEquals(_key, value);
}
/**
* Equivalent to new ERXKeyComparisonQualifier(key,
* EOQualifier.QualifierOperatorNotEqual, value);
*
* @param value
* the value
* @return an ERXKeyComparisonQualifier
*/
public ERXKeyComparisonQualifier ne(ERXKey<T> value) {
return ERXQ.notEquals(this, value);
}
/**
* Equivalent to new ERXKeyValueQualifier(key,
* EOQualifier.QualifierOperatorGreaterThan, value);
*
* @param value
* the value
* @return an ERXKeyValueQualifier
*/
public ERXKeyValueQualifier greaterThan(T value) {
return ERXQ.greaterThan(_key, value);
}
/**
* Equivalent to new ERXKeyComparisonQualifier(key,
* EOQualifier.QualifierOperatorGreaterThan, value);
*
* @param value
* the value
* @return an ERXKeyComparisonQualifier
*/
public ERXKeyComparisonQualifier greaterThan(ERXKey<T> value) {
return ERXQ.greaterThan(this, value);
}
/**
* Equivalent to new ERXKeyValueQualifier(key,
* EOQualifier.QualifierOperatorGreaterThan, value);
*
* @param value
* the value
* @return an ERXKeyValueQualifier
*/
public ERXKeyValueQualifier gt(T value) {
return ERXQ.greaterThan(_key, value);
}
/**
* Equivalent to new ERXKeyComparisonQualifier(key,
* EOQualifier.QualifierOperatorGreaterThan, value);
*
* @param value
* the value
* @return an ERXKeyComparisonQualifier
*/
public ERXKeyComparisonQualifier gt(ERXKey<T> value) {
return ERXQ.greaterThan(this, value);
}
/**
* Equivalent to new ERXKeyValueQualifier(key,
* EOQualifier.QualifierOperatorLessThan, value);
*
* @param value
* the value
* @return an ERXKeyValueQualifier
*/
public ERXKeyValueQualifier lessThan(T value) {
return ERXQ.lessThan(_key, value);
}
/**
* Equivalent to new ERXKeyComparisonQualifier(key,
* EOQualifier.QualifierOperatorLessThan, value);
*
* @param value
* the value
* @return an ERXKeyComparisonQualifier
*/
public ERXKeyComparisonQualifier lessThan(ERXKey<T> value) {
return ERXQ.lessThan(this, value);
}
/**
* Equivalent to new ERXKeyValueQualifier(key,
* EOQualifier.QualifierOperatorLessThan, value);
*
* @param value
* the value
* @return an ERXKeyValueQualifier
*/
public ERXKeyValueQualifier lt(T value) {
return ERXQ.lessThan(_key, value);
}
/**
* Equivalent to new ERXKeyComparisonQualifier(key,
* EOQualifier.QualifierOperatorLessThan, value);
*
* @param value
* the value
* @return an ERXKeyComparisonQualifier
*/
public ERXKeyComparisonQualifier lt(ERXKey<T> value) {
return ERXQ.lessThan(this, value);
}
/**
* Equivalent to new ERXKeyValueQualifier(key,
* EOQualifier.QualifierOperatorGreaterThanOrEqualTo, value);
*
* @param value
* the value
* @return an ERXKeyValueQualifier
*/
public ERXKeyValueQualifier greaterThanOrEqualTo(T value) {
return ERXQ.greaterThanOrEqualTo(_key, value);
}
/**
* Equivalent to new ERXKeyComparisonQualifier(key,
* EOQualifier.QualifierOperatorGreaterThanOrEqualTo, value);
*
* @param value
* the value
* @return an ERXKeyComparisonQualifier
*/
public ERXKeyComparisonQualifier greaterThanOrEqualTo(ERXKey<T> value) {
return ERXQ.greaterThanOrEqualTo(this, value);
}
/**
* Equivalent to new ERXKeyValueQualifier(key,
* EOQualifier.QualifierOperatorGreaterThanOrEqualTo, value);
*
* @param value
* the value
* @return an ERXKeyValueQualifier
*/
public ERXKeyValueQualifier gte(T value) {
return ERXQ.greaterThanOrEqualTo(_key, value);
}
/**
* Equivalent to new ERXKeyComparisonQualifier(key,
* EOQualifier.QualifierOperatorGreaterThanOrEqualTo, value);
*
* @param value
* the value
* @return an ERXKeyComparisonQualifier
*/
public ERXKeyComparisonQualifier gte(ERXKey<T> value) {
return ERXQ.greaterThanOrEqualTo(this, value);
}
/**
* Equivalent to new ERXKeyValueQualifier(key,
* EOQualifier.QualifierOperatorLessThanOrEqualTo, value);
*
* @param value
* the value
* @return an ERXKeyValueQualifier
*/
public ERXKeyValueQualifier lessThanOrEqualTo(T value) {
return ERXQ.lessThanOrEqualTo(_key, value);
}
/**
* Equivalent to new ERXKeyComparisonQualifier(key,
* EOQualifier.QualifierOperatorLessThanOrEqualTo, value);
*
* @param value
* the value
* @return an ERXKeyComparisonQualifier
*/
public ERXKeyComparisonQualifier lessThanOrEqualTo(ERXKey<T> value) {
return ERXQ.lessThanOrEqualTo(this, value);
}
/**
* Equivalent to new ERXKeyValueQualifier(key,
* EOQualifier.QualifierOperatorLessThanOrEqualTo, value);
*
* @param value
* the value
* @return an ERXKeyValueQualifier
*/
public ERXKeyValueQualifier lte(T value) {
return ERXQ.lessThanOrEqualTo(_key, value);
}
/**
* Equivalent to new ERXKeyComparisonQualifier(key,
* EOQualifier.QualifierOperatorLessThanOrEqualTo, value);
*
* @param value
* the value
* @return an ERXKeyComparisonQualifier
*/
public ERXKeyComparisonQualifier lte(ERXKey<T> value) {
return ERXQ.lessThanOrEqualTo(this, value);
}
/**
* Equivalent to new ERXKeyValueQualifier(key,
* EOQualifier.QualifierOperatorLike, value);
*
* @param value
* the value
* @return an ERXKeyValueQualifier
*/
public ERXKeyValueQualifier like(String value) {
return ERXQ.like(_key, value);
}
/**
* Equivalent to new ERXKeyValueQualifier(key,
* EOQualifier.QualifierOperatorCaseInsensitiveLike, value);
*
* @param value
* the value
* @return an ERXKeyValueQualifier
*/
public ERXKeyValueQualifier likeInsensitive(String value) {
return ERXQ.likeInsensitive(_key, value);
}
/**
* Equivalent to new ERXKeyValueQualifier(key,
* EOQualifier.QualifierOperatorCaseInsensitiveLike, value);
*
* @param value
* the value
* @return an ERXKeyValueQualifier
*/
public ERXKeyValueQualifier ilike(String value) {
return ERXQ.likeInsensitive(_key, value);
}
/**
* Equivalent to new ERXKeyValueQualifier(key,
* EOQualifier.QualifierOperatorEqual, null);
*
* @return an ERXKeyValueQualifier
*
* @see isEmptyRelationship
*/
public ERXKeyValueQualifier isNull() {
return ERXQ.isNull(_key);
}
/**
* Equivalent to new ERXKeyValueQualifier(key,
* EOQualifier.QualifierOperatorNotEqual, null);
*
* @return an ERXKeyValueQualifier
*/
public ERXKeyValueQualifier isNotNull() {
return ERXQ.isNotNull(_key);
}
/**
* Equivalent to a new ERXOrQualifier of EOKeyValueQualifier with key equals
* value for each value.
*
* @param values
* the values
* @return an ERXOrQualifier
*/
public ERXOrQualifier inObjects(T... values) {
return ERXQ.inObjects(_key, values);
}
/**
* Equivalent to a new ERXAndQualifier of
* EONotQualifier(EOKeyValueQualifier) with key equals value for each value.
*
* @param values
* the values
* @return an ERXAndQualifier
*/
public ERXAndQualifier notInObjects(T... values) {
return ERXQ.notInObjects(_key, values);
}
/**
* Equivalent to a new ERXOrQualifier of EOKeyValueQualifier with key equals
* value for each value.
*
* @param values
* the values
* @return an ERXOrQualifier
*/
public ERXOrQualifier in(NSArray<T> values) {
return ERXQ.in(_key, values);
}
/**
* Equivalent to a new ERXAndQualifier of
* EONotQualifier(EOKeyValueQualifier) with key equals value for each value.
*
* @param values
* the values
* @return an ERXAndQualifier
*/
public ERXAndQualifier notIn(NSArray<T> values) {
return ERXQ.notIn(_key, values);
}
/**
* Equivalent to new ERXKeyValueQualifier(key,
* EOQualifier.QualifierOperatorLessThan, value);
*
* @param when
* the date to compare with
* @return an ERXKeyValueQualifier
*/
public ERXKeyValueQualifier before(NSTimestamp when) {
return ERXQ.lessThan(_key, when);
}
/**
* Equivalent to new ERXKeyComparisonQualifier(key,
* EOQualifier.QualifierOperatorLessThan, value);
*
* @param when
* the date to compare with
* @return an ERXKeyComparisonQualifier
*/
@SuppressWarnings("unchecked")
public ERXKeyComparisonQualifier before(ERXKey<? extends NSTimestamp> when) {
return ERXQ.lessThan((ERXKey)this, when);
}
/**
* Equivalent to new ERXKeyValueQualifier(key,
* EOQualifier.QualifierOperatorGreaterThan, value);
*
* @param when
* the date to compare with
* @return an ERXKeyValueQualifier
*/
public ERXKeyValueQualifier after(NSTimestamp when) {
return ERXQ.greaterThan(_key, when);
}
/**
* Equivalent to new ERXKeyComparisonQualifier(key,
* EOQualifier.QualifierOperatorGreaterThan, value);
*
* @param when
* the date to compare with
* @return an ERXKeyComparisonQualifier
*/
@SuppressWarnings("unchecked")
public ERXKeyComparisonQualifier after(ERXKey<? extends NSTimestamp> when) {
return ERXQ.greaterThan((ERXKey)this, when);
}
/**
* Equivalent to key > lowerBound and key < upperBound (exclusive). Note
* that this does not return an ERXBetweenQualifier.
*
* @param lowerBound
* the lower bound value
* @param upperBound
* the upper bound value
* @return the qualifier
*/
public EOQualifier between(T lowerBound, T upperBound) {
return ERXQ.between(_key, lowerBound, upperBound);
}
/**
* Equivalent to key >= lowerBound and key <= upperBound (inclusive). Note
* that this does not return an ERXBetweenQualifier.
*
* @param lowerBound
* the lower bound value
* @param upperBound
* the upper bound value
* @param inclusive
* whether or not the between includes the endpoints
* @return the qualifier
*/
public EOQualifier between(T lowerBound, T upperBound, boolean inclusive) {
return ERXQ.between(_key, lowerBound, upperBound, inclusive);
}
/**
* Equivalent to new ERXKeyValueQualifier(key,
* EOQualifier.OperatorLike, value + "*").
*
* @param value
* the substring value
* @return an ERXKeyValueQualifier
*/
public ERXKeyValueQualifier startsWith(String value) {
return ERXQ.startsWith(_key, value);
}
/**
* Equivalent to new ERXKeyValueQualifier(key,
* EOQualifier.OperatorCaseInsensitiveLike, value + "*").
*
* @param value
* the substring value
* @return an ERXKeyValueQualifier
*/
public ERXKeyValueQualifier startsWithInsensitive(String value) {
return ERXQ.startsWithInsensitive(_key, value);
}
/**
* Equivalent to new ERXKeyValueQualifier(key,
* EOQualifier.OperatorLike, "*" + value).
*
* @param value
* the substring value
* @return an ERXKeyValueQualifier
*/
public ERXKeyValueQualifier endsWith(String value) {
return ERXQ.endsWith(_key, value);
}
/**
* Equivalent to new ERXKeyValueQualifier(key,
* EOQualifier.OperatorCaseInsensitiveLike, "*" + value).
*
* @param value
* the substring value
* @return an ERXKeyValueQualifier
*/
public ERXKeyValueQualifier endsWithInsensitive(String value) {
return ERXQ.endsWithInsensitive(_key, value);
}
/**
* Equivalent to new ERXKeyValueQualifier(key,
* EOQualifier.OperatorCaseInsensitiveLike, "*" + value + "*").
*
* @param value
* the substring value
* @return an ERXKeyValueQualifier
*/
public ERXKeyValueQualifier contains(String value) {
return ERXQ.contains(_key, value);
}
/**
* Return a qualifier that evaluates 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 tokens
* a whitespace separated list of tokens to search for
* @return an ERXOrQualifier
*/
public ERXOrQualifier containsAny(String tokens) {
return ERXQ.containsAny(_key, tokens);
}
/**
* Return a qualifier that evaluates to true when the value of the given key
* contains any of the given tokens (insensitively).
*
* @param tokens
* the list of tokens to search for
* @return an ERXOrQualifier
*/
public ERXOrQualifier containsAny(String[] tokens) {
return ERXQ.containsAny(_key, tokens);
}
/**
* Return a qualifier that evaluates 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 tokens
* a whitespace separated list of tokens to search for
* @return an ERXAndQualifier
*/
public ERXAndQualifier containsAll(String tokens) {
return ERXQ.containsAll(_key, tokens);
}
/**
* Return a qualifier that evaluates to true when the value of the given key
* contains all of the given tokens (insensitively).
*
* @param tokens
* the list of tokens to search for
* @return an ERXAndQualifier
*/
public ERXAndQualifier containsAll(String[] tokens) {
return ERXQ.containsAll(_key, tokens);
}
/**
* Return a qualifier that evaluates to true when the given to many key
* contains the given object.
* <p>
* Equivalent to new ERXKeyValueQualifier(key, EOQualifier.OperatorContains,
* value).
*
* @param obj
* the object
* @return an EOKeyValueQualifier
*/
public ERXKeyValueQualifier containsObject(Object obj) {
return ERXQ.containsObject(_key, obj);
}
/**
* Uses ERXExistsQualifier to build a qualifier that returns true if at least one the objects
* specified is found in the to many relationship represented by this key.
*
* @param valueArray
* an array of {@link ERXGenericRecord} we want to have in this to many relationship.
* @return a qualifier that evaluates to true when at least one the the objects specified in
* {@code valueArray} is found in the to many {@link EORelationship}
* represented by this ERXKey.
*
* @author Samuel Pelletier
* @since May 16, 2016
*/
public ERXExistsQualifier containsAnyOfTheseObjects(NSArray<? extends ERXGenericRecord> valueArray) {
ERXExistsQualifier existsQualifier = new ERXExistsQualifier(ERXQ.isIn(valueArray), _key);
existsQualifier.setUsesInQualInstead(true);
return existsQualifier;
}
/**
* Equivalent to <code>new ERXExistsQualifier(qualifier, key)</code>.
*
* @param qualifier
* a qualifier for the {@link EORelationship#destinationEntity()
* destinationEntity} of the {@link EORelationship} represented
* by this ERXKey
* @return a qualifier that evaluates to true when the {@link EORelationship}
* represented by this ERXKey contains at least one object matching
* the given {@code qualifier}
*
* @author David Avendasora
* @since Mar 26, 2014
*/
public ERXExistsQualifier containsAnyObjectSatisfying(EOQualifier qualifier) {
return new ERXExistsQualifier(qualifier, _key);
}
/**
* Equivalent to <code>new ERXExistsQualifier(qualifier, key)</code>.
* <p>
* Since this qualifier will <em>not</em> result in a join in the database,
* it can be very useful when testing relationships that use the
* <code>InnerJoin</code> {@link EORelationship#joinSemantic() joinSemantic}
* yet the relationship may be empty (to-many relationships) or
* <code>null</code> (to-one relationships).
*
* @param qualifier
* a qualifier for the {@link EORelationship#destinationEntity()
* destinationEntity} of the {@link EORelationship} represented
* by this ERXKey
* @return a qualifier that evaluates to true when the
* {@link EORelationship} represented by this ERXKey does not
* contain any objects that satisfy the given {@code qualifier}
*
* @author David Avendasora
* @since Mar 26, 2014
*/
public ERXNotQualifier doesNotContainsAnyObjectSatisfying(EOQualifier qualifier) {
return new ERXNotQualifier(containsAnyObjectSatisfying(qualifier));
}
/**
* Equivalent to containsAnyObjectSatisfying() but set the ERXExistsQualifier to uses IN instead of EXISTS.
*
* @param qualifier
* a qualifier for the {@link EORelationship#destinationEntity()
* destinationEntity} of the {@link EORelationship} represented
* by this ERXKey
* @return a qualifier that evaluates to true when the {@link EORelationship}
* represented by this ERXKey contains at least one object matching
* the given {@code qualifier}
*
* @author Samuel Pelletier
* @since May 56, 2016
*/
public ERXExistsQualifier containsAnyObjectSatisfyingUsingIn(EOQualifier qualifier) {
ERXExistsQualifier existsQualifier = new ERXExistsQualifier(qualifier, _key);
existsQualifier.setUsesInQualInstead(true);
return existsQualifier;
}
/**
* Equivalent to doesNotContainsAnyObjectSatisfying() but set the ERXExistsQualifier to uses IN instead of EXISTS.
*
* @param qualifier
* a qualifier for the {@link EORelationship#destinationEntity()
* destinationEntity} of the {@link EORelationship} represented
* by this ERXKey
* @return a qualifier that evaluates to true when the {@link EORelationship}
* represented by this ERXKey does not contains at least one object matching
* the given {@code qualifier}
*
* @author Samuel Pelletier
* @since May 56, 2016
*/
public ERXNotQualifier doesNotContainsAnyObjectSatisfyingUsingIn(EOQualifier qualifier) {
return new ERXNotQualifier(containsAnyObjectSatisfyingUsingIn(qualifier));
}
/**
* Determines if there are any objects in the to-one or to-many
* {@link EORelationship} that this ERXKey represents.
*
* @return a qualifier that evaluates to <code>true</code> when the
* {@link EORelationship} represented by this ERXKey contains at
* least one object
*
* @author David Avendasora
* @since Mar 26, 2014
*/
public ERXExistsQualifier isNotEmptyRelationship() {
return containsAnyObjectSatisfying(new ERXTrueQualifier());
}
/**
* Determines if there are any objects in the to-one or to-many
* EORelationship that this ERXKey represents.
* <p>
* Since this qualifier will <em>not</em> result in a join in the database,
* it can be very useful when testing relationships that use the
* <code>InnerJoin</code> {@link EORelationship#joinSemantic() joinSemantic}
* and the relationship could be empty (to-many relationships) or
* <code>null</code> (to-one relationships).
*
* @return a qualifier that evaluates to <code>true</code> when the
* {@link EORelationship} represented by this ERXKey is empty
*
* @author David Avendasora
* @since Mar 26, 2014
*/
public ERXNotQualifier isEmptyRelationship() {
return doesNotContainsAnyObjectSatisfying(new ERXTrueQualifier());
}
/**
* Equivalent to new ERXInQualifier(key, values);
*
* @param values
* the values
* @return an ERXKeyValueQualifier
*/
public ERXKeyValueQualifier hasValues(NSArray<T> values) {
return ERXQ.hasValues(_key, values);
}
@Override
public int hashCode() {
return _key.hashCode();
}
@Override
public boolean equals(Object obj) {
return obj instanceof ERXKey && ((ERXKey) obj)._key.equals(_key);
}
/**
* Return a new ERXKey that appends the given key to this keypath. For
* instance, if this key is "person" and you add "firstName" to it, this
* will return a new ERXKey "person.firstName".
* <p>
* Note: ERXKey has a limitation that it will not return the proper generic
* type if you attempt to build a keypath extension of an NSArray. For
* instance,
* ERXKey<NSArray<Person>>.append(ERXKey<String>) will
* return ERXKey<String> when, in fact, it should be
* ERXKey<NSArray<String>>. This is a limitation due to type
* erasure with generics that we cannot currently resolve this problem.
*
* @param <U> the type of the next key
*
* @param key
* the key to append to this keypath
* @return the new appended key
*/
public <U> ERXKey<U> append(String key) {
return new ERXKey<U>((_key != null && _key.length() != 0) ? _key + NSKeyValueCodingAdditions.KeyPathSeparator + key : key);
}
/**
* Call append(key)
*
* @param <U>
* the key type
* @param key
* the key to append to this keypath
* @return the new appended key
*/
public <U> ERXKey<U> dot(String key) {
return append(key);
}
/**
* Return a new ERXKey that appends the given key to this keypath. For
* instance, if this key is "person" and you add "firstName" to it, this
* will return a new ERXKey "person.firstName".
* <p>
* Note: ERXKey has a limitation that it will not return the proper generic
* type if you attempt to build a keypath extension of an NSArray. For
* instance,
* ERXKey<NSArray<Person>>.append(ERXKey<String>) will
* return ERXKey<String> when, in fact, it should be
* ERXKey<NSArray<String>>. This is a limitation due to type
* erasure with generics that we cannot currently resolve this problem.
*
* @param <U> the type of the next key
*
* @param key
* the key to append to this keypath
* @return the new appended key
*/
public <U> ERXKey<U> append(ERXKey<U> key) {
return append(key.key());
}
/**
* Call append(key)
*
* @param <U>
* the key type
* @param key
* the key to append to this keypath
* @return the new appended key
*/
public <U> ERXKey<U> dot(ERXKey<U> key) {
return append(key);
}
/**
* Return a new ERXKey that appends the given key to this keypath. For
* instance, if this key is "person" and you add "firstName" to it, this
* will return a new ERXKey "person.firstName".
*
* <pre><code>
* ERXKey<String> k = new ERXKey<String>("foo");
* ERXKey<NSArray<String>> a = new ERXKey<NSArray<String>>("foos");
* k = k.append(k);
* a = a.append(k);
* a = k.appendAsArray(k);
* k = k.appendAsArray(k);
* a = k.appendAsArray(a);
* a = a.appendAsArray(k);
* a = a.appendAsArray(a);
* </code></pre>
*
* @param <U> the type of the next key in the array
*
* @param key
* the key to append to this keypath
* @return the new appended key
*/
public <U> ERXKey<NSArray<U>> appendAsArray(ERXKey<U> key) {
return append(key.key());
}
/**
* Call appendAsArray(key).
*
* @param <U>
* the type
* @param key
* the key to append to this keypath
* @return the new append to this keypath
*/
public <U> ERXKey<NSArray<U>> dotArray(ERXKey<U> key) {
return append(key.key());
}
/**
* Return the value of this keypath on the given object.
* <p>
* Note: If you ERXKey representation a keypath through an NSArray, this
* method will result in a ClassCastException. See the 'Note' on .append(..)
* for further explanation.
*
* @param obj
* the target object to apply this keypath on
* @return the value of the keypath on the target object
*/
@SuppressWarnings("unchecked")
public T valueInObject(Object obj) {
return (T) rawValueInObject(obj);
}
/**
* Return the value of this keypath on the given object.
*
* @param obj
* the target object to apply this keypath on
* @return the value of the keypath on the target object
*/
public Object rawValueInObject(Object obj) {
return NSKeyValueCodingAdditions.Utility.valueForKeyPath(obj, _key);
}
/**
* Return the value of this keypath on the given object cast as an NSArray.
*
* @param obj
* the target object to apply this keypath on
* @return the value of the keypath on the target object
*/
@SuppressWarnings("unchecked")
public NSArray<T> arrayValueInObject(Object obj) {
return (NSArray<T>) rawValueInObject(obj);
}
/**
* Set the value of this keypath on the given object.
*
* @param value
* the value to set
* @param obj
* the object to set the value on
*/
public void takeValueInObject(T value, Object obj) {
NSKeyValueCodingAdditions.Utility.takeValueForKeyPath(obj, value, _key);
}
/**
* Prefix the keys in the given qualifier with this key. For example, if you have a qualifier on Company of name = 'mDT'
* and you want to find Person eo's whose companies match that qualifier, you need to prefix all the keys in the qualifier
* to be "company.whatever" (to go through the company relationship on Person) -- so in the example you would need
* company.name = 'mDT'. Prefix provides a mechanism to do that.
*
* Person.COMPANY.prefix(ERXQ.is("name", "mDT")) is equivalent to ERXQ.is("company.name", "mDT")
*
* @param qualifier the qualifier to prefix
* @return a qualifier with all of its keys prefixed with this key
*/
public EOQualifier prefix(EOQualifier qualifier) {
return ERXPrefixQualifierTraversal.prefixQualifierWithKey(qualifier, this);
}
@Override
public String toString() {
return _key;
}
/**
* Prefix the key in the given sort ordering with this key. For example, if
* you have a sort ordering on Company of "name ascending" and you want to
* sort a group of Person eo's by the name of the company they work for, you
* need to prefix the key in the existing sort ordering to be "company.name
* ascending" (to go through the company relationship on Person). Prefix
* provides a mechanism to do that.
*
* Person.COMPANY.prefix(Company.NAME.asc()) is equivalent to ERXS.sortOrder("compan.name", ERXS.ASC)
*
* @param sortOrder
* the sort ordering to prefix
* @return a sort ordering with its key prefixed with this key
* @author David Avendasora
*/
public ERXSortOrdering prefix(EOSortOrdering sortOrder) {
String keyPathToChain = sortOrder.key();
String fullKeyPath = append(keyPathToChain).key();
NSSelector selector = sortOrder.selector();
ERXSortOrdering prefixedSortOrdering = ERXS.sortOrder(fullKeyPath, selector);
return prefixedSortOrdering;
}
/**
* Prefix the keys in the given array of sort orderings with this key.
*
* @param sortOrderings
* an Array of sort orderings to prefix
* @return a sort ordering with its key prefixed with this key
* @see #prefix(EOSortOrdering)
* @author David Avendasora
*/
public ERXSortOrderings prefix(NSArray<EOSortOrdering> sortOrderings) {
ERXSortOrderings prefixedSortOrderings = new ERXSortOrderings();
for (EOSortOrdering sortOrdering : sortOrderings) {
EOSortOrdering prefixedSortOrdering = prefix(sortOrdering);
prefixedSortOrderings.addObject(prefixedSortOrdering);
}
return prefixedSortOrderings;
}
/**
* Simple cover method for {@link #prefix(EOQualifier)}.
*
* @param qualifier
* the qualifier to prefix
* @return a qualifier with all of its keys prefixed with this key
* @author David Avendasora
*/
public EOQualifier dot(EOQualifier qualifier) {
return prefix(qualifier);
}
/**
* Simple cover method for {@link #prefix(EOSortOrdering)}.
*
* @param sortOrdering
* the sort ordering to prefix
* @return a sort ordering with its key prefixed with this key
* @author David Avendasora
*/
public ERXSortOrdering dot(EOSortOrdering sortOrdering) {
return prefix(sortOrdering);
}
/**
* Simple cover method for {@link #prefix(NSArray)}.
*
* @param sortOrderings
* an Array of sort orderings to prefix
* @return a sort ordering with its key prefixed with this key
* @author David Avendasora
*/
public ERXSortOrderings dot(NSArray<EOSortOrdering> sortOrderings) {
return prefix(sortOrderings);
}
/**
* See {@link #ERXKey(String, Type)} for information on how to automatically
* set this.
*
* @return the {@link Type}, if specified, for this key.
*/
public Type type() {
return _type;
}
public void setType(Type type) {
_type = type;
}
/**
* Checks this key's {@link Type} to determine if it represents an
* {@link EOAttribute}.
* <p>
* <em>Note:</em> if {@link #type()} has not been set, then this will return
* <code>false</code>. To set it, you have the following options:
* <ul>
* <li>Set it manually using {@link #setType(Type)}</li>
* <li>Set it using the {@link #ERXKey(String, Type)} constructor. If this
* key was declared in code generated by EOGenerator (i.e. in a _Entity.java
* class), you will need to modify your EOGenerator template. See
* {@link #ERXKey(String, Type)} for details.</li>
* </ul>
*
* @return <code>true</code> if {@link #type()} returns either
* {@link ERXKey.Type.Attribute} or
* {@link ERXKey.Type.NonModelAttribute}, <code>false</code>
* otherwise.
*
* @see isToOneRelationship
* @see isToManyRelationship
*/
public boolean isAttribute() {
return type() == ERXKey.Type.Attribute || type() == ERXKey.Type.NonModelAttribute;
}
/**
* Checks this key's {@link ERXKey.Type} to determine if it represents a
* to-one {@link EORelationship}.
* <p>
* <em>Note:</em> if {@link #type()} has not been set, then this will return
* <code>false</code>. To set it, you have the following options:
* <ul>
* <li>Set it manually using {@link #setType(Type)}</li>
* <li>Set it using the {@link #ERXKey(String, Type)} constructor. If this
* key was declared in code generated by EOGenerator (i.e. in a _Entity.java
* class), you will need to modify your EOGenerator template. See
* {@link #ERXKey(String, Type)} for details.</li>
* </ul>
*
* @return <code>true</code> if {@link #type()} returns either
* {@link ERXKey.Type.ToOneRelationship} or
* {@link ERXKey.Type.NonModelToOneRelationship}, <code>false</code>
* otherwise.
*
* @see isAttribute
* @see isToManyRelationship
*/
public boolean isToOneRelationship() {
return type() == ERXKey.Type.ToOneRelationship || type() == ERXKey.Type.NonModelToOneRelationship;
}
/**
* Checks this key's {@link ERXKey.Type} to determine if it represents a
* to-many {@link EORelationship}.
* <p>
* <em>Note:</em> if {@link #type()} has not been set, then this will return
* <code>false</code>. To set it, you have the following options:
* <ul>
* <li>Set it manually using {@link #setType(Type)}</li>
* <li>Set it using the {@link #ERXKey(String, Type)} constructor. If this
* key was declared in code generated by EOGenerator (i.e. in a _Entity.java
* class), you will need to modify your EOGenerator template. See
* {@link #ERXKey(String, Type)} for details.</li>
* </ul>
*
* @return <code>true</code> if {@link #type()} returns either
* {@link ERXKey.Type.ToOneRelationship} or
* {@link ERXKey.Type.NonModelToOneRelationship}, <code>false</code>
* otherwise.
*
* @see isAttribute
* @see isToOneRelationship
*/
public boolean isToManyRelationship() {
return type() == ERXKey.Type.ToManyRelationship || type() == ERXKey.Type.NonModelToManyRelationship;
}
}