Пример #1
0
 /** Creates a new instance of the specified type. */
 protected Object newInstance(Class<?> type) throws Exception {
   // find the most specific constructor that can take the last value
   if (_lvalue != null) {
     boolean inner = ReflectionUtil.isInner(type);
     _lvalue.getClass();
     Constructor cctor = null;
     Class<?> cptype = null;
     for (Constructor ctor : type.getConstructors()) {
       Class<?>[] ptypes = ctor.getParameterTypes();
       if (inner ? (ptypes.length != 2 || !ptypes[0].isInstance(_outer)) : (ptypes.length != 1)) {
         continue;
       }
       Class<?> ptype = ptypes[ptypes.length - 1];
       if (ptype.isInstance(_lvalue) && (cctor == null || cptype.isAssignableFrom(ptype))) {
         cctor = ctor;
         cptype = ptype;
       }
     }
     if (cctor != null) {
       return inner ? cctor.newInstance(_outer, _lvalue) : cctor.newInstance(_lvalue);
     }
   }
   // fall back on default constructor
   return ReflectionUtil.newInstance(type, _outer);
 }
Пример #2
0
 /** Determines whether the supplied value is legal for this property. */
 protected boolean isLegalValue(Class<?> type, Object value) {
   if (type.isPrimitive()) {
     if (value == null) {
       return false;
     }
     type = ClassUtil.objectEquivalentOf(type);
   }
   return (value == null) ? getAnnotation().nullable() : type.isInstance(value);
 }
Пример #3
0
 /** Adds the subtypes listed in the provided annotation to the supplied list. */
 protected static void addSubtypes(EditorTypes annotation, Collection<Class<?>> types) {
   for (Class<?> sclazz : annotation.value()) {
     // handle the case where the annotation includes the annotated class
     if (sclazz.getAnnotation(EditorTypes.class) == annotation) {
       types.add(sclazz);
     } else {
       addSubtypes(sclazz, types);
     }
   }
 }
Пример #4
0
  /** Returns the component type of this (array or collection) type. */
  public Class<?> getComponentType() {
    Class<?> type = getType();
    if (type.isArray()) {
      return type.getComponentType();

    } else if (Collection.class.isAssignableFrom(type)) {
      return getArgumentType(Collection.class);
    }
    return null;
  }
Пример #5
0
 /**
  * Returns the arguments of the provided generic class or interface.
  *
  * @param type the class to search.
  * @param args the class arguments.
  * @param clazz the generic class or interface of interest.
  * @return the arguments of the generic class or interface, or <code>null</code> if not found.
  */
 protected static Type[] getTypeArguments(Class<?> type, Type[] args, Class<?> clazz) {
   if (type == clazz) {
     return args;
   }
   TypeVariable[] params = type.getTypeParameters();
   for (Type iface : type.getGenericInterfaces()) {
     Type[] result = getTypeArguments(iface, params, args, clazz);
     if (result != null) {
       return result;
     }
   }
   return getTypeArguments(type.getGenericSuperclass(), params, args, clazz);
 }
Пример #6
0
 /** Returns the message bundle to use when translating the supplied class's properties. */
 public static String getMessageBundle(Class<?> clazz) {
   while (clazz.isArray()) {
     clazz = clazz.getComponentType();
   }
   if (clazz.isPrimitive()) {
     return EditorMessageBundle.DEFAULT;
   }
   String bundle = _bundles.get(clazz);
   if (bundle == null) {
     _bundles.put(clazz, bundle = findMessageBundle(clazz));
   }
   return bundle;
 }
Пример #7
0
  /** Returns the generic component type of this (array or collection) type. */
  public Type getGenericComponentType() {
    Class<?> type = getType();
    Type gtype = getGenericType();
    if (gtype instanceof GenericArrayType) {
      return ((GenericArrayType) gtype).getGenericComponentType();

    } else if (type.isArray()) {
      return type.getComponentType();

    } else if (Collection.class.isAssignableFrom(type)) {
      return getGenericArgumentType(Collection.class);
    }
    return null;
  }
Пример #8
0
 /**
  * Adds the subtypes of the specified class to the provided list. If the class has an {@link
  * EditorTypes} annotation, the classes therein will be added; otherwise, the class itself will be
  * added.
  */
 protected static void addSubtypes(Class<?> clazz, Collection<Class<?>> types) {
   EditorTypes annotation = clazz.getAnnotation(EditorTypes.class);
   if (annotation == null) {
     types.add(clazz);
   } else {
     addSubtypes(annotation, types);
   }
 }
Пример #9
0
  /**
   * Returns an array containing the available subtypes of the specified type, first looking to
   * subtypes listed in the annotation, then attempting to find a method using reflection.
   */
  protected Class<?>[] getSubtypes(Class<?> type) {
    ArrayList<Class<?>> types = new ArrayList<Class<?>>();

    // start with the null class, if allowed
    boolean nullable = getAnnotation().nullable();
    if (nullable) {
      types.add(null);
    }

    // look for a subtype annotation and add its types
    EditorTypes ownAnnotation = getAnnotation(EditorTypes.class);
    EditorTypes annotation =
        (ownAnnotation == null) ? type.getAnnotation(EditorTypes.class) : ownAnnotation;
    if (annotation != null) {
      addSubtypes(annotation, types);
    }

    // get the config key and add the config types
    String key = (annotation == null) ? type.getName() : annotation.key();
    if (StringUtil.isBlank(key)) {
      if (annotation == ownAnnotation) {
        Member member = getMember();
        key = member.getDeclaringClass().getName() + "." + member.getName();
      } else {
        key = type.getName();
      }
    }
    Class<?>[] ctypes = _configTypes.get(key);
    if (ctypes != null) {
      Collections.addAll(types, ctypes);
    }

    // if we don't have at least one non-null class, add the type itself
    if (types.size() == (nullable ? 1 : 0)) {
      types.add(type);
    }

    // convert to array, return
    return types.toArray(new Class<?>[types.size()]);
  }
