// $ANTLR 2.7.2: "ValidWhenParser.g" -> "ValidWhenParser.java"$ /* * $Id: ValidWhenParser.java 54929 2004-10-16 16:38:42Z germuska $ * * Copyright 2003-2004 The Apache Software Foundation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.struts.validator.validwhen; import java.util.Stack; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.commons.validator.util.ValidatorUtils; import antlr.TokenBuffer; import antlr.TokenStreamException; import antlr.TokenStreamIOException; import antlr.ANTLRException; import antlr.LLkParser; import antlr.Token; import antlr.TokenStream; import antlr.RecognitionException; import antlr.NoViableAltException; import antlr.MismatchedTokenException; import antlr.SemanticException; import antlr.ParserSharedInputState; import antlr.collections.impl.BitSet; public class ValidWhenParser extends antlr.LLkParser implements ValidWhenParserTokenTypes { private static Log log = LogFactory.getLog(ValidWhenParser.class); Stack argStack = new Stack(); Object form; int index; String value; public void setForm(Object f) { form = f; }; public void setIndex (int i) { index = i; }; public void setValue (String v) { value = v; }; public boolean getResult() { return ((Boolean)argStack.peek()).booleanValue(); } private final int LESS_EQUAL=0; private final int LESS_THAN=1; private final int EQUAL=2; private final int GREATER_THAN=3; private final int GREATER_EQUAL=4; private final int NOT_EQUAL=5; private final int AND=6; private final int OR=7; /** * Modified by Nate Minshew on 12/28/2004. Added support for comparing * doubles as well as integers. * * @param v1 - First object to compare. * @param compare - Object representing the comparator. * @param v2 - Second object to compare. * @return boolean - Indicating whether the fields are valid. */ private boolean evaluateComparison (Object v1, Object compare, Object v2) { boolean intCompare = false; boolean doubleCompare = false; boolean unknown = false; if ((v1 == null) || (v2 == null)) { if (String.class.isInstance(v1)) { if (((String) v1).length() == 0) { v1 = null; } } if (String.class.isInstance(v2)) { if (((String) v2).length() == 0) { v2 = null; } } switch (((Integer)compare).intValue()) { case LESS_EQUAL: case GREATER_THAN: case LESS_THAN: case GREATER_EQUAL: return false; case EQUAL: return (v1 == v2); case NOT_EQUAL: return (v1 != v2); } } // Moved the check for a string to the end and added a check for objects // of type Double. if (Integer.class.isInstance(v1) && Integer.class.isInstance(v2)) { intCompare = true; } else if (Double.class.isInstance(v1) && Double.class.isInstance(v2)) { doubleCompare = true; } else if (String.class.isInstance(v1) && String.class.isInstance(v2)) { unknown = true; } // This means that the values are strings, which could mean they are // integers or doubles. Attempting here to determine of what type v1 // and v2 are to determine how to compare the 2. if (unknown) { try { Integer.parseInt((String) v1); Integer.parseInt((String) v2); intCompare = true; } catch (NumberFormatException e) { log.debug("Unable to parse value as an integer."); } try { Double.parseDouble((String) v1); Double.parseDouble((String) v2); doubleCompare = true; } catch (NumberFormatException e) { log.debug("Unable to parse value as a double."); } } if (intCompare) { // This means that v1 and v2 are of either type Java Integer or // primitive integer. This parses and compares the 2 values. try { int v1i = 0, v2i = 0; if (Integer.class.isInstance(v1)) { v1i = ((Integer)v1).intValue(); } else { v1i = Integer.parseInt((String) v1); } if (Integer.class.isInstance(v2) && intCompare) { v2i = ((Integer)v2).intValue(); } else { v2i = Integer.parseInt((String) v2); } switch (((Integer)compare).intValue()) { case LESS_EQUAL: return (v1i <= v2i); case LESS_THAN: return (v1i < v2i); case EQUAL: return (v1i == v2i); case GREATER_THAN: return (v1i > v2i); case GREATER_EQUAL: return (v1i >= v2i); case NOT_EQUAL: return (v1i != v2i); } } catch (NumberFormatException ex) { // This shouldn't happend since we do the check above. } } else if (doubleCompare) { // This means that v1 and v2 are either of type Java Double or // primitive double. Parsing and comparing the 2 values. try { double v1d = 0.0, v2d = 0.0; if (Double.class.isInstance(v1)) { v1d = ((Double) v1).doubleValue(); } else { v1d = Double.parseDouble((String) v1); } if (Double.class.isInstance(v2)) { v2d = ((Double) v2).doubleValue(); } else { v2d = Double.parseDouble((String) v2); } switch (((Integer)compare).intValue()) { case LESS_EQUAL: return (v1d <= v2d); case LESS_THAN: return (v1d < v2d); case EQUAL: return (v1d == v2d); case GREATER_THAN: return (v1d > v2d); case GREATER_EQUAL: return (v1d >= v2d); case NOT_EQUAL: return (v1d != v2d); } } catch (NumberFormatException e) { // This shouldn't happen since we do the check above. } } // If this code is reached then it means that v1 and v2 are neither of // double or integer type and should be handled with a string comparison. String v1s = "", v2s = ""; if (Integer.class.isInstance(v1)) { v1s = ((Integer)v1).toString(); } else if (Double.class.isInstance(v1)) { v1s = ((Double) v1).toString(); } else { v1s = (String) v1; } if (Integer.class.isInstance(v2)) { v2s = ((Integer)v2).toString(); } else if (Double.class.isInstance(v2)) { v2s = ((Double) v2).toString(); } else { v2s = (String) v2; } int res = v1s.compareTo(v2s); switch (((Integer)compare).intValue()) { case LESS_EQUAL: return (res <= 0); case LESS_THAN: return (res < 0); case EQUAL: return (res == 0); case GREATER_THAN: return (res > 0); case GREATER_EQUAL: return (res >= 0); case NOT_EQUAL: return (res != 0); } return true; } protected ValidWhenParser(TokenBuffer tokenBuf, int k) { super(tokenBuf,k); tokenNames = _tokenNames; } public ValidWhenParser(TokenBuffer tokenBuf) { this(tokenBuf,6); } protected ValidWhenParser(TokenStream lexer, int k) { super(lexer,k); tokenNames = _tokenNames; } public ValidWhenParser(TokenStream lexer) { this(lexer,6); } public ValidWhenParser(ParserSharedInputState state) { super(state,6); tokenNames = _tokenNames; } public final void integer() throws RecognitionException, TokenStreamException { Token d = null; Token h = null; Token o = null; switch ( LA(1)) { case DECIMAL_LITERAL: { d = LT(1); match(DECIMAL_LITERAL); argStack.push(Integer.decode(d.getText())); break; } case HEX_LITERAL: { h = LT(1); match(HEX_LITERAL); argStack.push(Integer.decode(h.getText())); break; } case OCTAL_LITERAL: { o = LT(1); match(OCTAL_LITERAL); argStack.push(Integer.decode(o.getText())); break; } default: { throw new NoViableAltException(LT(1), getFilename()); } } } public final void string() throws RecognitionException, TokenStreamException { Token str = null; str = LT(1); match(STRING_LITERAL); argStack.push(str.getText().substring(1, str.getText().length()-1)); } public final void identifier() throws RecognitionException, TokenStreamException { Token str = null; str = LT(1); match(IDENTIFIER); argStack.push(str.getText()); } public final void field() throws RecognitionException, TokenStreamException { if ((LA(1)==IDENTIFIER) && (LA(2)==LBRACKET) && (LA(3)==RBRACKET) && (LA(4)==IDENTIFIER)) { identifier(); match(LBRACKET); match(RBRACKET); identifier(); Object i2 = argStack.pop(); Object i1 = argStack.pop(); argStack.push(ValidatorUtils.getValueAsString(form, i1 + "[" + index + "]" + i2)); } else if ((LA(1)==IDENTIFIER) && (LA(2)==LBRACKET) && ((LA(3) >= DECIMAL_LITERAL && LA(3) <= OCTAL_LITERAL)) && (LA(4)==RBRACKET) && (LA(5)==IDENTIFIER)) { identifier(); match(LBRACKET); integer(); match(RBRACKET); identifier(); Object i5 = argStack.pop(); Object i4 = argStack.pop(); Object i3 = argStack.pop(); argStack.push(ValidatorUtils.getValueAsString(form, i3 + "[" + i4 + "]" + i5)); } else if ((LA(1)==IDENTIFIER) && (LA(2)==LBRACKET) && ((LA(3) >= DECIMAL_LITERAL && LA(3) <= OCTAL_LITERAL)) && (LA(4)==RBRACKET) && (LA(5)==LBRACKET)) { identifier(); match(LBRACKET); integer(); match(RBRACKET); match(LBRACKET); Object i7 = argStack.pop(); Object i6 = argStack.pop(); argStack.push(ValidatorUtils.getValueAsString(form, i6 + "[" + i7 + "]")); } else if ((LA(1)==IDENTIFIER) && (LA(2)==LBRACKET) && (LA(3)==RBRACKET) && (_tokenSet_0.member(LA(4)))) { identifier(); match(LBRACKET); match(RBRACKET); Object i8 = argStack.pop(); argStack.push(ValidatorUtils.getValueAsString(form, i8 + "[" + index + "]")); } else if ((LA(1)==IDENTIFIER) && (_tokenSet_0.member(LA(2)))) { identifier(); Object i9 = argStack.pop(); argStack.push(ValidatorUtils.getValueAsString(form, (String)i9)); } else { throw new NoViableAltException(LT(1), getFilename()); } } public final void literal() throws RecognitionException, TokenStreamException { switch ( LA(1)) { case DECIMAL_LITERAL: case HEX_LITERAL: case OCTAL_LITERAL: { integer(); break; } case STRING_LITERAL: { string(); break; } case LITERAL_null: { match(LITERAL_null); argStack.push(null); break; } case THIS: { match(THIS); argStack.push(value); break; } default: { throw new NoViableAltException(LT(1), getFilename()); } } } public final void value() throws RecognitionException, TokenStreamException { switch ( LA(1)) { case IDENTIFIER: { field(); break; } case DECIMAL_LITERAL: case HEX_LITERAL: case OCTAL_LITERAL: case STRING_LITERAL: case LITERAL_null: case THIS: { literal(); break; } default: { throw new NoViableAltException(LT(1), getFilename()); } } } public final void expression() throws RecognitionException, TokenStreamException { expr(); match(Token.EOF_TYPE); } public final void expr() throws RecognitionException, TokenStreamException { if ((LA(1)==LPAREN) && (_tokenSet_1.member(LA(2)))) { match(LPAREN); comparisonExpression(); match(RPAREN); } else if ((LA(1)==LPAREN) && (LA(2)==LPAREN)) { match(LPAREN); joinedExpression(); match(RPAREN); } else { throw new NoViableAltException(LT(1), getFilename()); } } public final void comparisonExpression() throws RecognitionException, TokenStreamException { value(); comparison(); value(); Object v2 = argStack.pop(); Object comp = argStack.pop(); Object v1 = argStack.pop(); argStack.push(new Boolean(evaluateComparison(v1, comp, v2))); } public final void joinedExpression() throws RecognitionException, TokenStreamException { expr(); join(); expr(); Boolean v1 = (Boolean) argStack.pop(); Integer join = (Integer) argStack.pop(); Boolean v2 = (Boolean) argStack.pop(); if (join.intValue() == AND) { argStack.push(new Boolean(v1.booleanValue() && v2.booleanValue())); } else { argStack.push(new Boolean(v1.booleanValue() || v2.booleanValue())); } } public final void join() throws RecognitionException, TokenStreamException { switch ( LA(1)) { case ANDSIGN: { match(ANDSIGN); argStack.push(new Integer(AND)); break; } case ORSIGN: { match(ORSIGN); argStack.push(new Integer(OR)); break; } default: { throw new NoViableAltException(LT(1), getFilename()); } } } public final void comparison() throws RecognitionException, TokenStreamException { switch ( LA(1)) { case EQUALSIGN: { match(EQUALSIGN); argStack.push(new Integer(EQUAL)); break; } case GREATERTHANSIGN: { match(GREATERTHANSIGN); argStack.push(new Integer(GREATER_THAN)); break; } case GREATEREQUALSIGN: { match(GREATEREQUALSIGN); argStack.push(new Integer(GREATER_EQUAL)); break; } case LESSTHANSIGN: { match(LESSTHANSIGN); argStack.push(new Integer(LESS_THAN)); break; } case LESSEQUALSIGN: { match(LESSEQUALSIGN); argStack.push(new Integer(LESS_EQUAL)); break; } case NOTEQUALSIGN: { match(NOTEQUALSIGN); argStack.push(new Integer(NOT_EQUAL)); break; } default: { throw new NoViableAltException(LT(1), getFilename()); } } } public static final String[] _tokenNames = { "<0>", "EOF", "<2>", "NULL_TREE_LOOKAHEAD", "DECIMAL_LITERAL", "HEX_LITERAL", "OCTAL_LITERAL", "STRING_LITERAL", "IDENTIFIER", "LBRACKET", "RBRACKET", "\"null\"", "THIS", "LPAREN", "RPAREN", "\"and\"", "\"or\"", "EQUALSIGN", "GREATERTHANSIGN", "GREATEREQUALSIGN", "LESSTHANSIGN", "LESSEQUALSIGN", "NOTEQUALSIGN", "WS" }; private static final long[] mk_tokenSet_0() { long[] data = { 8273920L, 0L}; return data; } public static final BitSet _tokenSet_0 = new BitSet(mk_tokenSet_0()); private static final long[] mk_tokenSet_1() { long[] data = { 6640L, 0L}; return data; } public static final BitSet _tokenSet_1 = new BitSet(mk_tokenSet_1()); }