View Javadoc
1 /* 2 * Scope: a generic MVC framework. 3 * Copyright (c) 2000-2002, The Scope team 4 * All rights reserved. 5 * 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 14 * Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * Neither the name "Scope" nor the names of its contributors 19 * may be used to endorse or promote products derived from this software 20 * without specific prior written permission. 21 * 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 24 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 25 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 26 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR 27 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 28 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 29 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 30 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 31 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 32 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 33 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 * 35 * 36 * $Id: Accessor.java,v 1.11 2002/09/12 18:24:41 ludovicc Exp $ 37 */ 38 package org.scopemvc.model.beans; 39 40 import java.beans.IndexedPropertyDescriptor; 41 import java.beans.PropertyDescriptor; 42 import java.lang.reflect.InvocationTargetException; 43 import java.lang.reflect.Method; 44 import java.util.List; 45 import org.apache.commons.logging.Log; 46 import org.apache.commons.logging.LogFactory; 47 import org.scopemvc.core.IntIndexSelector; 48 import org.scopemvc.core.Selector; 49 import org.scopemvc.core.StringIndexSelector; 50 import org.scopemvc.util.Debug; 51 52 /*** 53 * <P> 54 * 55 * Describes a single JavaBeans accessor. Since this includes indexed 56 * properties, it might represent access into an ordered Collection, consuming 57 * two Selectors: a String one to describe the Collection and an int one to 58 * fetch the member of the List; eg "customers.0" can be traversed in one step 59 * if the parent model JavaBean has a <CODE>getCustomer(int)</CODE> method. <br> 60 * Handles java.util.List and Object[] for int indexed properties. </P> <p> 61 * 62 * Make sure to call findProperty before traverseProperty.</p> 63 * 64 * @author <A HREF="mailto:smeyfroi@users.sourceforge.net">Steve Meyfroidt</A> 65 * @created 05 September 2002 66 * @version $Revision: 1.11 $ $Date: 2002/09/12 18:24:41 $ 67 */ 68 final class Accessor { 69 70 private static final Log LOG = LogFactory.getLog(Accessor.class); 71 72 /*** 73 * Current model (changes when traverseProperty is called) 74 */ 75 Object model; 76 77 /*** 78 * Current selector (changes when traverseProperty is called) 79 */ 80 Selector selector; 81 82 /*** 83 * Original model, used for error reports 84 */ 85 Object originalModel; 86 87 /*** 88 * Original selector, used for error reports 89 */ 90 Selector originalSelector; 91 92 /*** 93 * Descriptor for the current property, either 94 * <ul> 95 * <li> IndexedPropertyDescriptor (traverse through indexed), 96 * <li> PropertyDescriptor (normal String), 97 * <li> or null (normal Integer through a List model) 98 * </ul> 99 * Populated in findProperty 100 */ 101 PropertyDescriptor descriptor; 102 103 /*** 104 * Populated in findProperty 105 */ 106 boolean isGetterIndexed; 107 108 /*** 109 * reuse this when invoking indexed properties 110 */ 111 private Object[] params = new Object[1]; 112 113 /*** 114 * Creates a new Accessor for the Selector in the model 115 * 116 * @param inModel The model object, not null 117 * @param inSelector The Selector for a property in the model, not null 118 */ 119 Accessor(Object inModel, Selector inSelector) { 120 if (inModel == null) { 121 throw new IllegalArgumentException("No model to find property for: " + selector); 122 } 123 if (inSelector == null) { 124 throw new IllegalArgumentException("No property selector defined for model: " + model); 125 } 126 originalModel = inModel; 127 originalSelector = inSelector; 128 model = inModel; 129 selector = inSelector; 130 } 131 132 133 /*** 134 * Returns a string representation of this object 135 * 136 * @return a string representation of this object 137 */ 138 public String toString() { 139 return "Accessor: original model(" + originalModel 140 + ") original selector(" + originalSelector 141 + ") current model(" + model 142 + ") current selector(" + selector 143 + ") descriptor(" + descriptor 144 + ") isGetterIndexed(" + isGetterIndexed + ")"; 145 } 146 147 148 /*** 149 * Next traversal is over the terminal property? Depends on prior call to 150 * {@link #findProperty}. 151 * 152 * @return The atTerminal value 153 */ 154 boolean isAtTerminal() { 155 if (LOG.isDebugEnabled()) { 156 LOG.debug("isAtTerminal: " + model + ", " + selector + ", " + isGetterIndexed); 157 } 158 159 return ( 160 selector == null 161 || (selector.getNext() == null) 162 || (isGetterIndexed && selector instanceof StringIndexSelector 163 && selector.getNext() instanceof IntIndexSelector 164 && selector.getNext().getNext() == null) 165 ); 166 } 167 168 169 /*** 170 * Find the next property and populate the descriptor. <br> 171 * descriptor == null if next selector is IntIndexed (ie access property 172 * through java.util.List or Object[]), else either a PropertyDescriptor or 173 * an IndexedPropertyDescriptor. 174 * 175 * @throws IllegalArgumentException if the model or the selector is null 176 * @throws NullPropertyException if the property could not be found in the 177 * model using the selector. 178 */ 179 void findProperty() throws IllegalArgumentException, NullPropertyException { 180 if (LOG.isDebugEnabled()) { 181 LOG.debug("findProperty: " + model + ", " + selector); 182 } 183 if (Debug.ON) { 184 Debug.assertTrue(selector != null, "null selector"); 185 } 186 187 if (model == null) { 188 Selector intermediateSelector = originalSelector.deepClone(); 189 intermediateSelector.removeLast(selector); 190 throw new NullPropertyException("Null property in model: " + originalModel + " with selector: " + intermediateSelector); 191 } 192 if (selector == null) { 193 throw new IllegalArgumentException("No property selector defined for model: " + model); 194 } 195 196 if (selector instanceof IntIndexSelector) { 197 descriptor = null; 198 isGetterIndexed = false; 199 } else { 200 String property = ((StringIndexSelector) selector).getIndex(); 201 descriptor = BeanInfos.getPropertyDescriptor(model.getClass(), property); 202 if (descriptor == null) { 203 throw new IllegalArgumentException("Property for selector: " + selector + 204 " could not be found in model: " + model); 205 } 206 if (descriptor instanceof IndexedPropertyDescriptor 207 && selector.getNext() instanceof IntIndexSelector 208 && ((IndexedPropertyDescriptor) descriptor).getIndexedReadMethod() != null) { 209 isGetterIndexed = true; 210 } else { 211 isGetterIndexed = false; 212 } 213 } 214 } 215 216 217 /*** 218 * Burrows down through the next accessor to the next one. If the property 219 * we return is an int-indexed property (ie accessed property from 220 * java.util.List or Object[]) then the PropertyDescriptor will be null. 221 * 222 * @throws IllegalArgumentException if the model or the selector is null 223 * @throws Exception Any other exception thrown when accessing the model 224 */ 225 void traverseProperty() throws IllegalArgumentException, Exception { 226 if (LOG.isDebugEnabled()) { 227 LOG.debug("traverseProperty: " + model + ", " + selector + ", " + descriptor); 228 } 229 230 try { 231 if (descriptor == null) { 232 // Traverse a List or array using int selector 233 if (Debug.ON) { 234 Debug.assertTrue(selector instanceof IntIndexSelector, "not IntIndexSelector: " + selector); 235 } 236 int index = ((IntIndexSelector) selector).getIndex(); 237 if (model instanceof List) { 238 model = ((List) model).get(index); 239 } else if (model instanceof Object[]) { 240 model = ((Object[]) model)[index]; 241 } else { 242 throw new IllegalArgumentException("Can't access properties using int index (expected List or Object[]): " + selector); 243 } 244 selector = selector.getNext(); 245 246 } else if (isGetterIndexed) { 247 // Traverse a javabeans indexed property using the int selector from selector.getNext() 248 if (Debug.ON) { 249 Debug.assertTrue(descriptor instanceof IndexedPropertyDescriptor, "not IndexedPropertyDescriptor: " + descriptor); 250 } 251 if (Debug.ON) { 252 Debug.assertTrue(selector instanceof StringIndexSelector, "not StringIndexSelector: " + selector); 253 } 254 if (Debug.ON) { 255 Debug.assertTrue(selector.getNext() instanceof IntIndexSelector, "not IntIndexSelector: " + selector.getNext()); 256 } 257 Method getter = ((IndexedPropertyDescriptor) descriptor).getIndexedReadMethod(); 258 params[0] = new Integer(((IntIndexSelector) selector.getNext()).getIndex()); 259 if (getter == null) { 260 throw new IllegalArgumentException("No indexed getter for: " + selector); 261 } 262 model = getter.invoke(model, params); 263 selector = selector.getNext().getNext(); 264 265 } else { 266 // Traverse a property using the String selector 267 if (Debug.ON) { 268 Debug.assertTrue(selector instanceof StringIndexSelector, "not StringIndexSelector: " + selector); 269 } 270 Method getter = descriptor.getReadMethod(); 271 if (getter == null) { 272 throw new IllegalArgumentException("No getter for: " + selector); 273 } 274 model = getter.invoke(model, null); 275 selector = selector.getNext(); 276 } 277 278 } catch (InvocationTargetException e) { 279 if (LOG.isDebugEnabled()) { 280 LOG.debug("traverseProperty: " + selector, e); 281 } 282 if (e.getTargetException() instanceof Exception) { 283 throw (Exception) e.getTargetException(); 284 } 285 throw e; 286 } catch (IllegalAccessException e1) { 287 if (LOG.isDebugEnabled()) { 288 LOG.debug("traverseProperty: no accessible getter: " + selector, e1); 289 } 290 throw e1; 291 } catch (IndexOutOfBoundsException e2) { 292 if (LOG.isDebugEnabled()) { 293 LOG.debug("traverseProperty: IndexOutOfBoundsException: " + selector, e2); 294 } 295 throw e2; 296 } catch (NullPointerException e3) { 297 if (LOG.isDebugEnabled()) { 298 LOG.debug("traverseProperty: NullPointerException: " + selector, e3); 299 } 300 throw e3; 301 } 302 } 303 } 304

This page was automatically generated by Maven