Source Code Cross Referenced for Validator.java in  » Development » OVal » net » sf » oval » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Development » OVal » net.sf.oval 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*******************************************************************************
0002:         * Portions created by Sebastian Thomschke are copyright (c) 2005-2007 Sebastian
0003:         * Thomschke.
0004:         * 
0005:         * All Rights Reserved. This program and the accompanying materials
0006:         * are made available under the terms of the Eclipse Public License v1.0
0007:         * which accompanies this distribution, and is available at
0008:         * http://www.eclipse.org/legal/epl-v10.html
0009:         * 
0010:         * Contributors:
0011:         *     Sebastian Thomschke - initial implementation.
0012:         *******************************************************************************/package net.sf.oval;
0013:
0014:        import java.lang.reflect.Constructor;
0015:        import java.lang.reflect.Field;
0016:        import java.lang.reflect.Method;
0017:        import java.util.Collection;
0018:        import java.util.List;
0019:        import java.util.Map;
0020:        import java.util.Set;
0021:        import java.util.WeakHashMap;
0022:
0023:        import net.sf.oval.collection.CollectionFactory;
0024:        import net.sf.oval.configuration.Configurer;
0025:        import net.sf.oval.configuration.annotation.AnnotationsConfigurer;
0026:        import net.sf.oval.configuration.pojo.elements.ClassConfiguration;
0027:        import net.sf.oval.configuration.pojo.elements.ConstraintSetConfiguration;
0028:        import net.sf.oval.configuration.pojo.elements.ConstructorConfiguration;
0029:        import net.sf.oval.configuration.pojo.elements.FieldConfiguration;
0030:        import net.sf.oval.configuration.pojo.elements.MethodConfiguration;
0031:        import net.sf.oval.configuration.pojo.elements.ObjectConfiguration;
0032:        import net.sf.oval.configuration.pojo.elements.ParameterConfiguration;
0033:        import net.sf.oval.constraint.AssertConstraintSetCheck;
0034:        import net.sf.oval.constraint.AssertFieldConstraintsCheck;
0035:        import net.sf.oval.constraint.AssertValidCheck;
0036:        import net.sf.oval.context.ClassContext;
0037:        import net.sf.oval.context.ConstructorParameterContext;
0038:        import net.sf.oval.context.FieldContext;
0039:        import net.sf.oval.context.MethodParameterContext;
0040:        import net.sf.oval.context.MethodReturnValueContext;
0041:        import net.sf.oval.context.OValContext;
0042:        import net.sf.oval.exception.ConstraintSetAlreadyDefinedException;
0043:        import net.sf.oval.exception.ConstraintsViolatedException;
0044:        import net.sf.oval.exception.ExceptionTranslator;
0045:        import net.sf.oval.exception.ExpressionLanguageNotAvailableException;
0046:        import net.sf.oval.exception.FieldNotFoundException;
0047:        import net.sf.oval.exception.InvalidConfigurationException;
0048:        import net.sf.oval.exception.MethodNotFoundException;
0049:        import net.sf.oval.exception.OValException;
0050:        import net.sf.oval.exception.UndefinedConstraintSetException;
0051:        import net.sf.oval.exception.ValidationFailedException;
0052:        import net.sf.oval.expression.ExpressionLanguage;
0053:        import net.sf.oval.expression.ExpressionLanguageBeanShellImpl;
0054:        import net.sf.oval.expression.ExpressionLanguageGroovyImpl;
0055:        import net.sf.oval.expression.ExpressionLanguageJRubyImpl;
0056:        import net.sf.oval.expression.ExpressionLanguageJavaScriptImpl;
0057:        import net.sf.oval.expression.ExpressionLanguageMVELImpl;
0058:        import net.sf.oval.expression.ExpressionLanguageOGNLImpl;
0059:        import net.sf.oval.guard.ParameterNameResolver;
0060:        import net.sf.oval.guard.ParameterNameResolverEnumerationImpl;
0061:        import net.sf.oval.internal.ClassChecks;
0062:        import net.sf.oval.internal.CollectionFactoryHolder;
0063:        import net.sf.oval.internal.Log;
0064:        import net.sf.oval.internal.MessageRenderer;
0065:        import net.sf.oval.internal.MessageResolverHolder;
0066:        import net.sf.oval.internal.util.ListOrderedSet;
0067:        import net.sf.oval.internal.util.ReflectionUtils;
0068:        import net.sf.oval.internal.util.StringUtils;
0069:        import net.sf.oval.internal.util.ThreadLocalList;
0070:        import net.sf.oval.localization.MessageResolver;
0071:        import net.sf.oval.logging.LoggerFactory;
0072:
0073:        /**
0074:         * @author Sebastian Thomschke
0075:         */
0076:        public class Validator {
0077:            private final static Log LOG = Log.getLog(Validator.class);
0078:
0079:            /**
0080:             * Returns a shared instance of the CollectionFactory
0081:             */
0082:            public static CollectionFactory getCollectionFactory() {
0083:                return CollectionFactoryHolder.getFactory();
0084:            }
0085:
0086:            /**
0087:             * @return the loggerFactory
0088:             */
0089:            public static LoggerFactory getLoggerFactory() {
0090:                return Log.getLoggerFactory();
0091:            }
0092:
0093:            /**
0094:             * @return the messageResolver
0095:             */
0096:            public static MessageResolver getMessageResolver() {
0097:                return MessageResolverHolder.getMessageResolver();
0098:            }
0099:
0100:            /**
0101:             * 
0102:             * @param factory the new collection factory to be used by all validator instances
0103:             */
0104:            public static void setCollectionFactory(
0105:                    final CollectionFactory factory)
0106:                    throws IllegalArgumentException {
0107:                CollectionFactoryHolder.setFactory(factory);
0108:            }
0109:
0110:            /**
0111:             * @param loggerFactory the loggerFactory to set
0112:             */
0113:            public static void setLoggerFactory(
0114:                    final LoggerFactory loggerFactory) {
0115:                Log.setLoggerFactory(loggerFactory);
0116:            }
0117:
0118:            /**
0119:             * @param messageResolver the messageResolver to set
0120:             * @throws IllegalArgumentException if <code>messageResolver == null</code>
0121:             */
0122:            public static void setMessageResolver(
0123:                    final MessageResolver messageResolver)
0124:                    throws IllegalArgumentException {
0125:                MessageResolverHolder.setMessageResolver(messageResolver);
0126:            }
0127:
0128:            private final Map<Class, ClassChecks> checksByClass = new WeakHashMap<Class, ClassChecks>();
0129:
0130:            private final ListOrderedSet<Configurer> configurers = new ListOrderedSet<Configurer>(
0131:                    4);
0132:
0133:            private final Map<String, ConstraintSet> constraintSetsById = CollectionFactoryHolder
0134:                    .getFactory().createMap(4);
0135:
0136:            private final ThreadLocalList<Object> currentlyValidatedObjects = new ThreadLocalList<Object>();
0137:
0138:            protected Map<String, ExpressionLanguage> expressionLanguages = CollectionFactoryHolder
0139:                    .getFactory().createMap(4);
0140:
0141:            /**
0142:             * Flag that indicates any configuration method related to profiles was called.
0143:             * Used for performance improvements.
0144:             */
0145:            private boolean isProfilesFeatureUsed = false;
0146:
0147:            private boolean isAllProfilesEnabledByDefault = true;
0148:
0149:            private final Set<String> disabledProfiles = CollectionFactoryHolder
0150:                    .getFactory().createSet();
0151:
0152:            private final Set<String> enabledProfiles = CollectionFactoryHolder
0153:                    .getFactory().createSet();
0154:
0155:            private ExceptionTranslator exceptionTranslator;
0156:
0157:            protected ParameterNameResolver parameterNameResolver = new ParameterNameResolverEnumerationImpl();
0158:
0159:            /**
0160:             * Constructs a new validator object and uses a new isntance of
0161:             * AnnotationsConfigurer
0162:             */
0163:            public Validator() {
0164:                initializeDefaultELs();
0165:
0166:                configurers.add(new AnnotationsConfigurer());
0167:            }
0168:
0169:            public Validator(final Collection<Configurer> configurers) {
0170:                initializeDefaultELs();
0171:
0172:                if (configurers != null) {
0173:                    this .configurers.addAll(configurers);
0174:                }
0175:            }
0176:
0177:            public Validator(final Configurer... configurers) {
0178:                initializeDefaultELs();
0179:
0180:                if (configurers != null) {
0181:                    for (final Configurer configurer : configurers)
0182:                        this .configurers.add(configurer);
0183:                }
0184:            }
0185:
0186:            /**
0187:             * Registers object-level constraint checks
0188:             *  
0189:             * @param clazz
0190:             * @param checks
0191:             * @throws IllegalArgumentException if <code>clazz == null</code> or <code>checks == null</code> or checks is empty 
0192:             */
0193:            public void addChecks(final Class clazz, final Check... checks)
0194:                    throws IllegalArgumentException {
0195:                if (clazz == null)
0196:                    throw new IllegalArgumentException("clazz cannot be null");
0197:                if (checks == null)
0198:                    throw new IllegalArgumentException("checks cannot be null");
0199:                if (checks.length == 0)
0200:                    throw new IllegalArgumentException("checks cannot empty");
0201:
0202:                final ClassChecks cc = getClassChecks(clazz);
0203:
0204:                cc.addObjectChecks(checks);
0205:            }
0206:
0207:            @SuppressWarnings("unchecked")
0208:            protected void addChecks(final ClassChecks cc,
0209:                    final ClassConfiguration classConfig) throws OValException {
0210:                if (Boolean.TRUE.equals(classConfig.overwrite)) {
0211:                    cc.clear();
0212:                }
0213:
0214:                if (classConfig.checkInvariants != null)
0215:                    cc.isCheckInvariants = classConfig.checkInvariants;
0216:
0217:                try {
0218:                    /*
0219:                     * apply object level checks
0220:                     */
0221:                    if (classConfig.objectConfiguration != null) {
0222:                        final ObjectConfiguration objectConfig = classConfig.objectConfiguration;
0223:                        if (Boolean.TRUE.equals(objectConfig.overwrite)) {
0224:                            cc.clearObjectChecks();
0225:                        }
0226:
0227:                        cc.addObjectChecks(objectConfig.checks);
0228:                    }
0229:
0230:                    /*
0231:                     * apply field checks
0232:                     */
0233:                    if (classConfig.fieldConfigurations != null)
0234:                        for (final FieldConfiguration fieldConfig : classConfig.fieldConfigurations) {
0235:                            final Field field = classConfig.type
0236:                                    .getDeclaredField(fieldConfig.name);
0237:
0238:                            if (Boolean.TRUE.equals(fieldConfig.overwrite)) {
0239:                                cc.clearFieldChecks(field);
0240:                            }
0241:
0242:                            if (fieldConfig.checks != null
0243:                                    && fieldConfig.checks.size() > 0) {
0244:                                cc.addFieldChecks(field, fieldConfig.checks);
0245:                            }
0246:                        }
0247:
0248:                    /*
0249:                     * apply constructor parameter checks
0250:                     */
0251:                    if (classConfig.constructorConfigurations != null)
0252:                        for (final ConstructorConfiguration constructorConfig : classConfig.constructorConfigurations) {
0253:                            if (constructorConfig.parameterConfigurations != null) {
0254:                                final Class<?>[] parameterTypes = new Class[constructorConfig.parameterConfigurations
0255:                                        .size()];
0256:
0257:                                for (int i = 0, l = constructorConfig.parameterConfigurations
0258:                                        .size(); i < l; i++) {
0259:                                    parameterTypes[i] = constructorConfig.parameterConfigurations
0260:                                            .get(i).type;
0261:                                }
0262:
0263:                                final Constructor constructor = classConfig.type
0264:                                        .getDeclaredConstructor(parameterTypes);
0265:
0266:                                final String[] parameterNames = parameterNameResolver
0267:                                        .getParameterNames(constructor);
0268:
0269:                                if (Boolean.TRUE
0270:                                        .equals(constructorConfig.overwrite)) {
0271:                                    cc.clearConstructorChecks(constructor);
0272:                                }
0273:
0274:                                if (constructorConfig.postCheckInvariants != null
0275:                                        && constructorConfig.postCheckInvariants)
0276:                                    cc.methodsWithCheckInvariantsPost
0277:                                            .add(constructor);
0278:
0279:                                for (int i = 0, l = constructorConfig.parameterConfigurations
0280:                                        .size(); i < l; i++) {
0281:                                    final ParameterConfiguration parameterConfig = constructorConfig.parameterConfigurations
0282:                                            .get(i);
0283:
0284:                                    if (Boolean.TRUE
0285:                                            .equals(parameterConfig.overwrite)) {
0286:                                        cc.clearConstructorParameterChecks(
0287:                                                constructor, i);
0288:                                    }
0289:
0290:                                    final List<Check> checks = parameterConfig.checks;
0291:
0292:                                    if (checks != null && checks.size() > 0) {
0293:                                        cc.addConstructorParameterChecks(
0294:                                                constructor, i, checks);
0295:                                    }
0296:
0297:                                    /* *******************
0298:                                     * applying field constraints to the single parameter of setter methods 
0299:                                     * *******************/
0300:                                    if (classConfig.applyFieldConstraintsToConstructors != null
0301:                                            && classConfig.applyFieldConstraintsToConstructors
0302:                                                    .booleanValue()) {
0303:                                        final Field field = ReflectionUtils
0304:                                                .getField(cc.clazz,
0305:                                                        parameterNames[i]);
0306:
0307:                                        // check if a corresponding field has been found
0308:                                        if (field != null
0309:                                                && parameterTypes[i]
0310:                                                        .isAssignableFrom(field
0311:                                                                .getType())) {
0312:                                            final AssertFieldConstraintsCheck check = new AssertFieldConstraintsCheck();
0313:                                            check.setFieldName(field.getName());
0314:                                            cc.addConstructorParameterChecks(
0315:                                                    constructor, i, check);
0316:                                        }
0317:                                    }
0318:                                }
0319:                            }
0320:                        }
0321:
0322:                    /*
0323:                     * apply method parameter and return value checks and pre/post conditions
0324:                     */
0325:                    if (classConfig.methodConfigurations != null)
0326:                        for (final MethodConfiguration methodConfig : classConfig.methodConfigurations) {
0327:                            /*
0328:                             * determine the method
0329:                             */
0330:                            Method method = null;
0331:
0332:                            if (methodConfig.parameterConfigurations == null
0333:                                    || methodConfig.parameterConfigurations
0334:                                            .size() == 0) {
0335:                                method = classConfig.type
0336:                                        .getDeclaredMethod(methodConfig.name);
0337:                            } else {
0338:                                final Class<?>[] parameterTypes = new Class[methodConfig.parameterConfigurations
0339:                                        .size()];
0340:
0341:                                for (int i = 0, l = methodConfig.parameterConfigurations
0342:                                        .size(); i < l; i++) {
0343:                                    parameterTypes[i] = methodConfig.parameterConfigurations
0344:                                            .get(i).type;
0345:                                }
0346:
0347:                                method = classConfig.type.getDeclaredMethod(
0348:                                        methodConfig.name, parameterTypes);
0349:                            }
0350:
0351:                            if (Boolean.TRUE.equals(methodConfig.overwrite)) {
0352:                                cc.clearMethodChecks(method);
0353:                            }
0354:
0355:                            /* *******************
0356:                             * applying field constraints to the single parameter of setter methods 
0357:                             * *******************/
0358:                            if (classConfig.applyFieldConstraintsToSetters != null
0359:                                    && classConfig.applyFieldConstraintsToSetters
0360:                                            .booleanValue()) {
0361:                                final Field field = ReflectionUtils
0362:                                        .getFieldForSetter(method);
0363:
0364:                                // check if a corresponding field has been found
0365:                                if (field != null) {
0366:                                    final AssertFieldConstraintsCheck check = new AssertFieldConstraintsCheck();
0367:                                    check.setFieldName(field.getName());
0368:                                    cc.addMethodParameterChecks(method, 0,
0369:                                            check);
0370:                                }
0371:                            }
0372:
0373:                            /*
0374:                             * configure parameter constraints
0375:                             */
0376:                            if (methodConfig.parameterConfigurations != null
0377:                                    && methodConfig.parameterConfigurations
0378:                                            .size() > 0) {
0379:                                for (int i = 0, l = methodConfig.parameterConfigurations
0380:                                        .size(); i < l; i++) {
0381:                                    final ParameterConfiguration parameterConfig = methodConfig.parameterConfigurations
0382:                                            .get(i);
0383:
0384:                                    if (Boolean.TRUE
0385:                                            .equals(parameterConfig.overwrite)) {
0386:                                        cc
0387:                                                .clearMethodParameterChecks(
0388:                                                        method, i);
0389:                                    }
0390:
0391:                                    final List<Check> checks = parameterConfig.checks;
0392:
0393:                                    if (checks != null && checks.size() > 0) {
0394:                                        cc.addMethodParameterChecks(method, i,
0395:                                                checks);
0396:                                    }
0397:                                }
0398:                            }
0399:
0400:                            /*
0401:                             * configure return value constraints
0402:                             */
0403:                            if (methodConfig.returnValueConfiguration != null) {
0404:                                if (Boolean.TRUE
0405:                                        .equals(methodConfig.returnValueConfiguration.overwrite)) {
0406:                                    cc.clearMethodReturnValueChecks(method);
0407:                                }
0408:
0409:                                if (methodConfig.returnValueConfiguration.checks != null
0410:                                        && methodConfig.returnValueConfiguration.checks
0411:                                                .size() > 0) {
0412:                                    cc
0413:                                            .addMethodReturnValueChecks(
0414:                                                    method,
0415:                                                    methodConfig.isInvariant,
0416:                                                    methodConfig.returnValueConfiguration.checks);
0417:                                }
0418:                            }
0419:
0420:                            if (methodConfig.preCheckInvariants != null
0421:                                    && methodConfig.preCheckInvariants) {
0422:                                cc.methodsWithCheckInvariantsPre.add(method);
0423:                            }
0424:
0425:                            /*
0426:                             * configure pre conditions
0427:                             */
0428:                            if (methodConfig.preExecutionConfiguration != null) {
0429:                                if (Boolean.TRUE
0430:                                        .equals(methodConfig.preExecutionConfiguration.overwrite)) {
0431:                                    cc.clearMethodPreChecks(method);
0432:                                }
0433:
0434:                                if (methodConfig.preExecutionConfiguration.checks != null
0435:                                        && methodConfig.preExecutionConfiguration.checks
0436:                                                .size() > 0) {
0437:                                    cc
0438:                                            .addMethodPreChecks(
0439:                                                    method,
0440:                                                    methodConfig.preExecutionConfiguration.checks);
0441:                                }
0442:                            }
0443:
0444:                            if (methodConfig.postCheckInvariants != null
0445:                                    && methodConfig.postCheckInvariants) {
0446:                                cc.methodsWithCheckInvariantsPost.add(method);
0447:                            }
0448:
0449:                            /*
0450:                             * configure post conditions
0451:                             */
0452:                            if (methodConfig.postExecutionConfiguration != null) {
0453:                                if (Boolean.TRUE
0454:                                        .equals(methodConfig.postExecutionConfiguration.overwrite)) {
0455:                                    cc.clearMethodPostChecks(method);
0456:                                }
0457:
0458:                                if (methodConfig.postExecutionConfiguration.checks != null
0459:                                        && methodConfig.postExecutionConfiguration.checks
0460:                                                .size() > 0) {
0461:                                    cc
0462:                                            .addMethodPostChecks(
0463:                                                    method,
0464:                                                    methodConfig.postExecutionConfiguration.checks);
0465:                                }
0466:                            }
0467:                        }
0468:                } catch (final NoSuchMethodException ex) {
0469:                    throw new MethodNotFoundException(ex);
0470:                } catch (final NoSuchFieldException ex) {
0471:                    throw new FieldNotFoundException(ex);
0472:                }
0473:            }
0474:
0475:            /**
0476:             * Registers constraint checks for the given field 
0477:             *  
0478:             * @param field
0479:             * @param checks
0480:             * @throws IllegalArgumentException if <code>field == null</code> or <code>checks == null</code> or checks is empty 
0481:             */
0482:            public void addChecks(final Field field, final Check... checks)
0483:                    throws IllegalArgumentException {
0484:                if (field == null)
0485:                    throw new IllegalArgumentException("field cannot be null");
0486:                if (checks == null)
0487:                    throw new IllegalArgumentException("checks cannot be null");
0488:                if (checks.length == 0)
0489:                    throw new IllegalArgumentException("checks cannot empty");
0490:
0491:                final ClassChecks cc = getClassChecks(field.getDeclaringClass());
0492:
0493:                cc.addFieldChecks(field, checks);
0494:            }
0495:
0496:            /**
0497:             * Registers constraint checks for the given getter's return value
0498:             * 
0499:             * @param invariantMethod a non-void, non-parameterized method (usually a JavaBean Getter style method)
0500:             * @param checks
0501:             * @throws IllegalArgumentException if <code>getter == null</code> or <code>checks == null</code>
0502:             * @throws InvalidConfigurationException if getter is not a getter method
0503:             */
0504:            public void addChecks(final Method invariantMethod,
0505:                    final Check... checks) throws IllegalArgumentException,
0506:                    InvalidConfigurationException {
0507:                if (invariantMethod == null)
0508:                    throw new IllegalArgumentException(
0509:                            "inVariantMethod cannot be null");
0510:                if (checks == null)
0511:                    throw new IllegalArgumentException("checks cannot be null");
0512:                if (checks.length == 0)
0513:                    throw new IllegalArgumentException("checks cannot empty");
0514:
0515:                final ClassChecks cc = getClassChecks(invariantMethod
0516:                        .getDeclaringClass());
0517:                cc.addMethodReturnValueChecks(invariantMethod, Boolean.TRUE,
0518:                        checks);
0519:            }
0520:
0521:            /**
0522:             * Registers a new constraint set.
0523:             * 
0524:             * @param constraintSet cannot be null
0525:             * @param overwrite
0526:             * @throws ConstraintSetAlreadyDefinedException if <code>overwrite == false</code> and a constraint set with the given id exists already 
0527:             * @throws IllegalArgumentException if <code>constraintSet == null</code> or <code>constraintSet.id == null</code> or <code>constraintSet.id.length == 0</code>
0528:             * @throws IllegalArgumentException if <code>constraintSet.id == null</code>
0529:             */
0530:            public void addConstraintSet(final ConstraintSet constraintSet,
0531:                    boolean overwrite)
0532:                    throws ConstraintSetAlreadyDefinedException,
0533:                    IllegalArgumentException {
0534:                if (constraintSet == null)
0535:                    throw new IllegalArgumentException(
0536:                            "constraintSet cannot be null");
0537:
0538:                if (constraintSet.getId() == null)
0539:                    throw new IllegalArgumentException(
0540:                            "constraintSet.id cannot be null");
0541:
0542:                if (constraintSet.getId().length() == 0)
0543:                    throw new IllegalArgumentException(
0544:                            "constraintSet.id cannot be empty");
0545:
0546:                synchronized (constraintSetsById) {
0547:                    if (!overwrite
0548:                            && constraintSetsById.containsKey(constraintSet
0549:                                    .getId()))
0550:                        throw new ConstraintSetAlreadyDefinedException(
0551:                                constraintSet.getId());
0552:
0553:                    constraintSetsById
0554:                            .put(constraintSet.getId(), constraintSet);
0555:                }
0556:            }
0557:
0558:            /**
0559:             * 
0560:             * @param languageId
0561:             * @param expressionLanguage
0562:             * @throws IllegalArgumentException if <code>languageId == null || expressionLanguage == null</code>
0563:             */
0564:            public void addExpressionLanguage(final String languageId,
0565:                    final ExpressionLanguage expressionLanguage)
0566:                    throws IllegalArgumentException {
0567:                if (languageId == null)
0568:                    throw new IllegalArgumentException(
0569:                            "languageId cannot be null");
0570:                if (expressionLanguage == null)
0571:                    throw new IllegalArgumentException(
0572:                            "expressionLanguage cannot be null");
0573:
0574:                if (LOG.isInfo())
0575:                    LOG.info("Expression language '" + languageId
0576:                            + "' registered: " + expressionLanguage);
0577:
0578:                expressionLanguages.put(languageId, expressionLanguage);
0579:            }
0580:
0581:            /**
0582:             * validates the field and getter constrains of the given object
0583:             * and throws an ConstraintsViolatedException if any constraint
0584:             * violations are detected
0585:             * 
0586:             * @param validatedObject the object to validate, cannot be null
0587:             * @throws ConstraintsViolatedException
0588:             * @throws ValidationFailedException
0589:             * @throws IllegalArgumentException if <code>validatedObject == null</code>
0590:             */
0591:            public void assertValid(final Object validatedObject)
0592:                    throws IllegalArgumentException, ValidationFailedException,
0593:                    ConstraintsViolatedException {
0594:                final List<ConstraintViolation> violations = validate(validatedObject);
0595:
0596:                if (violations.size() > 0)
0597:                    throw translateException(new ConstraintsViolatedException(
0598:                            violations));
0599:            }
0600:
0601:            /**
0602:             * Validates the give value against the defined field constraints and throws 
0603:             * an ConstraintsViolatedException if any constraint violations are detected.<br>
0604:             * 
0605:             * @param validatedObject the object to validate, cannot be null
0606:             * @param validatedField the field to validate, cannot be null
0607:             * @throws IllegalArgumentException if <code>validatedObject == null</code> or <code>field == null</code>
0608:             * @throws ConstraintsViolatedException
0609:             * @throws ValidationFailedException 
0610:             */
0611:            public void assertValidFieldValue(final Object validatedObject,
0612:                    final Field validatedField,
0613:                    final Object fieldValueToValidate)
0614:                    throws IllegalArgumentException, ValidationFailedException,
0615:                    ConstraintsViolatedException {
0616:                final List<ConstraintViolation> violations = validateFieldValue(
0617:                        validatedObject, validatedField, fieldValueToValidate);
0618:
0619:                if (violations.size() > 0)
0620:                    throw translateException(new ConstraintsViolatedException(
0621:                            violations));
0622:            }
0623:
0624:            protected void checkConstraint(
0625:                    final List<ConstraintViolation> violations,
0626:                    final Check check, final Object validatedObject,
0627:                    final Object valueToValidate, final OValContext context)
0628:                    throws OValException {
0629:                if (!isAnyProfileEnabled(check.getProfiles()))
0630:                    return;
0631:
0632:                /*
0633:                 * special handling of the AssertValid constraint
0634:                 */
0635:                if (check instanceof  AssertValidCheck) {
0636:                    checkConstraintAssertValid(violations,
0637:                            (AssertValidCheck) check, validatedObject,
0638:                            valueToValidate, context);
0639:                    return;
0640:                }
0641:
0642:                /*
0643:                 * special handling of the FieldConstraints constraint
0644:                 */
0645:                if (check instanceof  AssertConstraintSetCheck) {
0646:                    checkConstraintAssertConstraintSet(violations,
0647:                            (AssertConstraintSetCheck) check, validatedObject,
0648:                            valueToValidate, context);
0649:                    return;
0650:                }
0651:
0652:                /*
0653:                 * special handling of the FieldConstraints constraint
0654:                 */
0655:                if (check instanceof  AssertFieldConstraintsCheck) {
0656:                    checkConstraintAssertFieldConstraints(violations,
0657:                            (AssertFieldConstraintsCheck) check,
0658:                            validatedObject, valueToValidate, context);
0659:                    return;
0660:                }
0661:
0662:                /*
0663:                 * standard constraints handling
0664:                 */
0665:                if (!check.isSatisfied(validatedObject, valueToValidate,
0666:                        context, this )) {
0667:                    final String errorMessage = renderMessage(context,
0668:                            valueToValidate, check.getMessage(), check
0669:                                    .getMessageVariables());
0670:                    violations.add(new ConstraintViolation(
0671:                            check.getErrorCode(), errorMessage, check
0672:                                    .getSeverity(), validatedObject,
0673:                            valueToValidate, context));
0674:                }
0675:            }
0676:
0677:            protected void checkConstraintAssertConstraintSet(
0678:                    final List<ConstraintViolation> violations,
0679:                    final AssertConstraintSetCheck check,
0680:                    final Object validatedObject, final Object valueToValidate,
0681:                    final OValContext context) throws OValException {
0682:                final ConstraintSet cs = getConstraintSet(check.getId());
0683:
0684:                if (cs == null)
0685:                    throw new UndefinedConstraintSetException(check.getId());
0686:
0687:                final Collection<Check> referencedChecks = cs.getChecks();
0688:
0689:                if (referencedChecks != null && referencedChecks.size() > 0)
0690:                    for (final Check referencedCheck : referencedChecks) {
0691:                        checkConstraint(violations, referencedCheck,
0692:                                validatedObject, valueToValidate, context);
0693:                    }
0694:            }
0695:
0696:            protected void checkConstraintAssertFieldConstraints(
0697:                    final List<ConstraintViolation> violations,
0698:                    final AssertFieldConstraintsCheck check,
0699:                    final Object validatedObject, final Object valueToValidate,
0700:                    final OValContext context) throws OValException {
0701:                Class targetClass;
0702:
0703:                /*
0704:                 * set the targetClass based on the validation context
0705:                 */
0706:                if (context instanceof  ConstructorParameterContext) {
0707:                    // the class declaring the field must either be the class declaring the constructor or one of its super
0708:                    // classes
0709:                    targetClass = ((ConstructorParameterContext) context)
0710:                            .getConstructor().getDeclaringClass();
0711:                } else if (context instanceof  MethodParameterContext) {
0712:                    // the class declaring the field must either be the class declaring the method or one of its super classes
0713:                    targetClass = ((MethodParameterContext) context)
0714:                            .getMethod().getDeclaringClass();
0715:                } else if (context instanceof  MethodReturnValueContext) {
0716:                    // the class declaring the field must either be the class declaring the getter or one of its super classes
0717:                    targetClass = ((MethodReturnValueContext) context)
0718:                            .getMethod().getDeclaringClass();
0719:                } else if (check.getDeclaringClass() != null
0720:                        && check.getDeclaringClass() != Void.class) {
0721:                    targetClass = check.getDeclaringClass();
0722:                } else {
0723:                    // the lowest class that is expected to declare the field (or one of its super classes)
0724:                    targetClass = validatedObject.getClass();
0725:
0726:                }
0727:
0728:                // the name of the field whose constraints shall be used
0729:                String fieldName = check.getFieldName();
0730:
0731:                /*
0732:                 * calculate the field name based on the validation context if the @FieldConstraints constraint didn't specify the field name
0733:                 */
0734:                if (fieldName == null || fieldName.length() == 0) {
0735:                    if (context instanceof  ConstructorParameterContext) {
0736:                        fieldName = ((ConstructorParameterContext) context)
0737:                                .getParameterName();
0738:                    } else if (context instanceof  MethodParameterContext) {
0739:                        fieldName = ((MethodParameterContext) context)
0740:                                .getParameterName();
0741:                    } else if (context instanceof  MethodReturnValueContext) {
0742:                        /*
0743:                         * calculate the fieldName based on the getXXX isXXX style getter method name
0744:                         */
0745:                        fieldName = ReflectionUtils
0746:                                .guessFieldName(((MethodReturnValueContext) context)
0747:                                        .getMethod());
0748:                    }
0749:                }
0750:
0751:                /*
0752:                 * find the field based on fieldName and targetClass
0753:                 */
0754:                final Field field = ReflectionUtils.getFieldRecursive(
0755:                        targetClass, fieldName);
0756:
0757:                if (field == null)
0758:                    throw new FieldNotFoundException("Field <" + fieldName
0759:                            + "> not found in class <" + targetClass
0760:                            + "> or its super classes.");
0761:
0762:                final ClassChecks cc = getClassChecks(field.getDeclaringClass());
0763:                final Collection<Check> referencedChecks = cc.checksForFields
0764:                        .get(field);
0765:                if (referencedChecks != null && referencedChecks.size() > 0) {
0766:                    for (final Check referencedCheck : referencedChecks) {
0767:                        checkConstraint(violations, referencedCheck,
0768:                                validatedObject, valueToValidate, context);
0769:                    }
0770:                }
0771:            }
0772:
0773:            protected void checkConstraintAssertValid(
0774:                    final List<ConstraintViolation> violations,
0775:                    final AssertValidCheck check, final Object validatedObject,
0776:                    final Object valueToValidate, final OValContext context)
0777:                    throws OValException {
0778:                if (valueToValidate == null)
0779:                    return;
0780:
0781:                // ignore circular dependencies
0782:                if (isCurrentlyValidated(valueToValidate))
0783:                    return;
0784:
0785:                final List<ConstraintViolation> additionalViolations = validate(valueToValidate);
0786:
0787:                if (additionalViolations.size() != 0) {
0788:                    final String errorMessage = renderMessage(context,
0789:                            valueToValidate, check.getMessage(), check
0790:                                    .getMessageVariables());
0791:
0792:                    violations.add(new ConstraintViolation(
0793:                            check.getErrorCode(), errorMessage, check
0794:                                    .getSeverity(), validatedObject,
0795:                            valueToValidate, context, additionalViolations));
0796:                }
0797:
0798:                // if the value to validate is a collection also validate the collection items
0799:                if (valueToValidate instanceof  Collection
0800:                        && check.isRequireValidElements()) {
0801:                    for (final Object item : (Collection) valueToValidate) {
0802:                        checkConstraintAssertValid(violations, check,
0803:                                validatedObject, item, context);
0804:                    }
0805:                }
0806:
0807:                // if the value to validate is a map also validate the map keys and values
0808:                else if (valueToValidate instanceof  Map
0809:                        && check.isRequireValidElements()) {
0810:                    for (final Object item : ((Map) valueToValidate).keySet()) {
0811:                        checkConstraintAssertValid(violations, check,
0812:                                validatedObject, item, context);
0813:                    }
0814:
0815:                    for (final Object item : ((Map) valueToValidate).values()) {
0816:                        checkConstraintAssertValid(violations, check,
0817:                                validatedObject, item, context);
0818:                    }
0819:                }
0820:
0821:                // if the value to validate is an array also validate the array elements
0822:                else if (valueToValidate.getClass().isArray()) {
0823:                    for (final Object item : (Object[]) valueToValidate) {
0824:                        checkConstraintAssertValid(violations, check,
0825:                                validatedObject, item, context);
0826:                    }
0827:                }
0828:            }
0829:
0830:            /**
0831:             * Enables all constraint profiles, i.e. all configured constraint will be validated.
0832:             */
0833:            public synchronized void disableAllProfiles() {
0834:                isProfilesFeatureUsed = true;
0835:                isAllProfilesEnabledByDefault = false;
0836:
0837:                enabledProfiles.clear();
0838:                disabledProfiles.clear();
0839:            }
0840:
0841:            /**
0842:             * Disables a constraints profile.
0843:             * @param profile the id of the profile
0844:             */
0845:            public void disableProfile(final String profile) {
0846:                isProfilesFeatureUsed = true;
0847:
0848:                if (isAllProfilesEnabledByDefault)
0849:                    disabledProfiles.add(profile);
0850:                else
0851:                    enabledProfiles.remove(profile);
0852:            }
0853:
0854:            /**
0855:             * Disables all constraint profiles, i.e. no configured constraint will be validated.
0856:             */
0857:            public synchronized void enableAllProfiles() {
0858:                isProfilesFeatureUsed = true;
0859:                isAllProfilesEnabledByDefault = true;
0860:
0861:                enabledProfiles.clear();
0862:                disabledProfiles.clear();
0863:            }
0864:
0865:            /**
0866:             * Enables a constraints profile.
0867:             * @param profile the id of the profile
0868:             */
0869:            public void enableProfile(final String profile) {
0870:                isProfilesFeatureUsed = true;
0871:
0872:                if (isAllProfilesEnabledByDefault)
0873:                    disabledProfiles.remove(profile);
0874:                else
0875:                    enabledProfiles.add(profile);
0876:            }
0877:
0878:            /**
0879:             * Gets the object-level constraint checks for the given class 
0880:             *  
0881:             * @param clazz
0882:             * @throws IllegalArgumentException if <code>clazz == null</code> 
0883:             */
0884:            public Check[] getChecks(final Class clazz)
0885:                    throws IllegalArgumentException {
0886:                if (clazz == null)
0887:                    throw new IllegalArgumentException("clazz cannot be null");
0888:
0889:                final ClassChecks cc = getClassChecks(clazz);
0890:
0891:                final Set<Check> checks = cc.checksForObject;
0892:                return checks == null ? null : checks.toArray(new Check[checks
0893:                        .size()]);
0894:            }
0895:
0896:            /**
0897:             * Gets the constraint checks for the given field 
0898:             *  
0899:             * @param field
0900:             * @throws IllegalArgumentException if <code>field == null</code> 
0901:             */
0902:            public Check[] getChecks(final Field field)
0903:                    throws IllegalArgumentException {
0904:                if (field == null)
0905:                    throw new IllegalArgumentException("field cannot be null");
0906:
0907:                final ClassChecks cc = getClassChecks(field.getDeclaringClass());
0908:
0909:                final Set<Check> checks = cc.checksForFields.get(field);
0910:                return checks == null ? null : checks.toArray(new Check[checks
0911:                        .size()]);
0912:            }
0913:
0914:            /**
0915:             * Gets the constraint checks for the given method's return value
0916:             *  
0917:             * @param method
0918:             * @throws IllegalArgumentException if <code>getter == null</code>
0919:             */
0920:            public Check[] getChecks(final Method method)
0921:                    throws IllegalArgumentException {
0922:                if (method == null)
0923:                    throw new IllegalArgumentException("method cannot be null");
0924:
0925:                final ClassChecks cc = getClassChecks(method
0926:                        .getDeclaringClass());
0927:
0928:                final Set<Check> checks = cc.checksForMethodReturnValues
0929:                        .get(method);
0930:                return checks == null ? null : checks.toArray(new Check[checks
0931:                        .size()]);
0932:            }
0933:
0934:            /**
0935:             * Returns the ClassChecks object for the particular class,
0936:             * allowing you to modify the checks
0937:             * 
0938:             * @param clazz cannot be null
0939:             * @return returns the ClassChecks for the given class
0940:             * @throws IllegalArgumentException if <code>clazz == null</code>
0941:             * @throws OValException
0942:             */
0943:            protected ClassChecks getClassChecks(final Class clazz)
0944:                    throws IllegalArgumentException, OValException {
0945:                if (clazz == null)
0946:                    throw new IllegalArgumentException("clazz cannot be null");
0947:
0948:                synchronized (checksByClass) {
0949:                    ClassChecks cc = checksByClass.get(clazz);
0950:
0951:                    if (cc == null) {
0952:                        cc = new ClassChecks(clazz);
0953:
0954:                        for (final Configurer configurer : configurers) {
0955:                            final ClassConfiguration classConfig = configurer
0956:                                    .getClassConfiguration(clazz);
0957:                            if (classConfig != null)
0958:                                addChecks(cc, classConfig);
0959:                        }
0960:
0961:                        checksByClass.put(clazz, cc);
0962:                    }
0963:
0964:                    return cc;
0965:                }
0966:            }
0967:
0968:            /**
0969:             * @return the internal list with the registered configurers
0970:             */
0971:            public List<Configurer> getConfigurers() {
0972:                return configurers;
0973:            }
0974:
0975:            public ConstraintSet getConstraintSet(final String constraintSetId)
0976:                    throws OValException {
0977:                synchronized (constraintSetsById) {
0978:                    ConstraintSet cs = constraintSetsById.get(constraintSetId);
0979:
0980:                    if (cs == null) {
0981:                        for (final Configurer configurer : configurers) {
0982:                            final ConstraintSetConfiguration csc = configurer
0983:                                    .getConstraintSetConfiguration(constraintSetId);
0984:                            if (csc != null) {
0985:                                cs = new ConstraintSet(csc.id);
0986:                                cs.setChecks(csc.checks);
0987:
0988:                                addConstraintSet(cs, csc.overwrite != null
0989:                                        && csc.overwrite);
0990:                            }
0991:                        }
0992:                    }
0993:                    return cs;
0994:                }
0995:            }
0996:
0997:            /**
0998:             * @return the exceptionProcessor
0999:             */
1000:            public ExceptionTranslator getExceptionTranslator() {
1001:                return exceptionTranslator;
1002:            }
1003:
1004:            /**
1005:             * 
1006:             * @param languageId the id of the language, cannot be null
1007:             * 
1008:             * @throws IllegalArgumentException if <code>languageName == null</code>
1009:             * @throws ExpressionLanguageNotAvailableException
1010:             */
1011:            public ExpressionLanguage getExpressionLanguage(
1012:                    final String languageId) throws IllegalArgumentException,
1013:                    ExpressionLanguageNotAvailableException {
1014:                if (languageId == null)
1015:                    throw new IllegalArgumentException(
1016:                            "languageId cannot be null");
1017:
1018:                final ExpressionLanguage el = expressionLanguages
1019:                        .get(languageId);
1020:
1021:                if (el == null)
1022:                    throw new ExpressionLanguageNotAvailableException(
1023:                            languageId);
1024:
1025:                return el;
1026:            }
1027:
1028:            private void initializeDefaultELs() {
1029:                // JavaScript support
1030:                if (ReflectionUtils
1031:                        .isClassPresent("org.mozilla.javascript.Context")) {
1032:                    addExpressionLanguage("javascript",
1033:                            new ExpressionLanguageJavaScriptImpl());
1034:                    addExpressionLanguage("js",
1035:                            getExpressionLanguage("javascript"));
1036:                }
1037:
1038:                // Groovy support
1039:                if (ReflectionUtils.isClassPresent("groovy.lang.Binding")) {
1040:                    addExpressionLanguage("groovy",
1041:                            new ExpressionLanguageGroovyImpl());
1042:                }
1043:
1044:                // BeanShell support
1045:                if (ReflectionUtils.isClassPresent("bsh.Interpreter")) {
1046:                    addExpressionLanguage("bsh",
1047:                            new ExpressionLanguageBeanShellImpl());
1048:                    addExpressionLanguage("beanshell",
1049:                            getExpressionLanguage("bsh"));
1050:                }
1051:
1052:                // OGNL support
1053:                if (ReflectionUtils.isClassPresent("ognl.Ognl")) {
1054:                    addExpressionLanguage("ognl",
1055:                            new ExpressionLanguageOGNLImpl());
1056:                }
1057:
1058:                // MVEL support
1059:                if (ReflectionUtils.isClassPresent("org.mvel.MVEL")) {
1060:                    addExpressionLanguage("mvel",
1061:                            new ExpressionLanguageMVELImpl());
1062:                }
1063:
1064:                // JRuby support
1065:                if (ReflectionUtils.isClassPresent("org.jruby.Ruby")) {
1066:                    addExpressionLanguage("ruby",
1067:                            new ExpressionLanguageJRubyImpl());
1068:                    addExpressionLanguage("jruby",
1069:                            getExpressionLanguage("ruby"));
1070:                }
1071:            }
1072:
1073:            /**
1074:             * Determines if at least one of the given profiles is enabled
1075:             * 
1076:             * @param profileIds
1077:             * @return Returns true if at least one of the given profiles is enabled. 
1078:             */
1079:            protected boolean isAnyProfileEnabled(final String[] profileIds) {
1080:                if (profileIds == null || profileIds.length == 0)
1081:                    return isAllProfilesEnabledByDefault;
1082:
1083:                for (final String profile : profileIds) {
1084:                    if (isProfileEnabled(profile))
1085:                        return true;
1086:                }
1087:                return false;
1088:            }
1089:
1090:            /**
1091:             * Determines if the given object is currently validated in the current thread
1092:             * 
1093:             * @param object
1094:             * @return Returns true if the given object is currently validated in the current thread.
1095:             */
1096:            protected boolean isCurrentlyValidated(final Object object) {
1097:                return currentlyValidatedObjects.get().contains(object);
1098:            }
1099:
1100:            /**
1101:             * Determines if the given profile is enabled.
1102:             * 
1103:             * @param profileId
1104:             * @return Returns true if the given profile is enabled.
1105:             */
1106:            public boolean isProfileEnabled(final String profileId) {
1107:                if (isProfilesFeatureUsed) {
1108:                    if (isAllProfilesEnabledByDefault)
1109:                        return !disabledProfiles.contains(profileId);
1110:
1111:                    return enabledProfiles.contains(profileId);
1112:                }
1113:                return true;
1114:            }
1115:
1116:            /**
1117:             * clears the checks and constraint sets => a reconfiguration using the
1118:             * currently registered configurers will automatically happen
1119:             */
1120:            public void reconfigureChecks() {
1121:                synchronized (checksByClass) {
1122:                    checksByClass.clear();
1123:                }
1124:                synchronized (constraintSetsById) {
1125:                    constraintSetsById.clear();
1126:                }
1127:            }
1128:
1129:            /**
1130:             * Removes object-level constraint checks 
1131:             *  
1132:             * @param clazz
1133:             * @param checks
1134:             * @throws IllegalArgumentException if <code>clazz == null</code> or <code>checks == null</code> or checks is empty 
1135:             */
1136:            public void removeChecks(final Class clazz, final Check... checks)
1137:                    throws IllegalArgumentException {
1138:                if (clazz == null)
1139:                    throw new IllegalArgumentException("clazz cannot be null");
1140:                if (checks == null)
1141:                    throw new IllegalArgumentException("checks cannot be null");
1142:                if (checks.length == 0)
1143:                    throw new IllegalArgumentException("checks cannot empty");
1144:
1145:                final ClassChecks cc = getClassChecks(clazz);
1146:                cc.removeObjectChecks(checks);
1147:            }
1148:
1149:            /**
1150:             * Removes constraint checks for the given field 
1151:             *  
1152:             * @param field
1153:             * @param checks
1154:             * @throws IllegalArgumentException if <code>field == null</code> or <code>checks == null</code> or checks is empty 
1155:             */
1156:            public void removeChecks(final Field field, final Check... checks)
1157:                    throws IllegalArgumentException {
1158:                if (field == null)
1159:                    throw new IllegalArgumentException("field cannot be null");
1160:                if (checks == null)
1161:                    throw new IllegalArgumentException("checks cannot be null");
1162:                if (checks.length == 0)
1163:                    throw new IllegalArgumentException("checks cannot empty");
1164:
1165:                final ClassChecks cc = getClassChecks(field.getDeclaringClass());
1166:                cc.removeFieldChecks(field, checks);
1167:            }
1168:
1169:            /**
1170:             * Removes constraint checks for the given getter's return value
1171:             * 
1172:             * @param getter a JavaBean Getter style method
1173:             * @param checks
1174:             * @throws IllegalArgumentException if <code>getter == null</code> or <code>checks == null</code>
1175:             */
1176:            public void removeChecks(final Method getter, final Check... checks)
1177:                    throws IllegalArgumentException {
1178:                if (getter == null)
1179:                    throw new IllegalArgumentException("field cannot be null");
1180:                if (checks == null)
1181:                    throw new IllegalArgumentException("checks cannot be null");
1182:                if (checks.length == 0)
1183:                    throw new IllegalArgumentException("checks cannot empty");
1184:
1185:                final ClassChecks cc = getClassChecks(getter
1186:                        .getDeclaringClass());
1187:                cc.removeMethodChecks(getter, checks);
1188:            }
1189:
1190:            /**
1191:             * Removes the constraint set with the given id
1192:             * @param id the id of the constraint set to remove, cannot be null
1193:             * @return the removed constraint set
1194:             * @throws IllegalArgumentException if <code>id == null</code>
1195:             */
1196:            public ConstraintSet removeConstraintSet(final String id)
1197:                    throws IllegalArgumentException {
1198:                if (id == null)
1199:                    throw new IllegalArgumentException("id cannot be null");
1200:                synchronized (constraintSetsById) {
1201:                    return constraintSetsById.remove(id);
1202:                }
1203:            }
1204:
1205:            protected String renderMessage(final OValContext context,
1206:                    final Object value, final String messageKey,
1207:                    final Map<String, String> messageValues) {
1208:                String message = MessageRenderer.renderMessage(messageKey,
1209:                        messageValues);
1210:
1211:                // if there are no place holders in the message simply return it
1212:                if (message.indexOf('{') == -1)
1213:                    return message;
1214:
1215:                message = StringUtils.replaceAll(message, "{context}", context
1216:                        .toString());
1217:                message = StringUtils.replaceAll(message, "{invalidValue}",
1218:                        value == null ? "null" : value.toString());
1219:
1220:                return message;
1221:            }
1222:
1223:            /**
1224:             * @param exceptionTranslator the exceptionTranslator to set
1225:             */
1226:            public void setExceptionTranslator(
1227:                    final ExceptionTranslator exceptionTranslator) {
1228:                this .exceptionTranslator = exceptionTranslator;
1229:            }
1230:
1231:            protected RuntimeException translateException(final OValException ex) {
1232:                if (exceptionTranslator != null) {
1233:                    final RuntimeException rex = exceptionTranslator
1234:                            .translateException(ex);
1235:                    if (rex != null)
1236:                        return rex;
1237:                }
1238:                return ex;
1239:            }
1240:
1241:            /**
1242:             * validates the field and getter constrains of the given object
1243:             * 
1244:             * @param validatedObject the object to validate, cannot be null
1245:             * @return a list with the detected constraint violations. if no violations are detected an empty list is returned
1246:             * @throws ValidationFailedException
1247:             * @throws IllegalArgumentException if <code>validatedObject == null</code>
1248:             */
1249:            public List<ConstraintViolation> validate(
1250:                    final Object validatedObject)
1251:                    throws IllegalArgumentException, ValidationFailedException {
1252:                if (validatedObject == null)
1253:                    throw new IllegalArgumentException(
1254:                            "validatedObject cannot be null");
1255:
1256:                final List<ConstraintViolation> violations = CollectionFactoryHolder
1257:                        .getFactory().createList();
1258:
1259:                validateInvariants(validatedObject, violations);
1260:                return violations;
1261:            }
1262:
1263:            /**
1264:             * Validates the give value against the defined field constraints.<br>
1265:             * 
1266:             * @return a list with the detected constraint violations. if no violations are detected an empty list is returned
1267:             * @throws IllegalArgumentException if <code>validatedObject == null</code> or <code>field == null</code>
1268:             * @throws ValidationFailedException 
1269:             */
1270:            public List<ConstraintViolation> validateFieldValue(
1271:                    final Object validatedObject, final Field validatedField,
1272:                    final Object fieldValueToValidate)
1273:                    throws IllegalArgumentException, ValidationFailedException {
1274:                if (validatedObject == null)
1275:                    throw new IllegalArgumentException(
1276:                            "validatedObject cannot be null");
1277:
1278:                if (validatedField == null)
1279:                    throw new IllegalArgumentException("field cannot be null");
1280:
1281:                try {
1282:                    final ClassChecks cc = getClassChecks(validatedField
1283:                            .getDeclaringClass());
1284:                    final Collection<Check> checks = cc.checksForFields
1285:                            .get(validatedField);
1286:
1287:                    if (checks == null || checks.size() == 0)
1288:                        return null;
1289:
1290:                    final List<ConstraintViolation> violations = CollectionFactoryHolder
1291:                            .getFactory().createList();
1292:
1293:                    final FieldContext context = new FieldContext(
1294:                            validatedField);
1295:
1296:                    for (final Check check : checks) {
1297:                        checkConstraint(violations, check, validatedObject,
1298:                                fieldValueToValidate, context);
1299:                    }
1300:                    return violations;
1301:                } catch (final OValException ex) {
1302:                    throw new ValidationFailedException(
1303:                            "Field validation failed. Field: " + validatedField
1304:                                    + " Validated object: " + validatedObject,
1305:                            ex);
1306:                }
1307:            }
1308:
1309:            /**
1310:             * validates the field and getter constrains of the given object.
1311:             * if the given object is a class the static fields and getters
1312:             * are validated.
1313:             * 
1314:             * @param validatedObject the object to validate, cannot be null
1315:             * @throws ValidationFailedException
1316:             * @throws IllegalArgumentException if <code>validatedObject == null</code>
1317:             */
1318:            protected void validateInvariants(final Object validatedObject,
1319:                    final List<ConstraintViolation> violations)
1320:                    throws IllegalArgumentException, ValidationFailedException {
1321:                if (validatedObject == null)
1322:                    throw new IllegalArgumentException(
1323:                            "validatedObject cannot be null");
1324:
1325:                currentlyValidatedObjects.get().add(validatedObject);
1326:                try {
1327:                    if (validatedObject instanceof  Class)
1328:                        validateStaticInvariants((Class) validatedObject,
1329:                                violations);
1330:                    else
1331:                        validateObjectInvariants(validatedObject,
1332:                                validatedObject.getClass(), violations);
1333:                } finally {
1334:                    currentlyValidatedObjects.get().remove(validatedObject);
1335:                }
1336:            }
1337:
1338:            /**
1339:             * validate validatedObject based on the constraints of the given clazz 
1340:             */
1341:            private void validateObjectInvariants(final Object validatedObject,
1342:                    final Class<?> clazz,
1343:                    final List<ConstraintViolation> violations)
1344:                    throws ValidationFailedException {
1345:                assert validatedObject != null;
1346:                assert clazz != null;
1347:                assert violations != null;
1348:
1349:                // abort if the root class has been reached
1350:                if (clazz == Object.class)
1351:                    return;
1352:
1353:                try {
1354:                    final ClassChecks cc = getClassChecks(clazz);
1355:
1356:                    // validate field constraints
1357:                    for (final Field field : cc.constrainedFields) {
1358:                        final Collection<Check> checks = cc.checksForFields
1359:                                .get(field);
1360:
1361:                        if (checks != null && checks.size() > 0) {
1362:                            final Object valueToValidate = ReflectionUtils
1363:                                    .getFieldValue(field, validatedObject);
1364:                            final FieldContext ctx = new FieldContext(field);
1365:
1366:                            for (final Check check : checks) {
1367:                                checkConstraint(violations, check,
1368:                                        validatedObject, valueToValidate, ctx);
1369:                            }
1370:                        }
1371:                    }
1372:
1373:                    // validate constraints on getter methods
1374:                    for (final Method getter : cc.constrainedMethods) {
1375:                        final Collection<Check> checks = cc.checksForMethodReturnValues
1376:                                .get(getter);
1377:
1378:                        if (checks != null && checks.size() > 0) {
1379:                            final Object valueToValidate = ReflectionUtils
1380:                                    .invokeMethod(getter, validatedObject);
1381:                            final MethodReturnValueContext ctx = new MethodReturnValueContext(
1382:                                    getter);
1383:
1384:                            for (final Check check : checks) {
1385:                                checkConstraint(violations, check,
1386:                                        validatedObject, valueToValidate, ctx);
1387:                            }
1388:                        }
1389:                    }
1390:
1391:                    // validate object constraints
1392:                    if (cc.checksForObject.size() > 0) {
1393:                        final ClassContext ctx = new ClassContext(clazz);
1394:                        for (final Check check : cc.checksForObject) {
1395:                            checkConstraint(violations, check, validatedObject,
1396:                                    validatedObject, ctx);
1397:                        }
1398:                    }
1399:
1400:                    // if the super class is annotated to be validatable also validate it against the object
1401:                    validateObjectInvariants(validatedObject, clazz
1402:                            .getSuperclass(), violations);
1403:                } catch (final OValException ex) {
1404:                    throw new ValidationFailedException(
1405:                            "Object validation failed. Class: " + clazz
1406:                                    + " Validated object: " + validatedObject,
1407:                            ex);
1408:                }
1409:            }
1410:
1411:            /**
1412:             * Validates the static field and static getter constrains of the given class.
1413:             * Constraints specified for super classes are not taken in account.
1414:             */
1415:            private void validateStaticInvariants(final Class validatedClass,
1416:                    final List<ConstraintViolation> violations)
1417:                    throws ValidationFailedException {
1418:                assert validatedClass != null;
1419:                assert violations != null;
1420:
1421:                final ClassChecks cc = getClassChecks(validatedClass);
1422:
1423:                // validate static field constraints
1424:                for (final Field field : cc.constrainedStaticFields) {
1425:                    final Collection<Check> checks = cc.checksForFields
1426:                            .get(field);
1427:
1428:                    if (checks != null && checks.size() > 0) {
1429:                        final Object valueToValidate = ReflectionUtils
1430:                                .getFieldValue(field, null);
1431:                        final FieldContext context = new FieldContext(field);
1432:
1433:                        for (final Check check : checks) {
1434:                            checkConstraint(violations, check, validatedClass,
1435:                                    valueToValidate, context);
1436:                        }
1437:                    }
1438:                }
1439:
1440:                // validate constraints on getter methods
1441:                for (final Method getter : cc.constrainedStaticMethods) {
1442:                    final Collection<Check> checks = cc.checksForMethodReturnValues
1443:                            .get(getter);
1444:
1445:                    if (checks != null && checks.size() > 0) {
1446:                        final Object valueToValidate = ReflectionUtils
1447:                                .invokeMethod(getter, null);
1448:                        final MethodReturnValueContext context = new MethodReturnValueContext(
1449:                                getter);
1450:
1451:                        for (final Check check : checks) {
1452:                            checkConstraint(violations, check, validatedClass,
1453:                                    valueToValidate, context);
1454:                        }
1455:                    }
1456:                }
1457:            }
1458:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.