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