1 /* 2 * Copyright (c) 1997, 2013, 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 26 package com.sun.xml.internal.bind.v2.runtime; 27 28 import java.io.IOException; 29 30 import javax.xml.bind.ValidationEvent; 31 import javax.xml.bind.helpers.ValidationEventImpl; 32 import javax.xml.namespace.QName; 33 import javax.xml.stream.XMLStreamException; 34 35 import com.sun.xml.internal.bind.api.AccessorException; 36 import com.sun.xml.internal.bind.v2.model.runtime.RuntimeLeafInfo; 37 import com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader; 38 import com.sun.xml.internal.bind.v2.runtime.unmarshaller.TextLoader; 39 import com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext; 40 import com.sun.xml.internal.bind.v2.runtime.unmarshaller.XsiTypeLoader; 41 42 import org.xml.sax.SAXException; 43 44 /** 45 * {@link JaxBeanInfo} implementation for immutable leaf classes. 46 * 47 * <p> 48 * Leaf classes are always bound to a text and they are often immutable. 49 * The JAXB spec allows this binding for a few special Java classes plus 50 * type-safe enums. 51 * 52 * <p> 53 * This implementation obtains necessary information from {@link RuntimeLeafInfo}. 54 * 55 * @author Kohsuke Kawaguchi 56 */ 57 final class LeafBeanInfoImpl<BeanT> extends JaxBeanInfo<BeanT> { 58 59 private final Loader loader; 60 private final Loader loaderWithSubst; 61 62 private final Transducer<BeanT> xducer; 63 64 /** 65 * Non-null only if the leaf is also an element. 66 */ 67 private final Name tagName; 68 69 public LeafBeanInfoImpl(JAXBContextImpl grammar, RuntimeLeafInfo li) { 70 super(grammar,li,li.getClazz(),li.getTypeNames(),li.isElement(),true,false); 71 72 xducer = li.getTransducer(); 73 loader = new TextLoader(xducer); 74 loaderWithSubst = new XsiTypeLoader(this); 75 76 if(isElement()) 77 tagName = grammar.nameBuilder.createElementName(li.getElementName()); 78 else 79 tagName = null; 80 } 81 82 @Override 83 public QName getTypeName(BeanT instance) { 84 QName tn = xducer.getTypeName(instance); 85 if(tn!=null) return tn; 86 // rely on default 87 return super.getTypeName(instance); 88 } 89 90 public final String getElementNamespaceURI(BeanT t) { 91 return tagName.nsUri; 92 } 93 94 public final String getElementLocalName(BeanT t) { 95 return tagName.localName; 96 } 97 98 public BeanT createInstance(UnmarshallingContext context) { 99 throw new UnsupportedOperationException(); 100 } 101 102 public final boolean reset(BeanT bean, UnmarshallingContext context) { 103 return false; 104 } 105 106 public final String getId(BeanT bean, XMLSerializer target) { 107 return null; 108 } 109 110 public final void serializeBody(BeanT bean, XMLSerializer w) throws SAXException, IOException, XMLStreamException { 111 // most of the times leaves are printed as leaf element/attribute property, 112 // so this code is only used for example when you have multiple XmlElement on a property 113 // and some of them are leaves. Hence this doesn't need to be super-fast. 114 try { 115 xducer.writeText(w,bean,null); 116 } catch (AccessorException e) { 117 w.reportError(null,e); 118 } 119 } 120 121 public final void serializeAttributes(BeanT bean, XMLSerializer target) { 122 // noop 123 } 124 125 public final void serializeRoot(BeanT bean, XMLSerializer target) throws SAXException, IOException, XMLStreamException { 126 if(tagName==null) { 127 target.reportError( 128 new ValidationEventImpl( 129 ValidationEvent.ERROR, 130 Messages.UNABLE_TO_MARSHAL_NON_ELEMENT.format(bean.getClass().getName()), 131 null, 132 null)); 133 } 134 else { 135 target.startElement(tagName,bean); 136 target.childAsSoleContent(bean,null); 137 target.endElement(); 138 } 139 } 140 141 public final void serializeURIs(BeanT bean, XMLSerializer target) throws SAXException { 142 // TODO: maybe we should create another LeafBeanInfoImpl class for 143 // context-dependent xducers? 144 if(xducer.useNamespace()) { 145 try { 146 xducer.declareNamespace(bean,target); 147 } catch (AccessorException e) { 148 target.reportError(null,e); 149 } 150 } 151 } 152 153 public final Loader getLoader(JAXBContextImpl context, boolean typeSubstitutionCapable) { 154 if(typeSubstitutionCapable) 155 return loaderWithSubst; 156 else 157 return loader; 158 } 159 160 public Transducer<BeanT> getTransducer() { 161 return xducer; 162 } 163 }