@SuppressWarnings("unchecked")
  @Override
  public <T> JavaConfigurationBuilder bindSetEntry(
      Class<? extends Name<Set<T>>> iface, Class<? extends T> impl) throws BindException {
    final Node n = getNode(iface);
    final Node m = getNode(impl);

    if (!(n instanceof NamedParameterNode)) {
      throw new BindException(
          "BindSetEntry got an interface that resolved to " + n + "; expected a NamedParameter");
    }
    final Type setType = ReflectionUtilities.getInterfaceTarget(Name.class, iface);
    if (!ReflectionUtilities.getRawClass(setType).equals(Set.class)) {
      throw new BindException(
          "BindSetEntry got a NamedParameter that takes a " + setType + "; expected Set<...>");
    }
    final Type valType = ReflectionUtilities.getInterfaceTarget(Set.class, setType);
    if (!ReflectionUtilities.getRawClass(valType).isAssignableFrom(impl)) {
      throw new BindException(
          "BindSetEntry got implementation "
              + impl
              + " that is incompatible with expected type "
              + valType);
    }

    super.bindSetEntry((NamedParameterNode<Set<T>>) n, m);
    return this;
  }
Example #2
0
  private <T, U> Node buildPathToNode(final Class<U> clazz) throws ClassHierarchyException {
    final String[] path = clazz.getName().split("\\$");

    Node root = namespace;
    for (int i = 0; i < path.length - 1; i++) {
      root = root.get(path[i]);
    }

    if (root == null) {
      throw new NullPointerException();
    }
    final Node parent = root;

    final Type argType = ReflectionUtilities.getNamedParameterTargetOrNull(clazz);

    if (argType == null) {
      return JavaNodeFactory.createClassNode(parent, clazz);
    } else {

      // checked inside of NamedParameterNode, using reflection.
      @SuppressWarnings("unchecked")
      final NamedParameterNode<T> np =
          JavaNodeFactory.createNamedParameterNode(
              parent, (Class<? extends Name<T>>) clazz, argType);

      if (parameterParser.canParse(ReflectionUtilities.getFullName(argType))
          && clazz.getAnnotation(NamedParameter.class).default_class() != Void.class) {
        throw new ClassHierarchyException(
            "Named parameter "
                + ReflectionUtilities.getFullName(clazz)
                + " defines default implementation for parsable type "
                + ReflectionUtilities.getFullName(argType));
      }

      final String shortName = np.getShortName();
      if (shortName != null) {
        final NamedParameterNode<?> oldNode = shortNames.get(shortName);
        if (oldNode != null) {
          if (oldNode.getFullName().equals(np.getFullName())) {
            throw new IllegalStateException(
                "Tried to double bind " + oldNode.getFullName() + " to short name " + shortName);
          }
          throw new ClassHierarchyException(
              "Named parameters "
                  + oldNode.getFullName()
                  + " and "
                  + np.getFullName()
                  + " have the same short name: "
                  + shortName);
        }
        shortNames.put(shortName, np);
      }
      return np;
    }
  }
  @SuppressWarnings({"unchecked", "rawtypes"})
  public Configuration build() throws BindException {
    ConfigurationModule c = deepCopy();

    if (!c.reqSet.containsAll(c.builder.reqDecl)) {
      Set<Field> missingSet = new MonotonicHashSet<>();
      for (Field f : c.builder.reqDecl) {
        if (!c.reqSet.contains(f)) {
          missingSet.add(f);
        }
      }
      throw new BindException(
          "Attempt to build configuration before setting required option(s): "
              + builder.toString(missingSet));
    }

    for (Class<?> clazz : c.builder.freeImpls.keySet()) {
      Impl<?> i = c.builder.freeImpls.get(clazz);
      if (c.setImpls.containsKey(i)) {
        c.builder.b.bind(clazz, c.setImpls.get(i));
      } else if (c.setLateImpls.containsKey(i)) {
        c.builder.b.bind(ReflectionUtilities.getFullName(clazz), c.setLateImpls.get(i));
      } else if (c.setImplSets.containsKey(i) || c.setLateImplSets.containsKey(i)) {
        for (Class<?> clz : c.setImplSets.getValuesForKey(i)) {
          c.builder.b.bindSetEntry((Class) clazz, (Class) clz);
        }
        for (String s : c.setLateImplSets.getValuesForKey(i)) {
          c.builder.b.bindSetEntry((Class) clazz, s);
        }
      } else if (c.setImplLists.containsKey(i)) {
        c.builder.b.bindList((Class) clazz, c.setImplLists.get(i));
      }
    }
    for (Class<? extends Name<?>> clazz : c.builder.freeParams.keySet()) {
      Param<?> p = c.builder.freeParams.get(clazz);
      String s = c.setParams.get(p);
      boolean foundOne = false;
      if (s != null) {
        c.builder.b.bindNamedParameter(clazz, s);
        foundOne = true;
      }
      // Find the bound list for the NamedParameter
      List list = c.setParamLists.get(p);
      if (list != null) {
        c.builder.b.bindList((Class) clazz, list);
        foundOne = true;
      }
      for (String paramStr : c.setParamSets.getValuesForKey(p)) {
        c.builder.b.bindSetEntry((Class) clazz, paramStr);
        foundOne = true;
      }
      if (!foundOne) {
        if (!(p instanceof OptionalParameter)) {
          throw new IllegalStateException();
        }
      }
    }
    return c.builder.b.build();
  }
  public List<Entry<String, String>> toStringPairs() {
    List<Entry<String, String>> ret = new ArrayList<>();
    class MyEntry implements Entry<String, String> {
      final String k;
      final String v;

      public MyEntry(String k, String v) {
        this.k = k;
        this.v = v;
      }

      @Override
      public String getKey() {
        return k;
      }

      @Override
      public String getValue() {
        return v;
      }

      @Override
      public String setValue(String value) {
        throw new UnsupportedOperationException();
      }
    }
    for (Class<?> c : this.builder.freeParams.keySet()) {
      ret.add(
          new MyEntry(
              ReflectionUtilities.getFullName(c),
              this.builder.map.get(this.builder.freeParams.get(c)).getName()));
    }
    for (Class<?> c : this.builder.freeImpls.keySet()) {
      ret.add(
          new MyEntry(
              ReflectionUtilities.getFullName(c),
              this.builder.map.get(this.builder.freeImpls.get(c)).getName()));
    }
    for (String s : ConfigurationFile.toConfigurationStringList(builder.b.build())) {
      String[] tok = s.split("=", 2);
      ret.add(new MyEntry(tok[0], tok[1]));
    }

    return ret;
  }
  @SuppressWarnings("unchecked")
  @Override
  public <T> JavaConfigurationBuilder bindSetEntry(
      Class<? extends Name<Set<T>>> iface, String value) throws BindException {
    final Node n = getNode(iface);

    if (!(n instanceof NamedParameterNode)) {
      throw new BindException(
          "BindSetEntry got an interface that resolved to " + n + "; expected a NamedParameter");
    }
    final Type setType = ReflectionUtilities.getInterfaceTarget(Name.class, iface);
    if (!ReflectionUtilities.getRawClass(setType).equals(Set.class)) {
      throw new BindException(
          "BindSetEntry got a NamedParameter that takes a " + setType + "; expected Set<...>");
    }
    //    Type valType = ReflectionUtilities.getInterfaceTarget(Set.class, setType);
    super.bindSetEntry((NamedParameterNode<Set<T>>) n, value);
    return this;
  }
