001 package edu.nrao.sss.model.project.scan; 002 003 import java.util.ArrayList; 004 import java.util.List; 005 006 import edu.nrao.sss.validation.AbstractValidator; 007 import edu.nrao.sss.validation.FailureSeverity; 008 import edu.nrao.sss.validation.Validation; 009 import edu.nrao.sss.validation.ValidationFailure; 010 import edu.nrao.sss.validation.ValidationPurpose; 011 import edu.nrao.sss.validation.Validator; 012 013 /** 014 * A validator of {@link ScanLoop scan loops}. 015 * <p> 016 * <u>Validations Performed for All Purposes</u> 017 * <ol> 018 * <li>Loop is not empty.</li> 019 * <li>Iteration count is positive.</li> 020 * <li>Maximum duration is positive.</li> 021 * <li>TODO: Start/stop times and durations of contained scans makes sense.</li> 022 * <li>Contained scans and scan loops are valid.<sup>1</sup></li> 023 * </ol> 024 * <sup>1</sup><i>The particular validations performed depend on the 025 * validator used by this one to operate on those contained scans</i>.</p> 026 * <p> 027 * <b>Version Info:</b> 028 * <table style="margin-left:2em"> 029 * <tr><td>$Revision: 1709 $</td></tr> 030 * <tr><td>$Date: 2008-11-14 11:22:37 -0700 (Fri, 14 Nov 2008) $</td></tr> 031 * <tr><td>$Author: dharland $</td></tr> 032 * </table></p> 033 * 034 * @author David M. Harland 035 * @since 2007-02-13 036 */ 037 public class ScanLoopValidator 038 extends AbstractValidator<ScanLoop> 039 { 040 private ScanValidator<? extends Scan> scanValidator; 041 042 private boolean skipLoop; 043 private int depth; 044 045 /** Creates a new instance. */ 046 public ScanLoopValidator() 047 { 048 super(ScanLoopValidator.class.getName(), ScanLoop.class); 049 skipLoop = false; 050 depth = 0; 051 } 052 053 public void setScanValidator(ScanValidator<? extends Scan> scanValidator) 054 { 055 this.scanValidator = scanValidator; 056 } 057 058 /** 059 * Tells this validator whether or not it should skip the validation 060 * of the target loop. Even if <tt>skip</tt> is set to <i>true</i>, 061 * the scans and inner loops of this loop will be validated. 062 * <p> 063 * This validator is originally configured so that it will 064 * not skip any validation.</p> 065 * <p> 066 * It is expected that validators of scheduling blocks will 067 * use this method with a parameter of <i>true</i>.</p> 068 * 069 * @param skip 070 * <i>true</i> if this validator should validate the contents 071 * of the target loop, but not the target loop itself. 072 */ 073 public void setSkipOutermostLoop(boolean skip) 074 { 075 skipLoop = skip; 076 } 077 078 /* (non-Javadoc) 079 * @see AbstractValidator#makeValidationList(ValidationPurpose) 080 */ 081 @Override 082 protected List<Validation<ScanLoop>> 083 makeValidationList(ValidationPurpose purpose) 084 { 085 List<Validation<ScanLoop>> validations = 086 new ArrayList<Validation<ScanLoop>>(); 087 088 validations.add(new HasElements (this, purpose)); 089 validations.add(new HasIterations(this, purpose)); 090 validations.add(new HasTime (this, purpose)); 091 092 return validations; 093 } 094 095 /* (non-Javadoc) 096 * @see edu.nrao.sss.model.validation.AbstractValidator#validate() 097 */ 098 @Override 099 protected void validate() 100 { 101 depth++; 102 103 if (!skipLoop || depth > 1) 104 super.validate(); 105 106 //Validate elements of the loop. 107 //Need to fetch validator within the loop because each element 108 //could be of a different type, requiring a diff validator. 109 for (ScanLoopElement element : target.getElements()) 110 { 111 Validator elemVal = getScanLoopElementValidator(element); 112 113 List<ValidationFailure> elemFailures = elemVal.validate(element, purpose); 114 115 if (elemVal != this) 116 failures.addAll(elemFailures); 117 } 118 119 depth--; 120 } 121 122 //============================================================================ 123 // COMPONENT VALIDATORS 124 //============================================================================ 125 126 /** Returns a validator for scan loop elements. */ 127 public Validator getScanLoopElementValidator(ScanLoopElement element) 128 { 129 Validator validator = scanValidator; 130 131 if (validator == null) 132 { 133 if (manager != null) 134 validator = manager.getValidator(element.getClass()); 135 136 if (validator == null) 137 validator = (element instanceof ScanLoop) ? this : new SimpleScanValidator(); 138 } 139 140 return validator; 141 } 142 143 //============================================================================ 144 // ENSURE LOOP HAS ELEMENTS 145 //============================================================================ 146 147 /** Make sure scan loop contains at least one scan or scan loop. */ 148 class HasElements extends Validation<ScanLoop> 149 { 150 protected HasElements(AbstractValidator<ScanLoop> validationContainer, 151 ValidationPurpose reasonForValidation) 152 { 153 super(validationContainer, reasonForValidation); 154 155 severity = 156 (reasonForValidation == ValidationPurpose.CERTIFY_READY_TO_USE) ? 157 FailureSeverity.ERROR : FailureSeverity.WARNING; 158 } 159 160 /** This test is passed if loop is not empty. */ 161 @Override 162 protected boolean passesTest() 163 { 164 return target.size() > 0; 165 } 166 167 /* (non-Javadoc) 168 * @see edu.nrao.sss.validation.Validation#displayMessage() 169 */ 170 @Override 171 protected String displayMessage() 172 { 173 StringBuilder buff = new StringBuilder("Scan loop '"); 174 buff.append(target.getName()).append("' is empty. "); 175 176 if (purpose == ValidationPurpose.CERTIFY_READY_TO_USE) 177 { 178 buff.append("A scan loop must have at least one scan or scan loop") 179 .append(" in order to be executed. Please add a scan or scan loop") 180 .append(" to this loop, or remove it altogether."); 181 } 182 else 183 { 184 buff.append("This is fine for now, but you will need to add at least") 185 .append(" one scan or scan loop to this loop before the") 186 .append(" containing project is ready for execution."); 187 } 188 189 return buff.toString(); 190 } 191 192 /* (non-Javadoc) 193 * @see edu.nrao.sss.validation.Validation#debugMessage() 194 */ 195 @Override 196 protected String debugMessage() 197 { 198 StringBuilder buff = new StringBuilder("ScanLoop '"); 199 200 buff.append(target.getId()).append("' has no elements."); 201 202 return buff.toString(); 203 } 204 } 205 206 //============================================================================ 207 // ENSURE LOOP HAS POSITIVE ITERATION COUNT 208 //============================================================================ 209 210 /** Make sure scan loop has iteration count > 0. */ 211 class HasIterations extends Validation<ScanLoop> 212 { 213 protected HasIterations(AbstractValidator<ScanLoop> validationContainer, 214 ValidationPurpose reasonForValidation) 215 { 216 super(validationContainer, reasonForValidation); 217 218 severity = 219 (reasonForValidation == ValidationPurpose.CERTIFY_READY_TO_USE) ? 220 FailureSeverity.ERROR : FailureSeverity.WARNING; 221 } 222 223 /** This test is passed if loop is not empty. */ 224 @Override 225 protected boolean passesTest() 226 { 227 return target.getIterationCount() > 0; 228 } 229 230 /* (non-Javadoc) 231 * @see edu.nrao.sss.validation.Validation#displayMessage() 232 */ 233 @Override 234 protected String displayMessage() 235 { 236 StringBuilder buff = new StringBuilder("Scan loop '"); 237 buff.append(target.getName()); 238 buff.append("' has an iteration count of zero. "); 239 240 if (purpose == ValidationPurpose.CERTIFY_READY_TO_USE) 241 { 242 buff.append("A scan loop must have at least one iteration") 243 .append(" in order to be executed. Please set the iteration") 244 .append(" count to a value greater than zero."); 245 } 246 else 247 { 248 buff.append("This is fine for now, but you will need to set the") 249 .append(" iteration count to a value greater than zero before the") 250 .append(" containing project is ready for execution."); 251 } 252 253 return buff.toString(); 254 } 255 256 /* (non-Javadoc) 257 * @see edu.nrao.sss.validation.Validation#debugMessage() 258 */ 259 @Override 260 protected String debugMessage() 261 { 262 StringBuilder buff = new StringBuilder("ScanLoop '"); 263 264 buff.append(target.getId()).append("' has no iterations."); 265 266 return buff.toString(); 267 } 268 } 269 270 //============================================================================ 271 // ENSURE LOOP HAS POSITIVE MAXIMUM DURATION 272 //============================================================================ 273 274 /** Make sure scan loop has max duration > 0. */ 275 class HasTime extends Validation<ScanLoop> 276 { 277 protected HasTime(AbstractValidator<ScanLoop> validationContainer, 278 ValidationPurpose reasonForValidation) 279 { 280 super(validationContainer, reasonForValidation); 281 282 severity = 283 (reasonForValidation == ValidationPurpose.CERTIFY_READY_TO_USE) ? 284 FailureSeverity.ERROR : FailureSeverity.WARNING; 285 } 286 287 /** This test is passed if loop has positive maximum duration. */ 288 @Override 289 protected boolean passesTest() 290 { 291 return target.getMaximumDuration().getValue().signum() > 0; 292 } 293 294 /* (non-Javadoc) 295 * @see edu.nrao.sss.validation.Validation#displayMessage() 296 */ 297 @Override 298 protected String displayMessage() 299 { 300 StringBuilder buff = new StringBuilder("Scan loop '"); 301 buff.append(target.getName()); 302 buff.append("' has a maximum duration of zero. "); 303 304 if (purpose == ValidationPurpose.CERTIFY_READY_TO_USE) 305 { 306 buff.append("A scan loop must have at a positive maximum duration") 307 .append(" in order to be executed. Please set the maximum") 308 .append(" duration to a value greater than zero."); 309 } 310 else 311 { 312 buff.append("This is fine for now, but you will need to set the") 313 .append(" maximum duration to a value greater than zero before the") 314 .append(" containing project is ready for execution."); 315 } 316 317 return buff.toString(); 318 } 319 320 /* (non-Javadoc) 321 * @see edu.nrao.sss.validation.Validation#debugMessage() 322 */ 323 @Override 324 protected String debugMessage() 325 { 326 StringBuilder buff = new StringBuilder("ScanLoop '"); 327 328 buff.append(target.getId()).append("' has max duration of zero."); 329 330 return buff.toString(); 331 } 332 } 333 }