123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272 |
- /*
- * 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.
- * <p>
- * This class should be considered internal to the framework and may change at
- * any time.
- * <p>
- *
- * @since 7.1.x
- */
- public class SelectorPath {
- private final String path;
- private final Element element;
- private final ComponentLocator locator;
- private static Map<String, Integer> counter = new HashMap<>();
- private static Map<String, String> 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<SelectorPredicate> postFilters = SelectorPredicate
- .extractPostFilterPredicates(path);
- if (!postFilters.isEmpty()) {
- 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<SelectorPredicate> 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<SelectorPredicate> 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;
- }
- }
|