View Javadoc

1   /* Generated By:JavaCC: Do not edit this line. VersionParser.java */
2   /*
3    *  jDTAUS Core RI Client Container
4    *  Copyright (C) 2005 Christian Schulte
5    *  <cs@schulte.it>
6    *
7    *  This library is free software; you can redistribute it and/or
8    *  modify it under the terms of the GNU Lesser General Public
9    *  License as published by the Free Software Foundation; either
10   *  version 2.1 of the License, or any later version.
11   *
12   *  This library is distributed in the hope that it will be useful,
13   *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14   *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15   *  Lesser General Public License for more details.
16   *
17   *  You should have received a copy of the GNU Lesser General Public
18   *  License along with this library; if not, write to the Free Software
19   *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20   *
21   *  $JDTAUS: VersionParser.jj 8641 2012-09-27 06:45:17Z schulte $
22   *
23   */
24  package org.jdtaus.core.container.ri.client.versioning;
25  
26  import java.io.StringReader;
27  import java.util.List;
28  import java.util.LinkedList;
29  import java.util.Locale;
30  import java.text.NumberFormat;
31  
32  /**
33   * Parses version identifiers.
34   * <p><blockquote><pre>
35   * Version    ::= Token ( ( &lt;SEPARATOR&gt; )* Token )* &lt;EOF&gt;
36   * Token      ::= &lt;INTEGER&gt;
37   *              | &lt;IDENTIFIER&gt;
38   * </pre></blockquote></p>
39   * <p>
40   * A separator character is defined as<blockquote><pre>
41   * [".","_","-","@","/","\\"," ","\t","\n","\r","\f","\b","\"","\'"]</pre></blockquote>
42   * An integer is a sequence of digits. An identifier is everything else, not
43   * a separator character or an integer.
44   * </p>
45   *
46   * @author <a href="mailto:cs@schulte.it">Christian Schulte</a>
47   * @version $JDTAUS: VersionParser.jj 8641 2012-09-27 06:45:17Z schulte $
48   * @see #compare(String, String)
49   */
50  public final class VersionParser implements VersionParserConstants {
51  
52    /**
53     * Parses the input to produce an array of tokens.
54     *
55     * @return the parsed tokens.
56     *
57     * @throws ParseException if the parse fails.
58     */
59    public Token[] parse() throws ParseException
60    {
61      return this.Version();
62    }
63  
64    /**
65     * Compares two versions for order.
66     * <p>This method parses the given strings to produce a sequence of tokens
67     * and then compares these tokens for order.</p>
68     *
69     * @param v1 the version to compare with.
70     * @param v2 the version to compare to.
71     *
72     * @return a negative integer, zero, or a positive integer as the first
73     * version is less than, equal to, or greater than the second.
74     *
75     * @throws NullPointerException if {@code v1} or {@code v2} is {@code null}.
76     * @throws java.text.ParseException if parsing fails.
77     */
78    public static int compare( final String v1, final String v2 )
79      throws java.text.ParseException
80    {
81      if ( v1 == null )
82      {
83        throw new NullPointerException( "v1" );
84      }
85      if ( v2 == null )
86      {
87        throw new NullPointerException( "v2" );
88      }
89  
90      try
91      {
92        final NumberFormat format =
93          NumberFormat.getNumberInstance( Locale.ENGLISH );
94  
95        final VersionParser versionParser =
96          new VersionParser( new StringReader( v1 ) );
97  
98        final Token[] c = versionParser.parse();
99  
100       versionParser.ReInit( new StringReader( v2 ) );
101       final Token[] r = versionParser.parse();
102 
103       final int len = Math.max( c.length, r.length );
104 
105       int result = 0;
106 
107       for ( int i = 0; i < len; i++ )
108       {
109         final Token current;
110         final Token spec;
111 
112         if ( i < c.length )
113         {
114           current = c[i];
115         }
116         else
117         {
118           current = new Token();
119           current.kind = r[i].kind;
120 
121           if ( r[i].kind == VersionParserConstants.IDENTIFIER )
122           {
123             // If a version has less tokens than another, comparison is stopped
124             // at the first identifier. Remaining tokens are considered suffices
125             // less than the shorter version.
126             result = 1;
127             break;
128           }
129           else if ( r[i].kind == VersionParserConstants.INTEGER )
130           {
131             current.image = "0";
132           }
133         }
134 
135         if ( i < r.length )
136         {
137           spec = r[i];
138         }
139         else
140         {
141           spec = new Token();
142           spec.kind = c[i].kind;
143 
144           if ( c[i].kind == VersionParserConstants.IDENTIFIER )
145           {
146             // If a version has less tokens than another, comparison is stopped
147             // at the first identifier. Remaining tokens are considered suffices
148             // less than the shorter version.
149             result = -1;
150             break;
151           }
152           else if ( c[i].kind == VersionParserConstants.INTEGER )
153           {
154             spec.image = "0";
155           }
156         }
157 
158         if ( current.kind != spec.kind )
159         {
160           throw new java.text.ParseException ( "Cannot compare '" +
161               current.image +"' to '" + spec.image + "' for input '" + v1 +
162               "' and '" + v2 + "'.", i );
163 
164         }
165 
166         if ( current.kind == VersionParserConstants.IDENTIFIER )
167         {
168           result = current.image.compareTo( spec.image );
169           if ( result != 0 )
170           {
171             break;
172           }
173         }
174         else if ( current.kind == VersionParserConstants.INTEGER )
175         {
176           final Long m = (Long) format.parse( current.image );
177           final Long n = (Long) format.parse( spec.image );
178 
179           result = m.compareTo( n );
180 
181           if ( result != 0 )
182           {
183             break;
184           }
185         }
186         else
187         {
188           // Unsupported tokens are compared lexicographically by default.
189           result = current.image.compareTo( spec.image );
190           if ( result != 0 )
191           {
192             break;
193           }
194         }
195       }
196 
197       return result;
198     }
199     catch ( ParseException e )
200     {
201       final java.text.ParseException pe =
202         new java.text.ParseException( e.getMessage(),
203                                       e.currentToken.beginColumn );
204 
205       pe.initCause ( e );
206       throw pe;
207     }
208     catch ( TokenMgrError e )
209     {
210       final java.text.ParseException pe =
211         new java.text.ParseException( e.getMessage(),
212                                       e.errorCode );
213 
214       pe.initCause ( e );
215       throw pe;
216     }
217   }
218 
219   final private Token[] Version() throws ParseException {
220     final List tokens = new LinkedList();
221     Token(tokens);
222     label_1:
223     while (true) {
224       switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
225       case INTEGER:
226       case SEPARATOR:
227       case IDENTIFIER:
228         ;
229         break;
230       default:
231         jj_la1[0] = jj_gen;
232         break label_1;
233       }
234       label_2:
235       while (true) {
236         switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
237         case SEPARATOR:
238           ;
239           break;
240         default:
241           jj_la1[1] = jj_gen;
242           break label_2;
243         }
244         jj_consume_token(SEPARATOR);
245       }
246       Token(tokens);
247     }
248     jj_consume_token(0);
249     {if (true) return (Token[]) tokens.toArray(new Token[tokens.size()]);}
250     throw new Error("Missing return statement in function");
251   }
252 
253   final private void Token(final List tokens) throws ParseException {
254     Token part;
255     switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
256     case INTEGER:
257       part = jj_consume_token(INTEGER);
258                      tokens.add ( part );
259       break;
260     case IDENTIFIER:
261       part = jj_consume_token(IDENTIFIER);
262                         tokens.add( part );
263       break;
264     default:
265       jj_la1[2] = jj_gen;
266       jj_consume_token(-1);
267       throw new ParseException();
268     }
269   }
270 
271   /** Generated Token Manager. */
272   public VersionParserTokenManager token_source;
273   SimpleCharStream jj_input_stream;
274   /** Current token. */
275   public Token token;
276   /** Next token. */
277   public Token jj_nt;
278   private int jj_ntk;
279   private int jj_gen;
280   final private int[] jj_la1 = new int[3];
281   static private int[] jj_la1_0;
282   static {
283       jj_la1_init_0();
284    }
285    private static void jj_la1_init_0() {
286       jj_la1_0 = new int[] {0xe,0x4,0xa,};
287    }
288 
289   /** Constructor with InputStream. */
290   public VersionParser(java.io.InputStream stream) {
291      this(stream, null);
292   }
293   /** Constructor with InputStream and supplied encoding */
294   public VersionParser(java.io.InputStream stream, String encoding) {
295     try { jj_input_stream = new SimpleCharStream(stream, encoding, 1, 1); } catch(java.io.UnsupportedEncodingException e) { throw new RuntimeException(e); }
296     token_source = new VersionParserTokenManager(jj_input_stream);
297     token = new Token();
298     jj_ntk = -1;
299     jj_gen = 0;
300     for (int i = 0; i < 3; i++) jj_la1[i] = -1;
301   }
302 
303   /** Reinitialise. */
304   public void ReInit(java.io.InputStream stream) {
305      ReInit(stream, null);
306   }
307   /** Reinitialise. */
308   public void ReInit(java.io.InputStream stream, String encoding) {
309     try { jj_input_stream.ReInit(stream, encoding, 1, 1); } catch(java.io.UnsupportedEncodingException e) { throw new RuntimeException(e); }
310     token_source.ReInit(jj_input_stream);
311     token = new Token();
312     jj_ntk = -1;
313     jj_gen = 0;
314     for (int i = 0; i < 3; i++) jj_la1[i] = -1;
315   }
316 
317   /** Constructor. */
318   public VersionParser(java.io.Reader stream) {
319     jj_input_stream = new SimpleCharStream(stream, 1, 1);
320     token_source = new VersionParserTokenManager(jj_input_stream);
321     token = new Token();
322     jj_ntk = -1;
323     jj_gen = 0;
324     for (int i = 0; i < 3; i++) jj_la1[i] = -1;
325   }
326 
327   /** Reinitialise. */
328   public void ReInit(java.io.Reader stream) {
329     jj_input_stream.ReInit(stream, 1, 1);
330     token_source.ReInit(jj_input_stream);
331     token = new Token();
332     jj_ntk = -1;
333     jj_gen = 0;
334     for (int i = 0; i < 3; i++) jj_la1[i] = -1;
335   }
336 
337   /** Constructor with generated Token Manager. */
338   public VersionParser(VersionParserTokenManager tm) {
339     token_source = tm;
340     token = new Token();
341     jj_ntk = -1;
342     jj_gen = 0;
343     for (int i = 0; i < 3; i++) jj_la1[i] = -1;
344   }
345 
346   /** Reinitialise. */
347   public void ReInit(VersionParserTokenManager tm) {
348     token_source = tm;
349     token = new Token();
350     jj_ntk = -1;
351     jj_gen = 0;
352     for (int i = 0; i < 3; i++) jj_la1[i] = -1;
353   }
354 
355   private Token jj_consume_token(int kind) throws ParseException {
356     Token oldToken;
357     if ((oldToken = token).next != null) token = token.next;
358     else token = token.next = token_source.getNextToken();
359     jj_ntk = -1;
360     if (token.kind == kind) {
361       jj_gen++;
362       return token;
363     }
364     token = oldToken;
365     jj_kind = kind;
366     throw generateParseException();
367   }
368 
369 
370 /** Get the next Token. */
371   final public Token getNextToken() {
372     if (token.next != null) token = token.next;
373     else token = token.next = token_source.getNextToken();
374     jj_ntk = -1;
375     jj_gen++;
376     return token;
377   }
378 
379 /** Get the specific Token. */
380   final public Token getToken(int index) {
381     Token t = token;
382     for (int i = 0; i < index; i++) {
383       if (t.next != null) t = t.next;
384       else t = t.next = token_source.getNextToken();
385     }
386     return t;
387   }
388 
389   private int jj_ntk() {
390     if ((jj_nt=token.next) == null)
391       return (jj_ntk = (token.next=token_source.getNextToken()).kind);
392     else
393       return (jj_ntk = jj_nt.kind);
394   }
395 
396   private java.util.List jj_expentries = new java.util.ArrayList();
397   private int[] jj_expentry;
398   private int jj_kind = -1;
399 
400   /** Generate ParseException. */
401   public ParseException generateParseException() {
402     jj_expentries.clear();
403     boolean[] la1tokens = new boolean[4];
404     if (jj_kind >= 0) {
405       la1tokens[jj_kind] = true;
406       jj_kind = -1;
407     }
408     for (int i = 0; i < 3; i++) {
409       if (jj_la1[i] == jj_gen) {
410         for (int j = 0; j < 32; j++) {
411           if ((jj_la1_0[i] & (1<<j)) != 0) {
412             la1tokens[j] = true;
413           }
414         }
415       }
416     }
417     for (int i = 0; i < 4; i++) {
418       if (la1tokens[i]) {
419         jj_expentry = new int[1];
420         jj_expentry[0] = i;
421         jj_expentries.add(jj_expentry);
422       }
423     }
424     int[][] exptokseq = new int[jj_expentries.size()][];
425     for (int i = 0; i < jj_expentries.size(); i++) {
426       exptokseq[i] = (int[])jj_expentries.get(i);
427     }
428     return new ParseException(token, exptokseq, tokenImage);
429   }
430 
431   /** Enable tracing. */
432   final public void enable_tracing() {
433   }
434 
435   /** Disable tracing. */
436   final public void disable_tracing() {
437   }
438 
439 }