View Javadoc

1   /***************************************************************************************
2    * Copyright (c) Jonas Bonér, Alexandre Vasseur. All rights reserved.                 *
3    * http://aspectwerkz.codehaus.org                                                    *
4    * ---------------------------------------------------------------------------------- *
5    * The software in this package is published under the terms of the LGPL license      *
6    * a copy of which has been included with this distribution in the license.txt file.  *
7    **************************************************************************************/
8   package org.codehaus.aspectwerkz.annotation;
9   
10  import org.codehaus.aspectwerkz.exception.WrappedRuntimeException;
11  
12  import java.io.Serializable;
13  import java.lang.reflect.Array;
14  
15  /***
16   * A structure for an Annotation element
17   * It wraps value behind an holder. The holder is the object itself (boxed) excepted
18   * for Class, for which it is a LazyClass.
19   *
20   * @author <a href="mailto:alex AT gnilux DOT com">Alexandre Vasseur</a>
21   */
22  public class AnnotationElement implements Serializable {
23  
24      //TODO calculate
25      private static final long serialVersionUID = 1L;
26  
27      /***
28       * element name
29       */
30      String name;
31  
32      /***
33       * element value holder
34       */
35      private Object valueHolder;
36  
37      /***
38       * true if we have a lasy class (optimization to avoid instance of at each get)
39       */
40      protected boolean isLazyClass = false;
41  
42      /***
43       * true if we have a lasy class array (N-dim) (optimization to avoid instance of at each get)
44       */
45      protected boolean isLazyClassArray = false;
46  
47      /***
48       * Build a new annotation element
49       * @param name
50       * @param valueHolder
51       */
52      public AnnotationElement(String name, Object valueHolder) {
53          this.name = name;
54          this.valueHolder = valueHolder;
55          if (valueHolder instanceof LazyClass) {
56              isLazyClass = true;
57          } else if (valueHolder instanceof LazyClass[]) {
58              isLazyClassArray = true;
59          }
60      }
61  
62      /***
63       * Returns the actual holded element value
64       *
65       * @param loader from which to resolve LazyClass. It should be the annotated element class loader
66       * @return
67       */
68      public Object resolveValueHolderFrom(ClassLoader loader) {
69          if (isLazyClass) {
70              return ((LazyClass) valueHolder).resolveFrom(loader);
71          } else if (isLazyClassArray) {
72              Object[] annotationValueHolderArray = (Object[]) valueHolder;
73              Class[] resolved = new Class[annotationValueHolderArray.length];
74              for (int i = 0; i < annotationValueHolderArray.length; i++) {
75                  resolved[i] = ((LazyClass)annotationValueHolderArray[i]).resolveFrom(loader);
76              }
77              return resolved;
78              //TODO support N dimension array needed ?
79          } else {
80              return valueHolder;
81          }
82      }
83  
84      /***
85       * Returns a string representation of the annotation element value
86       *
87       * Note that such a represention won't look like source code.
88       * (f.e. element String s() will not have quotes and escapes etc).
89       * @return
90       */
91      public String toString() {
92          if (isLazyClass) {
93              StringBuffer sb = new StringBuffer("class ");
94              sb.append(((LazyClass) valueHolder).className);
95              return sb.toString();
96          } else {
97              if (valueHolder == null) {
98                  return "null";
99              } else {
100                 return valueHolder.toString();
101             }
102         }
103     }
104 
105     /***
106      * A wrapper for a className, that will allow late loading of the actual Class object of an annotation value
107      * For array type, className is componentClassName([])*
108      *
109      * @author <a href="mailto:alex AT gnilux DOT com">Alexandre Vasseur</a>
110      */
111     public static class LazyClass implements Serializable {
112 
113         //TODO calculate
114         private static final long serialVersionUID = 1L;
115 
116         public String className;
117         private String componentClassName = null;
118         private int dimemsion = 0;
119 
120         public LazyClass(String className) {
121             this.className = className;
122 
123             componentClassName = className;
124             while (componentClassName.endsWith("[]")) {
125                 dimemsion++;
126                 componentClassName = componentClassName.substring(0, componentClassName.length()-2);
127             }
128         }
129 
130         public String toString() {
131             return className;
132         }
133 
134         public Class resolveFrom(ClassLoader loader) {
135             try {
136                 if (dimemsion <= 0) {
137                     return Class.forName(className, false, loader);
138                 } else {
139                     Class componentClass = Class.forName(componentClassName, false, loader);
140                     return (Array.newInstance(componentClass, dimemsion)).getClass();
141                 }
142             } catch (ClassNotFoundException e) {
143                 throw new WrappedRuntimeException(e);
144             }
145         }
146     }
147 
148 }