001: //--------------------------------------------------------------------------
002: // Copyright (c) 1998-2004, Drew Davidson and Luke Blanshard
003: // All rights reserved.
004: //
005: // Redistribution and use in source and binary forms, with or without
006: // modification, are permitted provided that the following conditions are
007: // met:
008: //
009: // Redistributions of source code must retain the above copyright notice,
010: // this list of conditions and the following disclaimer.
011: // Redistributions in binary form must reproduce the above copyright
012: // notice, this list of conditions and the following disclaimer in the
013: // documentation and/or other materials provided with the distribution.
014: // Neither the name of the Drew Davidson nor the names of its contributors
015: // may be used to endorse or promote products derived from this software
016: // without specific prior written permission.
017: //
018: // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
019: // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
020: // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
021: // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
022: // COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
023: // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
024: // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
025: // OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
026: // AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
027: // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
028: // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
029: // DAMAGE.
030: //--------------------------------------------------------------------------
031: package ognl;
032:
033: import java.beans.*;
034: import java.lang.reflect.*;
035:
036: /**
037: * <p>PropertyDescriptor subclass that describes an indexed set of read/write
038: * methods to get a property. Unlike IndexedPropertyDescriptor this allows
039: * the "key" to be an arbitrary object rather than just an int. Consequently
040: * it does not have a "readMethod" or "writeMethod" because it only expects
041: * a pattern like:</p>
042: *<pre>
043: * public void set<i>Property</i>(<i>KeyType</i>, <i>ValueType</i>);
044: * public <i>ValueType</i> get<i>Property</i>(<i>KeyType</i>);
045: *</pre>
046: * <p>and does not require the methods that access it as an array. OGNL can
047: * get away with this without losing functionality because if the object
048: * does expose the properties they are most probably in a Map and that case
049: * is handled by the normal OGNL property accessors.
050: *</p>
051: *<p>For example, if an object were to have methods that accessed and "attributes"
052: * property it would be natural to index them by String rather than by integer
053: * and expose the attributes as a map with a different property name:
054: *<pre>
055: * public void setAttribute(String name, Object value);
056: * public Object getAttribute(String name);
057: * public Map getAttributes();
058: *</pre>
059: *<p>Note that the index get/set is called get/set <code>Attribute</code>
060: * whereas the collection getter is called <code>Attributes</code>. This
061: * case is handled unambiguously by the OGNL property accessors because the
062: * set/get<code>Attribute</code> methods are detected by this object and the
063: * "attributes" case is handled by the <code>MapPropertyAccessor</code>.
064: * Therefore OGNL expressions calling this code would be handled in the
065: * following way:
066: *</p>
067: *<table>
068: * <tr><th>OGNL Expression</th>
069: * <th>Handling</th>
070: * </tr>
071: * <tr>
072: * <td><code>attribute["name"]</code></td>
073: * <td>Handled by an index getter, like <code>getAttribute(String)</code>.</td>
074: * </tr>
075: * <tr>
076: * <td><code>attribute["name"] = value</code></td>
077: * <td>Handled by an index setter, like <code>setAttribute(String, Object)</code>.</td>
078: * </tr>
079: * <tr>
080: * <td><code>attributes["name"]</code></td>
081: * <td>Handled by <code>MapPropertyAccessor</code> via a <code>Map.get()</code>. This
082: * will <b>not</b> go through the index get accessor.
083: * </td>
084: * </tr>
085: * <tr>
086: * <td><code>attributes["name"] = value</code></td>
087: * <td>Handled by <code>MapPropertyAccessor</code> via a <code>Map.put()</code>. This
088: * will <b>not</b> go through the index set accessor.
089: * </td>
090: * </tr>
091: * </table>
092: * @author Luke Blanshard (blanshlu@netscape.net)
093: * @author Drew Davidson (drew@ognl.org)
094: */
095: public class ObjectIndexedPropertyDescriptor extends PropertyDescriptor {
096: private Method indexedReadMethod;
097: private Method indexedWriteMethod;
098: private Class propertyType;
099:
100: public ObjectIndexedPropertyDescriptor(String propertyName,
101: Class propertyType, Method indexedReadMethod,
102: Method indexedWriteMethod) throws IntrospectionException {
103: super (propertyName, null, null);
104: this .propertyType = propertyType;
105: this .indexedReadMethod = indexedReadMethod;
106: this .indexedWriteMethod = indexedWriteMethod;
107: }
108:
109: public Method getIndexedReadMethod() {
110: return indexedReadMethod;
111: }
112:
113: public Method getIndexedWriteMethod() {
114: return indexedWriteMethod;
115: }
116:
117: public Class getPropertyType() {
118: return propertyType;
119: }
120: }
|