/*******************************************************************************
* Copyright 2014 JHC Systems Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************/
package jhc.redsniff.core;
import jhc.redsniff.action.ActionPerformer;
import jhc.redsniff.action.ActionableFinder;
import jhc.redsniff.internal.core.CollectionOf;
import jhc.redsniff.internal.core.Item;
import jhc.redsniff.internal.core.Quantity;
import jhc.redsniff.internal.predicates.ItemPresent;
import jhc.redsniff.internal.predicates.NoItem;
import jhc.redsniff.internal.predicates.NoItems;
import jhc.redsniff.internal.predicates.Predicate;
import jhc.redsniff.internal.predicates.SingleItemMatching;
import jhc.redsniff.internal.predicates.SomeItem;
import jhc.redsniff.internal.predicates.SomeItemForPurpose;
import jhc.redsniff.internal.predicates.SomeItemsForPurpose;
import org.hamcrest.Description;
import org.hamcrest.Matcher;
public final class FindingPredicates {
private FindingPredicates(){}
/**
* Checks that the number of elements in the collection satisfies the numerical matcher(cardinality constraint)
* eg - at least 4 elements
* @param cardinalityConstraint
* @param clazz - the class of element - for generic resolution
* @return
*/
public static <E> jhc.redsniff.internal.predicates.Predicate<E, CollectionOf<E>> aNumberOfElements(org.hamcrest.Matcher<java.lang.Integer> cardinalityConstraint, Class<E> clazz) {
return jhc.redsniff.internal.predicates.SomeNumberOfItems.<E>aNumberOfElements(cardinalityConstraint);
}
/**
* Checks the collection is not empty
* @param clazz - the class of element - for generic resolution
* @return
*/
public static <E> jhc.redsniff.internal.predicates.Predicate<E, CollectionOf<E>> someElementPresent(Class<E> clazz) {
return jhc.redsniff.internal.predicates.SomeItem.<E>someElementPresent();
}
/**
* Checks for exactly one element, using the word "a unique" to describe it
* @param clazz
* @return
*/
public static <E> jhc.redsniff.internal.predicates.Predicate<E, CollectionOf<E>> uniqueElement(Class<E> clazz) {
return jhc.redsniff.internal.predicates.UniqueItem.<E>uniqueElement();
}
/**
* Checks for an empty collection
* @param clazz
* @return
*/
public static <E> jhc.redsniff.internal.predicates.Predicate<E, CollectionOf<E>> noElements(Class<E> clazz) {
return jhc.redsniff.internal.predicates.NoItems.<E>noElements();
}
/**
* Predicate expecting no results, using the type of quantity relevant to the class of finder passed
*
* @param clazz - the class of {@link Finder}
* @return If {@code clazz} is an {@link MFinder}, a predicate on an empty collection, otherwise on a null single {@link Item}
*/
@SuppressWarnings("unchecked")
public static < E, Q extends Quantity<E>, F extends Finder<E, Q, ?>> Predicate<E,Q> absence(Class<F> clazz){
if(MFinder.class.isAssignableFrom(clazz))
return (Predicate<E, Q>) NoItems.<E> noElements();
else
return (Predicate<E, Q>) NoItem.<E>nothing();
}
/**
* Predicate expecting some result, using the type of quantity relevant to the class of finder passed
*
* @param clazz - the class of {@link Finder}
* @return If {@code clazz} is an {@link MFinder}, a predicate on a collection with some elements, otherwise on a populated single {@link Item}
*/
@SuppressWarnings("unchecked")
public static < E, Q extends Quantity<E>, F extends Finder<E, Q, ?>> Predicate<E,Q> presence(Class<F> clazz){
if(MFinder.class.isAssignableFrom(clazz))
return (Predicate<E, Q>) SomeItem.<E> someElementPresent();
else
return (Predicate<E, Q>) ItemPresent.<E> someElement();
}
/**
* Predicate on a single {@link Item} , that it matches the given matcher
* @param matcher
* @return
*/
public static <E> Predicate<E, Item<E>> singleItemMatches(Matcher<? super E> matcher) {
return new SingleItemMatching<E>(matcher);
}
/**
* Predicate on presence of an element, that will be used for the given purpose, eg clicking. Includes the description of action.
* @param performer - the action performer the target item(s) are intended for
* @param clazz - the class of finder, to determine the quantity type
* @return
*/
public static <E, Q extends Quantity<E>> Predicate<E, Q> actionPredicate(ActionPerformer<E> performer, ActionableFinder<E, Q, ?> actionableFinder) {
Description purposeDescription = Describer.newDescription().appendDescriptionOf(performer);
actionableFinder.describeTypeOfActionTo(purposeDescription);
return forPurposePredicate(purposeDescription.toString(), actionableFinder);
}
/**
*
* @param purpose
* @param clazz
* @return
*/
@SuppressWarnings("unchecked")
public static < E, Q extends Quantity<E>> Predicate<E,Q> forPurposePredicate(String purpose, Finder<E, Q, ?> actionableFinder){
if(actionableFinder instanceof MFinder)
return (Predicate<E, Q>) SomeItemsForPurpose.<E>elementTo(purpose);
else
return (Predicate<E, Q>) SomeItemForPurpose.<E>elementTo(purpose);
}
}