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.runtime;
027:
028: import java.io.IOException;
029:
030: import javax.xml.bind.ValidationEvent;
031: import javax.xml.bind.helpers.ValidationEventImpl;
032: import javax.xml.namespace.QName;
033: import javax.xml.stream.XMLStreamException;
034:
035: import com.sun.xml.internal.bind.api.AccessorException;
036: import com.sun.xml.internal.bind.v2.model.runtime.RuntimeLeafInfo;
037: import com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader;
038: import com.sun.xml.internal.bind.v2.runtime.unmarshaller.TextLoader;
039: import com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext;
040: import com.sun.xml.internal.bind.v2.runtime.unmarshaller.XsiTypeLoader;
041:
042: import org.xml.sax.SAXException;
043:
044: /**
045: * {@link JaxBeanInfo} implementation for immutable leaf classes.
046: *
047: * <p>
048: * Leaf classes are always bound to a text and they are often immutable.
049: * The JAXB spec allows this binding for a few special Java classes plus
050: * type-safe enums.
051: *
052: * <p>
053: * This implementation obtains necessary information from {@link RuntimeLeafInfo}.
054: *
055: * @author Kohsuke Kawaguchi
056: */
057: final class LeafBeanInfoImpl<BeanT> extends JaxBeanInfo<BeanT> {
058:
059: private final Loader loader;
060: private final Loader loaderWithSubst;
061:
062: private final Transducer<BeanT> xducer;
063:
064: /**
065: * Non-null only if the leaf is also an element.
066: */
067: private final Name tagName;
068:
069: public LeafBeanInfoImpl(JAXBContextImpl grammar, RuntimeLeafInfo li) {
070: super (grammar, li, li.getClazz(), li.getTypeNames(), li
071: .isElement(), true, false);
072:
073: xducer = li.getTransducer();
074: loader = new TextLoader(xducer);
075: loaderWithSubst = new XsiTypeLoader(this );
076:
077: if (isElement())
078: tagName = grammar.nameBuilder.createElementName(li
079: .getElementName());
080: else
081: tagName = null;
082: }
083:
084: public QName getTypeName(BeanT instance) {
085: QName tn = xducer.getTypeName(instance);
086: if (tn != null)
087: return tn;
088: // rely on default
089: return super .getTypeName(instance);
090: }
091:
092: public final String getElementNamespaceURI(BeanT _) {
093: return tagName.nsUri;
094: }
095:
096: public final String getElementLocalName(BeanT _) {
097: return tagName.localName;
098: }
099:
100: public BeanT createInstance(UnmarshallingContext context) {
101: throw new UnsupportedOperationException();
102: }
103:
104: public final boolean reset(BeanT bean, UnmarshallingContext context) {
105: return false;
106: }
107:
108: public final String getId(BeanT bean, XMLSerializer target) {
109: return null;
110: }
111:
112: public final void serializeBody(BeanT bean, XMLSerializer w)
113: throws SAXException, IOException, XMLStreamException {
114: // most of the times leaves are printed as leaf element/attribute property,
115: // so this code is only used for example when you have multiple XmlElement on a property
116: // and some of them are leaves. Hence this doesn't need to be super-fast.
117: try {
118: xducer.writeText(w, bean, null);
119: } catch (AccessorException e) {
120: w.reportError(null, e);
121: }
122: }
123:
124: public final void serializeAttributes(BeanT bean,
125: XMLSerializer target) {
126: // noop
127: }
128:
129: public final void serializeRoot(BeanT bean, XMLSerializer target)
130: throws SAXException, IOException, XMLStreamException {
131: if (tagName == null) {
132: target.reportError(new ValidationEventImpl(
133: ValidationEvent.ERROR,
134: Messages.UNABLE_TO_MARSHAL_NON_ELEMENT.format(bean
135: .getClass().getName()), null, null));
136: } else {
137: target.startElement(tagName, bean);
138: target.childAsSoleContent(bean, null);
139: target.endElement();
140: }
141: }
142:
143: public final void serializeURIs(BeanT bean, XMLSerializer target)
144: throws SAXException {
145: // TODO: maybe we should create another LeafBeanInfoImpl class for
146: // context-dependent xducers?
147: if (xducer.useNamespace()) {
148: try {
149: xducer.declareNamespace(bean, target);
150: } catch (AccessorException e) {
151: target.reportError(null, e);
152: }
153: }
154: }
155:
156: public final Loader getLoader(JAXBContextImpl context,
157: boolean typeSubstitutionCapable) {
158: if (typeSubstitutionCapable)
159: return loaderWithSubst;
160: else
161: return loader;
162: }
163:
164: public Transducer<BeanT> getTransducer() {
165: return xducer;
166: }
167: }
|