package com.abmash.REMOVE.core.htmlquery.condition;
import java.util.TreeSet;
import com.abmash.REMOVE.core.element.distance.ElementDistanceComparator;
import com.abmash.REMOVE.core.element.distance.ElementDistanceComparator.CalculationType;
import com.abmash.REMOVE.core.element.distance.ElementDistanceComparator.DistanceType;
import com.abmash.REMOVE.core.htmlquery.selector.JQuerySelector;
import com.abmash.REMOVE.core.htmlquery.selector.SelectorGroup;
import com.abmash.api.HtmlElement;
import com.abmash.api.HtmlElements;
public class ClosenessCondition extends Condition {
final static int MAX_REFERENCE_ELEMENTS = 10;
/**
* Direction for closeness conditions
*/
public enum Direction {
/**
* The searched element is close to the/any reference element.
*/
CLOSE,
/**
* The searched element is an input field close to the/any reference element.
*/
INPUT,
/**
* The searched element is a select, checkbox or radio field close to the/any reference element.
*/
SELECT,
/**
* The searched element is above the/any reference element.
*/
ABOVE,
/**
* The searched element is below the/any reference element.
*/
BELOW,
/**
* The searched element is left to the/any reference element.
*/
LEFT,
/**
* The searched element is right to the/any reference element.
*/
RIGHT,
/**
* The searched element is above all reference elements.
*/
ABOVE_ALL,
/**
* The searched element is below all reference elements.
*/
BELOW_ALL,
/**
* The searched element is left to all reference elements.
*/
LEFT_ALL,
/**
* The searched element is right to all reference elements.
*/
RIGHT_ALL,
}
private Direction direction;
private SelectorGroup group = new SelectorGroup();
// constructors
public ClosenessCondition(HtmlElements referenceElements, Direction direction) {
group.addReferenceElements(referenceElements);
this.direction = direction;
}
// condition
// @Override
// public boolean isElementFinder() {
// // this is not an element finder, closeness conditions are executed in the end
// return false;
// }
@Override
protected void buildSelectors() {
// jquery closeness selectors
switch (direction) {
case CLOSE:
group.add(new JQuerySelector("closeTo(abmash.getData('referenceElements'))"));
break;
case INPUT:
group.add(new JQuerySelector("hasLabel(abmash.getData('referenceElements'))"));
break;
case SELECT:
group.add(new JQuerySelector("hasLabelForSelect(abmash.getData('referenceElements'))"));
break;
case ABOVE:
group.add(new JQuerySelector("above(abmash.getData('referenceElements'))"));
break;
case BELOW:
group.add(new JQuerySelector("below(abmash.getData('referenceElements'))"));
break;
case LEFT:
group.add(new JQuerySelector("leftTo(abmash.getData('referenceElements'))"));
break;
case RIGHT:
group.add(new JQuerySelector("rightTo(abmash.getData('referenceElements'))"));
break;
case ABOVE_ALL:
group.add(new JQuerySelector("aboveAll(abmash.getData('referenceElements'))"));
break;
case BELOW_ALL:
group.add(new JQuerySelector("belowAll(abmash.getData('referenceElements'))"));
break;
case LEFT_ALL:
group.add(new JQuerySelector("leftToAll(abmash.getData('referenceElements'))"));
break;
case RIGHT_ALL:
group.add(new JQuerySelector("rightToAll(abmash.getData('referenceElements'))"));
break;
}
if(!group.isEmpty()) selectorGroups.add(group);
}
// @Override
// public HtmlElements sortElements(HtmlElements unsortedElements) {
// HtmlElements sortedElements = new HtmlElements();
//
// DistanceType distanceType;
// CalculationType calculationType = CalculationType.MIN;
//
// switch (direction) {
// case INPUT:
// distanceType = DistanceType.TOPLEFT;
// break;
// case ABOVE_ALL:
// calculationType = CalculationType.AVERAGE;
// case ABOVE:
// distanceType = DistanceType.BOTTOMLEFT;
// break;
// case BELOW_ALL:
// calculationType = CalculationType.AVERAGE;
// case BELOW:
// distanceType = DistanceType.TOPLEFT;
// break;
// case LEFT_ALL:
// calculationType = CalculationType.AVERAGE;
// case LEFT:
// distanceType = DistanceType.RIGHT;
// break;
// case RIGHT_ALL:
// calculationType = CalculationType.AVERAGE;
// case RIGHT:
// distanceType = DistanceType.LEFT;
// break;
// case CLOSE:
// default:
// distanceType = DistanceType.DEFAULT;
// break;
// }
//
// TreeSet<HtmlElement> elementSet = new TreeSet<HtmlElement>(new ElementDistanceComparator(distanceType, calculationType));
//
// // TODO higher weight for reference elements in the beginning of the list
//
//// System.out.println("reference elements: " + group.getReferenceElements());
// for (HtmlElement foundElement: unsortedElements) {
// // TODO allow reference elements in result
// if(!group.getReferenceElements().contains(foundElement) && elementValid(foundElement)) {
// // TODO speichern der reference elemente globaler?
// foundElement.setReferenceElements(group.getReferenceElements());
//// System.out.println("ADDED valid found element: " + foundElement);
// // add if element is in allowed location
// elementSet.add(foundElement); // ordered by closeness
// }
// }
//
// // build sorted element result set
// for (HtmlElement element: elementSet) {
// sortedElements.addAndIgnoreDuplicates(element);
// }
//
// return sortedElements;
// }
//
// public boolean elementValid(HtmlElement foundElement) {
// if(!super.elementValid(foundElement)) return false;
//
// for (HtmlElement referenceElement: referenceElements) {
//
//// System.out.println("CLOSENESS: " + foundElement + " vs. " + referenceElement);
//// System.out.println("FOUND location: [" + foundElement.getLocation() + "] + size: [" + foundElement.getSize());
//// System.out.println("REFER location: [" + referenceElement.getLocation() + "] + size: [" + referenceElement.getSize());
//// System.out.println("HORIZ BOUNDS: " + inHorizontalBounds(foundElement, referenceElement));
//// System.out.println("VERTI BOUNDS: " + inVerticalBounds(foundElement, referenceElement));
// switch (direction) {
// case INPUT:
// // only allow elements below or right of the reference element
// if(below(foundElement, referenceElement) || right(foundElement, referenceElement)) {
// return true;
// }
// break;
// case ABOVE:
//// System.out.println("ABOVE: " + above(foundElement, referenceElement));
// case ABOVE_ALL:
// // only allow elements above the reference element
// if(above(foundElement, referenceElement) && inHorizontalBounds(foundElement, referenceElement)) {
// if(direction == Direction.ABOVE) return true;
// } else if(direction == Direction.ABOVE_ALL) {
// return false;
// }
// break;
// case BELOW:
//// System.out.println("BELOW: " + below(foundElement, referenceElement));
// case BELOW_ALL:
// // only allow elements below the reference element
// if(below(foundElement, referenceElement) && inHorizontalBounds(foundElement, referenceElement)) {
// if(direction == Direction.BELOW) return true;
// } else if(direction == Direction.BELOW_ALL) {
// return false;
// }
// break;
// case LEFT:
//// System.out.println("CLOSENESS: " + foundElement + " vs. " + referenceElement);
//// System.out.println("LEFTTO: " + left(foundElement, referenceElement));
//// System.out.println("VERTIC BOUNDS: " + inVerticalBounds(foundElement, referenceElement));
// case LEFT_ALL:
// // only allow elements in the left of the reference element
// if(left(foundElement, referenceElement) && inVerticalBounds(foundElement, referenceElement)) {
// if(direction == Direction.LEFT) return true;
// } else if(direction == Direction.LEFT_ALL) {
// return false;
// }
// break;
// case RIGHT:
//// System.out.println("RIGHTTO: " + right(foundElement, referenceElement));
// case RIGHT_ALL:
// // only allow elements in the right of the reference element
// if(right(foundElement, referenceElement) && inVerticalBounds(foundElement, referenceElement)) {
// if(direction == Direction.RIGHT) return true;
// } else if(direction == Direction.RIGHT_ALL) {
// return false;
// }
// break;
// case CLOSE:
// default:
// return true;
// }
// }
//
// // location is valid if all reference elements were checked
// boolean isValidLocation = false;
// if(direction == Direction.ABOVE_ALL || direction == Direction.BELOW_ALL || direction == Direction.LEFT_ALL || direction == Direction.RIGHT_ALL) {
// isValidLocation = true;
// }
//
// return isValidLocation;
// }
//
// private boolean above(HtmlElement foundElement, HtmlElement referenceElement) {
// Location foundLocation = foundElement.getLocation();
// Location referenceLocation = referenceElement.getLocation();
// Size foundSize = foundElement.getSize();
//
// return foundLocation.getY() + foundSize.getHeight() <= referenceLocation.getY();
// }
//
// private boolean below(HtmlElement foundElement, HtmlElement referenceElement) {
// Location foundLocation = foundElement.getLocation();
// Location referenceLocation = referenceElement.getLocation();
// Size referenceSize = referenceElement.getSize();
//
// return foundLocation.getY() >= referenceLocation.getY() + referenceSize.getHeight();
// }
//
// private boolean left(HtmlElement foundElement, HtmlElement referenceElement) {
// Location foundLocation = foundElement.getLocation();
// Location referenceLocation = referenceElement.getLocation();
// Size foundSize = foundElement.getSize();
//
// return foundLocation.getX() + foundSize.getWidth() <= referenceLocation.getX();
// }
//
// private boolean right(HtmlElement foundElement, HtmlElement referenceElement) {
// Location foundLocation = foundElement.getLocation();
// Location referenceLocation = referenceElement.getLocation();
// Size referenceSize = referenceElement.getSize();
//
// return foundLocation.getX() >= referenceLocation.getX() + referenceSize.getWidth();
// }
//
// private boolean inVerticalBounds(HtmlElement foundElement, HtmlElement referenceElement) {
// return !above(foundElement, referenceElement) && !below(foundElement, referenceElement);
// }
//
// private boolean inHorizontalBounds(HtmlElement foundElement, HtmlElement referenceElement) {
// return !left(foundElement, referenceElement) && !right(foundElement, referenceElement);
// }
public String toString() {
return super.toString() + " with direction [" + direction + "] and reference elements [" + group.getReferenceElements() + "]";
}
}