@Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if (isHashCode(method)) { return proxyHashCode(proxy); } else if (isEquals(method)) { return proxyEquals(proxy, args[0]); } else if (isAnnotationType(method)) { return proxyAnnotationType(); } else if (isToString(method)) { return proxyToString(proxy); } else if (attributes.containsKey(method.getName()) && method.getParameterTypes().length == 0) { return copyAnnotationValue(attributes.get(method.getName())); } else { // fall back to the default return copyAnnotationValue(method.getDefaultValue()); } // wait() and other Object methods do not get sent to the InvocationHandler // so we don't have any other cases }
private AnnotationBuilder<T> set(String name, Object value, Class<?> type) { try { Method attr = this.type.getMethod(name); if (!attr.getReturnType().isAssignableFrom(type)) { throw new IllegalArgumentException("Attribute named: " + name + " expects a type of " + attr.getReturnType() + ", but got " + type); } // if valid, save for later attributes.put(name, AnnotationProxy.copyAnnotationValue(value)); return this; } catch (SecurityException e) { throw new RuntimeException(e); } catch (NoSuchMethodException e) { throw new IllegalArgumentException("Annotation type " + this.type + " does not have an attribute named: " + name); } }
/** * Build an Annotation instance of type T that is configured to return the * values assigned by the various set() methods for its defined attributes. * If attributes have a default value and the value was not overridden by * the builder's configuration, then the default will be returned by the * annotation instance. * * @return An instance of T with the attribute values specified on this * builder * @throws IllegalStateException if there are attributes with no default * that have not been assigned explicit values */ public T build() { for (Method attr: type.getDeclaredMethods()) { if (attr.getDefaultValue() == null) { // this is a required value, so we have to // verify that its been assigned if (!attributes.containsKey(attr.getName())) { throw new IllegalStateException("No value assigned to required attribute: " + attr.getName()); } } } return type.cast(Proxy.newProxyInstance(getClass().getClassLoader(), new Class<?>[] { type }, new AnnotationProxy<T>(type, attributes))); } }