com.vaadin.client.debug.internal.SelectorPath Maven / Gradle / Ivy
Show all versions of vaadin-client Show documentation
/*
* Copyright 2000-2016 Vaadin Ltd.
*
* 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 com.vaadin.client.debug.internal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.google.gwt.dom.client.Element;
import com.vaadin.client.ServerConnector;
import com.vaadin.client.componentlocator.ComponentLocator;
import com.vaadin.client.componentlocator.SelectorPredicate;
/**
* A single segment of a selector path pointing to an Element.
*
* This class should be considered internal to the framework and may change at
* any time.
*
*
* @since 7.1.x
*/
public class SelectorPath {
private final String path;
private final Element element;
private final ComponentLocator locator;
private static Map counter = new HashMap<>();
private static Map legacyNames = new HashMap<>();
static {
legacyNames.put("FilterSelect", "ComboBox");
legacyNames.put("ScrollTable", "Table");
}
protected SelectorPath(ServerConnector c, Element e) {
element = e;
locator = new ComponentLocator(c.getConnection());
path = locator.getPathForElement(e);
}
public String getPath() {
return path;
}
public Element getElement() {
return element;
}
public ComponentLocator getLocator() {
return locator;
}
/**
* Generate ElementQuery code for Java. Fallback to By.vaadin(path) if
* dealing with LegacyLocator
*
* @return String containing Java code for finding the element described by
* path
*/
public String getElementQuery() {
if (path.isEmpty() || locator.isValidForLegacyLocator(path)) {
return getLegacyLocatorQuery();
}
String[] fragments;
String tmpPath = path;
List postFilters = SelectorPredicate
.extractPostFilterPredicates(path);
if (postFilters.size() > 0) {
tmpPath = tmpPath.substring(1, tmpPath.lastIndexOf(')'));
if (tmpPath.contains("#")) {
// FIXME: SubParts should be handled.
tmpPath = tmpPath.split("#")[0];
}
}
// Generate an ElementQuery
fragments = tmpPath.split("/");
String elementQueryString = "";
int index = 0;
for (SelectorPredicate p : postFilters) {
if (p.getIndex() > 0) {
index = p.getIndex();
}
}
for (int i = 1; i < fragments.length; ++i) {
if (fragments[i].isEmpty()) {
// Recursive searches cause empty fragments
continue;
}
// if i == 1 or previous fragment was empty, search is recursive
boolean recursive = (i > 1 ? fragments[i - 1].isEmpty() : false);
// if elementQueryString is not empty, join the next query with .
String queryFragment = (!elementQueryString.isEmpty() ? "." : "");
// if search is not recursive, add another $ in front of fragment
queryFragment += (!recursive ? "$" : "")
+ generateFragment(fragments[i]);
elementQueryString += queryFragment;
}
if (!hasId(fragments[fragments.length - 1])) {
if (index == 0) {
elementQueryString += ".first()";
} else {
elementQueryString += ".get(" + index + ")";
}
}
// Return full Java variable assignment and eQuery
return generateJavaVariable(fragments[fragments.length - 1])
+ elementQueryString + ";";
}
/**
* Finds out if the given query fragment has a defined id
*
* @param fragment
* Query fragment
* @return true if has id
*/
private boolean hasId(String fragment) {
for (SelectorPredicate p : SelectorPredicate
.extractPredicates(fragment)) {
if (p.getName().equals("id")) {
return true;
}
}
return false;
}
/**
* Generates a recursive ElementQuery for given path fragment
*
* @param fragment
* Query fragment
* @return ElementQuery java code as a String
*/
private String generateFragment(String fragment) {
// Get Element.class -name
String elementClass = getComponentName(fragment) + "Element.class";
String queryFragment = "$(" + elementClass + ")";
for (SelectorPredicate p : SelectorPredicate
.extractPredicates(fragment)) {
// Add in predicates like .caption and .id
queryFragment += "." + p.getName() + "(\"" + p.getValue() + "\")";
}
return queryFragment;
}
/**
* Returns the name of the component described by given query fragment
*
* @param fragment
* Query fragment
* @return Class part of fragment
*/
protected String getComponentName(String fragment) {
return fragment.split("\\[")[0];
}
/**
* Generates a legacy locator for SelectorPath.
*
* @return String containing Java code for element search and assignment
*/
private String getLegacyLocatorQuery() {
String name;
if (!path.isEmpty()) {
String[] frags = path.split("/");
name = getComponentName(frags[frags.length - 1]).substring(1);
} else {
name = "root";
}
if (legacyNames.containsKey(name)) {
name = legacyNames.get(name);
}
name = getNameWithCount(name);
// Use direct path and elementX naming style.
return "WebElement " + name.substring(0, 1).toLowerCase()
+ name.substring(1) + " = getDriver().findElement(By.vaadin(\""
+ path + "\"));";
}
/**
* Get variable name with counter for given component name.
*
* @param name
* Component name
* @return name followed by count
*/
protected String getNameWithCount(String name) {
if (!counter.containsKey(name)) {
counter.put(name, 0);
}
counter.put(name, counter.get(name) + 1);
name += counter.get(name);
return name;
}
/**
* Generate Java variable assignment from given selector fragment
*
* @param pathFragment
* Selector fragment
* @return piece of java code
*/
private String generateJavaVariable(String pathFragment) {
// Get element type and predicates from fragment
List predicates = SelectorPredicate
.extractPredicates(pathFragment);
String elementType = pathFragment.split("\\[")[0];
String name = getNameFromPredicates(predicates, elementType);
if (name.equals(elementType)) {
name = getNameWithCount(name);
}
// Replace unusable characters
name = name.replaceAll("\\W", "");
// Lowercase the first character of name
return elementType + "Element " + name.substring(0, 1).toLowerCase()
+ name.substring(1) + " = ";
}
/**
* Get variable name based on predicates. Fallback to elementType
*
* @param predicates
* Predicates related to element
* @param elementType
* Element type
* @return name for Variable
*/
private String getNameFromPredicates(List predicates,
String elementType) {
String name = elementType;
for (SelectorPredicate p : predicates) {
if ("caption".equals(p.getName())) {
// Caption + elementType is a suitable name
name = p.getValue() + elementType;
} else if ("id".equals(p.getName())) {
// Just id. This is unique, use it.
return p.getValue();
}
}
return name;
}
}