Builds a symbol for a type variable from a list of upper bounds.
@param typeVariable the name of the variable
@param upperBounds the upper bounds of the type variable
@return a SymbolType that represents a variable (for generics)
777514
public static SymbolType typeVariableOf(final String typeVariable, List<SymbolType> upperBounds) {
        return new SymbolType(upperBounds, typeVariable);
    }
1175427
final List<Type> boundedVars() {
        return filterVars(uv -> uv.getBounds(InferenceBound.UPPER)
                 .diff(uv.getDeclaredBounds())
                 .appendList(uv.getBounds(InferenceBound.EQ, InferenceBound.LOWER)).nonEmpty());
    }
734764
public static SymbolType typeVariableOf(TypeVariable<?> typeVariable) throws InvalidTypeException {
        return valueOf(typeVariable, null).cloneAsTypeVariable(typeVariable.getName());
    }
72711
public static TypeVariableName get(String name, Type... bounds) {
    return TypeVariableName.of(name, TypeName.list(bounds));
  }
135966
private static Map<TypeVariable<?>, Type> getAllAssignments(final Type t) {
        return spider(new TypeVariableMap(), new HashSet<>(), t);
    }
1134957
public static Type getBound(WildcardType wildcardType) {
    Type[] lowerBounds = wildcardType.getLowerBounds();
    if (lowerBounds.length != 0) {
      return lowerBounds[0];
    }
    return wildcardType.getUpperBounds()[0];
  }
661306
public TypeName resolve(TypeName inputType) {
		if (!hasTypeVariables())
			return inputType;
		
		if (inputType.isPrimitive() || inputType.isBoxedPrimitive() || inputType.equals(TypeName.get(String.class))) {
			return inputType;
		}
		
		if (TypeName.VOID.equals(inputType)) return inputType;
		
		TypeName resolved=null;
		if (inputType instanceof ParameterizedTypeName)
		{
			ParameterizedTypeName inputParametrizedTypeName=(ParameterizedTypeName)inputType;
			
			TypeName[] typeArguments=new TypeName[inputParametrizedTypeName.typeArguments.size()];
			int i=0;
			for (TypeName item: inputParametrizedTypeName.typeArguments)
			{
				typeArguments[i]=resolve(item);
				i++;
			}
			
			resolved=ParameterizedTypeName.get((ClassName)resolve(inputParametrizedTypeName.rawType), typeArguments);
			
			return resolved;
		} else if (inputType instanceof ArrayTypeName)
		{
			ArrayTypeName inputTypeName=(ArrayTypeName)inputType;
			
			resolved=ArrayTypeName.of(resolve(inputTypeName.componentType));
			
			return resolved;
		} else {
			// it's not a type variable
			if (inputType.toString().contains(".")) {
				return inputType;
			}
			// ASSERT: simple typeName 
			if (typeVariableMap.containsKey(inputType.toString())) {
				TypeName type = typeVariableMap.get(inputType.toString());
				return type;
			} else if (declaredTypeArgumentList.size()==1){
				resolved = declaredTypeArgumentList.get(0);
				// if we found an unique type variable, we use it.
				//typeVariableMap = new HashMap<>();
				//typeVariableMap.put(inputTypeName.toString(), resolved);

				return resolved;
			}
			
			AssertKripton.assertTrue(false, "In type hierarchy of %s '%s' there is a unresolved type variable named '%s'. Define it with @BindTypeVariables", element.getKind()==ElementKind.CLASS ? "class" :"interface", element.getQualifiedName(),
					inputType.toString());
			
			return resolved;
		}
		
	}
