1/*
2 * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package com.sun.tools.internal.xjc.model;
27
28import java.util.Collection;
29
30import javax.activation.MimeType;
31import javax.xml.namespace.QName;
32
33import com.sun.codemodel.internal.JClass;
34import com.sun.codemodel.internal.JExpression;
35import com.sun.tools.internal.xjc.model.nav.NClass;
36import com.sun.tools.internal.xjc.model.nav.NType;
37import com.sun.tools.internal.xjc.outline.Aspect;
38import com.sun.tools.internal.xjc.outline.Outline;
39import com.sun.xml.internal.bind.v2.model.annotation.Locatable;
40import com.sun.xml.internal.bind.v2.model.core.EnumLeafInfo;
41import com.sun.xml.internal.bind.v2.model.core.ID;
42import com.sun.xml.internal.bind.v2.model.core.NonElement;
43import com.sun.xml.internal.bind.v2.model.core.Element;
44import com.sun.xml.internal.bind.v2.runtime.Location;
45import com.sun.xml.internal.xsom.XSComponent;
46import com.sun.xml.internal.xsom.XmlString;
47
48import org.xml.sax.Locator;
49
50/**
51 * Transducer that converts a string into an "enumeration class."
52 *
53 * The structure of the generated class needs to precisely
54 * follow the JAXB spec.
55 *
56 * @author Kohsuke KAWAGUCHI
57 */
58public final class CEnumLeafInfo implements EnumLeafInfo<NType,NClass>, NClass, CNonElement
59{
60    /**
61     * The {@link Model} object to which this bean belongs.
62     */
63    public final Model model;
64
65    /**
66     * The parent into which the enum class should be generated.
67     */
68    public final CClassInfoParent parent;
69
70    /**
71     * Short name of the generated type-safe enum.
72     */
73    public final String shortName;
74
75    private final QName typeName;
76
77    private final XSComponent source;
78
79    /**
80     * Represents the underlying type of this enumeration
81     * and its conversion.
82     *
83     * <p>
84     * To parse XML into a constant, we use the base type
85     * to do {@code lexical -> value}, then use a map to pick up the right one.
86     *
87     * <p>
88     * Hence this also represents the type of the Java value.
89     * For example, if this is an enumeration of xs:int,
90     * then this field will be Java int.
91     */
92    public final CNonElement base;
93
94
95    /**
96     * List of enum members.
97     */
98    public final Collection<CEnumConstant> members;
99
100    private final CCustomizations customizations;
101
102    /**
103     * @see #getLocator()
104     */
105    private final Locator sourceLocator;
106
107    public String javadoc;
108
109    public CEnumLeafInfo(Model model,
110                         QName typeName,
111                         CClassInfoParent container,
112                         String shortName,
113                         CNonElement base,
114                         Collection<CEnumConstant> _members,
115                         XSComponent source,
116                         CCustomizations customizations,
117                         Locator _sourceLocator) {
118        this.model = model;
119        this.parent = container;
120        this.shortName = model.allocator.assignClassName(parent,shortName);
121        this.base = base;
122        this.members = _members;
123        this.source = source;
124        if(customizations==null)
125            customizations = CCustomizations.EMPTY;
126        this.customizations = customizations;
127        this.sourceLocator = _sourceLocator;
128        this.typeName = typeName;
129
130        for( CEnumConstant mem : members )
131            mem.setParent(this);
132
133        model.add(this);
134
135        // TODO: can we take advantage of the fact that enum can be XmlRootElement?
136    }
137
138    /**
139     * Source line information that points to the place
140     * where this type-safe enum is defined.
141     * Used to report error messages.
142     */
143    public Locator getLocator() {
144        return sourceLocator;
145    }
146
147    public QName getTypeName() {
148        return typeName;
149    }
150
151    public NType getType() {
152        return this;
153    }
154
155    /**
156     * @deprecated
157     *      why are you calling the method whose return value is known?
158     */
159    public boolean canBeReferencedByIDREF() {
160        return false;
161    }
162
163    public boolean isElement() {
164        return false;
165    }
166
167    public QName getElementName() {
168        return null;
169    }
170
171    public Element<NType,NClass> asElement() {
172        return null;
173    }
174
175    public NClass getClazz() {
176        return this;
177    }
178
179    public XSComponent getSchemaComponent() {
180        return source;
181    }
182
183    public JClass toType(Outline o, Aspect aspect) {
184        return o.getEnum(this).clazz;
185    }
186
187    public boolean isAbstract() {
188        return false;
189    }
190
191    public boolean isBoxedType() {
192        return false;
193    }
194
195    public String fullName() {
196        return parent.fullName()+'.'+shortName;
197    }
198
199    public boolean isPrimitive() {
200        return false;
201    }
202
203    public boolean isSimpleType() {
204        return true;
205    }
206
207
208    /**
209     * The spec says the value field in the enum class will be generated
210     * only under certain circumstances.
211     *
212     * @return
213     *      true if the generated enum class should have the value field.
214     */
215    public boolean needsValueField() {
216        for (CEnumConstant cec : members) {
217            if(!cec.getName().equals(cec.getLexicalValue()))
218                return true;
219        }
220        return false;
221    }
222
223    public JExpression createConstant(Outline outline, XmlString literal) {
224        // correctly identifying which constant it maps to is hard, so
225        // here I'm cheating
226        JClass type = toType(outline,Aspect.EXPOSED);
227        for (CEnumConstant mem : members) {
228            if(mem.getLexicalValue().equals(literal.value))
229                return type.staticRef(mem.getName());
230        }
231        return null;
232    }
233
234    @Deprecated
235    public boolean isCollection() {
236        return false;
237    }
238
239    @Deprecated
240    public CAdapter getAdapterUse() {
241        return null;
242    }
243
244    @Deprecated
245    public CNonElement getInfo() {
246        return this;
247    }
248
249    public ID idUse() {
250        return ID.NONE;
251    }
252
253    public MimeType getExpectedMimeType() {
254        return null;
255    }
256
257    public Collection<CEnumConstant> getConstants() {
258        return members;
259    }
260
261    public NonElement<NType,NClass> getBaseType() {
262        return base;
263    }
264
265    public CCustomizations getCustomizations() {
266        return customizations;
267    }
268
269    public Locatable getUpstream() {
270        throw new UnsupportedOperationException();
271    }
272
273    public Location getLocation() {
274        throw new UnsupportedOperationException();
275    }
276}
277