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 org.springframework.rules.constraint.Constraint;
019    import org.springframework.rules.closure.support.Block;
020    import org.springframework.rules.Rules;
021    import org.springframework.rules.constraint.property.CompoundPropertyConstraint;
022    import org.springframework.rules.constraint.property.PropertyConstraint;
023    import org.springframework.rules.constraint.property.PropertyValueConstraint;
024    import org.springframework.util.Assert;
025    
026    /**
027     * @author Keith Donald
028     */
029    public class BeanValidationResultsCollector extends ValidationResultsCollector {
030    
031        private Object bean;
032    
033        public BeanValidationResultsCollector(Object bean) {
034            super();
035            setBean(bean);
036        }
037    
038        public void setBean(Object bean) {
039            Assert.notNull(bean, "bean is required");
040            this.bean = bean;
041        }
042    
043        protected BeanValidationResultsBuilder getBeanResultsBuilder() {
044            return (BeanValidationResultsBuilder)getResultsBuilder();
045        }
046    
047        public void setResultsBuilder(ValidationResultsBuilder builder) {
048            Assert.isTrue(builder instanceof BeanValidationResultsBuilder,
049                    "Builder must be a bean validation results builder");
050            super.setResultsBuilder(builder);
051        }
052    
053        public BeanValidationResults collectResults(Rules rules) {
054            Assert.notNull(rules, "rules is required");
055            setResultsBuilder(new BeanValidationResultsBuilder(bean));
056            new Block() {
057                protected void handle(Object beanPropertyConstraint) {
058                    collectPropertyResultsInternal((PropertyConstraint)beanPropertyConstraint);
059                }
060            }.forEach(rules.iterator());
061            return getBeanResultsBuilder();
062        }
063    
064        public PropertyResults collectPropertyResults(PropertyConstraint propertyRootExpression) {
065            Assert.notNull(propertyRootExpression, "propertyRootExpression is required");
066            setResultsBuilder(new BeanValidationResultsBuilder(this.bean));
067            return collectPropertyResultsInternal(propertyRootExpression);
068        }
069    
070        private PropertyResults collectPropertyResultsInternal(PropertyConstraint rootExpression) {
071            getBeanResultsBuilder().setCurrentBeanPropertyExpression(rootExpression);
072            setArgument(getBeanResultsBuilder().getCurrentPropertyValue());
073            boolean result = ((Boolean)visitorSupport.invokeVisit(this, rootExpression)).booleanValue();
074            if (logger.isDebugEnabled()) {
075                logger.debug("Final validation result: " + result);
076            }
077            if (!result)
078                return getBeanResultsBuilder().getResults(rootExpression.getPropertyName());
079    
080            return null;
081        }
082    
083        Boolean visit(CompoundPropertyConstraint rule) {
084            if (logger.isDebugEnabled()) {
085                logger.debug("Validating compound bean property expression [" + rule + "]...");
086            }
087            return (Boolean)visitorSupport.invokeVisit(this, rule.getPredicate());
088        }
089    
090        boolean visit(PropertyConstraint constraint) {
091            if (logger.isDebugEnabled()) {
092                logger.debug("Validating bean properties expression [" + constraint + "]...");
093            }
094            return testBeanPropertyExpression(constraint);
095        }
096    
097        private boolean testBeanPropertyExpression(PropertyConstraint constraint) {
098            boolean result = constraint.test(bean);
099            result = applyAnyNegation(result);
100            if (!result) {
101                getBeanResultsBuilder().push(constraint);
102            }
103            if (logger.isDebugEnabled()) {
104                logger.debug("Constraint [" + constraint + "] " + (result ? "passed" : "failed"));
105            }
106            return result;
107        }
108    
109        Boolean visit(PropertyValueConstraint valueConstraint) {
110            if (logger.isDebugEnabled()) {
111                logger.debug("Validating property value constraint [" + valueConstraint + "]...");
112            }
113            return (Boolean)visitorSupport.invokeVisit(this, valueConstraint.getConstraint());
114        }
115    
116        boolean visit(Constraint constraint) {
117            return super.visit(constraint);
118        }
119    }