View Javadoc
1 /*** 2 * AccessorOperator.java 3 * 4 * $Author: mballesteros $ 5 * $Date: 2003/11/28 19:18:03 $ 6 * $Revision: 1.1 $ 7 */ 8 package net.sf.jec; 9 10 import java.lang.reflect.InvocationTargetException; 11 import java.lang.reflect.Method; 12 import java.util.Map; 13 14 import net.sf.jec.util.XMLHelper; 15 16 import org.apache.commons.beanutils.PropertyUtils; 17 import org.w3c.dom.Element; 18 19 /*** 20 * This operator returns/sets a property of the context object. The actual 21 * "property" definition depends on the context object class: 22 * <ul> 23 * <li>For a Map, a property is just an entry, being the property name the key 24 * and the property value the associated key value.</li> 25 * <li>For a bean, a property is anything acccessible through a getter/setter 26 * methods</li> 27 * <li>For a DOM element, a property is a named child and its value the child's 28 * content</li> 29 * </ul> 30 * 31 * @author mballesteros 32 */ 33 public class AccessorOperator extends InvertibleOperator { 34 35 private String field; 36 private Getter getter; 37 private Setter setter; 38 private boolean throwExceptions; 39 40 /*** 41 * Creates a new AccessorOperator that will try to get and set the 42 * <code>field</code> property of the context 43 * 44 * @param field The field that will be accessed 45 * @param throwExceptions 46 */ 47 public AccessorOperator(String field, boolean throwExceptions) { 48 super(); 49 this.field = field; 50 this.throwExceptions = throwExceptions; 51 } 52 53 /*** 54 * Creates a new AccessorOperator that will try to get and set the 55 * <code>field</code> property of the context 56 * 57 * @param field The field that will be accessed 58 * @param nestedOp The nested operator 59 * @param throwExceptions 60 */ 61 public AccessorOperator( 62 String field, 63 Operator nestedOp, 64 boolean throwExceptions) { 65 super(nestedOp); 66 this.field = field; 67 this.throwExceptions = throwExceptions; 68 } 69 70 /*** 71 * Returns a function representation String for this operator 72 * 73 * @return A String representation in a Function like style 74 */ 75 public String toFunctionString() { 76 return "Accessor('" 77 + field 78 + "'" 79 + (nestedOp == null ? "" : ", " + nestedOp) 80 + ")"; 81 } 82 83 /*** 84 * Returns an expression String representation for this operator 85 * @return A String representation in an expression like style 86 */ 87 public String toExpressionString() { 88 return (nestedOp == null ? "" : nestedOp + ".") + field; 89 } 90 91 /*** 92 * Returns the associated value to the given context and root context 93 * @param rootCtx The root context, needed for operators that require 94 * expression evaluation from root point. Example: Indexer operators 95 * @param ctx The current context where the operator will work over 96 * @return The direct mapping of this operator on the given context 97 * @throws EvaluationException Thrown if there's an evaluation problem 98 */ 99 protected Object directMap(Object rootCtx, Object ctx) 100 throws EvaluationException { 101 if (getter == null) 102 getter = getGetter(ctx, field); 103 return getter.getField(ctx, field); 104 } 105 106 /*** 107 * Sets the given value if this operator is at the end of the operator chain 108 * or just resolves the context object and passes it to the next operator in 109 * the chain. 110 * @param rootCtx The root context, needed for operators that require 111 * expression evaluation from root point. Example: Indexer operators 112 * @param ctx The current context where the operator will work over 113 * @param value The value to set. 114 * @throws EvaluationException Thrown if there's an evaluation problem 115 */ 116 protected void inverseMap(Object rootCtx, Object ctx, Object value) 117 throws EvaluationException { 118 if (setter == null) 119 setter = getSetter(ctx, field, value); 120 setter.setField(ctx, field, value); 121 } 122 123 //========================================================================= 124 // Helper classes... 125 //========================================================================= 126 interface Getter { 127 public Object getField(Object ctx, String field) 128 throws EvaluationException; 129 } 130 131 interface Setter { 132 public void setField(Object ctx, String field, Object value) 133 throws EvaluationException; 134 } 135 136 //========================================================================= 137 // GETTERS 138 Getter getGetter(Object obj, String fieldname) throws EvaluationException { 139 if (obj instanceof Map) { 140 return new MapGetter(); 141 } else if (obj instanceof Element) { 142 return new ElementGetter(); 143 } else { 144 Method getter; 145 try { 146 getter = 147 PropertyUtils.getReadMethod( 148 PropertyUtils.getPropertyDescriptor(obj, fieldname)); 149 return new AccessorOperator.BeanGetter(getter); 150 } catch (IllegalAccessException e) { 151 // Do nothing 152 } catch (InvocationTargetException e) { 153 // Do nothing 154 } catch (NoSuchMethodException e) { 155 // Do nothing 156 } 157 if (throwExceptions) { 158 throw new EvaluationException( 159 "Cannot find getter for property '" 160 + fieldname 161 + "' in class: " 162 + obj.getClass().getName()); 163 } else { 164 return new NullGetter(); 165 } 166 } 167 } 168 169 class NullGetter implements Getter { 170 public Object getField(Object ctx, String field) 171 throws EvaluationException { 172 return null; 173 } 174 } 175 176 class MapGetter implements Getter { 177 public Object getField(Object ctx, String field) 178 throws EvaluationException { 179 return ((Map) ctx).get(field); 180 } 181 } 182 183 class ElementGetter implements Getter { 184 public Object getField(Object ctx, String field) 185 throws EvaluationException { 186 if (field.charAt(0) == '@') { 187 return ((Element) ctx).getAttribute(field.substring(1)); 188 } else { 189 if (field.equals("_text")) { 190 return XMLHelper.getText((Element) ctx); 191 } else { 192 return XMLHelper.getChild((Element) ctx, field); 193 } 194 } 195 } 196 } 197 198 class BeanGetter implements Getter { 199 private Method method; 200 public BeanGetter(Method method) { 201 this.method = method; 202 } 203 public Object getField(Object ctx, String field) 204 throws EvaluationException { 205 try { 206 return ObjectConverter.normalize(method.invoke(ctx, null)); 207 } catch (Exception e) { 208 if (throwExceptions) 209 throw new EvaluationException( 210 "Error invokating method: " + e.getMessage()); 211 else 212 return null; 213 } 214 } 215 } 216 217 //========================================================================= 218 // SETTERS 219 Setter getSetter(Object obj, String fieldname, Object fieldvalue) 220 throws EvaluationException { 221 if (obj instanceof Map) { 222 return new HashMapSetter(); 223 } else if (obj instanceof Element) { 224 return new ElementSetter(); 225 } else { 226 Method setter; 227 try { 228 setter = 229 PropertyUtils.getWriteMethod( 230 PropertyUtils.getPropertyDescriptor(obj, fieldname)); 231 return new AccessorOperator.BeanSetter(setter); 232 } catch (IllegalAccessException e) {} catch (InvocationTargetException e) {} catch (NoSuchMethodException e) {} 233 if (throwExceptions) { 234 throw new EvaluationException( 235 "Cannot find setter for property '" 236 + fieldname 237 + "' in class: " 238 + obj.getClass().getName()); 239 } else { 240 return null; 241 } 242 } 243 } 244 245 class HashMapSetter implements Setter { 246 public void setField(Object ctx, String field, Object value) 247 throws EvaluationException { 248 ((Map) ctx).put(field, value); 249 } 250 } 251 252 class ElementSetter implements Setter { 253 public void setField(Object ctx, String field, Object value) 254 throws EvaluationException { 255 if (field.charAt(0) == '@') { 256 ((Element) ctx).setAttribute( 257 field.substring(1), 258 value.toString()); 259 } else { 260 if (field.equals("_text")) { 261 XMLHelper.setText((Element) ctx, value.toString()); 262 } else { 263 XMLHelper.setChild((Element) ctx, field, value); 264 } 265 } 266 } 267 } 268 269 class BeanSetter implements Setter { 270 private Method method; 271 private Class targetClass; 272 private int conversionType; 273 274 public BeanSetter(Method method) { 275 this.method = method; 276 this.targetClass = method.getParameterTypes()[0]; 277 } 278 public BeanSetter(Method method, Class targetClass) { 279 this.method = method; 280 this.targetClass = targetClass; 281 } 282 283 public void setField(Object ctx, String field, Object value) 284 throws EvaluationException { 285 try { 286 value = ObjectConverter.convert(value, targetClass); 287 method.invoke(ctx, new Object[] { value }); 288 } catch (Exception e) { 289 if (throwExceptions) 290 throw new EvaluationException( 291 "Error invokating method: " + e.getMessage()); 292 } 293 } 294 } 295 }

This page was automatically generated by Maven