Пример #10
0
 /** Finds the editor message bundle for the supplied class. */
 protected static String findMessageBundle(Class<?> clazz) {
   EditorMessageBundle annotation = clazz.getAnnotation(EditorMessageBundle.class);
   if (annotation != null) {
     return annotation.value();
   }
   Class<?> eclazz = clazz.getEnclosingClass();
   if (eclazz != null) {
     return getMessageBundle(eclazz);
   }
   String name = clazz.getName();
   int idx;
   while ((idx = name.lastIndexOf('.')) != -1) {
     name = name.substring(0, idx);
     Package pkg = Package.getPackage(name);
     if (pkg != null) {
       annotation = pkg.getAnnotation(EditorMessageBundle.class);
       if (annotation != null) {
         return annotation.value();
       }
     }
   }
   return EditorMessageBundle.DEFAULT;
 }
Пример #11
0
  /** Creates and returns the list of properties for the supplied class. */
  protected static Property[] createProperties(Class<?> clazz) {
    // get the list of properties
    ArrayList<Property> properties = new ArrayList<Property>();
    createProperties(clazz, properties);

    // sort the properties by weight
    Collections.sort(properties, WEIGHT_COMP);

    // if the class has a property order attribute, move the listed properties
    // to the beginning in the desired order
    PropertyOrder order = clazz.getAnnotation(PropertyOrder.class);
    if (order != null) {
      int index = 0;
      for (String name : order.value()) {
        int oindex = index;
        for (int ii = index, nn = properties.size(); ii < nn; ii++) {
          Property property = properties.get(ii);
          if (property.getName().equals(name)) {
            properties.remove(ii);
            properties.add(index++, property);
            break;
          }
        }
        if (index == oindex) {
          log.warning(
              "Missing property in order annotation [class="
                  + clazz.getName()
                  + ", property="
                  + name
                  + "].");
        }
      }
    }

    // return an array with the results
    return properties.toArray(new Property[properties.size()]);
  }
Пример #12
0
 static {
   // load the types from the configuration
   Config config = new Config("/rsrc/config/editor/type");
   for (Iterator<String> it = config.keys(); it.hasNext(); ) {
     String key = it.next();
     ArrayList<Class<?>> classes = new ArrayList<Class<?>>();
     for (String cname : config.getValue(key, ArrayUtil.EMPTY_STRING)) {
       try {
         addSubtypes(Class.forName(cname), classes);
       } catch (ClassNotFoundException e) {
         log.warning("Missing type config class.", "class", cname, e);
       }
     }
     _configTypes.put(key, classes.toArray(new Class<?>[classes.size()]));
   }
 }
Пример #13
0
 /**
  * Returns the editor types annotation on the property, if it exists, or on the specified type, if
  * that exists, or <code>null</code> if neither one exists.
  */
 protected EditorTypes getEditorTypes(Class<?> type) {
   EditorTypes annotation = getAnnotation(EditorTypes.class);
   return (annotation == null) ? type.getAnnotation(EditorTypes.class) : annotation;
 }
Пример #14
0
  /** Retrieves all {@link Editable} properties of the specified class. */
  protected static void createProperties(Class<?> clazz, ArrayList<Property> properties) {
    // prepend the superclass properties
    Class<?> sclazz = clazz.getSuperclass();
    if (sclazz != null) {
      Collections.addAll(properties, getProperties(sclazz));
    }

    // find the getters and setters
    HashMap<String, Method> unpaired = new HashMap<String, Method>();
    for (Method method : clazz.getDeclaredMethods()) {
      if (!method.isAnnotationPresent(Editable.class)) {
        continue;
      }
      String name = method.getName();
      boolean getter;
      if (name.startsWith("set")) {
        name = name.substring(3);
        getter = false;
      } else {
        if (name.startsWith("get")) {
          name = name.substring(3);
        } else if (name.startsWith("is")) {
          name = name.substring(2);
        } else {
          log.warning(
              "Invalid method name for editable property [class="
                  + clazz
                  + ", name="
                  + name
                  + "].");
          continue;
        }
        getter = true;
      }
      Method omethod = unpaired.remove(name);
      if (omethod != null) {
        Method gmethod = getter ? method : omethod;
        Method smethod = getter ? omethod : method;
        Class<?> rtype = gmethod.getReturnType();
        Class<?>[] ptypes = smethod.getParameterTypes();
        if (ptypes.length != 1 || ptypes[0] != rtype) {
          log.warning(
              "Mismatched types on getter/setter [class="
                  + clazz
                  + ", getter="
                  + gmethod
                  + ", setter="
                  + smethod
                  + "].");
          continue;
        }
        properties.add(new MethodProperty(gmethod, smethod));
      } else {
        unpaired.put(name, method);
      }
    }
    if (!unpaired.isEmpty()) {
      log.warning(
          "Found unmatched getters/setters [class="
              + clazz
              + ", methods="
              + unpaired.values()
              + "].");
    }

    // add all editable fields
    for (Field field : clazz.getDeclaredFields()) {
      if (field.isAnnotationPresent(Editable.class)) {
        properties.add(new FieldProperty(field));
      }
    }
  }