001/* Generated By:JavaCC: Do not edit this line. VersionParser.java */
002/*
003 *  jDTAUS Core RI Client Container
004 *  Copyright (C) 2005 Christian Schulte
005 *  <cs@schulte.it>
006 *
007 *  This library is free software; you can redistribute it and/or
008 *  modify it under the terms of the GNU Lesser General Public
009 *  License as published by the Free Software Foundation; either
010 *  version 2.1 of the License, or any later version.
011 *
012 *  This library is distributed in the hope that it will be useful,
013 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
014 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
015 *  Lesser General Public License for more details.
016 *
017 *  You should have received a copy of the GNU Lesser General Public
018 *  License along with this library; if not, write to the Free Software
019 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
020 *
021 *  $JDTAUS: VersionParser.jj 8641 2012-09-27 06:45:17Z schulte $
022 *
023 */
024package org.jdtaus.core.container.ri.client.versioning;
025
026import java.io.StringReader;
027import java.util.List;
028import java.util.LinkedList;
029import java.util.Locale;
030import java.text.NumberFormat;
031
032/**
033 * Parses version identifiers.
034 * <p><blockquote><pre>
035 * Version    ::= Token ( ( &lt;SEPARATOR&gt; )* Token )* &lt;EOF&gt;
036 * Token      ::= &lt;INTEGER&gt;
037 *              | &lt;IDENTIFIER&gt;
038 * </pre></blockquote></p>
039 * <p>
040 * A separator character is defined as<blockquote><pre>
041 * [".","_","-","@","/","\\"," ","\t","\n","\r","\f","\b","\"","\'"]</pre></blockquote>
042 * An integer is a sequence of digits. An identifier is everything else, not
043 * a separator character or an integer.
044 * </p>
045 *
046 * @author <a href="mailto:cs@schulte.it">Christian Schulte</a>
047 * @version $JDTAUS: VersionParser.jj 8641 2012-09-27 06:45:17Z schulte $
048 * @see #compare(String, String)
049 */
050public final class VersionParser implements VersionParserConstants {
051
052  /**
053   * Parses the input to produce an array of tokens.
054   *
055   * @return the parsed tokens.
056   *
057   * @throws ParseException if the parse fails.
058   */
059  public Token[] parse() throws ParseException
060  {
061    return this.Version();
062  }
063
064  /**
065   * Compares two versions for order.
066   * <p>This method parses the given strings to produce a sequence of tokens
067   * and then compares these tokens for order.</p>
068   *
069   * @param v1 the version to compare with.
070   * @param v2 the version to compare to.
071   *
072   * @return a negative integer, zero, or a positive integer as the first
073   * version is less than, equal to, or greater than the second.
074   *
075   * @throws NullPointerException if {@code v1} or {@code v2} is {@code null}.
076   * @throws java.text.ParseException if parsing fails.
077   */
078  public static int compare( final String v1, final String v2 )
079    throws java.text.ParseException
080  {
081    if ( v1 == null )
082    {
083      throw new NullPointerException( "v1" );
084    }
085    if ( v2 == null )
086    {
087      throw new NullPointerException( "v2" );
088    }
089
090    try
091    {
092      final NumberFormat format =
093        NumberFormat.getNumberInstance( Locale.ENGLISH );
094
095      final VersionParser versionParser =
096        new VersionParser( new StringReader( v1 ) );
097
098      final Token[] c = versionParser.parse();
099
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}