private Object addArrayValue( Object proxy, String name, Class itemType, Class expectedReturnType, Object arg) { if (arrays == null) arrays = new HashMap<String, JAnnotationArrayMember>(); JAnnotationArrayMember m = arrays.get(name); if (m == null) { m = use.paramArray(name); arrays.put(name, m); } // sub annotation if (Annotation.class.isAssignableFrom(itemType)) { Class<? extends Annotation> r = (Class<? extends Annotation>) itemType; if (!JAnnotationWriter.class.isAssignableFrom(expectedReturnType)) throw new IllegalArgumentException("Unexpected return type " + expectedReturnType); return new TypedAnnotationWriter(r, expectedReturnType, m.annotate(r)).createProxy(); } // primitive if (arg instanceof JType) { checkType(Class.class, itemType); m.param((JType) arg); return proxy; } checkType(arg.getClass(), itemType); if (arg instanceof String) { m.param((String) arg); return proxy; } if (arg instanceof Boolean) { m.param((Boolean) arg); return proxy; } if (arg instanceof Integer) { m.param((Integer) arg); return proxy; } if (arg instanceof Class) { m.param((Class) arg); return proxy; } // TODO: enum constant. how should we handle it? throw new IllegalArgumentException("Unable to handle this method call "); }
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if (method.getDeclaringClass() == JAnnotationWriter.class) { try { return method.invoke(this, args); } catch (InvocationTargetException e) { throw e.getTargetException(); } } String name = method.getName(); Object arg = null; if (args != null && args.length > 0) arg = args[0]; // check how it's defined on the annotation Method m = annotation.getDeclaredMethod(name); Class<?> rt = m.getReturnType(); // array value if (rt.isArray()) { return addArrayValue(proxy, name, rt.getComponentType(), method.getReturnType(), arg); } // sub annotation if (Annotation.class.isAssignableFrom(rt)) { Class<? extends Annotation> r = (Class<? extends Annotation>) rt; return new TypedAnnotationWriter(r, method.getReturnType(), use.annotationParam(name, r)) .createProxy(); } // scalar value if (arg instanceof JType) { JType targ = (JType) arg; checkType(Class.class, rt); if (m.getDefaultValue() != null) { // check the default if (targ.equals(targ.owner().ref((Class) m.getDefaultValue()))) return proxy; // defaulted } use.param(name, targ); return proxy; } // other Java built-in types checkType(arg.getClass(), rt); if (m.getDefaultValue() != null && m.getDefaultValue().equals(arg)) // defaulted. no need to write out. return proxy; if (arg instanceof String) { use.param(name, (String) arg); return proxy; } if (arg instanceof Boolean) { use.param(name, (Boolean) arg); return proxy; } if (arg instanceof Integer) { use.param(name, (Integer) arg); return proxy; } if (arg instanceof Class) { use.param(name, (Class) arg); return proxy; } if (arg instanceof Enum) { use.param(name, (Enum) arg); return proxy; } throw new IllegalArgumentException("Unable to handle this method call " + method.toString()); }