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.tools.internal.xjc.model;
027:
028: import java.awt.*;
029: import java.math.BigDecimal;
030: import java.math.BigInteger;
031: import java.util.HashMap;
032: import java.util.Map;
033:
034: import javax.activation.DataHandler;
035: import javax.activation.MimeType;
036: import javax.xml.bind.DatatypeConverter;
037: import javax.xml.bind.annotation.XmlIDREF;
038: import javax.xml.bind.annotation.adapters.CollapsedStringAdapter;
039: import javax.xml.bind.annotation.adapters.HexBinaryAdapter;
040: import javax.xml.bind.annotation.adapters.NormalizedStringAdapter;
041: import javax.xml.bind.annotation.adapters.XmlAdapter;
042: import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
043: import javax.xml.datatype.Duration;
044: import javax.xml.datatype.XMLGregorianCalendar;
045: import javax.xml.namespace.QName;
046: import javax.xml.transform.Source;
047:
048: import com.sun.codemodel.internal.JExpr;
049: import com.sun.codemodel.internal.JExpression;
050: import com.sun.codemodel.internal.JType;
051: import com.sun.tools.internal.xjc.model.nav.NClass;
052: import com.sun.tools.internal.xjc.model.nav.NType;
053: import com.sun.tools.internal.xjc.model.nav.NavigatorImpl;
054: import com.sun.tools.internal.xjc.outline.Aspect;
055: import com.sun.tools.internal.xjc.outline.Outline;
056: import com.sun.tools.internal.xjc.runtime.ZeroOneBooleanAdapter;
057: import com.sun.tools.internal.xjc.util.NamespaceContextAdapter;
058: import com.sun.xml.internal.bind.DatatypeConverterImpl;
059: import com.sun.xml.internal.bind.v2.WellKnownNamespace;
060: import com.sun.xml.internal.bind.v2.model.core.ID;
061: import com.sun.xml.internal.bind.v2.model.impl.BuiltinLeafInfoImpl;
062: import com.sun.xml.internal.xsom.XSComponent;
063: import com.sun.xml.internal.xsom.XmlString;
064:
065: import org.xml.sax.Locator;
066:
067: /**
068: * Encapsulates the default handling for leaf classes (which are bound
069: * to text in XML.) In particular this class knows how to convert
070: * the lexical value into the Java class according to this default rule.
071: *
072: * <p>
073: * This represents the spec-defined default handling for the Java
074: * type ({@link #getType()}.
075: *
076: * <p>
077: * For those Java classes (such as {@link String} or {@link Boolean})
078: * where the spec designates a specific default handling, there are
079: * constants in this class (such as {@link #STRING} or {@link #BOOLEAN}.)
080: *
081: * <p>
082: * The generated type-safe enum classes are also a leaf class,
083: * and as such there are {@link CEnumLeafInfo} that represents it
084: * as {@link CBuiltinLeafInfo}.
085: *
086: * <p>
087: * This class represents the <b>default handling</b>, and therefore
088: * we can only have one instance per one {@link NType}. Handling of
089: * other XML Schema types (such as xs:token) are represented as
090: * a general {@link TypeUse} objects.
091: *
092: *
093: * @author Kohsuke Kawaguchi
094: */
095: public abstract class CBuiltinLeafInfo extends
096: BuiltinLeafInfoImpl<NType, NClass> implements CNonElement {
097:
098: private final ID id;
099:
100: // no derived class other than the spec-defined ones. definitely not for enum.
101: private CBuiltinLeafInfo(NType typeToken, QName typeName, ID id) {
102: super (typeToken, typeName);
103: this .id = id;
104: }
105:
106: /**
107: * Gets the code model representation of this type.
108: */
109: public JType toType(Outline o, Aspect aspect) {
110: return getType().toType(o, aspect);
111: }
112:
113: /**
114: * Since {@link CBuiltinLeafInfo} represents a default binding,
115: * it is never a collection.
116: */
117: public final boolean isCollection() {
118: return false;
119: }
120:
121: public ID idUse() {
122: return id;
123: }
124:
125: /**
126: * {@link CBuiltinLeafInfo} never has a default associated MIME type.
127: */
128: public MimeType getExpectedMimeType() {
129: return null;
130: }
131:
132: /**
133: * By definition, a default handling doesn't need any adapter.
134: */
135: public final CAdapter getAdapterUse() {
136: return null;
137: }
138:
139: public final CBuiltinLeafInfo getInfo() {
140: return this ;
141: }
142:
143: public Locator getLocator() {
144: return Model.EMPTY_LOCATOR;
145: }
146:
147: public final XSComponent getSchemaComponent() {
148: throw new UnsupportedOperationException(
149: "TODO. If you hit this, let us know.");
150: }
151:
152: /**
153: * Creates a {@link TypeUse} that represents a collection of this {@link CBuiltinLeafInfo}.
154: */
155: public final TypeUse makeCollection() {
156: return TypeUseFactory.makeCollection(this );
157: }
158:
159: /**
160: * Creates a {@link TypeUse} that represents an adapted use of this {@link CBuiltinLeafInfo}.
161: */
162: public final TypeUse makeAdapted(
163: Class<? extends XmlAdapter> adapter, boolean copy) {
164: return TypeUseFactory.adapt(this , adapter, copy);
165: }
166:
167: /**
168: * Creates a {@link TypeUse} that represents a MIME-type assocaited version of this {@link CBuiltinLeafInfo}.
169: */
170: public final TypeUse makeMimeTyped(MimeType mt) {
171: return TypeUseFactory.makeMimeTyped(this , mt);
172: }
173:
174: /**
175: * {@link CBuiltinLeafInfo} for Java classes that have
176: * the spec defined built-in binding semantics.
177: */
178: private static abstract class Builtin extends CBuiltinLeafInfo {
179: protected Builtin(Class c, String typeName) {
180: this (c, typeName,
181: com.sun.xml.internal.bind.v2.model.core.ID.NONE);
182: }
183:
184: protected Builtin(Class c, String typeName, ID id) {
185: super (NavigatorImpl.theInstance.ref(c), new QName(
186: WellKnownNamespace.XML_SCHEMA, typeName), id);
187: LEAVES.put(getType(), this );
188: }
189:
190: /**
191: * No vendor customization in the built-in classes.
192: */
193: public CCustomizations getCustomizations() {
194: return CCustomizations.EMPTY;
195: }
196: }
197:
198: private static final class NoConstantBuiltin extends Builtin {
199: public NoConstantBuiltin(Class c, String typeName) {
200: super (c, typeName);
201: }
202:
203: public JExpression createConstant(Outline outline,
204: XmlString lexical) {
205: return null;
206: }
207: }
208:
209: /**
210: * All built-in leaves.
211: */
212: public static final Map<NType, CBuiltinLeafInfo> LEAVES = new HashMap<NType, CBuiltinLeafInfo>();
213:
214: public static final CBuiltinLeafInfo ANYTYPE = new NoConstantBuiltin(
215: Object.class, "anyType");
216: public static final CBuiltinLeafInfo STRING = new Builtin(
217: String.class, "string") {
218: public JExpression createConstant(Outline outline,
219: XmlString lexical) {
220: return JExpr.lit(lexical.value);
221: }
222: };
223: public static final CBuiltinLeafInfo BOOLEAN = new Builtin(
224: Boolean.class, "boolean") {
225: public JExpression createConstant(Outline outline,
226: XmlString lexical) {
227: return JExpr.lit(DatatypeConverterImpl
228: ._parseBoolean(lexical.value));
229: }
230: };
231: public static final CBuiltinLeafInfo INT = new Builtin(
232: Integer.class, "int") {
233: public JExpression createConstant(Outline outline,
234: XmlString lexical) {
235: return JExpr.lit(DatatypeConverterImpl
236: ._parseInt(lexical.value));
237: }
238: };
239: public static final CBuiltinLeafInfo LONG = new Builtin(Long.class,
240: "long") {
241: public JExpression createConstant(Outline outline,
242: XmlString lexical) {
243: return JExpr.lit(DatatypeConverterImpl
244: ._parseLong(lexical.value));
245: }
246: };
247: public static final CBuiltinLeafInfo BYTE = new Builtin(Byte.class,
248: "byte") {
249: public JExpression createConstant(Outline outline,
250: XmlString lexical) {
251: return JExpr.cast(outline.getCodeModel().BYTE, JExpr
252: .lit(DatatypeConverterImpl
253: ._parseByte(lexical.value)));
254: }
255: };
256: public static final CBuiltinLeafInfo SHORT = new Builtin(
257: Short.class, "short") {
258: public JExpression createConstant(Outline outline,
259: XmlString lexical) {
260: return JExpr.cast(outline.getCodeModel().SHORT, JExpr
261: .lit(DatatypeConverterImpl
262: ._parseShort(lexical.value)));
263: }
264: };
265: public static final CBuiltinLeafInfo FLOAT = new Builtin(
266: Float.class, "float") {
267: public JExpression createConstant(Outline outline,
268: XmlString lexical) {
269: return JExpr.lit(DatatypeConverterImpl
270: ._parseFloat(lexical.value));
271: }
272: };
273: public static final CBuiltinLeafInfo DOUBLE = new Builtin(
274: Double.class, "double") {
275: public JExpression createConstant(Outline outline,
276: XmlString lexical) {
277: return JExpr.lit(DatatypeConverterImpl
278: ._parseDouble(lexical.value));
279: }
280: };
281: public static final CBuiltinLeafInfo QNAME = new Builtin(
282: QName.class, "QName") {
283: public JExpression createConstant(Outline outline,
284: XmlString lexical) {
285: QName qn = DatatypeConverterImpl._parseQName(lexical.value,
286: new NamespaceContextAdapter(lexical));
287: return JExpr._new(outline.getCodeModel().ref(QName.class))
288: .arg(qn.getNamespaceURI()).arg(qn.getLocalPart())
289: .arg(qn.getPrefix());
290: }
291: };
292: // XMLGregorianCalendar is mutable, so we can't support default values anyhow.
293: public static final CBuiltinLeafInfo CALENDAR = new NoConstantBuiltin(
294: XMLGregorianCalendar.class, "dateTime");
295: public static final CBuiltinLeafInfo DURATION = new NoConstantBuiltin(
296: Duration.class, "duration");
297:
298: public static final CBuiltinLeafInfo BIG_INTEGER = new Builtin(
299: BigInteger.class, "integer") {
300: public JExpression createConstant(Outline outline,
301: XmlString lexical) {
302: return JExpr._new(
303: outline.getCodeModel().ref(BigInteger.class)).arg(
304: lexical.value.trim());
305: }
306: };
307:
308: public static final CBuiltinLeafInfo BIG_DECIMAL = new Builtin(
309: BigDecimal.class, "decimal") {
310: public JExpression createConstant(Outline outline,
311: XmlString lexical) {
312: return JExpr._new(
313: outline.getCodeModel().ref(BigDecimal.class)).arg(
314: lexical.value.trim());
315: }
316: };
317:
318: public static final CBuiltinLeafInfo BASE64_BYTE_ARRAY = new Builtin(
319: byte[].class, "base64Binary") {
320: public JExpression createConstant(Outline outline,
321: XmlString lexical) {
322: return outline.getCodeModel().ref(DatatypeConverter.class)
323: .staticInvoke("parseBase64Binary").arg(
324: lexical.value);
325: }
326: };
327:
328: public static final CBuiltinLeafInfo DATA_HANDLER = new NoConstantBuiltin(
329: DataHandler.class, "base64Binary");
330: public static final CBuiltinLeafInfo IMAGE = new NoConstantBuiltin(
331: Image.class, "base64Binary");
332: public static final CBuiltinLeafInfo XML_SOURCE = new NoConstantBuiltin(
333: Source.class, "base64Binary");
334:
335: public static final TypeUse HEXBIN_BYTE_ARRAY = STRING.makeAdapted(
336: HexBinaryAdapter.class, false);
337:
338: // TODO: not sure if they should belong here,
339: // but I couldn't find other places that fit.
340: public static final TypeUse TOKEN = STRING.makeAdapted(
341: CollapsedStringAdapter.class, false);
342:
343: public static final TypeUse NORMALIZED_STRING = STRING.makeAdapted(
344: NormalizedStringAdapter.class, false);
345:
346: public static final TypeUse ID = TypeUseFactory.makeID(TOKEN,
347: com.sun.xml.internal.bind.v2.model.core.ID.ID);
348:
349: /**
350: * boolean restricted to 0 or 1.
351: */
352: public static final TypeUse BOOLEAN_ZERO_OR_ONE = STRING
353: .makeAdapted(ZeroOneBooleanAdapter.class, true);
354:
355: /**
356: * IDREF.
357: *
358: * IDREF is has a whitespace normalization semantics of token, but
359: * we don't want {@link XmlJavaTypeAdapter} and {@link XmlIDREF} to interact.
360: */
361: public static final TypeUse IDREF = TypeUseFactory.makeID(ANYTYPE,
362: com.sun.xml.internal.bind.v2.model.core.ID.IDREF);
363:
364: /**
365: * For all list of strings, such as NMTOKENS, ENTITIES.
366: */
367: public static final TypeUse STRING_LIST = STRING.makeCollection();
368: }
|