/**
   * There is a possible case that methods of particular object should be executed with classpath
   * different from the one implied by the current class' class loader. External system offers
   * {@link ParametersEnhancer#enhanceLocalProcessing(List)} method for defining that custom
   * classpath.
   *
   * <p>It's also possible that particular implementation of {@link ParametersEnhancer} is compiled
   * using dependency to classes which are provided by the {@link
   * ParametersEnhancer#enhanceLocalProcessing(List) expanded classpath}. E.g. a class <code>'A'
   * </code> might use method of class <code>'B'</code> and 'A' is located at the current
   * (system/plugin) classpath but <code>'B'</code> is not. We need to reload <code>'A'</code> using
   * its expanded classpath then, i.e. create new class loaded with that expanded classpath and load
   * <code>'A'</code> by it.
   *
   * <p>This method allows to do that.
   *
   * @param clazz custom classpath-aware class which instance should be created (is assumed to have
   *     a no-args constructor)
   * @param <T> target type
   * @return newly created instance of the given class loaded by custom classpath-aware loader
   * @throws IllegalAccessException as defined by reflection processing
   * @throws InstantiationException as defined by reflection processing
   * @throws NoSuchMethodException as defined by reflection processing
   * @throws InvocationTargetException as defined by reflection processing
   * @throws ClassNotFoundException as defined by reflection processing
   */
  @NotNull
  public static <T extends ParametersEnhancer> T reloadIfNecessary(@NotNull final Class<T> clazz)
      throws IllegalAccessException, InstantiationException, NoSuchMethodException,
          InvocationTargetException, ClassNotFoundException {
    T instance = clazz.newInstance();
    List<URL> urls = ContainerUtilRt.newArrayList();
    instance.enhanceLocalProcessing(urls);
    if (urls.isEmpty()) {
      return instance;
    }

    final ClassLoader baseLoader = clazz.getClassLoader();
    Method method = baseLoader.getClass().getMethod("getUrls");
    if (method != null) {
      //noinspection unchecked
      urls.addAll((Collection<? extends URL>) method.invoke(baseLoader));
    }
    UrlClassLoader loader =
        new UrlClassLoader(UrlClassLoader.build().urls(urls).parent(baseLoader.getParent())) {
          @Override
          protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
            if (name.equals(clazz.getName())) {
              return super.loadClass(name, resolve);
            } else {
              try {
                return baseLoader.loadClass(name);
              } catch (ClassNotFoundException e) {
                return super.loadClass(name, resolve);
              }
            }
          }
        };
    //noinspection unchecked
    return (T) loader.loadClass(clazz.getName()).newInstance();
  }
 @SuppressWarnings({"unchecked"})
 private static <T extends BaseInjection> List<T> readExternal(
     Element element, Factory<T> factory) {
   final List<T> injections = new ArrayList<T>();
   if (element != null) {
     final List<Element> list = element.getChildren(ENTRY_NAME);
     for (Element entry : list) {
       final T o = factory.create();
       o.loadState(entry);
       injections.add(o);
     }
   }
   return injections;
 }
  @SuppressWarnings({"unchecked"})
  @NotNull
  public static <T extends PsiType> T originalize(@NotNull T type) {
    if (!type.isValid()) {
      return type;
    }

    T result =
        new PsiTypeMapper() {
          private final Set<PsiClassType> myVisited = ContainerUtil.newIdentityTroveSet();

          @Override
          public PsiType visitClassType(final PsiClassType classType) {
            if (!myVisited.add(classType)) return classType;

            final PsiClassType.ClassResolveResult classResolveResult = classType.resolveGenerics();
            final PsiClass psiClass = classResolveResult.getElement();
            final PsiSubstitutor substitutor = classResolveResult.getSubstitutor();
            if (psiClass == null) return classType;

            return new PsiImmediateClassType(
                CompletionUtil.getOriginalOrSelf(psiClass), originalizeSubstitutor(substitutor));
          }

          private PsiSubstitutor originalizeSubstitutor(final PsiSubstitutor substitutor) {
            PsiSubstitutor originalSubstitutor = PsiSubstitutor.EMPTY;
            for (final Map.Entry<PsiTypeParameter, PsiType> entry :
                substitutor.getSubstitutionMap().entrySet()) {
              final PsiType value = entry.getValue();
              originalSubstitutor =
                  originalSubstitutor.put(
                      CompletionUtil.getOriginalOrSelf(entry.getKey()),
                      value == null ? null : mapType(value));
            }
            return originalSubstitutor;
          }

          @Override
          public PsiType visitType(PsiType type) {
            return type;
          }
        }.mapType(type);
    if (result == null) {
      throw new AssertionError("Null result for type " + type + " of class " + type.getClass());
    }
    return result;
  }
 public static <T> void assertOneOf(T value, T... values) {
   boolean found = false;
   for (T v : values) {
     if (value == v || value != null && value.equals(v)) {
       found = true;
     }
   }
   Assert.assertTrue(value + " should be equal to one of " + Arrays.toString(values), found);
 }