Ejemplo n.º 1
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;
  }
Ejemplo n.º 4
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);
   }
 }
 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));
 }
Ejemplo n.º 7
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;
  }
Ejemplo n.º 8
0
 private Node getAlreadyBoundNode(final Class<?> clazz) throws NameResolutionException {
   return getAlreadyBoundNode(ReflectionUtilities.getFullName(clazz));
 }