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