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.lang.reflect.Array;
038import java.util.Set;
039
040import javax.validation.ConstraintViolation;
041
042import org.granite.client.util.WeakIdentityHashMap;
043import org.granite.client.validation.NotifyingValidator.ConstraintViolationsHandler;
044
045/**
046 * @author William DRAI
047 */
048public class ValidationNotifier {
049    
050    private final WeakIdentityHashMap<Object, ConstraintViolationsHandler<?>[]> handlersMap = new WeakIdentityHashMap<Object, ConstraintViolationsHandler<?>[]>();
051    
052    
053    public <T> void notifyConstraintViolations(T entity, Set<ConstraintViolation<T>> constraintViolations) {
054        @SuppressWarnings("unchecked")
055        ConstraintViolationsHandler<T>[] handlers = (ConstraintViolationsHandler<T>[])handlersMap.get(entity);
056        if (handlers == null)
057            return;
058        
059        for (ConstraintViolationsHandler<T> handler : handlers)
060            handler.handle(entity, constraintViolations);
061    }
062
063    @SuppressWarnings("unchecked")
064    public <T> void addConstraintViolationsHandler(T entity, ConstraintViolationsHandler<T> handler) {
065        ConstraintViolationsHandler<T>[] handlers = (ConstraintViolationsHandler<T>[])handlersMap.get(entity);
066        if (handlers == null) {
067            handlers = (ConstraintViolationsHandler<T>[])Array.newInstance(ConstraintViolationsHandler.class, 1);
068            handlers[0] = handler;
069        }
070        else {
071            ConstraintViolationsHandler<T>[] newHandlers = (ConstraintViolationsHandler<T>[])Array.newInstance(ConstraintViolationsHandler.class, handlers.length+1);
072            System.arraycopy(handlers, 0, newHandlers, 0, handlers.length);
073            newHandlers[handlers.length] = handler;
074            handlers = newHandlers;
075        }
076        handlersMap.put(entity, handlers);
077    }
078
079    public <T> void removeConstraintViolationsHandler(T entity, ConstraintViolationsHandler<T> handler) {
080        @SuppressWarnings("unchecked")
081        ConstraintViolationsHandler<T>[] handlers = (ConstraintViolationsHandler<T>[])handlersMap.get(entity);
082        if (handlers == null)
083            return;
084        if (handlers.length == 1 && handlers[0] == handler) {
085            handlersMap.remove(entity);
086            return;
087        }
088        int index = -1;
089        for (int i = 0; i < handlers.length; i++) {
090            if (handlers[i] == handler) {
091                index = i;
092                break;
093            }
094        }
095        if (index < 0)
096            return; // Handler not found
097        
098        @SuppressWarnings({"rawtypes", "unchecked"})
099        ConstraintViolationsHandler[] newHandlers = (ConstraintViolationsHandler<T>[])Array.newInstance(ConstraintViolationsHandler.class, handlers.length-1);
100        if (index > 0)
101            System.arraycopy(handlers, 0, newHandlers, 0, index);
102        if (index < handlers.length-1)
103            System.arraycopy(handlers, index+1, newHandlers, index, handlers.length-index-1);
104        handlersMap.put(entity, newHandlers);
105    }
106
107
108}