package com.smash.revolance.ui.model.element.api; /* * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * Revolance-UI-Model * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * Copyright (C) 2012 - 2013 RevoLance * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program. If not, see * <http://www.gnu.org/licenses/gpl-3.0.html>. * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ /* This file is part of Revolance UI Suite. Revolance UI Suite is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Revolance UI Suite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Revolance UI Suite. If not, see <http://www.gnu.org/licenses/>. */ import com.smash.revolance.ui.materials.JsonHelper; import com.smash.revolance.ui.model.diff.DiffCondition; import com.smash.revolance.ui.model.diff.ElementDiffType; import com.smash.revolance.ui.model.page.api.PageBean; import org.codehaus.jackson.annotate.JsonAutoDetect; import org.codehaus.jackson.annotate.JsonIgnore; import org.openqa.selenium.Dimension; import org.openqa.selenium.Point; import java.awt.*; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.NoSuchElementException; import java.util.UUID; /** * User: wsmash * Date: 28/02/13 * Time: 18:51 */ @JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.NONE, isGetterVisibility = JsonAutoDetect.Visibility.NONE) public class ElementBean implements Comparable<ElementBean> { private String internalId = ""; // Location & Area of the element private int x, y, w, h; // UI look of the element private String caption = ""; // HTML description of the element private String tag = ""; private String id = ""; private String clz = ""; private String txt = ""; private String type = ""; private String href = ""; private String value = ""; private String target = ""; // What king of element is this? // Can be anyone of 'Link', 'Button', 'Input', 'Data' or an 'Image' private String impl = ""; // The background file of the element private String bg = ""; // Alternative content rendered when the 'Image' cannot be displayed private String alt = ""; // bot functional data private boolean clicked = false; // When the page contains a broken link private boolean broken = false; // Clicking on an element, we should see a change (url or dynamic content udpate) private boolean disabled = false; // URLs are relative but those outside the user's domain are absolute private boolean external = false; @JsonIgnore private PageBean page; @JsonIgnore private Element instance; //+ Constructors public ElementBean() { setInternalId( UUID.randomUUID().toString() ); } public ElementBean(Element instance) { this(); setInstance( instance ); } //- Constructors //+ Getters / Setters public void setClicked(boolean clicked) { this.clicked = clicked; } public void setId(String id) { if ( id != null ) this.id = id; } public String getId() { return id; } public void setHref(String href) { if ( href != null ) this.href = href; } public String getHref() { return href; } public boolean hasBeenClicked() { return clicked; } public void setTag(String tag) { if ( tag != null ) this.tag = tag; } public String getTag() { return tag; } public void setClz(String clz) { if ( clz != null ) this.clz = clz; } public String getClz() { return clz; } public void setDim(Dimension dim) { if ( dim != null ) { this.w = dim.getWidth(); this.h = dim.getHeight(); } } public Dimension getDim() { return new Dimension( w, h ); } public void setPos(Point pos) { if ( pos != null ) { this.x = pos.getX(); this.y = pos.getY(); } } public Point getPos() { return new Point( x, y ); } public void setType(String type) { if ( type != null ) this.type = type; } public String getType() { return type; } public void setText(String txt) { if ( txt != null ) this.txt = txt; } public String getText() { return txt; } public void setValue(String value) { if ( value != null ) this.value = value; } public String getValue() { return value; } public void setBroken(boolean broken) { this.broken = broken; } public boolean isBroken() { return broken; } public void setCaption(String caption) { if ( caption != null ) this.caption = caption; } public String getCaption() { return caption; } public void setImpl(String impl) { if ( impl != null ) this.impl = impl; } public String getImpl() { return impl; } public void setTarget(String target) { if ( target != null ) this.target = target; } public String getTarget() { return target; } public void setExternal(boolean external) { this.external = external; } public boolean isExternal() { return external; } public void setDisabled(boolean disabled) { this.disabled = disabled; } public boolean isDisabled() { return disabled; } public void setPage(PageBean page) { this.page = page; } public PageBean getPage() { return page; } public void setInternalId(String internalId) { if ( internalId != null ) this.internalId = internalId; } public String getInternalId() { return internalId; } public void setInstance(Element instance) { this.instance = instance; } public Element getInstance() { if ( instance == null ) { instance = Element.buildElement( this ); } return instance; } public void setBg(String bg) { if ( bg != null ) this.bg = bg; } public String getBg() { return bg; } public void setAlt(String alt) { if ( alt != null ) this.alt = alt; } public String getAlt() { return alt; } public int getX() { return x; } public int getY() { return y; } public double getHeight() { return h; } public double getWidth() { return w; } //- Getters / Setters // + Comparison methods public boolean equals(ElementBean bean) throws IOException { return equalsByAll( bean, ElementDiffType.values() ); } public boolean equalsByAll(ElementBean bean, ElementDiffType... diffTypes) { return equalsBy( bean, DiffCondition.AND, diffTypes ); } public boolean equalsByOne(ElementBean bean, ElementDiffType... diffTypes) { return equalsBy( bean, DiffCondition.OR, diffTypes ); } private boolean equalsByState(ElementBean bean) { return isDisabled() == bean.isDisabled(); } public boolean equalsByType(ElementBean bean) { return bean.getImpl().contentEquals( getImpl() ); } public boolean equalsByLook(ElementBean bean) { return bean.getDim().getHeight() == getDim().getHeight() && bean.getDim().getWidth() == getDim().getWidth() && equalsByLocation( bean ) && bean.getCaption().contentEquals( getCaption() ); } private boolean equalsByLocation(ElementBean bean) { return bean.getLocation().contains( getLocation() ) && getLocation().contains( bean.getLocation() ); } public boolean equalsByTarget(ElementBean bean) { return getHref().contentEquals( bean.getHref() ); } public boolean equalsByContent(ElementBean bean) { return getContent().contentEquals( bean.getContent() ); } public boolean equalsBy(ElementBean element, DiffCondition condition, ElementDiffType... diffTypes) { boolean b; if ( condition == DiffCondition.AND ) { b = true; } else { b = false; } for ( ElementDiffType diffType : diffTypes ) { switch ( diffType ) { case LOOK: if ( condition == DiffCondition.AND ) { b = b && equalsByLook( element ); } else if ( condition == DiffCondition.OR ) { b = b || equalsByLook( element ); } break; case TYPE: if ( condition == DiffCondition.AND ) { b = b && equalsByType( element ); } else if ( condition == DiffCondition.OR ) { b = b || equalsByType( element ); } break; case TARGET: if ( condition == DiffCondition.AND ) { b = b && equalsByTarget( element ); } else if ( condition == DiffCondition.OR ) { b = b || equalsByTarget( element ); } break; case CONTENT: if ( condition == DiffCondition.AND ) { b = b && equalsByContent( element ); } else if ( condition == DiffCondition.OR ) { b = b || equalsByContent( element ); } break; case LOCATION: if ( condition == DiffCondition.AND ) { b = b && equalsByLocation( element ); } else if ( condition == DiffCondition.OR ) { b = b || equalsByLocation( element ); } break; } } return b; } public List<ElementDiffType> getDiff(ElementBean refElement) { List<ElementDiffType> differencies = new ArrayList(); for ( ElementDiffType diffType : ElementDiffType.values() ) { if ( !equalsByOne( refElement, diffType ) ) { differencies.add( diffType ); } } return differencies; } // - Comparison methods //+ Convenience methods /** * Detect if the area of this element includes the area of the element in parameter * * @param element * @return true if this element includes the element in parameter or false otherwise. */ public boolean isIncluded(ElementBean element) { return element.getContent().contains( getContent() ) && element.getLocation().contains( getLocation() ); } /** * Compute a rectangle object for this object location * * @return a rectangle sized and located at this element */ public Rectangle getLocation() { return new Rectangle( getPos().getX(), getPos().getY(), getDim().getWidth(), getDim().getHeight() ); } /** * Sort the elements in a collection so that the topleft element is before the top right and before the bottom left. * * @param element * @return -1 is this element is to be placed before the element in parameter or 1 otherwise */ @Override public int compareTo(ElementBean element) { if ( isLeft( element ) && isAbove( element ) ) { return -1; } else if ( isLeft( element ) && isBelow( element ) ) { return 1; } else if ( isRight( element ) && isAbove( element ) ) { return -1; } else if ( isRight( element ) && isBelow( element ) ) { return 1; } else { return 0; } } public boolean isLeft(ElementBean element) { return isLeft( this, element ); } public static boolean isLeft(ElementBean e1, ElementBean e2) { return e1.getCenter().getX() < e2.getCenter().getX(); } public boolean isRight(ElementBean element) { return !isLeft( element ); } public boolean isAbove(ElementBean element) { return isAbove( this, element ); } public static boolean isAbove(ElementBean e1, ElementBean e2) { return e1.getCenter().getY() < e2.getCenter().getY(); } public boolean isBelow(ElementBean element) { return !isAbove( element ); } /** * Compute the pixel area of this element. * * @return getWidth() * getHeight() */ public int getArea() { return getDim().getWidth() * getDim().getHeight(); } /** * Keep only the datas contained in the content. * * @param content * @return a list of the datas in the content */ public static List<ElementBean> filterDatas(List<ElementBean> content) { return filterByImpl( content, "Data" ); } /** * Keep only the links contained in the content. * * @param content * @return a list of the links in the content */ public static List<ElementBean> filterLinks(List<ElementBean> content) { return filterByImpl( content, "Link" ); } /** * Keep only the buttons contained in the content. * * @param content * @return a list of the buttons in the content */ public static List<ElementBean> filterButtons(List<ElementBean> content) { return filterByImpl( content, "Button" ); } /** * Keep only the images contained in the content. * * @param content * @return a list of the images in the content */ public static List<ElementBean> filterImages(List<ElementBean> content) { return filterByImpl( content, "Image" ); } public static boolean containsLink(List<ElementBean> elements, String link) { for ( ElementBean element : filterLinks( elements ) ) { if ( element.getContent().contentEquals( link ) ) { return true; } } return false; } public static ElementBean getLink(List<ElementBean> elements, String link) { for ( ElementBean element : filterLinks( elements ) ) { if ( element.getContent().contentEquals( link ) ) { return element; } } throw new NoSuchElementException( "Unable to find any link matching: " + link ); } public static boolean containsData(List<ElementBean> elements, String content) { for ( ElementBean element : filterDatas( elements ) ) { if ( element.getText().contentEquals( content ) ) { return true; } } return false; } public static ElementBean getData(List<ElementBean> elements, String data) { for ( ElementBean element : filterDatas( elements ) ) { if ( element.getContent().contentEquals( data ) ) { return element; } } throw new NoSuchElementException( "Unable to find any data matching: " + data ); } public static boolean containsImage(List<ElementBean> elements, String caption) { for ( ElementBean element : filterImages( elements ) ) { if ( element.getCaption().contentEquals( caption ) ) { return true; } } return false; } /** * For convenience, retrieve the center of this element * * @return the center Point of this element */ public Point getCenter() { Rectangle area = getLocation(); return new Point( (int) area.getCenterX(), (int) area.getCenterY() ); } /** * For convenience, retrieve the user visible value of this element * * @return the text visible in the browser for this element */ public String getContent() { return getText().isEmpty() ? getValue() : getText(); } public String toJson() throws IOException { return JsonHelper.getInstance().map( this ); } public String toString() { return "[" + getImpl() + "] " + getContent() + " -> " + getHref(); } public static boolean isIncluded(ElementBean element, Rectangle rectangle) { return element.getLocation().contains( rectangle ); } //- Convenience methods //+ Private methods /** * Filter the content given an implementation. . * * @param content * @param implementation * The implementation can be: 'Link' or 'Button' * @return a list of the content matching the implementation criteria */ public static List<ElementBean> filterByImpl(List<ElementBean> content, String implementation) { List<ElementBean> elements = new ArrayList<ElementBean>(); for ( ElementBean element : content ) { if ( element.getImpl().contentEquals( implementation ) ) { elements.add( element ); } } return elements; } //- Private methods }