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 ( ( <SEPARATOR> )* Token )* <EOF> 036 * Token ::= <INTEGER> 037 * | <IDENTIFIER> 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}