View Javadoc
1   /*
2    =================== DO NOT EDIT THIS FILE ====================
3    Generated by Modello 1.0.1 on 2016-10-29 20:36:58,
4    any modifications will be overwritten.
5    ==============================================================
6    */
7   
8   package org.apache.maven.plugins.changes.model.io.xpp3;
9   
10    //---------------------------------/
11   //- Imported classes and packages -/
12  //---------------------------------/
13  
14  import java.io.IOException;
15  import java.io.InputStream;
16  import java.io.Reader;
17  import java.text.DateFormat;
18  import java.util.Locale;
19  import org.apache.maven.plugins.changes.model.Action;
20  import org.apache.maven.plugins.changes.model.Author;
21  import org.apache.maven.plugins.changes.model.Body;
22  import org.apache.maven.plugins.changes.model.ChangesDocument;
23  import org.apache.maven.plugins.changes.model.Component;
24  import org.apache.maven.plugins.changes.model.DueTo;
25  import org.apache.maven.plugins.changes.model.FixedIssue;
26  import org.apache.maven.plugins.changes.model.Properties;
27  import org.apache.maven.plugins.changes.model.Release;
28  import org.codehaus.plexus.util.ReaderFactory;
29  import org.codehaus.plexus.util.xml.pull.MXParser;
30  import org.codehaus.plexus.util.xml.pull.XmlPullParser;
31  import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
32  
33  /**
34   * Class ChangesXpp3Reader.
35   * 
36   * @version $Revision$ $Date$
37   */
38  public class ChangesXpp3Reader
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        //-----------/
59       //- Methods -/
60      //-----------/
61  
62      /**
63       * Method checkFieldWithDuplicate.
64       * 
65       * @param parser
66       * @param parsed
67       * @param alias
68       * @param tagName
69       * @throws XmlPullParserException
70       * @return boolean
71       */
72      private boolean checkFieldWithDuplicate( XmlPullParser parser, String tagName, String alias, java.util.Set parsed )
73          throws XmlPullParserException
74      {
75          if ( !( parser.getName().equals( tagName ) || parser.getName().equals( alias ) ) )
76          {
77              return false;
78          }
79          if ( parsed.contains( tagName ) )
80          {
81              throw new XmlPullParserException( "Duplicated tag: '" + tagName + "'", parser, null );
82          }
83          parsed.add( tagName );
84          return true;
85      } //-- boolean checkFieldWithDuplicate( XmlPullParser, String, String, java.util.Set )
86  
87      /**
88       * Returns the state of the "add default entities" flag.
89       * 
90       * @return boolean
91       */
92      public boolean getAddDefaultEntities()
93      {
94          return addDefaultEntities;
95      } //-- boolean getAddDefaultEntities()
96  
97      /**
98       * Method getBooleanValue.
99       * 
100      * @param s
101      * @param parser
102      * @param attribute
103      * @throws XmlPullParserException
104      * @return boolean
105      */
106     private boolean getBooleanValue( String s, String attribute, XmlPullParser parser )
107         throws XmlPullParserException
108     {
109         return getBooleanValue( s, attribute, parser, null );
110     } //-- boolean getBooleanValue( String, String, XmlPullParser )
111 
112     /**
113      * Method getBooleanValue.
114      * 
115      * @param s
116      * @param defaultValue
117      * @param parser
118      * @param attribute
119      * @throws XmlPullParserException
120      * @return boolean
121      */
122     private boolean getBooleanValue( String s, String attribute, XmlPullParser parser, String defaultValue )
123         throws XmlPullParserException
124     {
125         if ( s != null && s.length() != 0 )
126         {
127             return Boolean.valueOf( s ).booleanValue();
128         }
129         if ( defaultValue != null )
130         {
131             return Boolean.valueOf( defaultValue ).booleanValue();
132         }
133         return false;
134     } //-- boolean getBooleanValue( String, String, XmlPullParser, String )
135 
136     /**
137      * Method getByteValue.
138      * 
139      * @param s
140      * @param strict
141      * @param parser
142      * @param attribute
143      * @throws XmlPullParserException
144      * @return byte
145      */
146     private byte getByteValue( String s, String attribute, XmlPullParser parser, boolean strict )
147         throws XmlPullParserException
148     {
149         if ( s != null )
150         {
151             try
152             {
153                 return Byte.valueOf( s ).byteValue();
154             }
155             catch ( NumberFormatException e )
156             {
157                 if ( strict )
158                 {
159                     throw new XmlPullParserException( "Unable to parse element '" + attribute + "', must be a byte", parser, null );
160                 }
161             }
162         }
163         return 0;
164     } //-- byte getByteValue( String, String, XmlPullParser, boolean )
165 
166     /**
167      * Method getCharacterValue.
168      * 
169      * @param s
170      * @param parser
171      * @param attribute
172      * @throws XmlPullParserException
173      * @return char
174      */
175     private char getCharacterValue( String s, String attribute, XmlPullParser parser )
176         throws XmlPullParserException
177     {
178         if ( s != null )
179         {
180             return s.charAt( 0 );
181         }
182         return 0;
183     } //-- char getCharacterValue( String, String, XmlPullParser )
184 
185     /**
186      * Method getDateValue.
187      * 
188      * @param s
189      * @param parser
190      * @param attribute
191      * @throws XmlPullParserException
192      * @return Date
193      */
194     private java.util.Date getDateValue( String s, String attribute, XmlPullParser parser )
195         throws XmlPullParserException
196     {
197         return getDateValue( s, attribute, null, parser );
198     } //-- java.util.Date getDateValue( String, String, XmlPullParser )
199 
200     /**
201      * Method getDateValue.
202      * 
203      * @param s
204      * @param parser
205      * @param dateFormat
206      * @param attribute
207      * @throws XmlPullParserException
208      * @return Date
209      */
210     private java.util.Date getDateValue( String s, String attribute, String dateFormat, XmlPullParser parser )
211         throws XmlPullParserException
212     {
213         if ( s != null )
214         {
215             String effectiveDateFormat = dateFormat;
216             if ( dateFormat == null )
217             {
218                 effectiveDateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS";
219             }
220             if ( "long".equals( effectiveDateFormat ) )
221             {
222                 try
223                 {
224                     return new java.util.Date( Long.parseLong( s ) );
225                 }
226                 catch ( NumberFormatException e )
227                 {
228                     throw new XmlPullParserException( e.getMessage() );
229                 }
230             }
231             else
232             {
233                 try
234                 {
235                     DateFormat dateParser = new java.text.SimpleDateFormat( effectiveDateFormat, Locale.US );
236                     return dateParser.parse( s );
237                 }
238                 catch ( java.text.ParseException e )
239                 {
240                     throw new XmlPullParserException( e.getMessage() );
241                 }
242             }
243         }
244         return null;
245     } //-- java.util.Date getDateValue( String, String, String, XmlPullParser )
246 
247     /**
248      * Method getDoubleValue.
249      * 
250      * @param s
251      * @param strict
252      * @param parser
253      * @param attribute
254      * @throws XmlPullParserException
255      * @return double
256      */
257     private double getDoubleValue( String s, String attribute, XmlPullParser parser, boolean strict )
258         throws XmlPullParserException
259     {
260         if ( s != null )
261         {
262             try
263             {
264                 return Double.valueOf( s ).doubleValue();
265             }
266             catch ( NumberFormatException e )
267             {
268                 if ( strict )
269                 {
270                     throw new XmlPullParserException( "Unable to parse element '" + attribute + "', must be a floating point number", parser, null );
271                 }
272             }
273         }
274         return 0;
275     } //-- double getDoubleValue( String, String, XmlPullParser, boolean )
276 
277     /**
278      * Method getFloatValue.
279      * 
280      * @param s
281      * @param strict
282      * @param parser
283      * @param attribute
284      * @throws XmlPullParserException
285      * @return float
286      */
287     private float getFloatValue( String s, String attribute, XmlPullParser parser, boolean strict )
288         throws XmlPullParserException
289     {
290         if ( s != null )
291         {
292             try
293             {
294                 return Float.valueOf( s ).floatValue();
295             }
296             catch ( NumberFormatException e )
297             {
298                 if ( strict )
299                 {
300                     throw new XmlPullParserException( "Unable to parse element '" + attribute + "', must be a floating point number", parser, null );
301                 }
302             }
303         }
304         return 0;
305     } //-- float getFloatValue( String, String, XmlPullParser, boolean )
306 
307     /**
308      * Method getIntegerValue.
309      * 
310      * @param s
311      * @param strict
312      * @param parser
313      * @param attribute
314      * @throws XmlPullParserException
315      * @return int
316      */
317     private int getIntegerValue( String s, String attribute, XmlPullParser parser, boolean strict )
318         throws XmlPullParserException
319     {
320         if ( s != null )
321         {
322             try
323             {
324                 return Integer.valueOf( s ).intValue();
325             }
326             catch ( NumberFormatException e )
327             {
328                 if ( strict )
329                 {
330                     throw new XmlPullParserException( "Unable to parse element '" + attribute + "', must be an integer", parser, null );
331                 }
332             }
333         }
334         return 0;
335     } //-- int getIntegerValue( String, String, XmlPullParser, boolean )
336 
337     /**
338      * Method getLongValue.
339      * 
340      * @param s
341      * @param strict
342      * @param parser
343      * @param attribute
344      * @throws XmlPullParserException
345      * @return long
346      */
347     private long getLongValue( String s, String attribute, XmlPullParser parser, boolean strict )
348         throws XmlPullParserException
349     {
350         if ( s != null )
351         {
352             try
353             {
354                 return Long.valueOf( s ).longValue();
355             }
356             catch ( NumberFormatException e )
357             {
358                 if ( strict )
359                 {
360                     throw new XmlPullParserException( "Unable to parse element '" + attribute + "', must be a long integer", parser, null );
361                 }
362             }
363         }
364         return 0;
365     } //-- long getLongValue( String, String, XmlPullParser, boolean )
366 
367     /**
368      * Method getRequiredAttributeValue.
369      * 
370      * @param s
371      * @param strict
372      * @param parser
373      * @param attribute
374      * @throws XmlPullParserException
375      * @return String
376      */
377     private String getRequiredAttributeValue( String s, String attribute, XmlPullParser parser, boolean strict )
378         throws XmlPullParserException
379     {
380         if ( s == null )
381         {
382             if ( strict )
383             {
384                 throw new XmlPullParserException( "Missing required value for attribute '" + attribute + "'", parser, null );
385             }
386         }
387         return s;
388     } //-- String getRequiredAttributeValue( String, String, XmlPullParser, boolean )
389 
390     /**
391      * Method getShortValue.
392      * 
393      * @param s
394      * @param strict
395      * @param parser
396      * @param attribute
397      * @throws XmlPullParserException
398      * @return short
399      */
400     private short getShortValue( String s, String attribute, XmlPullParser parser, boolean strict )
401         throws XmlPullParserException
402     {
403         if ( s != null )
404         {
405             try
406             {
407                 return Short.valueOf( s ).shortValue();
408             }
409             catch ( NumberFormatException e )
410             {
411                 if ( strict )
412                 {
413                     throw new XmlPullParserException( "Unable to parse element '" + attribute + "', must be a short integer", parser, null );
414                 }
415             }
416         }
417         return 0;
418     } //-- short getShortValue( String, String, XmlPullParser, boolean )
419 
420     /**
421      * Method getTrimmedValue.
422      * 
423      * @param s
424      * @return String
425      */
426     private String getTrimmedValue( String s )
427     {
428         if ( s != null )
429         {
430             s = s.trim();
431         }
432         return s;
433     } //-- String getTrimmedValue( String )
434 
435     /**
436      * Method parseAction.
437      * 
438      * @param tagName
439      * @param strict
440      * @param parser
441      * @throws IOException
442      * @throws XmlPullParserException
443      * @return Action
444      */
445     private Action parseAction( String tagName, XmlPullParser parser, boolean strict )
446         throws IOException, XmlPullParserException
447     {
448         Action action = new Action();
449         if ( parser.getAttributeValue( "", "dev" ) != null  )
450         {
451             action.setDev( getTrimmedValue( parser.getAttributeValue( "", "dev" ) ) );
452         }
453         if ( parser.getAttributeValue( "", "due-to" ) != null  )
454         {
455             action.setDueTo( getTrimmedValue( parser.getAttributeValue( "", "due-to" ) ) );
456         }
457         if ( parser.getAttributeValue( "", "due-to-email" ) != null  )
458         {
459             action.setDueToEmail( getTrimmedValue( parser.getAttributeValue( "", "due-to-email" ) ) );
460         }
461         if ( parser.getAttributeValue( "", "issue" ) != null  )
462         {
463             action.setIssue( getTrimmedValue( parser.getAttributeValue( "", "issue" ) ) );
464         }
465         if ( parser.getAttributeValue( "", "type" ) != null  )
466         {
467             action.setType( getTrimmedValue( parser.getAttributeValue( "", "type" ) ) );
468         }
469         if ( parser.getAttributeValue( "", "system" ) != null  )
470         {
471             action.setSystem( getTrimmedValue( parser.getAttributeValue( "", "system" ) ) );
472         }
473         if ( parser.getAttributeValue( "", "date" ) != null  )
474         {
475             action.setDate( getTrimmedValue( parser.getAttributeValue( "", "date" ) ) );
476         }
477         parser.next();
478         action.setAction( getTrimmedValue( parser.getText() ) ); 
479         java.util.Set parsed = new java.util.HashSet();
480         while ( parser.nextTag() == XmlPullParser.START_TAG )
481         {
482             if ( checkFieldWithDuplicate( parser, "action", null, parsed ) )
483             {
484             }
485             else if ( parser.getName().equals( "fixes" ) )
486             {
487                 java.util.List fixedIssues = action.getFixedIssues();
488                 if ( fixedIssues == null )
489                 {
490                     fixedIssues = new java.util.ArrayList/*<FixedIssue>*/();
491                     action.setFixedIssues( fixedIssues );
492                 }
493                 fixedIssues.add( parseFixedIssue( "fixes", parser, strict ) );
494             }
495             else if ( parser.getName().equals( "dueto" ) )
496             {
497                 java.util.List dueTos = action.getDueTos();
498                 if ( dueTos == null )
499                 {
500                     dueTos = new java.util.ArrayList/*<DueTo>*/();
501                     action.setDueTos( dueTos );
502                 }
503                 dueTos.add( parseDueTo( "dueto", parser, strict ) );
504             }
505             else
506             {
507                 if ( strict )
508                 {
509                     throw new XmlPullParserException( "Unrecognised tag: '" + parser.getName() + "'", parser, null );
510                 }
511                 else
512                 {
513                     // swallow up to end tag since this is not valid
514                     while ( parser.next() != XmlPullParser.END_TAG ) {}
515                 }
516             }
517         }
518         return action;
519     } //-- Action parseAction( String, XmlPullParser, boolean )
520 
521     /**
522      * Method parseAuthor.
523      * 
524      * @param tagName
525      * @param strict
526      * @param parser
527      * @throws IOException
528      * @throws XmlPullParserException
529      * @return Author
530      */
531     private Author parseAuthor( String tagName, XmlPullParser parser, boolean strict )
532         throws IOException, XmlPullParserException
533     {
534         Author author = new Author();
535         if ( parser.getAttributeValue( "", "email" ) != null  )
536         {
537             author.setAuthorEmail( getTrimmedValue( parser.getAttributeValue( "", "email" ) ) );
538         }
539         parser.next();
540         author.setName( getTrimmedValue( parser.getText() ) ); 
541         java.util.Set parsed = new java.util.HashSet();
542         while ( parser.nextTag() == XmlPullParser.START_TAG )
543         {
544             if ( checkFieldWithDuplicate( parser, "name", null, parsed ) )
545             {
546             }
547             else
548             {
549                 if ( strict )
550                 {
551                     throw new XmlPullParserException( "Unrecognised tag: '" + parser.getName() + "'", parser, null );
552                 }
553                 else
554                 {
555                     // swallow up to end tag since this is not valid
556                     while ( parser.next() != XmlPullParser.END_TAG ) {}
557                 }
558             }
559         }
560         return author;
561     } //-- Author parseAuthor( String, XmlPullParser, boolean )
562 
563     /**
564      * Method parseBody.
565      * 
566      * @param tagName
567      * @param strict
568      * @param parser
569      * @throws IOException
570      * @throws XmlPullParserException
571      * @return Body
572      */
573     private Body parseBody( String tagName, XmlPullParser parser, boolean strict )
574         throws IOException, XmlPullParserException
575     {
576         Body body = new Body();
577         java.util.Set parsed = new java.util.HashSet();
578         while ( parser.nextTag() == XmlPullParser.START_TAG )
579         {
580             if ( parser.getName().equals( "release" ) )
581             {
582                 java.util.List releases = body.getReleases();
583                 if ( releases == null )
584                 {
585                     releases = new java.util.ArrayList/*<Release>*/();
586                     body.setReleases( releases );
587                 }
588                 releases.add( parseRelease( "release", parser, strict ) );
589             }
590             else
591             {
592                 if ( strict )
593                 {
594                     throw new XmlPullParserException( "Unrecognised tag: '" + parser.getName() + "'", parser, null );
595                 }
596                 else
597                 {
598                     // swallow up to end tag since this is not valid
599                     while ( parser.next() != XmlPullParser.END_TAG ) {}
600                 }
601             }
602         }
603         return body;
604     } //-- Body parseBody( String, XmlPullParser, boolean )
605 
606     /**
607      * Method parseChangesDocument.
608      * 
609      * @param tagName
610      * @param strict
611      * @param parser
612      * @throws IOException
613      * @throws XmlPullParserException
614      * @return ChangesDocument
615      */
616     private ChangesDocument parseChangesDocument( String tagName, XmlPullParser parser, boolean strict )
617         throws IOException, XmlPullParserException
618     {
619         ChangesDocument changesDocument = new ChangesDocument();
620         java.util.Set parsed = new java.util.HashSet();
621         int eventType = parser.getEventType();
622         boolean foundRoot = false;
623         while ( eventType != XmlPullParser.END_DOCUMENT )
624         {
625             if ( eventType == XmlPullParser.START_TAG )
626             {
627                 if ( parser.getName().equals( tagName ) )
628                 {
629                     foundRoot = true;
630                 }
631                 else if ( strict && ! foundRoot )
632                 {
633                     throw new XmlPullParserException( "Expected root element '" + tagName + "' but found '" + parser.getName() + "'", parser, null );
634                 }
635                 else if ( checkFieldWithDuplicate( parser, "properties", null, parsed ) )
636                 {
637                     changesDocument.setProperties( parseProperties( "properties", parser, strict ) );
638                 }
639                 else if ( checkFieldWithDuplicate( parser, "body", null, parsed ) )
640                 {
641                     changesDocument.setBody( parseBody( "body", parser, strict ) );
642                 }
643                 else if ( strict )
644                 {
645                     throw new XmlPullParserException( "Unrecognised tag: '" + parser.getName() + "'", parser, null );
646                 }
647             }
648             eventType = parser.next();
649         }
650         return changesDocument;
651     } //-- ChangesDocument parseChangesDocument( String, XmlPullParser, boolean )
652 
653     /**
654      * Method parseComponent.
655      * 
656      * @param tagName
657      * @param strict
658      * @param parser
659      * @throws IOException
660      * @throws XmlPullParserException
661      * @return Component
662      */
663     private Component parseComponent( String tagName, XmlPullParser parser, boolean strict )
664         throws IOException, XmlPullParserException
665     {
666         Component component = new Component();
667         java.util.Set parsed = new java.util.HashSet();
668         while ( parser.nextTag() == XmlPullParser.START_TAG )
669         {
670             if ( checkFieldWithDuplicate( parser, "name", null, parsed ) )
671             {
672                 component.setName( getTrimmedValue( parser.nextText() ) );
673             }
674             else if ( checkFieldWithDuplicate( parser, "description", null, parsed ) )
675             {
676                 component.setDescription( getTrimmedValue( parser.nextText() ) );
677             }
678             else if ( checkFieldWithDuplicate( parser, "actions", null, parsed ) )
679             {
680                 java.util.List actions = new java.util.ArrayList/*<Action>*/();
681                 component.setActions( actions );
682                 while ( parser.nextTag() == XmlPullParser.START_TAG )
683                 {
684                     if ( parser.getName().equals( "action" ) )
685                     {
686                         actions.add( parseAction( "action", parser, strict ) );
687                     }
688                     else if ( strict )
689                     {
690                         throw new XmlPullParserException( "Unrecognised association: '" + parser.getName() + "'", parser, null );
691                     }
692                     else
693                     {
694                         // swallow up to end tag since this is not valid
695                         while ( parser.next() != XmlPullParser.END_TAG ) {}
696                     }
697                 }
698             }
699             else
700             {
701                 if ( strict )
702                 {
703                     throw new XmlPullParserException( "Unrecognised tag: '" + parser.getName() + "'", parser, null );
704                 }
705                 else
706                 {
707                     // swallow up to end tag since this is not valid
708                     while ( parser.next() != XmlPullParser.END_TAG ) {}
709                 }
710             }
711         }
712         return component;
713     } //-- Component parseComponent( String, XmlPullParser, boolean )
714 
715     /**
716      * Method parseDueTo.
717      * 
718      * @param tagName
719      * @param strict
720      * @param parser
721      * @throws IOException
722      * @throws XmlPullParserException
723      * @return DueTo
724      */
725     private DueTo parseDueTo( String tagName, XmlPullParser parser, boolean strict )
726         throws IOException, XmlPullParserException
727     {
728         DueTo dueTo = new DueTo();
729         if ( parser.getAttributeValue( "", "name" ) != null  )
730         {
731             dueTo.setName( getTrimmedValue( parser.getAttributeValue( "", "name" ) ) );
732         }
733         if ( parser.getAttributeValue( "", "email" ) != null  )
734         {
735             dueTo.setEmail( getTrimmedValue( parser.getAttributeValue( "", "email" ) ) );
736         }
737         java.util.Set parsed = new java.util.HashSet();
738         while ( parser.nextTag() == XmlPullParser.START_TAG )
739         {
740             if ( strict )
741             {
742                 throw new XmlPullParserException( "Unrecognised tag: '" + parser.getName() + "'", parser, null );
743             }
744             else
745             {
746                 // swallow up to end tag since this is not valid
747                 while ( parser.next() != XmlPullParser.END_TAG ) {}
748             }
749         }
750         return dueTo;
751     } //-- DueTo parseDueTo( String, XmlPullParser, boolean )
752 
753     /**
754      * Method parseFixedIssue.
755      * 
756      * @param tagName
757      * @param strict
758      * @param parser
759      * @throws IOException
760      * @throws XmlPullParserException
761      * @return FixedIssue
762      */
763     private FixedIssue parseFixedIssue( String tagName, XmlPullParser parser, boolean strict )
764         throws IOException, XmlPullParserException
765     {
766         FixedIssue fixedIssue = new FixedIssue();
767         if ( parser.getAttributeValue( "", "issue" ) != null  )
768         {
769             fixedIssue.setIssue( getTrimmedValue( parser.getAttributeValue( "", "issue" ) ) );
770         }
771         java.util.Set parsed = new java.util.HashSet();
772         while ( parser.nextTag() == XmlPullParser.START_TAG )
773         {
774             if ( strict )
775             {
776                 throw new XmlPullParserException( "Unrecognised tag: '" + parser.getName() + "'", parser, null );
777             }
778             else
779             {
780                 // swallow up to end tag since this is not valid
781                 while ( parser.next() != XmlPullParser.END_TAG ) {}
782             }
783         }
784         return fixedIssue;
785     } //-- FixedIssue parseFixedIssue( String, XmlPullParser, boolean )
786 
787     /**
788      * Method parseProperties.
789      * 
790      * @param tagName
791      * @param strict
792      * @param parser
793      * @throws IOException
794      * @throws XmlPullParserException
795      * @return Properties
796      */
797     private Properties parseProperties( String tagName, XmlPullParser parser, boolean strict )
798         throws IOException, XmlPullParserException
799     {
800         Properties properties = new Properties();
801         java.util.Set parsed = new java.util.HashSet();
802         while ( parser.nextTag() == XmlPullParser.START_TAG )
803         {
804             if ( checkFieldWithDuplicate( parser, "title", null, parsed ) )
805             {
806                 properties.setTitle( getTrimmedValue( parser.nextText() ) );
807             }
808             else if ( checkFieldWithDuplicate( parser, "author", null, parsed ) )
809             {
810                 properties.setAuthor( parseAuthor( "author", parser, strict ) );
811             }
812             else
813             {
814                 if ( strict )
815                 {
816                     throw new XmlPullParserException( "Unrecognised tag: '" + parser.getName() + "'", parser, null );
817                 }
818                 else
819                 {
820                     // swallow up to end tag since this is not valid
821                     while ( parser.next() != XmlPullParser.END_TAG ) {}
822                 }
823             }
824         }
825         return properties;
826     } //-- Properties parseProperties( String, XmlPullParser, boolean )
827 
828     /**
829      * Method parseRelease.
830      * 
831      * @param tagName
832      * @param strict
833      * @param parser
834      * @throws IOException
835      * @throws XmlPullParserException
836      * @return Release
837      */
838     private Release parseRelease( String tagName, XmlPullParser parser, boolean strict )
839         throws IOException, XmlPullParserException
840     {
841         Release release = new Release();
842         if ( parser.getAttributeValue( "", "version" ) != null  )
843         {
844             release.setVersion( getTrimmedValue( parser.getAttributeValue( "", "version" ) ) );
845         }
846         if ( parser.getAttributeValue( "", "date" ) != null  )
847         {
848             release.setDateRelease( getTrimmedValue( parser.getAttributeValue( "", "date" ) ) );
849         }
850         if ( parser.getAttributeValue( "", "description" ) != null  )
851         {
852             release.setDescription( getTrimmedValue( parser.getAttributeValue( "", "description" ) ) );
853         }
854         java.util.Set parsed = new java.util.HashSet();
855         while ( parser.nextTag() == XmlPullParser.START_TAG )
856         {
857             if ( parser.getName().equals( "action" ) )
858             {
859                 java.util.List actions = release.getActions();
860                 if ( actions == null )
861                 {
862                     actions = new java.util.ArrayList/*<Action>*/();
863                     release.setActions( actions );
864                 }
865                 actions.add( parseAction( "action", parser, strict ) );
866             }
867             else
868             {
869                 if ( strict )
870                 {
871                     throw new XmlPullParserException( "Unrecognised tag: '" + parser.getName() + "'", parser, null );
872                 }
873                 else
874                 {
875                     // swallow up to end tag since this is not valid
876                     while ( parser.next() != XmlPullParser.END_TAG ) {}
877                 }
878             }
879         }
880         return release;
881     } //-- Release parseRelease( String, XmlPullParser, boolean )
882 
883     /**
884      * @see ReaderFactory#newXmlReader
885      * 
886      * @param reader
887      * @param strict
888      * @throws IOException
889      * @throws XmlPullParserException
890      * @return ChangesDocument
891      */
892     public ChangesDocument read( Reader reader, boolean strict )
893         throws IOException, XmlPullParserException
894     {
895         XmlPullParser parser = new MXParser();
896 
897         parser.setInput( reader );
898 
899         if ( addDefaultEntities )
900         {
901             // ----------------------------------------------------------------------
902             // Latin 1 entities
903             // ----------------------------------------------------------------------
904 
905             parser.defineEntityReplacementText( "nbsp", "\u00a0" );
906             parser.defineEntityReplacementText( "iexcl", "\u00a1" );
907             parser.defineEntityReplacementText( "cent", "\u00a2" );
908             parser.defineEntityReplacementText( "pound", "\u00a3" );
909             parser.defineEntityReplacementText( "curren", "\u00a4" );
910             parser.defineEntityReplacementText( "yen", "\u00a5" );
911             parser.defineEntityReplacementText( "brvbar", "\u00a6" );
912             parser.defineEntityReplacementText( "sect", "\u00a7" );
913             parser.defineEntityReplacementText( "uml", "\u00a8" );
914             parser.defineEntityReplacementText( "copy", "\u00a9" );
915             parser.defineEntityReplacementText( "ordf", "\u00aa" );
916             parser.defineEntityReplacementText( "laquo", "\u00ab" );
917             parser.defineEntityReplacementText( "not", "\u00ac" );
918             parser.defineEntityReplacementText( "shy", "\u00ad" );
919             parser.defineEntityReplacementText( "reg", "\u00ae" );
920             parser.defineEntityReplacementText( "macr", "\u00af" );
921             parser.defineEntityReplacementText( "deg", "\u00b0" );
922             parser.defineEntityReplacementText( "plusmn", "\u00b1" );
923             parser.defineEntityReplacementText( "sup2", "\u00b2" );
924             parser.defineEntityReplacementText( "sup3", "\u00b3" );
925             parser.defineEntityReplacementText( "acute", "\u00b4" );
926             parser.defineEntityReplacementText( "micro", "\u00b5" );
927             parser.defineEntityReplacementText( "para", "\u00b6" );
928             parser.defineEntityReplacementText( "middot", "\u00b7" );
929             parser.defineEntityReplacementText( "cedil", "\u00b8" );
930             parser.defineEntityReplacementText( "sup1", "\u00b9" );
931             parser.defineEntityReplacementText( "ordm", "\u00ba" );
932             parser.defineEntityReplacementText( "raquo", "\u00bb" );
933             parser.defineEntityReplacementText( "frac14", "\u00bc" );
934             parser.defineEntityReplacementText( "frac12", "\u00bd" );
935             parser.defineEntityReplacementText( "frac34", "\u00be" );
936             parser.defineEntityReplacementText( "iquest", "\u00bf" );
937             parser.defineEntityReplacementText( "Agrave", "\u00c0" );
938             parser.defineEntityReplacementText( "Aacute", "\u00c1" );
939             parser.defineEntityReplacementText( "Acirc", "\u00c2" );
940             parser.defineEntityReplacementText( "Atilde", "\u00c3" );
941             parser.defineEntityReplacementText( "Auml", "\u00c4" );
942             parser.defineEntityReplacementText( "Aring", "\u00c5" );
943             parser.defineEntityReplacementText( "AElig", "\u00c6" );
944             parser.defineEntityReplacementText( "Ccedil", "\u00c7" );
945             parser.defineEntityReplacementText( "Egrave", "\u00c8" );
946             parser.defineEntityReplacementText( "Eacute", "\u00c9" );
947             parser.defineEntityReplacementText( "Ecirc", "\u00ca" );
948             parser.defineEntityReplacementText( "Euml", "\u00cb" );
949             parser.defineEntityReplacementText( "Igrave", "\u00cc" );
950             parser.defineEntityReplacementText( "Iacute", "\u00cd" );
951             parser.defineEntityReplacementText( "Icirc", "\u00ce" );
952             parser.defineEntityReplacementText( "Iuml", "\u00cf" );
953             parser.defineEntityReplacementText( "ETH", "\u00d0" );
954             parser.defineEntityReplacementText( "Ntilde", "\u00d1" );
955             parser.defineEntityReplacementText( "Ograve", "\u00d2" );
956             parser.defineEntityReplacementText( "Oacute", "\u00d3" );
957             parser.defineEntityReplacementText( "Ocirc", "\u00d4" );
958             parser.defineEntityReplacementText( "Otilde", "\u00d5" );
959             parser.defineEntityReplacementText( "Ouml", "\u00d6" );
960             parser.defineEntityReplacementText( "times", "\u00d7" );
961             parser.defineEntityReplacementText( "Oslash", "\u00d8" );
962             parser.defineEntityReplacementText( "Ugrave", "\u00d9" );
963             parser.defineEntityReplacementText( "Uacute", "\u00da" );
964             parser.defineEntityReplacementText( "Ucirc", "\u00db" );
965             parser.defineEntityReplacementText( "Uuml", "\u00dc" );
966             parser.defineEntityReplacementText( "Yacute", "\u00dd" );
967             parser.defineEntityReplacementText( "THORN", "\u00de" );
968             parser.defineEntityReplacementText( "szlig", "\u00df" );
969             parser.defineEntityReplacementText( "agrave", "\u00e0" );
970             parser.defineEntityReplacementText( "aacute", "\u00e1" );
971             parser.defineEntityReplacementText( "acirc", "\u00e2" );
972             parser.defineEntityReplacementText( "atilde", "\u00e3" );
973             parser.defineEntityReplacementText( "auml", "\u00e4" );
974             parser.defineEntityReplacementText( "aring", "\u00e5" );
975             parser.defineEntityReplacementText( "aelig", "\u00e6" );
976             parser.defineEntityReplacementText( "ccedil", "\u00e7" );
977             parser.defineEntityReplacementText( "egrave", "\u00e8" );
978             parser.defineEntityReplacementText( "eacute", "\u00e9" );
979             parser.defineEntityReplacementText( "ecirc", "\u00ea" );
980             parser.defineEntityReplacementText( "euml", "\u00eb" );
981             parser.defineEntityReplacementText( "igrave", "\u00ec" );
982             parser.defineEntityReplacementText( "iacute", "\u00ed" );
983             parser.defineEntityReplacementText( "icirc", "\u00ee" );
984             parser.defineEntityReplacementText( "iuml", "\u00ef" );
985             parser.defineEntityReplacementText( "eth", "\u00f0" );
986             parser.defineEntityReplacementText( "ntilde", "\u00f1" );
987             parser.defineEntityReplacementText( "ograve", "\u00f2" );
988             parser.defineEntityReplacementText( "oacute", "\u00f3" );
989             parser.defineEntityReplacementText( "ocirc", "\u00f4" );
990             parser.defineEntityReplacementText( "otilde", "\u00f5" );
991             parser.defineEntityReplacementText( "ouml", "\u00f6" );
992             parser.defineEntityReplacementText( "divide", "\u00f7" );
993             parser.defineEntityReplacementText( "oslash", "\u00f8" );
994             parser.defineEntityReplacementText( "ugrave", "\u00f9" );
995             parser.defineEntityReplacementText( "uacute", "\u00fa" );
996             parser.defineEntityReplacementText( "ucirc", "\u00fb" );
997             parser.defineEntityReplacementText( "uuml", "\u00fc" );
998             parser.defineEntityReplacementText( "yacute", "\u00fd" );
999             parser.defineEntityReplacementText( "thorn", "\u00fe" );
1000             parser.defineEntityReplacementText( "yuml", "\u00ff" );
1001 
1002             // ----------------------------------------------------------------------
1003             // Special entities
1004             // ----------------------------------------------------------------------
1005 
1006             parser.defineEntityReplacementText( "OElig", "\u0152" );
1007             parser.defineEntityReplacementText( "oelig", "\u0153" );
1008             parser.defineEntityReplacementText( "Scaron", "\u0160" );
1009             parser.defineEntityReplacementText( "scaron", "\u0161" );
1010             parser.defineEntityReplacementText( "Yuml", "\u0178" );
1011             parser.defineEntityReplacementText( "circ", "\u02c6" );
1012             parser.defineEntityReplacementText( "tilde", "\u02dc" );
1013             parser.defineEntityReplacementText( "ensp", "\u2002" );
1014             parser.defineEntityReplacementText( "emsp", "\u2003" );
1015             parser.defineEntityReplacementText( "thinsp", "\u2009" );
1016             parser.defineEntityReplacementText( "zwnj", "\u200c" );
1017             parser.defineEntityReplacementText( "zwj", "\u200d" );
1018             parser.defineEntityReplacementText( "lrm", "\u200e" );
1019             parser.defineEntityReplacementText( "rlm", "\u200f" );
1020             parser.defineEntityReplacementText( "ndash", "\u2013" );
1021             parser.defineEntityReplacementText( "mdash", "\u2014" );
1022             parser.defineEntityReplacementText( "lsquo", "\u2018" );
1023             parser.defineEntityReplacementText( "rsquo", "\u2019" );
1024             parser.defineEntityReplacementText( "sbquo", "\u201a" );
1025             parser.defineEntityReplacementText( "ldquo", "\u201c" );
1026             parser.defineEntityReplacementText( "rdquo", "\u201d" );
1027             parser.defineEntityReplacementText( "bdquo", "\u201e" );
1028             parser.defineEntityReplacementText( "dagger", "\u2020" );
1029             parser.defineEntityReplacementText( "Dagger", "\u2021" );
1030             parser.defineEntityReplacementText( "permil", "\u2030" );
1031             parser.defineEntityReplacementText( "lsaquo", "\u2039" );
1032             parser.defineEntityReplacementText( "rsaquo", "\u203a" );
1033             parser.defineEntityReplacementText( "euro", "\u20ac" );
1034 
1035             // ----------------------------------------------------------------------
1036             // Symbol entities
1037             // ----------------------------------------------------------------------
1038 
1039             parser.defineEntityReplacementText( "fnof", "\u0192" );
1040             parser.defineEntityReplacementText( "Alpha", "\u0391" );
1041             parser.defineEntityReplacementText( "Beta", "\u0392" );
1042             parser.defineEntityReplacementText( "Gamma", "\u0393" );
1043             parser.defineEntityReplacementText( "Delta", "\u0394" );
1044             parser.defineEntityReplacementText( "Epsilon", "\u0395" );
1045             parser.defineEntityReplacementText( "Zeta", "\u0396" );
1046             parser.defineEntityReplacementText( "Eta", "\u0397" );
1047             parser.defineEntityReplacementText( "Theta", "\u0398" );
1048             parser.defineEntityReplacementText( "Iota", "\u0399" );
1049             parser.defineEntityReplacementText( "Kappa", "\u039a" );
1050             parser.defineEntityReplacementText( "Lambda", "\u039b" );
1051             parser.defineEntityReplacementText( "Mu", "\u039c" );
1052             parser.defineEntityReplacementText( "Nu", "\u039d" );
1053             parser.defineEntityReplacementText( "Xi", "\u039e" );
1054             parser.defineEntityReplacementText( "Omicron", "\u039f" );
1055             parser.defineEntityReplacementText( "Pi", "\u03a0" );
1056             parser.defineEntityReplacementText( "Rho", "\u03a1" );
1057             parser.defineEntityReplacementText( "Sigma", "\u03a3" );
1058             parser.defineEntityReplacementText( "Tau", "\u03a4" );
1059             parser.defineEntityReplacementText( "Upsilon", "\u03a5" );
1060             parser.defineEntityReplacementText( "Phi", "\u03a6" );
1061             parser.defineEntityReplacementText( "Chi", "\u03a7" );
1062             parser.defineEntityReplacementText( "Psi", "\u03a8" );
1063             parser.defineEntityReplacementText( "Omega", "\u03a9" );
1064             parser.defineEntityReplacementText( "alpha", "\u03b1" );
1065             parser.defineEntityReplacementText( "beta", "\u03b2" );
1066             parser.defineEntityReplacementText( "gamma", "\u03b3" );
1067             parser.defineEntityReplacementText( "delta", "\u03b4" );
1068             parser.defineEntityReplacementText( "epsilon", "\u03b5" );
1069             parser.defineEntityReplacementText( "zeta", "\u03b6" );
1070             parser.defineEntityReplacementText( "eta", "\u03b7" );
1071             parser.defineEntityReplacementText( "theta", "\u03b8" );
1072             parser.defineEntityReplacementText( "iota", "\u03b9" );
1073             parser.defineEntityReplacementText( "kappa", "\u03ba" );
1074             parser.defineEntityReplacementText( "lambda", "\u03bb" );
1075             parser.defineEntityReplacementText( "mu", "\u03bc" );
1076             parser.defineEntityReplacementText( "nu", "\u03bd" );
1077             parser.defineEntityReplacementText( "xi", "\u03be" );
1078             parser.defineEntityReplacementText( "omicron", "\u03bf" );
1079             parser.defineEntityReplacementText( "pi", "\u03c0" );
1080             parser.defineEntityReplacementText( "rho", "\u03c1" );
1081             parser.defineEntityReplacementText( "sigmaf", "\u03c2" );
1082             parser.defineEntityReplacementText( "sigma", "\u03c3" );
1083             parser.defineEntityReplacementText( "tau", "\u03c4" );
1084             parser.defineEntityReplacementText( "upsilon", "\u03c5" );
1085             parser.defineEntityReplacementText( "phi", "\u03c6" );
1086             parser.defineEntityReplacementText( "chi", "\u03c7" );
1087             parser.defineEntityReplacementText( "psi", "\u03c8" );
1088             parser.defineEntityReplacementText( "omega", "\u03c9" );
1089             parser.defineEntityReplacementText( "thetasym", "\u03d1" );
1090             parser.defineEntityReplacementText( "upsih", "\u03d2" );
1091             parser.defineEntityReplacementText( "piv", "\u03d6" );
1092             parser.defineEntityReplacementText( "bull", "\u2022" );
1093             parser.defineEntityReplacementText( "hellip", "\u2026" );
1094             parser.defineEntityReplacementText( "prime", "\u2032" );
1095             parser.defineEntityReplacementText( "Prime", "\u2033" );
1096             parser.defineEntityReplacementText( "oline", "\u203e" );
1097             parser.defineEntityReplacementText( "frasl", "\u2044" );
1098             parser.defineEntityReplacementText( "weierp", "\u2118" );
1099             parser.defineEntityReplacementText( "image", "\u2111" );
1100             parser.defineEntityReplacementText( "real", "\u211c" );
1101             parser.defineEntityReplacementText( "trade", "\u2122" );
1102             parser.defineEntityReplacementText( "alefsym", "\u2135" );
1103             parser.defineEntityReplacementText( "larr", "\u2190" );
1104             parser.defineEntityReplacementText( "uarr", "\u2191" );
1105             parser.defineEntityReplacementText( "rarr", "\u2192" );
1106             parser.defineEntityReplacementText( "darr", "\u2193" );
1107             parser.defineEntityReplacementText( "harr", "\u2194" );
1108             parser.defineEntityReplacementText( "crarr", "\u21b5" );
1109             parser.defineEntityReplacementText( "lArr", "\u21d0" );
1110             parser.defineEntityReplacementText( "uArr", "\u21d1" );
1111             parser.defineEntityReplacementText( "rArr", "\u21d2" );
1112             parser.defineEntityReplacementText( "dArr", "\u21d3" );
1113             parser.defineEntityReplacementText( "hArr", "\u21d4" );
1114             parser.defineEntityReplacementText( "forall", "\u2200" );
1115             parser.defineEntityReplacementText( "part", "\u2202" );
1116             parser.defineEntityReplacementText( "exist", "\u2203" );
1117             parser.defineEntityReplacementText( "empty", "\u2205" );
1118             parser.defineEntityReplacementText( "nabla", "\u2207" );
1119             parser.defineEntityReplacementText( "isin", "\u2208" );
1120             parser.defineEntityReplacementText( "notin", "\u2209" );
1121             parser.defineEntityReplacementText( "ni", "\u220b" );
1122             parser.defineEntityReplacementText( "prod", "\u220f" );
1123             parser.defineEntityReplacementText( "sum", "\u2211" );
1124             parser.defineEntityReplacementText( "minus", "\u2212" );
1125             parser.defineEntityReplacementText( "lowast", "\u2217" );
1126             parser.defineEntityReplacementText( "radic", "\u221a" );
1127             parser.defineEntityReplacementText( "prop", "\u221d" );
1128             parser.defineEntityReplacementText( "infin", "\u221e" );
1129             parser.defineEntityReplacementText( "ang", "\u2220" );
1130             parser.defineEntityReplacementText( "and", "\u2227" );
1131             parser.defineEntityReplacementText( "or", "\u2228" );
1132             parser.defineEntityReplacementText( "cap", "\u2229" );
1133             parser.defineEntityReplacementText( "cup", "\u222a" );
1134             parser.defineEntityReplacementText( "int", "\u222b" );
1135             parser.defineEntityReplacementText( "there4", "\u2234" );
1136             parser.defineEntityReplacementText( "sim", "\u223c" );
1137             parser.defineEntityReplacementText( "cong", "\u2245" );
1138             parser.defineEntityReplacementText( "asymp", "\u2248" );
1139             parser.defineEntityReplacementText( "ne", "\u2260" );
1140             parser.defineEntityReplacementText( "equiv", "\u2261" );
1141             parser.defineEntityReplacementText( "le", "\u2264" );
1142             parser.defineEntityReplacementText( "ge", "\u2265" );
1143             parser.defineEntityReplacementText( "sub", "\u2282" );
1144             parser.defineEntityReplacementText( "sup", "\u2283" );
1145             parser.defineEntityReplacementText( "nsub", "\u2284" );
1146             parser.defineEntityReplacementText( "sube", "\u2286" );
1147             parser.defineEntityReplacementText( "supe", "\u2287" );
1148             parser.defineEntityReplacementText( "oplus", "\u2295" );
1149             parser.defineEntityReplacementText( "otimes", "\u2297" );
1150             parser.defineEntityReplacementText( "perp", "\u22a5" );
1151             parser.defineEntityReplacementText( "sdot", "\u22c5" );
1152             parser.defineEntityReplacementText( "lceil", "\u2308" );
1153             parser.defineEntityReplacementText( "rceil", "\u2309" );
1154             parser.defineEntityReplacementText( "lfloor", "\u230a" );
1155             parser.defineEntityReplacementText( "rfloor", "\u230b" );
1156             parser.defineEntityReplacementText( "lang", "\u2329" );
1157             parser.defineEntityReplacementText( "rang", "\u232a" );
1158             parser.defineEntityReplacementText( "loz", "\u25ca" );
1159             parser.defineEntityReplacementText( "spades", "\u2660" );
1160             parser.defineEntityReplacementText( "clubs", "\u2663" );
1161             parser.defineEntityReplacementText( "hearts", "\u2665" );
1162             parser.defineEntityReplacementText( "diams", "\u2666" );
1163 
1164         }
1165 
1166         parser.next();
1167         return parseChangesDocument( "document", parser, strict );
1168     } //-- ChangesDocument read( Reader, boolean )
1169 
1170     /**
1171      * @see ReaderFactory#newXmlReader
1172      * 
1173      * @param reader
1174      * @throws IOException
1175      * @throws XmlPullParserException
1176      * @return ChangesDocument
1177      */
1178     public ChangesDocument read( Reader reader )
1179         throws IOException, XmlPullParserException
1180     {
1181         return read( reader, true );
1182     } //-- ChangesDocument read( Reader )
1183 
1184     /**
1185      * Method read.
1186      * 
1187      * @param in
1188      * @param strict
1189      * @throws IOException
1190      * @throws XmlPullParserException
1191      * @return ChangesDocument
1192      */
1193     public ChangesDocument read( InputStream in, boolean strict )
1194         throws IOException, XmlPullParserException
1195     {
1196         Reader reader = ReaderFactory.newXmlReader( in );
1197 
1198         return read( reader, strict );
1199     } //-- ChangesDocument read( InputStream, boolean )
1200 
1201     /**
1202      * Method read.
1203      * 
1204      * @param in
1205      * @throws IOException
1206      * @throws XmlPullParserException
1207      * @return ChangesDocument
1208      */
1209     public ChangesDocument read( InputStream in )
1210         throws IOException, XmlPullParserException
1211     {
1212         Reader reader = ReaderFactory.newXmlReader( in );
1213 
1214         return read( reader );
1215     } //-- ChangesDocument read( InputStream )
1216 
1217     /**
1218      * Sets the state of the "add default entities" flag.
1219      * 
1220      * @param addDefaultEntities
1221      */
1222     public void setAddDefaultEntities( boolean addDefaultEntities )
1223     {
1224         this.addDefaultEntities = addDefaultEntities;
1225     } //-- void setAddDefaultEntities( boolean )
1226 
1227 
1228 }