/** * 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); }
/** * @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(); }