001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common Development
008: * and Distribution License("CDDL") (collectively, the "License"). You
009: * may not use this file except in compliance with the License. You can obtain
010: * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
011: * or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
012: * language governing permissions and limitations under the License.
013: *
014: * When distributing the software, include this License Header Notice in each
015: * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
016: * Sun designates this particular file as subject to the "Classpath" exception
017: * as provided by Sun in the GPL Version 2 section of the License file that
018: * accompanied this code. If applicable, add the following below the License
019: * Header, with the fields enclosed by brackets [] replaced by your own
020: * identifying information: "Portions Copyrighted [year]
021: * [name of copyright owner]"
022: *
023: * Contributor(s):
024: *
025: * If you wish your version of this file to be governed by only the CDDL or
026: * only the GPL Version 2, indicate your decision by adding "[Contributor]
027: * elects to include this software in this distribution under the [CDDL or GPL
028: * Version 2] license." If you don't indicate a single choice of license, a
029: * recipient has the option to distribute your version of this file under
030: * either the CDDL, the GPL Version 2 or to extend the choice of license to
031: * its licensees as provided above. However, if you add GPL Version 2 code
032: * and therefore, elected the GPL Version 2 license, then the option applies
033: * only if the new code is made subject to such option by the copyright
034: * holder.
035: */
036:
037: package com.sun.tools.xjc.model;
038:
039: import java.awt.*;
040: import java.math.BigDecimal;
041: import java.math.BigInteger;
042: import java.util.HashMap;
043: import java.util.Map;
044:
045: import javax.activation.DataHandler;
046: import javax.activation.MimeType;
047: import javax.xml.bind.DatatypeConverter;
048: import javax.xml.bind.annotation.XmlIDREF;
049: import javax.xml.bind.annotation.adapters.CollapsedStringAdapter;
050: import javax.xml.bind.annotation.adapters.HexBinaryAdapter;
051: import javax.xml.bind.annotation.adapters.NormalizedStringAdapter;
052: import javax.xml.bind.annotation.adapters.XmlAdapter;
053: import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
054: import javax.xml.datatype.Duration;
055: import javax.xml.datatype.XMLGregorianCalendar;
056: import javax.xml.namespace.QName;
057: import javax.xml.transform.Source;
058:
059: import com.sun.codemodel.JExpr;
060: import com.sun.codemodel.JExpression;
061: import com.sun.codemodel.JType;
062: import com.sun.tools.xjc.model.nav.NClass;
063: import com.sun.tools.xjc.model.nav.NType;
064: import com.sun.tools.xjc.model.nav.NavigatorImpl;
065: import com.sun.tools.xjc.outline.Aspect;
066: import com.sun.tools.xjc.outline.Outline;
067: import com.sun.tools.xjc.runtime.ZeroOneBooleanAdapter;
068: import com.sun.tools.xjc.util.NamespaceContextAdapter;
069: import com.sun.xml.bind.DatatypeConverterImpl;
070: import com.sun.xml.bind.v2.WellKnownNamespace;
071: import com.sun.xml.bind.v2.model.core.ID;
072: import com.sun.xml.bind.v2.model.impl.BuiltinLeafInfoImpl;
073: import com.sun.xml.xsom.XSComponent;
074: import com.sun.xml.xsom.XmlString;
075:
076: import org.xml.sax.Locator;
077:
078: /**
079: * Encapsulates the default handling for leaf classes (which are bound
080: * to text in XML.) In particular this class knows how to convert
081: * the lexical value into the Java class according to this default rule.
082: *
083: * <p>
084: * This represents the spec-defined default handling for the Java
085: * type ({@link #getType()}.
086: *
087: * <p>
088: * For those Java classes (such as {@link String} or {@link Boolean})
089: * where the spec designates a specific default handling, there are
090: * constants in this class (such as {@link #STRING} or {@link #BOOLEAN}.)
091: *
092: * <p>
093: * The generated type-safe enum classes are also a leaf class,
094: * and as such there are {@link CEnumLeafInfo} that represents it
095: * as {@link CBuiltinLeafInfo}.
096: *
097: * <p>
098: * This class represents the <b>default handling</b>, and therefore
099: * we can only have one instance per one {@link NType}. Handling of
100: * other XML Schema types (such as xs:token) are represented as
101: * a general {@link TypeUse} objects.
102: *
103: *
104: * @author Kohsuke Kawaguchi
105: */
106: public abstract class CBuiltinLeafInfo extends
107: BuiltinLeafInfoImpl<NType, NClass> implements CNonElement {
108:
109: private final ID id;
110:
111: // no derived class other than the spec-defined ones. definitely not for enum.
112: private CBuiltinLeafInfo(NType typeToken, QName typeName, ID id) {
113: super (typeToken, typeName);
114: this .id = id;
115: }
116:
117: /**
118: * Gets the code model representation of this type.
119: */
120: public JType toType(Outline o, Aspect aspect) {
121: return getType().toType(o, aspect);
122: }
123:
124: /**
125: * Since {@link CBuiltinLeafInfo} represents a default binding,
126: * it is never a collection.
127: */
128: @Deprecated
129: public final boolean isCollection() {
130: return false;
131: }
132:
133: /**
134: * Guaranteed to return this.
135: */
136: @Deprecated
137: public CNonElement getInfo() {
138: return this ;
139: }
140:
141: public ID idUse() {
142: return id;
143: }
144:
145: /**
146: * {@link CBuiltinLeafInfo} never has a default associated MIME type.
147: */
148: public MimeType getExpectedMimeType() {
149: return null;
150: }
151:
152: @Deprecated
153: public final CAdapter getAdapterUse() {
154: return null;
155: }
156:
157: public Locator getLocator() {
158: return Model.EMPTY_LOCATOR;
159: }
160:
161: public final XSComponent getSchemaComponent() {
162: throw new UnsupportedOperationException(
163: "TODO. If you hit this, let us know.");
164: }
165:
166: /**
167: * Creates a {@link TypeUse} that represents a collection of this {@link CBuiltinLeafInfo}.
168: */
169: public final TypeUse makeCollection() {
170: return TypeUseFactory.makeCollection(this );
171: }
172:
173: /**
174: * Creates a {@link TypeUse} that represents an adapted use of this {@link CBuiltinLeafInfo}.
175: */
176: public final TypeUse makeAdapted(
177: Class<? extends XmlAdapter> adapter, boolean copy) {
178: return TypeUseFactory.adapt(this , adapter, copy);
179: }
180:
181: /**
182: * Creates a {@link TypeUse} that represents a MIME-type assocaited version of this {@link CBuiltinLeafInfo}.
183: */
184: public final TypeUse makeMimeTyped(MimeType mt) {
185: return TypeUseFactory.makeMimeTyped(this , mt);
186: }
187:
188: /**
189: * {@link CBuiltinLeafInfo} for Java classes that have
190: * the spec defined built-in binding semantics.
191: */
192: private static abstract class Builtin extends CBuiltinLeafInfo {
193: protected Builtin(Class c, String typeName) {
194: this (c, typeName, com.sun.xml.bind.v2.model.core.ID.NONE);
195: }
196:
197: protected Builtin(Class c, String typeName, ID id) {
198: super (NavigatorImpl.theInstance.ref(c), new QName(
199: WellKnownNamespace.XML_SCHEMA, typeName), id);
200: LEAVES.put(getType(), this );
201: }
202:
203: /**
204: * No vendor customization in the built-in classes.
205: */
206: public CCustomizations getCustomizations() {
207: return CCustomizations.EMPTY;
208: }
209: }
210:
211: private static final class NoConstantBuiltin extends Builtin {
212: public NoConstantBuiltin(Class c, String typeName) {
213: super (c, typeName);
214: }
215:
216: public JExpression createConstant(Outline outline,
217: XmlString lexical) {
218: return null;
219: }
220: }
221:
222: /**
223: * All built-in leaves.
224: */
225: public static final Map<NType, CBuiltinLeafInfo> LEAVES = new HashMap<NType, CBuiltinLeafInfo>();
226:
227: public static final CBuiltinLeafInfo ANYTYPE = new NoConstantBuiltin(
228: Object.class, "anyType");
229: public static final CBuiltinLeafInfo STRING = new Builtin(
230: String.class, "string") {
231: public JExpression createConstant(Outline outline,
232: XmlString lexical) {
233: return JExpr.lit(lexical.value);
234: }
235: };
236: public static final CBuiltinLeafInfo BOOLEAN = new Builtin(
237: Boolean.class, "boolean") {
238: public JExpression createConstant(Outline outline,
239: XmlString lexical) {
240: return JExpr.lit(DatatypeConverterImpl
241: ._parseBoolean(lexical.value));
242: }
243: };
244: public static final CBuiltinLeafInfo INT = new Builtin(
245: Integer.class, "int") {
246: public JExpression createConstant(Outline outline,
247: XmlString lexical) {
248: return JExpr.lit(DatatypeConverterImpl
249: ._parseInt(lexical.value));
250: }
251: };
252: public static final CBuiltinLeafInfo LONG = new Builtin(Long.class,
253: "long") {
254: public JExpression createConstant(Outline outline,
255: XmlString lexical) {
256: return JExpr.lit(DatatypeConverterImpl
257: ._parseLong(lexical.value));
258: }
259: };
260: public static final CBuiltinLeafInfo BYTE = new Builtin(Byte.class,
261: "byte") {
262: public JExpression createConstant(Outline outline,
263: XmlString lexical) {
264: return JExpr.cast(outline.getCodeModel().BYTE, JExpr
265: .lit(DatatypeConverterImpl
266: ._parseByte(lexical.value)));
267: }
268: };
269: public static final CBuiltinLeafInfo SHORT = new Builtin(
270: Short.class, "short") {
271: public JExpression createConstant(Outline outline,
272: XmlString lexical) {
273: return JExpr.cast(outline.getCodeModel().SHORT, JExpr
274: .lit(DatatypeConverterImpl
275: ._parseShort(lexical.value)));
276: }
277: };
278: public static final CBuiltinLeafInfo FLOAT = new Builtin(
279: Float.class, "float") {
280: public JExpression createConstant(Outline outline,
281: XmlString lexical) {
282: return JExpr.lit(DatatypeConverterImpl
283: ._parseFloat(lexical.value));
284: }
285: };
286: public static final CBuiltinLeafInfo DOUBLE = new Builtin(
287: Double.class, "double") {
288: public JExpression createConstant(Outline outline,
289: XmlString lexical) {
290: return JExpr.lit(DatatypeConverterImpl
291: ._parseDouble(lexical.value));
292: }
293: };
294: public static final CBuiltinLeafInfo QNAME = new Builtin(
295: QName.class, "QName") {
296: public JExpression createConstant(Outline outline,
297: XmlString lexical) {
298: QName qn = DatatypeConverterImpl._parseQName(lexical.value,
299: new NamespaceContextAdapter(lexical));
300: return JExpr._new(outline.getCodeModel().ref(QName.class))
301: .arg(qn.getNamespaceURI()).arg(qn.getLocalPart())
302: .arg(qn.getPrefix());
303: }
304: };
305: // XMLGregorianCalendar is mutable, so we can't support default values anyhow.
306: // For CALENAR we are uses a most unlikely name so as to avoid potential name
307: // conflicts in the furture.
308: public static final CBuiltinLeafInfo CALENDAR = new NoConstantBuiltin(
309: XMLGregorianCalendar.class, "\u0000");
310: public static final CBuiltinLeafInfo DURATION = new NoConstantBuiltin(
311: Duration.class, "duration");
312:
313: public static final CBuiltinLeafInfo BIG_INTEGER = new Builtin(
314: BigInteger.class, "integer") {
315: public JExpression createConstant(Outline outline,
316: XmlString lexical) {
317: return JExpr._new(
318: outline.getCodeModel().ref(BigInteger.class)).arg(
319: lexical.value.trim());
320: }
321: };
322:
323: public static final CBuiltinLeafInfo BIG_DECIMAL = new Builtin(
324: BigDecimal.class, "decimal") {
325: public JExpression createConstant(Outline outline,
326: XmlString lexical) {
327: return JExpr._new(
328: outline.getCodeModel().ref(BigDecimal.class)).arg(
329: lexical.value.trim());
330: }
331: };
332:
333: public static final CBuiltinLeafInfo BASE64_BYTE_ARRAY = new Builtin(
334: byte[].class, "base64Binary") {
335: public JExpression createConstant(Outline outline,
336: XmlString lexical) {
337: return outline.getCodeModel().ref(DatatypeConverter.class)
338: .staticInvoke("parseBase64Binary").arg(
339: lexical.value);
340: }
341: };
342:
343: public static final CBuiltinLeafInfo DATA_HANDLER = new NoConstantBuiltin(
344: DataHandler.class, "base64Binary");
345: public static final CBuiltinLeafInfo IMAGE = new NoConstantBuiltin(
346: Image.class, "base64Binary");
347: public static final CBuiltinLeafInfo XML_SOURCE = new NoConstantBuiltin(
348: Source.class, "base64Binary");
349:
350: public static final TypeUse HEXBIN_BYTE_ARRAY = STRING.makeAdapted(
351: HexBinaryAdapter.class, false);
352:
353: // TODO: not sure if they should belong here,
354: // but I couldn't find other places that fit.
355: public static final TypeUse TOKEN = STRING.makeAdapted(
356: CollapsedStringAdapter.class, false);
357:
358: public static final TypeUse NORMALIZED_STRING = STRING.makeAdapted(
359: NormalizedStringAdapter.class, false);
360:
361: public static final TypeUse ID = TypeUseFactory.makeID(TOKEN,
362: com.sun.xml.bind.v2.model.core.ID.ID);
363:
364: /**
365: * boolean restricted to 0 or 1.
366: */
367: public static final TypeUse BOOLEAN_ZERO_OR_ONE = STRING
368: .makeAdapted(ZeroOneBooleanAdapter.class, true);
369:
370: /**
371: * IDREF.
372: *
373: * IDREF is has a whitespace normalization semantics of token, but
374: * we don't want {@link XmlJavaTypeAdapter} and {@link XmlIDREF} to interact.
375: */
376: public static final TypeUse IDREF = TypeUseFactory.makeID(ANYTYPE,
377: com.sun.xml.bind.v2.model.core.ID.IDREF);
378:
379: /**
380: * For all list of strings, such as NMTOKENS, ENTITIES.
381: */
382: public static final TypeUse STRING_LIST = STRING.makeCollection();
383: }
|