org.openqa.selenium.grid.config.DescribedOption Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of selenium-grid Show documentation
Show all versions of selenium-grid Show documentation
Selenium automates browsers. That's it! What you do with that power is entirely up to you.
// Licensed to the Software Freedom Conservancy (SFC) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The SFC licenses this file
// to you 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 org.openqa.selenium.grid.config;
import static java.util.Comparator.comparing;
import static java.util.Comparator.naturalOrder;
import com.beust.jcommander.Parameter;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedSet;
import com.google.common.collect.Sets;
import com.google.common.primitives.Primitives;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.ServiceLoader;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
/** Represents a configurable attribute of the Selenium Grid. */
public class DescribedOption implements Comparable {
public final String section;
public final String optionName;
public final String description;
public final String type;
public final String[] example;
public final String defaultValue;
public final boolean prefixed;
public final boolean repeats;
public final boolean quotable;
public final boolean hidden;
public final Set flags;
DescribedOption(Type type, Parameter parameter, ConfigValue configValue, String defaultValue) {
Objects.requireNonNull(type);
Objects.requireNonNull(parameter);
Objects.requireNonNull(configValue);
Objects.requireNonNull(defaultValue);
this.section = configValue.section();
this.optionName = configValue.name();
this.type = getType(type);
this.description = parameter.description();
this.prefixed = configValue.prefixed();
this.repeats = isCollection(type);
this.quotable = isTomlStringType(type);
this.example = configValue.example();
this.flags = ImmutableSortedSet.naturalOrder().add(parameter.names()).build();
this.defaultValue = defaultValue;
this.hidden = parameter.hidden();
}
public static Set findAllMatchingOptions(Collection roles) {
Objects.requireNonNull(roles);
Set minimized = ImmutableSet.copyOf(roles);
return StreamSupport.stream(ServiceLoader.load(HasRoles.class).spliterator(), false)
.filter(hasRoles -> !Sets.intersection(hasRoles.getRoles(), minimized).isEmpty())
.flatMap(DescribedOption::getAllFields)
.collect(ImmutableSortedSet.toImmutableSortedSet(naturalOrder()));
}
private static Stream getAllFields(HasRoles hasRoles) {
Set fields = new HashSet<>();
Class> clazz = hasRoles.getClass();
while (clazz != null && !Object.class.equals(clazz)) {
for (Field field : clazz.getDeclaredFields()) {
field.setAccessible(true);
Parameter param = field.getAnnotation(Parameter.class);
ConfigValue configValue = field.getAnnotation(ConfigValue.class);
String fieldValue = "";
try {
Object fieldInstance = field.get(clazz.newInstance());
fieldValue = fieldInstance == null ? "" : fieldInstance.toString();
} catch (IllegalAccessException | InstantiationException ignore) {
// We'll swallow this exception since we are just trying to get field's default value
}
if (param != null && configValue != null) {
fields.add(new DescribedOption(field.getGenericType(), param, configValue, fieldValue));
}
}
clazz = clazz.getSuperclass();
}
return fields.stream();
}
public String section() {
return section;
}
public String optionName() {
return optionName;
}
public String description() {
return description;
}
public boolean repeats() {
return repeats;
}
public boolean requiresTomlQuoting() {
return quotable;
}
public String[] example() {
return example;
}
public String example(Config config, String example) {
Optional> allOptions = config.getAll(section, optionName);
if (allOptions.isPresent() && !allOptions.get().isEmpty()) {
if (repeats) {
return allOptions.get().stream()
.map(value -> quotable ? "\"" + value + "\"" : String.valueOf(value))
.collect(Collectors.joining(", ", "[", "]"));
}
String value = allOptions.get().get(0);
return quotable ? "\"" + value + "\"" : value;
}
return example;
}
public Set flags() {
return flags;
}
@Override
public int compareTo(DescribedOption o) {
return comparing((DescribedOption describedOption) -> describedOption.section)
.thenComparing(describedOption -> describedOption.optionName)
.compare(this, o);
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
DescribedOption that = (DescribedOption) o;
return repeats == that.repeats
&& quotable == that.quotable
&& Objects.equals(section, that.section)
&& Objects.equals(optionName, that.optionName)
&& Objects.equals(description, that.description)
&& Objects.equals(defaultValue, that.defaultValue)
&& Objects.equals(type, that.type)
&& Arrays.equals(example, that.example)
&& Objects.equals(flags, that.flags);
}
@Override
public int hashCode() {
return Objects.hash(
section,
optionName,
description,
type,
Arrays.hashCode(example),
repeats,
quotable,
flags,
defaultValue);
}
public String getType(Type type) {
String className = deriveClass(type).getSimpleName().toLowerCase();
return isCollection(type) ? "list of " + className + "s" : className;
}
private boolean isTomlStringType(Type type) {
Class> derived = Primitives.wrap(deriveClass(type));
// Everything other than numbers and booleans must be quoted
return !(Number.class.isAssignableFrom(derived) || Boolean.class.isAssignableFrom(derived));
}
private Class> deriveClass(Type type) {
if (type instanceof ParameterizedType
&& ((ParameterizedType) type).getRawType() instanceof Class
&& Collection.class.isAssignableFrom((Class>) ((ParameterizedType) type).getRawType())) {
Type[] typeArgs = ((ParameterizedType) type).getActualTypeArguments();
if (typeArgs.length == 1 && typeArgs[0] instanceof Class) {
// TODO: This is not how to pluralise something
return (Class>) typeArgs[0];
}
}
if (type instanceof Class) {
return (Class>) type;
}
throw new IllegalStateException("Unknown type: " + type);
}
private boolean isCollection(Type type) {
return type instanceof ParameterizedType
&& ((ParameterizedType) type).getRawType() instanceof Class
&& Collection.class.isAssignableFrom((Class>) ((ParameterizedType) type).getRawType());
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy