/**
   * Adapts the source object to a view object.
   *
   * @param mapper An action that is invoked for each source object in the graph that is to be
   *     adapted. The action can influence how the source object is adapted via the provided {@link
   *     SourceObjectMapping}.
   */
  public <T, S> T adapt(
      Class<T> targetType, S sourceObject, Action<? super SourceObjectMapping> mapper) {
    if (sourceObject == null) {
      return null;
    }
    Class<? extends T> wrapperType = targetTypeProvider.getTargetType(targetType, sourceObject);
    DefaultSourceObjectMapping mapping =
        new DefaultSourceObjectMapping(sourceObject, targetType, wrapperType);
    mapper.execute(mapping);
    wrapperType = mapping.wrapperType.asSubclass(targetType);
    if (wrapperType.isInstance(sourceObject)) {
      return wrapperType.cast(sourceObject);
    }
    if (targetType.isEnum()) {
      return adaptToEnum(targetType, sourceObject);
    }

    MixInMethodInvoker mixInMethodInvoker = null;
    if (mapping.mixInType != null) {
      mixInMethodInvoker =
          new MixInMethodInvoker(
              mapping.mixInType, new AdaptingMethodInvoker(mapper, new ReflectionMethodInvoker()));
    }
    MethodInvoker overrideInvoker = chainInvokers(mixInMethodInvoker, mapping.overrideInvoker);
    Object proxy =
        Proxy.newProxyInstance(
            wrapperType.getClassLoader(),
            new Class<?>[] {wrapperType},
            new InvocationHandlerImpl(sourceObject, overrideInvoker, mapper));
    if (mixInMethodInvoker != null) {
      mixInMethodInvoker.setProxy(proxy);
    }
    return wrapperType.cast(proxy);
  }
 public void apply()
     throws IllegalAccessException, InvocationTargetException, InstantiationException {
   if (type.isEnum()) {
     for (T instance : type.getEnumConstants()) {
       assertThat(
           instance.toString(),
           is(
               type.getCanonicalName().substring(type.getPackage().getName().length() + 1)
                   + "."
                   + ((Enum<?>) instance).name()));
     }
     return;
   }
   for (Constructor<?> constructor : type.getDeclaredConstructors()) {
     if (constructor.isSynthetic() && skipSynthetic) {
       continue;
     }
     constructor.setAccessible(true);
     Class<?>[] parameterTypes = constructor.getParameterTypes();
     Object[] actualArguments = new Object[parameterTypes.length];
     Object[] otherArguments = new Object[parameterTypes.length];
     int index = 0;
     for (Class<?> parameterType : parameterTypes) {
       putInstance(parameterType, actualArguments, otherArguments, index++);
     }
     int testIndex = 0;
     @SuppressWarnings("unchecked")
     T instance = (T) constructor.newInstance(actualArguments);
     assertThat(instance, is(instance));
     assertThat(instance, not(is((Object) null)));
     assertThat(instance, not(is(new Object())));
     Object similarInstance = constructor.newInstance(actualArguments);
     assertThat(instance.hashCode(), is(similarInstance.hashCode()));
     assertThat(instance, is(similarInstance));
     if (skipToString) {
       assertThat(instance.toString(), notNullValue());
     } else if (optionalToStringRegex == null) {
       checkString(instance);
     } else {
       assertThat(instance.toString(), new RegexMatcher(optionalToStringRegex));
     }
     for (Object otherArgument : otherArguments) {
       Object[] compareArguments = new Object[actualArguments.length];
       int argumentIndex = 0;
       for (Object actualArgument : actualArguments) {
         if (argumentIndex == testIndex) {
           compareArguments[argumentIndex] = otherArgument;
         } else {
           compareArguments[argumentIndex] = actualArgument;
         }
         argumentIndex++;
       }
       Object unlikeInstance = constructor.newInstance(compareArguments);
       assertThat(instance.hashCode(), not(is(unlikeInstance)));
       assertThat(instance, not(is(unlikeInstance)));
       testIndex++;
     }
   }
 }
 private void putInstance(
     Class<?> parameterType, Object actualArguments, Object otherArguments, int index) {
   Object actualArgument, otherArgument;
   if (parameterType == boolean.class) {
     actualArgument = DEFAULT_BOOLEAN;
     otherArgument = OTHER_BOOLEAN;
   } else if (parameterType == byte.class) {
     actualArgument = DEFAULT_BYTE;
     otherArgument = OTHER_BYTE;
   } else if (parameterType == char.class) {
     actualArgument = DEFAULT_CHAR;
     otherArgument = OTHER_CHAR;
   } else if (parameterType == short.class) {
     actualArgument = DEFAULT_SHORT;
     otherArgument = OTHER_SHORT;
   } else if (parameterType == int.class) {
     actualArgument = DEFAULT_INT;
     otherArgument = OTHER_INT;
   } else if (parameterType == long.class) {
     actualArgument = DEFAULT_LONG;
     otherArgument = OTHER_LONG;
   } else if (parameterType == float.class) {
     actualArgument = DEFAULT_FLOAT;
     otherArgument = OTHER_FLOAT;
   } else if (parameterType == double.class) {
     actualArgument = DEFAULT_DOUBLE;
     otherArgument = OTHER_DOUBLE;
   } else if (parameterType.isEnum()) {
     Object[] enumConstants = parameterType.getEnumConstants();
     if (enumConstants.length == 1) {
       throw new IllegalArgumentException("Enum with only one constant: " + parameterType);
     }
     actualArgument = enumConstants[0];
     otherArgument = enumConstants[1];
   } else if (parameterType.isArray()) {
     actualArgument = Array.newInstance(parameterType.getComponentType(), 1);
     otherArgument = Array.newInstance(parameterType.getComponentType(), 1);
     putInstance(parameterType.getComponentType(), actualArgument, otherArgument, 0);
   } else {
     actualArgument = creator.replace(parameterType, generator, false);
     refinement.apply(actualArgument);
     otherArgument = creator.replace(parameterType, generator, true);
     refinement.apply(otherArgument);
   }
   Array.set(actualArguments, index, actualArgument);
   Array.set(otherArguments, index, otherArgument);
 }
