View Javadoc
1   /*
2    * #%L
3    * Nuiton Validator
4    * %%
5    * Copyright (C) 2013 - 2014 Code Lutin, Tony Chemit
6    * %%
7    * This program is free software: you can redistribute it and/or modify
8    * it under the terms of the GNU Lesser General Public License as 
9    * published by the Free Software Foundation, either version 3 of the 
10   * License, or (at your option) any later version.
11   * 
12   * This program is distributed in the hope that it will be useful,
13   * but WITHOUT ANY WARRANTY; without even the implied warranty of
14   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15   * GNU General Lesser Public License for more details.
16   * 
17   * You should have received a copy of the GNU General Lesser Public 
18   * License along with this program.  If not, see
19   * <http://www.gnu.org/licenses/lgpl-3.0.html>.
20   * #L%
21   */
22  package org.nuiton.validator.xwork2.field;
23  
24  import com.opensymphony.xwork2.util.ValueStack;
25  import com.opensymphony.xwork2.validator.ValidationException;
26  import com.opensymphony.xwork2.validator.validators.FieldExpressionValidator;
27  import org.apache.commons.logging.Log;
28  import org.apache.commons.logging.LogFactory;
29  import org.nuiton.converter.ConverterUtil;
30  
31  import java.util.Map;
32  import java.util.StringTokenizer;
33  import java.util.TreeMap;
34  import java.util.regex.Matcher;
35  import java.util.regex.Pattern;
36  
37  /**
38   * Extends {@link FieldExpressionValidator} to add some extra parameters available
39   * in the {@link #getExpression()}
40   *
41   * @author Tony Chemit - chemit@codelutin.com
42   * @since 1.3
43   */
44  public class FieldExpressionWithParamsValidator extends NuitonFieldExpressionValidator {
45  
46      private static final Log log = LogFactory.getLog(FieldExpressionWithParamsValidator.class);
47  
48      protected static final Pattern EXTRA_BOOLEAN_PARAM_ENTRY_PATTERN = Pattern.compile("(\\w+)\\:(false|true)");
49  
50      protected static final Pattern EXTRA_SHORT_PARAM_ENTRY_PATTERN = Pattern.compile("(\\w+)\\:(-\\d+|\\d+)");
51  
52      protected static final Pattern EXTRA_INT_PARAM_ENTRY_PATTERN = Pattern.compile("(\\w+)\\:(-\\d+|\\d+)");
53  
54      protected static final Pattern EXTRA_LONG_PARAM_ENTRY_PATTERN = Pattern.compile("(\\w+)\\:(-\\d+|\\d+)");
55  
56      protected static final Pattern EXTRA_DOUBLE_PARAM_ENTRY_PATTERN = Pattern.compile("(\\w+)\\:(-\\d+\\.\\d+|\\d+\\.\\d+)");
57  
58      protected static final Pattern EXTRA_STRING_PARAM_ENTRY_PATTERN = Pattern.compile("(\\w+)\\:(.+)");
59  
60      protected ValueStack stack;
61  
62      protected String booleanParams;
63  
64      protected String shortParams;
65  
66      protected String intParams;
67  
68      protected String longParams;
69  
70      protected String doubleParams;
71  
72      protected String stringParams;
73  
74      protected Map<String, Boolean> booleans;
75  
76      protected Map<String, Short> shorts;
77  
78      protected Map<String, Integer> ints;
79  
80      protected Map<String, Long> longs;
81  
82      protected Map<String, Double> doubles;
83  
84      protected Map<String, String> strings;
85  
86      public String getBooleanParams() {
87          return booleanParams;
88      }
89  
90      public void setBooleanParams(String booleanParams) {
91          this.booleanParams = booleanParams;
92      }
93  
94      public String getDoubleParams() {
95          return doubleParams;
96      }
97  
98      public void setDoubleParams(String doubleParams) {
99          this.doubleParams = doubleParams;
100     }
101 
102     public String getIntParams() {
103         return intParams;
104     }
105 
106     public void setIntParams(String intParams) {
107         this.intParams = intParams;
108     }
109 
110     public String getLongParams() {
111         return longParams;
112     }
113 
114     public void setLongParams(String longParams) {
115         this.longParams = longParams;
116     }
117 
118     public String getShortParams() {
119         return shortParams;
120     }
121 
122     public void setShortParams(String shortParams) {
123         this.shortParams = shortParams;
124     }
125 
126     public String getStringParams() {
127         return stringParams;
128     }
129 
130     public void setStringParams(String stringParams) {
131         this.stringParams = stringParams;
132     }
133 
134     public Map<String, Boolean> getBooleans() {
135         return booleans;
136     }
137 
138     public Map<String, Double> getDoubles() {
139         return doubles;
140     }
141 
142     public Map<String, Integer> getInts() {
143         return ints;
144     }
145 
146     public Map<String, Long> getLongs() {
147         return longs;
148     }
149 
150     public Map<String, Short> getShorts() {
151         return shorts;
152     }
153 
154     public Map<String, String> getStrings() {
155         return strings;
156     }
157 
158     @Override
159     public String getValidatorType() {
160         return "fieldexpressionwithparams";
161     }
162 
163     @Override
164     public void setValueStack(ValueStack stack) {
165         super.setValueStack(stack);
166         this.stack = stack;
167     }
168 
169     @Override
170     public void validate(Object object) throws ValidationException {
171         super.validate(object);
172     }
173 
174     @Override
175     public void validateWhenNotSkip(Object object) throws ValidationException {
176 
177         booleans = initParams(Boolean.class, booleanParams, EXTRA_BOOLEAN_PARAM_ENTRY_PATTERN);
178         shorts = initParams(Short.class, shortParams, EXTRA_SHORT_PARAM_ENTRY_PATTERN);
179         ints = initParams(Integer.class, intParams, EXTRA_INT_PARAM_ENTRY_PATTERN);
180         longs = initParams(Long.class, longParams, EXTRA_LONG_PARAM_ENTRY_PATTERN);
181         doubles = initParams(Double.class, doubleParams, EXTRA_DOUBLE_PARAM_ENTRY_PATTERN);
182         strings = initParams(String.class, stringParams, EXTRA_STRING_PARAM_ENTRY_PATTERN);
183 
184         boolean pop = false;
185         if (!stack.getRoot().contains(this)) {
186             stack.push(this);
187             pop = true;
188         }
189 
190         try {
191             super.validateWhenNotSkip(object);
192         } finally {
193             if (pop) {
194                 stack.pop();
195             }
196         }
197 
198     }
199 
200     protected <T> Map<String, T> initParams(Class<T> klass, String extraParams, Pattern pattern) throws ValidationException {
201 
202         if (extraParams == null || extraParams.isEmpty()) {
203             // not using
204             return null;
205         }
206 
207         StringTokenizer stk = new StringTokenizer(extraParams, "|");
208         Map<String, T> result = new TreeMap<String, T>();
209         while (stk.hasMoreTokens()) {
210             String entry = stk.nextToken();
211             Matcher matcher = pattern.matcher(entry);
212             if (!matcher.matches()) {
213                 throw new ValidationException("could not parse for extra params " + extraParams + " for type " + klass.getName());
214             }
215             String paramName = matcher.group(1);
216             String paramValueStr = matcher.group(2);
217             T paramValue = ConverterUtil.convert(klass, paramValueStr);
218             if (log.isDebugEnabled()) {
219                 log.debug("detected extra param : <type:" + klass + ", name:" + paramName + ", value:" + paramValue + ">");
220             }
221             result.put(paramName, paramValue);
222         }
223         return result;
224     }
225 }