/*
 * Copyright 2015 The Error Prone Authors.
 *
 * 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.google.errorprone.predicates;

import com.google.common.base.Function;
import com.google.common.collect.Iterables;
import com.google.errorprone.predicates.type.Any;
import com.google.errorprone.predicates.type.Array;
import com.google.errorprone.predicates.type.DescendantOf;
import com.google.errorprone.predicates.type.DescendantOfAny;
import com.google.errorprone.predicates.type.Exact;
import com.google.errorprone.predicates.type.ExactAny;
import com.google.errorprone.suppliers.Supplier;
import com.google.errorprone.suppliers.Suppliers;
import com.sun.tools.javac.code.Type;

/** A collection of {@link TypePredicate}s. */
public final class TypePredicates {

  /** Match arrays. */
  public static TypePredicate isArray() {
    return Array.INSTANCE;
  }

  /** Match any type. */
  public static TypePredicate anyType() {
    return Any.INSTANCE;
  }

  /** Match types that are exactly equal. */
  public static TypePredicate isExactType(String type) {
    return isExactType(Suppliers.typeFromString(type));
  }

  /** Match types that are exactly equal. */
  public static TypePredicate isExactType(Supplier<Type> type) {
    return new Exact(type);
  }

  private static final Function<String, Supplier<Type>> GET_TYPE =
      new Function<String, Supplier<Type>>() {
        @Override
        public Supplier<Type> apply(String input) {
          return Suppliers.typeFromString(input);
        }
      };

  /** Match types that are exactly equal to any of the given types. */
  public static TypePredicate isExactTypeAny(Iterable<String> types) {
    return new ExactAny(Iterables.transform(types, GET_TYPE));
  }

  /** Match sub-types of the given type. */
  public static TypePredicate isDescendantOf(Supplier<Type> type) {
    return new DescendantOf(type);
  }

  /** Match types that are a sub-type of one of the given types. */
  public static TypePredicate isDescendantOfAny(Iterable<String> types) {
    return new DescendantOfAny(Iterables.transform(types, GET_TYPE));
  }

  /** Match sub-types of the given type. */
  public static TypePredicate isDescendantOf(String type) {
    return isDescendantOf(Suppliers.typeFromString(type));
  }

  public static TypePredicate allOf(TypePredicate... predicates) {
    return (type, state) -> {
      for (TypePredicate predicate : predicates) {
        if (!predicate.apply(type, state)) {
          return false;
        }
      }
      return true;
    };
  }

  public static TypePredicate anyOf(TypePredicate... predicates) {
    return (type, state) -> {
      for (TypePredicate predicate : predicates) {
        if (predicate.apply(type, state)) {
          return true;
        }
      }
      return false;
    };
  }

  public static TypePredicate not(TypePredicate predicate) {
    return (type, state) -> !predicate.apply(type, state);
  }
}

@@ -644,32 +644,39 @@
 icates;%0A%0Aimport 
+static 
 com.google.commo
@@ -674,74 +674,53 @@
 gle.
-common.base.Function;%0Aimport com.google.common.collect.Iterable
+errorprone.suppliers.Suppliers.fromString
 s;%0A
+%0A
 impo
@@ -1771,262 +1771,8 @@
  %7D%0A%0A
-  private static final Function%3CString, Supplier%3CType%3E%3E GET_TYPE =%0A      new Function%3CString, Supplier%3CType%3E%3E() %7B%0A        @Override%0A        public Supplier%3CType%3E apply(String input) %7B%0A          return Suppliers.typeFromString(input);%0A        %7D%0A      %7D;%0A%0A
   /*
@@ -1830,32 +1830,32 @@
 given types. */%0A
+
   public static 
@@ -1937,43 +1937,25 @@
 Any(
-Iterables.transform(types, GET_TYPE
+fromStrings(types
 ));%0A
@@ -2288,43 +2288,25 @@
 Any(
-Iterables.transform(types, GET_TYPE
+fromStrings(types
 ));%0A

Convert from String to Supplier<Type> only once per string