/*******************************************************************************
* 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.internal.core.CollectionOf;
import org.hamcrest.Matcher;
/**
* A {@link Finder} for which there could be multiple results.
* The {@link Finder#findFrom(Object, org.hamcrest.Description)} method will, when successful, return a {@link Collection} of elements rather than a single element.
* Most {@link Finder} implementations will typically descend from this.
* Implementations should be immutable.
*
* @param <E> the type of the elements the Finder finds
* @param <C> the type of the context in which the Finder searches
*/
public interface MFinder<E, C> extends Finder<E,CollectionOf<E>, C> {
/**
* Takes a Matcher<E> to add as a filter and returns a new {@link MFinder} with that filter applied.
* eg adding <tt>.that( hasName("bob") )</tt> will return a Finder based on this one but which will only find elements that have name "bob".
* @param elementMatcher a hamcrest {@link Matcher}. The returned finder's findFrom method will return only those elements who match for this matcher.
* @return A {@link MFinder} based on this one but with the given matcher applied as a filter
*/
MFinder<E, C> that(Matcher<? super E> elementMatcher);
/**
* Takes another MFinder expression and returns a finder which will use the results of that finder as contexts for this finder.
* e.g. <tt>button().withinA( div() )</tt> will give a finder that searches for only those buttons within div elements
* @param outerFinder the outer finder with which to search for a context
* @param <OC> the type of the context used by the outerFinder
* @param <OE> the type of the element found by the outerFinder. this must be a subtype of the type of context (<C>) used by this finder.
* @return a new {@link MFinder} that performs a transitive search
*/
<OE extends C, OC > MFinder<E, OC> withinA(MFinder<OE, OC> outerFinder);
/**
* Takes an SFinder expression and returns a finder which will use the result of that finder as context for this finder.
* e.g. <tt>button().withinThe( only( div() ) )</tt> will give a finder that searches for only those buttons within the unique div element
* @param outerFinder the outer finder with which to search for a context
* @param <OC> the type of the context used by the outerFinder
* @param <OE> the type of the element found by the outerFinder. this must be a subtype of the type of context (<C>) used by this finder.
* @return a new finder that performs a transitive search
*/
<OE extends C, OC > MFinder<E, OC> withinThe(SFinder<OE, OC> finder);
/**
* Takes an SFinder expression and returns a finder which will use the result of that finder as context for this finder.
* e.g. <tt>button().withinThe( only( div() ) )</tt> will give a finder that searches for only those buttons within the unique div element
* @param outerFinder the outer finder with which to search for a context
* @param <OC> the type of the context used by the outerFinder
* @param <OE> the type of the element found by the outerFinder. this must be a subtype of the type of context (<C>) used by this finder.
* @return a new finder that performs a transitive search
*/
<OE extends C, OC > MFinder<E, OC> withinThe(MFinder<OE, OC> finder);
/**
* Used internally to optimize composite finders. May be removed from this interface shortly.
* @return a restructured composite {@link MFinder} with the same criteria but optimized.
*/
MFinder<E, C> asOptimizedFinder();//TODO - could these be hidden from users somehow?
/**
* Used internally to optimize composite finders with matchers applied
* @return a restructured composite {@link MFinder} with the same criteria but optimized.
*/
MFinder<E, C> optimizedWith(Matcher<? super E> matcher);
}