/**
  * returns an implementation of the spec class corresponding to the given target type; for use in
  * {@link BrooklynTypePlanTransformer#create(RegisteredType, RegisteredTypeLoadingContext)}
  * implementations when dealing with a spec; returns null if none found
  *
  * @param mgmt
  */
 @Beta
 public static AbstractBrooklynObjectSpec<?, ?> newSpecInstance(
     ManagementContext mgmt, Class<? extends BrooklynObject> targetType) throws Exception {
   Class<? extends AbstractBrooklynObjectSpec<?, ?>> specType =
       RegisteredTypeLoadingContexts.lookupSpecTypeForTarget(targetType);
   if (specType == null) return null;
   Method createMethod = specType.getMethod("create", Class.class);
   return (AbstractBrooklynObjectSpec<?, ?>) createMethod.invoke(null, targetType);
 }
  private static <T> Maybe<T> tryValidateSpec(
      T object, RegisteredType rType, final RegisteredTypeLoadingContext constraint) {
    if (object == null) return Maybe.absentNull("object is null");

    if (!(object instanceof AbstractBrooklynObjectSpec)) {
      Maybe.absent("Found " + object + " when expecting a spec");
    }
    Class<?> targetType = ((AbstractBrooklynObjectSpec<?, ?>) object).getType();

    if (targetType == null) {
      Maybe.absent("Spec " + object + " does not have a target type");
    }

    if (rType != null) {
      if (rType.getKind() != RegisteredTypeKind.SPEC)
        Maybe.absent("Validating a spec when type is " + rType.getKind() + " " + rType);
      if (!isSubtypeOf(targetType, rType))
        Maybe.absent(object + " does not have all the java supertypes of " + rType);
    }

    if (constraint != null) {
      if (constraint.getExpectedJavaSuperType() != null) {
        if (!constraint.getExpectedJavaSuperType().isAssignableFrom(targetType)) {
          Maybe.absent(
              object
                  + " does not target the expected java supertype "
                  + constraint.getExpectedJavaSuperType());
        }
        if (constraint.getExpectedJavaSuperType().isAssignableFrom(BrooklynObjectInternal.class)) {
          // don't check spec type; any spec is acceptable
        } else {
          @SuppressWarnings("unchecked")
          Class<? extends AbstractBrooklynObjectSpec<?, ?>> specType =
              RegisteredTypeLoadingContexts.lookupSpecTypeForTarget(
                  (Class<? extends BrooklynObject>) constraint.getExpectedJavaSuperType());
          if (specType == null) {
            // means a problem in our classification of spec types!
            Maybe.absent(
                object
                    + " is returned as spec for unexpected java supertype "
                    + constraint.getExpectedJavaSuperType());
          }
          if (!specType.isAssignableFrom(object.getClass())) {
            Maybe.absent(
                object
                    + " is not a spec of the expected java supertype "
                    + constraint.getExpectedJavaSuperType());
          }
        }
      }
    }
    return Maybe.of(object);
  }