View Javadoc

1   /*
2    * Copyright 2004-2010 the Seasar Foundation and the Others.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
13   * either express or implied. See the License for the specific language
14   * governing permissions and limitations under the License.
15   */
16  
17  package org.seasar.cubby.plugins.oval.validation;
18  
19  import java.util.List;
20  import java.util.Map;
21  
22  import net.sf.oval.ConstraintViolation;
23  import net.sf.oval.Validator;
24  import net.sf.oval.context.ClassContext;
25  import net.sf.oval.context.ConstructorParameterContext;
26  import net.sf.oval.context.FieldContext;
27  import net.sf.oval.context.MethodEntryContext;
28  import net.sf.oval.context.MethodExitContext;
29  import net.sf.oval.context.MethodParameterContext;
30  import net.sf.oval.context.MethodReturnValueContext;
31  import net.sf.oval.context.OValContext;
32  
33  import org.seasar.cubby.action.ActionErrors;
34  import org.seasar.cubby.action.FieldInfo;
35  import org.seasar.cubby.spi.ContainerProvider;
36  import org.seasar.cubby.spi.ProviderFactory;
37  import org.seasar.cubby.spi.container.Container;
38  import org.seasar.cubby.spi.container.LookupException;
39  import org.seasar.cubby.validator.ValidationException;
40  import org.seasar.cubby.validator.ValidationRule;
41  
42  /**
43   * OVal によって入力を検証する {@link ValidationRule} です。
44   * 
45   * @author baba
46   */
47  public class OValValidationRule implements ValidationRule {
48  
49  	/** リソースのキープレフィックス。 */
50  	private final String resourceKeyPrefix;
51  
52  	/**
53  	 * キーのプレフィックスなしでインスタンス化します。
54  	 */
55  	public OValValidationRule() {
56  		this(null);
57  	}
58  
59  	/**
60  	 * 指定されたプレフィックスをフィールド名のキーのプレフィックスとしてインスタンス化します。
61  	 * 
62  	 * @param resourceKeyPrefix
63  	 *            リソースのキープレフィックス
64  	 */
65  	public OValValidationRule(final String resourceKeyPrefix) {
66  		this.resourceKeyPrefix = resourceKeyPrefix;
67  	}
68  
69  	/**
70  	 * {@inheritDoc}
71  	 */
72  	public void apply(final Map<String, Object[]> params, final Object form,
73  			final ActionErrors errors) throws ValidationException {
74  		final OValValidationContext context = OValValidationContext.get();
75  		context.setResourceKeyPrefix(resourceKeyPrefix);
76  		try {
77  			final Validator validator = buildValidator();
78  			final List<ConstraintViolation> violations = validator
79  					.validate(form);
80  			processViolations(violations, errors);
81  		} finally {
82  			OValValidationContext.remove();
83  		}
84  	}
85  
86  	/**
87  	 * バリデータを構築します。
88  	 * 
89  	 * @return バリデータ
90  	 */
91  	protected Validator buildValidator() {
92  		final Container container = ProviderFactory
93  				.get(ContainerProvider.class).getContainer();
94  		try {
95  			return container.lookup(Validator.class);
96  		} catch (final LookupException e) {
97  			return new Validator();
98  		}
99  	}
100 
101 	/**
102 	 * 入力検証で検出した制約違反を処理します。
103 	 * <p>
104 	 * <code>errors</code> に制約違反から抽出したメッセージを設定します。
105 	 * </p>
106 	 * 
107 	 * @param violations
108 	 *            制約違反のリスト
109 	 * @param errors
110 	 *            メッセージを設定するオブジェクト
111 	 */
112 	protected void processViolations(
113 			final List<ConstraintViolation> violations,
114 			final ActionErrors errors) {
115 		for (final ConstraintViolation violation : violations) {
116 			final String message = violation.getMessage();
117 			final FieldInfo fieldInfo = createFieldInfo(violation.getContext());
118 			if (fieldInfo != null) {
119 				errors.add(message, fieldInfo);
120 			} else {
121 				errors.add(message);
122 			}
123 		}
124 	}
125 
126 	/**
127 	 * <code>ovalContext</code> から {@link FieldInfo} を生成します。
128 	 * 
129 	 * @param ovalContext
130 	 *            OVal のコンテキスト
131 	 * @return <code>ovalContext</code> から生成された {@link FieldInfo}
132 	 */
133 	protected FieldInfo createFieldInfo(final OValContext ovalContext) {
134 		final FieldInfo fieldInfo;
135 		if (ovalContext instanceof ClassContext) {
136 			fieldInfo = null;
137 		} else if (ovalContext instanceof FieldContext) {
138 			final FieldContext ctx = (FieldContext) ovalContext;
139 			fieldInfo = new FieldInfo(ctx.getField().getName());
140 		} else if (ovalContext instanceof ConstructorParameterContext) {
141 			final ConstructorParameterContext ctx = (ConstructorParameterContext) ovalContext;
142 			fieldInfo = new FieldInfo(ctx.getParameterName());
143 		} else if (ovalContext instanceof MethodParameterContext) {
144 			final MethodParameterContext ctx = (MethodParameterContext) ovalContext;
145 			fieldInfo = new FieldInfo(ctx.getParameterName());
146 		} else if (ovalContext instanceof MethodEntryContext) {
147 			final MethodEntryContext ctx = (MethodEntryContext) ovalContext;
148 			fieldInfo = new FieldInfo(ctx.getMethod().getName());
149 		} else if (ovalContext instanceof MethodExitContext) {
150 			final MethodExitContext ctx = (MethodExitContext) ovalContext;
151 			fieldInfo = new FieldInfo(ctx.getMethod().getName());
152 		} else if (ovalContext instanceof MethodReturnValueContext) {
153 			final MethodReturnValueContext ctx = (MethodReturnValueContext) ovalContext;
154 			fieldInfo = new FieldInfo(ctx.getMethod().getName());
155 		} else {
156 			fieldInfo = null;
157 		}
158 
159 		return fieldInfo;
160 	}
161 
162 }