View Javadoc

1   /*
2    * Copyright 2002-2004 The Apache Software Foundation
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  package org.apache.commons.clazz.reflect.common;
17  
18  import java.lang.reflect.Method;
19  import java.util.Iterator;
20  import java.util.Map;
21  
22  import org.apache.commons.clazz.reflect.ReflectedClazz;
23  
24  /**
25   * A ReflectedPropertyIntrospector that discovers list (aka indexed) properties.
26   * 
27   * @author <a href="mailto:dmitri@apache.org">Dmitri Plotnikov</a>
28   * @version $Id: ReflectedListPropertyIntrospectorSupport.java 155436 2005-02-26 13:17:48Z dirkv $
29   */
30  public abstract class ReflectedListPropertyIntrospectorSupport
31      extends ReflectedPropertyIntrospectorSupport 
32  {
33      protected static final AccessorMethodParser READ_METHOD_PARSER =
34          new ReadAccessorMethodParser();
35  
36      protected static final AccessorMethodParser WRITE_METHOD_PARSER =
37          new WriteAccessorMethodParser();
38  
39      protected static final AccessorMethodParser GET_METHOD_PARSER =
40          new GetAccessorMethodParser();
41  
42      protected static final AccessorMethodParser SET_METHOD_PARSER =
43          new SetAccessorMethodParser();
44  
45      protected AccessorMethodParser getReadAccessMethodParser() {
46          return READ_METHOD_PARSER;  
47      }
48      
49      protected AccessorMethodParser getWriteAccessMethodParser() {
50          return WRITE_METHOD_PARSER;  
51      }
52      
53      protected AccessorMethodParser getGetAccessMethodParser() {
54          return GET_METHOD_PARSER;  
55      }
56      
57      protected AccessorMethodParser getSetAccessMethodParser() {
58          return SET_METHOD_PARSER;  
59      }
60      
61      /**
62       * Finds a ReflectedListPropertyParseResults for the given
63       * propertyName or creates a new one and puts it in the map.
64       */
65      protected ReflectedListPropertyParseResults getParseResults(
66              ReflectedClazz clazz,
67              Map parseResultMap,
68              String propertyName) 
69      {
70          ReflectedListPropertyParseResults parseResults =
71              (ReflectedListPropertyParseResults) parseResultMap.get(
72                  propertyName);
73          if (parseResults == null) {
74              parseResults =
75                  new ReflectedListPropertyParseResults(clazz, propertyName);
76              parseResultMap.put(propertyName, parseResults);
77          }
78          return parseResults;
79      }
80  
81      /**
82       * Combines data collected from singular methods like
83       * <code>getFoo(index)</code> with Properties, which already
84       * contain data about plural methods like <code>getFooList()</code>.
85       */
86      protected void mergeSingularMethods(
87              Map parseResultMapPlural, Map parseResultMapSingular)
88      {
89          Iterator iter = parseResultMapSingular.values().iterator();
90          while (iter.hasNext()) {
91  
92              ReflectedListPropertyParseResults singular =
93                  (ReflectedListPropertyParseResults) iter.next();
94  
95              ReflectedListPropertyParseResults plural =
96                  findBySingularName(
97                          parseResultMapPlural, singular.getPropertyName());
98  
99              if (plural != null) {
100                 plural.merge(singular);
101             }
102             else {
103                 // We don't have any plural methods - let's just use
104                 // the singular ones then
105                 parseResultMapPlural.put(singular.getPropertyName(), singular);
106             }
107         }
108     }
109     
110     /**
111      * Given a singular form of a property name, locates parse results
112      * for a property with the corresponding plural name.
113      */
114     protected ReflectedListPropertyParseResults findBySingularName(
115             Map parseResultMapPlural,
116             String singularName)
117     {
118         ReflectedListPropertyParseResults plural =
119             (ReflectedListPropertyParseResults)
120                 parseResultMapPlural.get(singularName);
121         if (plural != null) {
122             return plural;
123         }
124 
125         Iterator iter = parseResultMapPlural.entrySet().iterator();
126         while (iter.hasNext()) {
127             Map.Entry entry = (Map.Entry) iter.next();
128             if (isCorrectPluralForm(singularName, (String) entry.getKey())) {
129                 return (ReflectedListPropertyParseResults) entry.getValue();
130             }
131         }
132         return null;
133     }
134     
135     /**
136      * Creates a new ReflectedListProperty based on parse results. 
137      */
138     protected ReflectedAccessorPairProperty createProperty(
139         ReflectedClazz clazz,
140         ReflectedPropertyParseResults parseResults)
141     {
142         ReflectedListProperty property =
143             new ReflectedListProperty(clazz, parseResults.getPropertyName());
144 
145         ReflectedListPropertyParseResults parseResultsList =
146                 (ReflectedListPropertyParseResults) parseResults;
147         
148         property.setAliases(parseResultsList.getAliases());
149         property.setType(parseResultsList.getPropertyType());
150         property.setContentType(parseResultsList.getContentType());
151         property.setReadMethod(parseResultsList.getReadMethod());
152         property.setWriteMethod(parseResultsList.getWriteMethod());
153         property.setGetMethod(parseResultsList.getGetMethod());
154         property.setSetMethod(parseResultsList.getSetMethod());
155         property.setAddMethod(parseResultsList.getAddMethod());
156         property.setAddIndexedMethod(parseResultsList.getAddIndexedMethod());
157         property.setRemoveMethod(parseResultsList.getRemoveMethod());
158         property.setRemoveIndexedMethod(
159             parseResultsList.getRemoveIndexedMethod());
160         property.setSizeMethod(parseResultsList.getSizeMethod());
161         return property;
162     }
163     /**
164      * Parser for the <code>getFooMap()</code> method:
165      * <ul>
166      *  <li>Return type not void</li>
167      *  <li>Name starts with "get" followed by capitalized property name</li>
168      *  <li>No parameters</li>
169      * </ul>
170      * 
171      * We don't check if the parameter is a List here. If it is not,
172      * we want to recognize the method and them mark the corresponding
173      * property as NotAProperty.
174      */
175     public static class ReadAccessorMethodParser extends AccessorMethodParser {
176         protected boolean testReturnType(Class returnType) {
177             return !returnType.equals(Void.TYPE);
178         }
179         protected String requiredPrefix() {
180             return "get";
181         }
182         protected int requiredParameterCount() {
183             return 0;
184         }
185         protected Class getValueType(Method method) {
186             return method.getReturnType();
187         }
188     }
189             
190     /**
191      * Parser for the <code>setFooList(List)</code> method:
192      * <ul>
193      *  <li>Return type void</li>
194      *  <li>Name starts with "set" followed by capitalized property name</li>
195      *  <li>One parameter</li>
196      * </ul>
197      * 
198      * We don't check if the parameter is a List here. If it is not,
199      * we want to recognize the method and them mark the corresponding
200      * property as NotAProperty.
201      */      
202     public static class WriteAccessorMethodParser extends AccessorMethodParser {
203         protected boolean testReturnType(Class returnType) {
204             return returnType.equals(Void.TYPE);
205         }
206         protected int requiredParameterCount() {
207             return 1;
208         }
209         protected String requiredPrefix() {
210             return "set";
211         }
212         protected Class getValueType(Method method) {
213             return method.getParameterTypes()[0];
214         }
215     }
216             
217     /**
218      * Parser for the <code>getFoo(int)</code> method:
219      * <ul>
220      *  <li>Return type not void</li>
221      *  <li>Name starts with "get" followed by capitalized singular
222      *      form of the property name</li>
223      *  <li>One integer parameter</li>
224      * </ul>
225      */            
226     public static class GetAccessorMethodParser extends AccessorMethodParser {
227         protected boolean testReturnType(Class returnType) {
228             return !returnType.equals(Void.TYPE);
229         }
230         protected String requiredPrefix() {
231             return "get";
232         }
233         protected int requiredParameterCount() {
234             return 1;
235         }
236         protected boolean testParameterType(int index, Class parameterType) {
237             return parameterType.equals(Integer.TYPE);
238         }
239         protected Class getValueType(Method method) {
240             return method.getReturnType();
241         }
242     }
243              
244     /**
245      * Parser for the <code>setFoo(index, value)</code> method:
246      * <ul>
247      *  <li>Return type void</li>
248      *  <li>Name starts with "set" followed by capitalized singular
249      *      form of the property name</li>
250      *  <li>Two parameters, first integer</li>
251      * </ul>
252      */                        
253     public static class SetAccessorMethodParser extends AccessorMethodParser {
254         protected String requiredPrefix() {
255             return "set";
256         }
257         protected int requiredParameterCount() {
258             return 2;
259         }
260         protected boolean testParameterType(int index, Class parameterType) {
261             if (index == 0) {            
262                 return parameterType.equals(Integer.TYPE);
263             }
264             return true;
265         }
266         protected Class getValueType(Method method) {
267             return method.getParameterTypes()[1];
268         }
269     }
270 
271 }