1 /*
2 * Copyright (c) 2002-2007 by OpenSymphony
3 * All rights reserved.
4 */
5 package com.opensymphony.xwork2.interceptor;
6
7 import com.opensymphony.xwork2.ActionContext;
8 import com.opensymphony.xwork2.ActionInvocation;
9 import com.opensymphony.xwork2.ValidationAware;
10 import com.opensymphony.xwork2.conversion.impl.XWorkConverter;
11 import com.opensymphony.xwork2.util.ValueStack;
12
13 import java.util.HashMap;
14 import java.util.Iterator;
15 import java.util.Map;
16
17
18 /**
19 * <!-- START SNIPPET: description -->
20 * ConversionErrorInterceptor adds conversion errors from the ActionContext to the Action's field errors.
21 *
22 * <p/>
23 * This interceptor adds any error found in the {@link ActionContext}'s conversionErrors map as a field error (provided
24 * that the action implements {@link ValidationAware}). In addition, any field that contains a validation error has its
25 * original value saved such that any subsequent requests for that value return the original value rather than the value
26 * in the action. This is important because if the value "abc" is submitted and can't be converted to an int, we want to
27 * display the original string ("abc") again rather than the int value (likely 0, which would make very little sense to
28 * the user).
29 *
30 *
31 * <!-- END SNIPPET: description -->
32 *
33 * <p/> <u>Interceptor parameters:</u>
34 *
35 * <!-- START SNIPPET: parameters -->
36 *
37 * <ul>
38 *
39 * <li>None</li>
40 *
41 * </ul>
42 *
43 * <!-- END SNIPPET: parameters -->
44 *
45 * <p/> <u>Extending the interceptor:</u>
46 *
47 * <p/>
48 *
49 * <!-- START SNIPPET: extending -->
50 *
51 * Because this interceptor is not web-specific, it abstracts the logic for whether an error should be added. This
52 * allows for web-specific interceptors to use more complex logic in the {@link #shouldAddError} method for when a value
53 * has a conversion error but is null or empty or otherwise indicates that the value was never actually entered by the
54 * user.
55 *
56 * <!-- END SNIPPET: extending -->
57 *
58 * <p/> <u>Example code:</u>
59 *
60 * <pre>
61 * <!-- START SNIPPET: example -->
62 * <action name="someAction" class="com.examples.SomeAction">
63 * <interceptor-ref name="params"/>
64 * <interceptor-ref name="conversionError"/>
65 * <result name="success">good_result.ftl</result>
66 * </action>
67 * <!-- END SNIPPET: example -->
68 * </pre>
69 *
70 * @author Jason Carreira
71 */
72 public class ConversionErrorInterceptor extends AbstractInterceptor {
73
74 public static final String ORIGINAL_PROPERTY_OVERRIDE = "original.property.override";
75
76 protected Object getOverrideExpr(ActionInvocation invocation, Object value) {
77 return "'" + value + "'";
78 }
79
80 public String intercept(ActionInvocation invocation) throws Exception {
81
82 ActionContext invocationContext = invocation.getInvocationContext();
83 Map conversionErrors = invocationContext.getConversionErrors();
84 ValueStack stack = invocationContext.getValueStack();
85
86 HashMap fakie = null;
87
88 for (Iterator iterator = conversionErrors.entrySet().iterator();
89 iterator.hasNext();) {
90 Map.Entry entry = (Map.Entry) iterator.next();
91 String propertyName = (String) entry.getKey();
92 Object value = entry.getValue();
93
94 if (shouldAddError(propertyName, value)) {
95 String message = XWorkConverter.getConversionErrorMessage(propertyName, stack);
96
97 Object action = invocation.getAction();
98 if (action instanceof ValidationAware) {
99 ValidationAware va = (ValidationAware) action;
100 va.addFieldError(propertyName, message);
101 }
102
103 if (fakie == null) {
104 fakie = new HashMap();
105 }
106
107 fakie.put(propertyName, getOverrideExpr(invocation, value));
108 }
109 }
110
111 if (fakie != null) {
112 // if there were some errors, put the original (fake) values in place right before the result
113 stack.getContext().put(ORIGINAL_PROPERTY_OVERRIDE, fakie);
114 invocation.addPreResultListener(new PreResultListener() {
115 public void beforeResult(ActionInvocation invocation, String resultCode) {
116 Map fakie = (Map) invocation.getInvocationContext().get(ORIGINAL_PROPERTY_OVERRIDE);
117
118 if (fakie != null) {
119 invocation.getStack().setExprOverrides(fakie);
120 }
121 }
122 });
123 }
124 return invocation.invoke();
125 }
126
127 protected boolean shouldAddError(String propertyName, Object value) {
128 return true;
129 }
130 }