001    /*--------------------------------------------------------------------------+
002    $Id: ConstraintValidator.java 26283 2010-02-18 11:18:57Z juergens $
003    |                                                                          |
004    | Copyright 2005-2010 Technische Universitaet Muenchen                     |
005    |                                                                          |
006    | Licensed under the Apache License, Version 2.0 (the "License");          |
007    | you may not use this file except in compliance with the License.         |
008    | You may obtain a copy of the License at                                  |
009    |                                                                          |
010    |    http://www.apache.org/licenses/LICENSE-2.0                            |
011    |                                                                          |
012    | Unless required by applicable law or agreed to in writing, software      |
013    | distributed under the License is distributed on an "AS IS" BASIS,        |
014    | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
015    | See the License for the specific language governing permissions and      |
016    | limitations under the License.                                           |
017    +--------------------------------------------------------------------------*/
018    package edu.tum.cs.commons.constraint;
019    
020    import edu.tum.cs.commons.collections.PairList;
021    import edu.tum.cs.commons.error.IExceptionHandler;
022    import edu.tum.cs.commons.error.RethrowingExceptionHandler;
023    import edu.tum.cs.commons.visitor.IMeshWalker;
024    import edu.tum.cs.commons.visitor.ITreeWalker;
025    import edu.tum.cs.commons.visitor.IVisitor;
026    import edu.tum.cs.commons.visitor.VisitorUtils;
027    
028    /**
029     * A class for storing constraints in the context of classes for which the
030     * constraint applies. Additionally it provides methods for checking all
031     * matching constraints for a given class.
032     * 
033     * @author hummelb
034     * @author $Author: juergens $
035     * @version $Rev: 26283 $
036     * @levd.rating GREEN Hash: 161B52F22D19EF2632D009F5148C7727
037     */
038    public class ConstraintValidator {
039    
040            /** Storage for constraints in conjunction with the class they apply to. */
041            private final PairList<Class<?>, ILocalConstraint<?>> localConstraints = new PairList<Class<?>, ILocalConstraint<?>>();
042    
043            /** Adds a constraint for a class. */
044            public <T> void addConstraint(Class<? extends T> clazz,
045                            ILocalConstraint<T> constraint) {
046                    localConstraints.add(clazz, constraint);
047            }
048    
049            /**
050             * Checks all constraints to the given object which are applicable to it.
051             * 
052             * @throws ConstraintViolationException
053             *             if any constraint is violated
054             */
055            public void checkConstaints(Object o) throws ConstraintViolationException {
056                    checkConstaints(o, RethrowingExceptionHandler
057                                    .<ConstraintViolationException> getInstance());
058            }
059    
060            /**
061             * Checks all constraints to the given object which are applicable to it. If
062             * a constraint is violated, the thrown exception is handled by the given
063             * provider.
064             */
065            @SuppressWarnings("unchecked")
066            public <X extends Exception> void checkConstaints(Object o,
067                            IExceptionHandler<ConstraintViolationException, X> handler)
068                            throws X {
069                    Class<?> clazz = o.getClass();
070                    for (int i = 0; i < localConstraints.size(); ++i) {
071                            if (localConstraints.getFirst(i).isAssignableFrom(clazz)) {
072                                    ILocalConstraint<?> constraint = localConstraints.getSecond(i);
073                                    try {
074                                            ((ILocalConstraint) constraint).checkLocalConstraint(o);
075                                    } catch (ConstraintViolationException e) {
076                                            handler.handleException(e);
077                                    }
078                            }
079                    }
080            }
081    
082            /**
083             * Validates all nodes of a tree. The first violation found is propagated to
084             * the top using a {@link ConstraintViolationException}.
085             * 
086             * @param root
087             *            the root of the tree.
088             * @param walker
089             *            the walker used to navigate the tree.
090             * @throws ConstraintViolationException
091             *             if a constraint violation was found.
092             * @throws X_WALKER
093             *             if the walker throws an exception.
094             */
095            public <T, X_WALKER extends Exception> void validateTree(T root,
096                            ITreeWalker<T, X_WALKER> walker)
097                            throws ConstraintViolationException, X_WALKER {
098    
099                    validateTree(root, walker, RethrowingExceptionHandler
100                                    .<ConstraintViolationException> getInstance());
101            }
102    
103            /**
104             * Validates all nodes of a tree.
105             * 
106             * @param root
107             *            the root of the tree.
108             * @param walker
109             *            the walker used to navigate the tree.
110             * @param handler
111             *            the exception handler used for dealing with constraint
112             *            violations.
113             * @throws X
114             *             if the constraint violation handler throws it.
115             * @throws X_WALKER
116             *             if the walker throws an exception.
117             */
118            public <T, X extends Exception, X_WALKER extends Exception> void validateTree(
119                            T root, ITreeWalker<T, X_WALKER> walker,
120                            IExceptionHandler<ConstraintViolationException, X> handler)
121                            throws X, X_WALKER {
122    
123                    VisitorUtils.visitAllPreOrder(root, walker, new CheckVisitor<T, X>(
124                                    handler));
125            }
126    
127            /**
128             * Validates all reachable elements of a mesh. The first violation found is
129             * propagated to the top using a {@link ConstraintViolationException}.
130             * 
131             * @param start
132             *            the start element of the mesh.
133             * @param walker
134             *            the walker used to navigate the mesh.
135             * @throws ConstraintViolationException
136             *             if a constraint violation was found.
137             * @throws X_WALKER
138             *             if the walker throws an exception.
139             */
140            public <T, X_WALKER extends Exception> void validateMesh(T start,
141                            IMeshWalker<T, X_WALKER> walker)
142                            throws ConstraintViolationException, X_WALKER {
143    
144                    validateMesh(start, walker, RethrowingExceptionHandler
145                                    .<ConstraintViolationException> getInstance());
146            }
147    
148            /**
149             * Validates all reachable elements of a mesh.
150             * 
151             * @param start
152             *            the start element of the mesh.
153             * @param walker
154             *            the walker used to navigate the mesh.
155             * @param handler
156             *            the exception handler used for dealing with constraint
157             *            violations.
158             * @throws X
159             *             if the constraint violation handler throws it.
160             * @throws X_WALKER
161             *             if the walker throws an exception.
162             */
163            public <T, X extends Exception, X_WALKER extends Exception> void validateMesh(
164                            T start, IMeshWalker<T, X_WALKER> walker,
165                            IExceptionHandler<ConstraintViolationException, X> handler)
166                            throws X, X_WALKER {
167    
168                    VisitorUtils.visitAllDepthFirst(start, walker, new CheckVisitor<T, X>(
169                                    handler));
170            }
171    
172            /**
173             * A simple visitor checking each element with the
174             * {@link ConstraintValidator#checkConstaints(Object, IExceptionHandler)}
175             * method.
176             */
177            private class CheckVisitor<T, X extends Exception> implements
178                            IVisitor<T, X> {
179    
180                    /** The handler used. */
181                    private final IExceptionHandler<ConstraintViolationException, X> handler;
182    
183                    /** Constructor. */
184                    public CheckVisitor(
185                                    IExceptionHandler<ConstraintViolationException, X> handler) {
186                            this.handler = handler;
187                    }
188    
189                    /** {@inheritDoc} */
190                    public void visit(T element) throws X {
191                            checkConstaints(element, handler);
192                    }
193    
194            }
195    }