001: /*******************************************************************************************
002: * Copyright (c) Jonas Bonér, Alexandre Vasseur. All rights reserved. *
003: * http://backport175.codehaus.org *
004: * --------------------------------------------------------------------------------------- *
005: * The software in this package is published under the terms of Apache License Version 2.0 *
006: * a copy of which has been included with this distribution in the license.txt file. *
007: *******************************************************************************************/package com.tc.backport175.bytecode;
008:
009: import java.util.List;
010: import java.util.ArrayList;
011: import java.util.Iterator;
012: import java.io.Serializable;
013:
014: /**
015: * Abstractions for the different reader elements.
016: *
017: * @author <a href="mailto:jboner@codehaus.org">Jonas Bonér</a>
018: */
019: public class AnnotationElement implements Serializable {
020:
021: public static final String DEFAULT_VALUE_NAME = "value";
022:
023: /**
024: * Enum for the different annotation element types.
025: *
026: * @author <a href="mailto:jboner@codehaus.org">Jonas Bonér</a>
027: */
028: public static final class Type {
029: public static final Type ANNOTATION = new Type("ANNOTATION");
030: public static final Type ARRAY = new Type("ARRAY");
031: public static final Type ENUM = new Type("ENUM");
032: public static final Type TYPE = new Type("TYPE");
033: public static final Type STRING = new Type("STRING");
034: public static final Type LONG = new Type("LONG");
035: public static final Type INTEGER = new Type("INTEGER");
036: public static final Type SHORT = new Type("SHORT");
037: public static final Type DOUBLE = new Type("DOUBLE");
038: public static final Type FLOAT = new Type("FLOAT");
039: public static final Type BYTE = new Type("BYTE");
040: public static final Type BOOLEAN = new Type("BOOLEAN");
041: public static final Type CHAR = new Type("CHAR");
042:
043: private final String m_name;
044:
045: private Type(final String name) {
046: m_name = name;
047: }
048:
049: public String toString() {
050: return m_name;
051: }
052: }
053:
054: /**
055: * Abstraction for the annotation element type.
056: *
057: * @author <a href="mailto:jboner@codehaus.org">Jonas Bonér</a>
058: */
059: public static class Annotation extends AnnotationElement implements
060: NestedAnnotationElement {
061: static final long serialVersionUID = 8769673036736880936L;
062:
063: private final String m_className;
064: private final List m_elements = new ArrayList();
065:
066: public Annotation(final String className) {
067: m_className = className;
068: }
069:
070: public void addElement(final String name, final Object element) {
071: m_elements.add(new AnnotationElement.NamedValue(name,
072: element));
073: }
074:
075: /**
076: * @return the annotation class name, java formatted (dot)
077: */
078: public String getInterfaceName() {
079: return m_className;
080: }
081:
082: public List getElements() {
083: return m_elements;
084: }
085:
086: public String toString() {
087: StringBuffer buf = new StringBuffer();
088: for (Iterator it = m_elements.iterator(); it.hasNext();) {
089: NamedValue namedValue = (NamedValue) it.next();
090: buf.append(namedValue.toString());
091: if (it.hasNext()) {
092: buf.append(", ");
093: }
094: }
095: return buf.toString();
096: }
097:
098: /**
099: * Add the given element if not already present ie default value
100: *
101: * @param defaultedElement
102: */
103: public void mergeDefaultedElement(NamedValue defaultedElement) {
104: for (Iterator iterator = m_elements.iterator(); iterator
105: .hasNext();) {
106: NamedValue namedValue = (NamedValue) iterator.next();
107: if (namedValue.getName().equals(
108: defaultedElement.getName())) {
109: return;// value is present
110: }
111: }
112: m_elements.add(defaultedElement);
113: }
114: }
115:
116: /**
117: * Abstraction for the array element type.
118: *
119: * @author <a href="mailto:jboner@codehaus.org">Jonas Bonér</a>
120: */
121: public static class Array extends AnnotationElement implements
122: NestedAnnotationElement {
123: static final long serialVersionUID = -6792525450471409048L;
124:
125: private final List m_elements = new ArrayList();
126:
127: public void addElement(final String name, final Object element) {
128: m_elements.add(new AnnotationElement.NamedValue(
129: DEFAULT_VALUE_NAME, element));
130: }
131:
132: public List getElements() {
133: return m_elements;
134: }
135:
136: public String toString() {
137: StringBuffer buf = new StringBuffer("[");
138: for (Iterator it = m_elements.iterator(); it.hasNext();) {
139: NamedValue namedValue = (NamedValue) it.next();
140: buf.append(namedValue.toString());
141: if (it.hasNext()) {
142: buf.append(", ");
143: }
144: }
145: buf.append(']');
146: return buf.toString();
147: }
148: }
149:
150: /**
151: * Abstraction for the named value type.
152: *
153: * @author <a href="mailto:jboner@codehaus.org">Jonas Bonér</a>
154: */
155: public static class NamedValue extends AnnotationElement {
156: static final long serialVersionUID = 4284696449802391088L;
157:
158: private final String m_name;
159: private final Object m_value;
160: private final Type m_type;
161: private boolean m_isResolved = false;
162: private Object m_resolvedValue;
163:
164: public NamedValue(final String name, final Object value) {
165: if (name == null) {
166: m_name = DEFAULT_VALUE_NAME;
167: } else {
168: m_name = name;
169: }
170: m_value = value;
171: if (value instanceof Enum) {
172: m_type = Type.ENUM;
173: } else if (value instanceof Byte) {
174: m_type = Type.BYTE;
175: } else if (value instanceof Boolean) {
176: m_type = Type.BOOLEAN;
177: } else if (value instanceof Character) {
178: m_type = Type.CHAR;
179: } else if (value instanceof Short) {
180: m_type = Type.SHORT;
181: } else if (value instanceof Integer) {
182: m_type = Type.INTEGER;
183: } else if (value instanceof Long) {
184: m_type = Type.LONG;
185: } else if (value instanceof Float) {
186: m_type = Type.FLOAT;
187: } else if (value instanceof Double) {
188: m_type = Type.DOUBLE;
189: } else if (value instanceof String) {
190: m_type = Type.STRING;
191: } else if (value instanceof com.tc.asm.Type) {
192: m_type = Type.TYPE;
193: } else if (value instanceof Array) {
194: m_type = Type.ARRAY;
195: } else if (value instanceof Annotation) {
196: m_type = Type.ANNOTATION;
197: } else {
198: throw new IllegalArgumentException(
199: "not valid type for named value in annotation ["
200: + value.toString() + "]");
201: }
202: }
203:
204: public String getName() {
205: return m_name;
206: }
207:
208: public Object getValue() {
209: return m_value;
210: }
211:
212: public Type getType() {
213: return m_type;
214: }
215:
216: public void setResolvedValue(final Object value) {
217: m_isResolved = true;
218: m_resolvedValue = value;
219: }
220:
221: public boolean isResolved() {
222: return m_isResolved;
223: }
224:
225: public Object getResolvedValue() {
226: return m_resolvedValue;
227: }
228:
229: public String toString() {
230: StringBuffer buf = new StringBuffer();
231: if (!m_name.equals(DEFAULT_VALUE_NAME)) {
232: buf.append(m_name);
233: buf.append('=');
234: }
235: if (m_type.equals(Type.TYPE)) {
236: buf.append(((com.tc.asm.Type) m_value).getClassName())
237: .append(".class");
238: } else {
239: buf.append(m_value);
240: }
241: return buf.toString();
242: }
243: }
244:
245: /**
246: * Abstraction for the enum (Java 5 enum) element type.
247: *
248: * @author <a href="mailto:jboner@codehaus.org">Jonas Bonér</a>
249: */
250: public static class Enum extends AnnotationElement {
251: static final long serialVersionUID = 1136400223420236391L;
252:
253: private final String m_desc;
254: private final String m_value;
255:
256: public Enum(final String desc, final String value) {
257: m_desc = desc;
258: m_value = value;
259: }
260:
261: public String getDesc() {
262: return m_desc;
263: }
264:
265: public String getValue() {
266: return m_value;
267: }
268:
269: public String toString() {
270: StringBuffer buf = new StringBuffer();
271: buf.append(m_desc.substring(1, m_desc.length() - 1)
272: .replace('/', '.'));
273: buf.append('.');
274: buf.append(m_value);
275: return buf.toString();
276: }
277: }
278:
279: /**
280: * Interface for the nested annotation element type. Composite pattern.
281: *
282: * @author <a href="mailto:jboner@codehaus.org">Jonas Bonér</a>
283: */
284: public static interface NestedAnnotationElement {
285: void addElement(String name, Object element);
286:
287: List getElements();
288: }
289: }
|