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