0001: //** Copyright Statement ***************************************************
0002: //The Salmon Open Framework for Internet Applications (SOFIA)
0003: // Copyright (C) 1999 - 2002, Salmon LLC
0004: //
0005: // This program is free software; you can redistribute it and/or
0006: // modify it under the terms of the GNU General Public License version 2
0007: // as published by the Free Software Foundation;
0008: //
0009: // This program is distributed in the hope that it will be useful,
0010: // but WITHOUT ANY WARRANTY; without even the implied warranty of
0011: // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
0012: // GNU General Public License for more details.
0013: //
0014: // You should have received a copy of the GNU General Public License
0015: // along with this program; if not, write to the Free Software
0016: // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
0017: //
0018: // For more information please visit http://www.salmonllc.com
0019: //** End Copyright Statement ***************************************************
0020: package com.salmonllc.sql;
0021:
0022: /////////////////////////
0023: //$Archive: /sofia/sourcecode/com/salmonllc/sql/DataStoreEvaluator.java $
0024: //$Author: Deepak $
0025: //$Revision: 33 $
0026: //$Modtime: 9/07/04 2:53p $
0027: /////////////////////////
0028:
0029: import java.sql.Timestamp;
0030: import java.text.*;
0031: import java.util.*;
0032:
0033: /**
0034: * This type is used to evaluate java-like expressions using rows in a DataBuffer.
0035: * The class needs to be passed a String containing the expression that will be used. This expression will be parsed and evaluated using the evaluate row method.The rules for expressions are as follows:<BR><BR>
0036: * Column names: Columns in the datastore can be referenced in the same way that they are referenced in the get and set methods in the datastore. Generally this is either by using tablename.columnname or a single intenral name string. Which you can use depends on how the column was added to the datastore.<BR><BR>
0037: * Comparisons: You can use ==, >=, <=, !=, > or < comparisons in your expressions. Use these to compare the values of Strings, Dates, Numbers or Booleans. (Note: The values of each part of the comparison will be used as opposed to the default java method which will test object references).<BR><BR>
0038: * Operators: You can use +, -, /, * and ^ (exponent) to perform operations on numeric values. The + operator may also be used to concatinate String values.<BR>
0039: * In addition the if operator can be used to return a value based on a comparison. The syntax for if is : if(comparison,truevalue,falsevalue)<BR><BR>
0040: * Literals: String Literals are surrounded by double quotes, Date, DateTime or Time Literals are also surrounded by quotes and in JDBC date escape form YYYY-MM-DD for dates, HH:MM:SS for times and a combination of the two for DateTimes<BR><BR>
0041: * Nulls: The constant "null" can be used to check for columns values that are filled in. The equals(==) and not equals(!=) comparisons will return valid results when used with null. Every other comparison returns false when used with a null value on either side of the expression.<BR><BR>
0042: * Several methods are available that can be called on the various columns in the datastore. This is done by placing the method name after the column name followed by any method parameters. ex: table1.column1.substring(0,10). Methods can only be invoked on columns in the datastore, not on literals as in Java. Any method invoked on a null column will itself return null.<BR><BR>
0043: * Examples:<BR>
0044: * <pre>
0045: * "table1.column1 == 'xxxx'"<BR>
0046: * "table1.column1.substring(2,3) + 'xxx'"<BR>
0047: * </pre>
0048: * String Methods:<BR>
0049: * String substring(int start, int end): Gets a section of the String starting at start and ending at the character before end.<BR>
0050: * Integer indexOf(String subString) : Finds the first position of subString in the string or -1 if no occurance is found.<BR>
0051: * Integer lastIndexOf(String substring) : Finds the last position of subString in the string or -1 if no occurance is found.<BR>
0052: * Integer length() : Finds the length of the string in characters.<BR>
0053: * String toUpperCase(): Returns an all upper case version of the string.<BR>
0054: * String urlEncode(): Replaces ampersand, questionmarks and spaces in a String with URL Encoded Characters<BR>
0055: * String toLowerCase(): Returns an all lower case version of the string.<BR>
0056: * String trim(): Returns all leading and trailing spaces from the string.<BR>
0057: * String charAt(int position): Returns the character at position.<BR>
0058: * String startsWith(String substring): Returns true if the string starts with the specified substring.<BR>
0059: * String endsWith(String substring): Returns true if the string ends with the specified substring.<BR>
0060: * String escape(): Returns a string with quotes and spaces escaped so they work in javascript code.<BR>
0061: * String tempValue(): Returns a string with the temporary value of the column<BR>
0062: * Numeric Methods:<BR><BR>
0063: * Double sqrt(): Returns the square root of the number.<BR>
0064: * Double round(int places): Returns the number rounded to "places" number of decimal places.<BR>
0065: * String format(String pattern): Format the value as a string using the specified pattern.<BR><BR>
0066: * Date Methods:<BR><BR>
0067: * Integer getMonth(): Returns the month of the given date (January = 0, Dec = 11).<BR>
0068: * Integer getDate(): Returns the day of the month of the given date.<BR>
0069: * Integer getDay(): Returns the day of the week of a given date (Sunday = 0, Saturday = 6).<BR>
0070: * Integer getYear(): Returns the year of the given date.<BR>
0071: * Integer getHours(): Returns the hours of the given time.<BR>
0072: * Integer getMinutes(): Returns the Minutes of the given time.<BR>
0073: * Integer getSeconds(): Returns the Seconds of the given time.<BR>
0074: * Date toDate(): Returns the Date portion of a DateTime.<BR>
0075: * Time toTime(): Returns the Time portion of a DateTime.<BR>
0076: * Date dateAdd(int days): Returns the specified date incremented by "days" number of days.<BR><BR>
0077: * String format(String pattern): Format the value as a string using the specified pattern.<BR><BR>
0078: * There are also five constants you can use<BR>
0079: * null: The value null<BR>
0080: * $DATE$:todays date as a Date value<BR>
0081: * $TIME$: todays date and time as Datetime value<BR>
0082: * $ROWNO$: the number of the row that the evaluator is evaluating<BR>
0083: * $ROWCOUNT$: the total number of the rows in the datastore<BR>
0084: * $ROWSTATUS$: the status of the row. See DatastoreBuffer.STATUS constants<br>
0085: * $QUOT$: include a single quote in a string<BR>
0086: */
0087: public class DataStoreEvaluator implements java.io.Serializable {
0088: private String _terminators = "+-*/=()\",><&|!^,'";
0089: private String _expression;
0090: private String _lastToken;
0091: private String[] _inPost;
0092: int _pos = 0;
0093: private Stack _st = new Stack();
0094: private int _stackCount = 0;
0095:
0096: private DataStoreBuffer _ds;
0097: private String _pattern = null;
0098: private Format _format = null;
0099: private DataStoreExpression _exp;
0100: private String _resultBucket = null;
0101:
0102: /**
0103: * @return Returns the resultBucket, a column to place the value of the results of the expression.
0104: */
0105: public String getResultBucket() {
0106: return _resultBucket;
0107: }
0108:
0109: /**
0110: * @param resultBucket The resultBucket to set. A column to place the value of the results of the expression
0111: */
0112: public void setResultBucket(String resultBucket) {
0113: _resultBucket = resultBucket;
0114: }
0115:
0116: //private Vector _refs = new Vector();
0117: //private Vector _refsTypes = new Vector();
0118:
0119: //private static final int FUNC_REF = 0;
0120: //private static final int VAR_REF = 1;
0121:
0122: private static final int TYPE_NUM = 0;
0123: private static final int TYPE_DATETIME = 1;
0124: private static final int TYPE_STRING = 2;
0125: private static final int TYPE_BOOL = 3;
0126: private static final int TYPE_ANY = 4;
0127: private static final int TYPE_DATE = 5;
0128: private static final int TYPE_TIME = 6;
0129:
0130: public static final int AGGREGATE_SUM = 0;
0131: public static final int AGGREGATE_COUNT = 1;
0132: public static final int AGGREGATE_AVERAGE = 2;
0133:
0134: /**
0135: * This method will construct a new DataStoreEvaluator using the specified expression.
0136: * @param db The DataStoreBuffer to evaluate.
0137: * @param expression The expression to evaluate.
0138: */
0139: public DataStoreEvaluator(DataStoreBuffer db,
0140: DataStoreExpression expression) throws DataStoreException {
0141: _ds = db;
0142: _exp = expression;
0143: }
0144:
0145: /**
0146: * This method will construct a new DataStoreEvaluator using the specified expression.
0147: * @param db The DataStoreBuffer to evaluate.
0148: * @param expression The expression to evaluate.
0149: * @param format The pattern for the output.
0150: * @see DataStore#setFormat
0151: */
0152: public DataStoreEvaluator(DataStoreBuffer db,
0153: DataStoreExpression expression, String format)
0154: throws DataStoreException {
0155: this (db, expression);
0156: _pattern = format;
0157: }
0158:
0159: /**
0160: * This method will construct a new DataStoreEvaluator using the specified expression.
0161: * @param db The DataStoreBuffer to evaluate.
0162: * @param expression The expression to evaluate.
0163: */
0164: public DataStoreEvaluator(DataStoreBuffer db, String expression)
0165: throws DataStoreException {
0166: _ds = db;
0167: try {
0168: intoPost(expression);
0169: } catch (Exception e) {
0170: throw new DataStoreException(e.getMessage());
0171: }
0172: }
0173:
0174: /**
0175: * This method will construct a new DataStoreEvaluator using the specified expression.
0176: * @param db The DataStoreBuffer to evaluate.
0177: * @param expression The expression to evaluate.
0178: * @param format The pattern for the output.
0179: * @see DataStore#setFormat
0180: */
0181: public DataStoreEvaluator(DataStoreBuffer db, String expression,
0182: String format) throws DataStoreException {
0183: this (db, expression);
0184: _pattern = format;
0185: }
0186:
0187: /**
0188: *
0189: * @param v
0190: * @param token
0191: */
0192: private void appendToVector(Vector v, String token) {
0193: v.addElement(token);
0194:
0195: /*if (isNumber(token))
0196: return;
0197: if (isString(token))
0198: return;
0199: if (isDateTime(token))
0200: return;
0201:
0202: if (orderOfOperations(token) > 0 && ! isFunction(token))
0203: return;
0204:
0205: boolean found = false;
0206: for (int i = 0;i< _refs.size();i++) {
0207: if ( token.equals((String) _refs.elementAt(i))) {
0208: found = true;
0209: break;
0210: }
0211: }
0212:
0213: if (! found) {
0214: _refs.addElement(token);
0215: if (isFunction(token))
0216: _refTypes.addElement(new Integer(FUNC_REF));
0217: else
0218: _refTypes.addElement(new Integer(VAR_REF));
0219: }*/
0220: }
0221:
0222: /**
0223: * This method evaluates the expression passed in the constructor for every row in the DataStoreBuffer.
0224: * @return A object with the result of the evaluation.
0225: * @param aggregateType Valid Values are:AGGREGATE_SUM, AGGREGATE_COUNT
0226: */
0227: public Object evaluateAggregate(int aggregateType)
0228: throws DataStoreException {
0229: return evaluateAggregate(aggregateType, 0,
0230: _ds.getRowCount() - 1);
0231: }
0232:
0233: /**
0234: * This method evaluates the expression passed in the constructor for every row in the DataStoreBuffer.
0235: * @return A object with the result of the evaluation.
0236: * @param aggregateType Valid Values are:AGGREGATE_SUM, AGGREGATE_COUNT
0237: * @param startRow the first row to evaluate
0238: * @param endRow the last row to evaluate
0239: */
0240: public Object evaluateAggregate(int aggregateType, int startRow,
0241: int endRow) throws DataStoreException {
0242: double result = 0;
0243: int rc = 0;
0244:
0245: for (int i = startRow; i <= endRow; i++) {
0246: Object o = evaluateRow(i);
0247: if (aggregateType == AGGREGATE_AVERAGE) {
0248: rc++;
0249: if (o instanceof Number)
0250: result = result + ((Number) o).doubleValue();
0251: }
0252: if (aggregateType == AGGREGATE_SUM) {
0253: if (o instanceof Number)
0254: result = result + ((Number) o).doubleValue();
0255: } else if (aggregateType == AGGREGATE_COUNT) {
0256: if (o instanceof Boolean) {
0257: if (((Boolean) o).booleanValue())
0258: result++;
0259: } else if (o != null)
0260: result++;
0261: }
0262: }
0263:
0264: if (aggregateType == AGGREGATE_AVERAGE && rc > 0)
0265: result = result / rc;
0266:
0267: if (_resultBucket != null) {
0268: _ds.setDouble(endRow, _resultBucket, result);
0269: _ds.setDouble(startRow, _resultBucket, result);
0270: }
0271:
0272: return new Double(result);
0273: }
0274:
0275: /**
0276: * This method evaluates the expression passed in the constructor for every row in the DataStoreBuffer. It will format the output according to the parrern specified and return a string version of it.
0277: * @return A object with the result of the evaluation.
0278: * @param aggregateType Valid Values are:AGGREGATE_SUM, AGGREGATE_COUNT
0279: */
0280: public String evaluateAggregateFormat(int aggregateType)
0281: throws DataStoreException {
0282: return evaluateAggregateFormat(aggregateType, 0, _ds
0283: .getRowCount() - 1);
0284: }
0285:
0286: /**
0287: * This method evaluates the expression passed in the constructor for every row in the DataStoreBuffer. It will format the output according to the parrern specified and return a string version of it.
0288: * @return A object with the result of the evaluation.
0289: * @param aggregateType Valid Values are:AGGREGATE_SUM, AGGREGATE_COUNT
0290: * @param startRow the first row to evaluate
0291: * @param endRow the last row to evaluate
0292: */
0293: public String evaluateAggregateFormat(int aggregateType,
0294: int startRow, int endRow) throws DataStoreException {
0295: Object res = evaluateAggregate(aggregateType, startRow, endRow);
0296: if (res == null)
0297: return null;
0298:
0299: if (_pattern == null)
0300: return res.toString();
0301:
0302: if (_format == null) {
0303: if (res instanceof Number)
0304: _format = new DecimalFormat(_pattern);
0305: else if (res instanceof java.util.Date)
0306: _format = new SimpleDateFormat(_pattern);
0307: else
0308: return res.toString();
0309: }
0310:
0311: if (res instanceof Number)
0312: return _format.format(res);
0313: else if (res instanceof java.util.Date)
0314: return _format.format(res);
0315: else
0316: return res.toString();
0317: }
0318:
0319: /**
0320: * This method evaluates the expression passed in the constructor for the current row in the DataStoreBuffer.
0321: * @return A object with the result of the evaluation.
0322: */
0323: public Object evaluateRow() throws DataStoreException {
0324: return evaluateRow(_ds.getRow());
0325: }
0326:
0327: /**
0328: * This method evaluates the expression passed in the constructor for a particular row in the DataStoreBuffer.
0329: * @param rowNo - row The row to evaluate.
0330: * @return A object with the result of the evaluation.
0331: * @throws DataStoreException
0332: */
0333: public Object evaluateRow(int rowNo) throws DataStoreException {
0334: if (_exp != null) {
0335: if (rowNo < 0 || rowNo >= _ds.getRowCount())
0336: return null;
0337: else
0338: return _exp.evaluateExpression(_ds, rowNo);
0339: }
0340:
0341: DSDataStoreDescriptor desc = _ds.getDescriptor();
0342: DSDataRow row = _ds.getDataRow(rowNo);
0343: if (row == null)
0344: return null;
0345:
0346: _st = new Stack();
0347: _stackCount = 0;
0348:
0349: int size = _inPost.length;
0350: String token = "";
0351:
0352: for (int i = 0; i < size; i++) {
0353: token = _inPost[i];
0354: if (token.equals("null"))
0355: _st.push(null);
0356: else if (token.charAt(0) == '$'
0357: && token.charAt(token.length() - 1) == '$') {
0358: if (token.equals("$TIME$"))
0359: _st.push(functionCurrentTime());
0360: else if (token.equals("$DATE$"))
0361: _st.push(functionCurrentDate());
0362: else if (token.equals("$ROWNO$"))
0363: _st.push(new Integer(rowNo));
0364: else if (token.equals("$ROWCOUNT$"))
0365: _st.push(new Integer(_ds.getRowCount()));
0366: else if (token.equals("$QUOT$"))
0367: _st.push("'");
0368: else if (token.equals("$ROWSTATUS$"))
0369: _st.push(new Integer(_ds.getRowStatus(rowNo)));
0370: else
0371: throw new DataStoreException("Unknown token error:"
0372: + token);
0373: } else if (isNumber(token))
0374: _st.push(Double.valueOf(token));
0375: else if (isDateTime(token))
0376: _st.push(java.sql.Timestamp.valueOf(token.substring(1,
0377: token.length() - 1)));
0378: else if (isDate(token))
0379: _st.push(java.sql.Date.valueOf(token.substring(1, token
0380: .length() - 1)));
0381: else if (isTime(token))
0382: _st.push(java.sql.Time.valueOf(token.substring(1, token
0383: .length() - 1)));
0384: else if (isString(token))
0385: _st.push(token.substring(1, token.length() - 1));
0386: else if (isBoolean(token))
0387: _st.push(Boolean.valueOf(token));
0388: else if (token.endsWith(".tempValue")) {
0389: token = token.substring(0, token.length() - 10);
0390: int ndx = desc.getColumnIndex(token);
0391: if (ndx < 0)
0392: throw new DataStoreException("Unknown token error:"
0393: + token);
0394: else {
0395: _st.push(row.getTempValue(ndx));
0396: }
0397: } else if (isOperator(token)) {
0398: Object o = executeOperation(desc, row, token);
0399: if (isFunction(token))
0400: _stackCount = -1;
0401: _st.push(o);
0402: } else {
0403: int ndx = desc.getColumnIndex(token);
0404: if (ndx < 0)
0405: throw new DataStoreException("Unknown token error:"
0406: + token);
0407: else {
0408: _st.push(row.getData(ndx));
0409: }
0410: }
0411: _stackCount++;
0412:
0413: }
0414:
0415: Object o = _st.pop();
0416:
0417: if (_resultBucket != null)
0418: _ds.setAny(rowNo, _resultBucket, o);
0419:
0420: return o;
0421: }
0422:
0423: /**
0424: * This method evaluates the expression passed in the constructor for the current row in the DataStoreBuffer. It will then format the result using the format pattern and return a String version of the result;
0425: * @return A String representation of the result of the evaluation.
0426: */
0427: public String evaluateRowFormat() throws DataStoreException {
0428: return evaluateRowFormat(_ds.getRow());
0429: }
0430:
0431: /**
0432: * This method evaluates the expression passed in the constructor for a particular row in the DataStoreBuffer. It will then format the result using the format pattern and return a String version of the result;
0433: * @return A String representation of the result of the evaluation.
0434: * @param rowNo The row to evaluate.
0435: */
0436: public String evaluateRowFormat(int rowNo)
0437: throws DataStoreException {
0438: Object res = evaluateRow(rowNo);
0439: if (res == null)
0440: return null;
0441:
0442: if (_pattern == null)
0443: return res.toString();
0444:
0445: if (_format == null) {
0446: if (res instanceof Number)
0447: _format = new DecimalFormat(_pattern);
0448: else if (res instanceof java.util.Date)
0449: _format = new SimpleDateFormat(_pattern);
0450: else
0451: return res.toString();
0452: }
0453:
0454: if (res instanceof Number)
0455: return _format.format(res);
0456: else if (res instanceof java.util.Date)
0457: return _format.format(res);
0458: else
0459: return res.toString();
0460: }
0461:
0462: private boolean executeComparison(String token)
0463: throws DataStoreException {
0464: boolean result = false;
0465: int type = -1;
0466:
0467: try {
0468: Object o1 = popValue(TYPE_ANY);
0469: Object o2 = popValue(TYPE_ANY);
0470:
0471: type = getType(o1);
0472: int type2 = getType(o2);
0473:
0474: //handle nulls
0475: if (o1 == null || o2 == null) {
0476: if (token.equals("==")) {
0477: if (o1 == null && o2 == null)
0478: return true;
0479: else
0480: return false;
0481: } else if (token.equals("!=")) {
0482: if (o1 == null && o2 != null)
0483: return true;
0484: else if (o2 == null && o1 != null)
0485: return true;
0486: else
0487: return false;
0488: } else
0489: return false;
0490: }
0491:
0492: //make sure the data types match
0493:
0494: if (type != type2) {
0495: if (type == TYPE_STRING
0496: && (type2 == TYPE_DATETIME
0497: || type2 == TYPE_TIME || type2 == TYPE_DATE)) {
0498: o2 = o2.toString();
0499: type = TYPE_STRING;
0500: } else if (type2 == TYPE_STRING
0501: && (type == TYPE_DATETIME || type == TYPE_TIME || type == TYPE_DATE)) {
0502: o1 = o1.toString();
0503: type = TYPE_STRING;
0504: } else {
0505: throw new DataStoreException(
0506: "Error: datatypes do not match on comparison.");
0507: }
0508: }
0509:
0510: //execute the comparison
0511: if (type == TYPE_STRING) {
0512: String s1 = (String) o1;
0513: String s2 = (String) o2;
0514:
0515: if (token.equals("=="))
0516: result = s1.equals(s2);
0517: else if (token.equals("!="))
0518: result = !s1.equals(s2);
0519: else if (token.equals(">"))
0520: result = (s1.compareTo(s2) < 0);
0521: else if (token.equals("<"))
0522: result = (s1.compareTo(s2) > 0);
0523: else if (token.equals(">="))
0524: result = (s1.compareTo(s2) <= 0);
0525: else if (token.equals("<="))
0526: result = (s1.compareTo(s2) >= 0);
0527: } else if (type == TYPE_DATETIME) {
0528: java.sql.Timestamp d1 = (java.sql.Timestamp) o1;
0529: java.sql.Timestamp d2 = (java.sql.Timestamp) o2;
0530:
0531: if (token.equals("=="))
0532: result = d1.equals(d2);
0533: else if (token.equals("!="))
0534: result = !d1.equals(d2);
0535: else if (token.equals("<"))
0536: result = d1.after(d2);
0537: else if (token.equals(">"))
0538: result = d1.before(d2);
0539: else if (token.equals("<="))
0540: result = (d1.after(d2) || d1.equals(d2));
0541: else if (token.equals(">="))
0542: result = (d1.before(d2) || d1.equals(d2));
0543:
0544: } else if (type == TYPE_DATE) {
0545: java.sql.Date d1 = (java.sql.Date) o1;
0546: java.sql.Date d2 = (java.sql.Date) o2;
0547:
0548: if (token.equals("=="))
0549: result = d1.equals(d2);
0550: else if (token.equals("!="))
0551: result = !d1.equals(d2);
0552: else if (token.equals("<"))
0553: result = d1.after(d2);
0554: else if (token.equals(">"))
0555: result = d1.before(d2);
0556: else if (token.equals("<="))
0557: result = (d1.after(d2) || d1.equals(d2));
0558: else if (token.equals(">="))
0559: result = (d1.before(d2) || d1.equals(d2));
0560:
0561: } else if (type == TYPE_TIME) {
0562: java.sql.Time d1 = (java.sql.Time) o1;
0563: java.sql.Time d2 = (java.sql.Time) o2;
0564:
0565: if (token.equals("=="))
0566: result = d1.equals(d2);
0567: else if (token.equals("!="))
0568: result = !d1.equals(d2);
0569: else if (token.equals("<"))
0570: result = d1.after(d2);
0571: else if (token.equals(">"))
0572: result = d1.before(d2);
0573: else if (token.equals("<="))
0574: result = (d1.after(d2) || d1.equals(d2));
0575: else if (token.equals(">="))
0576: result = (d1.before(d2) || d1.equals(d2));
0577:
0578: } else if (type == TYPE_NUM) {
0579: double d1 = ((Number) o1).doubleValue();
0580: double d2 = ((Number) o2).doubleValue();
0581:
0582: if (token.equals("=="))
0583: result = d1 == d2;
0584: else if (token.equals("!="))
0585: result = d1 != d2;
0586: else if (token.equals(">"))
0587: result = d2 > d1;
0588: else if (token.equals("<"))
0589: result = d2 < d1;
0590: else if (token.equals(">="))
0591: result = d2 >= d1;
0592: else if (token.equals("<="))
0593: result = d2 <= d1;
0594:
0595: } else if (type == TYPE_BOOL) {
0596: boolean b1 = ((Boolean) o1).booleanValue();
0597: boolean b2 = ((Boolean) o2).booleanValue();
0598:
0599: if (token.equals("=="))
0600: result = b1 == b2;
0601: else if (token.equals("!="))
0602: result = b1 != b2;
0603: else
0604: throw new DataStoreException(
0605: "Only == and != are valid comparisons for boolean values");
0606:
0607: }
0608: } catch (DataStoreException e) {
0609: throw e;
0610: } catch (Exception e) {
0611: throw new DataStoreException(e.getMessage());
0612: }
0613:
0614: return result;
0615: }
0616:
0617: private Object executeFunction(DSDataStoreDescriptor desc,
0618: DSDataRow row, String token) throws DataStoreException {
0619: //to implement a new function
0620: //create a method for it and call below
0621: //add an entry to isFunction method
0622: //add an entry to getPopCount method
0623:
0624: Object result = null;
0625:
0626: try {
0627:
0628: int pos = token.lastIndexOf(".");
0629: Object o = null;
0630:
0631: String function = token.substring(pos + 1);
0632: String column = token.substring(0, pos);
0633: if (pos == 0) {
0634: Vector v = new Vector(_stackCount);
0635: for (int i = 0; i < _stackCount; i++)
0636: v.addElement(_st.pop());
0637: if (_st.isEmpty())
0638: o = v.elementAt(v.size() - 1);
0639: else
0640: o = _st.pop();
0641: for (int i = v.size() - 1; i > -1; i--)
0642: _st.push(v.elementAt(i));
0643: } else {
0644: int ndx = desc.getColumnIndex(column);
0645: if (ndx < 0)
0646: throw (new DataStoreException("Error: Column "
0647: + column + " not found "));
0648: o = row.getData(ndx);
0649: }
0650:
0651: if (o == null) {
0652: for (int i = 0; i < getPopCount(function); i++)
0653: popValue(TYPE_ANY);
0654: return null;
0655: }
0656:
0657: if (o instanceof String) {
0658: String s = (String) o;
0659: if (function.equals("substring"))
0660: return functionSubstring(s);
0661: else if (function.equals("indexOf"))
0662: return functionIndexOf(s);
0663: else if (function.equals("lastIndexOf"))
0664: return functionLastIndexOf(s);
0665: else if (function.equals("toUpperCase"))
0666: return functionToUpperCase(s);
0667: else if (function.equals("toLowerCase"))
0668: return functionToLowerCase(s);
0669: else if (function.equals("charAt"))
0670: return functionCharAt(s);
0671: else if (function.equals("startsWith"))
0672: return functionStartsWith(s);
0673: else if (function.equals("endsWith"))
0674: return functionEndsWith(s);
0675: else if (function.equals("length"))
0676: return functionLength(s);
0677: else if (function.equals("trim"))
0678: return functionTrim(s);
0679: else if (function.equals("urlEncode"))
0680: return functionUrlEncode(s);
0681: else if (function.equals("escape"))
0682: return functionEscape(s);
0683: } else if (o instanceof Number) {
0684: double d = ((Number) o).doubleValue();
0685:
0686: if (function.equals("sqrt"))
0687: return functionSqrt(d);
0688: else if (function.equals("round"))
0689: return functionRound(d);
0690: else if (function.equals("format"))
0691: return functionFormat(o);
0692: }
0693: if (o instanceof java.util.Date) {
0694: java.util.Date d = (java.util.Date) o;
0695:
0696: if (function.equals("getHours"))
0697: return functionGetHours(d);
0698: else if (function.equals("getYear"))
0699: return functionGetYear(d);
0700: else if (function.equals("getMonth"))
0701: return functionGetMonth(d);
0702: else if (function.equals("getDate"))
0703: return functionGetDate(d);
0704: else if (function.equals("getDay"))
0705: return functionGetDay(d);
0706: else if (function.equals("getMinutes"))
0707: return functionGetMinutes(d);
0708: else if (function.equals("getSeconds"))
0709: return functionGetSeconds(d);
0710: else if (function.equals("toDate"))
0711: return functionToDate(d);
0712: else if (function.equals("toTime"))
0713: return functionToTime(d);
0714: else if (function.equals("dateAdd"))
0715: return functionDateAdd(d);
0716: else if (function.equals("substring"))
0717: return functionSubstring(d.toString());
0718: else if (function.equals("indexOf"))
0719: return functionIndexOf(d.toString());
0720: else if (function.equals("toUpperCase"))
0721: return functionToUpperCase(d.toString());
0722: else if (function.equals("toLowerCase"))
0723: return functionToLowerCase(d.toString());
0724: else if (function.equals("charAt"))
0725: return functionCharAt(d.toString());
0726: else if (function.equals("startsWith"))
0727: return functionStartsWith(d.toString());
0728: else if (function.equals("endsWith"))
0729: return functionEndsWith(d.toString());
0730: else if (function.equals("length"))
0731: return functionLength(d.toString());
0732: else if (function.equals("trim"))
0733: return functionTrim(d.toString());
0734: else if (function.equals("format"))
0735: return functionFormat(d);
0736: }
0737: } catch (DataStoreException e) {
0738: throw e;
0739: } catch (Exception e) {
0740: throw new DataStoreException(e.getMessage());
0741: }
0742:
0743: return result;
0744: }
0745:
0746: /**
0747: *
0748: * @param desc
0749: * @param row
0750: * @param token
0751: * @return
0752: * @throws DataStoreException
0753: */
0754: private Object executeOperation(DSDataStoreDescriptor desc,
0755: DSDataRow row, String token) throws DataStoreException {
0756: Object result = null;
0757:
0758: try {
0759: if (token.equals("+")) {
0760: Object o1 = popValue(TYPE_ANY);
0761: Object o2 = popValue(TYPE_ANY);
0762:
0763: if (o1 == null)
0764: o1 = new String("");
0765: if (o2 == null)
0766: o2 = new String("");
0767:
0768: if (getType(o1) == TYPE_STRING
0769: || getType(o2) == TYPE_STRING)
0770: result = o2.toString() + o1.toString();
0771: else
0772: result = new Double(((Number) o1).doubleValue()
0773: + ((Number) o2).doubleValue());
0774: } else if (token.equals("-")) {
0775: double v1 = ((Double) popValue(TYPE_NUM)).doubleValue();
0776: double v2 = ((Double) popValue(TYPE_NUM)).doubleValue();
0777: result = new Double(v2 - v1);
0778: } else if (token.equals("*")) {
0779: result = new Double(((Double) popValue(TYPE_NUM))
0780: .doubleValue()
0781: * ((Double) popValue(TYPE_NUM)).doubleValue());
0782: } else if (token.equals("/")) {
0783: double v1 = ((Double) popValue(TYPE_NUM)).doubleValue();
0784: double v2 = ((Double) popValue(TYPE_NUM)).doubleValue();
0785: result = new Double(v2 / v1);
0786: } else if (token.equals("^")) {
0787: double v1 = ((Double) popValue(TYPE_NUM)).doubleValue();
0788: double v2 = ((Double) popValue(TYPE_NUM)).doubleValue();
0789: result = new Double(Math.pow(v2, v1));
0790: } else if (token.equals("!")) {
0791: result = new Boolean(!((Boolean) popValue(TYPE_BOOL))
0792: .booleanValue());
0793: } else if (token.equals("&&")) {
0794: Boolean b1 = (Boolean) popValue(TYPE_BOOL);
0795: Boolean b2 = (Boolean) popValue(TYPE_BOOL);
0796: result = new Boolean(b1.booleanValue()
0797: && b2.booleanValue());
0798: } else if (token.equals("||")) {
0799: Boolean b1 = (Boolean) popValue(TYPE_BOOL);
0800: Boolean b2 = (Boolean) popValue(TYPE_BOOL);
0801: result = new Boolean(b1.booleanValue()
0802: || b2.booleanValue());
0803: } else if (token.equals("==") || token.equals(">")
0804: || token.equals("<") || token.equals(">=")
0805: || token.equals("<=") || token.equals("!=")) {
0806: result = new Boolean(executeComparison(token));
0807: } else if (token.equals("if")) {
0808: result = functionIf();
0809: } else if (isFunction(token)) {
0810: result = executeFunction(desc, row, token);
0811: }
0812:
0813: } catch (DataStoreException e) {
0814: throw e;
0815: } catch (Exception e) {
0816: return null;
0817: }
0818:
0819: return result;
0820: }
0821:
0822: /**
0823: *
0824: * @param s
0825: * @return
0826: * @throws DataStoreException
0827: */
0828: private String functionCharAt(String s) throws DataStoreException {
0829: int i1 = ((Double) popValue(TYPE_NUM)).intValue();
0830:
0831: if ((i1 < 0) || i1 >= s.length())
0832: return null;
0833:
0834: char[] c = new char[1];
0835: c[0] = s.charAt(i1);
0836: return new String(c);
0837: }
0838:
0839: //new method
0840: private String functionEscape(String value) {
0841: if (value == null)
0842: return null;
0843: StringBuffer buffer = new StringBuffer();
0844: for (int i = 0; i < value.length(); i++) {
0845: char c = value.charAt(i);
0846: if (c == '\'')
0847: buffer.append("\\'");
0848: else if (c == '\\')
0849: buffer.append("\\\\");
0850: else if (c == '"')
0851: buffer.append(""");
0852: else if (c == ' ')
0853: buffer.append("%20");
0854: else
0855: buffer.append(c);
0856: }
0857: return buffer.toString();
0858: }
0859:
0860: /**
0861: *
0862: * @param d
0863: * @return
0864: * @throws DataStoreException
0865: */
0866: private java.util.Date functionDateAdd(java.util.Date d)
0867: throws DataStoreException {
0868:
0869: Double arg = (Double) popValue(TYPE_NUM);
0870:
0871: GregorianCalendar cal = new GregorianCalendar();
0872: cal.setTime(d);
0873: cal.add(Calendar.DATE, arg.intValue());
0874:
0875: int month = cal.get(Calendar.MONTH) + 1;
0876: int year = cal.get(Calendar.YEAR);
0877: int day = cal.get(Calendar.DATE);
0878:
0879: return java.sql.Date.valueOf(year + "-" + month + "-" + day);
0880:
0881: }
0882:
0883: /**
0884: *
0885: * @param s
0886: * @return
0887: * @throws DataStoreException
0888: */
0889: private Boolean functionEndsWith(String s)
0890: throws DataStoreException {
0891: String s1 = ((String) popValue(TYPE_STRING));
0892:
0893: return new Boolean(s.endsWith(s1));
0894: }
0895:
0896: /**
0897: *
0898: * @param d
0899: * @return
0900: * @throws DataStoreException
0901: */
0902: private Integer functionGetDate(java.util.Date d)
0903: throws DataStoreException {
0904:
0905: if (d instanceof java.sql.Time)
0906: throw (new DataStoreException(
0907: "The getDate function cannot be used with Time values"));
0908:
0909: GregorianCalendar cal = new GregorianCalendar();
0910: cal.setTime(d);
0911:
0912: return new Integer(cal.get(Calendar.DATE));
0913:
0914: }
0915:
0916: /**
0917: *
0918: * @param d
0919: * @return
0920: * @throws DataStoreException
0921: */
0922: private Integer functionGetDay(java.util.Date d)
0923: throws DataStoreException {
0924: if (d instanceof java.sql.Time)
0925: throw (new DataStoreException(
0926: "The getDay function cannot be used with Time values"));
0927:
0928: GregorianCalendar cal = new GregorianCalendar();
0929: cal.setTime(d);
0930:
0931: return new Integer(cal.get(Calendar.DAY_OF_WEEK));
0932:
0933: // return new Integer(d.getDay());
0934:
0935: }
0936:
0937: /**
0938: *
0939: * @param d
0940: * @return
0941: * @throws DataStoreException
0942: */
0943: private Integer functionGetHours(java.util.Date d)
0944: throws DataStoreException {
0945: if (d instanceof java.sql.Date)
0946: throw (new DataStoreException(
0947: "The getHours function cannot be used with Date values"));
0948:
0949: GregorianCalendar cal = new GregorianCalendar();
0950: cal.setTime(d);
0951:
0952: return new Integer(cal.get(Calendar.HOUR_OF_DAY));
0953:
0954: }
0955:
0956: /**
0957: *
0958: * @param d
0959: * @return
0960: * @throws DataStoreException
0961: */
0962: private Integer functionGetMinutes(java.util.Date d)
0963: throws DataStoreException {
0964: if (d instanceof java.sql.Date)
0965: throw (new DataStoreException(
0966: "The getMinutes function cannot be used with Date values"));
0967:
0968: GregorianCalendar cal = new GregorianCalendar();
0969: cal.setTime(d);
0970:
0971: return new Integer(cal.get(Calendar.MINUTE));
0972:
0973: }
0974:
0975: /**
0976: *
0977: * @param d
0978: * @return
0979: * @throws DataStoreException
0980: */
0981: private Integer functionGetMonth(java.util.Date d)
0982: throws DataStoreException {
0983: if (d instanceof java.sql.Time)
0984: throw (new DataStoreException(
0985: "The getMonth function cannot be used with Time values"));
0986:
0987: GregorianCalendar cal = new GregorianCalendar();
0988: cal.setTime(d);
0989:
0990: return new Integer(cal.get(Calendar.MONTH));
0991:
0992: }
0993:
0994: /**
0995: *
0996: * @param d
0997: * @return
0998: * @throws DataStoreException
0999: */
1000: private Integer functionGetSeconds(java.util.Date d)
1001: throws DataStoreException {
1002: if (d instanceof java.sql.Date)
1003: throw (new DataStoreException(
1004: "The getSeconds function cannot be used with Date values"));
1005:
1006: GregorianCalendar cal = new GregorianCalendar();
1007: cal.setTime(d);
1008:
1009: return new Integer(cal.get(Calendar.SECOND));
1010:
1011: }
1012:
1013: /**
1014: *
1015: * @param d
1016: * @return
1017: * @throws DataStoreException
1018: */
1019: private Integer functionGetYear(java.util.Date d)
1020: throws DataStoreException {
1021: if (d instanceof java.sql.Time)
1022: throw (new DataStoreException(
1023: "The getYear function cannot be used with Time values"));
1024:
1025: GregorianCalendar cal = new GregorianCalendar();
1026: cal.setTime(d);
1027:
1028: return new Integer(cal.get(Calendar.YEAR));
1029:
1030: }
1031:
1032: /**
1033: *
1034: * @return
1035: * @throws DataStoreException
1036: */
1037: private Object functionIf() throws DataStoreException {
1038: Object falseValue = popValue(TYPE_ANY);
1039: Object trueValue = popValue(TYPE_ANY);
1040: Boolean exp = (Boolean) popValue(TYPE_BOOL);
1041:
1042: if (exp.booleanValue())
1043: return trueValue;
1044: else
1045: return falseValue;
1046:
1047: }
1048:
1049: private String functionFormat(Object o) throws DataStoreException {
1050: String pattern = ((String) popValue(TYPE_STRING));
1051: Format format = null;
1052:
1053: if (o instanceof java.util.Date) {
1054: format = new SimpleDateFormat(pattern);
1055: return format.format(o);
1056: } else if (o instanceof Number) {
1057: format = new DecimalFormat(pattern);
1058: return format.format(o);
1059:
1060: } else
1061: throw (new DataStoreException(
1062: "The format function can only be used with Date or Numeric values"));
1063:
1064: }
1065:
1066: /**
1067: *
1068: * @param s
1069: * @return
1070: * @throws DataStoreException
1071: */
1072: private Integer functionIndexOf(String s) throws DataStoreException {
1073: String s1 = (String) popValue(TYPE_STRING);
1074: if (s1 == null)
1075: return null;
1076: return new Integer(s.indexOf(s1));
1077: }
1078:
1079: /**
1080: *
1081: * @param s
1082: * @return
1083: * @throws DataStoreException
1084: */
1085: private Integer functionLastIndexOf(String s)
1086: throws DataStoreException {
1087: String s1 = (String) popValue(TYPE_STRING);
1088: if (s1 == null)
1089: return null;
1090: return new Integer(s.lastIndexOf(s1));
1091: }
1092:
1093: private Double functionLength(String s) {
1094: return new Double(s.length());
1095: }
1096:
1097: /**
1098: *
1099: * @param d
1100: * @return
1101: * @throws DataStoreException
1102: */
1103: private Double functionRound(double d) throws DataStoreException {
1104: int places = ((Number) popValue(TYPE_NUM)).intValue();
1105: double ret;
1106:
1107: if (places > 0)
1108: places = 10 * places;
1109: else
1110: places = 1;
1111:
1112: ret = d * places;
1113: ret = Math.round(ret);
1114: ret = ret / places;
1115:
1116: return new Double(ret);
1117: }
1118:
1119: private Double functionSqrt(double d) {
1120: return new Double(Math.sqrt(d));
1121: }
1122:
1123: /**
1124: *
1125: * @param s
1126: * @return
1127: * @throws DataStoreException
1128: */
1129: private Boolean functionStartsWith(String s)
1130: throws DataStoreException {
1131: String s1 = ((String) popValue(TYPE_STRING));
1132:
1133: return new Boolean(s.startsWith(s1));
1134: }
1135:
1136: /**
1137: *
1138: * @param s
1139: * @return
1140: * @throws DataStoreException
1141: */
1142: private String functionSubstring(String s)
1143: throws DataStoreException {
1144: int i1 = ((Double) popValue(TYPE_NUM)).intValue();
1145: int i2 = ((Double) popValue(TYPE_NUM)).intValue();
1146: if ((i1 < 0) || i1 > s.length())
1147: return null;
1148: else if ((i2 < 0) || i2 > s.length())
1149: return null;
1150: else if (i1 <= i2)
1151: return null;
1152: else
1153: return (s.substring(i2, i1));
1154: }
1155:
1156: /**
1157: *
1158: * @param d
1159: * @return
1160: * @throws DataStoreException
1161: */
1162: private java.sql.Date functionToDate(java.util.Date d)
1163: throws DataStoreException {
1164: if (!(d instanceof java.sql.Timestamp))
1165: throw (new DataStoreException(
1166: "The toDate function can only be used with DateTime values"));
1167:
1168: GregorianCalendar cal = new GregorianCalendar();
1169: cal.setTime(d);
1170:
1171: int month = cal.get(Calendar.MONTH) + 1;
1172: int year = cal.get(Calendar.YEAR);
1173: int day = cal.get(Calendar.DATE);
1174:
1175: return java.sql.Date.valueOf(year + "-" + month + "-" + day);
1176: }
1177:
1178: private java.sql.Timestamp functionCurrentTime() {
1179: return new Timestamp(System.currentTimeMillis());
1180: }
1181:
1182: private java.sql.Date functionCurrentDate()
1183: throws DataStoreException {
1184: return functionToDate(new Timestamp(System.currentTimeMillis()));
1185: }
1186:
1187: private String functionToLowerCase(String s) {
1188: return s.toLowerCase();
1189: }
1190:
1191: /**
1192: *
1193: * @param d
1194: * @return
1195: * @throws DataStoreException
1196: */
1197: private java.sql.Time functionToTime(java.util.Date d)
1198: throws DataStoreException {
1199:
1200: if (!(d instanceof java.sql.Timestamp))
1201: throw (new DataStoreException(
1202: "The toTime function can only be used with DateTime values"));
1203:
1204: GregorianCalendar cal = new GregorianCalendar();
1205: cal.setTime(d);
1206:
1207: return new java.sql.Time(cal.getTime().getTime());
1208:
1209: }
1210:
1211: private String functionToUpperCase(String s) {
1212: return s.toUpperCase();
1213: }
1214:
1215: private String functionTrim(String s) {
1216: return (s.trim());
1217: }
1218:
1219: private String functionUrlEncode(String s) {
1220: if (s == null)
1221: return null;
1222: StringBuffer b = new StringBuffer();
1223: for (int i = 0; i < s.length(); i++) {
1224: char c = s.charAt(i);
1225: if (c == ' ')
1226: b.append('+');
1227: else if (c == '&')
1228: b.append("%26");
1229: else if (c == '?')
1230: b.append("%3F");
1231: else if (c == '#')
1232: b.append("%35");
1233: else
1234: b.append(c);
1235: }
1236: return b.toString();
1237: }
1238:
1239: /**
1240: * This method returns the original expression that will be evaluated.
1241: */
1242: public String getExpression() {
1243: return _expression;
1244: }
1245:
1246: /**
1247: * This method sets the display format for the result of the expression.
1248: * @see DataStore#setFormat(String,String).
1249: */
1250: public String getFormat() {
1251: return _pattern;
1252: }
1253:
1254: /**
1255: * This method was created in VisualAge.
1256: * @return boolean
1257: * @param token java.lang.String
1258: */
1259: private int getPopCount(String token) {
1260: if (token.equals("substring"))
1261: return 2;
1262: if (token.equals("indexOf"))
1263: return 1;
1264: if (token.equals("lastIndexOf"))
1265: return 1;
1266: if (token.equals("charAt"))
1267: return 1;
1268: if (token.equals("startsWith"))
1269: return 1;
1270: if (token.equals("endsWith"))
1271: return 1;
1272: if (token.equals("round"))
1273: return 1;
1274: if (token.equals("dateAdd"))
1275: return 1;
1276:
1277: return 0;
1278: }
1279:
1280: /**
1281: *
1282: * @return
1283: */
1284: private String getToken() {
1285:
1286: if (_pos >= _expression.length()) {
1287: _lastToken = null;
1288: return null;
1289: }
1290:
1291: StringBuffer ret = new StringBuffer();
1292:
1293: //remove white space
1294: char c = _expression.charAt(_pos);
1295: while (c == ' ') {
1296: _pos++;
1297: if (_pos >= _expression.length()) {
1298: _lastToken = null;
1299: return null;
1300: }
1301: c = _expression.charAt(_pos);
1302: }
1303:
1304: //get the token
1305: char lastChar;
1306: boolean quoteMode = false;
1307: char quoteModeStart = ' ';
1308: while (_pos < _expression.length()) {
1309: lastChar = c;
1310: c = _expression.charAt(_pos);
1311: if (c == '"' || c == '\'') {
1312: if (quoteMode) {
1313: if (lastChar == '~')
1314: ret.append(c);
1315: else if (c != quoteModeStart)
1316: ret.append(c);
1317: else {
1318: _pos++;
1319: _lastToken = ret.toString() + c;
1320: return _lastToken;
1321: }
1322: } else {
1323: quoteMode = true;
1324: quoteModeStart = c;
1325: ret.append(c);
1326: }
1327: } else if (c == '~') {
1328: if (!quoteMode || lastChar == '~')
1329: ret.append("~");
1330: } else if (quoteMode)
1331: ret.append(c);
1332: else if (c == ' ') {
1333: _pos++;
1334: _lastToken = ret.toString();
1335: return _lastToken;
1336: } else if (_terminators.indexOf(c) > -1) {
1337: if (_pos < (_expression.length() - 1)) {
1338: char next = _expression.charAt(_pos + 1);
1339: if ((c == '=' || c == '|' || c == '&')
1340: && (next == c) && ret.length() == 0) {
1341: ret.append(c);
1342: _pos++;
1343: } else if ((c == '!' || c == '>' || c == '<')
1344: && next == '=') {
1345: if (ret.length() == 0) {
1346: ret.append(c);
1347: ret.append('=');
1348: _lastToken = ret.toString();
1349: _pos += 2;
1350: return _lastToken;
1351: } else {
1352: _lastToken = ret.toString();
1353: return _lastToken;
1354: }
1355: }
1356: }
1357:
1358: if (c == '-' && minusIsSign() && ret.length() == 0) {
1359: ret.append(c);
1360: } else if (ret.length() == 0
1361: || ((c == '=' || c == '|' || c == '&') && ret
1362: .length() == 1)) {
1363: _pos++;
1364: ret.append(c);
1365: _lastToken = ret.toString();
1366: return _lastToken;
1367: } else {
1368: _lastToken = ret.toString();
1369: return _lastToken;
1370: }
1371: } else
1372: ret.append(c);
1373:
1374: _pos++;
1375: }
1376:
1377: if (ret.length() == 0) {
1378: _lastToken = null;
1379: return null;
1380: } else {
1381: _lastToken = ret.toString();
1382: return _lastToken;
1383: }
1384:
1385: }
1386:
1387: /**
1388: * This method was created in VisualAge.
1389: * @return int
1390: * @param o java.lang.Object
1391: */
1392: private int getType(Object o) {
1393: if (o instanceof String)
1394: return TYPE_STRING;
1395: else if (o instanceof java.sql.Timestamp)
1396: return TYPE_DATETIME;
1397: else if (o instanceof java.sql.Time)
1398: return TYPE_TIME;
1399: else if (o instanceof java.sql.Date)
1400: return TYPE_DATE;
1401: else if (o instanceof Number)
1402: return TYPE_NUM;
1403: else if (o instanceof Boolean)
1404: return TYPE_BOOL;
1405:
1406: return -1;
1407: }
1408:
1409: /**
1410: *
1411: * @param exp
1412: * @throws EmptyStackException
1413: * @throws DataStoreException
1414: */
1415: private void intoPost(String exp) throws EmptyStackException,
1416: DataStoreException {
1417: //_refs.removeAllElements();
1418: //_refTypes.removeAllElements();
1419:
1420: _expression = exp;
1421: _pos = 0;
1422: _lastToken = null;
1423:
1424: Stack stack = new Stack();
1425: Vector inPost = new Vector();
1426:
1427: String token = getToken();
1428: while (token != null) {
1429: if (token.equals("("))
1430: stack.push(token);
1431: else if (token.equals(")")) {
1432: token = (String) stack.pop();
1433: while (!token.equals("(")) {
1434: appendToVector(inPost, token);
1435: token = (String) stack.pop();
1436: }
1437: } else if (token.equals(",")) {
1438: token = (String) stack.pop();
1439: while (!(token.equals("(") || token.equals(","))) {
1440: appendToVector(inPost, token);
1441: token = (String) stack.pop();
1442: }
1443: stack.push("(");
1444: } else {
1445: int ordOp = orderOfOperations(token);
1446: if (ordOp == 0) {
1447: appendToVector(inPost, token);
1448: } else {
1449: while ((!stack.isEmpty())
1450: && orderOfOperations((String) stack.peek()) <= ordOp) {
1451: appendToVector(inPost, (String) stack.pop());
1452: }
1453: stack.push(token);
1454: }
1455: }
1456: token = getToken();
1457: }
1458:
1459: while (!stack.isEmpty()) {
1460: token = (String) stack.pop();
1461: if (token.equals("(")) {
1462: throw new DataStoreException(
1463: "Unmatched Parentheses Error");
1464: }
1465: appendToVector(inPost, token);
1466: }
1467:
1468: _inPost = new String[inPost.size()];
1469: inPost.copyInto(_inPost);
1470: }
1471:
1472: /**
1473: * This method was created in VisualAge.
1474: * @return boolean
1475: * @param token java.lang.String
1476: */
1477: public static boolean isBoolean(String token) {
1478: String test = token.toLowerCase();
1479: if (test.equals("true") || test.equals("false")) {
1480: return true;
1481: }
1482: return false;
1483: }
1484:
1485: /**
1486: * This method was created in VisualAge.
1487: * @return boolean
1488: * @param token java.lang.String
1489: */
1490: public static boolean isDate(String token) {
1491: if (token.length() > 0) {
1492: if ((token.charAt(0) == '"' || token.charAt(0) == '\'')
1493: && token.charAt(token.length() - 1) == token
1494: .charAt(0)) {
1495: try {
1496: java.sql.Date.valueOf(token.substring(1, token
1497: .length() - 1));
1498: return true;
1499: } catch (Exception e) {
1500: return false;
1501: }
1502: }
1503: }
1504: return false;
1505: }
1506:
1507: /**
1508: * This method was created in VisualAge.
1509: * @return boolean
1510: * @param token java.lang.String
1511: */
1512: public static boolean isDateTime(String token) {
1513: if (token.length() > 0) {
1514: if ((token.charAt(0) == '"' || token.charAt(0) == '\'')
1515: && token.charAt(token.length() - 1) == token
1516: .charAt(0)) {
1517: try {
1518: java.sql.Timestamp.valueOf(token.substring(1, token
1519: .length() - 1)); // unused
1520: return true;
1521: } catch (Exception e) {
1522: return false;
1523: }
1524: }
1525: }
1526: return false;
1527: }
1528:
1529: /**
1530: * This method was created in VisualAge.
1531: * @return boolean
1532: * @param token java.lang.String
1533: */
1534: private boolean isFunction(String token) {
1535: if (token.endsWith(".substring"))
1536: return true;
1537: if (token.endsWith(".indexOf"))
1538: return true;
1539: if (token.endsWith(".lastIndexOf"))
1540: return true;
1541: if (token.endsWith(".toUpperCase"))
1542: return true;
1543: if (token.endsWith(".toLowerCase"))
1544: return true;
1545: if (token.endsWith(".charAt"))
1546: return true;
1547: if (token.endsWith(".startsWith"))
1548: return true;
1549: if (token.endsWith(".endsWith"))
1550: return true;
1551: if (token.endsWith(".trim"))
1552: return true;
1553: if (token.endsWith(".length"))
1554: return true;
1555: if (token.endsWith(".sqrt"))
1556: return true;
1557: if (token.endsWith(".round"))
1558: return true;
1559: if (token.endsWith(".getMonth"))
1560: return true;
1561: if (token.endsWith(".getDate"))
1562: return true;
1563: if (token.endsWith(".getDay"))
1564: return true;
1565: if (token.endsWith(".getYear"))
1566: return true;
1567: if (token.endsWith(".getHours"))
1568: return true;
1569: if (token.endsWith(".getMinutes"))
1570: return true;
1571: if (token.endsWith(".getSeconds"))
1572: return true;
1573: if (token.endsWith(".toDate"))
1574: return true;
1575: if (token.endsWith(".toTime"))
1576: return true;
1577: if (token.endsWith(".dateAdd"))
1578: return true;
1579: if (token.endsWith(".urlEncode"))
1580: return true;
1581: if (token.endsWith(".format"))
1582: return true;
1583: if (token.endsWith(".escape"))
1584: return true;
1585: //if (token.endsWith(".tempValue"))
1586: // return true;
1587:
1588: return false;
1589: }
1590:
1591: /**
1592: * This method was created in VisualAge.
1593: * @return boolean
1594: * @param token java.lang.String
1595: */
1596: public static boolean isNumber(String token) {
1597: String work = new String(token);
1598: int dotPos = token.indexOf(".");
1599: if (dotPos > -1)
1600: work = token.substring(0, dotPos)
1601: + token.substring(dotPos + 1);
1602:
1603: try {
1604: Integer.parseInt(work);
1605: } catch (Exception e) {
1606: return false;
1607: }
1608:
1609: return true;
1610: }
1611:
1612: /**
1613: * This method was created in VisualAge.
1614: * @return boolean
1615: * @param token java.lang.String
1616: */
1617: private boolean isOperator(String token) {
1618: return (orderOfOperations(token) != 0);
1619: }
1620:
1621: /**
1622: * This method was created in VisualAge.
1623: * @return boolean
1624: * @param token java.lang.String
1625: */
1626: public static boolean isString(String token) {
1627: if (token.length() > 0) {
1628: if ((token.charAt(0) == '"' || token.charAt(0) == '\'')
1629: && token.charAt(token.length() - 1) == token
1630: .charAt(0)) {
1631: if (isTime(token))
1632: return false;
1633: else if (isDate(token))
1634: return false;
1635: else if (isDateTime(token))
1636: return false;
1637: else
1638: return true;
1639:
1640: }
1641: }
1642:
1643: return false;
1644: }
1645:
1646: /**
1647: * This method was created in VisualAge.
1648: * @return boolean
1649: * @param token java.lang.String
1650: */
1651: public static boolean isTime(String token) {
1652: if (token.length() > 0) {
1653: if (token.charAt(0) == '"'
1654: && token.charAt(token.length() - 1) == '"') {
1655: try {
1656: java.sql.Time.valueOf(token.substring(1, token
1657: .length() - 1));// unused
1658: return true;
1659: } catch (Exception e) {
1660: return false;
1661: }
1662: }
1663: }
1664: return false;
1665: }
1666:
1667: /**
1668: * This method was created in VisualAge.
1669: * @return boolean
1670: */
1671: private boolean minusIsSign() {
1672: if (_pos < (_expression.length() - 1)) {
1673: char nextChar = _expression.charAt(_pos + 1);
1674: if (Character.isDigit(nextChar) || nextChar == '.')
1675: if (_lastToken == null)
1676: return true;
1677: else if (_lastToken.length() == 0)
1678: return true;
1679: else {
1680: char c = _lastToken.charAt(0);
1681: if ("+*=(,><!".indexOf(c) > -1)
1682: return true;
1683: else if (_lastToken.equals("-"))
1684: return true;
1685: }
1686: }
1687:
1688: return false;
1689: }
1690:
1691: /**
1692: * This method was created in VisualAge.
1693: * @return int
1694: * @param token java.lang.String
1695: */
1696: private int orderOfOperations(String token) {
1697: if (token.equals("^"))
1698: return 2;
1699: else if (token.equals("*") || token.equals("/"))
1700: return 3;
1701: else if (token.equals("+") || token.equals("-"))
1702: return 4;
1703: else if (isFunction(token) || token.equals("if")
1704: || token.equals("tempValue"))
1705: return 1;
1706: else if (token.equals("==") || token.equals(">")
1707: || token.equals("<") || token.equals(">=")
1708: || token.equals("<=") || token.equals("!="))
1709: return 6;
1710: else if (token.equals("!") || token.equals("&&")
1711: || token.equals("||"))
1712: return 7;
1713: else if (token.equals("(") || token.equals(")")
1714: || token.equals(","))
1715: return 8;
1716: else
1717: return 0;
1718: }
1719:
1720: /**
1721: *
1722: * @param type
1723: * @return
1724: * @throws DataStoreException
1725: */
1726: private Object popValue(int type) throws DataStoreException {
1727: if (_st.isEmpty())
1728: throw new DataStoreException(
1729: "Expecting value evaluating expression");
1730:
1731: _stackCount--;
1732:
1733: Object o = _st.pop();
1734: if (o == null)
1735: return o;
1736:
1737: if (type == TYPE_NUM)
1738: if (!(o instanceof Number))
1739: throw new DataStoreException("Expecting Numeric Value");
1740: else if (!(o instanceof Double)) {
1741: o = new Double(((Number) o).doubleValue());
1742: }
1743:
1744: if (type == TYPE_DATETIME)
1745: if (!(o instanceof java.sql.Timestamp))
1746: throw new DataStoreException("Expecting DateTime Value");
1747:
1748: if (type == TYPE_DATE)
1749: if (!(o instanceof java.sql.Date))
1750: throw new DataStoreException("Expecting Date Value");
1751:
1752: if (type == TYPE_TIME)
1753: if (!(o instanceof java.sql.Time))
1754: throw new DataStoreException("Expecting Time Value");
1755:
1756: if (type == TYPE_BOOL)
1757: if (!(o instanceof Boolean))
1758: throw new DataStoreException("Expecting Boolean Value");
1759:
1760: if (type == TYPE_STRING)
1761: if (o instanceof java.sql.Timestamp)
1762: o = o.toString();
1763: else if (!(o instanceof String))
1764: throw new DataStoreException("Expecting String Value");
1765:
1766: return o;
1767: }
1768:
1769: /**
1770: * This method sets the display format for the result of the expression.
1771: * @see DataStore#setFormat(String,String).
1772: */
1773: public void setFormat(String format) {
1774: _pattern = format;
1775: }
1776:
1777: /**
1778: * This method gets the DataStoreExpression being used for this DataStoreEvaluator.
1779: * @return DataStoreExpression
1780: */
1781: public DataStoreExpression getDataStoreExpression() {
1782: return _exp;
1783: }
1784:
1785: /**
1786: * Returns the datastore
1787: */
1788: public DataStoreBuffer getDataStore() {
1789: return _ds;
1790: }
1791: }
|