View Javadoc

1   /* ==========================================================================
2    * Copyright 2005 Mevenide Team
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   *  Unless required by applicable law or agreed to in writing, software
11   *  distributed under the License is distributed on an "AS IS" BASIS,
12   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   *  See the License for the specific language governing permissions and
14   *  limitations under the License.
15   * =========================================================================
16   */
17  package org.codehaus.modello.plugin.jdom;
18  
19  import org.codehaus.modello.ModelloException;
20  import org.codehaus.modello.model.Model;
21  import org.codehaus.modello.model.ModelAssociation;
22  import org.codehaus.modello.model.ModelClass;
23  import org.codehaus.modello.model.ModelDefault;
24  import org.codehaus.modello.model.ModelField;
25  import org.codehaus.modello.plugin.java.javasource.JClass;
26  import org.codehaus.modello.plugin.java.javasource.JConstructor;
27  import org.codehaus.modello.plugin.java.javasource.JField;
28  import org.codehaus.modello.plugin.java.javasource.JMethod;
29  import org.codehaus.modello.plugin.java.javasource.JParameter;
30  import org.codehaus.modello.plugin.java.javasource.JSourceCode;
31  import org.codehaus.modello.plugin.java.javasource.JSourceWriter;
32  import org.codehaus.modello.plugin.java.javasource.JType;
33  import org.codehaus.modello.plugin.java.metadata.JavaFieldMetadata;
34  import org.codehaus.modello.plugins.xml.metadata.XmlAssociationMetadata;
35  import org.codehaus.modello.plugins.xml.metadata.XmlFieldMetadata;
36  
37  import java.io.IOException;
38  import java.util.ArrayList;
39  import java.util.List;
40  import java.util.Properties;
41  
42  /**
43   * @author mkleint@codehaus.org
44   */
45  public class JDOMWriterGenerator
46      extends AbstractJDOMGenerator
47  {
48  
49      private boolean requiresDomSupport;
50  
51      public void generate( Model model, Properties parameters )
52          throws ModelloException
53      {
54          initialize( model, parameters );
55  
56          requiresDomSupport = false;
57  
58          try
59          {
60              generateJDOMWriter();
61          }
62          catch ( IOException ex )
63          {
64              throw new ModelloException( "Exception while generating JDOM Writer.", ex );
65          }
66      }
67  
68      private void generateJDOMWriter()
69          throws ModelloException, IOException
70      {
71          Model objectModel = getModel();
72  
73          String packageName =
74              objectModel.getDefaultPackageName( isPackageWithVersion(), getGeneratedVersion() ) + ".io.jdom";
75  
76          String marshallerName = getFileName( "JDOMWriter" );
77  
78          JSourceWriter sourceWriter = newJSourceWriter( packageName, marshallerName );
79  
80          JClass jClass = new JClass( packageName + '.' + marshallerName );
81          initHeader( jClass );
82          suppressAllWarnings( objectModel, jClass );
83  
84          // -------------------------------------------------------------
85          // imports now
86          // -------------------------------------------------------------
87          jClass.addImport( "java.io.OutputStream" );
88          jClass.addImport( "java.io.OutputStreamWriter" );
89          jClass.addImport( "java.io.Writer" );
90          jClass.addImport( "java.text.DateFormat" );
91          jClass.addImport( "java.util.ArrayList" );
92          jClass.addImport( "java.util.Collection" );
93          jClass.addImport( "java.util.Iterator" );
94          jClass.addImport( "java.util.List" );
95          jClass.addImport( "java.util.ListIterator" );
96          jClass.addImport( "java.util.Locale" );
97          jClass.addImport( "java.util.Map" );
98          jClass.addImport( "java.util.Properties" );
99          jClass.addImport( "org.jdom.Content" );
100         jClass.addImport( "org.jdom.DefaultJDOMFactory" );
101         jClass.addImport( "org.jdom.Document" );
102         jClass.addImport( "org.jdom.Element" );
103         jClass.addImport( "org.jdom.Text" );
104         jClass.addImport( "org.jdom.output.Format" );
105         jClass.addImport( "org.jdom.output.XMLOutputter" );
106 
107         addModelImports( jClass, null );
108 
109         jClass.addField( new JField( new JClass( "DefaultJDOMFactory" ), "factory" ) );
110         jClass.addField( new JField( new JClass( "String" ), "lineSeparator" ) );
111 
112         createCounter( jClass );
113 
114         // constructor --
115         JConstructor constructor = jClass.createConstructor();
116         JSourceCode constCode = constructor.getSourceCode();
117         constCode.add( "factory = new DefaultJDOMFactory();" );
118         constCode.add( "lineSeparator = \"\\n\";" );
119 
120         String root = objectModel.getRoot( getGeneratedVersion() );
121 
122         ModelClass rootClass = objectModel.getClass( root, getGeneratedVersion() );
123 
124         String rootElement = resolveTagName( rootClass );
125 
126         // the public global write method..
127         jClass.addMethod( generateWriteModel( root, rootElement ) );
128         jClass.addMethod( generateWriteModel2( root, rootElement ) );
129         jClass.addMethod( generateWriteModel3( root, rootElement ) );
130         // the private utility classes;
131         jClass.addMethods( generateUtilityMethods() );
132 
133         writeAllClasses( objectModel, jClass, rootClass );
134 
135         if ( requiresDomSupport )
136         {
137             jClass.addImport( "org.codehaus.plexus.util.xml.Xpp3Dom" );
138             jClass.addMethods( generateDomMethods() );
139         }
140 
141         jClass.print( sourceWriter );
142 
143         sourceWriter.close();
144     }
145 
146     private void createCounter( final JClass jClass )
147         throws IllegalArgumentException
148     {
149         // inner counter class
150         JClass counter = jClass.createInnerClass( "Counter" );
151         counter.getModifiers().setStatic( true );
152 
153         JField fld = new JField( new JType( "int" ), "currentIndex" );
154         fld.setInitString( "0" );
155         counter.addField( fld );
156 
157         fld = new JField( new JType( "int" ), "level" );
158         counter.addField( fld );
159 
160         JConstructor constr =
161             counter.createConstructor( new JParameter[] { new JParameter( new JType( "int" ), "depthLevel" ) } );
162         constr.getSourceCode().append( "level = depthLevel;" );
163 
164         JMethod inc = new JMethod( "increaseCount" );
165         inc.getSourceCode().add( "currentIndex = currentIndex + 1;" );
166         counter.addMethod( inc );
167 
168         JMethod getter = new JMethod( "getCurrentIndex", new JType( "int" ), null );
169         getter.getSourceCode().add( "return currentIndex;" );
170         counter.addMethod( getter );
171 
172         getter = new JMethod( "getDepth", new JType( "int" ), null );
173         getter.getSourceCode().add( "return level;" );
174         counter.addMethod( getter );
175     }
176 
177     private JMethod generateWriteModel( String root, String rootElement )
178     {
179         String variableName = uncapitalise( root );
180 
181         JMethod marshall = new JMethod( "write" );
182 
183         marshall.addParameter( new JParameter( new JClass( root ), variableName ) );
184         marshall.addParameter( new JParameter( new JClass( "Document" ), "document" ) );
185         marshall.addParameter( new JParameter( new JClass( "OutputStream" ), "stream" ) );
186         marshall.addException( new JClass( "java.io.IOException" ) );
187 
188         marshall.getJDocComment().appendComment( "\n@deprecated" );
189 
190         JSourceCode sc = marshall.getSourceCode();
191         sc.add( "update" + root + "( " + variableName + ", \"" + rootElement
192                 + "\", new Counter( 0 ), document.getRootElement() );" );
193         sc.add( "XMLOutputter outputter = new XMLOutputter();" );
194         sc.add( "outputter.setFormat( Format.getPrettyFormat()" );
195         sc.add( "    .setIndent( \"    \" )" );
196         sc.add( "    .setLineSeparator( System.getProperty( \"line.separator\" ) ) );" );
197         sc.add( "outputter.output( document, stream );" );
198 
199         return marshall;
200 
201     }
202 
203     private JMethod generateWriteModel2( String root, String rootElement )
204     {
205         String variableName = uncapitalise( root );
206 
207         JMethod marshall = new JMethod( "write" );
208 
209         marshall.addParameter( new JParameter( new JClass( root ), variableName ) );
210         marshall.addParameter( new JParameter( new JClass( "Document" ), "document" ) );
211         marshall.addParameter( new JParameter( new JClass( "OutputStreamWriter" ), "writer" ) );
212         marshall.addException( new JClass( "java.io.IOException" ) );
213 
214         JSourceCode sc = marshall.getSourceCode();
215         sc.add( "Format format = Format.getRawFormat()" );
216         sc.add( "    .setEncoding( writer.getEncoding() )" );
217         sc.add( "    .setLineSeparator( System.getProperty( \"line.separator\" ) );" );
218         sc.add( "write( " + variableName + ", document, writer, format );" );
219         return marshall;
220 
221     }
222 
223     private JMethod generateWriteModel3( String root, String rootElement )
224     {
225         String variableName = uncapitalise( root );
226 
227         JMethod marshall = new JMethod( "write" );
228 
229         marshall.addParameter( new JParameter( new JClass( root ), variableName ) );
230         marshall.addParameter( new JParameter( new JClass( "Document" ), "document" ) );
231         marshall.addParameter( new JParameter( new JClass( "Writer" ), "writer" ) );
232         marshall.addParameter( new JParameter( new JClass( "Format" ), "jdomFormat" ) );
233         marshall.addException( new JClass( "java.io.IOException" ) );
234 
235         JSourceCode sc = marshall.getSourceCode();
236         sc.add( "update" + root + "( " + variableName + ", \"" + rootElement
237             + "\", new Counter( 0 ), document.getRootElement() );" );
238         sc.add( "XMLOutputter outputter = new XMLOutputter();" );
239         sc.add( "outputter.setFormat( jdomFormat );" );
240         sc.add( "outputter.output( document, writer );" );
241 
242         return marshall;
243 
244     }
245 
246     private JMethod[] generateUtilityMethods()
247     {
248         JMethod findRSElement = new JMethod( "findAndReplaceSimpleElement", new JClass( "Element" ), null );
249         findRSElement.addParameter( new JParameter( new JClass( "Counter" ), "counter" ) );
250         findRSElement.addParameter( new JParameter( new JClass( "Element" ), "parent" ) );
251         findRSElement.addParameter( new JParameter( new JClass( "String" ), "name" ) );
252         findRSElement.addParameter( new JParameter( new JClass( "String" ), "text" ) );
253         findRSElement.addParameter( new JParameter( new JClass( "String" ), "defaultValue" ) );
254 
255         findRSElement.getModifiers().makeProtected();
256         JSourceCode sc = findRSElement.getSourceCode();
257         sc.add( "if ( ( defaultValue != null ) && ( text != null ) && defaultValue.equals( text ) )" );
258         sc.add( "{" );
259         sc.indent();
260         sc.add( "Element element =  parent.getChild( name, parent.getNamespace() );" );
261         sc.add( "// if exist and is default value or if doesn't exist.. just keep the way it is.." );
262         sc.add( "if ( ( element != null && defaultValue.equals( element.getText() ) ) || element == null )" );
263         sc.add( "{" );
264         sc.addIndented( "return element;" );
265         sc.add( "}" );
266         sc.unindent();
267         sc.add( "}" );
268 
269         sc.add( "boolean shouldExist = ( text != null ) && ( text.trim().length() > 0 );" );
270         sc.add( "Element element = updateElement( counter, parent, name, shouldExist );" );
271         sc.add( "if ( shouldExist )" );
272         sc.add( "{" );
273         sc.addIndented( "element.setText( text );" );
274         sc.add( "}" );
275         sc.add( "return element;" );
276 
277         JMethod updateElement = new JMethod( "updateElement", new JClass( "Element" ), null );
278         updateElement.addParameter( new JParameter( new JClass( "Counter" ), "counter" ) );
279         updateElement.addParameter( new JParameter( new JClass( "Element" ), "parent" ) );
280         updateElement.addParameter( new JParameter( new JClass( "String" ), "name" ) );
281         updateElement.addParameter( new JParameter( new JType( "boolean" ), "shouldExist" ) );
282         updateElement.getModifiers().makeProtected();
283         sc = updateElement.getSourceCode();
284         sc.add( "Element element =  parent.getChild( name, parent.getNamespace() );" );
285 
286         sc.add( "if ( shouldExist )" );
287         sc.add( "{" );
288         sc.indent();
289         sc.add( "if ( element == null )" );
290         sc.add( "{" );
291         sc.indent();
292         sc.add( "element = factory.element( name, parent.getNamespace() );" );
293         sc.add( "insertAtPreferredLocation( parent, element, counter );" );
294         sc.unindent();
295         sc.add( "}" );
296         sc.add( "counter.increaseCount();" );
297         sc.unindent();
298         sc.add( "}" );
299 
300         sc.add( "else if ( element != null )" );
301         sc.add( "{" );
302         sc.indent();
303         sc.add( "int index = parent.indexOf( element );" );
304         sc.add( "if ( index > 0 )" );
305         sc.add( "{" );
306         sc.indent();
307         sc.add( "Content previous = parent.getContent( index - 1 );" );
308         sc.add( "if ( previous instanceof Text )" );
309         sc.add( "{" );
310         sc.indent();
311         sc.add( "Text txt = (Text) previous;" );
312         sc.add( "if ( txt.getTextTrim().length() == 0 )" );
313         sc.add( "{" );
314         sc.addIndented( "parent.removeContent( txt );" );
315         sc.add( "}" );
316         sc.unindent();
317         sc.add( "}" );
318         sc.unindent();
319         sc.add( "}" );
320         sc.add( "parent.removeContent( element );" );
321         sc.unindent();
322         sc.add( "}" );
323         sc.add( "return element;" );
324 
325         JMethod insAtPref = new JMethod( "insertAtPreferredLocation" );
326         insAtPref.addParameter( new JParameter( new JClass( "Element" ), "parent" ) );
327         insAtPref.addParameter( new JParameter( new JClass( "Element" ), "child" ) );
328         insAtPref.addParameter( new JParameter( new JClass( "Counter" ), "counter" ) );
329         insAtPref.getModifiers().makeProtected();
330         sc = insAtPref.getSourceCode();
331         sc.add( "int contentIndex = 0;" );
332         sc.add( "int elementCounter = 0;" );
333         sc.add( "Iterator it = parent.getContent().iterator();" );
334         sc.add( "Text lastText = null;" );
335         sc.add( "int offset = 0;" );
336         sc.add( "while ( it.hasNext() && elementCounter <= counter.getCurrentIndex() )" );
337         sc.add( "{" );
338         sc.indent();
339         sc.add( "Object next = it.next();" );
340         sc.add( "offset = offset + 1;" );
341         sc.add( "if ( next instanceof Element )" );
342         sc.add( "{" );
343         sc.indent();
344         sc.add( "elementCounter = elementCounter + 1;" );
345         sc.add( "contentIndex = contentIndex + offset;" );
346         sc.add( "offset = 0;" );
347         sc.unindent();
348         sc.add( "}" );
349         sc.add( "if ( next instanceof Text && it.hasNext() )" );
350         sc.add( "{" );
351         sc.addIndented( "lastText = (Text) next;" );
352         sc.add( "}" );
353         sc.unindent();
354         sc.add( "}" );
355 //        sc.add("if ( lastText == null )" );
356 //        sc.add( "{" );
357 //        sc.indent();
358 //        sc.add( "int index = parent.getParentElement().indexOf( parent );" );
359 //        sc.add( "if ( index > 0 ) ");
360 //        sc.add( "{" );
361 //        sc.indent();
362 //        sc.add( "Content cont = parent.getParentElement().getContent( index  - 1 );" );
363 //        sc.add( "if ( cont instanceof Text )" );
364 //        sc.add( "{" );
365 //        sc.addIndented( "lastText = (Text) cont;" );
366 //        sc.add( "}" );
367 //        sc.unindent();
368 //        sc.add( "}" );
369 //        sc.unindent();
370 //        sc.add( "}" );
371 
372         sc.add( "if ( lastText != null && lastText.getTextTrim().length() == 0 )" );
373         sc.add( "{" );
374         sc.addIndented( "lastText = (Text) lastText.clone();" );
375         sc.add( "}" );
376         sc.add( "else" );
377         sc.add( "{" );
378         sc.indent();
379         sc.add( "String starter = lineSeparator;" );
380         sc.add( "for ( int i = 0; i < counter.getDepth(); i++ )" );
381         sc.add( "{" );
382         sc.addIndented( "starter = starter + \"    \"; //TODO make settable?" );
383         sc.add( "}" );
384         sc.add( "lastText = factory.text( starter );" );
385         sc.unindent();
386         sc.add( "}" );
387         sc.add( "if ( parent.getContentSize() == 0 )" );
388         sc.add( "{" );
389         sc.indent();
390         sc.add( "Text finalText = (Text) lastText.clone();" );
391         sc.add(
392             "finalText.setText( finalText.getText().substring( 0, finalText.getText().length() - \"    \".length() ) );"
393             );
394         sc.add( "parent.addContent( contentIndex, finalText );" );
395         sc.unindent();
396         sc.add( "}" );
397         sc.add( "parent.addContent( contentIndex, child );" );
398         sc.add( "parent.addContent( contentIndex, lastText );" );
399 
400         JMethod findRSProps = new JMethod( "findAndReplaceProperties", new JClass( "Element" ), null );
401         findRSProps.addParameter( new JParameter( new JClass( "Counter" ), "counter" ) );
402         findRSProps.addParameter( new JParameter( new JClass( "Element" ), "parent" ) );
403         findRSProps.addParameter( new JParameter( new JClass( "String" ), "name" ) );
404         findRSProps.addParameter( new JParameter( new JClass( "Map" ), "props" ) );
405         findRSProps.getModifiers().makeProtected();
406         sc = findRSProps.getSourceCode();
407         sc.add( "boolean shouldExist = ( props != null ) && ! props.isEmpty();" );
408         sc.add( "Element element = updateElement( counter, parent, name, shouldExist );" );
409         sc.add( "if ( shouldExist )" );
410         sc.add( "{" );
411         sc.indent();
412         sc.add( "Iterator it = props.keySet().iterator();" );
413         sc.add( "Counter innerCounter = new Counter( counter.getDepth() + 1 );" );
414         sc.add( "while ( it.hasNext() )" );
415         sc.add( "{" );
416         sc.indent();
417         sc.add( "String key = (String) it.next();" );
418         sc.add( "findAndReplaceSimpleElement( innerCounter, element, key, (String) props.get( key ), null );" );
419         sc.unindent();
420         sc.add( "}" );
421         sc.add( "ArrayList lst = new ArrayList( props.keySet() );" );
422         sc.add( "it = element.getChildren().iterator();" );
423         sc.add( "while ( it.hasNext() )" );
424         sc.add( "{" );
425         sc.indent();
426         sc.add( "Element elem = (Element) it.next();" );
427         sc.add( "String key = elem.getName();" );
428         sc.add( "if ( !lst.contains( key ) )" );
429         sc.add( "{" );
430         sc.addIndented( "it.remove();" );
431         sc.add( "}" );
432         sc.unindent();
433         sc.add( "}" );
434         sc.unindent();
435         sc.add( "}" );
436         sc.add( "return element;" );
437 
438         JMethod findRSLists = new JMethod( "findAndReplaceSimpleLists", new JClass( "Element" ), null );
439         findRSLists.addParameter( new JParameter( new JClass( "Counter" ), "counter" ) );
440         findRSLists.addParameter( new JParameter( new JClass( "Element" ), "parent" ) );
441         findRSLists.addParameter( new JParameter( new JClass( "java.util.Collection" ), "list" ) );
442         findRSLists.addParameter( new JParameter( new JClass( "String" ), "parentName" ) );
443         findRSLists.addParameter( new JParameter( new JClass( "String" ), "childName" ) );
444         findRSLists.getModifiers().makeProtected();
445         sc = findRSLists.getSourceCode();
446         sc.add( "boolean shouldExist = ( list != null ) && ( list.size() > 0 );" );
447         sc.add( "Element element = updateElement( counter, parent, parentName, shouldExist );" );
448         sc.add( "if ( shouldExist )" );
449         sc.add( "{" );
450         sc.indent();
451         sc.add( "Iterator it = list.iterator();" );
452         sc.add( "Iterator elIt = element.getChildren( childName, element.getNamespace() ).iterator();" );
453         sc.add( "if ( ! elIt.hasNext() )" );
454         sc.add( "{" );
455         sc.addIndented( " elIt = null;" );
456         sc.add( "}" );
457         sc.add( "Counter innerCount = new Counter( counter.getDepth() + 1 );" );
458         sc.add( "while ( it.hasNext() )" );
459         sc.add( "{" );
460         sc.indent();
461         sc.add( "String value = (String) it.next();" );
462         sc.add( "Element el;" );
463         sc.add( "if ( elIt != null && elIt.hasNext() )" );
464         sc.add( "{" );
465         sc.indent();
466         sc.add( "el = (Element) elIt.next();" );
467         sc.add( "if ( ! elIt.hasNext() )" );
468         sc.add( "{" );
469         sc.addIndented( "elIt = null;" );
470         sc.add( "}" );
471         sc.unindent();
472         sc.add( "}" );
473         sc.add( "else" );
474         sc.add( "{" );
475         sc.indent();
476         sc.add( "el = factory.element( childName, element.getNamespace() );" );
477         sc.add( "insertAtPreferredLocation( element, el, innerCount );" );
478         sc.unindent();
479         sc.add( "}" );
480         sc.add( "el.setText( value );" );
481         sc.add( "innerCount.increaseCount();" );
482 
483         sc.unindent();
484         sc.add( "}" );
485         sc.add( "if ( elIt != null )" );
486         sc.add( "{" );
487         sc.indent();
488         sc.add( "while ( elIt.hasNext() )" );
489         sc.add( "{" );
490         sc.indent();
491         sc.add( "elIt.next();" );
492         sc.add( "elIt.remove();" );
493         sc.unindent();
494         sc.add( "}" );
495         sc.unindent();
496         sc.add( "}" );
497         sc.unindent();
498         sc.add( "}" );
499         sc.add( "return element;" );
500 
501         return new JMethod[] { findRSElement, updateElement, insAtPref, findRSProps, findRSLists };
502     }
503 
504     private JMethod[] generateDomMethods()
505     {
506         JMethod findRSDom = new JMethod( "findAndReplaceXpp3DOM", new JClass( "Element" ), null );
507         findRSDom.addParameter( new JParameter( new JClass( "Counter" ), "counter" ) );
508         findRSDom.addParameter( new JParameter( new JClass( "Element" ), "parent" ) );
509         findRSDom.addParameter( new JParameter( new JClass( "String" ), "name" ) );
510         findRSDom.addParameter( new JParameter( new JClass( "Xpp3Dom" ), "dom" ) );
511         findRSDom.getModifiers().makeProtected();
512         JSourceCode sc = findRSDom.getSourceCode();
513         sc.add( "boolean shouldExist = ( dom != null ) && ( dom.getChildCount() > 0 || dom.getValue() != null );" );
514         sc.add( "Element element = updateElement( counter, parent, name, shouldExist );" );
515         sc.add( "if ( shouldExist )" );
516         sc.add( "{" );
517         sc.addIndented( "replaceXpp3DOM( element, dom, new Counter( counter.getDepth() + 1 ) );" );
518         sc.add( "}" );
519         sc.add( "return element;" );
520 
521         JMethod findRSDom2 = new JMethod( "replaceXpp3DOM" );
522         findRSDom2.addParameter( new JParameter( new JClass( "Element" ), "parent" ) );
523         findRSDom2.addParameter( new JParameter( new JClass( "Xpp3Dom" ), "parentDom" ) );
524         findRSDom2.addParameter( new JParameter( new JClass( "Counter" ), "counter" ) );
525         findRSDom2.getModifiers().makeProtected();
526         sc = findRSDom2.getSourceCode();
527         sc.add( "if ( parentDom.getChildCount() > 0 )" );
528         sc.add( "{" );
529         sc.indent();
530         sc.add( "Xpp3Dom[] childs = parentDom.getChildren();" );
531         sc.add( "Collection domChilds = new ArrayList();" );
532         sc.add( "for ( int i = 0; i < childs.length; i++ )" );
533         sc.add( "{" );
534         sc.addIndented( "domChilds.add( childs[i] );" );
535         sc.add( "}" );
536         sc.add( "ListIterator it = parent.getChildren().listIterator();" );
537         sc.add( "while ( it.hasNext() )" );
538         sc.add( "{" );
539         sc.indent();
540         sc.add( "Element elem = (Element) it.next();" );
541         sc.add( "Iterator it2 = domChilds.iterator();" );
542         sc.add( "Xpp3Dom corrDom = null;" );
543         sc.add( "while ( it2.hasNext() )" );
544         sc.add( "{" );
545         sc.indent();
546         sc.add( "Xpp3Dom dm = (Xpp3Dom) it2.next();" );
547         sc.add( "if ( dm.getName().equals( elem.getName() ) )" );
548         sc.add( "{" );
549         sc.indent();
550         sc.add( "corrDom = dm;" );
551         sc.add( "break;" );
552         sc.unindent();
553         sc.add( "}" );
554         sc.unindent();
555         sc.add( "}" );
556         sc.add( "if ( corrDom != null )" );
557         sc.add( "{" );
558         sc.indent();
559         sc.add( "domChilds.remove( corrDom );" );
560         sc.add( "replaceXpp3DOM( elem, corrDom, new Counter( counter.getDepth() + 1 ) );" );
561         sc.add( "counter.increaseCount();" );
562         sc.unindent();
563         sc.add( "}" );
564         sc.add( "else" );
565         sc.add( "{" );
566         sc.addIndented( "it.remove();" );
567         sc.add( "}" );
568         sc.unindent();
569         sc.add( "}" );
570         sc.add( "Iterator it2 = domChilds.iterator();" );
571         sc.add( "while ( it2.hasNext() )" );
572         sc.add( "{" );
573         sc.indent();
574         sc.add( "Xpp3Dom dm = (Xpp3Dom) it2.next();" );
575         sc.add( "Element elem = factory.element( dm.getName(), parent.getNamespace() );" );
576         sc.add( "insertAtPreferredLocation( parent, elem, counter );" );
577         sc.add( "counter.increaseCount();" );
578         sc.add( "replaceXpp3DOM( elem, dm, new Counter( counter.getDepth() + 1 ) );" );
579         sc.unindent();
580         sc.add( "}" );
581         sc.unindent();
582         sc.add( "}" );
583         sc.add( " else if ( parentDom.getValue() != null )" );
584         sc.add( "{" );
585         sc.addIndented( "parent.setText( parentDom.getValue() );" );
586         sc.add( "}" );
587 
588         return new JMethod[] { findRSDom, findRSDom2 };
589     }
590 
591     private void writeAllClasses( Model objectModel, JClass jClass, ModelClass rootClass )
592         throws ModelloException
593     {
594         List<ModelClass> alwaysExistingElements = new ArrayList<ModelClass>();
595         alwaysExistingElements.add( rootClass );
596 
597         for ( ModelClass clazz : getClasses( objectModel ) )
598         {
599             updateClass( clazz, jClass, alwaysExistingElements );
600         }
601     }
602 
603     private void updateClass( ModelClass clazz, JClass jClass, List<ModelClass> alwaysExisting )
604         throws ModelloException
605     {
606         String className = clazz.getName();
607 
608         String capClassName = capitalise( className );
609 
610         String uncapClassName = uncapitalise( className );
611 
612         JMethod marshall = new JMethod( "update" + capClassName );
613         marshall.addParameter( new JParameter( new JClass( className ), uncapClassName ) );
614         marshall.addParameter( new JParameter( new JClass( "String" ), "xmlTag" ) );
615         marshall.addParameter( new JParameter( new JClass( "Counter" ), "counter" ) );
616         marshall.addParameter( new JParameter( new JClass( "Element" ), "element" ) );
617         marshall.getModifiers().makeProtected();
618 
619         JSourceCode sc = marshall.getSourceCode();
620         boolean shouldExist = alwaysExisting.contains( clazz );
621         if ( shouldExist )
622         {
623             sc.add( "Element root = element;" );
624         }
625         else
626         {
627             sc.add( "boolean shouldExist = ( " + uncapClassName + " != null );" );
628             sc.add( "Element root = updateElement( counter, element, xmlTag, shouldExist );" );
629             sc.add( "if ( shouldExist )" );
630             sc.add( "{" );
631             sc.indent();
632         }
633         sc.add( "Counter innerCount = new Counter( counter.getDepth() + 1 );" );
634 
635         List<ModelField> modelFields = getFieldsForXml( clazz, getGeneratedVersion() );
636 
637         for ( ModelField field : modelFields )
638         {
639             XmlFieldMetadata xmlFieldMetadata = (XmlFieldMetadata) field.getMetadata( XmlFieldMetadata.ID );
640             JavaFieldMetadata javaFieldMetadata = (JavaFieldMetadata) field.getMetadata( JavaFieldMetadata.ID );
641 
642             String fieldTagName = resolveTagName( field, xmlFieldMetadata );
643 
644             String type = field.getType();
645             String value = uncapClassName + '.' + getPrefix( javaFieldMetadata ) + capitalise( field.getName() ) + "()";
646             if ( xmlFieldMetadata.isAttribute() )
647             {
648                 continue;
649             }
650             if ( field instanceof ModelAssociation )
651             {
652                 ModelAssociation association = (ModelAssociation) field;
653                 ModelClass toClass = association.getToClass();
654                 if ( association.isOneMultiplicity() )
655                 {
656                     sc.add( "update" + capitalise( field.getType() ) + "( " + value + ", \"" + fieldTagName
657                         + "\", innerCount, root );" );
658                 }
659                 else
660                 {
661                     //MANY_MULTIPLICITY
662 
663                     XmlAssociationMetadata xmlAssociationMetadata =
664                         (XmlAssociationMetadata) association.getAssociationMetadata( XmlAssociationMetadata.ID );
665 
666                     //String valuesTagName = resolveTagName( fieldTagName, xmlAssociationMetadata );
667 //
668 //                    type = association.getType();
669 //                    String toType = association.getTo();
670 //
671                     if ( ModelDefault.LIST.equals( type ) || ModelDefault.SET.equals( type ) )
672                     {
673 //                        type = association.getType();
674                         String toType = association.getTo();
675                         if ( toClass != null )
676                         {
677                             if ( xmlAssociationMetadata.isWrappedItems() )
678                             {
679                                 sc.add( "iterate" + capitalise( toType ) + "( innerCount, root, " + value + ",\""
680                                     + field.getName() + "\",\"" + singular( fieldTagName ) + "\" );" );
681                                 createIterateMethod( field.getName(), toClass, singular( fieldTagName ), jClass );
682                             }
683                             else
684                             {
685                                 //assume flat..
686                                 sc.add( "iterate2" + capitalise( toType ) + "( innerCount, root, " + value + ", \""
687                                         + singular( fieldTagName ) + "\" );" );
688                                 createIterateMethod2( field.getName(), toClass, singular( fieldTagName ), jClass );
689                             }
690                             alwaysExisting.add( toClass );
691                         }
692                         else
693                         {
694                             //list of strings?
695                             sc.add( "findAndReplaceSimpleLists( innerCount, root, " + value + ", \"" + fieldTagName
696                                 + "\", \"" + singular( fieldTagName ) + "\" );" );
697                         }
698                     }
699                     else
700                     {
701                         //Map or Properties
702                         sc.add(
703                             "findAndReplaceProperties( innerCount, root,  \"" + fieldTagName + "\", " + value + " );" );
704                     }
705                 }
706             }
707             else
708             {
709                 if ( "DOM".equals( field.getType() ) )
710                 {
711                     sc.add(
712                         "findAndReplaceXpp3DOM( innerCount, root, \"" + fieldTagName + "\", (Xpp3Dom) " + value + " );" );
713 
714                     requiresDomSupport = true;
715                 }
716                 else
717                 {
718                     sc.add( "findAndReplaceSimpleElement( innerCount, root, \"" + fieldTagName + "\", "
719                         + getJdomValueChecker( type, value, field ) + getValue( type, value, xmlFieldMetadata ) + ", "
720                         + ( field.getDefaultValue() != null ? ( "\"" + field.getDefaultValue() + "\"" ) : "null" )
721                         + " );" );
722                 }
723             }
724         }
725         if ( !shouldExist )
726         {
727             sc.unindent();
728             sc.add( "}" );
729         }
730         jClass.addMethod( marshall );
731     }
732 
733     private String getJdomValueChecker( String type, String value, ModelField field )
734         throws ModelloException
735     {
736         if ( "boolean".equals( type ) || "double".equals( type ) || "float".equals( type ) || "int".equals( type )
737             || "long".equals( type ) || "short".equals( type ) || "byte".equals( type ) || "char".equals( type ) )
738         {
739             return value + " == " + getJavaDefaultValue( field ) + " ? null : ";
740         }
741         else if ( ModelDefault.LIST.equals( type ) || ModelDefault.SET.equals( type )
742             || ModelDefault.MAP.equals( type ) || ModelDefault.PROPERTIES.equals( type ) )
743         {
744             return value + " == null || " + value + ".size() == 0 ? null : ";
745 //        } else if ( "String".equals( type ) && field.getDefaultValue() != null ) {
746 //            return "" + value + " == null || " + value + ".equals( \"" + field.getDefaultValue() + "\" ) ? null : ";
747         }
748         else if ( "Date".equals( type ) && field.getDefaultValue() != null )
749         {
750             return "" + value + " == null || " + value + ".equals( " + getJavaDefaultValue( field ) + " ) ? null : ";
751         }
752         else
753         {
754             return value + " == null ? null : ";
755         }
756     }
757 
758     private void createIterateMethod( String field, ModelClass toClass, String childFieldTagName, JClass jClass )
759     {
760         if ( jClass.getMethod( "iterate" + capitalise( toClass.getName() ), 0 ) != null )
761         {
762 //            System.out.println("method iterate" + capitalise(field) + " already exists");
763             return;
764         }
765         JMethod toReturn = new JMethod( "iterate" + capitalise( toClass.getName() ) );
766         toReturn.addParameter( new JParameter( new JClass( "Counter" ), "counter" ) );
767         toReturn.addParameter( new JParameter( new JClass( "Element" ), "parent" ) );
768         toReturn.addParameter( new JParameter( new JClass( "java.util.Collection" ), "list" ) );
769         toReturn.addParameter( new JParameter( new JClass( "java.lang.String" ), "parentTag" ) );
770         toReturn.addParameter( new JParameter( new JClass( "java.lang.String" ), "childTag" ) );
771         toReturn.getModifiers().makeProtected();
772         JSourceCode sc = toReturn.getSourceCode();
773         sc.add( "boolean shouldExist = ( list != null ) && ( list.size() > 0 );" );
774         sc.add( "Element element = updateElement( counter, parent, parentTag, shouldExist );" );
775         sc.add( "if ( shouldExist )" );
776         sc.add( "{" );
777         sc.indent();
778         sc.add( "Iterator it = list.iterator();" );
779         sc.add( "Iterator elIt = element.getChildren( childTag, element.getNamespace() ).iterator();" );
780         sc.add( "if ( !elIt.hasNext() )" );
781         sc.add( "{" );
782         sc.addIndented( "elIt = null;" );
783         sc.add( "}" );
784         sc.add( "Counter innerCount = new Counter( counter.getDepth() + 1 );" );
785         sc.add( "while ( it.hasNext() )" );
786         sc.add( "{" );
787         sc.indent();
788         sc.add( toClass.getName() + " value = (" + toClass.getName() + ") it.next();" );
789         sc.add( "Element el;" );
790         sc.add( "if ( elIt != null && elIt.hasNext() )" );
791         sc.add( "{" );
792         sc.indent();
793         sc.add( "el = (Element) elIt.next();" );
794         sc.add( "if ( ! elIt.hasNext() )" );
795         sc.add( "{" );
796         sc.addIndented( " elIt = null;" );
797         sc.add( "}" );
798         sc.unindent();
799         sc.add( "}" );
800         sc.add( "else" );
801         sc.add( "{" );
802         sc.indent();
803         sc.add( "el = factory.element( childTag, element.getNamespace() );" );
804         sc.add( "insertAtPreferredLocation( element, el, innerCount );" );
805         sc.unindent();
806         sc.add( "}" );
807         sc.add( "update" + toClass.getName() + "( value, childTag, innerCount, el );" );
808         sc.add( "innerCount.increaseCount();" );
809         sc.unindent();
810         sc.add( "}" );
811         sc.add( "if ( elIt != null )" );
812         sc.add( "{" );
813         sc.indent();
814         sc.add( "while ( elIt.hasNext() )" );
815         sc.add( "{" );
816         sc.indent();
817         sc.add( "elIt.next();" );
818         sc.add( "elIt.remove();" );
819         sc.unindent();
820         sc.add( "}" );
821         sc.unindent();
822         sc.add( "}" );
823         sc.unindent();
824         sc.add( "}" );
825 
826         jClass.addMethod( toReturn );
827     }
828 
829     private void createIterateMethod2( String field, ModelClass toClass, String childFieldTagName, JClass jClass )
830     {
831         if ( jClass.getMethod( "iterate2" + capitalise( toClass.getName() ), 0 ) != null )
832         {
833 //            System.out.println("method iterate" + capitalise(field) + " already exists");
834             return;
835         }
836         JMethod toReturn = new JMethod( "iterate2" + capitalise( toClass.getName() ) );
837         toReturn.addParameter( new JParameter( new JClass( "Counter" ), "counter" ) );
838         toReturn.addParameter( new JParameter( new JClass( "Element" ), "parent" ) );
839         toReturn.addParameter( new JParameter( new JClass( "java.util.Collection" ), "list" ) );
840         toReturn.addParameter( new JParameter( new JClass( "java.lang.String" ), "childTag" ) );
841         toReturn.getModifiers().makeProtected();
842         JSourceCode sc = toReturn.getSourceCode();
843         sc.add( "Iterator it = list.iterator();" );
844         sc.add( "Iterator elIt = parent.getChildren( childTag, parent.getNamespace() ).iterator();" );
845         sc.add( "if ( !elIt.hasNext() )" );
846         sc.add( "{" );
847         sc.addIndented( "elIt = null;" );
848         sc.add( "}" );
849         sc.add( "Counter innerCount = new Counter( counter.getDepth() + 1 );" );
850         sc.add( "while ( it.hasNext() )" );
851         sc.add( "{" );
852         sc.indent();
853         sc.add( toClass.getName() + " value = (" + toClass.getName() + ") it.next();" );
854         sc.add( "Element el;" );
855         sc.add( "if ( elIt != null && elIt.hasNext() )" );
856         sc.add( "{" );
857         sc.indent();
858         sc.add( "el = (Element) elIt.next();" );
859         sc.add( "if ( ! elIt.hasNext() )" );
860         sc.add( "{" );
861         sc.addIndented( "elIt = null;" );
862         sc.add( "}" );
863         sc.unindent();
864         sc.add( "}" );
865         sc.add( "else" );
866         sc.add( "{" );
867         sc.indent();
868         sc.add( "el = factory.element( childTag, parent.getNamespace() );" );
869         sc.add( "insertAtPreferredLocation( parent, el, innerCount );" );
870         sc.unindent();
871         sc.add( "}" );
872         sc.add( "update" + toClass.getName() + "( value, childTag, innerCount, el );" );
873         sc.add( "innerCount.increaseCount();" );
874         sc.unindent();
875         sc.add( "}" );
876         sc.add( "if ( elIt != null )" );
877         sc.add( "{" );
878         sc.indent();
879         sc.add( "while ( elIt.hasNext() )" );
880         sc.add( "{" );
881         sc.indent();
882         sc.add( "elIt.next();" );
883         sc.add( "elIt.remove();" );
884         sc.unindent();
885         sc.add( "}" );
886         sc.unindent();
887         sc.add( "}" );
888 
889         jClass.addMethod( toReturn );
890     }
891 
892 
893 }