public static Type getNamedParameterTargetOrNull(final Class<?> clazz)
      throws ClassHierarchyException {
    final Annotation npAnnotation = clazz.getAnnotation(NamedParameter.class);
    final boolean hasSuperClass = clazz.getSuperclass() != Object.class;

    boolean isInjectable = false;
    boolean hasConstructor = false;
    // TODO Figure out how to properly differentiate between default and
    // non-default zero-arg constructors?
    final Constructor<?>[] constructors = clazz.getDeclaredConstructors();
    if (constructors.length > 1) {
      hasConstructor = true;
    }
    if (constructors.length == 1) {
      final Constructor<?> c = constructors[0];
      final Class<?>[] p = c.getParameterTypes();
      if (p.length > 1) {
        // Multiple args. Definitely not implicit.
        hasConstructor = true;
      } else if (p.length == 1) {
        // One arg. Could be an inner class, in which case the compiler
        // included an implicit one parameter constructor that takes the
        // enclosing type.
        if (p[0] != clazz.getEnclosingClass()) {
          hasConstructor = true;
        }
      }
    }
    for (final Constructor<?> c : constructors) {
      for (final Annotation a : c.getDeclaredAnnotations()) {
        if (a instanceof Inject) {
          isInjectable = true;
        }
      }
    }

    final Class<?>[] allInterfaces = clazz.getInterfaces();

    final boolean hasMultipleInterfaces = allInterfaces.length > 1;
    boolean implementsName;
    Type parameterClass = null;
    try {
      parameterClass = getInterfaceTarget(Name.class, clazz);
      implementsName = true;
    } catch (final IllegalArgumentException e) {
      implementsName = false;
    }

    if (npAnnotation == null) {
      if (implementsName) {
        throw new ClassHierarchyException("Named parameter " + getFullName(clazz)
            + " is missing its @NamedParameter annotation.");
      } else {
        return null;
      }
    } else {
      if (!implementsName) {
        throw new ClassHierarchyException("Found illegal @NamedParameter " + getFullName(clazz)
            + " does not implement Name<?>");
      }
      if (hasSuperClass) {
        throw new ClassHierarchyException("Named parameter " + getFullName(clazz)
            + " has a superclass other than Object.");
      }
      if (hasConstructor || isInjectable) {
        throw new ClassHierarchyException("Named parameter " + getFullName(clazz) + " has "
            + (isInjectable ? "an injectable" : "a") + " constructor. "
            + " Named parameters must not declare any constructors.");
      }
      if (hasMultipleInterfaces) {
        throw new ClassHierarchyException("Named parameter " + getFullName(clazz) + " implements "
            + "multiple interfaces.  It is only allowed to implement Name<T>");
      }
      if (parameterClass == null) {
        throw new ClassHierarchyException(
            "Missing type parameter in named parameter declaration.  " + getFullName(clazz)
                + " implements raw type Name, but must implement"
                + " generic type Name<T>.");
      }
      return parameterClass;
    }
  }
public static Type getNamedParameterTargetOrNull ( final Class < ? > clazz ) throws ClassHierarchyException { final Annotation npAnnotation = clazz . getAnnotation ( NamedParameter . class ) ; final boolean hasSuperClass = clazz . getSuperclass ( ) != Object . class ; boolean isInjectable = false ; boolean hasConstructor = false ; final Constructor < ? > [ ] constructors = clazz . getDeclaredConstructors ( ) ; if ( constructors . length > 1 ) { hasConstructor = true ; } if ( constructors . length == 1 ) { final Constructor < ? > c = constructors [ 0 ] ; final Class < ? > [ ] p = c . getParameterTypes ( ) ; if ( p . length > 1 ) { hasConstructor = true ; } else if ( p . length == 1 ) { if ( p [ 0 ] != clazz . getEnclosingClass ( ) ) { hasConstructor = true ; } } } for ( final Constructor < ? > c : constructors ) { for ( final Annotation a : c . getDeclaredAnnotations ( ) ) { if ( a instanceof Inject ) { isInjectable = true ; } } } final Class < ? > [ ] allInterfaces = clazz . getInterfaces ( ) ; final boolean hasMultipleInterfaces = allInterfaces . length > 1 ; boolean implementsName ; Type parameterClass = null ; try { parameterClass = getInterfaceTarget ( Name . class , clazz ) ; implementsName = true ; } catch ( final IllegalArgumentException e ) { implementsName = false ; } if ( npAnnotation == null ) { if ( implementsName ) { throw new ClassHierarchyException ( "Named parameter " + getFullName ( clazz ) + " is missing its @NamedParameter annotation." ) ; } else { return null ; } } else { if ( ! implementsName ) { throw new ClassHierarchyException ( "Found illegal @NamedParameter " + getFullName ( clazz ) + " does not implement Name<?>" ) ; } if ( hasSuperClass ) { throw new ClassHierarchyException ( "Named parameter " + getFullName ( clazz ) + " has a superclass other than Object." ) ; } if ( hasConstructor || isInjectable ) { throw new ClassHierarchyException ( "Named parameter " + getFullName ( clazz ) + " has " + ( isInjectable ? "an injectable" : "a" ) + " constructor. " + " Named parameters must not declare any constructors." ) ; } if ( hasMultipleInterfaces ) { throw new ClassHierarchyException ( "Named parameter " + getFullName ( clazz ) + " implements " + "multiple interfaces.  It is only allowed to implement Name<T>" ) ; } if ( parameterClass == null ) { throw new ClassHierarchyException ( "Missing type parameter in named parameter declaration.  " + getFullName ( clazz ) + " implements raw type Name, but must implement" + " generic type Name<T>." ) ; } return parameterClass ; } }
@param clazz
@return T if clazz implements {@code Name<T>}, null otherwise
@throws org.apache.reef.tang.exceptions.BindException
If clazz's definition incorrectly uses Name or @NamedParameter