EMMA Coverage Report (generated Mon Nov 26 19:18:24 CET 2007)
[all classes][net.sourceforge.retroweaver.runtime.java.lang.annotation]

COVERAGE SUMMARY FOR SOURCE FILE [AnnotationImpl.java]

nameclass, %method, %block, %line, %
AnnotationImpl.java100% (1/1)50%  (4/8)45%  (103/230)40%  (17/42)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class AnnotationImpl100% (1/1)50%  (4/8)45%  (103/230)40%  (17/42)
annotationType (): Class 0%   (0/1)0%   (0/3)0%   (0/1)
equals (Object): boolean 0%   (0/1)0%   (0/13)0%   (0/1)
hashCode (): int 0%   (0/1)0%   (0/4)0%   (0/1)
toString (): String 0%   (0/1)0%   (0/72)0%   (0/15)
invoke (Object, Method, Object []): Object 100% (1/1)70%  (33/47)73%  (8/11)
createAnnotation (Class, Map): Annotation 100% (1/1)73%  (38/52)33%  (1/3)
<static initializer> 100% (1/1)74%  (20/27)67%  (4/6)
AnnotationImpl (Class, Map): void 100% (1/1)100% (12/12)100% (4/4)

1 
2package net.sourceforge.retroweaver.runtime.java.lang.annotation;
3 
4import java.lang.reflect.InvocationHandler;
5import java.lang.reflect.Method;
6import java.lang.reflect.Proxy;
7import java.util.HashMap;
8import java.util.Map;
9 
10/**
11 * The implementation of the Annotation interface, which gets returned from various points
12 * in java.lang.Class and java.lang.reflect.* classes.
13 *
14 * @author Toby Reyelts
15 * Date: Feb 20, 2005
16 * Time: 11:37:18 PM
17 */
18public class AnnotationImpl implements InvocationHandler, Annotation {
19 
20  private final Class<? extends Annotation> annotationType_;
21  private final Map<String,Object> attributes;
22 
23  /**
24   * Called from generated bytecode to instantiate a new Annotation.
25   * Specifically, a new dynamic proxy is created with a type annotationType,
26   * and this class as the InvocationHandler.
27   *
28   * @param annotationType - The Annotation class that this AnnotationImpl should represent
29   * @param attributes - The attributes for the Annotation
30   *
31   * For example, for @Persistable, Persistable.class
32   */
33  public static Annotation createAnnotation(final Class<? extends Annotation> annotationType, final Map<String,Object> attributes) {
34    try {
35      return (Annotation) Proxy.newProxyInstance(AnnotationImpl.class.getClassLoader(), new Class[] { Annotation.class, annotationType }, new AnnotationImpl(annotationType, attributes)); 
36    }
37    catch (IllegalArgumentException e) {
38      throw new AnnotationFormatError("Unexpected exception while trying to create an annotation of type: " + annotationType, e);
39    }
40  }
41 
42  private AnnotationImpl(final Class<? extends Annotation> annotationType, final Map<String,Object> attributes) {
43    this.attributes = new HashMap<String,Object>(attributes);
44    this.annotationType_ = annotationType;
45  }
46 
47  private static final Method cloneMethod;
48 
49  static {
50        try {
51                cloneMethod = Object.class.getDeclaredMethod("clone", new Class[0]);
52                cloneMethod.setAccessible(true);
53        } catch (NoSuchMethodException e) {
54                throw new RuntimeException(e.getMessage());
55        }
56  }
57 
58  public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable {
59    // If it's declared in the annotationType, it's an attribute
60    if (method.getDeclaringClass().equals(annotationType_)) {
61        final String name = method.getName();
62            if (attributes.containsKey(name)) {
63                    Object o = attributes.get(name);
64                    if (o == null) {
65                            return null;
66                    } else if (o.getClass().isArray()) {
67                            o = cloneMethod.invoke(o);
68                    }
69                    return o;
70            }
71            throw new IncompleteAnnotationException(annotationType_, name);
72    }
73 
74    // Otherwise it's something we handle innately
75    return method.invoke(this, args);
76  }
77 
78  // Returns the annotation type of this annotation.
79  public Class<? extends Annotation> annotationType() {
80    return annotationType_;
81  }
82 
83  // Returns true if the specified object represents an annotation that is logically equivalent to this one.
84  public boolean equals(final Object obj) {
85    return (obj instanceof AnnotationImpl && ((AnnotationImpl) obj).annotationType_ == annotationType_);
86  }
87 
88  // Returns the hash code of this annotation, as defined below:
89  public int hashCode() {
90    // TODO: Implement this according to spec.
91    //System.out.println("Warning: Annotation.hashCode() has yet to be implemented according to spec.");
92    //return annotationType.hashCode();
93          return toString().hashCode();
94  }
95 
96  // Returns a string representation of this annotation.
97  public String toString() {
98    // TODO: Implement this according to spec.
99 
100          final StringBuilder msg = new StringBuilder();
101          msg.append('@').append(annotationType_.getName()).append('('); 
102          boolean first = true;
103          for (Map.Entry<String, Object> e: attributes.entrySet()) {
104                  if (first) {
105                          first = false;
106                  } else {
107                          msg.append(", ");
108                  }
109                  msg.append(e.getKey()).append('=');
110                  final Object o = e.getValue();
111                  if (o.getClass().isArray()) {
112                          msg.append(java.util.Arrays.deepToString((Object[])o));
113                  } else {
114                          msg.append(o);
115                  }
116          }
117          msg.append(')');
118          return msg.toString();
119  }
120 
121}
122 

[all classes][net.sourceforge.retroweaver.runtime.java.lang.annotation]
EMMA 2.0.7906 (unsupported private build) (C) Vladimir Roubtsov