001: /**************************************************************************************
002: * Copyright (c) Jonas Bonér, Alexandre Vasseur. All rights reserved. *
003: * http://aspectwerkz.codehaus.org *
004: * ---------------------------------------------------------------------------------- *
005: * The software in this package is published under the terms of the LGPL license *
006: * a copy of which has been included with this distribution in the license.txt file. *
007: **************************************************************************************/package org.codehaus.aspectwerkz.annotation;
008:
009: import org.codehaus.aspectwerkz.exception.WrappedRuntimeException;
010:
011: import java.io.Serializable;
012: import java.lang.reflect.Array;
013:
014: /**
015: * A structure for an Annotation element
016: * It wraps value behind an holder. The holder is the object itself (boxed) excepted
017: * for Class, for which it is a LazyClass.
018: *
019: * @author <a href="mailto:alex AT gnilux DOT com">Alexandre Vasseur</a>
020: */
021: public class AnnotationElement implements Serializable {
022:
023: //TODO calculate
024: private static final long serialVersionUID = 1L;
025:
026: /**
027: * element name
028: */
029: String name;
030:
031: /**
032: * element value holder
033: */
034: private Object valueHolder;
035:
036: /**
037: * true if we have a lasy class (optimization to avoid instance of at each get)
038: */
039: protected boolean isLazyClass = false;
040:
041: /**
042: * true if we have a lasy class array (N-dim) (optimization to avoid instance of at each get)
043: */
044: protected boolean isLazyClassArray = false;
045:
046: /**
047: * Build a new annotation element
048: * @param name
049: * @param valueHolder
050: */
051: public AnnotationElement(String name, Object valueHolder) {
052: this .name = name;
053: this .valueHolder = valueHolder;
054: if (valueHolder instanceof LazyClass) {
055: isLazyClass = true;
056: } else if (valueHolder instanceof LazyClass[]) {
057: isLazyClassArray = true;
058: }
059: }
060:
061: /**
062: * Returns the actual holded element value
063: *
064: * @param loader from which to resolve LazyClass. It should be the annotated element class loader
065: * @return
066: */
067: public Object resolveValueHolderFrom(ClassLoader loader) {
068: if (isLazyClass) {
069: return ((LazyClass) valueHolder).resolveFrom(loader);
070: } else if (isLazyClassArray) {
071: Object[] annotationValueHolderArray = (Object[]) valueHolder;
072: Class[] resolved = new Class[annotationValueHolderArray.length];
073: for (int i = 0; i < annotationValueHolderArray.length; i++) {
074: resolved[i] = ((LazyClass) annotationValueHolderArray[i])
075: .resolveFrom(loader);
076: }
077: return resolved;
078: //TODO support N dimension array needed ?
079: } else {
080: return valueHolder;
081: }
082: }
083:
084: /**
085: * Returns a string representation of the annotation element value
086: *
087: * Note that such a represention won't look like source code.
088: * (f.e. element String s() will not have quotes and escapes etc).
089: * @return
090: */
091: public String toString() {
092: if (isLazyClass) {
093: StringBuffer sb = new StringBuffer("class ");
094: sb.append(((LazyClass) valueHolder).className);
095: return sb.toString();
096: } else {
097: if (valueHolder == null) {
098: return "null";
099: } 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,
127: componentClassName.length() - 2);
128: }
129: }
130:
131: public String toString() {
132: return className;
133: }
134:
135: public Class resolveFrom(ClassLoader loader) {
136: try {
137: if (dimemsion <= 0) {
138: return Class.forName(className, false, loader);
139: } else {
140: Class componentClass = Class.forName(
141: componentClassName, false, loader);
142: return (Array
143: .newInstance(componentClass, dimemsion))
144: .getClass();
145: }
146: } catch (ClassNotFoundException e) {
147: throw new WrappedRuntimeException(e);
148: }
149: }
150: }
151:
152: }
|