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