001 /* 002 * Copyright 2002-2004 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); you may not 005 * use this file except in compliance with the License. You may obtain a copy of 006 * 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, WITHOUT 012 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 013 * License for the specific language governing permissions and limitations under 014 * the License. 015 */ 016 package org.springframework.rules.reporting; 017 018 import java.util.Iterator; 019 020 import org.apache.commons.logging.Log; 021 import org.apache.commons.logging.LogFactory; 022 import org.springframework.core.ReflectiveVisitorHelper; 023 import org.springframework.rules.closure.Closure; 024 import org.springframework.rules.constraint.Constraint; 025 import org.springframework.core.style.ToStringCreator; 026 import org.springframework.rules.constraint.And; 027 import org.springframework.rules.constraint.ClosureResultConstraint; 028 import org.springframework.rules.constraint.Not; 029 import org.springframework.rules.constraint.Or; 030 031 /** 032 * @author Keith Donald 033 */ 034 public class ValidationResultsCollector { 035 protected static final Log logger = LogFactory 036 .getLog(ValidationResultsCollector.class); 037 038 protected ReflectiveVisitorHelper visitorSupport = new ReflectiveVisitorHelper(); 039 040 private ValidationResultsBuilder resultsBuilder; 041 042 private ValidationResults results; 043 044 private boolean collectAllErrors; 045 046 private Object argument; 047 048 public ValidationResultsCollector() { 049 } 050 051 public ValidationResults collect(final Object argument, 052 final Constraint constraint) { 053 this.resultsBuilder = new ValidationResultsBuilder() { 054 public void constraintSatisfied() { 055 } 056 057 public void constraintViolated(Constraint constraint) { 058 results = new ValueValidationResults(argument, constraint); 059 } 060 }; 061 if (results == null) { 062 results = new ValueValidationResults(argument); 063 } 064 this.argument = argument; 065 visitorSupport.invokeVisit(this, constraint); 066 return results; 067 } 068 069 public void setCollectAllErrors(boolean collectAllErrors) { 070 this.collectAllErrors = collectAllErrors; 071 } 072 073 protected ValidationResultsBuilder getResultsBuilder() { 074 return resultsBuilder; 075 } 076 077 protected void setResultsBuilder(ValidationResultsBuilder resultsBuilder) { 078 this.resultsBuilder = resultsBuilder; 079 } 080 081 protected void setArgument(Object argument) { 082 this.argument = argument; 083 } 084 085 boolean visit(And and) { 086 resultsBuilder.pushAnd(); 087 if (logger.isDebugEnabled()) { 088 logger.debug("Starting [and]..."); 089 } 090 boolean result = true; 091 Iterator it = and.iterator(); 092 while (it.hasNext()) { 093 boolean test = ((Boolean)visitorSupport.invokeVisit( 094 ValidationResultsCollector.this, it.next())).booleanValue(); 095 if (!test) { 096 if (!collectAllErrors) { 097 resultsBuilder.pop(false); 098 return false; 099 } 100 101 if (result) { 102 result = false; 103 } 104 } 105 } 106 if (logger.isDebugEnabled()) { 107 logger.debug("Finished [and]..."); 108 } 109 resultsBuilder.pop(result); 110 return result; 111 } 112 113 boolean visit(Or or) { 114 resultsBuilder.pushOr(); 115 if (logger.isDebugEnabled()) { 116 logger.debug("Starting [or]..."); 117 } 118 Iterator it = or.iterator(); 119 while (it.hasNext()) { 120 boolean result = ((Boolean)visitorSupport.invokeVisit( 121 ValidationResultsCollector.this, it.next())).booleanValue(); 122 if (result) { 123 resultsBuilder.pop(result); 124 return true; 125 } 126 } 127 if (logger.isDebugEnabled()) { 128 logger.debug("Finished [or]..."); 129 } 130 resultsBuilder.pop(false); 131 return false; 132 } 133 134 Boolean visit(Not not) { 135 resultsBuilder.pushNot(); 136 if (logger.isDebugEnabled()) { 137 logger.debug("Starting [not]..."); 138 } 139 Boolean result = (Boolean)visitorSupport.invokeVisit(this, not 140 .getConstraint()); 141 if (logger.isDebugEnabled()) { 142 logger.debug("Finished [not]..."); 143 } 144 resultsBuilder.pop(result.booleanValue()); 145 return result; 146 } 147 148 Boolean visit(ClosureResultConstraint ofConstraint) { 149 Closure f = ofConstraint.getFunction(); 150 if (logger.isDebugEnabled()) { 151 logger.debug("Invoking function with argument " + argument); 152 } 153 setArgument(f.call(argument)); 154 return (Boolean)visitorSupport.invokeVisit(this, ofConstraint 155 .getPredicate()); 156 } 157 158 boolean visit(Constraint constraint) { 159 if (logger.isDebugEnabled()) { 160 logger.debug("Testing constraint [" + constraint + "] with argument '" 161 + argument + "']"); 162 } 163 boolean result = constraint.test(argument); 164 result = applyAnyNegation(result); 165 if (!result) { 166 resultsBuilder.push(constraint); 167 } 168 if (logger.isDebugEnabled()) { 169 logger.debug("Constraint [" + constraint + "] " 170 + (result ? "passed" : "failed")); 171 } 172 return result; 173 } 174 175 protected boolean applyAnyNegation(boolean result) { 176 boolean negated = resultsBuilder.negated(); 177 if (logger.isDebugEnabled()) { 178 if (negated) { 179 logger.debug("[negate result]"); 180 } 181 else { 182 logger.debug("[no negation]"); 183 } 184 } 185 return negated ? !result : result; 186 } 187 188 public String toString() { 189 return new ToStringCreator(this).append("collectAllErrors", 190 collectAllErrors).append("validationResultsBuilder", 191 resultsBuilder).toString(); 192 } 193 194 }