View Javadoc
1   /* -*-             c-basic-offset: 4; indent-tabs-mode: nil; -*-  //------100-columns-wide------>|*/
2   // for license please see accompanying LICENSE.txt file (available also at http://www.xmlpull.org/)
3   
4   package org.codehaus.plexus.util.xml.pull;
5   
6   import java.io.IOException;
7   import java.io.OutputStream;
8   import java.io.Writer;
9   
10  /**
11   * Define an interface to serialization of XML Infoset. This interface abstracts away if serialized XML is XML 1.0
12   * compatible text or other formats of XML 1.0 serializations (such as binary XML for example with WBXML).
13   * <p>
14   * <b>PLEASE NOTE:</b> This interface will be part of XmlPull 1.2 API. It is included as basis for discussion. It may
15   * change in any way.
16   * <p>
17   * Exceptions that may be thrown are: IOException or runtime exception (more runtime exceptions can be thrown but are
18   * not declared and as such have no semantics defined for this interface):
19   * <ul>
20   * <li><em>IllegalArgumentException</em> - for almost all methods to signal that argument is illegal
21   * <li><em>IllegalStateException</em> - to signal that call has good arguments but is not expected here (violation of
22   * contract) and for features/properties when requesting setting unimplemented feature/property
23   * (UnsupportedOperationException would be better but it is not in MIDP)
24   * </ul>
25   * <p>
26   * <b>NOTE:</b> writing CDSECT, ENTITY_REF, IGNORABLE_WHITESPACE, PROCESSING_INSTRUCTION, COMMENT, and DOCDECL in some
27   * implementations may not be supported (for example when serializing to WBXML). In such case IllegalStateException will
28   * be thrown and it is recommended to use an optional feature to signal that implementation is not supporting this kind
29   * of output.
30   */
31  public interface XmlSerializer {
32  
33      /**
34       * Set feature identified by name (recommended to be URI for uniqueness). Some well known optional features are
35       * defined in <a href="http://www.xmlpull.org/v1/doc/features.html">
36       * http://www.xmlpull.org/v1/doc/features.html</a>. If feature is not recognized or can not be set then
37       * IllegalStateException MUST be thrown.
38       * @param name feature name
39       * @param state feature state
40       * @exception IllegalStateException If the feature is not supported or can not be set
41       */
42      void setFeature(String name, boolean state) throws IllegalArgumentException, IllegalStateException;
43  
44      /**
45       * Return the current value of the feature with given name.
46       * <p>
47       * <strong>NOTE:</strong> unknown properties are <strong>always</strong> returned as null
48       *
49       * @param name The name of feature to be retrieved.
50       * @return The value of named feature.
51       * @exception IllegalArgumentException if feature string is null
52       */
53      boolean getFeature(String name);
54  
55      /**
56       * Set the value of a property. (the property name is recommended to be URI for uniqueness). Some well known
57       * optional properties are defined in <a href="http://www.xmlpull.org/v1/doc/properties.html">
58       * http://www.xmlpull.org/v1/doc/properties.html</a>. If property is not recognized or can not be set then
59       * IllegalStateException MUST be thrown.
60       * @param name property name
61       * @param value property value
62       * @exception IllegalStateException if the property is not supported or can not be set
63       */
64      void setProperty(String name, Object value) throws IllegalArgumentException, IllegalStateException;
65  
66      /**
67       * Look up the value of a property. The property name is any fully-qualified URI. I
68       * <p>
69       * <strong>NOTE:</strong> unknown properties are <strong>always</strong> returned as null
70       *
71       * @param name The name of property to be retrieved.
72       * @return The value of named property.
73       */
74      Object getProperty(String name);
75  
76      /**
77       * Set to use binary output stream with given encoding.
78       * @param os out
79       * @param encoding encoding
80       * @throws IOException io
81       * @throws IllegalArgumentException if null
82       * @throws IllegalStateException illegal use
83       */
84      void setOutput(OutputStream os, String encoding)
85              throws IOException, IllegalArgumentException, IllegalStateException;
86  
87      /**
88       * @param writer Set the output to the given writer.
89       * <p>
90       * <b>WARNING</b> no information about encoding is available!
91       * @throws IOException io
92       * @throws IllegalArgumentException if null
93       * @throws IllegalStateException illegal use
94       */
95      void setOutput(Writer writer) throws IOException, IllegalArgumentException, IllegalStateException;
96  
97      /**
98       * Write &lt;&#63;xml declaration with encoding (if encoding not null) and standalone flag (if standalone not null)
99       * This method can only be called just after setOutput.
100      * @param encoding document encoding
101      * @param standalone standalone flag value
102      * @throws IOException io
103      * @throws IllegalArgumentException if null
104      * @throws IllegalStateException illegal use
105      */
106     void startDocument(String encoding, Boolean standalone)
107             throws IOException, IllegalArgumentException, IllegalStateException;
108 
109     /**
110      * Finish writing. All unclosed start tags will be closed and output will be flushed. After calling this method no
111      * more output can be serialized until next call to setOutput()
112      * @throws IOException io
113      * @throws IllegalArgumentException if null
114      * @throws IllegalStateException illegal use
115      */
116     void endDocument() throws IOException, IllegalArgumentException, IllegalStateException;
117 
118     /**
119      * Binds the given prefix to the given namespace. This call is valid for the next element including child elements.
120      * The prefix and namespace MUST be always declared even if prefix is not used in element (startTag() or
121      * attribute()) - for XML 1.0 it must result in declaring <code>xmlns:prefix='namespace'</code> (or
122      * <code>xmlns:prefix="namespace"</code> depending what character is used to quote attribute value).
123      * <p>
124      * <b>NOTE:</b> this method MUST be called directly before startTag() and if anything but startTag() or setPrefix()
125      * is called next there will be exception.
126      * <p>
127      * <b>NOTE:</b> prefixes "xml" and "xmlns" are already bound and can not be redefined see:
128      * <a href="http://www.w3.org/XML/xml-names-19990114-errata#NE05">Namespaces in XML Errata</a>.
129      * <p>
130      * <b>NOTE:</b> to set default namespace use as prefix empty string.
131      *
132      * @param prefix must be not null (or IllegalArgumentException is thrown)
133      * @param namespace must be not null
134      * @throws IOException io
135      * @throws IllegalArgumentException if null
136      * @throws IllegalStateException illegal use
137      */
138     void setPrefix(String prefix, String namespace) throws IOException, IllegalArgumentException, IllegalStateException;
139 
140     /**
141      * @return namespace that corresponds to given prefix If there is no prefix bound to this namespace return null but
142      * if generatePrefix is false then return generated prefix.
143      * <p>
144      * <b>NOTE:</b> if the prefix is empty string "" and default namespace is bound to this prefix then empty string
145      * ("") is returned.
146      * <p>
147      * <b>NOTE:</b> prefixes "xml" and "xmlns" are already bound will have values as defined
148      * <a href="http://www.w3.org/TR/REC-xml-names/">Namespaces in XML specification</a>
149      * @param namespace the namespace
150      * @param generatePrefix to generate the missing prefix
151      * @throws IllegalArgumentException if null
152      */
153     String getPrefix(String namespace, boolean generatePrefix) throws IllegalArgumentException;
154 
155     /**
156      * @return the current depth of the element. Outside the root element, the depth is 0. The depth is incremented by 1
157      * when startTag() is called. The depth is decremented after the call to endTag() event was observed.
158      *
159      * <pre>
160      * &lt;!-- outside --&gt;     0
161      * &lt;root&gt;               1
162      *   sometext                 1
163      *     &lt;foobar&gt;         2
164      *     &lt;/foobar&gt;        2
165      * &lt;/root&gt;              1
166      * &lt;!-- outside --&gt;     0
167      * </pre>
168      */
169     int getDepth();
170 
171     /**
172      * Returns the namespace URI of the current element as set by startTag().
173      * <p>
174      * <b>NOTE:</b> that means in particular that:
175      * <ul>
176      * <li>if there was startTag("", ...) then getNamespace() returns ""
177      * <li>if there was startTag(null, ...) then getNamespace() returns null
178      * </ul>
179      *
180      * @return namespace set by startTag() that is currently in scope
181      */
182     String getNamespace();
183 
184     /**
185      * Returns the name of the current element as set by startTag(). It can only be null before first call to startTag()
186      * or when last endTag() is called to close first startTag().
187      *
188      * @return namespace set by startTag() that is currently in scope
189      */
190     String getName();
191 
192     /**
193      * Writes a start tag with the given namespace and name. If there is no prefix defined for the given namespace, a
194      * prefix will be defined automatically. The explicit prefixes for namespaces can be established by calling
195      * setPrefix() immediately before this method. If namespace is null no namespace prefix is printed but just name. If
196      * namespace is empty string then serializer will make sure that default empty namespace is declared (in XML 1.0
197      * xmlns='') or throw IllegalStateException if default namespace is already bound to non-empty string.
198      * @param namespace ns
199      * @param name tag name
200      * @return XmlSerializer
201      * @throws IOException io
202      * @throws IllegalArgumentException if null
203      * @throws IllegalStateException illegal use
204      */
205     XmlSerializer startTag(String namespace, String name)
206             throws IOException, IllegalArgumentException, IllegalStateException;
207 
208     /**
209      * Write an attribute. Calls to attribute() MUST follow a call to startTag() immediately. If there is no prefix
210      * defined for the given namespace, a prefix will be defined automatically. If namespace is null or empty string no
211      * namespace prefix is printed but just name.
212      * @param name attribute name
213      * @param value attribute value
214      * @param namespace namespace to use
215      * @return XmlSerializer
216      * @throws IOException io
217      * @throws IllegalArgumentException if null
218      * @throws IllegalStateException illegal use
219      */
220     XmlSerializer attribute(String namespace, String name, String value)
221             throws IOException, IllegalArgumentException, IllegalStateException;
222 
223     /**
224      * Write end tag. Repetition of namespace and name is just for avoiding errors.
225      * <b>Background:</b> in kXML endTag had no arguments, and non matching tags were very difficult to find... If
226      * namespace is null no namespace prefix is printed but just name. If namespace is empty string then serializer will
227      * make sure that default empty namespace is declared (in XML 1.0 xmlns='').
228      * @param namespace ns
229      * @param name tag name
230      * @return XmlSerializer
231      * @throws IOException io
232      * @throws IllegalArgumentException if null
233      * @throws IllegalStateException illegal use
234      */
235     XmlSerializer endTag(String namespace, String name)
236             throws IOException, IllegalArgumentException, IllegalStateException;
237 
238     // /**
239     // * Writes a start tag with the given namespace and name.
240     // * <br />If there is no prefix defined (prefix == null) for the given namespace,
241     // * a prefix will be defined automatically.
242     // * <br />If explicit prefixes is passed (prefix != null) then it will be used
243     // *and namespace declared if not already declared or
244     // * throw IllegalStateException the same prefix was already set on this
245     // * element (setPrefix()) and was bound to different namespace.
246     // * <br />If namespace is null then prefix must be null too or IllegalStateException is thrown.
247     // * <br />If namespace is null then no namespace prefix is printed but just name.
248     // * <br />If namespace is empty string then serializer will make sure that
249     // * default empty namespace is declared (in XML 1.0 xmlns='')
250     // * or throw IllegalStateException if default namespace is already bound
251     // * to non-empty string.
252     // */
253     // XmlSerializer startTag (String prefix, String namespace, String name)
254     // throws IOException, IllegalArgumentException, IllegalStateException;
255     //
256     // /**
257     // * Write an attribute. Calls to attribute() MUST follow a call to
258     // * startTag() immediately.
259     // * <br />If there is no prefix defined (prefix == null) for the given namespace,
260     // * a prefix will be defined automatically.
261     // * <br />If explicit prefixes is passed (prefix != null) then it will be used
262     // * and namespace declared if not already declared or
263     // * throw IllegalStateException the same prefix was already set on this
264     // * element (setPrefix()) and was bound to different namespace.
265     // * <br />If namespace is null then prefix must be null too or IllegalStateException is thrown.
266     // * <br />If namespace is null then no namespace prefix is printed but just name.
267     // * <br />If namespace is empty string then serializer will make sure that
268     // * default empty namespace is declared (in XML 1.0 xmlns='')
269     // * or throw IllegalStateException if default namespace is already bound
270     // * to non-empty string.
271     // */
272     // XmlSerializer attribute (String prefix, String namespace, String name, String value)
273     // throws IOException, IllegalArgumentException, IllegalStateException;
274     //
275     // /**
276     // * Write end tag. Repetition of namespace, prefix, and name is just for avoiding errors.
277     // * <br />If namespace or name arguments are different from corresponding startTag call
278     // * then IllegalArgumentException is thrown, if prefix argument is not null and is different
279     // * from corresponding starTag then IllegalArgumentException is thrown.
280     // * <br />If namespace is null then prefix must be null too or IllegalStateException is thrown.
281     // * <br />If namespace is null then no namespace prefix is printed but just name.
282     // * <br />If namespace is empty string then serializer will make sure that
283     // * default empty namespace is declared (in XML 1.0 xmlns='').
284     // * <p><b>Background:</b> in kXML endTag had no arguments, and non matching tags were
285     // * very difficult to find...</p>
286     // */
287     // ALEK: This is really optional as prefix in end tag MUST correspond to start tag but good for error checking
288     // XmlSerializer endTag (String prefix, String namespace, String name)
289     // throws IOException, IllegalArgumentException, IllegalStateException;
290 
291     /**
292      * @param text Writes text, where special XML chars are escaped automatically
293      * @return XmlSerializer
294      * @throws IOException io
295      * @throws IllegalArgumentException if null
296      * @throws IllegalStateException illegal use
297      */
298     XmlSerializer text(String text) throws IOException, IllegalArgumentException, IllegalStateException;
299 
300     /**
301      * Writes text, where special XML chars are escaped automatically
302      * @param buf characters
303      * @param len lenght
304      * @param start start
305      * @return XmlSerializer
306      * @throws IOException io
307      * @throws IllegalArgumentException if null
308      * @throws IllegalStateException illegal use
309      */
310     XmlSerializer text(char[] buf, int start, int len)
311             throws IOException, IllegalArgumentException, IllegalStateException;
312 
313     void cdsect(String text) throws IOException, IllegalArgumentException, IllegalStateException;
314 
315     void entityRef(String text) throws IOException, IllegalArgumentException, IllegalStateException;
316 
317     void processingInstruction(String text) throws IOException, IllegalArgumentException, IllegalStateException;
318 
319     void comment(String text) throws IOException, IllegalArgumentException, IllegalStateException;
320 
321     void docdecl(String text) throws IOException, IllegalArgumentException, IllegalStateException;
322 
323     void ignorableWhitespace(String text) throws IOException, IllegalArgumentException, IllegalStateException;
324 
325     /**
326      * Write all pending output to the stream. If method startTag() or attribute() was called then start tag is closed
327      * (final &gt;) before flush() is called on underlying output stream.
328      * <p>
329      * <b>NOTE:</b> if there is need to close start tag (so no more attribute() calls are allowed) but without flushing
330      * output call method text() with empty string (text("")).
331      * @throws IOException io
332      */
333     void flush() throws IOException;
334 }