001: /*
002: * Copyright 2006 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004: *
005: * This code is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU General Public License version 2 only, as
007: * published by the Free Software Foundation. Sun designates this
008: * particular file as subject to the "Classpath" exception as provided
009: * by Sun in the LICENSE file that accompanied this code.
010: *
011: * This code is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014: * version 2 for more details (a copy is included in the LICENSE file that
015: * accompanied this code).
016: *
017: * You should have received a copy of the GNU General Public License version
018: * 2 along with this work; if not, write to the Free Software Foundation,
019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022: * CA 95054 USA or visit www.sun.com if you need additional information or
023: * have any questions.
024: */
025:
026: package com.sun.xml.internal.bind.v2.model.impl;
027:
028: import java.util.Iterator;
029:
030: import javax.xml.bind.annotation.XmlEnum;
031: import javax.xml.bind.annotation.XmlEnumValue;
032: import javax.xml.bind.annotation.XmlRootElement;
033: import javax.xml.namespace.QName;
034:
035: import com.sun.xml.internal.bind.v2.model.annotation.Locatable;
036: import com.sun.xml.internal.bind.v2.model.core.EnumConstant;
037: import com.sun.xml.internal.bind.v2.model.core.EnumLeafInfo;
038: import com.sun.xml.internal.bind.v2.model.core.NonElement;
039: import com.sun.xml.internal.bind.v2.model.core.Element;
040: import com.sun.xml.internal.bind.v2.model.core.ClassInfo;
041: import com.sun.xml.internal.bind.v2.runtime.Location;
042:
043: /**
044: * {@link EnumLeafInfo} implementation.
045: *
046: * @author Kohsuke Kawaguchi
047: */
048: class EnumLeafInfoImpl<T, C, F, M> extends TypeInfoImpl<T, C, F, M>
049: implements EnumLeafInfo<T, C>, Element<T, C>,
050: Iterable<EnumConstantImpl<T, C, F, M>> {
051:
052: /**
053: * The enum class whose information this object represents.
054: */
055: /*package*/final C clazz;
056:
057: NonElement<T, C> baseType;
058:
059: private final T type;
060:
061: /**
062: * Can be null for anonymous types.
063: */
064: private final QName typeName;
065:
066: /**
067: * All the {@link EnumConstantImpl}s are linked in this list.
068: */
069: private EnumConstantImpl<T, C, F, M> firstConstant;
070:
071: /**
072: * If this enum is also bound to an element, that tag name.
073: * Or else null.
074: */
075: private QName elementName;
076:
077: /**
078: * @param clazz
079: * @param type
080: * clazz and type should both point to the enum class
081: * that this {@link EnumLeafInfo} represents.
082: * Because of the type parameterization we have to take them separately.
083: */
084: public EnumLeafInfoImpl(ModelBuilder<T, C, F, M> builder,
085: Locatable upstream, C clazz, T type) {
086: super (builder, upstream);
087: this .clazz = clazz;
088: this .type = type;
089:
090: elementName = parseElementName(clazz);
091:
092: // compute the type name
093: // TODO: I guess it must be allowed for enums to have @XmlElement
094: typeName = parseTypeName(clazz);
095:
096: // locate the base type.
097: // this can be done eagerly because there shouldn't be no cycle.
098: XmlEnum xe = builder.reader.getClassAnnotation(XmlEnum.class,
099: clazz, this );
100: if (xe != null) {
101: T base = builder.reader.getClassValue(xe, "value");
102: baseType = builder.getTypeInfo(base, this );
103: } else {
104: baseType = builder.getTypeInfo(builder.nav
105: .ref(String.class), this );
106: }
107: }
108:
109: /**
110: * Build {@link EnumConstant}s and discover/report any error in it.
111: */
112: protected void calcConstants() {
113: EnumConstantImpl<T, C, F, M> last = null;
114: for (F constant : nav().getEnumConstants(clazz)) {
115: String name = nav().getFieldName(constant);
116: XmlEnumValue xev = builder.reader.getFieldAnnotation(
117: XmlEnumValue.class, constant, this );
118:
119: String literal;
120: if (xev == null)
121: literal = name;
122: else
123: literal = xev.value();
124:
125: last = createEnumConstant(name, literal, constant, last);
126: }
127: this .firstConstant = last;
128: }
129:
130: protected EnumConstantImpl<T, C, F, M> createEnumConstant(
131: String name, String literal, F constant,
132: EnumConstantImpl<T, C, F, M> last) {
133: return new EnumConstantImpl<T, C, F, M>(this , name, literal,
134: last);
135: }
136:
137: public T getType() {
138: return type;
139: }
140:
141: /**
142: * Leaf-type cannot be referenced from IDREF.
143: *
144: * @deprecated
145: * why are you calling a method whose return value is always known?
146: */
147: public final boolean canBeReferencedByIDREF() {
148: return false;
149: }
150:
151: public QName getTypeName() {
152: return typeName;
153: }
154:
155: public C getClazz() {
156: return clazz;
157: }
158:
159: public NonElement<T, C> getBaseType() {
160: return baseType;
161: }
162:
163: public boolean isSimpleType() {
164: return true;
165: }
166:
167: public Location getLocation() {
168: return nav().getClassLocation(clazz);
169: }
170:
171: public Iterable<? extends EnumConstantImpl<T, C, F, M>> getConstants() {
172: if (firstConstant == null)
173: calcConstants();
174: return this ;
175: }
176:
177: public void link() {
178: // make sure we've computed constants
179: getConstants();
180: super .link();
181: }
182:
183: /**
184: * No substitution.
185: *
186: * @deprecated if you are invoking this method directly, there's something wrong.
187: */
188: public Element<T, C> getSubstitutionHead() {
189: return null;
190: }
191:
192: public QName getElementName() {
193: return elementName;
194: }
195:
196: public boolean isElement() {
197: return elementName != null;
198: }
199:
200: public Element<T, C> asElement() {
201: if (isElement())
202: return this ;
203: else
204: return null;
205: }
206:
207: /**
208: * When a bean binds to an element, it's always through {@link XmlRootElement},
209: * so this method always return null.
210: *
211: * @deprecated
212: * you shouldn't be invoking this method on {@link ClassInfoImpl}.
213: */
214: public ClassInfo<T, C> getScope() {
215: return null;
216: }
217:
218: public Iterator<EnumConstantImpl<T, C, F, M>> iterator() {
219: return new Iterator<EnumConstantImpl<T, C, F, M>>() {
220: private EnumConstantImpl<T, C, F, M> next = firstConstant;
221:
222: public boolean hasNext() {
223: return next != null;
224: }
225:
226: public EnumConstantImpl<T, C, F, M> next() {
227: EnumConstantImpl<T, C, F, M> r = next;
228: next = next.next;
229: return r;
230: }
231:
232: public void remove() {
233: throw new UnsupportedOperationException();
234: }
235: };
236: }
237: }
|