Example #6
0
 @Override
 public Node getNode(final Class<?> clazz) {
   try {
     return getNode(ReflectionUtilities.getFullName(clazz));
   } catch (final NameResolutionException e) {
     throw new ClassHierarchyException(
         "JavaClassHierarchy could not resolve "
             + clazz
             + " which is definitely avalable at runtime",
         e);
   }
 }
  /**
   * Binding list method for JavaConfigurationBuilder. It checks the type of a given named
   * parameter, and whether all the list's elements can be applied to the named parameter. The
   * elements' type should be either java Class or String.
   *
   * <p>It does not check whether the list's String values can be parsed to T, like bindSetEntry.
   *
   * @param iface target named parameter to be instantiated
   * @param implList implementation list used to instantiate the named parameter
   * @param <T> type of the list
   * @return bound JavaConfigurationBuilder object
   * @throws BindException
   */
  @SuppressWarnings("unchecked")
  @Override
  public <T> JavaConfigurationBuilder bindList(Class<? extends Name<List<T>>> iface, List implList)
      throws BindException {
    final Node n = getNode(iface);
    List<Object> result = new ArrayList<>();

    if (!(n instanceof NamedParameterNode)) {
      throw new BindException(
          "BindList got an interface that resolved to " + n + "; expected a NamedParameter");
    }
    final Type listType = ReflectionUtilities.getInterfaceTarget(Name.class, iface);
    if (!ReflectionUtilities.getRawClass(listType).equals(List.class)) {
      throw new BindException(
          "BindList got a NamedParameter that takes a " + listType + "; expected List<...>");
    }
    if (!implList.isEmpty()) {
      final Type valType = ReflectionUtilities.getInterfaceTarget(List.class, listType);
      for (Object item : implList) {
        if (item instanceof Class) {
          if (!ReflectionUtilities.getRawClass(valType).isAssignableFrom((Class) item)) {
            throw new BindException(
                "BindList got a list element which is not assignable to the given Type; "
                    + "expected: "
                    + valType);
          }
          result.add(getNode((Class) item));
        } else if (item instanceof String) {
          result.add(item);
        } else {
          throw new BindException(
              "BindList got an list element with unsupported type; expected Class or String "
                  + "object");
        }
      }
    }

    super.bindList((NamedParameterNode<List<T>>) n, result);
    return this;
  }
 private <T> void processSet(Object impl) {
   Field f = builder.map.get(impl);
   if (f == null) {
       /* throw */
     throw new ClassHierarchyException(
         "Unknown Impl/Param when setting "
             + ReflectionUtilities.getSimpleName(impl.getClass())
             + ".  Did you pass in a field from some other module?");
   }
   if (!reqSet.contains(f)) {
     reqSet.add(f);
   }
 }
 public Set<NamedParameterNode<?>> getBoundNamedParameters() {
   Configuration c = this.builder.b.build();
   Set<NamedParameterNode<?>> nps = new MonotonicSet<>();
   nps.addAll(c.getNamedParameters());
   for (Class<?> np : this.builder.freeParams.keySet()) {
     try {
       nps.add(
           (NamedParameterNode<?>)
               builder.b.getClassHierarchy().getNode(ReflectionUtilities.getFullName(np)));
     } catch (NameResolutionException e) {
       throw new IllegalStateException(e);
     }
   }
   return nps;
 }
 public final <T> ConfigurationModule set(Param<T> opt, Class<? extends T> val) {
   return set(opt, ReflectionUtilities.getFullName(val));
 }
