001: /*
002: * Copyright 2003 The Apache Software Foundation.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package velosurf.validation;
018:
019: import java.sql.SQLException;
020: import java.util.Locale;
021: import java.util.regex.Pattern;
022:
023: /**
024: * <p>A type and range constraint on numbers. Syntax is:</p>
025: * <pre>
026: * <<i>column</i> [type="integer"] [min="<i>min</i>"] [max="<i>max</i>"]/>
027: * </pre>
028: * <p>where you donnot need to specify both min and max.</p>
029: * <p>Or:</p>
030: * <pre>
031: * <integer|number [min="<i>min-value</i>"] [max="<i>max-value</i>"] [message="<i>error-message</i>"] />
032: * </pre>
033: * <p>Note: this constraint is not meant to replace an internal SQL constraint in the database,
034: * since it cannot be made sure that complex updates will respect this constraint.</p>
035: *
036: * @author <a href="mailto:claude.brisson@gmail.com">Claude Brisson</a>
037: */
038: public class Range extends FieldConstraint {
039: /** minimum value. */
040: private Number min = null;
041: /** maximum value. */
042: private Number max = null;
043: /** integer value expected. */
044: private boolean integer = false;
045: /** integer value pattern matcher. */
046: private static Pattern intPattern = Pattern
047: .compile("(?:\\+|-)?\\d+");
048:
049: /**
050: * Constructor.
051: */
052: public Range() {
053: setMessage("field {0}: '{1}' is not in the valid range");
054: }
055:
056: /**
057: * Whether to expect an integer or not.
058: * @param integer a boolean
059: */
060: public void setInteger(boolean integer) {
061: this .integer = integer;
062: }
063:
064: /**
065: * Minimum value setter.
066: * @param min minimum value
067: */
068: public void setMin(Number min) {
069: this .min = min;
070: }
071:
072: /**
073: * Maximum value setter.
074: * @param max maximum value
075: */
076: public void setMax(Number max) {
077: this .max = max;
078: }
079:
080: /**
081: * Validate data against this constraint.
082: * @param data the data to be validated
083: * @return true if data is in the expected range and type
084: */
085: public boolean validate(Object data) throws SQLException {
086: if (data == null || data.toString().length() == 0) {
087: return true;
088: }
089: Number number;
090: if (data instanceof Number) {
091: number = (Number) data;
092: } else {
093: try {
094: if (integer) {
095: number = Integer.parseInt(data.toString());
096: } else {
097: number = Double.parseDouble(data.toString());
098: }
099: } catch (NumberFormatException nfe) {
100: return false;
101: }
102: }
103: if (min != null && min.doubleValue() > number.doubleValue()) {
104: return false;
105: }
106: if (max != null && max.doubleValue() < number.doubleValue()) {
107: return false;
108: }
109: return true;
110: }
111:
112: /**
113: * return a string representation for this constraint.
114: * @return string
115: */
116: public String toString() {
117: return (integer ? "type integer" : "type number")
118: + (min != null && max != null ? ", between " + min
119: + " and " + max : min != null ? ", >= " + min
120: : ", <=" + max);
121: }
122: }
|