All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.openqa.selenium.remote.CapabilitiesUtils Maven / Gradle / Ivy

// 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.remote;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;

import org.openqa.selenium.AcceptedW3CCapabilityKeys;
import org.openqa.selenium.internal.Require;
import org.openqa.selenium.remote.session.CapabilitiesFilter;
import org.openqa.selenium.remote.session.CapabilityTransform;
import org.openqa.selenium.remote.session.ProxyTransform;
import org.openqa.selenium.remote.session.StripAnyPlatform;
import org.openqa.selenium.remote.session.W3CPlatformNameNormaliser;

import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Queue;
import java.util.ServiceLoader;
import java.util.Set;
import java.util.TreeMap;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class CapabilitiesUtils {

  private static final Predicate ACCEPTED_W3C_PATTERNS = new AcceptedW3CCapabilityKeys();

  private CapabilitiesUtils() {
    // Helper class
  }

  public static Stream> makeW3CSafe(Map possiblyInvalidCapabilities) {
    Require.nonNull("Capabilities", possiblyInvalidCapabilities);

    Set adapters = ImmutableSet.of();

    // If there's an OSS value, generate a stream of capabilities from that using the transforms,
    // then add magic to generate each of the w3c capabilities. For the sake of simplicity, we're
    // going to make the (probably wrong) assumption we can hold all of the firstMatch values and
    // alwaysMatch value in memory at the same time.
    Stream> fromOss;
    Set usedKeys = new HashSet<>();

    // Are there any values we care want to pull out into a mapping of their own?
    List> firsts = adapters.stream()
      .map(adapter -> adapter.apply(possiblyInvalidCapabilities))
      .filter(Objects::nonNull)
      .filter(map -> !map.isEmpty())
      .map(
        map -> map.entrySet().stream()
          .filter(entry -> entry.getKey() != null)
          .filter(entry -> ACCEPTED_W3C_PATTERNS.test(entry.getKey()))
          .filter(entry -> entry.getValue() != null)
          .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)))
      .peek(map -> usedKeys.addAll(map.keySet()))
      .collect(ImmutableList.toImmutableList());
    if (firsts.isEmpty()) {
      firsts = ImmutableList.of(ImmutableMap.of());
    }

    // Are there any remaining unused keys?
    Map always = possiblyInvalidCapabilities.entrySet().stream()
      .filter(entry -> !usedKeys.contains(entry.getKey()))
      .filter(entry -> entry.getValue() != null)
      .collect(ImmutableMap.toImmutableMap(Map.Entry::getKey, Map.Entry::getValue));

    // Firsts contains at least one entry, always contains everything else. Let's combine them
    // into the stream to form a unified set of capabilities. Woohoo!
    fromOss = firsts.stream()
      .map(first -> ImmutableMap.builder().putAll(always).putAll(first).build())
      .map(CapabilitiesUtils::applyTransforms)
      .map(map -> map.entrySet().stream()
        .filter(entry -> ACCEPTED_W3C_PATTERNS.test(entry.getKey()))
        .collect(ImmutableMap.toImmutableMap(Map.Entry::getKey, Map.Entry::getValue)));

    return fromOss;
  }

  public static Map applyTransforms(Map caps) {
    Queue> toExamine = new LinkedList<>(caps.entrySet());
    Set seenKeys = new HashSet<>();
    Map toReturn = new TreeMap<>();

    Set transforms = getCapabilityTransforms();

    // Take each entry and apply the transforms
    while (!toExamine.isEmpty()) {
      Map.Entry entry = toExamine.remove();
      seenKeys.add(entry.getKey());

      if (entry.getValue() == null) {
        continue;
      }

      for (CapabilityTransform transform : transforms) {
        Collection> result = transform.apply(entry);
        if (result == null) {
          toReturn.remove(entry.getKey());
          break;
        }

        for (Map.Entry newEntry : result) {
          if (!seenKeys.contains(newEntry.getKey())) {
            toExamine.add(newEntry);
          } else {
            if (newEntry.getKey().equals(entry.getKey())) {
              entry = newEntry;
            }
            toReturn.put(newEntry.getKey(), newEntry.getValue());
          }
        }
      }
    }
    return toReturn;
  }

  private static Set getCapabilityTransforms() {
    ImmutableSet.Builder transforms = ImmutableSet.builder();
    ServiceLoader.load(CapabilityTransform.class).forEach(transforms::add);
    transforms
      .add(new ProxyTransform())
      .add(new StripAnyPlatform())
      .add(new W3CPlatformNameNormaliser());
    return transforms.build();
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy