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: import java.util.Collection;
030:
031: import javax.xml.namespace.QName;
032: import javax.xml.stream.XMLStreamException;
033:
034: import com.sun.xml.internal.bind.api.AccessorException;
035: import com.sun.xml.internal.bind.v2.util.QNameMap;
036: import com.sun.xml.internal.bind.v2.model.runtime.RuntimePropertyInfo;
037: import com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl;
038: import com.sun.xml.internal.bind.v2.runtime.Name;
039: import com.sun.xml.internal.bind.v2.runtime.XMLSerializer;
040: import com.sun.xml.internal.bind.v2.runtime.unmarshaller.ChildLoader;
041: import com.sun.xml.internal.bind.v2.runtime.unmarshaller.TagName;
042: import com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader;
043: import com.sun.xml.internal.bind.v2.runtime.unmarshaller.Receiver;
044: import com.sun.xml.internal.bind.v2.runtime.unmarshaller.Scope;
045: import com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext;
046:
047: import org.xml.sax.SAXException;
048:
049: /**
050: * Commonality between {@link ArrayElementProperty} and {@link ArrayReferenceNodeProperty}.
051: *
052: * Mostly handles the unmarshalling of the wrapper element.
053: *
054: * @author Kohsuke Kawaguchi
055: */
056: abstract class ArrayERProperty<BeanT, ListT, ItemT> extends
057: ArrayProperty<BeanT, ListT, ItemT> {
058:
059: /**
060: * Wrapper tag name if any, or null.
061: */
062: protected final Name wrapperTagName;
063:
064: /**
065: * True if the wrapper tag name is nillable.
066: * Always false if {@link #wrapperTagName}==null.
067: */
068: protected final boolean isWrapperNillable;
069:
070: protected ArrayERProperty(JAXBContextImpl grammar,
071: RuntimePropertyInfo prop, QName tagName,
072: boolean isWrapperNillable) {
073: super (grammar, prop);
074: if (tagName == null)
075: this .wrapperTagName = null;
076: else
077: this .wrapperTagName = grammar.nameBuilder
078: .createElementName(tagName);
079: this .isWrapperNillable = isWrapperNillable;
080: }
081:
082: private static final class ItemsLoader extends Loader {
083: public ItemsLoader(QNameMap<ChildLoader> children) {
084: super (false);
085: this .children = children;
086: }
087:
088: @Override
089: public void startElement(UnmarshallingContext.State state,
090: TagName ea) {
091: state.getContext().startScope(1);
092: // inherit the target so that our children can access its target
093: state.target = state.prev.target;
094: }
095:
096: private final QNameMap<ChildLoader> children;
097:
098: @Override
099: public void childElement(UnmarshallingContext.State state,
100: TagName ea) throws SAXException {
101: ChildLoader child = children.get(ea.uri, ea.local);
102: if (child != null) {
103: state.loader = child.loader;
104: state.receiver = child.receiver;
105: } else {
106: super .childElement(state, ea);
107: }
108: }
109:
110: @Override
111: public void leaveElement(UnmarshallingContext.State state,
112: TagName ea) throws SAXException {
113: state.getContext().endScope(1);
114: }
115:
116: @Override
117: public Collection<QName> getExpectedChildElements() {
118: return children.keySet();
119: }
120: }
121:
122: public final void serializeBody(BeanT o, XMLSerializer w,
123: Object outerPeer) throws SAXException, AccessorException,
124: IOException, XMLStreamException {
125: ListT list = acc.get(o);
126:
127: if (list != null) {
128: if (wrapperTagName != null) {
129: w.startElement(wrapperTagName, null);
130: w.endNamespaceDecls(list);
131: w.endAttributes();
132: }
133:
134: serializeListBody(o, w, list);
135:
136: if (wrapperTagName != null)
137: w.endElement();
138: } else {
139: // list is null
140: if (isWrapperNillable) {
141: w.startElement(wrapperTagName, null);
142: w.writeXsiNilTrue();
143: w.endElement();
144: } // otherwise don't print the wrapper tag name
145: }
146: }
147:
148: /**
149: * Serializses the items of the list.
150: * This method is invoked after the necessary wrapper tag is produced (if necessary.)
151: *
152: * @param list
153: * always non-null.
154: */
155: protected abstract void serializeListBody(BeanT o, XMLSerializer w,
156: ListT list) throws IOException, XMLStreamException,
157: SAXException, AccessorException;
158:
159: /**
160: * Creates the unmarshaller to unmarshal the body.
161: */
162: protected abstract void createBodyUnmarshaller(
163: UnmarshallerChain chain, QNameMap<ChildLoader> loaders);
164:
165: public final void buildChildElementUnmarshallers(
166: UnmarshallerChain chain, QNameMap<ChildLoader> loaders) {
167: if (wrapperTagName != null) {
168: UnmarshallerChain c = new UnmarshallerChain(chain.context);
169: QNameMap<ChildLoader> m = new QNameMap<ChildLoader>();
170: createBodyUnmarshaller(c, m);
171: loaders.put(wrapperTagName, new ChildLoader(
172: new ItemsLoader(m), null));
173: } else {
174: createBodyUnmarshaller(chain, loaders);
175: }
176: }
177:
178: /**
179: * {@link Receiver} that puts the child object into the {@link Scope} object.
180: */
181: protected final class ReceiverImpl implements Receiver {
182: private final int offset;
183:
184: protected ReceiverImpl(int offset) {
185: this .offset = offset;
186: }
187:
188: public void receive(UnmarshallingContext.State state, Object o)
189: throws SAXException {
190: state.getContext().getScope(offset).add(acc, lister, o);
191: }
192: }
193: }
|