示例#4
0
  /**
   * @return Null if class might be a bean; type String (that identifies why it's not a bean) if not
   */
  public static String canBeABeanType(Class<?> type) {
    // First: language constructs that ain't beans:
    if (type.isAnnotation()) {
      return "annotation";
    }
    if (type.isArray()) {
      return "array";
    }
    if (type.isEnum()) {
      return "enum";
    }
    if (type.isPrimitive()) {
      return "primitive";
    }

    // Anything else? Seems valid, then
    return null;
  }
 public JSONObject describeClass(Class<?> clazz) throws Exception {
   JSONObject desc = new JSONObject();
   desc.put("name", clazz.getName());
   if (clazz.isEnum()) {
     @SuppressWarnings("unchecked")
     Class<Enum<?>> enumClass = (Class<Enum<?>>) clazz;
     ArrayList<String> enumNames = Lists.newArrayList();
     for (Enum<?> e : enumClass.getEnumConstants()) {
       enumNames.add(e.name());
     }
     desc.put("enum", enumNames);
   }
   UI_TYPE ui_type = UI_TYPE.getEnumFor(clazz);
   if (ui_type != null) {
     desc.put("uiType", ui_type.getName());
   }
   desc.put("properties", getClassProperties(clazz, 0));
   return desc;
 }
 @SuppressWarnings("unchecked")
 private static <T> T createFinalArgumentPlaceholder(Class<T> clazz) {
   if (clazz == Boolean.TYPE || clazz == Boolean.class) return (T) Boolean.FALSE;
   if (clazz.isEnum()) return (T) EnumSet.allOf((Class<? extends Enum>) clazz).iterator().next();
   return (T) createArgumentPlaceholder(clazz, FINAL_PLACEHOLDER_SEED);
 }
 @SuppressWarnings("unchecked")
 Object getNextPlaceholder(Class<?> clazz) {
   return clazz.isEnum()
       ? getNextEnumPlaceholder((Class<? extends Enum>) clazz)
       : getNextBooleanPlaceholder();
 }
 private static boolean isLimitedValues(Class<?> clazz) {
   return clazz == Boolean.TYPE || clazz == Boolean.class || clazz.isEnum();
 }