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.output;
038:
039: import java.io.IOException;
040:
041: import javax.xml.bind.JAXBContext;
042: import javax.xml.stream.XMLStreamException;
043:
044: import com.sun.xml.bind.v2.runtime.Name;
045: import com.sun.xml.bind.v2.runtime.NameList;
046: import com.sun.xml.bind.v2.runtime.XMLSerializer;
047:
048: import org.xml.sax.SAXException;
049:
050: /**
051: * Well-formed XML writer.
052: *
053: * <p>
054: * Implementations of this interface is used to connect {@link XMLSerializer}
055: * to the actual target. This allows {@link XMLSerializer} to be API agnostic.
056: *
057: *
058: * <h2>Notes</h2>
059: * <p>
060: * {@link JAXBContext} assigns indices to URIs and local names
061: * that are statically known by using {@link NameList}.
062: * {@link XmlOutput} implementation can use these indices to improve
063: * the performance. For example, those namespace URI indices can be
064: * turned into prefixes quickly.
065: *
066: * <p>
067: * {@link XmlOutput} still allows arbitrary namepsace URIs / local names
068: * to be written.
069: *
070: * <p>
071: * The {@link NamespaceContextImpl} object, which is shared between {@link XmlOutput} and
072: * {@link XMLSerializer}, keeps track of the in-scope namespace bindings. By the time
073: * the {@link #beginStartTag} method is called, all the namespace bindings for the new
074: * element is already declared. Similarly, after the {@link #endTag} method is called,
075: * in-scope bindings will be removed. This book keeping is all done outside {@link XmlOutput}.
076: *
077: * <p>
078: * {@link XmlOutput} and {@link XMLSerializer} uses indices to
079: * reference prefixes/URIs to be written. {@link NamespaceContextImpl} can
080: * convert prefix indices to URIs and the string representations of prefixes.
081: * Binding from indices to URIs and prefixes do not change while indices
082: * are "in scope", so {@link XmlOutput} is again expected to take advantage of
083: * this to improve the perofmrnace.
084: *
085: * <p>
086: * prefix index 0 is reserved for "xml", and this binding is assumed to be always there.
087: * {@link NamespaceContextImpl} can handle this index correctly, but this binding will never
088: * be reported to {@link XmlOutput} through {@link #beginStartTag}.
089: *
090: * <p>
091: * One pecurilar behavior of a {@link NamespaceContextImpl} object is that it tries
092: * to define redundant xmlns="" on the root element. Implementations of {@link XmlOutput}
093: * is encouraged to check for this and avoid generating redundant namespace declarations.
094: *
095: *
096: *
097: * <h2>Call Sequence</h2>
098: * <p>
099: * {@link XMLSerializer} calls the writer methods in the following order:
100: *
101: * <pre>
102: * CALLSEQUENCE := {@link #startDocument startDocument} ELEMENT {@link #endDocument endDocument}
103: * | ELEMENT // for fragment
104: *
105: * ELEMENT := {@link #beginStartTag beginStartTag} {@link #attribute attribute}* {@link #endStartTag endStartTag} CONTENTS {@link #endTag endTag}
106: *
107: * CONTENTS := (ELEMENT | {@link #text text})*
108: * </pre>
109: *
110: * TODO: for FI, consider making attribute values from Strings to CharSequences.
111: *
112: * @author Kohsuke Kawaguchi
113: */
114: public interface XmlOutput {
115: //
116: //
117: // Contracts
118: //
119: //
120: /**
121: * Called at the very beginning.
122: *
123: * @param serializer
124: * the {@link XMLSerializer} that coordinates this whole marshalling episode.
125: * @param fragment
126: * true if we are marshalling a fragment.
127: */
128: public void startDocument(XMLSerializer serializer,
129: boolean fragment, int[] nsUriIndex2prefixIndex,
130: NamespaceContextImpl nsContext) throws IOException,
131: SAXException, XMLStreamException;
132:
133: /**
134: * Called at the very end. This is the last method to be invoked.
135: *
136: * @param fragment
137: * false if we are writing the whole document.
138: */
139: public void endDocument(boolean fragment) throws IOException,
140: SAXException, XMLStreamException;
141:
142: /**
143: * Writes a start tag.
144: *
145: * <p>
146: * At this point {@link NamespaceContextImpl} holds namespace declarations needed for this
147: * new element.
148: *
149: * <p>
150: * This method is used for writing tags that are indexed.
151: */
152: public void beginStartTag(Name name) throws IOException,
153: XMLStreamException;
154:
155: public void beginStartTag(int prefix, String localName)
156: throws IOException, XMLStreamException;
157:
158: public void attribute(Name name, String value) throws IOException,
159: XMLStreamException;
160:
161: /**
162: * @param prefix
163: * -1 if this attribute does not have a prefix
164: * (this handling differs from that of elements.)
165: */
166: public void attribute(int prefix, String localName, String value)
167: throws IOException, XMLStreamException;
168:
169: public void endStartTag() throws IOException, SAXException;
170:
171: public void endTag(Name name) throws IOException, SAXException,
172: XMLStreamException;
173:
174: public void endTag(int prefix, String localName)
175: throws IOException, SAXException, XMLStreamException;
176:
177: /**
178: * Writes XML text with character escaping, if necessary.
179: *
180: * @param value
181: * this string can contain characters that might need escaping
182: * (such as '&' or '>')
183: * @param needsSeparatingWhitespace
184: */
185: public void text(String value, boolean needsSeparatingWhitespace)
186: throws IOException, SAXException, XMLStreamException;
187:
188: /**
189: * Writes XML text with character escaping, if necessary.
190: *
191: * @param value
192: * this string can contain characters that might need escaping
193: * (such as '&' or '>')
194: * @param needsSeparatingWhitespace
195: */
196: public void text(Pcdata value, boolean needsSeparatingWhitespace)
197: throws IOException, SAXException, XMLStreamException;
198: }
|