001: //** Copyright Statement ***************************************************
002: //The Salmon Open Framework for Internet Applications (SOFIA)
003: // Copyright (C) 1999 - 2002, Salmon LLC
004: //
005: // This program is free software; you can redistribute it and/or
006: // modify it under the terms of the GNU General Public License version 2
007: // as published by the Free Software Foundation;
008: //
009: // This program is distributed in the hope that it will be useful,
010: // but WITHOUT ANY WARRANTY; without even the implied warranty of
011: // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
012: // GNU General Public License for more details.
013: //
014: // You should have received a copy of the GNU General Public License
015: // along with this program; if not, write to the Free Software
016: // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
017: //
018: // For more information please visit http://www.salmonllc.com
019: //** End Copyright Statement ***************************************************
020:
021: package com.salmonllc.sql;
022:
023: import java.sql.Statement;
024: import java.sql.ResultSet;
025:
026: import com.salmonllc.util.RegularExpressionMatcher;
027:
028: /**
029: * The definition of a validation rule
030: */
031: public class ValidationRule implements java.io.Serializable {
032: public static final int TYPE_EXPRESSION = 0;
033: public static final int TYPE_TYPE_CHECK = 1;
034: public static final int TYPE_LOOKUP = 3;
035: public static final int TYPE_REMOTE = 4;
036: public static final int TYPE_REQUIRED = 5;
037: public static final int TYPE_JAVASCRIPT = 6;
038: public static final int TYPE_REGULAR_EXPRESSION = 7;
039: public static final int TYPE_RANGE = 8;
040: private int _ruleType;
041: private String _expression;
042: private DataStoreExpression _dsExpression;
043: private transient DataStoreEvaluator _eval;
044: private String _errorMessage;
045: private Object _minValue, _maxValue;
046: private boolean _executeOnServer = false;
047: private String _lookupTable, _lookupExpression, _desciptionColumn,
048: _descriptionBucket;
049: private RegularExpressionMatcher _regMatcher;
050:
051: /**
052: * Creates an expression rule. The expression is a boolean value and the rule will be violated if the expression returns false
053: * @param expression The expression to evaluate
054: * @param errorMessage The message to return if the rule is violated
055: */
056: public ValidationRule(String expression, String errorMessage) {
057: _expression = expression;
058: _executeOnServer = false;
059: _errorMessage = errorMessage;
060: _ruleType = TYPE_EXPRESSION;
061: }
062:
063: /**
064: * Creates a range rule. The rule is true if the value of the field is within the minValue and maxValue
065: */
066: public ValidationRule(Object minValue, Object maxValue,
067: String errorMessage) {
068: _minValue = minValue;
069: _maxValue = maxValue;
070: _executeOnServer = false;
071: _errorMessage = errorMessage;
072: _ruleType = TYPE_RANGE;
073: }
074:
075: /**
076: * Creates an expression rule. The rule can be a SOFIA expression or a regular expression. A SOFIA expression returns a boolean value and the rule will be violated if the expression returns false. A regular expression will be violated if the value in the datastore column doesn't match the specified regular expression
077: * @param expression The expression to evaluate
078: * @param errorMessage The message to return if the rule is violated
079: * @param type TYPE_EXPRESSION (SOFIA Expression) or TYPE_REGULAR_EXPRESSION (Regular Expression) or TYPE_JAVASCRIPT (Note JavaScript Rules are not executed by this validator, they can be added here as a place holder in case the rules are imported into an HtmlValidatorTextComponent)
080: */
081: public ValidationRule(String expression, String errorMessage,
082: int type) {
083: _expression = expression;
084: _executeOnServer = false;
085: _errorMessage = errorMessage;
086: if (type == TYPE_REGULAR_EXPRESSION)
087: _regMatcher = new RegularExpressionMatcher(expression);
088: _ruleType = type;
089: }
090:
091: /**
092: * Creates an expression rule. The expression is a boolean value and the rule will be violated if the expression returns false
093: * @param expression The expression to evaluate
094: * @param errorMessage The message to return if the rule is violated
095: * @param executeOnServer If the validator is being used from a proxy datastore and the rule must be executed on the server set this value to true
096: */
097: public ValidationRule(DataStoreExpression expression,
098: String errorMessage, boolean executeOnServer) {
099: _dsExpression = expression;
100: _executeOnServer = executeOnServer;
101: _errorMessage = errorMessage;
102: _ruleType = TYPE_EXPRESSION;
103: }
104:
105: /**
106: * Creates a type check rule. The type check rule checks if a field is the correct data type
107: * @param errorMessage The message to return if the rule is violated
108: */
109: public ValidationRule(String errorMessage) {
110: _ruleType = TYPE_TYPE_CHECK;
111: _executeOnServer = false;
112: _errorMessage = errorMessage;
113: }
114:
115: /**
116: * Creates a type or a required rule rule. The type check rule checks if a field is the correct data type, required checks that the value is not null or spaces
117: * @param errorMessage The message to return if the rule is violated
118: * @param type The type of rule TYPE_TYPE_CHECK or TYPE_REQUIRED
119: */
120: public ValidationRule(String errorMessage, int type) {
121: _ruleType = type;
122: _executeOnServer = false;
123: _errorMessage = errorMessage;
124: }
125:
126: /**
127: * Creates a lookup rule
128: * @param lookupTable The name of the table to lookup the value against.
129: * @param searchExpression A DataStore Expression that returns a String and will be used as the where clause for the SQL that will validate the data.
130: * @param errorMessage The error message to display if the error expression returns false.
131: * @param descriptionColumn The name of the column in the lookup table used to fill in the description.
132: * @param descriptionBucket The name of a bucket column in the datastore to place the description.
133: * @param errorMessage The message to return if the rule is violated
134: */
135: public ValidationRule(String lookupTable, String searchExpression,
136: String descriptionColumn, String descriptionBucket,
137: String errorMessage) {
138: _ruleType = TYPE_LOOKUP;
139: _executeOnServer = true;
140: _lookupTable = lookupTable;
141: _lookupExpression = searchExpression;
142: _desciptionColumn = descriptionColumn;
143: _descriptionBucket = descriptionBucket;
144: _errorMessage = errorMessage;
145: }
146:
147: /**
148: * Creates a proxy rule that will run on the server
149: */
150: public ValidationRule() {
151: _ruleType = TYPE_REMOTE;
152: _executeOnServer = true;
153: }
154:
155: /**
156: * Evaluates the rule for a specific datastore, row and column. It throws a DataStoreException if the rule is violated
157: */
158: public void evaluateRule(DataStoreBuffer ds, int rowNo, int colNo,
159: DBConnection conn) throws DataStoreException {
160: if (_ruleType == TYPE_TYPE_CHECK) {
161: if (ds.getTempValue(rowNo, colNo) == null)
162: return;
163: else if (!ds.isFormattedStringValid(colNo, ds.getTempValue(
164: rowNo, colNo))) {
165: throw new DataStoreException(_errorMessage);
166: }
167: } else if (_ruleType == TYPE_EXPRESSION) {
168: DataStoreEvaluator eval = getEvaluator(ds);
169: Object o = eval.evaluateRow(rowNo);
170: if (!(o instanceof Boolean))
171: throw new DataStoreException(
172: "Error, rule expression is not boolean");
173: else if (!((Boolean) o).booleanValue())
174: throw new DataStoreException(_errorMessage);
175: } else if (_ruleType == TYPE_LOOKUP && conn != null) {
176: if (!validateLookup(ds, rowNo, colNo, conn)) {
177: throw new DataStoreException(_errorMessage);
178: }
179: } else if (_ruleType == TYPE_REQUIRED) {
180: if (ds.getAny(rowNo, colNo) == null)
181: throw new DataStoreException(_errorMessage);
182: else if (ds.getColumnDataType(colNo) == DataStoreBuffer.DATATYPE_STRING
183: && ds.getString(rowNo, colNo).trim().length() == 0)
184: throw new DataStoreException(_errorMessage);
185: } else if (_ruleType == TYPE_REGULAR_EXPRESSION) {
186: String st = ds.getFormattedString(rowNo, colNo);
187: if (!_regMatcher.match(st))
188: throw new DataStoreException(_errorMessage);
189: } else if (_ruleType == TYPE_RANGE) {
190: if (_minValue != null) {
191: if (!ds.valueEqual(rowNo, colNo, _minValue))
192: if (!ds.valueGreater(rowNo, colNo, _minValue))
193: throw new DataStoreException(_errorMessage);
194: }
195: if (_maxValue != null) {
196: if (!ds.valueEqual(rowNo, colNo, _maxValue))
197: if (!ds.valueLess(rowNo, colNo, _maxValue))
198: throw new DataStoreException(_errorMessage);
199: }
200: }
201: }
202:
203: public String getDesciptionColumn() {
204: return _desciptionColumn;
205: }
206:
207: public String getDescriptionBucket() {
208: return _descriptionBucket;
209: }
210:
211: public DataStoreExpression getDsExpression() {
212: return _dsExpression;
213: }
214:
215: public String getErrorMessage() {
216: return _errorMessage;
217: }
218:
219: public boolean isExecuteOnServer() {
220: return _executeOnServer;
221: }
222:
223: public String getExpression() {
224: return _expression;
225: }
226:
227: public String getLookupExpression() {
228: return _lookupExpression;
229: }
230:
231: public String getLookupTable() {
232: return _lookupTable;
233: }
234:
235: public int getRuleType() {
236: return _ruleType;
237: }
238:
239: private boolean validateLookup(DataStoreBuffer ds, int rowNo,
240: int colNo, DBConnection conn) throws DataStoreException {
241:
242: boolean retVal = false;
243:
244: String lookupTable = _lookupTable;
245: DataStoreEvaluator d = getEvaluator(ds);
246: String descColumn = _desciptionColumn;
247: String descBucket = _descriptionBucket;
248:
249: if (ds.getAny(rowNo, colNo) == null) {
250: if (descBucket != null) {
251: ds.setAny(rowNo, descBucket, null);
252: return true;
253: }
254: }
255:
256: String sql = "";
257: if (descColumn != null)
258: sql = "SELECT " + descColumn + " FROM " + lookupTable
259: + " WHERE ";
260: else
261: sql = "SELECT count(*) FROM " + lookupTable + " WHERE ";
262:
263: sql += (String) d.evaluateRow(rowNo);
264:
265: String desc = null;
266: try {
267: Statement st = conn.createStatement();
268: ResultSet r = st.executeQuery(sql);
269:
270: if (r.next()) {
271: if (descColumn == null) {
272: if (r.getInt(1) > 0)
273: retVal = true;
274: } else {
275: desc = r.getString(1);
276: retVal = true;
277: }
278: }
279: r.close();
280: st.close();
281: } catch (java.sql.SQLException ex) {
282: throw new DataStoreException(ex.getMessage(), ex);
283: }
284:
285: if (descBucket != null)
286: ds.setString(rowNo, descBucket, desc);
287:
288: return retVal;
289: }
290:
291: private DataStoreEvaluator getEvaluator(DataStoreBuffer ds)
292: throws DataStoreException {
293: if (_eval != null)
294: if (_eval.getDataStore() != ds)
295: _eval = null;
296:
297: if (_eval == null) {
298: if (_expression != null)
299: _eval = new DataStoreEvaluator(ds, _expression);
300: else if (_dsExpression != null)
301: _eval = new DataStoreEvaluator(ds, _dsExpression);
302: else if (_lookupExpression != null)
303: _eval = new DataStoreEvaluator(ds, _lookupExpression);
304: }
305: return _eval;
306: }
307:
308: public Object getMaxValue() {
309: return _maxValue;
310: }
311:
312: public Object getMinValue() {
313: return _minValue;
314: }
315:
316: }
|