View Javadoc
1   package org.codehaus.modello.plugin.sax;
2   
3   /*
4    * Copyright (c) 2013, Codehaus.org
5    *
6    * Permission is hereby granted, free of charge, to any person obtaining a copy of
7    * this software and associated documentation files (the "Software"), to deal in
8    * the Software without restriction, including without limitation the rights to
9    * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
10   * of the Software, and to permit persons to whom the Software is furnished to do
11   * so, subject to the following conditions:
12   *
13   * The above copyright notice and this permission notice shall be included in all
14   * copies or substantial portions of the Software.
15   *
16   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22   * SOFTWARE.
23   */
24  
25  import javax.inject.Named;
26  
27  import java.io.IOException;
28  import java.util.List;
29  import java.util.Properties;
30  
31  import org.codehaus.modello.ModelloException;
32  import org.codehaus.modello.model.Model;
33  import org.codehaus.modello.model.ModelAssociation;
34  import org.codehaus.modello.model.ModelClass;
35  import org.codehaus.modello.model.ModelDefault;
36  import org.codehaus.modello.model.ModelField;
37  import org.codehaus.modello.plugin.java.javasource.JClass;
38  import org.codehaus.modello.plugin.java.javasource.JConstructor;
39  import org.codehaus.modello.plugin.java.javasource.JField;
40  import org.codehaus.modello.plugin.java.javasource.JMethod;
41  import org.codehaus.modello.plugin.java.javasource.JParameter;
42  import org.codehaus.modello.plugin.java.javasource.JSourceCode;
43  import org.codehaus.modello.plugin.java.javasource.JSourceWriter;
44  import org.codehaus.modello.plugin.java.javasource.JType;
45  import org.codehaus.modello.plugin.java.metadata.JavaFieldMetadata;
46  import org.codehaus.modello.plugin.model.ModelClassMetadata;
47  import org.codehaus.modello.plugins.xml.AbstractXmlJavaGenerator;
48  import org.codehaus.modello.plugins.xml.metadata.XmlAssociationMetadata;
49  import org.codehaus.modello.plugins.xml.metadata.XmlFieldMetadata;
50  import org.codehaus.modello.plugins.xml.metadata.XmlModelMetadata;
51  
52  /**
53   * @since 1.8
54   * @author <a href="mailto:simonetripodi@apache.org">Simone Tripodi</a>
55   */
56  @Named("sax-writer")
57  public class SaxWriterGenerator extends AbstractXmlJavaGenerator {
58  
59      private boolean requiresDomSupport;
60  
61      public void generate(Model model, Properties parameters) throws ModelloException {
62          initialize(model, parameters);
63  
64          requiresDomSupport = false;
65  
66          try {
67              generateSaxWriter();
68          } catch (IOException ex) {
69              throw new ModelloException("Exception while generating SAX Writer.", ex);
70          }
71      }
72  
73      private void generateSaxWriter() throws ModelloException, IOException {
74          Model objectModel = getModel();
75  
76          String packageName =
77                  objectModel.getDefaultPackageName(isPackageWithVersion(), getGeneratedVersion()) + ".io.sax";
78  
79          String marshallerName = getFileName("SaxWriter");
80  
81          JSourceWriter sourceWriter = newJSourceWriter(packageName, marshallerName);
82  
83          JClass jClass = new JClass(packageName + '.' + marshallerName);
84          initHeader(jClass);
85          suppressAllWarnings(objectModel, jClass);
86  
87          jClass.addImport("java.io.IOException");
88          jClass.addImport("java.io.OutputStream");
89          jClass.addImport("java.io.OutputStreamWriter");
90          jClass.addImport("java.io.UnsupportedEncodingException");
91          jClass.addImport("java.io.Writer");
92          jClass.addImport("java.util.Iterator");
93          jClass.addImport("java.util.Properties");
94          jClass.addImport("javax.xml.transform.OutputKeys");
95          jClass.addImport("javax.xml.transform.TransformerException");
96          jClass.addImport("javax.xml.transform.TransformerFactory");
97          jClass.addImport("javax.xml.transform.sax.SAXTransformerFactory");
98          jClass.addImport("javax.xml.transform.sax.TransformerHandler");
99          jClass.addImport("javax.xml.transform.stream.StreamResult");
100         jClass.addImport("org.xml.sax.ContentHandler");
101         jClass.addImport("org.xml.sax.SAXException");
102         jClass.addImport("org.xml.sax.helpers.AttributesImpl");
103 
104         JField namespaceField = new JField(new JClass("String"), "NAMESPACE");
105         namespaceField.getModifiers().setFinal(true);
106         namespaceField.getModifiers().setStatic(true);
107         namespaceField.setInitString("\"\"");
108         jClass.addField(namespaceField);
109 
110         JField factoryField = new JField(new JClass("SAXTransformerFactory"), "transformerFactory");
111         factoryField.getModifiers().setFinal(true);
112         factoryField.setInitString("(SAXTransformerFactory) TransformerFactory.newInstance()");
113         jClass.addField(factoryField);
114 
115         addModelImports(jClass, null);
116 
117         String root = objectModel.getRoot(getGeneratedVersion());
118 
119         ModelClass rootClass = objectModel.getClass(root, getGeneratedVersion());
120 
121         String rootElement = resolveTagName(rootClass);
122 
123         JConstructor saxWriterConstructor = new JConstructor(jClass);
124         JSourceCode sc = saxWriterConstructor.getSourceCode();
125         if (hasJavaSourceSupport(5)) {
126             sc.add("transformerFactory.setAttribute( \"indent-number\", 2 );");
127         } else {
128             sc.add("transformerFactory.setAttribute( \"indent-number\", new Integer( 2 ) );");
129         }
130 
131         jClass.addConstructor(saxWriterConstructor);
132 
133         // ----------------------------------------------------------------------
134         // Write the write( Writer, Model ) method which will do the unmarshalling.
135         // ----------------------------------------------------------------------
136 
137         JMethod marshall = new JMethod("write");
138 
139         String rootElementParameterName = uncapitalise(root);
140         marshall.addParameter(new JParameter(new JClass("Writer"), "writer"));
141         marshall.addParameter(new JParameter(new JClass(root), rootElementParameterName));
142 
143         marshall.addException(new JClass("SAXException"));
144         marshall.addException(new JClass("TransformerException"));
145 
146         sc = marshall.getSourceCode();
147 
148         sc.add("TransformerHandler transformerHandler = transformerFactory.newTransformerHandler();");
149 
150         sc.add("Properties format = new Properties();");
151         sc.add("format.put( OutputKeys.ENCODING, " + rootElementParameterName + ".getModelEncoding() );");
152         sc.add("format.put( OutputKeys.INDENT, \"yes\" );");
153         sc.add("format.put( OutputKeys.MEDIA_TYPE, \"text/xml\" );");
154         sc.add("format.put( OutputKeys.METHOD, \"xml\" );");
155 
156         sc.add("transformerHandler.getTransformer().setOutputProperties( format );");
157         sc.add("transformerHandler.setResult( new StreamResult( writer ) );");
158 
159         sc.add("write( transformerHandler, " + rootElementParameterName + " );");
160 
161         jClass.addMethod(marshall);
162 
163         // ----------------------------------------------------------------------
164         // Write the write( OutputStream, Model ) method which will do the unmarshalling.
165         // ----------------------------------------------------------------------
166 
167         marshall = new JMethod("write");
168 
169         marshall.addParameter(new JParameter(new JClass("OutputStream"), "stream"));
170         marshall.addParameter(new JParameter(new JClass(root), rootElementParameterName));
171 
172         marshall.addException(new JClass("SAXException"));
173         marshall.addException(new JClass("TransformerException"));
174         marshall.addException(new JClass("UnsupportedEncodingException"));
175 
176         sc = marshall.getSourceCode();
177 
178         sc.add("write( new OutputStreamWriter( stream, " + rootElementParameterName + ".getModelEncoding() ), "
179                 + rootElementParameterName + " );");
180 
181         jClass.addMethod(marshall);
182 
183         // ----------------------------------------------------------------------
184         // Write the write( ContentHandler, Model ) method which will do the unmarshalling.
185         // ----------------------------------------------------------------------
186 
187         marshall = new JMethod("write");
188 
189         marshall.addParameter(new JParameter(new JClass("ContentHandler"), "contentHandler"));
190         marshall.addParameter(new JParameter(new JClass(root), rootElementParameterName));
191 
192         marshall.addException(new JClass("SAXException"));
193 
194         sc = marshall.getSourceCode();
195 
196         sc.add("write( contentHandler, " + rootElementParameterName + ", true );");
197 
198         jClass.addMethod(marshall);
199 
200         // ----------------------------------------------------------------------
201         // Write the write( ContentHandler, Model, boolean ) method which will do the unmarshalling.
202         // ----------------------------------------------------------------------
203 
204         marshall = new JMethod("write");
205 
206         marshall.addParameter(new JParameter(new JClass("ContentHandler"), "contentHandler"));
207         marshall.addParameter(new JParameter(new JClass(root), rootElementParameterName));
208         marshall.addParameter(new JParameter(JType.BOOLEAN, "startDocument"));
209 
210         marshall.addException(new JClass("SAXException"));
211 
212         sc = marshall.getSourceCode();
213 
214         sc.add("if ( startDocument )");
215         sc.add("{");
216         sc.addIndented("contentHandler.startDocument();");
217         sc.add("}");
218 
219         sc.add("AttributesImpl attributes = new AttributesImpl();");
220 
221         sc.add("write" + root + "( " + rootElementParameterName + ", \"" + rootElement
222                 + "\", contentHandler, attributes );");
223 
224         sc.add("if ( startDocument )");
225         sc.add("{");
226         sc.addIndented("contentHandler.endDocument();");
227         sc.add("}");
228 
229         jClass.addMethod(marshall);
230 
231         // ----------------------------------------------------------------------
232         // Write the writeText( String, ContentHandler ) method which will help unmarshalling textual values.
233         // ----------------------------------------------------------------------
234 
235         marshall = new JMethod("writeText");
236         marshall.getModifiers().makePrivate();
237 
238         marshall.addParameter(new JParameter(new JClass("String"), "text"));
239         marshall.addParameter(new JParameter(new JClass("ContentHandler"), "contentHandler"));
240 
241         marshall.addException(new JClass("SAXException"));
242 
243         sc = marshall.getSourceCode();
244 
245         sc.add("contentHandler.characters( text.toCharArray(), 0, text.length() );");
246 
247         // generate the code
248 
249         jClass.addMethod(marshall);
250 
251         writeAllClasses(objectModel, jClass);
252 
253         if (requiresDomSupport) {
254             createWriteDomMethod(jClass);
255             createXpp3DomMethod(jClass);
256         }
257 
258         jClass.print(sourceWriter);
259 
260         sourceWriter.close();
261     }
262 
263     private void writeAllClasses(Model objectModel, JClass jClass) throws ModelloException {
264         for (ModelClass clazz : getClasses(objectModel)) {
265             writeClass(clazz, jClass);
266         }
267     }
268 
269     private void writeClass(ModelClass modelClass, JClass jClass) throws ModelloException {
270         String className = modelClass.getName();
271 
272         String uncapClassName = uncapitalise(className);
273 
274         JMethod marshall = new JMethod("write" + className);
275 
276         marshall.addParameter(new JParameter(new JClass(className), uncapClassName));
277         marshall.addParameter(new JParameter(new JClass("String"), "tagName"));
278         marshall.addParameter(new JParameter(new JClass("ContentHandler"), "contentHandler"));
279         marshall.addParameter(new JParameter(new JClass("AttributesImpl"), "attributes"));
280 
281         marshall.addException(new JClass("SAXException"));
282 
283         marshall.getModifiers().makePrivate();
284 
285         JSourceCode sc = marshall.getSourceCode();
286 
287         ModelClassMetadata classMetadata = (ModelClassMetadata) modelClass.getMetadata(ModelClassMetadata.ID);
288 
289         String namespace = null;
290         XmlModelMetadata xmlModelMetadata =
291                 (XmlModelMetadata) modelClass.getModel().getMetadata(XmlModelMetadata.ID);
292 
293         ModelField contentField = null;
294 
295         String contentValue = null;
296 
297         List<ModelField> modelFields = getFieldsForXml(modelClass, getGeneratedVersion());
298 
299         boolean needsToCleanAttributes = false;
300 
301         // XML attributes
302         for (ModelField field : modelFields) {
303             XmlFieldMetadata xmlFieldMetadata = (XmlFieldMetadata) field.getMetadata(XmlFieldMetadata.ID);
304 
305             JavaFieldMetadata javaFieldMetadata = (JavaFieldMetadata) field.getMetadata(JavaFieldMetadata.ID);
306 
307             String fieldTagName = resolveTagName(field, xmlFieldMetadata);
308 
309             String type = field.getType();
310 
311             String value = uncapClassName + "." + getPrefix(javaFieldMetadata) + capitalise(field.getName()) + "()";
312 
313             if (xmlFieldMetadata.isContent()) {
314                 contentField = field;
315                 contentValue = value;
316                 continue;
317             }
318 
319             if (xmlFieldMetadata.isAttribute()) {
320                 sc.add(getValueChecker(type, value, field));
321 
322                 sc.add("{");
323                 sc.addIndented("attributes.addAttribute( NAMESPACE, \""
324                         + fieldTagName
325                         + "\", \""
326                         + fieldTagName
327                         + "\", \"CDATA\", "
328                         + getValue(field.getType(), value, xmlFieldMetadata)
329                         + " );");
330                 sc.add("}");
331 
332                 needsToCleanAttributes = true;
333             }
334         }
335 
336         // add namespace information for root element only
337         if (classMetadata.isRootElement() && (xmlModelMetadata.getNamespace() != null)) {
338             namespace = xmlModelMetadata.getNamespace(getGeneratedVersion());
339             sc.add("contentHandler.startPrefixMapping( \"\", \"" + namespace + "\" );");
340         }
341 
342         if ((namespace != null) && (xmlModelMetadata.getSchemaLocation() != null)) {
343             String url = xmlModelMetadata.getSchemaLocation(getGeneratedVersion());
344 
345             sc.add("contentHandler.startPrefixMapping( \"xsi\", \"http://www.w3.org/2001/XMLSchema-instance\" );");
346 
347             sc.add(
348                     "attributes.addAttribute( \"http://www.w3.org/2001/XMLSchema-instance\", \"schemaLocation\", \"xsi:schemaLocation\", \"CDATA\", \""
349                             + namespace + " " + url + "\" );");
350         }
351 
352         sc.add("contentHandler.startElement( NAMESPACE, tagName, tagName, attributes );");
353 
354         if (needsToCleanAttributes) {
355             sc.add("attributes.clear();");
356         }
357 
358         if (contentField != null) {
359             XmlFieldMetadata xmlFieldMetadata = (XmlFieldMetadata) contentField.getMetadata(XmlFieldMetadata.ID);
360             sc.add("writeText( " + getValue(contentField.getType(), contentValue, xmlFieldMetadata)
361                     + ", contentHandler );");
362         }
363 
364         // XML tags
365         for (ModelField field : modelFields) {
366             XmlFieldMetadata xmlFieldMetadata = (XmlFieldMetadata) field.getMetadata(XmlFieldMetadata.ID);
367 
368             if (xmlFieldMetadata.isContent()) {
369                 // skip field with type Content
370                 continue;
371             }
372 
373             JavaFieldMetadata javaFieldMetadata = (JavaFieldMetadata) field.getMetadata(JavaFieldMetadata.ID);
374 
375             String fieldTagName = resolveTagName(field, xmlFieldMetadata);
376 
377             String type = field.getType();
378 
379             String value = uncapClassName + "." + getPrefix(javaFieldMetadata) + capitalise(field.getName()) + "()";
380 
381             if (xmlFieldMetadata.isAttribute()) {
382                 continue;
383             }
384 
385             if (field instanceof ModelAssociation) {
386                 ModelAssociation association = (ModelAssociation) field;
387 
388                 String associationName = association.getName();
389 
390                 if (association.isOneMultiplicity()) {
391                     sc.add(getValueChecker(type, value, association));
392 
393                     sc.add("{");
394                     sc.addIndented("write" + association.getTo() + "( (" + association.getTo() + ") " + value + ", \""
395                             + fieldTagName + "\", contentHandler, attributes );");
396                     sc.add("}");
397                 } else {
398                     // MANY_MULTIPLICITY
399 
400                     XmlAssociationMetadata xmlAssociationMetadata =
401                             (XmlAssociationMetadata) association.getAssociationMetadata(XmlAssociationMetadata.ID);
402 
403                     String valuesTagName = resolveTagName(fieldTagName, xmlAssociationMetadata);
404 
405                     type = association.getType();
406                     String toType = association.getTo();
407 
408                     boolean wrappedItems = xmlAssociationMetadata.isWrappedItems();
409 
410                     if (ModelDefault.LIST.equals(type) || ModelDefault.SET.equals(type)) {
411                         sc.add(getValueChecker(type, value, association));
412 
413                         sc.add("{");
414                         sc.indent();
415 
416                         if (wrappedItems) {
417                             sc.add("contentHandler.startElement( NAMESPACE, \"" + fieldTagName + "\", \"" + fieldTagName
418                                     + "\", attributes );");
419                         }
420 
421                         sc.add("for ( Iterator iter = " + value + ".iterator(); iter.hasNext(); )");
422 
423                         sc.add("{");
424                         sc.indent();
425 
426                         if (isClassInModel(association.getTo(), modelClass.getModel())) {
427                             sc.add(toType + " o = (" + toType + ") iter.next();");
428 
429                             sc.add("write" + toType + "( o, \"" + valuesTagName + "\", contentHandler, attributes );");
430                         } else {
431                             sc.add(toType + " " + singular(uncapitalise(field.getName())) + " = (" + toType
432                                     + ") iter.next();");
433 
434                             sc.add("contentHandler.startElement( NAMESPACE, \"" + valuesTagName + "\", \""
435                                     + valuesTagName + "\", attributes );");
436                             sc.add("writeText( " + singular(uncapitalise(field.getName())) + ", contentHandler );");
437                             sc.add("contentHandler.endElement( NAMESPACE, \"" + valuesTagName + "\", \"" + valuesTagName
438                                     + "\" );");
439                         }
440 
441                         sc.unindent();
442                         sc.add("}");
443 
444                         if (wrappedItems) {
445                             sc.add("contentHandler.endElement( NAMESPACE, \"" + fieldTagName + "\", \"" + fieldTagName
446                                     + "\" );");
447                         }
448 
449                         sc.unindent();
450                         sc.add("}");
451                     } else {
452                         // Map or Properties
453 
454                         sc.add(getValueChecker(type, value, field));
455 
456                         sc.add("{");
457                         sc.indent();
458 
459                         if (wrappedItems) {
460                             sc.add("contentHandler.startElement( NAMESPACE, \"" + fieldTagName + "\", \"" + fieldTagName
461                                     + "\", attributes );");
462                         }
463 
464                         sc.add("for ( Iterator iter = " + value + ".keySet().iterator(); iter.hasNext(); )");
465 
466                         sc.add("{");
467                         sc.indent();
468 
469                         sc.add("String key = (String) iter.next();");
470 
471                         sc.add(association.getTo() + " value = (" + association.getTo() + ") " + value
472                                 + ".get( key );");
473 
474                         if (xmlAssociationMetadata.isMapExplode()) {
475                             sc.add("contentHandler.startElement( NAMESPACE, \"" + singular(associationName) + "\", \""
476                                     + singular(associationName) + "\", attributes );");
477 
478                             sc.add("contentHandler.startElement( NAMESPACE, \"key\", \"key\", attributes );");
479                             sc.add("writeText( key, contentHandler );");
480                             sc.add("contentHandler.endElement( NAMESPACE, \"key\", \"key\" );");
481 
482                             if (isClassInModel(
483                                     association.getTo(),
484                                     association.getModelClass().getModel())) {
485                                 sc.add("write" + association.getTo()
486                                         + "( value, \"value\", contentHandler, attributes );");
487                             } else {
488                                 sc.add("contentHandler.startElement( NAMESPACE, \"value\", \"value\", attributes );");
489                                 sc.add("writeText( " + getValue(association.getTo(), "value", xmlFieldMetadata)
490                                         + ", contentHandler );");
491                                 sc.add("contentHandler.endElement( NAMESPACE, \"value\", \"value\" );");
492                             }
493 
494                             sc.add("contentHandler.endElement( NAMESPACE, \"" + singular(associationName) + "\", \""
495                                     + singular(associationName) + "\" );");
496                         } else {
497                             if (isClassInModel(
498                                     association.getTo(),
499                                     association.getModelClass().getModel())) {
500                                 sc.add("write" + association.getTo() + "( value, key, contentHandler, attributes );");
501                             } else {
502                                 sc.add("contentHandler.startElement( NAMESPACE, key, key, attributes );");
503                                 sc.add("writeText( " + getValue(association.getTo(), "value", xmlFieldMetadata)
504                                         + ", contentHandler );");
505                                 sc.add("contentHandler.endElement( NAMESPACE, key, key );");
506                             }
507                         }
508 
509                         sc.unindent();
510                         sc.add("}");
511 
512                         if (wrappedItems) {
513                             sc.add("contentHandler.endElement( NAMESPACE, \"" + fieldTagName + "\", \"" + fieldTagName
514                                     + "\" );");
515                         }
516 
517                         sc.unindent();
518                         sc.add("}");
519                     }
520                 }
521             } else {
522                 sc.add(getValueChecker(type, value, field));
523 
524                 sc.add("{");
525                 if ("DOM".equals(field.getType())) {
526                     if (domAsXpp3) {
527                         sc.addIndented("writeDom( (Xpp3Dom) " + value + ", contentHandler, attributes );");
528                     } else {
529                         sc.addIndented("writeDom( (Element) " + value + ", contentHandler );");
530                     }
531 
532                     requiresDomSupport = true;
533                 } else {
534                     sc.indent();
535                     sc.add("contentHandler.startElement( NAMESPACE, \"" + fieldTagName + "\", \"" + fieldTagName
536                             + "\", attributes );");
537                     sc.add("writeText( " + getValue(field.getType(), value, xmlFieldMetadata) + ", contentHandler );");
538                     sc.add("contentHandler.endElement( NAMESPACE, \"" + fieldTagName + "\", \"" + fieldTagName
539                             + "\" );");
540                     sc.unindent();
541                 }
542                 sc.add("}");
543             }
544         }
545 
546         sc.add("contentHandler.endElement( NAMESPACE, tagName, tagName );");
547 
548         jClass.addMethod(marshall);
549     }
550 
551     private void createXpp3DomMethod(JClass jClass) {
552         jClass.addImport("org.codehaus.plexus.util.xml.Xpp3Dom");
553 
554         JMethod method = new JMethod("writeDom");
555         method.getModifiers().makePrivate();
556 
557         method.addParameter(new JParameter(new JType("Xpp3Dom"), "dom"));
558         method.addParameter(new JParameter(new JClass("ContentHandler"), "contentHandler"));
559         method.addParameter(new JParameter(new JClass("AttributesImpl"), "attributes"));
560 
561         method.addException(new JClass("SAXException"));
562 
563         JSourceCode sc = method.getSourceCode();
564 
565         sc.add("String[] attributeNames = dom.getAttributeNames();");
566         sc.add("if ( attributeNames != null && attributeNames.length > 0 )");
567         sc.add("{");
568         sc.indent();
569         sc.add("String attributeName;");
570         sc.add("String attributeValue;");
571         sc.add("for ( int i = 0; i < attributeNames.length; i++ )");
572         sc.add("{");
573         sc.indent();
574         sc.add("attributeName = attributeNames[i];");
575         sc.add("attributeValue = dom.getAttribute( attributeName );");
576         sc.add("attributes.addAttribute( NAMESPACE, attributeName, attributeName, \"CDATA\", attributeValue );");
577         sc.unindent();
578         sc.add("}");
579         sc.unindent();
580         sc.add("}");
581 
582         sc.add("contentHandler.startElement( NAMESPACE, dom.getName(), dom.getName(), attributes );");
583 
584         sc.add("if ( attributeNames != null && attributeNames.length > 0 )");
585         sc.add("{");
586         sc.addIndented("attributes.clear();");
587         sc.add("}");
588 
589         sc.add("Xpp3Dom[] children = dom.getChildren();");
590         sc.add("if ( children != null &&  children.length > 0 )");
591         sc.add("{");
592         sc.indent();
593         sc.add("for ( int i = 0; i < children.length; i++ )");
594         sc.add("{");
595         sc.addIndented("writeDom( children[i], contentHandler, attributes );");
596         sc.add("}");
597         sc.unindent();
598         sc.add("}");
599 
600         sc.add("String value = dom.getValue();");
601         sc.add("if ( value != null )");
602         sc.add("{");
603         sc.addIndented("writeText( value, contentHandler );");
604         sc.add("}");
605         sc.add("contentHandler.endElement( NAMESPACE, dom.getName(), dom.getName() );");
606 
607         jClass.addMethod(method);
608     }
609 
610     private void createWriteDomMethod(JClass jClass) {
611         jClass.addImport("org.w3c.dom.Element");
612         jClass.addImport("javax.xml.transform.Transformer");
613         jClass.addImport("javax.xml.transform.dom.DOMSource");
614         jClass.addImport("javax.xml.transform.sax.SAXResult");
615 
616         JMethod method = new JMethod("writeDom");
617         method.getModifiers().makePrivate();
618 
619         method.addParameter(new JParameter(new JType("Element"), "dom"));
620         method.addParameter(new JParameter(new JClass("ContentHandler"), "contentHandler"));
621 
622         method.addException(new JClass("SAXException"));
623 
624         JSourceCode sc = method.getSourceCode();
625 
626         sc.add("try");
627         sc.add("{");
628         sc.indent();
629         sc.add("Transformer transformer = transformerFactory.newTransformer();");
630         sc.add("DOMSource source = new DOMSource( dom );");
631         sc.add("SAXResult result = new SAXResult( contentHandler );");
632         sc.add("transformer.transform( source, result );");
633         sc.unindent();
634         sc.add("}");
635 
636         sc.add("catch ( TransformerException e )");
637         sc.add("{");
638         sc.addIndented("throw new SAXException( \"Impossible to convert DOM element, see nested exceptions.\", e );");
639         sc.add("}");
640 
641         jClass.addMethod(method);
642     }
643 }