View Javadoc

1   /*
2    * Copyright 2004-2009 the original author or authors.
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, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package org.springmodules.validation.valang.parser;
18  
19  import java.util.HashMap;
20  import java.util.Map;
21  
22  import org.springframework.beans.BeansException;
23  import org.springframework.context.ApplicationContext;
24  import org.springframework.context.ApplicationContextAware;
25  import org.springframework.util.StringUtils;
26  import org.springmodules.validation.valang.functions.FunctionDefinition;
27  import org.springmodules.validation.valang.functions.FunctionWrapper;
28  
29  /**
30   * A simple implementation of {@link ValangBased}.
31   *
32   * @author Uri Boness
33   */
34  public class SimpleValangBased implements ApplicationContextAware, ValangBased {
35  
36      private ApplicationContext applicationContext = null;
37      private Map<String, Object> hCustomFunctions = new HashMap<String, Object>();
38      private Map dateParsers = new HashMap();
39      
40      /**
41       * Implementation of <code>ApplicationContextAware</code>.
42       */
43      public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
44          this.applicationContext = applicationContext;
45      }
46      
47      /**
48       * @see ValangBased#setCustomFunctions(java.util.Map)
49       */
50      public void setCustomFunctions(Map<String, Object> hCustomFunctions) {
51          this.hCustomFunctions = hCustomFunctions;
52      }
53  
54      /**
55       * @see ValangBased#addCustomFunction(String, String)
56       */
57      public void addCustomFunction(String functionName, String functionClassName) {
58          hCustomFunctions.put(functionName, functionClassName);
59      }
60  
61      /**
62       * @see ValangBased#setDateParsers(java.util.Map)
63       */
64      public void setDateParsers(Map parserByRegexp) {
65          dateParsers = (parserByRegexp != null) ? parserByRegexp : new HashMap();
66      }
67  
68      public Map<String, Object> getCustomFunctions() {
69          return hCustomFunctions;
70      }
71  
72      public Map getDateParsers() {
73          return dateParsers;
74      }
75  
76      /**
77       * Creates a new {@link ValangParser} that is already configured with the proper custom functions and date
78       * parsers.
79       * 
80       * @param       expression      Valang language validation expression.
81       *
82       * @return A new {@link ValangParser}.
83       */
84      public ValangParser createValangParser(String expression) {
85          return createValangParser(expression, null);
86      }
87  
88      /**
89       * Creates a new {@link ValangParser} that is already configured with the proper custom functions and date
90       * parsers and uses the class name to perform bytecode generation to avoid reflection.
91       *
92       * @param       expression      Valang language validation expression.
93       * @param       className       Name of the <code>Class</code> to generated 
94       *                              a <code>Function</code> to retrieve a property.
95       *
96       * @return A new {@link ValangParser}.
97       */
98      public ValangParser createValangParser(String expression, String className) {
99          ValangParser parser = new ValangParser(expression, className, getAllCustomFunctions(), dateParsers);
100         
101         // visitor needs context to look up bean references for functions (like a list (ex: person IN @personList))
102         if (parser.getVisitor() instanceof ApplicationContextAware) {
103             ((ApplicationContextAware)parser.getVisitor()).setApplicationContext(applicationContext);
104         }
105 
106         return parser;
107     }
108 
109     public void initValang(Object object) {
110         if (object instanceof ValangBased) {
111             ((ValangBased) object).setCustomFunctions(hCustomFunctions);
112             ((ValangBased) object).setDateParsers(dateParsers);
113         }
114     }
115 
116     /**
117      * Returns all the custom functions that can be found. This method returns all the custom functions
118      * that were explicitly registered with this instance and all custom functions that can be found in the
119      * application context (if one is set) by looking for {@link org.springmodules.validation.valang.functions.FunctionDefinition}
120      * beans.
121      *
122      * @return All the custom function that can be found.
123      */
124     public Map<String, Object> getAllCustomFunctions() {
125         Map<String, Object> functionByName = new HashMap<String, Object>();
126         
127         functionByName.putAll(findAllCustomFunctionsInApplicationContext());
128         
129         // let explicitly configured custom functions override discovered ones
130         functionByName.putAll(hCustomFunctions);
131         
132         return functionByName;
133     }
134 
135     /**
136      * Finds all <code>FunctionDefinition</code> and  <code>FunctionWrapper</code> beans 
137      * in the Spring context.
138      */
139     protected Map<String, Object> findAllCustomFunctionsInApplicationContext() {
140         Map<String, Object> hFunctions = new HashMap<String, Object>();
141 
142         if (applicationContext != null) {
143             // find FunctionDefinitions
144             String[] beanNames = applicationContext.getBeanNamesForType(FunctionDefinition.class);
145             
146             if (beanNames != null) {        
147                 for (int i = 0; i < beanNames.length; i++) {
148                     FunctionDefinition functionDefinition = (FunctionDefinition) applicationContext.getBean(beanNames[i]);
149         
150                     hFunctions.put(functionDefinition.getName(), functionDefinition.getClassName());
151                 }
152             }
153             
154             // find FunctionWrappers
155             beanNames = applicationContext.getBeanNamesForType(FunctionWrapper.class);
156             
157             if (beanNames != null) {
158                 for (int i = 0; i < beanNames.length; i++) {
159                     String beanName = beanNames[i];
160                     
161                     FunctionWrapper functionWrapper = (FunctionWrapper) applicationContext.getBean(beanName);
162                     
163                     String key = functionWrapper.getFunctionName();
164                     
165                     if (!StringUtils.hasText(key)) {
166                         key = beanName;
167                     }
168                     
169                     hFunctions.put(key, functionWrapper);
170                 }
171             }
172         }
173         
174         return hFunctions;
175     }
176 
177 }