001/**
002 *   GRANITE DATA SERVICES
003 *   Copyright (C) 2006-2013 GRANITE DATA SERVICES S.A.S.
004 *
005 *   This file is part of the Granite Data Services Platform.
006 *
007 *                               ***
008 *
009 *   Community License: GPL 3.0
010 *
011 *   This file is free software: you can redistribute it and/or modify
012 *   it under the terms of the GNU General Public License as published
013 *   by the Free Software Foundation, either version 3 of the License,
014 *   or (at your option) any later version.
015 *
016 *   This file is distributed in the hope that it will be useful, but
017 *   WITHOUT ANY WARRANTY; without even the implied warranty of
018 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
019 *   GNU General Public License for more details.
020 *
021 *   You should have received a copy of the GNU General Public License
022 *   along with this program. If not, see <http://www.gnu.org/licenses/>.
023 *
024 *                               ***
025 *
026 *   Available Commercial License: GraniteDS SLA 1.0
027 *
028 *   This is the appropriate option if you are creating proprietary
029 *   applications and you are not prepared to distribute and share the
030 *   source code of your application under the GPL v3 license.
031 *
032 *   Please visit http://www.granitedataservices.com/license for more
033 *   details.
034 */
035package org.granite.client.validation;
036
037import java.util.HashMap;
038import java.util.HashSet;
039import java.util.Map;
040import java.util.Set;
041
042import javax.validation.ConstraintViolation;
043import javax.validation.Validator;
044import javax.validation.metadata.BeanDescriptor;
045
046/**
047 * @author William DRAI
048 */
049public class DefaultNotifyingValidator implements NotifyingValidator {
050    
051    private final Validator validator;
052    private final ValidationNotifier validationNotifier;
053    
054    public DefaultNotifyingValidator(Validator validator, ValidationNotifier validationNotifier) {
055        this.validator = validator;
056        this.validationNotifier = validationNotifier;
057    }
058    
059    @Override
060    public <T> Set<ConstraintViolation<T>> validate(T object, Class<?>... groups) {
061        Set<ConstraintViolation<T>> constraintViolations = validator.validate(object, groups);
062        
063        Set<ConstraintViolation<?>> genericsAreAPainInTheAss = new HashSet<ConstraintViolation<?>>(constraintViolations.size());
064        genericsAreAPainInTheAss.addAll(constraintViolations);
065        
066        notifyConstraintViolations(object, genericsAreAPainInTheAss);
067        
068        return constraintViolations;
069    }
070    
071    @SuppressWarnings("unchecked")
072    public <T> void notifyConstraintViolations(T root, Set<ConstraintViolation<?>> constraintViolations) {
073        Map<Object, Set<ConstraintViolation<Object>>> violationsMap = new HashMap<Object, Set<ConstraintViolation<Object>>>();
074        
075        for (ConstraintViolation<?> violation : constraintViolations) {
076            Object rootBean = violation.getRootBean();
077            Object leafBean = violation.getLeafBean();
078            Object bean = leafBean != null ? leafBean : rootBean;
079            
080            Set<ConstraintViolation<Object>> violations = violationsMap.get(bean);
081            if (violations == null) {
082                violations = new HashSet<ConstraintViolation<Object>>();
083                violationsMap.put(bean, violations);
084            }           
085            violations.add((ConstraintViolation<Object>)violation);
086        }
087        
088        for (Object bean : violationsMap.keySet()) {
089            if (bean != root)
090                validationNotifier.notifyConstraintViolations(bean, violationsMap.get(bean));
091        }
092        
093        validationNotifier.notifyConstraintViolations(root, violationsMap.get(root));
094    }
095    
096    @Override
097    public <T> Set<ConstraintViolation<T>> validateProperty(T object, String propertyName, Class<?>... groups) {
098        return validator.validateProperty(object, propertyName, groups);
099    }
100    
101    @Override
102    public <T> Set<ConstraintViolation<T>> validateValue(Class<T> beanType, String propertyName, Object value, Class<?>... groups) {
103        return validator.validateValue(beanType, propertyName, value, groups);
104    }
105
106    @Override
107    public BeanDescriptor getConstraintsForClass(Class<?> entityClass) {
108        return validator.getConstraintsForClass(entityClass);
109    }
110
111    @Override
112    public <T> T unwrap(Class<T> entityClass) {
113        return validator.unwrap(entityClass);
114    }
115    
116    
117    @Override
118    public <T> void addConstraintViolationsHandler(T entity, ConstraintViolationsHandler<T> handler) {
119        validationNotifier.addConstraintViolationsHandler(entity, handler);
120    }
121
122    @Override
123    public <T> void removeConstraintViolationsHandler(T entity, ConstraintViolationsHandler<T> handler) {
124        validationNotifier.removeConstraintViolationsHandler(entity, handler);
125    }
126
127
128}