001 /*
002 * Copyright (c) 2005 Peter Palotas, Fredrik Johansson, Einar Pehrson,
003 * Sebastian Kekkonen, Lars Magnus Lång, Malin Johansson and Sofia Nilsson
004 *
005 * This file is part of
006 * CleanSheets Extension for Assertions
007 *
008 * CleanSheets Extension for Assertions is free software; you can
009 * redistribute it and/or modify it under the terms of the GNU General Public
010 * License as published by the Free Software Foundation; either version 2 of
011 * the License, or (at your option) any later version.
012 *
013 * CleanSheets Extension for Assertions is distributed in the hope that
014 * it will be useful, but WITHOUT ANY WARRANTY; without even the implied
015 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
016 * See the GNU General Public License for more details.
017 *
018 * You should have received a copy of the GNU General Public License
019 * along with CleanSheets Extension for Assertions; if not, write to the
020 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
021 * Boston, MA 02111-1307 USA
022 */
023 package csheets.ext.assertion;
024
025 import java.io.Serializable;
026 import java.util.Iterator;
027
028 import csheets.core.IllegalValueTypeException;
029 import csheets.core.Value;
030
031 /** Abstract class representing an assertion. This class contains the common
032 data and functionality for assertion (USAssertion and SGAssertion).
033 @author Peter Palotas
034 */
035 public abstract class Assertion implements Serializable {
036
037 /** Represents the intervals of allowed values for this assertion. */
038 protected MultiInterval intervals = new MultiInterval();
039
040 /** Indicates wether only integer values are allowed */
041 protected boolean isInteger;
042
043 /** Enumeration indicating the result of a validation of a value. */
044 public enum Result {
045 /** Indicates the assertion succeeded. */
046 OK,
047 /** Indicates the assertion failed. */
048 FAILED,
049 /** Indicates there was no data to validate. */
050 NO_DATA,
051 /** Indicates the assertion failed because the data was not a number. */
052 NAN
053 };
054
055 /**
056 * The possible results when two assertions are compared.
057 * @see AssertableCell#assertAssertions()
058 */
059 public enum ComparisonResult {
060 /** Denotes that the assertions on this cell are okay */
061 OK,
062 /** Denotes that the user supplied assertion and the system generated assertion
063 associated with this cell do <i>not</i> represent the same range(s) of values. */
064 NON_EQUAL,
065 /** Denotes that the system generated assertion for this cell can not be generated because the
066 formula in this cell contains a possible illegal mathematic operation. Such as division by
067 zero or calculations with an imaginary result. (Due to either an error in the formula
068 itself or in the assertion(s) of its precedents. */
069 ILLEGAL_INTERVAL {
070 /** A message describing the error */
071 private String errorMsg;
072
073 public void setErrorMsg(String msg) {
074 errorMsg = msg;
075 }
076
077 public String getErrorMsg() {
078 return errorMsg;
079 }
080 };
081 public void setErrorMsg(String msg) {}
082
083 public String getErrorMsg() {
084 return null;
085 }
086 };
087
088 /** Returns an iterator over the intervals representing all allowed values in
089 this assertion. Note that this iterator cannot be used to modify the underlying
090 collection.
091 @return Returns an iterator over the intervals representing all allowed values in
092 this assertion. */
093 public Iterator<Interval> getIntervalIterator() {
094 return intervals.iterator();
095 }
096
097 /** Returns the MultiInterval specifying the valid values for this assertion.
098 @return the MultiInterval specifying the valid values for this assertion.*/
099 public MultiInterval getMultiInterval() {
100 return intervals;
101 }
102
103 /** Checks if this assertion allows only integer values.
104 @return <code>true</code> if this assertion will validate only integer values
105 successfully, and <code>false</code> otherwise. */
106 public boolean allowsIntegersOnly() {
107 return isInteger;
108 }
109
110 /**
111 * Checks if the current assertion holds for the given value. The value
112 * may be any object.
113 * @param value An arbritrary object. The value the assertion will be verified
114 * against will be retrieved from the object using its <code>toString()</code> method.
115 * @return <ul>
116 <li><code>Result.NO_DATA</code> if <code>value</code> is <code>null</code> or
117 <code>value.toString()</code> returns an empty string.
118 <li><code>Result.NAN</code> if the string returned by <code>value.toString()</code>
119 does not represent a number parsable by <code>Double.parseDouble()</code>.
120 <li><code>Result.OK</code> if assertion holds for the value.
121 <li><code>Result.FAILED</code> if the assertion failed for the value, unless
122 one of the reasons above.
123 </ul>
124 */
125 public Result validate(Value value) {
126 if (value.toAny() == null)
127 return Result.NO_DATA;
128 try {
129 return validate(value.toDouble());
130 } catch (IllegalValueTypeException e) {
131 return Result.NAN;
132 }
133
134 }
135 /**
136 * Checks if the current assertion holds for the given value
137 * @return <ul>
138 <li><code>Result.OK</code> if the assertion holds for the value,
139 * <li><code>Result.NAN</code> if <code>value == Double.NaN</code>
140 * <li><code>Result.FAILED</code> otherwise.
141 </ul>
142 */
143 public Result validate(double value) {
144 if (Double.isNaN(value))
145 return Result.NAN;
146
147 // Check if the isInteger criterion holds
148 if (isInteger && (Math.ceil(value) != Math.floor(value)))
149 {
150 return Result.FAILED;
151 }
152
153 return intervals.contains(value) ? Result.OK : Result.FAILED;
154
155 }
156
157 public boolean equals(Object o) {
158 if (o == null)
159 return false;
160
161 if (!(o instanceof Assertion))
162 return false;
163
164 Assertion a = (Assertion)o;
165
166 return intervals.equals(a.intervals);
167 }
168
169 public String toString() {
170 String s = "";
171 for (Iterator<Interval> iter = intervals.iterator(); iter.hasNext(); ) {
172 Interval i = iter.next();
173 s += i.toString();
174 if (iter.hasNext())
175 s += " or ";
176 }
177 return s;
178 }
179
180 }