1 /***
2 * Licensed under the Artistic License; you may not use this file
3 * except in compliance with the License.
4 * You may obtain a copy of the License at
5 *
6 * http://displaytag.sourceforge.net/license.html
7 *
8 * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
9 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
10 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
11 */
12 package org.displaytag.decorator;
13
14 import java.lang.reflect.InvocationTargetException;
15 import java.util.HashMap;
16 import java.util.Map;
17
18 import javax.servlet.jsp.PageContext;
19
20 import org.apache.commons.beanutils.PropertyUtils;
21 import org.apache.commons.lang.BooleanUtils;
22
23
24 /***
25 * <p>
26 * This class provides some basic functionality for all objects which serve as decorators for the objects in the List
27 * being displayed.
28 * <p>
29 * <p>
30 * Decorator should never be subclassed directly. Use TableDecorator instead
31 * </p>
32 * @author mraible
33 * @author Fabrizio Giustina
34 * @version $Revision: 1.15 $ ($Author: fgiust $)
35 */
36 abstract class Decorator
37 {
38
39 /***
40 * Char used to separate class name and property in the cache key.
41 */
42 private static final char CLASS_PROPERTY_SEPARATOR = '#';
43
44 /***
45 * property info cache contains classname#propertyname Strings as keys and Booleans as values.
46 */
47 private static Map propertyMap = new HashMap();
48
49 /***
50 * page context.
51 */
52 private PageContext pageContext;
53
54 /***
55 * decorated object. Usually a List
56 */
57 private Object decoratedObject;
58
59 /***
60 * Initialize the TableTecorator instance.
61 * @param context PageContext
62 * @param decorated decorated object (usually a list)
63 */
64 public void init(PageContext context, Object decorated)
65 {
66 this.pageContext = context;
67 this.decoratedObject = decorated;
68 }
69
70 /***
71 * returns the page context.
72 * @return PageContext
73 */
74 public PageContext getPageContext()
75 {
76 return this.pageContext;
77 }
78
79 /***
80 * returns the decorated object.
81 * @return Object
82 */
83 public Object getDecoratedObject()
84 {
85 return this.decoratedObject;
86 }
87
88 /***
89 * Called at the end of evaluation to clean up instance variable. A subclass of Decorator can override this method
90 * but should always call super.finish() before return
91 */
92 public void finish()
93 {
94 this.pageContext = null;
95 this.decoratedObject = null;
96 }
97
98 /***
99 * Check if a getter exists for a given property. Uses cached info if property has already been requested. This
100 * method only check for a simple property, if pPropertyName contains multiple tokens only the first part is
101 * evaluated
102 * @param propertyName name of the property to check
103 * @return boolean true if the decorator has a getter for the given property
104 */
105 public boolean hasGetterFor(String propertyName)
106 {
107 String simpleProperty = propertyName;
108
109
110 int indexOfDot = simpleProperty.indexOf('.');
111 if (indexOfDot > 0)
112 {
113 simpleProperty = simpleProperty.substring(0, indexOfDot);
114 }
115
116 Boolean cachedResult = (Boolean) propertyMap.get(getClass().getName()
117 + CLASS_PROPERTY_SEPARATOR
118 + simpleProperty);
119
120 if (cachedResult != null)
121 {
122 return cachedResult.booleanValue();
123 }
124
125
126 boolean hasGetter = searchGetterFor(propertyName);
127
128
129 propertyMap.put(getClass().getName() + CLASS_PROPERTY_SEPARATOR + simpleProperty, BooleanUtils
130 .toBooleanObject(hasGetter));
131
132
133 return hasGetter;
134
135 }
136
137 /***
138 * Looks for a getter for the given property using introspection.
139 * @param propertyName name of the property to check
140 * @return boolean true if the decorator has a getter for the given property
141 */
142 public boolean searchGetterFor(String propertyName)
143 {
144
145 Class type = null;
146
147 try
148 {
149
150
151
152 type = PropertyUtils.getPropertyType(this, propertyName);
153 }
154 catch (IllegalAccessException e)
155 {
156
157 }
158 catch (InvocationTargetException e)
159 {
160
161 }
162 catch (NoSuchMethodException e)
163 {
164
165 }
166
167 return type != null;
168
169 }
170
171 }