View Javadoc
1   // =================== DO NOT EDIT THIS FILE ====================
2   // Generated by Modello 1.9.1,
3   // any modifications will be overwritten.
4   // ==============================================================
5   
6   package org.apache.maven.doxia.site.decoration.io.xpp3;
7   
8     //---------------------------------/
9    //- Imported classes and packages -/
10  //---------------------------------/
11  
12  import java.io.IOException;
13  import java.io.InputStream;
14  import java.io.Reader;
15  import java.text.DateFormat;
16  import org.apache.maven.doxia.site.decoration.Banner;
17  import org.apache.maven.doxia.site.decoration.Body;
18  import org.apache.maven.doxia.site.decoration.DecorationModel;
19  import org.apache.maven.doxia.site.decoration.LinkItem;
20  import org.apache.maven.doxia.site.decoration.Logo;
21  import org.apache.maven.doxia.site.decoration.Menu;
22  import org.apache.maven.doxia.site.decoration.MenuItem;
23  import org.apache.maven.doxia.site.decoration.PublishDate;
24  import org.apache.maven.doxia.site.decoration.Skin;
25  import org.apache.maven.doxia.site.decoration.Version;
26  import org.codehaus.plexus.util.ReaderFactory;
27  import org.codehaus.plexus.util.xml.pull.EntityReplacementMap;
28  import org.codehaus.plexus.util.xml.pull.MXParser;
29  import org.codehaus.plexus.util.xml.pull.XmlPullParser;
30  import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
31  
32  /**
33   * Class DecorationXpp3Reader.
34   * 
35   * @version $Revision$ $Date$
36   */
37  @SuppressWarnings( "all" )
38  public class DecorationXpp3Reader
39  {
40  
41        //--------------------------/
42       //- Class/Member Variables -/
43      //--------------------------/
44  
45      /**
46       * If set the parser will be loaded with all single characters
47       * from the XHTML specification.
48       * The entities used:
49       * <ul>
50       * <li>http://www.w3.org/TR/xhtml1/DTD/xhtml-lat1.ent</li>;
51       * <li>http://www.w3.org/TR/xhtml1/DTD/xhtml-special.ent</li>;
52       * <li>http://www.w3.org/TR/xhtml1/DTD/xhtml-symbol.ent</li>;
53       * </ul>
54       */
55      private boolean addDefaultEntities = true;
56  
57      /**
58       * Field contentTransformer.
59       */
60      public final ContentTransformer contentTransformer;
61  
62  
63        //----------------/
64       //- Constructors -/
65      //----------------/
66  
67      public DecorationXpp3Reader()
68      {
69          this( new ContentTransformer()
70          {
71              public String transform( String source, String fieldName )
72              {
73                  return source;
74              }
75          } );
76      } //-- org.apache.maven.doxia.site.decoration.io.xpp3.DecorationXpp3Reader()
77  
78      public DecorationXpp3Reader(ContentTransformer contentTransformer)
79      {
80          this.contentTransformer = contentTransformer;
81      } //-- org.apache.maven.doxia.site.decoration.io.xpp3.DecorationXpp3Reader(ContentTransformer)
82  
83  
84        //-----------/
85       //- Methods -/
86      //-----------/
87  
88      /**
89       * Method checkFieldWithDuplicate.
90       * 
91       * @param parser
92       * @param parsed
93       * @param alias
94       * @param tagName
95       * @throws XmlPullParserException
96       * @return boolean
97       */
98      private boolean checkFieldWithDuplicate( XmlPullParser parser, String tagName, String alias, java.util.Set parsed )
99          throws XmlPullParserException
100     {
101         if ( !( parser.getName().equals( tagName ) || parser.getName().equals( alias ) ) )
102         {
103             return false;
104         }
105         if ( !parsed.add( tagName ) )
106         {
107             throw new XmlPullParserException( "Duplicated tag: '" + tagName + "'", parser, null );
108         }
109         return true;
110     } //-- boolean checkFieldWithDuplicate( XmlPullParser, String, String, java.util.Set )
111 
112     /**
113      * Method checkUnknownAttribute.
114      * 
115      * @param parser
116      * @param strict
117      * @param tagName
118      * @param attribute
119      * @throws XmlPullParserException
120      * @throws IOException
121      */
122     private void checkUnknownAttribute( XmlPullParser parser, String attribute, String tagName, boolean strict )
123         throws XmlPullParserException, IOException
124     {
125         // strictXmlAttributes = true for model: if strict == true, not only elements are checked but attributes too
126         if ( strict )
127         {
128             throw new XmlPullParserException( "Unknown attribute '" + attribute + "' for tag '" + tagName + "'", parser, null );
129         }
130     } //-- void checkUnknownAttribute( XmlPullParser, String, String, boolean )
131 
132     /**
133      * Method checkUnknownElement.
134      * 
135      * @param parser
136      * @param strict
137      * @throws XmlPullParserException
138      * @throws IOException
139      */
140     private void checkUnknownElement( XmlPullParser parser, boolean strict )
141         throws XmlPullParserException, IOException
142     {
143         if ( strict )
144         {
145             throw new XmlPullParserException( "Unrecognised tag: '" + parser.getName() + "'", parser, null );
146         }
147 
148         for ( int unrecognizedTagCount = 1; unrecognizedTagCount > 0; )
149         {
150             int eventType = parser.next();
151             if ( eventType == XmlPullParser.START_TAG )
152             {
153                 unrecognizedTagCount++;
154             }
155             else if ( eventType == XmlPullParser.END_TAG )
156             {
157                 unrecognizedTagCount--;
158             }
159         }
160     } //-- void checkUnknownElement( XmlPullParser, boolean )
161 
162     /**
163      * Returns the state of the "add default entities" flag.
164      * 
165      * @return boolean
166      */
167     public boolean getAddDefaultEntities()
168     {
169         return addDefaultEntities;
170     } //-- boolean getAddDefaultEntities()
171 
172     /**
173      * Method getBooleanValue.
174      * 
175      * @param s
176      * @param parser
177      * @param attribute
178      * @throws XmlPullParserException
179      * @return boolean
180      */
181     private boolean getBooleanValue( String s, String attribute, XmlPullParser parser )
182         throws XmlPullParserException
183     {
184         return getBooleanValue( s, attribute, parser, null );
185     } //-- boolean getBooleanValue( String, String, XmlPullParser )
186 
187     /**
188      * Method getBooleanValue.
189      * 
190      * @param s
191      * @param defaultValue
192      * @param parser
193      * @param attribute
194      * @throws XmlPullParserException
195      * @return boolean
196      */
197     private boolean getBooleanValue( String s, String attribute, XmlPullParser parser, String defaultValue )
198         throws XmlPullParserException
199     {
200         if ( s != null && s.length() != 0 )
201         {
202             return Boolean.valueOf( s ).booleanValue();
203         }
204         if ( defaultValue != null )
205         {
206             return Boolean.valueOf( defaultValue ).booleanValue();
207         }
208         return false;
209     } //-- boolean getBooleanValue( String, String, XmlPullParser, String )
210 
211     /**
212      * Method getByteValue.
213      * 
214      * @param s
215      * @param strict
216      * @param parser
217      * @param attribute
218      * @throws XmlPullParserException
219      * @return byte
220      */
221     private byte getByteValue( String s, String attribute, XmlPullParser parser, boolean strict )
222         throws XmlPullParserException
223     {
224         if ( s != null )
225         {
226             try
227             {
228                 return Byte.valueOf( s ).byteValue();
229             }
230             catch ( NumberFormatException nfe )
231             {
232                 if ( strict )
233                 {
234                     throw new XmlPullParserException( "Unable to parse element '" + attribute + "', must be a byte", parser, nfe );
235                 }
236             }
237         }
238         return 0;
239     } //-- byte getByteValue( String, String, XmlPullParser, boolean )
240 
241     /**
242      * Method getCharacterValue.
243      * 
244      * @param s
245      * @param parser
246      * @param attribute
247      * @throws XmlPullParserException
248      * @return char
249      */
250     private char getCharacterValue( String s, String attribute, XmlPullParser parser )
251         throws XmlPullParserException
252     {
253         if ( s != null )
254         {
255             return s.charAt( 0 );
256         }
257         return 0;
258     } //-- char getCharacterValue( String, String, XmlPullParser )
259 
260     /**
261      * Method getDateValue.
262      * 
263      * @param s
264      * @param parser
265      * @param attribute
266      * @throws XmlPullParserException
267      * @return Date
268      */
269     private java.util.Date getDateValue( String s, String attribute, XmlPullParser parser )
270         throws XmlPullParserException
271     {
272         return getDateValue( s, attribute, null, parser );
273     } //-- java.util.Date getDateValue( String, String, XmlPullParser )
274 
275     /**
276      * Method getDateValue.
277      * 
278      * @param s
279      * @param parser
280      * @param dateFormat
281      * @param attribute
282      * @throws XmlPullParserException
283      * @return Date
284      */
285     private java.util.Date getDateValue( String s, String attribute, String dateFormat, XmlPullParser parser )
286         throws XmlPullParserException
287     {
288         if ( s != null )
289         {
290             String effectiveDateFormat = dateFormat;
291             if ( dateFormat == null )
292             {
293                 effectiveDateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS";
294             }
295             if ( "long".equals( effectiveDateFormat ) )
296             {
297                 try
298                 {
299                     return new java.util.Date( Long.parseLong( s ) );
300                 }
301                 catch ( NumberFormatException e )
302                 {
303                     throw new XmlPullParserException( e.getMessage(), parser, e );
304                 }
305             }
306             else
307             {
308                 try
309                 {
310                     DateFormat dateParser = new java.text.SimpleDateFormat( effectiveDateFormat, java.util.Locale.US );
311                     return dateParser.parse( s );
312                 }
313                 catch ( java.text.ParseException e )
314                 {
315                     throw new XmlPullParserException( e.getMessage(), parser, e );
316                 }
317             }
318         }
319         return null;
320     } //-- java.util.Date getDateValue( String, String, String, XmlPullParser )
321 
322     /**
323      * Method getDoubleValue.
324      * 
325      * @param s
326      * @param strict
327      * @param parser
328      * @param attribute
329      * @throws XmlPullParserException
330      * @return double
331      */
332     private double getDoubleValue( String s, String attribute, XmlPullParser parser, boolean strict )
333         throws XmlPullParserException
334     {
335         if ( s != null )
336         {
337             try
338             {
339                 return Double.valueOf( s ).doubleValue();
340             }
341             catch ( NumberFormatException nfe )
342             {
343                 if ( strict )
344                 {
345                     throw new XmlPullParserException( "Unable to parse element '" + attribute + "', must be a floating point number", parser, nfe );
346                 }
347             }
348         }
349         return 0;
350     } //-- double getDoubleValue( String, String, XmlPullParser, boolean )
351 
352     /**
353      * Method getFloatValue.
354      * 
355      * @param s
356      * @param strict
357      * @param parser
358      * @param attribute
359      * @throws XmlPullParserException
360      * @return float
361      */
362     private float getFloatValue( String s, String attribute, XmlPullParser parser, boolean strict )
363         throws XmlPullParserException
364     {
365         if ( s != null )
366         {
367             try
368             {
369                 return Float.valueOf( s ).floatValue();
370             }
371             catch ( NumberFormatException nfe )
372             {
373                 if ( strict )
374                 {
375                     throw new XmlPullParserException( "Unable to parse element '" + attribute + "', must be a floating point number", parser, nfe );
376                 }
377             }
378         }
379         return 0;
380     } //-- float getFloatValue( String, String, XmlPullParser, boolean )
381 
382     /**
383      * Method getIntegerValue.
384      * 
385      * @param s
386      * @param strict
387      * @param parser
388      * @param attribute
389      * @throws XmlPullParserException
390      * @return int
391      */
392     private int getIntegerValue( String s, String attribute, XmlPullParser parser, boolean strict )
393         throws XmlPullParserException
394     {
395         if ( s != null )
396         {
397             try
398             {
399                 return Integer.valueOf( s ).intValue();
400             }
401             catch ( NumberFormatException nfe )
402             {
403                 if ( strict )
404                 {
405                     throw new XmlPullParserException( "Unable to parse element '" + attribute + "', must be an integer", parser, nfe );
406                 }
407             }
408         }
409         return 0;
410     } //-- int getIntegerValue( String, String, XmlPullParser, boolean )
411 
412     /**
413      * Method getLongValue.
414      * 
415      * @param s
416      * @param strict
417      * @param parser
418      * @param attribute
419      * @throws XmlPullParserException
420      * @return long
421      */
422     private long getLongValue( String s, String attribute, XmlPullParser parser, boolean strict )
423         throws XmlPullParserException
424     {
425         if ( s != null )
426         {
427             try
428             {
429                 return Long.valueOf( s ).longValue();
430             }
431             catch ( NumberFormatException nfe )
432             {
433                 if ( strict )
434                 {
435                     throw new XmlPullParserException( "Unable to parse element '" + attribute + "', must be a long integer", parser, nfe );
436                 }
437             }
438         }
439         return 0;
440     } //-- long getLongValue( String, String, XmlPullParser, boolean )
441 
442     /**
443      * Method getRequiredAttributeValue.
444      * 
445      * @param s
446      * @param strict
447      * @param parser
448      * @param attribute
449      * @throws XmlPullParserException
450      * @return String
451      */
452     private String getRequiredAttributeValue( String s, String attribute, XmlPullParser parser, boolean strict )
453         throws XmlPullParserException
454     {
455         if ( s == null )
456         {
457             if ( strict )
458             {
459                 throw new XmlPullParserException( "Missing required value for attribute '" + attribute + "'", parser, null );
460             }
461         }
462         return s;
463     } //-- String getRequiredAttributeValue( String, String, XmlPullParser, boolean )
464 
465     /**
466      * Method getShortValue.
467      * 
468      * @param s
469      * @param strict
470      * @param parser
471      * @param attribute
472      * @throws XmlPullParserException
473      * @return short
474      */
475     private short getShortValue( String s, String attribute, XmlPullParser parser, boolean strict )
476         throws XmlPullParserException
477     {
478         if ( s != null )
479         {
480             try
481             {
482                 return Short.valueOf( s ).shortValue();
483             }
484             catch ( NumberFormatException nfe )
485             {
486                 if ( strict )
487                 {
488                     throw new XmlPullParserException( "Unable to parse element '" + attribute + "', must be a short integer", parser, nfe );
489                 }
490             }
491         }
492         return 0;
493     } //-- short getShortValue( String, String, XmlPullParser, boolean )
494 
495     /**
496      * Method getTrimmedValue.
497      * 
498      * @param s
499      * @return String
500      */
501     private String getTrimmedValue( String s )
502     {
503         if ( s != null )
504         {
505             s = s.trim();
506         }
507         return s;
508     } //-- String getTrimmedValue( String )
509 
510     /**
511      * Method interpolatedTrimmed.
512      * 
513      * @param value
514      * @param context
515      * @return String
516      */
517     private String interpolatedTrimmed( String value, String context )
518     {
519         return getTrimmedValue( contentTransformer.transform( value, context ) );
520     } //-- String interpolatedTrimmed( String, String )
521 
522     /**
523      * Method nextTag.
524      * 
525      * @param parser
526      * @throws IOException
527      * @throws XmlPullParserException
528      * @return int
529      */
530     private int nextTag( XmlPullParser parser )
531         throws IOException, XmlPullParserException
532     {
533         int eventType = parser.next();
534         if ( eventType == XmlPullParser.TEXT )
535         {
536             eventType = parser.next();
537         }
538         if ( eventType != XmlPullParser.START_TAG && eventType != XmlPullParser.END_TAG )
539         {
540             throw new XmlPullParserException( "expected START_TAG or END_TAG not " + XmlPullParser.TYPES[eventType], parser, null );
541         }
542         return eventType;
543     } //-- int nextTag( XmlPullParser )
544 
545     /**
546      * @see ReaderFactory#newXmlReader
547      * 
548      * @param reader
549      * @param strict
550      * @throws IOException
551      * @throws XmlPullParserException
552      * @return DecorationModel
553      */
554     public DecorationModel read( Reader reader, boolean strict )
555         throws IOException, XmlPullParserException
556     {
557         XmlPullParser parser = addDefaultEntities ? new MXParser(EntityReplacementMap.defaultEntityReplacementMap) : new MXParser( );
558 
559         parser.setInput( reader );
560 
561 
562         return read( parser, strict );
563     } //-- DecorationModel read( Reader, boolean )
564 
565     /**
566      * @see ReaderFactory#newXmlReader
567      * 
568      * @param reader
569      * @throws IOException
570      * @throws XmlPullParserException
571      * @return DecorationModel
572      */
573     public DecorationModel read( Reader reader )
574         throws IOException, XmlPullParserException
575     {
576         return read( reader, true );
577     } //-- DecorationModel read( Reader )
578 
579     /**
580      * Method read.
581      * 
582      * @param in
583      * @param strict
584      * @throws IOException
585      * @throws XmlPullParserException
586      * @return DecorationModel
587      */
588     public DecorationModel read( InputStream in, boolean strict )
589         throws IOException, XmlPullParserException
590     {
591         return read( ReaderFactory.newXmlReader( in ), strict );
592     } //-- DecorationModel read( InputStream, boolean )
593 
594     /**
595      * Method read.
596      * 
597      * @param in
598      * @throws IOException
599      * @throws XmlPullParserException
600      * @return DecorationModel
601      */
602     public DecorationModel read( InputStream in )
603         throws IOException, XmlPullParserException
604     {
605         return read( ReaderFactory.newXmlReader( in ) );
606     } //-- DecorationModel read( InputStream )
607 
608     /**
609      * Method parseBanner.
610      * 
611      * @param parser
612      * @param strict
613      * @throws IOException
614      * @throws XmlPullParserException
615      * @return Banner
616      */
617     private Banner parseBanner( XmlPullParser parser, boolean strict )
618         throws IOException, XmlPullParserException
619     {
620         String tagName = parser.getName();
621         Banner banner = new Banner();
622         for ( int i = parser.getAttributeCount() - 1; i >= 0; i-- )
623         {
624             String name = parser.getAttributeName( i );
625             String value = parser.getAttributeValue( i );
626 
627             if ( name.indexOf( ':' ) >= 0 )
628             {
629                 // just ignore attributes with non-default namespace (for example: xmlns:xsi)
630             }
631             else
632             {
633                 checkUnknownAttribute( parser, name, tagName, strict );
634             }
635         }
636         java.util.Set parsed = new java.util.HashSet();
637         while ( ( strict ? parser.nextTag() : nextTag( parser ) ) == XmlPullParser.START_TAG )
638         {
639             if ( checkFieldWithDuplicate( parser, "name", null, parsed ) )
640             {
641                 banner.setName( interpolatedTrimmed( parser.nextText(), "name" ) );
642             }
643             else if ( checkFieldWithDuplicate( parser, "src", null, parsed ) )
644             {
645                 banner.setSrc( interpolatedTrimmed( parser.nextText(), "src" ) );
646             }
647             else if ( checkFieldWithDuplicate( parser, "alt", null, parsed ) )
648             {
649                 banner.setAlt( interpolatedTrimmed( parser.nextText(), "alt" ) );
650             }
651             else if ( checkFieldWithDuplicate( parser, "href", null, parsed ) )
652             {
653                 banner.setHref( interpolatedTrimmed( parser.nextText(), "href" ) );
654             }
655             else if ( checkFieldWithDuplicate( parser, "border", null, parsed ) )
656             {
657                 banner.setBorder( interpolatedTrimmed( parser.nextText(), "border" ) );
658             }
659             else if ( checkFieldWithDuplicate( parser, "width", null, parsed ) )
660             {
661                 banner.setWidth( interpolatedTrimmed( parser.nextText(), "width" ) );
662             }
663             else if ( checkFieldWithDuplicate( parser, "height", null, parsed ) )
664             {
665                 banner.setHeight( interpolatedTrimmed( parser.nextText(), "height" ) );
666             }
667             else if ( checkFieldWithDuplicate( parser, "title", null, parsed ) )
668             {
669                 banner.setTitle( interpolatedTrimmed( parser.nextText(), "title" ) );
670             }
671             else
672             {
673                 checkUnknownElement( parser, strict );
674             }
675         }
676         return banner;
677     } //-- Banner parseBanner( XmlPullParser, boolean )
678 
679     /**
680      * Method parseBody.
681      * 
682      * @param parser
683      * @param strict
684      * @throws IOException
685      * @throws XmlPullParserException
686      * @return Body
687      */
688     private Body parseBody( XmlPullParser parser, boolean strict )
689         throws IOException, XmlPullParserException
690     {
691         String tagName = parser.getName();
692         Body body = new Body();
693         for ( int i = parser.getAttributeCount() - 1; i >= 0; i-- )
694         {
695             String name = parser.getAttributeName( i );
696             String value = parser.getAttributeValue( i );
697 
698             if ( name.indexOf( ':' ) >= 0 )
699             {
700                 // just ignore attributes with non-default namespace (for example: xmlns:xsi)
701             }
702             else
703             {
704                 checkUnknownAttribute( parser, name, tagName, strict );
705             }
706         }
707         java.util.Set parsed = new java.util.HashSet();
708         while ( ( strict ? parser.nextTag() : nextTag( parser ) ) == XmlPullParser.START_TAG )
709         {
710             if ( checkFieldWithDuplicate( parser, "head", null, parsed ) )
711             {
712                 body.setHead( interpolatedTrimmed( parser.nextText(), "head" ) );
713             }
714             else if ( checkFieldWithDuplicate( parser, "links", null, parsed ) )
715             {
716                 java.util.List<LinkItem> links = new java.util.ArrayList<LinkItem>();
717                 body.setLinks( links );
718                 while ( parser.nextTag() == XmlPullParser.START_TAG )
719                 {
720                     if ( "item".equals( parser.getName() ) )
721                     {
722                         links.add( parseLinkItem( parser, strict ) );
723                     }
724                     else
725                     {
726                         checkUnknownElement( parser, strict );
727                     }
728                 }
729             }
730             else if ( checkFieldWithDuplicate( parser, "breadcrumbs", null, parsed ) )
731             {
732                 java.util.List<LinkItem> breadcrumbs = new java.util.ArrayList<LinkItem>();
733                 body.setBreadcrumbs( breadcrumbs );
734                 while ( parser.nextTag() == XmlPullParser.START_TAG )
735                 {
736                     if ( "item".equals( parser.getName() ) )
737                     {
738                         breadcrumbs.add( parseLinkItem( parser, strict ) );
739                     }
740                     else
741                     {
742                         checkUnknownElement( parser, strict );
743                     }
744                 }
745             }
746             else if ( "menu".equals( parser.getName() ) )
747             {
748                 java.util.List<Menu> menus = body.getMenus();
749                 if ( menus == null )
750                 {
751                     menus = new java.util.ArrayList<Menu>();
752                     body.setMenus( menus );
753                 }
754                 menus.add( parseMenu( parser, strict ) );
755             }
756             else if ( checkFieldWithDuplicate( parser, "footer", null, parsed ) )
757             {
758                 body.setFooter( interpolatedTrimmed( parser.nextText(), "footer" ) );
759             }
760             else
761             {
762                 checkUnknownElement( parser, strict );
763             }
764         }
765         return body;
766     } //-- Body parseBody( XmlPullParser, boolean )
767 
768     /**
769      * Method parseDecorationModel.
770      * 
771      * @param parser
772      * @param strict
773      * @throws IOException
774      * @throws XmlPullParserException
775      * @return DecorationModel
776      */
777     private DecorationModel parseDecorationModel( XmlPullParser parser, boolean strict )
778         throws IOException, XmlPullParserException
779     {
780         String tagName = parser.getName();
781         DecorationModel decorationModel = new DecorationModel();
782         for ( int i = parser.getAttributeCount() - 1; i >= 0; i-- )
783         {
784             String name = parser.getAttributeName( i );
785             String value = parser.getAttributeValue( i );
786 
787             if ( name.indexOf( ':' ) >= 0 )
788             {
789                 // just ignore attributes with non-default namespace (for example: xmlns:xsi)
790             }
791             else if ( "xmlns".equals( name ) )
792             {
793                 // ignore xmlns attribute in root class, which is a reserved attribute name
794             }
795             else if ( "name".equals( name ) )
796             {
797                 decorationModel.setName( interpolatedTrimmed( value, "name" ) );
798             }
799             else if ( "combine.self".equals( name ) )
800             {
801                 decorationModel.setCombineSelf( interpolatedTrimmed( value, "combine.self" ) );
802             }
803             else
804             {
805                 checkUnknownAttribute( parser, name, tagName, strict );
806             }
807         }
808         java.util.Set parsed = new java.util.HashSet();
809         while ( ( strict ? parser.nextTag() : nextTag( parser ) ) == XmlPullParser.START_TAG )
810         {
811             if ( checkFieldWithDuplicate( parser, "bannerLeft", null, parsed ) )
812             {
813                 decorationModel.setBannerLeft( parseBanner( parser, strict ) );
814             }
815             else if ( checkFieldWithDuplicate( parser, "bannerRight", null, parsed ) )
816             {
817                 decorationModel.setBannerRight( parseBanner( parser, strict ) );
818             }
819             else if ( checkFieldWithDuplicate( parser, "googleAdSenseClient", null, parsed ) )
820             {
821                 decorationModel.setGoogleAdSenseClient( interpolatedTrimmed( parser.nextText(), "googleAdSenseClient" ) );
822             }
823             else if ( checkFieldWithDuplicate( parser, "googleAdSenseSlot", null, parsed ) )
824             {
825                 decorationModel.setGoogleAdSenseSlot( interpolatedTrimmed( parser.nextText(), "googleAdSenseSlot" ) );
826             }
827             else if ( checkFieldWithDuplicate( parser, "googleAnalyticsAccountId", null, parsed ) )
828             {
829                 decorationModel.setGoogleAnalyticsAccountId( interpolatedTrimmed( parser.nextText(), "googleAnalyticsAccountId" ) );
830             }
831             else if ( checkFieldWithDuplicate( parser, "publishDate", null, parsed ) )
832             {
833                 decorationModel.setPublishDate( parsePublishDate( parser, strict ) );
834             }
835             else if ( checkFieldWithDuplicate( parser, "version", null, parsed ) )
836             {
837                 decorationModel.setVersion( parseVersion( parser, strict ) );
838             }
839             else if ( checkFieldWithDuplicate( parser, "edit", null, parsed ) )
840             {
841                 decorationModel.setEdit( interpolatedTrimmed( parser.nextText(), "edit" ) );
842             }
843             else if ( checkFieldWithDuplicate( parser, "poweredBy", null, parsed ) )
844             {
845                 java.util.List<Logo> poweredBy = new java.util.ArrayList<Logo>();
846                 decorationModel.setPoweredBy( poweredBy );
847                 while ( parser.nextTag() == XmlPullParser.START_TAG )
848                 {
849                     if ( "logo".equals( parser.getName() ) )
850                     {
851                         poweredBy.add( parseLogo( parser, strict ) );
852                     }
853                     else
854                     {
855                         checkUnknownElement( parser, strict );
856                     }
857                 }
858             }
859             else if ( checkFieldWithDuplicate( parser, "skin", null, parsed ) )
860             {
861                 decorationModel.setSkin( parseSkin( parser, strict ) );
862             }
863             else if ( checkFieldWithDuplicate( parser, "body", null, parsed ) )
864             {
865                 decorationModel.setBody( parseBody( parser, strict ) );
866             }
867             else if ( checkFieldWithDuplicate( parser, "custom", null, parsed ) )
868             {
869                 decorationModel.setCustom( org.codehaus.plexus.util.xml.Xpp3DomBuilder.build( parser, true ) );
870             }
871             else
872             {
873                 checkUnknownElement( parser, strict );
874             }
875         }
876         return decorationModel;
877     } //-- DecorationModel parseDecorationModel( XmlPullParser, boolean )
878 
879     /**
880      * Method parseLinkItem.
881      * 
882      * @param parser
883      * @param strict
884      * @throws IOException
885      * @throws XmlPullParserException
886      * @return LinkItem
887      */
888     private LinkItem parseLinkItem( XmlPullParser parser, boolean strict )
889         throws IOException, XmlPullParserException
890     {
891         String tagName = parser.getName();
892         LinkItem linkItem = new LinkItem();
893         for ( int i = parser.getAttributeCount() - 1; i >= 0; i-- )
894         {
895             String name = parser.getAttributeName( i );
896             String value = parser.getAttributeValue( i );
897 
898             if ( name.indexOf( ':' ) >= 0 )
899             {
900                 // just ignore attributes with non-default namespace (for example: xmlns:xsi)
901             }
902             else if ( "name".equals( name ) )
903             {
904                 linkItem.setName( interpolatedTrimmed( value, "name" ) );
905             }
906             else if ( "href".equals( name ) )
907             {
908                 linkItem.setHref( interpolatedTrimmed( value, "href" ) );
909             }
910             else if ( "img".equals( name ) )
911             {
912                 linkItem.setImg( interpolatedTrimmed( value, "img" ) );
913             }
914             else if ( "position".equals( name ) )
915             {
916                 linkItem.setPosition( interpolatedTrimmed( value, "position" ) );
917             }
918             else if ( "alt".equals( name ) )
919             {
920                 linkItem.setAlt( interpolatedTrimmed( value, "alt" ) );
921             }
922             else if ( "border".equals( name ) )
923             {
924                 linkItem.setBorder( interpolatedTrimmed( value, "border" ) );
925             }
926             else if ( "width".equals( name ) )
927             {
928                 linkItem.setWidth( interpolatedTrimmed( value, "width" ) );
929             }
930             else if ( "height".equals( name ) )
931             {
932                 linkItem.setHeight( interpolatedTrimmed( value, "height" ) );
933             }
934             else if ( "target".equals( name ) )
935             {
936                 linkItem.setTarget( interpolatedTrimmed( value, "target" ) );
937             }
938             else if ( "title".equals( name ) )
939             {
940                 linkItem.setTitle( interpolatedTrimmed( value, "title" ) );
941             }
942             else
943             {
944                 checkUnknownAttribute( parser, name, tagName, strict );
945             }
946         }
947         java.util.Set parsed = new java.util.HashSet();
948         while ( ( strict ? parser.nextTag() : nextTag( parser ) ) == XmlPullParser.START_TAG )
949         {
950             checkUnknownElement( parser, strict );
951         }
952         return linkItem;
953     } //-- LinkItem parseLinkItem( XmlPullParser, boolean )
954 
955     /**
956      * Method parseLogo.
957      * 
958      * @param parser
959      * @param strict
960      * @throws IOException
961      * @throws XmlPullParserException
962      * @return Logo
963      */
964     private Logo parseLogo( XmlPullParser parser, boolean strict )
965         throws IOException, XmlPullParserException
966     {
967         String tagName = parser.getName();
968         Logo logo = new Logo();
969         for ( int i = parser.getAttributeCount() - 1; i >= 0; i-- )
970         {
971             String name = parser.getAttributeName( i );
972             String value = parser.getAttributeValue( i );
973 
974             if ( name.indexOf( ':' ) >= 0 )
975             {
976                 // just ignore attributes with non-default namespace (for example: xmlns:xsi)
977             }
978             else if ( "name".equals( name ) )
979             {
980                 logo.setName( interpolatedTrimmed( value, "name" ) );
981             }
982             else if ( "href".equals( name ) )
983             {
984                 logo.setHref( interpolatedTrimmed( value, "href" ) );
985             }
986             else if ( "img".equals( name ) )
987             {
988                 logo.setImg( interpolatedTrimmed( value, "img" ) );
989             }
990             else if ( "position".equals( name ) )
991             {
992                 logo.setPosition( interpolatedTrimmed( value, "position" ) );
993             }
994             else if ( "alt".equals( name ) )
995             {
996                 logo.setAlt( interpolatedTrimmed( value, "alt" ) );
997             }
998             else if ( "border".equals( name ) )
999             {
1000                 logo.setBorder( interpolatedTrimmed( value, "border" ) );
1001             }
1002             else if ( "width".equals( name ) )
1003             {
1004                 logo.setWidth( interpolatedTrimmed( value, "width" ) );
1005             }
1006             else if ( "height".equals( name ) )
1007             {
1008                 logo.setHeight( interpolatedTrimmed( value, "height" ) );
1009             }
1010             else if ( "target".equals( name ) )
1011             {
1012                 logo.setTarget( interpolatedTrimmed( value, "target" ) );
1013             }
1014             else if ( "title".equals( name ) )
1015             {
1016                 logo.setTitle( interpolatedTrimmed( value, "title" ) );
1017             }
1018             else
1019             {
1020                 checkUnknownAttribute( parser, name, tagName, strict );
1021             }
1022         }
1023         java.util.Set parsed = new java.util.HashSet();
1024         while ( ( strict ? parser.nextTag() : nextTag( parser ) ) == XmlPullParser.START_TAG )
1025         {
1026             checkUnknownElement( parser, strict );
1027         }
1028         return logo;
1029     } //-- Logo parseLogo( XmlPullParser, boolean )
1030 
1031     /**
1032      * Method parseMenu.
1033      * 
1034      * @param parser
1035      * @param strict
1036      * @throws IOException
1037      * @throws XmlPullParserException
1038      * @return Menu
1039      */
1040     private Menu parseMenu( XmlPullParser parser, boolean strict )
1041         throws IOException, XmlPullParserException
1042     {
1043         String tagName = parser.getName();
1044         Menu menu = new Menu();
1045         for ( int i = parser.getAttributeCount() - 1; i >= 0; i-- )
1046         {
1047             String name = parser.getAttributeName( i );
1048             String value = parser.getAttributeValue( i );
1049 
1050             if ( name.indexOf( ':' ) >= 0 )
1051             {
1052                 // just ignore attributes with non-default namespace (for example: xmlns:xsi)
1053             }
1054             else if ( "name".equals( name ) )
1055             {
1056                 menu.setName( interpolatedTrimmed( value, "name" ) );
1057             }
1058             else if ( "inherit".equals( name ) )
1059             {
1060                 menu.setInherit( interpolatedTrimmed( value, "inherit" ) );
1061             }
1062             else if ( "inheritAsRef".equals( name ) )
1063             {
1064                 menu.setInheritAsRef( getBooleanValue( interpolatedTrimmed( value, "inheritAsRef" ), "inheritAsRef", parser, "false" ) );
1065             }
1066             else if ( "ref".equals( name ) )
1067             {
1068                 menu.setRef( interpolatedTrimmed( value, "ref" ) );
1069             }
1070             else if ( "img".equals( name ) )
1071             {
1072                 menu.setImg( interpolatedTrimmed( value, "img" ) );
1073             }
1074             else if ( "alt".equals( name ) )
1075             {
1076                 menu.setAlt( interpolatedTrimmed( value, "alt" ) );
1077             }
1078             else if ( "position".equals( name ) )
1079             {
1080                 menu.setPosition( interpolatedTrimmed( value, "position" ) );
1081             }
1082             else if ( "border".equals( name ) )
1083             {
1084                 menu.setBorder( interpolatedTrimmed( value, "border" ) );
1085             }
1086             else if ( "width".equals( name ) )
1087             {
1088                 menu.setWidth( interpolatedTrimmed( value, "width" ) );
1089             }
1090             else if ( "height".equals( name ) )
1091             {
1092                 menu.setHeight( interpolatedTrimmed( value, "height" ) );
1093             }
1094             else if ( "title".equals( name ) )
1095             {
1096                 menu.setTitle( interpolatedTrimmed( value, "title" ) );
1097             }
1098             else
1099             {
1100                 checkUnknownAttribute( parser, name, tagName, strict );
1101             }
1102         }
1103         java.util.Set parsed = new java.util.HashSet();
1104         while ( ( strict ? parser.nextTag() : nextTag( parser ) ) == XmlPullParser.START_TAG )
1105         {
1106             if ( "item".equals( parser.getName() ) )
1107             {
1108                 java.util.List<MenuItem> items = menu.getItems();
1109                 if ( items == null )
1110                 {
1111                     items = new java.util.ArrayList<MenuItem>();
1112                     menu.setItems( items );
1113                 }
1114                 items.add( parseMenuItem( parser, strict ) );
1115             }
1116             else
1117             {
1118                 checkUnknownElement( parser, strict );
1119             }
1120         }
1121         return menu;
1122     } //-- Menu parseMenu( XmlPullParser, boolean )
1123 
1124     /**
1125      * Method parseMenuItem.
1126      * 
1127      * @param parser
1128      * @param strict
1129      * @throws IOException
1130      * @throws XmlPullParserException
1131      * @return MenuItem
1132      */
1133     private MenuItem parseMenuItem( XmlPullParser parser, boolean strict )
1134         throws IOException, XmlPullParserException
1135     {
1136         String tagName = parser.getName();
1137         MenuItem menuItem = new MenuItem();
1138         for ( int i = parser.getAttributeCount() - 1; i >= 0; i-- )
1139         {
1140             String name = parser.getAttributeName( i );
1141             String value = parser.getAttributeValue( i );
1142 
1143             if ( name.indexOf( ':' ) >= 0 )
1144             {
1145                 // just ignore attributes with non-default namespace (for example: xmlns:xsi)
1146             }
1147             else if ( "collapse".equals( name ) )
1148             {
1149                 menuItem.setCollapse( getBooleanValue( interpolatedTrimmed( value, "collapse" ), "collapse", parser, "false" ) );
1150             }
1151             else if ( "ref".equals( name ) )
1152             {
1153                 menuItem.setRef( interpolatedTrimmed( value, "ref" ) );
1154             }
1155             else if ( "name".equals( name ) )
1156             {
1157                 menuItem.setName( interpolatedTrimmed( value, "name" ) );
1158             }
1159             else if ( "href".equals( name ) )
1160             {
1161                 menuItem.setHref( interpolatedTrimmed( value, "href" ) );
1162             }
1163             else if ( "img".equals( name ) )
1164             {
1165                 menuItem.setImg( interpolatedTrimmed( value, "img" ) );
1166             }
1167             else if ( "position".equals( name ) )
1168             {
1169                 menuItem.setPosition( interpolatedTrimmed( value, "position" ) );
1170             }
1171             else if ( "alt".equals( name ) )
1172             {
1173                 menuItem.setAlt( interpolatedTrimmed( value, "alt" ) );
1174             }
1175             else if ( "border".equals( name ) )
1176             {
1177                 menuItem.setBorder( interpolatedTrimmed( value, "border" ) );
1178             }
1179             else if ( "width".equals( name ) )
1180             {
1181                 menuItem.setWidth( interpolatedTrimmed( value, "width" ) );
1182             }
1183             else if ( "height".equals( name ) )
1184             {
1185                 menuItem.setHeight( interpolatedTrimmed( value, "height" ) );
1186             }
1187             else if ( "target".equals( name ) )
1188             {
1189                 menuItem.setTarget( interpolatedTrimmed( value, "target" ) );
1190             }
1191             else if ( "title".equals( name ) )
1192             {
1193                 menuItem.setTitle( interpolatedTrimmed( value, "title" ) );
1194             }
1195             else
1196             {
1197                 checkUnknownAttribute( parser, name, tagName, strict );
1198             }
1199         }
1200         java.util.Set parsed = new java.util.HashSet();
1201         while ( ( strict ? parser.nextTag() : nextTag( parser ) ) == XmlPullParser.START_TAG )
1202         {
1203             if ( checkFieldWithDuplicate( parser, "description", null, parsed ) )
1204             {
1205                 menuItem.setDescription( interpolatedTrimmed( parser.nextText(), "description" ) );
1206             }
1207             else if ( "item".equals( parser.getName() ) )
1208             {
1209                 java.util.List<MenuItem> items = menuItem.getItems();
1210                 if ( items == null )
1211                 {
1212                     items = new java.util.ArrayList<MenuItem>();
1213                     menuItem.setItems( items );
1214                 }
1215                 items.add( parseMenuItem( parser, strict ) );
1216             }
1217             else
1218             {
1219                 checkUnknownElement( parser, strict );
1220             }
1221         }
1222         return menuItem;
1223     } //-- MenuItem parseMenuItem( XmlPullParser, boolean )
1224 
1225     /**
1226      * Method parsePublishDate.
1227      * 
1228      * @param parser
1229      * @param strict
1230      * @throws IOException
1231      * @throws XmlPullParserException
1232      * @return PublishDate
1233      */
1234     private PublishDate parsePublishDate( XmlPullParser parser, boolean strict )
1235         throws IOException, XmlPullParserException
1236     {
1237         String tagName = parser.getName();
1238         PublishDate publishDate = new PublishDate();
1239         for ( int i = parser.getAttributeCount() - 1; i >= 0; i-- )
1240         {
1241             String name = parser.getAttributeName( i );
1242             String value = parser.getAttributeValue( i );
1243 
1244             if ( name.indexOf( ':' ) >= 0 )
1245             {
1246                 // just ignore attributes with non-default namespace (for example: xmlns:xsi)
1247             }
1248             else if ( "position".equals( name ) )
1249             {
1250                 publishDate.setPosition( interpolatedTrimmed( value, "position" ) );
1251             }
1252             else if ( "format".equals( name ) )
1253             {
1254                 publishDate.setFormat( interpolatedTrimmed( value, "format" ) );
1255             }
1256             else
1257             {
1258                 checkUnknownAttribute( parser, name, tagName, strict );
1259             }
1260         }
1261         java.util.Set parsed = new java.util.HashSet();
1262         while ( ( strict ? parser.nextTag() : nextTag( parser ) ) == XmlPullParser.START_TAG )
1263         {
1264             checkUnknownElement( parser, strict );
1265         }
1266         return publishDate;
1267     } //-- PublishDate parsePublishDate( XmlPullParser, boolean )
1268 
1269     /**
1270      * Method parseSkin.
1271      * 
1272      * @param parser
1273      * @param strict
1274      * @throws IOException
1275      * @throws XmlPullParserException
1276      * @return Skin
1277      */
1278     private Skin parseSkin( XmlPullParser parser, boolean strict )
1279         throws IOException, XmlPullParserException
1280     {
1281         String tagName = parser.getName();
1282         Skin skin = new Skin();
1283         for ( int i = parser.getAttributeCount() - 1; i >= 0; i-- )
1284         {
1285             String name = parser.getAttributeName( i );
1286             String value = parser.getAttributeValue( i );
1287 
1288             if ( name.indexOf( ':' ) >= 0 )
1289             {
1290                 // just ignore attributes with non-default namespace (for example: xmlns:xsi)
1291             }
1292             else
1293             {
1294                 checkUnknownAttribute( parser, name, tagName, strict );
1295             }
1296         }
1297         java.util.Set parsed = new java.util.HashSet();
1298         while ( ( strict ? parser.nextTag() : nextTag( parser ) ) == XmlPullParser.START_TAG )
1299         {
1300             if ( checkFieldWithDuplicate( parser, "groupId", null, parsed ) )
1301             {
1302                 skin.setGroupId( interpolatedTrimmed( parser.nextText(), "groupId" ) );
1303             }
1304             else if ( checkFieldWithDuplicate( parser, "artifactId", null, parsed ) )
1305             {
1306                 skin.setArtifactId( interpolatedTrimmed( parser.nextText(), "artifactId" ) );
1307             }
1308             else if ( checkFieldWithDuplicate( parser, "version", null, parsed ) )
1309             {
1310                 skin.setVersion( interpolatedTrimmed( parser.nextText(), "version" ) );
1311             }
1312             else
1313             {
1314                 checkUnknownElement( parser, strict );
1315             }
1316         }
1317         return skin;
1318     } //-- Skin parseSkin( XmlPullParser, boolean )
1319 
1320     /**
1321      * Method parseVersion.
1322      * 
1323      * @param parser
1324      * @param strict
1325      * @throws IOException
1326      * @throws XmlPullParserException
1327      * @return Version
1328      */
1329     private Version parseVersion( XmlPullParser parser, boolean strict )
1330         throws IOException, XmlPullParserException
1331     {
1332         String tagName = parser.getName();
1333         Version version = new Version();
1334         for ( int i = parser.getAttributeCount() - 1; i >= 0; i-- )
1335         {
1336             String name = parser.getAttributeName( i );
1337             String value = parser.getAttributeValue( i );
1338 
1339             if ( name.indexOf( ':' ) >= 0 )
1340             {
1341                 // just ignore attributes with non-default namespace (for example: xmlns:xsi)
1342             }
1343             else if ( "position".equals( name ) )
1344             {
1345                 version.setPosition( interpolatedTrimmed( value, "position" ) );
1346             }
1347             else
1348             {
1349                 checkUnknownAttribute( parser, name, tagName, strict );
1350             }
1351         }
1352         java.util.Set parsed = new java.util.HashSet();
1353         while ( ( strict ? parser.nextTag() : nextTag( parser ) ) == XmlPullParser.START_TAG )
1354         {
1355             checkUnknownElement( parser, strict );
1356         }
1357         return version;
1358     } //-- Version parseVersion( XmlPullParser, boolean )
1359 
1360     /**
1361      * Method read.
1362      * 
1363      * @param parser
1364      * @param strict
1365      * @throws IOException
1366      * @throws XmlPullParserException
1367      * @return DecorationModel
1368      */
1369     private DecorationModel read( XmlPullParser parser, boolean strict )
1370         throws IOException, XmlPullParserException
1371     {
1372         DecorationModel decorationModel = null;
1373         int eventType = parser.getEventType();
1374         boolean parsed = false;
1375         while ( eventType != XmlPullParser.END_DOCUMENT )
1376         {
1377             if ( eventType == XmlPullParser.START_TAG )
1378             {
1379                 if ( strict && ! "project".equals( parser.getName() ) )
1380                 {
1381                     throw new XmlPullParserException( "Expected root element 'project' but found '" + parser.getName() + "'", parser, null );
1382                 }
1383                 else if ( parsed )
1384                 {
1385                     // fallback, already expected a XmlPullParserException due to invalid XML
1386                     throw new XmlPullParserException( "Duplicated tag: 'project'", parser, null );
1387                 }
1388                 decorationModel = parseDecorationModel( parser, strict );
1389                 decorationModel.setModelEncoding( parser.getInputEncoding() );
1390                 parsed = true;
1391             }
1392             eventType = parser.next();
1393         }
1394         if ( parsed )
1395         {
1396             return decorationModel;
1397         }
1398         throw new XmlPullParserException( "Expected root element 'project' but found no element at all: invalid XML document", parser, null );
1399     } //-- DecorationModel read( XmlPullParser, boolean )
1400 
1401     /**
1402      * Sets the state of the "add default entities" flag.
1403      * 
1404      * @param addDefaultEntities
1405      */
1406     public void setAddDefaultEntities( boolean addDefaultEntities )
1407     {
1408         this.addDefaultEntities = addDefaultEntities;
1409     } //-- void setAddDefaultEntities( boolean )
1410 
1411     public static interface ContentTransformer
1412 {
1413     /**
1414      * Interpolate the value read from the xpp3 document
1415      * @param source The source value
1416      * @param fieldName A description of the field being interpolated. The implementation may use this to
1417      *                           log stuff.
1418      * @return The interpolated value.
1419      */
1420     String transform( String source, String fieldName );
1421 }
1422 
1423 }