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