Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
ObjectIndexedPropertyDescriptor |
|
| 4.0;4 |
1 | package org.apache.commons.ognl; | |
2 | ||
3 | /* | |
4 | * Licensed to the Apache Software Foundation (ASF) under one | |
5 | * or more contributor license agreements. See the NOTICE file | |
6 | * distributed with this work for additional information | |
7 | * regarding copyright ownership. The ASF licenses this file | |
8 | * to you under the Apache License, Version 2.0 (the | |
9 | * "License"); you may not use this file except in compliance | |
10 | * with the License. You may obtain a copy of the License at | |
11 | * | |
12 | * http://www.apache.org/licenses/LICENSE-2.0 | |
13 | * | |
14 | * Unless required by applicable law or agreed to in writing, | |
15 | * software distributed under the License is distributed on an | |
16 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |
17 | * KIND, either express or implied. See the License for the | |
18 | * specific language governing permissions and limitations | |
19 | * under the License. | |
20 | */ | |
21 | ||
22 | import java.beans.IntrospectionException; | |
23 | import java.beans.PropertyDescriptor; | |
24 | import java.lang.reflect.Method; | |
25 | ||
26 | /** | |
27 | * <p> | |
28 | * PropertyDescriptor subclass that describes an indexed set of read/write methods to get a property. Unlike | |
29 | * IndexedPropertyDescriptor this allows the "key" to be an arbitrary object rather than just an int. Consequently it | |
30 | * does not have a "readMethod" or "writeMethod" because it only expects a pattern like: | |
31 | * </p> | |
32 | * | |
33 | * <pre> | |
34 | * public void set<i>Property</i>(<i>KeyType</i>, <i>ValueType</i>); | |
35 | * public <i>ValueType</i> get<i>Property</i>(<i>KeyType</i>); | |
36 | * </pre> | |
37 | * <p> | |
38 | * and does not require the methods that access it as an array. OGNL can get away with this without losing functionality | |
39 | * because if the object does expose the properties they are most probably in a Map and that case is handled by the | |
40 | * normal OGNL property accessors. | |
41 | * </p> | |
42 | * <p> | |
43 | * For example, if an object were to have methods that accessed and "attributes" property it would be natural to index | |
44 | * them by String rather than by integer and expose the attributes as a map with a different property name: | |
45 | * | |
46 | * <pre> | |
47 | * public void setAttribute( String name, Object value ); | |
48 | * | |
49 | * public Object getAttribute( String name ); | |
50 | * | |
51 | * public Map getAttributes(); | |
52 | * </pre> | |
53 | * <p> | |
54 | * Note that the index get/set is called get/set <code>Attribute</code> whereas the collection getter is called | |
55 | * <code>Attributes</code>. This case is handled unambiguously by the OGNL property accessors because the set/get | |
56 | * <code>Attribute</code> methods are detected by this object and the "attributes" case is handled by the | |
57 | * <code>MapPropertyAccessor</code>. Therefore OGNL expressions calling this code would be handled in the following way: | |
58 | * </p> | |
59 | * <table> | |
60 | * <tr> | |
61 | * <th>OGNL Expression</th> | |
62 | * <th>Handling</th> | |
63 | * </tr> | |
64 | * <tr> | |
65 | * <td><code>attribute["name"]</code></td> | |
66 | * <td>Handled by an index getter, like <code>getAttribute(String)</code>.</td> | |
67 | * </tr> | |
68 | * <tr> | |
69 | * <td><code>attribute["name"] = value</code></td> | |
70 | * <td>Handled by an index setter, like <code>setAttribute(String, Object)</code>.</td> | |
71 | * </tr> | |
72 | * <tr> | |
73 | * <td><code>attributes["name"]</code></td> | |
74 | * <td>Handled by <code>MapPropertyAccessor</code> via a <code>Map.get()</code>. This will <b>not</b> go through the | |
75 | * index get accessor.</td> | |
76 | * </tr> | |
77 | * <tr> | |
78 | * <td><code>attributes["name"] = value</code></td> | |
79 | * <td>Handled by <code>MapPropertyAccessor</code> via a <code>Map.put()</code>. This will <b>not</b> go through the | |
80 | * index set accessor.</td> | |
81 | * </tr> | |
82 | * </table> | |
83 | * | |
84 | * @author Luke Blanshard (blanshlu@netscape.net) | |
85 | * @author Drew Davidson (drew@ognl.org) | |
86 | */ | |
87 | public class ObjectIndexedPropertyDescriptor | |
88 | extends PropertyDescriptor | |
89 | { | |
90 | private Method indexedReadMethod; | |
91 | ||
92 | private Method indexedWriteMethod; | |
93 | ||
94 | private Class<?> propertyType; | |
95 | ||
96 | public ObjectIndexedPropertyDescriptor( String propertyName, Class<?> propertyType, Method indexedReadMethod, | |
97 | Method indexedWriteMethod ) | |
98 | throws IntrospectionException | |
99 | { | |
100 | 21 | super( propertyName, null, null ); |
101 | 21 | this.propertyType = propertyType; |
102 | 21 | this.indexedReadMethod = indexedReadMethod; |
103 | 21 | this.indexedWriteMethod = indexedWriteMethod; |
104 | 21 | } |
105 | ||
106 | public Method getIndexedReadMethod() | |
107 | { | |
108 | 30 | return indexedReadMethod; |
109 | } | |
110 | ||
111 | public Method getIndexedWriteMethod() | |
112 | { | |
113 | 8 | return indexedWriteMethod; |
114 | } | |
115 | ||
116 | @Override | |
117 | public Class<?> getPropertyType() | |
118 | { | |
119 | 0 | return propertyType; |
120 | } | |
121 | ||
122 | @Override | |
123 | public boolean equals(Object o) { | |
124 | 0 | if (this == o) |
125 | { | |
126 | 0 | return true; |
127 | } | |
128 | ||
129 | 0 | if (!(o instanceof ObjectIndexedPropertyDescriptor)) |
130 | { | |
131 | 0 | return false; |
132 | } | |
133 | ||
134 | 0 | if (!super.equals(o)) |
135 | { | |
136 | 0 | return false; |
137 | } | |
138 | ||
139 | 0 | ObjectIndexedPropertyDescriptor that = (ObjectIndexedPropertyDescriptor) o; |
140 | ||
141 | 0 | if (indexedReadMethod != null ? !indexedReadMethod.equals(that.indexedReadMethod) : that.indexedReadMethod != null) |
142 | { | |
143 | 0 | return false; |
144 | } | |
145 | ||
146 | 0 | if (indexedWriteMethod != null ? !indexedWriteMethod.equals(that.indexedWriteMethod) : that.indexedWriteMethod != null) |
147 | { | |
148 | 0 | return false; |
149 | } | |
150 | ||
151 | 0 | if (propertyType != null ? !propertyType.equals(that.propertyType) : that.propertyType != null) |
152 | { | |
153 | 0 | return false; |
154 | } | |
155 | ||
156 | 0 | return true; |
157 | } | |
158 | ||
159 | @Override | |
160 | public int hashCode() { | |
161 | 0 | int result = super.hashCode(); |
162 | 0 | result = 31 * result + (indexedReadMethod != null ? indexedReadMethod.hashCode() : 0); |
163 | 0 | result = 31 * result + (indexedWriteMethod != null ? indexedWriteMethod.hashCode() : 0); |
164 | 0 | result = 31 * result + (propertyType != null ? propertyType.hashCode() : 0); |
165 | 0 | return result; |
166 | } | |
167 | } |