001/* 002 * Copyright (c) 2005 Peter Palotas, Fredrik Johansson, Einar Pehrson, 003 * Sebastian Kekkonen, Lars Magnus Lang, 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 */ 023package csheets.ext.assertion; 024 025import java.io.Serializable; 026import java.util.Iterator; 027 028import csheets.core.IllegalValueTypeException; 029import 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*/ 035public 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}