Example #11
0
  private Node register(final String s) {
    final Class<?> c;
    try {
      c = classForName(s);
    } catch (final ClassNotFoundException e1) {
      return null;
    }
    try {
      final Node n = getAlreadyBoundNode(c);
      return n;
    } catch (final NameResolutionException e) {
      // node not bound yet
    }
    // First, walk up the class hierarchy, registering all out parents. This
    // can't be loopy.
    if (c.getSuperclass() != null) {
      register(ReflectionUtilities.getFullName(c.getSuperclass()));
    }
    for (final Class<?> i : c.getInterfaces()) {
      register(ReflectionUtilities.getFullName(i));
    }
    // Now, we'd like to register our enclosing classes. This turns out to be
    // safe.
    // Thankfully, Java doesn't allow:
    // class A implements A.B { class B { } }

    // It also doesn't allow cycles such as:
    // class A implements B.BB { interface AA { } }
    // class B implements A.AA { interface BB { } }

    // So, even though grafting arbitrary DAGs together can give us cycles, Java
    // seems
    // to have our back on this one.
    final Class<?> enclosing = c.getEnclosingClass();
    if (enclosing != null) {
      register(ReflectionUtilities.getFullName(enclosing));
    }

    // Now register the class. This has to be after the above so we know our
    // parents (superclasses and enclosing packages) are already registered.
    final Node n = registerClass(c);

    // Finally, do things that might introduce cycles that invlove c.
    // This has to be below registerClass, which ensures that any cycles
    // this stuff introduces are broken.
    for (final Class<?> innerClass : c.getDeclaredClasses()) {
      register(ReflectionUtilities.getFullName(innerClass));
    }
    if (n instanceof ClassNode) {
      final ClassNode<?> cls = (ClassNode<?>) n;
      for (final ConstructorDef<?> def : cls.getInjectableConstructors()) {
        for (final ConstructorArg arg : def.getArgs()) {
          register(arg.getType());
          if (arg.getNamedParameterName() != null) {
            final NamedParameterNode<?> np =
                (NamedParameterNode<?>) register(arg.getNamedParameterName());
            try {
              // TODO: When handling sets, need to track target of generic parameter, and check the
              // type here!
              if (!np.isSet()
                  && !np.isList()
                  && !ReflectionUtilities.isCoercable(
                      classForName(arg.getType()), classForName(np.getFullArgName()))) {
                throw new ClassHierarchyException(
                    "Named parameter type mismatch in "
                        + cls.getFullName()
                        + ".  Constructor expects a "
                        + arg.getType()
                        + " but "
                        + np.getName()
                        + " is a "
                        + np.getFullArgName());
              }
            } catch (final ClassNotFoundException e) {
              throw new ClassHierarchyException(
                  "Constructor refers to unknown class " + arg.getType(), e);
            }
          }
        }
      }
    } else if (n instanceof NamedParameterNode) {
      final NamedParameterNode<?> np = (NamedParameterNode<?>) n;
      register(np.getFullArgName());
    }
    return n;
  }
Example #12
0
 private Node getAlreadyBoundNode(final Class<?> clazz) throws NameResolutionException {
   return getAlreadyBoundNode(ReflectionUtilities.getFullName(clazz));
 }
Example #13
0
 /** Helper method that converts a String to a Class using this ClassHierarchy's classloader. */
 @Override
 public Class<?> classForName(final String name) throws ClassNotFoundException {
   return ReflectionUtilities.classForName(name, loader);
 }