001// Copyright 2009-2013 The Apache Software Foundation 002// 003// Licensed under the Apache License, Version 2.0 (the "License"); 004// you may not use this file except in compliance with the License. 005// You may obtain a copy of the License at 006// 007// http://www.apache.org/licenses/LICENSE-2.0 008// 009// Unless required by applicable law or agreed to in writing, software 010// distributed under the License is distributed on an "AS IS" BASIS, 011// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 012// See the License for the specific language governing permissions and 013// limitations under the License. 014package org.apache.tapestry5.beanvalidator.modules; 015 016import org.apache.tapestry5.MarkupWriter; 017import org.apache.tapestry5.beanvalidator.*; 018import org.apache.tapestry5.internal.beanvalidator.*; 019import org.apache.tapestry5.ioc.Configuration; 020import org.apache.tapestry5.ioc.MappedConfiguration; 021import org.apache.tapestry5.ioc.OrderedConfiguration; 022import org.apache.tapestry5.ioc.ServiceBinder; 023import org.apache.tapestry5.ioc.annotations.Local; 024import org.apache.tapestry5.ioc.services.PropertyShadowBuilder; 025import org.apache.tapestry5.ioc.services.ThreadLocale; 026import org.apache.tapestry5.services.FieldValidatorDefaultSource; 027import org.apache.tapestry5.services.javascript.DataConstants; 028import org.apache.tapestry5.services.javascript.JavaScriptSupport; 029 030import javax.validation.MessageInterpolator; 031import javax.validation.Validator; 032import javax.validation.ValidatorFactory; 033import javax.validation.constraints.*; 034import javax.validation.groups.Default; 035import java.util.Map; 036 037/** 038 * Module for JSR-303 services. 039 * 040 * @since 5.2.0.0 041 */ 042public class BeanValidatorModule 043{ 044 045 private static final String MODULE_NAME = "t5/beanvalidator/beanvalidator-validation"; 046 047 public static void bind(final ServiceBinder binder) 048 { 049 binder.bind(FieldValidatorDefaultSource.class, BeanFieldValidatorDefaultSource.class).withSimpleId(); 050 binder.bind(BeanValidatorGroupSource.class, BeanValidationGroupSourceImpl.class); 051 binder.bind(BeanValidatorSource.class, BeanValidatorSourceImpl.class); 052 binder.bind(ClientConstraintDescriptorSource.class, ClientConstraintDescriptorImpl.class); 053 } 054 055 public static void contributeServiceOverride( 056 MappedConfiguration<Class<?>, Object> configuration, 057 @Local FieldValidatorDefaultSource source) 058 { 059 configuration.add(FieldValidatorDefaultSource.class, source); 060 } 061 062 public static Validator buildBeanValidator(ValidatorFactory validatorFactory, PropertyShadowBuilder propertyShadowBuilder) 063 { 064 return propertyShadowBuilder.build(validatorFactory, "validator", Validator.class); 065 } 066 067 068 public static ValidatorFactory buildValidatorFactory(BeanValidatorSource beanValidatorSource, PropertyShadowBuilder propertyShadowBuilder) 069 { 070 return propertyShadowBuilder.build(beanValidatorSource, "validatorFactory", ValidatorFactory.class); 071 } 072 073 public static void contributeBeanValidatorGroupSource( 074 final Configuration<Class<?>> configuration) 075 { 076 configuration.add(Default.class); 077 } 078 079 public static void contributeBeanValidatorSource( 080 final OrderedConfiguration<BeanValidatorConfigurer> configuration, final ThreadLocale threadLocale) 081 { 082 configuration.add("LocaleAwareMessageInterpolator", new BeanValidatorConfigurer() 083 { 084 @Override 085 public void configure(javax.validation.Configuration<?> configuration) 086 { 087 MessageInterpolator defaultInterpolator = configuration.getDefaultMessageInterpolator(); 088 089 configuration.messageInterpolator(new MessageInterpolatorImpl(defaultInterpolator, threadLocale)); 090 } 091 }); 092 } 093 094 public static void contributeClientConstraintDescriptorSource(final JavaScriptSupport javaScriptSupport, 095 final Configuration<ClientConstraintDescriptor> configuration) 096 { 097 configuration.add(new BaseCCD(Max.class, "value") 098 { 099 @Override 100 public void applyClientValidation(MarkupWriter writer, String message, Map<String, Object> attributes) 101 { 102 javaScriptSupport.require("t5/core/validation"); 103 writer.attributes( 104 "data-validate", true, 105 "data-validate-max", attributes.get("value"), 106 "data-max-message", message); 107 108 } 109 }); 110 111 configuration.add(new BaseCCD(Min.class, "value") 112 { 113 @Override 114 public void applyClientValidation(MarkupWriter writer, String message, Map<String, Object> attributes) 115 { 116 javaScriptSupport.require("t5/core/validation"); 117 writer.attributes( 118 DataConstants.VALIDATION_ATTRIBUTE, true, 119 "data-validate-min", attributes.get("value"), 120 "data-min-message", message); 121 122 } 123 }); 124 125 configuration.add(new BaseCCD(NotNull.class) 126 { 127 @Override 128 public void applyClientValidation(MarkupWriter writer, String message, Map<String, Object> attributes) 129 { 130 javaScriptSupport.require("t5/core/validation"); 131 writer.attributes( 132 DataConstants.VALIDATION_ATTRIBUTE, true, 133 "data-optionality", "required", 134 "data-required-message", message); 135 } 136 }); 137 138 configuration.add(new BaseCCD(Null.class) 139 { 140 @Override 141 public void applyClientValidation(MarkupWriter writer, String message, Map<String, Object> attributes) 142 { 143 javaScriptSupport.require(MODULE_NAME); 144 writer.attributes( 145 DataConstants.VALIDATION_ATTRIBUTE, true, 146 "data-optionality", "prohibited", 147 "data-prohibited-message", message); 148 } 149 }); 150 151 configuration.add(new BaseCCD(Pattern.class, "regexp") 152 { 153 @Override 154 public void applyClientValidation(MarkupWriter writer, String message, Map<String, Object> attributes) 155 { 156 javaScriptSupport.require(MODULE_NAME); 157 writer.attributes( 158 DataConstants.VALIDATION_ATTRIBUTE, true, 159 "data-validate-regexp", attributes.get("regexp"), 160 "data-regexp-message", message); 161 } 162 }); 163 164 configuration.add(new BaseCCD(Size.class, "min", "max") 165 { 166 @Override 167 public void applyClientValidation(MarkupWriter writer, String message, Map<String, Object> attributes) 168 { 169 javaScriptSupport.require(MODULE_NAME); 170 writer.attributes( 171 DataConstants.VALIDATION_ATTRIBUTE, true, 172 "data-range-message", message); 173 174 int min = (Integer) attributes.get("min"); 175 176 if (min != 0) 177 { 178 writer.attributes("data-range-min", min); 179 } 180 181 int max = (Integer) attributes.get("max"); 182 183 if (max != Integer.MAX_VALUE) 184 { 185 writer.attributes("data-range-max", max); 186 } 187 } 188 }); 189 190 configuration.add(new BaseCCD(AssertTrue.class) 191 { 192 @Override 193 public void applyClientValidation(MarkupWriter writer, String message, Map<String, Object> attributes) 194 { 195 javaScriptSupport.require("t5/core/validation"); 196 197 writer.attributes( 198 DataConstants.VALIDATION_ATTRIBUTE, true, 199 "data-expected-status", "checked", 200 "data-checked-message", message); 201 } 202 }); 203 204 configuration.add(new BaseCCD(AssertFalse.class) 205 { 206 @Override 207 public void applyClientValidation(MarkupWriter writer, String message, Map<String, Object> attributes) 208 { 209 javaScriptSupport.require("t5/core/validation"); 210 211 writer.attributes( 212 DataConstants.VALIDATION_ATTRIBUTE, true, 213 "data-expected-status", "unchecked", 214 "data-checked-message", message); 215 } 216 }); 217 } 218}