diff --git a/src/main/java/io/appium/java_client/pagefactory/DefaultElementByBuilder.java b/src/main/java/io/appium/java_client/pagefactory/DefaultElementByBuilder.java index d31b56fe4..135c2f423 100644 --- a/src/main/java/io/appium/java_client/pagefactory/DefaultElementByBuilder.java +++ b/src/main/java/io/appium/java_client/pagefactory/DefaultElementByBuilder.java @@ -50,7 +50,7 @@ public class DefaultElementByBuilder extends AppiumByBuilder { private static final String PRIORITY = "priority"; private static final String VALUE = "value"; - private static final Class[] ANNOTATION_ARGUMENTS = new Class[]{}; + private static final Class[] ANNOTATION_ARGUMENTS = new Class[]{}; private static final Object[] ANNOTATION_PARAMETERS = new Object[]{}; public DefaultElementByBuilder(String platform, String automation) { @@ -155,7 +155,7 @@ private By[] getBys(Class singleLocator, Class[] DEFAULT_ANNOTATION_METHOD_ARGUMENTS = new Class[] {}; + protected static final Class[] DEFAULT_ANNOTATION_METHOD_ARGUMENTS = new Class[]{}; - private static final List METHODS_TO_BE_EXCLUDED_WHEN_ANNOTATION_IS_READ = - new ArrayList() { - private static final long serialVersionUID = 1L; { - Stream.of(Object.class, Annotation.class, Proxy.class) + private static final List METHODS_TO_BE_EXCLUDED_WHEN_ANNOTATION_IS_READ = new ArrayList() { + private static final long serialVersionUID = 1L; + + { + Stream.of(Object.class, Annotation.class, Proxy.class) .map(Class::getDeclaredMethods) .map(AppiumByBuilder::getMethodNames) .flatMap(List::stream) .forEach(this::add); - } - }; + } + }; protected final AnnotatedElementContainer annotatedElementContainer; protected final String platform; protected final String automation; @@ -65,79 +68,68 @@ protected AppiumByBuilder(String platform, String automation) { } private static List getMethodNames(Method[] methods) { - List names = new ArrayList<>(); - for (Method m : methods) { - names.add(m.getName()); - } - return names; + return Stream.of(methods).map(Method::getName).collect(Collectors.toList()); } private static Method[] prepareAnnotationMethods(Class annotation) { - List targetAnnotationMethodNamesList = - getMethodNames(annotation.getDeclaredMethods()); + List targetAnnotationMethodNamesList = getMethodNames(annotation.getDeclaredMethods()); targetAnnotationMethodNamesList.removeAll(METHODS_TO_BE_EXCLUDED_WHEN_ANNOTATION_IS_READ); - Method[] result = new Method[targetAnnotationMethodNamesList.size()]; - for (String methodName : targetAnnotationMethodNamesList) { - try { - result[targetAnnotationMethodNamesList.indexOf(methodName)] = - annotation.getMethod(methodName, DEFAULT_ANNOTATION_METHOD_ARGUMENTS); - } catch (NoSuchMethodException | SecurityException e) { - throw new RuntimeException(e); - } - } - return result; + return targetAnnotationMethodNamesList.stream() + .map((methodName) -> { + try { + return annotation.getMethod(methodName, DEFAULT_ANNOTATION_METHOD_ARGUMENTS); + } catch (NoSuchMethodException | SecurityException e) { + throw new RuntimeException(e); + } + }).toArray(Method[]::new); } private static String getFilledValue(Annotation mobileBy) { - Method[] values = prepareAnnotationMethods(mobileBy.getClass()); - for (Method value : values) { - if (!String.class.equals(value.getReturnType())) { - continue; - } - - try { - String strategyParameter = value.invoke(mobileBy).toString(); - if (!strategyParameter.isEmpty()) { - return value.getName(); - } - } catch (IllegalAccessException - | IllegalArgumentException - | InvocationTargetException e) { - throw new RuntimeException(e); - } - } - throw new IllegalArgumentException( - "@" + mobileBy.getClass().getSimpleName() + ": one of " + Strategies.strategiesNames() - .toString() + " should be filled"); + return Stream.of(prepareAnnotationMethods(mobileBy.getClass())) + .filter((method) -> String.class == method.getReturnType()) + .filter((method) -> { + try { + Object strategyParameter = method.invoke(mobileBy); + return strategyParameter != null && !String.valueOf(strategyParameter).isEmpty(); + } catch (IllegalAccessException | IllegalArgumentException + | InvocationTargetException e) { + throw new RuntimeException(e); + } + }) + .findFirst() + .map(Method::getName) + .orElseThrow(() -> new IllegalArgumentException( + String.format("@%s: one of %s should be filled", + mobileBy.getClass().getSimpleName(), Strategies.strategiesNames()) + )); } private static By getMobileBy(Annotation annotation, String valueName) { - Strategies[] strategies = Strategies.values(); - for (Strategies strategy : strategies) { - if (strategy.returnValueName().equals(valueName)) { - return strategy.getBy(annotation); - } - } - throw new IllegalArgumentException( - "@" + annotation.getClass().getSimpleName() + ": There is an unknown strategy " - + valueName); + return Stream.of(Strategies.values()) + .filter((strategy) -> strategy.returnValueName().equals(valueName)) + .findFirst() + .map((strategy) -> strategy.getBy(annotation)) + .orElseThrow(() -> new IllegalArgumentException( + String.format("@%s: There is an unknown strategy %s", + annotation.getClass().getSimpleName(), valueName) + )); } - private static T getComplexMobileBy(Annotation[] annotations, - Class requiredByClass) { - By[] byArray = new By[annotations.length]; - for (int i = 0; i < annotations.length; i++) { - byArray[i] = getMobileBy(annotations[i], getFilledValue(annotations[i])); - } + private static T getComplexMobileBy(Annotation[] annotations, Class requiredByClass) { + By[] byArray = Stream.of(annotations) + .map((annotation) -> getMobileBy(annotation, getFilledValue(annotation))) + .toArray(By[]::new); try { Constructor c = requiredByClass.getConstructor(By[].class); - Object[] values = new Object[] {byArray}; + Object[] values = new Object[]{byArray}; return c.newInstance(values); - } catch (Exception e) { + } catch (InvocationTargetException | NoSuchMethodException | InstantiationException + | IllegalAccessException e) { throw new RuntimeException(e); } } + @Nullable protected static By createBy(Annotation[] annotations, HowToUseSelectors howToUseLocators) { if (annotations == null || annotations.length == 0) { return null; diff --git a/src/main/java/io/appium/java_client/pagefactory/bys/builder/ByChained.java b/src/main/java/io/appium/java_client/pagefactory/bys/builder/ByChained.java index 0ea7dde77..f8d2240cb 100644 --- a/src/main/java/io/appium/java_client/pagefactory/bys/builder/ByChained.java +++ b/src/main/java/io/appium/java_client/pagefactory/bys/builder/ByChained.java @@ -35,6 +35,9 @@ public class ByChained extends org.openqa.selenium.support.pagefactory.ByChained private static AppiumFunction getSearchingFunction(By by) { return input -> { try { + if (input == null) { + return null; + } return input.findElement(by); } catch (NoSuchElementException e) { return null; @@ -71,7 +74,7 @@ public WebElement findElement(SearchContext context) { checkNotNull(searchingFunction); return waiting.until(searchingFunction); } catch (TimeoutException e) { - throw new NoSuchElementException("Cannot locate an element using " + toString()); + throw new NoSuchElementException("Cannot locate an element using " + this); } } } diff --git a/src/main/java/io/appium/java_client/pagefactory/bys/builder/HowToUseSelectors.java b/src/main/java/io/appium/java_client/pagefactory/bys/builder/HowToUseSelectors.java index 8fce3c467..a4d4f4fdb 100644 --- a/src/main/java/io/appium/java_client/pagefactory/bys/builder/HowToUseSelectors.java +++ b/src/main/java/io/appium/java_client/pagefactory/bys/builder/HowToUseSelectors.java @@ -17,7 +17,5 @@ package io.appium.java_client.pagefactory.bys.builder; public enum HowToUseSelectors { - USE_ONE, - BUILD_CHAINED, - USE_ANY; + USE_ONE, BUILD_CHAINED, USE_ANY } diff --git a/src/main/java/io/appium/java_client/pagefactory/bys/builder/Strategies.java b/src/main/java/io/appium/java_client/pagefactory/bys/builder/Strategies.java index 7b1d13ab1..d175f37e3 100644 --- a/src/main/java/io/appium/java_client/pagefactory/bys/builder/Strategies.java +++ b/src/main/java/io/appium/java_client/pagefactory/bys/builder/Strategies.java @@ -19,8 +19,9 @@ import java.lang.annotation.Annotation; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; -import java.util.ArrayList; import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; import org.openqa.selenium.By; @@ -127,12 +128,7 @@ enum Strategies { } static List strategiesNames() { - Strategies[] strategies = values(); - List result = new ArrayList<>(); - for (Strategies strategy : strategies) { - result.add(strategy.valueName); - } - return result; + return Stream.of(values()).map((s) -> s.valueName).collect(Collectors.toList()); } private static String getValue(Annotation annotation, Strategies strategy) {