3727
private static void buildMatchVariables(
      TypeSpec.Builder type, Map<String, Set<String>> territoryData, LanguageMatchingData data) {
    
    Map<String, Set<String>> territories = flatten(territoryData);
    
    CodeBlock.Builder code = CodeBlock.builder();
    code.add("new $T<$T, $T<$T>>() {{\n", HASHMAP, STRING, SET, STRING);
    for (Map.Entry<String, Set<String>> entry : territories.entrySet()) {
      code.add("  put($S, new $T<>(", entry.getKey(), HASHSET);
      List<String> list = new ArrayList<>(entry.getValue());
      Collections.sort(list);
      addStringList(code, list, "    ");
      code.add("));\n");
    }
    code.add("\n}}");
    
    TypeName typeName = ParameterizedTypeName.get(MAP, STRING, SET_STRING);
    type.addField(FieldSpec.builder(typeName, "TERRITORIES", PROTECTED, STATIC, FINAL)
        .initializer(code.build())
        .build());

    // Generate mapping for each variable and its inverse.
    Map<String, Set<String>> variables = new LinkedHashMap<>();
    
    for (Pair<String, String> pair : data.matchVariables) {
      String variable = pair._1;
      
      Set<String> countries = new HashSet<>();
      for (String regionId : pair._2.split("\\+")) {
        Set<String> children = territories.get(regionId);
        if (children != null) {
          countries.addAll(children);
        } else {
          countries.add(regionId);
        }
      }

      variables.put(variable, countries);
    }

    // Build the final variable tables.
    code = CodeBlock.builder();
    code.add("new $T<$T, $T<$T>>() {{\n", HASHMAP, STRING, SET, STRING);
    for (Map.Entry<String, Set<String>> entry : variables.entrySet()) {
      code.add("  put($S, new $T<>(", entry.getKey(), HASHSET);
      List<String> list = new ArrayList<>(entry.getValue());
      Collections.sort(list);
      addStringList(code, list, "    ");
      code.add("));\n");
    }
    code.add("\n}}");
    
    type.addField(FieldSpec.builder(typeName, "VARIABLES", PROTECTED, STATIC, FINAL)
        .initializer(code.build())
        .build());
  }
410698
public Class resolveTypeVariable (TypeVariable typeVariable) {
		for (int i = argumentsSize - 2; i >= 0; i -= 2)
			if (arguments[i] == typeVariable) return (Class)arguments[i + 1];
		return null;
	}
35371
static TypeMirror replaceTypeVariablesWithUpperBounds(Types types, TypeMirror type) {
    return type.accept(UpperBoundSubstitutingVisitor.INSTANCE, types);
  }
1244071
private static boolean isAssignableFrom(TypeVariable<?> type1, TypeVariable<?> type2) {
        if (type1.equals(type2)) {
            return true;
        }
        // if a type variable extends another type variable, it cannot declare other bounds
        if (type2.getBounds()[0] instanceof TypeVariable<?>) {
            return isAssignableFrom(type1, (TypeVariable<?>) type2.getBounds()[0]);
        }
        return false;
    }
313982
public com.sun.javadoc.Type[] bounds() {
        return TypeMaker.getTypes(env, getBounds((TypeVar)type, env));
    }
428557
private static <T> void mapTypeVariablesToArguments(final Class<T> cls,
            final ParameterizedType parameterizedType, final Map<TypeVariable<?>, Type> typeVarAssigns) {
        // capture the type variables from the owner type that have assignments
        final Type ownerType = parameterizedType.getOwnerType();

        if (ownerType instanceof ParameterizedType) {
            // recursion to make sure the owner's owner type gets processed
            mapTypeVariablesToArguments(cls, (ParameterizedType) ownerType, typeVarAssigns);
        }

        // parameterizedType is a generic interface/class (or it's in the owner
        // hierarchy of said interface/class) implemented/extended by the class
        // cls. Find out which type variables of cls are type arguments of
        // parameterizedType:
        final Type[] typeArgs = parameterizedType.getActualTypeArguments();

        // of the cls's type variables that are arguments of parameterizedType,
        // find out which ones can be determined from the super type's arguments
        final TypeVariable<?>[] typeVars = getRawType(parameterizedType).getTypeParameters();

        // use List view of type parameters of cls so the contains() method can be used:
        final List<TypeVariable<Class<T>>> typeVarList = Arrays.asList(cls
                .getTypeParameters());

        for (int i = 0; i < typeArgs.length; i++) {
            final TypeVariable<?> typeVar = typeVars[i];
            final Type typeArg = typeArgs[i];

            // argument of parameterizedType is a type variable of cls
            if (typeVarList.contains(typeArg)
            // type variable of parameterizedType has an assignment in
                    // the super type.
                    && typeVarAssigns.containsKey(typeVar)) {
                // map the assignment to the cls's type variable
                typeVarAssigns.put((TypeVariable<?>) typeArg, typeVarAssigns.get(typeVar));
            }
        }
    }
