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