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.property;
027:
028: import java.io.IOException;
029:
030: import javax.xml.bind.JAXBException;
031: import javax.xml.bind.annotation.DomHandler;
032: import javax.xml.stream.XMLStreamException;
033:
034: import com.sun.xml.internal.bind.v2.ClassFactory;
035: import com.sun.xml.internal.bind.v2.model.core.PropertyKind;
036: import com.sun.xml.internal.bind.v2.model.core.WildcardMode;
037: import com.sun.xml.internal.bind.v2.model.runtime.RuntimeElement;
038: import com.sun.xml.internal.bind.v2.model.runtime.RuntimeReferencePropertyInfo;
039: import com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl;
040: import com.sun.xml.internal.bind.v2.runtime.JaxBeanInfo;
041: import com.sun.xml.internal.bind.v2.runtime.XMLSerializer;
042: import com.sun.xml.internal.bind.v2.runtime.reflect.Accessor;
043: import com.sun.xml.internal.bind.v2.runtime.reflect.ListIterator;
044: import com.sun.xml.internal.bind.v2.runtime.unmarshaller.ChildLoader;
045: import com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader;
046: import com.sun.xml.internal.bind.v2.runtime.unmarshaller.Receiver;
047: import com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext;
048: import com.sun.xml.internal.bind.v2.runtime.unmarshaller.WildcardLoader;
049: import com.sun.xml.internal.bind.v2.util.QNameMap;
050:
051: import org.xml.sax.SAXException;
052:
053: /**
054: * @author Kohsuke Kawaguchi
055: */
056: class ArrayReferenceNodeProperty<BeanT, ListT, ItemT> extends
057: ArrayERProperty<BeanT, ListT, ItemT> {
058:
059: /**
060: * Expected element names and what class to unmarshal.
061: */
062: private final QNameMap<JaxBeanInfo> expectedElements = new QNameMap<JaxBeanInfo>();
063:
064: private final boolean isMixed;
065:
066: private final DomHandler domHandler;
067: private final WildcardMode wcMode;
068:
069: public ArrayReferenceNodeProperty(JAXBContextImpl p,
070: RuntimeReferencePropertyInfo prop) {
071: super (p, prop, prop.getXmlName(), prop.isCollectionNillable());
072:
073: for (RuntimeElement e : prop.getElements()) {
074: JaxBeanInfo bi = p.getOrCreate(e);
075: expectedElements.put(e.getElementName().getNamespaceURI(),
076: e.getElementName().getLocalPart(), bi);
077: }
078:
079: isMixed = prop.isMixed();
080:
081: if (prop.getWildcard() != null) {
082: domHandler = (DomHandler) ClassFactory.create(prop
083: .getDOMHandler());
084: wcMode = prop.getWildcard();
085: } else {
086: domHandler = null;
087: wcMode = null;
088: }
089: }
090:
091: protected final void serializeListBody(BeanT o, XMLSerializer w,
092: ListT list) throws IOException, XMLStreamException,
093: SAXException {
094: ListIterator<ItemT> itr = lister.iterator(list, w);
095:
096: while (itr.hasNext()) {
097: try {
098: ItemT item = itr.next();
099: if (item != null) {
100: if (isMixed && item.getClass() == String.class) {
101: w.text((String) item, null);
102: } else {
103: JaxBeanInfo bi = w.grammar.getBeanInfo(item,
104: true);
105: if (bi.jaxbType == Object.class
106: && domHandler != null)
107: // even if 'v' is a DOM node, it always derive from Object,
108: // so the getBeanInfo returns BeanInfo for Object
109: w.writeDom(item, domHandler, o, fieldName);
110: else
111: bi.serializeRoot(item, w);
112: }
113: }
114: } catch (JAXBException e) {
115: w.reportError(fieldName, e);
116: // recover by ignoring this item
117: }
118: }
119: }
120:
121: public void createBodyUnmarshaller(UnmarshallerChain chain,
122: QNameMap<ChildLoader> loaders) {
123: final int offset = chain.allocateOffset();
124:
125: Receiver recv = new ReceiverImpl(offset);
126:
127: for (QNameMap.Entry<JaxBeanInfo> n : expectedElements
128: .entrySet()) {
129: final JaxBeanInfo beanInfo = n.getValue();
130: loaders.put(n.nsUri, n.localName, new ChildLoader(beanInfo
131: .getLoader(chain.context, true), recv));
132: }
133:
134: if (isMixed) {
135: // handler for processing mixed contents.
136: loaders.put(TEXT_HANDLER, new ChildLoader(
137: new MixedTextoader(recv), null));
138: }
139:
140: if (domHandler != null) {
141: loaders.put(CATCH_ALL, new ChildLoader(new WildcardLoader(
142: domHandler, wcMode), recv));
143: }
144: }
145:
146: private static final class MixedTextoader extends Loader {
147:
148: private final Receiver recv;
149:
150: public MixedTextoader(Receiver recv) {
151: super (true);
152: this .recv = recv;
153: }
154:
155: public void text(UnmarshallingContext.State state,
156: CharSequence text) throws SAXException {
157: recv.receive(state, text.toString());
158: }
159: }
160:
161: public PropertyKind getKind() {
162: return PropertyKind.REFERENCE;
163: }
164:
165: @Override
166: public Accessor getElementPropertyAccessor(String nsUri,
167: String localName) {
168: // TODO: unwrap JAXBElement
169: if (wrapperTagName != null) {
170: if (wrapperTagName.equals(nsUri, localName))
171: return acc;
172: } else {
173: if (expectedElements.containsKey(nsUri, localName))
174: return acc;
175: }
176: return null;
177: }
178: }
|