224454
public static <T extends Comparable<?>> ComparableEntityPath<T> comparableEntityPath(Class<? extends T> type,
                                                                             String variable) {
        return new ComparableEntityPath<T>(type, PathMetadataFactory.forVariable(variable));
    }
715184
public static TypeVariableResolver build(TypeElement element)
	{
		List<TypeName> typeArgs = TypeUtility.getTypeArguments(element);
		Map<String, TypeName> typeVariableMap=new HashMap<>();
		
		BindTypeVariables annotationBeanType = element.getAnnotation(BindTypeVariables.class);
		List<String> typeVariables = new ArrayList<String>();
		if (annotationBeanType != null) {
			typeVariables = Arrays.asList(annotationBeanType.value());
		}
		
		List<String> typeParameters = AnnotationUtility.extractAsClassNameArray(BindTypeSubProcessor.elementUtils, element, BindTypeVariables.class, AnnotationAttributeType.TYPE_PARAMETERS);

		AssertKripton.assertTrue(typeVariables.size() >= typeParameters.size(), "%s '%s' has incorrect definition of type variables/parameters on annotation @BindTypeVariables",
				element.getKind()==ElementKind.CLASS ? "Class" :"Interface", element.asType());

		if (typeVariables.size() > 0) {
			String[] temp;

			AssertKripton.assertTrue((typeParameters.size() == 0) || (typeVariables.size() == typeParameters.size()),
					"%s '%s' has an incorrect definition of type variables/parameters on annotation @BindTypeVariables(typeVariables, typeParameters)", element.getKind()==ElementKind.CLASS ? "Class" :"Interface", element.asType());

			if (StringUtils.hasText(typeVariables.get(0))) {
				int i = 0;
				for (String key : typeVariables) {
					if (StringUtils.hasText(key)) {
						temp = key.split(",");
						for (String alias : temp) {
							if (typeParameters.size() > 0) {
								typeVariableMap.put(alias.trim(), TypeUtility.typeName(typeParameters.get(i)));
							} else {
								typeVariableMap.put(alias.trim(), typeArgs.get(i));
							}
						}
					}
					i++;
				}

			} else {
				AssertKripton.assertTrue(typeVariableMap == null && typeArgs.size() < 2, "%s '%s' use more than one type variables in its class hierarchy. Try to use @BindTypeVariables",
						element.getKind()==ElementKind.CLASS ? "Class" :"Interface", element.asType());
			}
		}
		
		
		return new TypeVariableResolver(element, typeArgs, typeVariableMap);
	}
720259
public static <T extends Number & Comparable<?>> NumberPath<T> numberPath(Class<? extends T> type,
            String variable) {
        return new NumberPath<T>(type, PathMetadataFactory.forVariable(variable));
    }
1080253
protected List<TypeNameWithArity> createTypeArityList(
      TypeName t, String extractVariableName, int maxArity) {
    TypeName u = match(t)
        .when(typeOf(TypeVariableName.class))
        .get(x -> (TypeName) TypeVariableName.get("E" + x.name, x))
        .orElse(x -> x)
        .getMatch();

    List<TypeNameWithArity> typeArityList = new ArrayList<>();
    //typeArityList.add(TypeNameWithArity.of(t, 0));
    typeArityList.add(TypeNameWithArity.of(ParameterizedTypeName.get(MATCH_EXACT, t), 0));
    typeArityList.add(TypeNameWithArity.of(ParameterizedTypeName.get(MATCH_ANY, t), 1));
    //typeArityList.add(TypeNameWithArity.of(TypeName.get(MatchesAny.class), 1));
    IntStream.rangeClosed(0, maxArity).forEach(
        extractArity -> {
          TypeName[] typeVariables = createTypeVariables(u, extractVariableName, extractArity);
          typeArityList.add(
              TypeNameWithArity.of(
                  ParameterizedTypeName
                      .get(
                          ClassName.get(getDecomposableBuilderByArity(extractArity)),
                          typeVariables), extractArity));
        });

    return typeArityList;
  }