package com.abmash.api.query;
import java.awt.Color;
import java.util.ArrayList;
import com.abmash.REMOVE.api.HtmlQuery;
import com.abmash.REMOVE.core.htmlquery.condition.ClosenessCondition.Direction;
import com.abmash.api.Browser;
import com.abmash.api.HtmlElement;
import com.abmash.api.HtmlElements;
import com.abmash.core.color.ColorName;
import com.abmash.core.color.Dominance;
import com.abmash.core.color.Tolerance;
import com.abmash.core.query.BooleanType;
import com.abmash.core.query.DirectionOptions;
import com.abmash.core.query.DirectionType;
import com.abmash.core.query.predicate.BooleanPredicate;
import com.abmash.core.query.predicate.CheckablePredicate;
import com.abmash.core.query.predicate.ChoosablePredicate;
import com.abmash.core.query.predicate.ClickablePredicate;
import com.abmash.core.query.predicate.ColorPredicate;
import com.abmash.core.query.predicate.DatepickerPredicate;
import com.abmash.core.query.predicate.DirectionPredicate;
import com.abmash.core.query.predicate.ContainsPredicate;
import com.abmash.core.query.predicate.ElementPredicate;
import com.abmash.core.query.predicate.FramePredicate;
import com.abmash.core.query.predicate.HeadlinePredicate;
import com.abmash.core.query.predicate.ImagePredicate;
import com.abmash.core.query.predicate.LinkPredicate;
import com.abmash.core.query.predicate.Predicate;
import com.abmash.core.query.predicate.SelectPredicate;
import com.abmash.core.query.predicate.SubmittablePredicate;
import com.abmash.core.query.predicate.TextPredicate;
import com.abmash.core.query.predicate.TypablePredicate;
import com.abmash.core.query.predicate.XPathPredicate;
/**
* Create new query predicates. Use a static import in your class:
* <pre>
* <code>import static com.abmash.api.query.QueryFactory.*;</code>
* </pre>
* @author Alper Ortac
*/
public class QueryFactory {
/**
* Creates a new query to find elements in the specified browser and with the given predicates, used by calling {@link Browser#query(Predicate...)}.
* <p>
* <strong>Examples:</strong>
* <ul>
* <li><code>browser.query(contains("result")).findFirst();</code> searches for elements containing the attribute or
* inner text <em>result</em></li>
* <li><code>browser.query(headline()).findFirst();</code> searches for title elements, i.e. {@code <h1>}, {@code <h2>}, ... {@code <h6>}
* and any element with a bigger font-size than the default on the current page</li>
* <li><code>browser.query(clickable()).findFirst();</code> searches for all clickable elements like links and buttons</li>
* <li><code>browser.query(image("description"), below(typable("mail")).findFirst();</code> searches for all image elements with the label
* <em>description</em> which are below typable elements labeled <em>mail</em></li>
* </ul>
* <p>
* <strong>Description:</strong>
* <p>
* Create a new query instance by calling <code>browser.query()</code>. Predicates can be chained and arbitrarily nested one after another.
* To get the matching {@link HtmlElements} or {@link HtmlElement}, call {@link Query#find()} or {@link Query#findFirst()}.
*
* @param browser
* @param predicates
* @return the new query object with all predicates
*/
public static Query query(Browser browser, Predicate... predicates) {
return new Query(browser, predicates);
}
/**
* Creates a union of multiple queries by merging their results.
*
* @param queries the queries for the union
* @return new {@link Query} with merged results
*/
public static Query union(Query... queries) {
Query unionQuery = null;
for (Query query: queries) {
if(unionQuery == null) {
unionQuery = query;
} else {
unionQuery.union(query);
}
}
return unionQuery;
}
// -------------------------------------------
// Boolean predicates
// -------------------------------------------
/**
* Defines a boolean "and" predicate. Elements are returned if all given predicates match.
*
* @param predicates all of the predicates need to match to return an element
* @return a boolean "and" predicate which can be arbitrarily nested with other predicates
*/
public static Predicate and(Predicate... predicates) {
return new BooleanPredicate(BooleanType.AND, predicates);
}
/**
* Defines a boolean "or" predicate. Elements are returned if at least on of the given predicates match.
*
* @param predicates at least one of the predicates need to match to return an element
* @return a boolean "or" predicate which can be arbitrarily nested with other predicates
*/
public static Predicate or(Predicate... predicates) {
return new BooleanPredicate(BooleanType.OR, predicates);
}
/**
* Defines a boolean "not" predicate. All elements that match the given predicates will be removed from the result set.
* <p>
* TODO describe standalone "not" predicates
*
* @param predicates all elements that match the predicates will be removed from the result set
* @return a boolean "not" predicate which can be arbitrarily nested with other predicates
*/
public static Predicate not(Predicate... predicates) {
return new BooleanPredicate(BooleanType.NOT, predicates);
}
// -------------------------------------------
// Element and document structure predicates
// -------------------------------------------
/**
* Returns the given {@link HtmlElements} as predicate result.
*
* @param elements the elements are directly passed to the result set
* @return the Predicate returning the provided {@link HtmlElements}
*/
public static Predicate elements(HtmlElements elements) {
return new ElementPredicate(elements);
}
/**
* Returns the given {@link HtmlElements} as predicate result.
*
* @param elements the elements are directly passed to the result set
* @return the Predicate returning the provided {@link HtmlElements}
*/
// public static Predicate insideOf(HtmlElements elements) {
// return new ElementPredicate(elements);
// }
// -------------------------------------------
// JQuery predicates
// -------------------------------------------
/**
* Finds elements that match the given selector (CSS or jQuery).
* <p>
* <strong>Example:</strong>
* <pre>
* select("div#content > p.info:visible > strong[name=author]")
* </pre>
*
* @param selector the jQuery/CSS selector
* @return {@link SelectPredicate}
*/
public static Predicate select(String selector) {
return new SelectPredicate(selector);
}
/**
* Finds elements that match the given XPath selector.
* <p>
* <strong>Example:</strong>
* <pre>
* xpath("//div[id=content]/p[class=info]/strong[name=author]")
* </pre>
*
* @param selector the XPath selector
* @return {@link XPathPredicate}
*/
public static Predicate xPath(String selector) {
return new XPathPredicate(selector);
}
/**
* Finds elements that contain a specific text or attribute value.
* <p>
* <strong>Example:</strong>
* <pre>
* contains("contact me")
* </pre>
*
* @param text case insensitive text
* @return {@link ContainsPredicate}
*/
public static Predicate contains(String text) {
return new ContainsPredicate(text);
}
/**
* Finds text elements that contain a specific text.
* <p>
* <strong>Example:</strong>
* <pre>
* text("lorem ipsum")
* </pre>
*
* @param text case insensitive text
* @return {@link TextPredicate}
*/
public static Predicate text(String text) {
return new TextPredicate(text);
}
/**
* Finds all elements that contain text.
*
* @see QueryFactory#text(String)
* @return {@link TextPredicate}
*/
public static Predicate text() {
return text(null);
}
/**
* Finds title/headline elements that contain a specific text and have a bigger font size than average elements.
* <p>
* <strong>Example:</strong>
* <pre>
* headline("contents")
* </pre>
*
* @param text case insensitive text
* @return {@link HeadlinePredicate}
*/
public static Predicate headline(String text) {
return new HeadlinePredicate(text);
}
/**
* Finds all elements that are titles/headlines or have a bigger font size than average elements.
*
* @see QueryFactory#headline(String)
* @return {@link HeadlinePredicate}
*/
public static Predicate headline() {
return headline(null);
}
/**
* Finds link elements that contain a specific text.
* <p>
* <strong>Example:</strong>
* <pre>
* link("follow me")
* </pre>
*
* @param text case insensitive text
* @return {@link LinkPredicate}
*/
public static Predicate link(String text) {
return new LinkPredicate(text);
}
/**
* Finds all link elements.
*
* @see QueryFactory#link(String)
* @return {@link LinkPredicate}
*/
public static Predicate link() {
return link(null);
}
/**
* Finds clickable elements that contain a specific text.
* <p>
* <strong>Example:</strong>
* <pre>
* clickable("search")
* </pre>
*
* @param text case insensitive text
* @return {@link ClickablePredicate}
*/
public static Predicate clickable(String text) {
return new ClickablePredicate(text);
}
/**
* Finds all clickable elements.
*
* @see QueryFactory#clickable(String)
* @return {@link ClickablePredicate}
*/
public static Predicate clickable() {
return clickable(null);
}
/**
* Finds input elements that can be used to enter text and are labeled with a specific text.
* <p>
* <strong>Example:</strong>
* <pre>
* typable("email")
* </pre>
*
* @param text case insensitive text
* @return {@link TypablePredicate}
*/
public static Predicate typable(String text) {
return new TypablePredicate(text);
}
/**
* Finds all input elements that can be used to enter text.
*
* @see QueryFactory#typable(String)
* @return {@link TypablePredicate}
*/
public static Predicate typable() {
return typable(null);
}
/**
* Finds input elements that can be used to check/uncheck an option and are labeled with a specific text.
* <p>
* <strong>Example:</strong>
* <pre>
* checkable("newsletter")
* </pre>
*
* @param text case insensitive text
* @return {@link CheckablePredicate}
*/
public static Predicate checkable(String text) {
return new CheckablePredicate(text);
}
/**
* Finds all input elements that can be used to check/uncheck an option.
*
* @see QueryFactory#checkable(String)
* @return {@link CheckablePredicate}
*/
public static Predicate checkable() {
return checkable(null);
}
/**
* Finds input elements that can be used to choose from multiple options and are labeled with a specific text.
* <p>
* <strong>Example:</strong>
* <pre>
* choosable("ingredients")
* </pre>
*
* @param text case insensitive text
* @return {@link ChoosablePredicate}
*/
public static Predicate choosable(String text) {
return new ChoosablePredicate(text);
}
/**
* Finds all input elements that can be used to choose from multiple options.
*
* @see QueryFactory#choosable(String)
* @return {@link ChoosablePredicate}
*/
public static Predicate choosable() {
return choosable(null);
}
/**
* Finds input elements that can be used to select a date and are labeled with a specific text.
* <p>
* <strong>Example:</strong>
* <pre>
* datepicker("departure")
* </pre>
*
* @param text case insensitive text
* @return {@link DatepickerPredicate}
*/
public static Predicate datepicker(String text) {
return new DatepickerPredicate(text);
}
/**
* Finds input elements that can be used to select a date.
*
* @see QueryFactory#datepicker(String)
* @return {@link DatepickerPredicate}
*/
public static Predicate datepicker() {
return datepicker(null);
}
/**
* Finds input elements that can be used to submit a form and are labeled with a specific text.
* <p>
* <strong>Example:</strong>
* <pre>
* submittable("purchase")
* </pre>
*
* @param text case insensitive text
* @return {@link SubmittablePredicate}
*/
public static Predicate submittable(String text) {
return new SubmittablePredicate(text);
}
/**
* Finds input elements that can be used to submit a form.
*
* @see QueryFactory#submittable(String)
* @return {@link SubmittablePredicate}
*/
public static Predicate submittable() {
return submittable(null);
}
/**
* Finds image elements that are labeled/captioned with a specific text.
* <p>
* <strong>Example:</strong>
* <pre>
* image("statistics last year")
* </pre>
*
* @param text case insensitive text
* @return {@link ImagePredicate}
*/
public static Predicate image(String text) {
return new ImagePredicate(text);
}
/**
* Finds all image elements.
*
* @see QueryFactory#image(String)
* @return {@link ImagePredicate}
*/
public static Predicate image() {
return image(null);
}
/**
* Finds frames and iframe elements that are labeled/captioned with a specific text.
* <p>
* <strong>Example:</strong>
* <pre>
* frame("information")
* </pre>
*
* @param text case insensitive text
* @return {@link FramePredicate}
*/
public static Predicate frame(String text) {
return new FramePredicate(text);
}
// -------------------------------------------
// Color predicates
// -------------------------------------------
/**
* Finds elements that match the desired color. Performs slow if no other predicates are used.
* <p>
* Tolerance: Lower values mean a lower tolerance regarding the color distance between the given color
* and the pixels of an element to select it.
* <p>
* Dominance: Lower values mean a lower percentage of pixels containing the specified color needed to select an element.
*
* @param color the result elements have a similar color as the specified {@link Color}
* @param tolerance the higher the tolerance, the more distant colors are matching.
* <code>1</code> is always true and <code>0</code> is only true if the image has enough dominant pixels with that exact color
* @param dominance the higher the dominance, the less percent of the element can be covered by other colors
* <code>0</code> is always true and <code>1</code> is only true if the image has exclusively colors within the tolerance range
* @see Tolerance
* @see Dominance
* @return {@link ColorPredicate}
*/
public static Predicate color(Color color, double tolerance, double dominance) {
return new ColorPredicate(color, tolerance, dominance);
}
/**
* Finds elements that match the desired color. See {@link #color(Color, double, double)} for details.
*
* @param color the result elements have a similar color as the specified {@link Color}
* @param tolerance the higher the tolerance, the more distant colors are matching
* @param dominance the higher the dominance, the less percent of the element can be covered by other colors
* @return {@link ColorPredicate}
*/
public static Predicate color(Color color, Tolerance tolerance, Dominance dominance) {
return color(color, tolerance.getValue(), dominance.getValue());
}
/**
* Finds elements that match the desired color. See {@link #color(Color, double, double)} for details.
*
* @param colorName the result elements have a similar color as the specified {@link ColorName}
* @param tolerance the higher the tolerance, the more distant colors are matching
* @param dominance the higher the dominance, the less percent of the element can be covered by other colors
* @return {@link ColorPredicate}
*/
public static Predicate color(ColorName colorName, double tolerance, double dominance) {
return color(colorName.getColor(), tolerance, dominance);
}
/**
* Finds elements that match the desired color. See {@link #color(Color, double, double)} for details.
*
* @param colorName the result elements have a similar color as the specified {@link ColorName}
* @param tolerance the higher the tolerance, the more distant colors are matching
* @param dominance the higher the dominance, the less percent of the element can be covered by other colors
* @return {@link ColorPredicate}
*/
public static Predicate color(ColorName colorName, Tolerance tolerance, Dominance dominance) {
return color(colorName.getColor(), tolerance.getValue(), dominance.getValue());
}
/**
* Finds elements that match the desired color. Tolerance and dominance are set to intermediate values.
* See {@link #color(Color, double, double)} for details.
*
* @param color the result elements have a similar color as the specified {@link Color}
* @return {@link ColorPredicate}
*/
public static Predicate color(Color color) {
return color(color, Tolerance.MIDHIGH, Dominance.MIDHIGH);
}
/**
* Finds elements that match the desired color. Tolerance and dominance are set to intermediate values.
* See {@link #color(Color, double, double)} for details.
*
* @param colorName the result elements have a similar color as the specified {@link ColorName}
* @return {@link ColorPredicate}
*/
public static Predicate color(ColorName colorName) {
return color(colorName.getColor());
}
// -------------------------------------------
// Direction predicates
// -------------------------------------------
/**
* Finds elements visually close to the elements that match the given predicates. The result is dependent on the current
* browser window size.
* <p>
* The {@link DirectionOptions} if found elements will be filtered out in case they are visually at another location.
* The found elements will be automatically ordered by closeness to the referenceElements.
* The distance is calculated by the euclidean measure.
* <p>
* Use the shortcuts of this method if needed. See ({@link #above(Predicate...)}, {@link #below(Predicate...)},
* {@link #leftOf(Predicate...)} and {@link #rightOf(Predicate...)}.
* <p>
* Calling {@link Query#find()} will order the result by closeness, so that the first result is the closest element to
* the reference element.
*
* @param options the parameters of this predicate, including maximum distance and allowed directions
* @param predicates the result elements are close to the elements determined by this predicates
* @return {@link DirectionPredicate}
*/
public static Predicate closeTo(DirectionOptions options, Predicate... predicates) {
return new DirectionPredicate(options, predicates);
}
/**
* Finds elements visually close to the given {@link HtmlElements}. See {@link #closeTo(Predicate...)} for details.
*
* @see QueryFactory#closeTo(DirectionOptions, Predicate...)
* @param options the parameters of this predicate, including maximum distance and allowed directions
* @param elements the result elements are close to these {@link HtmlElements}
* @return {@link DirectionPredicate}
*/
public static Predicate closeTo(DirectionOptions options, HtmlElements elements) {
return closeTo(options, new ElementPredicate(elements));
}
/**
* Finds elements visually close to the given {@link HtmlElement}. See {@link #closeTo(Predicate...)} for details.
*
* @see QueryFactory#closeTo(DirectionOptions, Predicate...)
* @param options the parameters of this predicate, including maximum distance and allowed directions
* @param element the result elements are close to this {@link HtmlElement}
* @return {@link DirectionPredicate}
*/
public static Predicate closeTo(DirectionOptions options, HtmlElement element) {
return closeTo(options, new ElementPredicate(new HtmlElements(element)));
}
/**
* Finds elements visually close to the elements that match the given predicates, with a maximum distance. See {@link #closeTo(Predicate...)} for details.
*
* @see QueryFactory#closeTo(DirectionOptions, Predicate...)
* @param maxDistance the result elements` allowed maximum distance to the predicate results in pixels
* @param predicates the result elements are close to the elements determined by this predicates
* @return {@link DirectionPredicate}
*/
public static Predicate closeTo(int maxDistance, Predicate... predicates) {
return closeTo(new DirectionOptions(DirectionType.CLOSETO).setMaxDistance(maxDistance), predicates);
}
/**
* Finds elements visually close to the given {@link HtmlElements}, with a maximum distance. See {@link #closeTo(Predicate...)} for details.
*
* @see QueryFactory#closeTo(DirectionOptions, Predicate...)
* @param maxDistance the result elements` allowed maximum distance to the predicate results in pixels
* @param elements the result elements are close to these {@link HtmlElements}
* @return {@link DirectionPredicate}
*/
public static Predicate closeTo(int maxDistance, HtmlElements elements) {
return closeTo(maxDistance, new ElementPredicate(elements));
}
/**
* Finds elements visually close to the given {@link HtmlElement}, with a maximum distance. See {@link #closeTo(Predicate...)} for details.
*
* @see QueryFactory#closeTo(DirectionOptions, Predicate...)
* @param maxDistance the result elements` allowed maximum distance to the predicate results in pixels
* @param element the result elements are close to this {@link HtmlElement}
* @return {@link DirectionPredicate}
*/
public static Predicate closeTo(int maxDistance, HtmlElement element) {
return closeTo(maxDistance, new HtmlElements(element));
}
/**
* Finds elements visually close to the elements that match the given predicates, with a maximum distance of 300 pixels. See {@link #closeTo(Predicate...)} for details.
*
* TODO make constant of 300 pixels configurable
*
* @see QueryFactory#closeTo(DirectionOptions, Predicate...)
* @param predicates the result elements are close to the elements determined by this predicates
* @return {@link DirectionPredicate}
*/
public static Predicate closeTo(Predicate... predicates) {
return closeTo(300, predicates);
}
/**
* Finds elements visually close to the given {@link HtmlElements}, with a maximum distance of 300 pixels. See {@link #closeTo(Predicate...)} for details.
*
* TODO make constant of 300 pixels configurable
*
* @see QueryFactory#closeTo(DirectionOptions, Predicate...)
* @param elements the result elements are close to these {@link HtmlElements}
* @return {@link DirectionPredicate}
*/
public static Predicate closeTo(HtmlElements elements) {
return closeTo(new ElementPredicate(elements));
}
/**
* Finds elements visually close to the given {@link HtmlElement}, with a maximum distance of 300 pixels. See {@link #closeTo(Predicate...)} for details.
*
* TODO make constant of 300 pixels configurable
*
* @see QueryFactory#closeTo(DirectionOptions, Predicate...)
* @param element the result elements are close to these {@link HtmlElement}
* @return {@link DirectionPredicate}
*/
public static Predicate closeTo(HtmlElement element) {
return closeTo(new HtmlElements(element));
}
/**
* Finds elements visually <strong>above</strong> the elements that match the given predicates.
* <p>
* Elements are above if their bottom y coordinate is equal or lower than the top y coordinate of the reference element.
* <s>In addition, the element has to be in horizontal bounds of the reference element.</s>
* <p>
* <strong>Example:</strong> (visual representation of the web page)
* <pre>{@code
* .
* ----------
* - <span> -
* ----------
* ---------
* - <div> -
* ---------
* --------
* - <ul> -
* --------
* }</pre>
* In this example, both the {@code <div>} and the {@code <span>} are above the {@code <ul>}.
* Also, the {@code <span>} is above the {@code <div>}, but the {@code <ul>} is not.
* <p>
* See {@link QueryFactory#closeTo(DirectionOptions, Predicate...)} for more details.
*
* @see QueryFactory#closeTo(DirectionOptions, Predicate...)
* @param predicates the result elements are above the elements determined by this predicates
* @return {@link DirectionPredicate}
*/
public static Predicate above(Predicate... predicates) {
return closeTo(new DirectionOptions(DirectionType.ABOVE), predicates);
}
/**
* Finds elements visually <strong>above</strong> the given {@link HtmlElements}. See {@link #above(Predicate...)} for details.
*
* @see #above(Predicate...)
* @param elements the result elements are above these {@link HtmlElements}
* @return {@link DirectionPredicate}
*/
public static Predicate above(HtmlElements elements) {
return above(new ElementPredicate(elements));
}
/**
* Finds elements visually <strong>above</strong> the given {@link HtmlElement}. See {@link #above(Predicate...)} for details.
*
* @see #above(Predicate...)
* @param element the result elements are above this {@link HtmlElement}
* @return {@link DirectionPredicate}
*/
public static Predicate above(HtmlElement element) {
return above(new HtmlElements(element));
}
/**
* Finds elements visually <strong>above</strong> the elements that match the given predicates.
* <p>
* Elements are below if their top y coordinate is equal or greater than the bottom y coordinate of the reference element.
* <s>In addition, the element has to be in horizontal bounds of the reference element.</s>
* <p>
* <strong>Example:</strong> (visual representation of the web page)
* <pre>{@code
* .
* --------
* - <ul> -
* --------
* ---------
* - <div> -
* ---------
* ----------
* - <span> -
* ----------
* }</pre>
* In this example, the {@code <div>} and the {@code <span>} are below the {@code <ul>}.
* Also, the {@code <span>} is below the {@code <div>}, but the {@code <ul>} is not.
* <p>
* See {@link QueryFactory#closeTo(DirectionOptions, Predicate...)} for more details.
*
* @see QueryFactory#closeTo(DirectionOptions, Predicate...)
* @param predicates the result elements are above the elements determined by this predicates
* @return {@link DirectionPredicate}
*/
public static Predicate below(Predicate... predicates) {
return closeTo(new DirectionOptions(DirectionType.BELOW), predicates);
}
/**
* Finds elements visually <strong>below</strong> the given {@link HtmlElements}. See {@link #below(Predicate...)} for details.
*
* @see #below(Predicate...)
* @param elements the result elements are below these {@link HtmlElements}
* @return {@link DirectionPredicate}
*/
public static Predicate below(HtmlElements elements) {
return below(new ElementPredicate(elements));
}
/**
* Finds elements visually <strong>below</strong> the given {@link HtmlElement}. See {@link #below(Predicate...)} for details.
*
* @see #below(Predicate...)
* @param element the result elements are below this {@link HtmlElement}
* @return {@link DirectionPredicate}
*/
public static Predicate below(HtmlElement element) {
return below(new HtmlElements(element));
}
/**
* Finds elements visually <strong>left of</strong> the elements that match the given predicates.
* <p>
* Elements are left of if their right x coordinate is equal or lower than the left x coordinate of the reference element.
* <s>In addition, the element has to be in vertical bounds of the reference element.</s>
* <p>
* <strong>Example:</strong> (visual representation of the web page)
* <pre>{@code
* .
* ----------
* -------- - <span> -
* - <ul> - ----------
* -------- ---------
* - <div> -
* ---------
* }</pre>
* In this example, the {@code <ul>} is left of the {@code <span>} and the {@code <div>}, but the {@code <div>} is
* not left of the {@code <span>}, because its right border is overlapping the left border of the {@code <span>}.
* <p>
* See {@link QueryFactory#closeTo(DirectionOptions, Predicate...)} for more details.
*
* @see QueryFactory#closeTo(DirectionOptions, Predicate...)
* @param predicates the result elements are above the elements determined by this predicates
* @return {@link DirectionPredicate}
*/
public static Predicate leftOf(Predicate... predicates) {
return closeTo(new DirectionOptions(DirectionType.LEFTOF), predicates);
}
/**
* Finds elements visually <strong>left of</strong> the given {@link HtmlElements}. See {@link #leftOf(Predicate...)} for details.
*
* @see #leftOf(Predicate...)
* @param elements the result elements are left of these {@link HtmlElements}
* @return {@link DirectionPredicate}
*/
public static Predicate leftOf(HtmlElements elements) {
return leftOf(new ElementPredicate(elements));
}
/**
* Finds elements visually <strong>left of</strong> the given {@link HtmlElement}. See {@link #leftOf(Predicate...)} for details.
*
* @see #leftOf(Predicate...)
* @param element the result elements are left of this {@link HtmlElement}
* @return {@link DirectionPredicate}
*/
public static Predicate leftOf(HtmlElement element) {
return leftOf(new HtmlElements(element));
}
/**
* Finds elements visually <strong>right of</strong> the elements that match the given predicates.
* <p>
* Elements are right of if their left x coordinate is higher than the right x coordinate of the reference element.
* <s>In addition, the element has to be in vertical bounds of the reference element.</s>
* <p>
* <strong>Example:</strong> (visual representation of the web page)
* <pre>{@code
* .
* ----------
* -------- - <span> -
* - <ul> - ----------
* -------- ---------
* - <div> -
* ---------
* }</pre>
* In this example, the {@code <span>} and the {@code <div>} are right of the {@code <ul>}, but the {@code <span>}
* is not right of the {@code <div>} because its left border is overlapping the right border of the {@code <span>}.
* <p>
* See {@link QueryFactory#closeTo(DirectionOptions, Predicate...)} for more details.
*
* @see QueryFactory#closeTo(DirectionOptions, Predicate...)
* @param predicates the result elements are above the elements determined by this predicates
* @return {@link DirectionPredicate}
*/
public static Predicate rightOf(Predicate... predicates) {
return closeTo(new DirectionOptions(DirectionType.RIGHTOF), predicates);
}
/**
* Finds elements visually <strong>right of</strong> the given {@link HtmlElements}. See {@link #rightOf(Predicate...)} for details.
*
* @see #rightOf(Predicate...)
* @param elements the result elements are left of these {@link HtmlElements}
* @return {@link DirectionPredicate}
*/
public static Predicate rightOf(HtmlElements elements) {
return rightOf(new ElementPredicate(elements));
}
/**
* Finds elements visually <strong>right of</strong> the given {@link HtmlElement}. See {@link #rightOf(Predicate...)} for details.
*
* @see #rightOf(Predicate...)
* @param element the result elements are left of this {@link HtmlElement}
* @return {@link DirectionPredicate}
*/
public static Predicate rightOf(HtmlElement element) {
return rightOf(new HtmlElements(element));
}
/**
* Finds elements visually <strong>above all</strong> the elements that match the given predicates.
* <p>
* <strong>Example:</strong> (visual representation of the web page)
* <pre>{@code
* .
* ----------
* - <span> -
* ----------
* --------- --------
* - <div> - - <ul> -
* --------- --------
* -------- ---------
* - <ul> - - <div> -
* -------- ---------
* }</pre>
* In this example, only the {@code <span>} is above all the {@code <ul>} (or {@code <div>} respectively).
* <p>
* See {@link QueryFactory#closeTo(DirectionOptions, Predicate...)} for more details.
*
* @see QueryFactory#closeTo(DirectionOptions, Predicate...)
* @see QueryFactory#above(Predicate...)
* @param predicates the result elements are above the elements determined by this predicates
* @return {@link DirectionPredicate}
*/
public static Predicate aboveAll(Predicate... predicates) {
return closeTo(new DirectionOptions(DirectionType.ABOVE).setDirectionHasToMatchAllTargets(true), predicates);
}
/**
* Finds elements visually <strong>above all</strong> the elements that match the given {@link HtmlElements}.
* See {@link #aboveAll(Predicate...)} for more details.
*
* @see QueryFactory#aboveAll(Predicate...)
* @param elements the result elements are above all these {@link HtmlElements}
* @return {@link DirectionPredicate}
*/
public static Predicate aboveAll(HtmlElements elements) {
return aboveAll(new ElementPredicate(elements));
}
/**
* Finds elements visually <strong>above all</strong> the elements that match the given {@link HtmlElement}.
* See {@link #aboveAll(Predicate...)} for more details.
*
* @see QueryFactory#aboveAll(Predicate...)
* @param element the result elements are above all this {@link HtmlElement}
* @return {@link DirectionPredicate}
*/
public static Predicate aboveAll(HtmlElement element) {
return aboveAll(new HtmlElements(element));
}
/**
* Finds elements visually <strong>below all</strong> the elements that match the given predicates.
* <p>
* <strong>Example:</strong> (visual representation of the web page)
* <pre>{@code
* .
* -------- ---------
* - <ul> - - <div> -
* -------- ---------
* --------- --------
* - <div> - - <ul> -
* --------- --------
* ----------
* - <span> -
* ----------
* }</pre>
* In this example, only the {@code <span>} is below all the {@code <ul>} (or {@code <div>} respectively).
* <p>
* See {@link QueryFactory#closeTo(DirectionOptions, Predicate...)} for more details.
*
* @see QueryFactory#closeTo(DirectionOptions, Predicate...)
* @see QueryFactory#below(Predicate...)
* @param predicates the result elements are above the elements determined by this predicates
* @return {@link DirectionPredicate}
*/
public static Predicate belowAll(Predicate... predicates) {
return closeTo(new DirectionOptions(DirectionType.BELOW).setDirectionHasToMatchAllTargets(true), predicates);
}
/**
* Finds elements visually <strong>below all</strong> the elements that match the given {@link HtmlElements}.
* See {@link #belowAll(Predicate...)} for more details.
*
* @see QueryFactory#belowAll(Predicate...)
* @param elements the result elements are below all these {@link HtmlElements}
* @return {@link DirectionPredicate}
*/
public static Predicate belowAll(HtmlElements elements) {
return belowAll(new ElementPredicate(elements));
}
/**
* Finds elements visually <strong>below all</strong> the elements that match the given {@link HtmlElement}.
* See {@link #belowAll(Predicate...)} for more details.
*
* @see QueryFactory#belowAll(Predicate...)
* @param element the result elements are below all this {@link HtmlElement}
* @return {@link DirectionPredicate}
*/
public static Predicate belowAll(HtmlElement element) {
return belowAll(new HtmlElements(element));
}
/**
* Finds elements visually <strong>left of all</strong> the elements that match the given predicates.
* <p>
* <strong>Example:</strong> (visual representation of the web page)
* <pre>{@code
* .
* --------
* - <ul> -
* --------- --------
* - <div> -
* ---------- ---------
* - <span> -
* ---------- ---------
* - <ul> -
* -------- ---------
* - <div> -
* ---------
* }</pre>
* In this example, only the {@code <span>} is left of all the {@code <ul>} (or {@code <div>} respectively).
* <p>
* See {@link QueryFactory#closeTo(DirectionOptions, Predicate...)} for more details.
*
* @see QueryFactory#closeTo(DirectionOptions, Predicate...)
* @see QueryFactory#leftOf(Predicate...)
* @param predicates the result elements are above the elements determined by this predicates
* @return {@link DirectionPredicate}
*/
public static Predicate leftOfAll(Predicate... predicates) {
return closeTo(new DirectionOptions(DirectionType.LEFTOF).setDirectionHasToMatchAllTargets(true), predicates);
}
/**
* Finds elements visually <strong>left of all</strong> the elements that match the given {@link HtmlElements}.
* See {@link #leftOfAll(Predicate...)} for more details.
*
* @see QueryFactory#leftOfAll(Predicate...)
* @param elements the result elements are left of all these {@link HtmlElements}
* @return {@link DirectionPredicate}
*/
public static Predicate leftOfAll(HtmlElements elements) {
return leftOfAll(new ElementPredicate(elements));
}
/**
* Finds elements visually <strong>left of all</strong> the elements that match the given {@link HtmlElement}.
* See {@link #leftOfAll(Predicate...)} for more details.
*
* @see QueryFactory#leftOfAll(Predicate...)
* @param element the result elements are left of all this {@link HtmlElement}
* @return {@link DirectionPredicate}
*/
public static Predicate leftOfAll(HtmlElement element) {
return leftOfAll(new HtmlElements(element));
}
/**
* Finds elements visually <strong>right of all</strong> the elements that match the given predicates.
* <p>
* <strong>Example:</strong> (visual representation of the web page)
* <pre>{@code
* .
* ---------
* - <div> -
* --------- --------
* - <ul> -
* -------- ----------
* - <span> -
* --------- ----------
* - <div> -
* -------- ---------
* - <ul> -
* --------
* }</pre>
* In this example, only the {@code <span>} is right of all the {@code <ul>} (or {@code <div>} respectively).
* <p>
* See {@link QueryFactory#closeTo(DirectionOptions, Predicate...)} for more details.
*
* @see QueryFactory#closeTo(DirectionOptions, Predicate...)
* @see QueryFactory#rightOf(Predicate...)
* @param predicates the result elements are above the elements determined by this predicates
* @return {@link DirectionPredicate}
*/
public static Predicate rightOfAll(Predicate... predicates) {
return closeTo(new DirectionOptions(DirectionType.RIGHTOF).setDirectionHasToMatchAllTargets(true), predicates);
}
/**
* Finds elements visually <strong>right of all</strong> the elements that match the given {@link HtmlElements}.
* See {@link #rightOfAll(Predicate...)} for more details.
*
* @see QueryFactory#rightOfAll(Predicate...)
* @param elements the result elements are right of all these {@link HtmlElements}
* @return {@link DirectionPredicate}
*/
public static Predicate rightOfAll(HtmlElements elements) {
return rightOfAll(new ElementPredicate(elements));
}
/**
* Finds elements visually <strong>right of all</strong> the elements that match the given {@link HtmlElement}.
* See {@link #rightOfAll(Predicate...)} for more details.
*
* @see QueryFactory#rightOfAll(Predicate...)
* @param element the result elements are right of all this {@link HtmlElement}
* @return {@link DirectionPredicate}
*/
public static Predicate rightOfAll(HtmlElement element) {
return rightOfAll(new HtmlElements(element));
}
}