1 30 package com.genimen.djeneric.tools.scriptengine.core.nodes; 31 32 import java.lang.reflect.InvocationTargetException ; 33 import java.lang.reflect.Method ; 34 import java.util.ArrayList ; 35 import java.util.HashMap ; 36 37 import com.genimen.djeneric.language.Messages; 38 import com.genimen.djeneric.tools.scriptengine.core.DjScriptParserEngine; 39 import com.genimen.djeneric.tools.scriptengine.core.ParseException; 40 import com.genimen.djeneric.tools.scriptengine.core.SimpleNode; 41 import com.genimen.djeneric.tools.scriptengine.core.util.DjScriptCallable; 42 import com.genimen.djeneric.tools.scriptengine.core.util.DjScriptCompileTimeScope; 43 import com.genimen.djeneric.tools.scriptengine.core.util.DjScriptExecutionException; 44 import com.genimen.djeneric.tools.scriptengine.core.util.DjScriptExecutionTimeScope; 45 import com.genimen.djeneric.tools.scriptengine.core.util.FunctionSupport; 46 47 public class PropertyOrFunctionNode extends SimpleNode implements ValueExpression 48 { 49 public static final String FUNCTION_DETERMINED = "[function determined]"; 50 boolean _isFunction = false; 51 52 public PropertyOrFunctionNode(int i) 53 { 54 super(i); 55 } 56 57 public PropertyOrFunctionNode(DjScriptParserEngine p, int i) 58 { 59 super(p, i); 60 } 61 62 public String getName() 63 { 64 if (_isFunction) return "function"; 65 return "property"; 66 } 67 68 public String toString() 69 { 70 return getName(); 71 } 72 73 public boolean isFunction() 74 { 75 return _isFunction; 76 } 77 78 public void setFunction(boolean b) 79 { 80 _isFunction = b; 81 } 82 83 public Object getValue(DjScriptExecutionTimeScope context) throws DjScriptExecutionException 84 { 85 if (isFunction()) 86 { 87 PropertyPathNode function = (PropertyPathNode) getChild(0); 88 Object result = evalFunction(context); 89 if (function.isNegated()) 90 { 91 if (!(result instanceof Boolean )) throw new DjScriptExecutionException(Messages 92 .getString("PropertyNode.CanNotNegate"), this); 93 result = new Boolean (!((Boolean ) result).booleanValue()); 94 } 95 return result; 96 } 97 else 98 { 99 ValueExpression prop = (ValueExpression) getChild(0); 100 return prop.getValue(context); 101 } 102 } 103 104 protected Object [] getParams(DjScriptExecutionTimeScope context) throws DjScriptExecutionException 105 { 106 ArrayList paramList = new ArrayList (); 107 for (int i = 1; i < getChildCount(); i++) 108 { 109 if (!(getChild(i) instanceof ValueExpression)) 110 { 111 throw new DjScriptExecutionException(Messages.getString("PropertyOrFunctionNode.Parameter1", getChild(i)), this); 112 } 113 ValueExpression val = (ValueExpression) getChild(i); 114 paramList.add(val.getValue(context)); 115 } 116 return paramList.toArray(new Object [0]); 117 } 118 119 protected Object evalFunction(Object obj, DjScriptExecutionTimeScope context) throws Exception 120 { 121 PropertyPathNode function = (PropertyPathNode) getChild(0); 122 String path = function.getPath(); 123 124 Object result = evalFunction(obj, path, context); 125 return result; 126 } 127 128 protected Object evalFunction(Object obj, String functionName, DjScriptExecutionTimeScope context) throws Exception 129 { 130 FunctionSupport functionSupport = context.getFunctionSupport(); 131 return functionSupport.call(obj, functionName, getParams(context), context); 132 } 133 134 protected Object evalFunction(DjScriptExecutionTimeScope context) throws DjScriptExecutionException 135 { 136 try 137 { 138 PropertyPathNode function = (PropertyPathNode) getChild(0); 139 String path = function.getPath(); 140 String functionName = null; 141 142 int idx = path.lastIndexOf("."); 143 if (idx == -1) 144 { 145 functionName = path; 146 path = null; 147 } 148 else 149 { 150 functionName = path.substring(idx + 1); 151 path = path.substring(0, idx); 152 } 153 154 if (path != null) 155 { 156 Object obj = context.getPropertyValue(path, this); 157 if (obj instanceof DjScriptCallable) return evalCallable((DjScriptCallable) obj, functionName, context); 158 else return evalFunction(obj, functionName, context); 159 } 160 else 161 { 162 return context.getFunctionSupport().staticCall(functionName, getParams(context), context); 163 } 164 } 165 catch (Exception x) 166 { 167 throw new DjScriptExecutionException(x, this); 168 } 169 } 170 171 private Object evalCallable(DjScriptCallable callable, String functionName, DjScriptExecutionTimeScope context) 172 throws DjScriptExecutionException 173 { 174 Method [] ms = callable.getClass().getMethods(); 175 Method method = null; 176 177 for (int i = 0; i < ms.length; i++) 178 if (ms[i].getName().equals(functionName)) 179 { 180 method = ms[i]; 181 break; 182 } 183 184 if (method == null) throw new DjScriptExecutionException(Messages.getString("PropertyOrFunctionNode.Method", 185 functionName), this); 186 187 try 188 { 189 callable.setContext(context); 190 return method.invoke(callable, coerseArgs(method.getParameterTypes(), getParams(context))); 191 } 192 catch (InvocationTargetException e) 193 { 194 throw new DjScriptExecutionException(e.getCause(), this); 195 } 196 catch (IllegalArgumentException e) 197 { 198 throw new DjScriptExecutionException(e, this); 199 } 200 catch (IllegalAccessException e) 201 { 202 throw new DjScriptExecutionException(e, this); 203 } 204 } 205 206 private Object [] coerseArgs(Class [] classes, Object [] objects) throws DjScriptExecutionException 207 { 208 Object [] result = new Object [objects.length]; 209 210 for (int i = 0; i < classes.length && i < objects.length; i++) 211 { 212 if (objects[i] != null) 213 { 214 if (classes[i].isAssignableFrom(objects[i].getClass())) result[i] = objects[i]; 215 else throw new DjScriptExecutionException(Messages.getString("PropertyOrFunctionNode.Parameter", String 216 .valueOf(i + 1), classes[i].getName(), objects[i].getClass().getName())); 217 } 218 } 219 220 return result; 221 } 222 223 public void execute(DjScriptExecutionTimeScope ctxt) throws DjScriptExecutionException 224 { 225 getValue(ctxt); 226 } 227 228 public void translateOql(DjScriptExecutionTimeScope ctxt, StringBuffer result, HashMap parameters) 229 throws ParseException 230 { 231 if (isFunction()) 232 { 233 String pname = "param" + parameters.size(); 234 result.append(":"); 235 result.append(pname); 236 parameters.put(pname, evalFunction(ctxt)); 237 } 238 else 239 { 240 PropertyPathNode prop = (PropertyPathNode) getChild(0); 241 242 if (ctxt.isVariable(prop.getPath())) 243 { 244 String pname = "param" + parameters.size(); 245 result.append(":"); 246 result.append(pname); 247 parameters.put(pname, ctxt.getValue(prop.getPath())); 248 } 249 else result.append(prop.getPath()); 250 } 251 } 252 253 public String getFunctionName() 254 { 255 PropertyPathNode function = (PropertyPathNode) getChild(0); 256 return function.getPath(); 257 } 258 259 public boolean isNegated() 260 { 261 PropertyPathNode function = (PropertyPathNode) getChild(0); 262 return function.isNegated(); 263 } 264 265 public String getValidatedTypeName(DjScriptCompileTimeScope context) throws DjScriptExecutionException 266 { 267 if (isFunction()) 268 { 269 boolean isOk = false; 270 271 String fname = getFunctionName(); 272 int idx = fname.lastIndexOf("."); 273 if (idx == -1) isOk = context.getFunctionSupport().isStaticCall(getFunctionName()); 274 else 275 { 276 String path = fname.substring(0, idx); 277 if (context.isKnownJavaBean(path)) isOk = true; 278 else isOk = context.getFunctionSupport().isCall(getFunctionName()); 279 } 280 281 if (!isOk) throw new DjScriptExecutionException("Function " + getFunctionName() + " not defined", this); 282 283 return FUNCTION_DETERMINED; 284 } 285 ValueExpression prop = (ValueExpression) getChild(0); 286 return prop.getValidatedTypeName(context); 287 } 288 289 public void validateScript(DjScriptCompileTimeScope ctxt) throws DjScriptExecutionException 290 { 291 getValidatedTypeName(ctxt); 292 super.validateScript(ctxt); 293 } 294 295 } | Popular Tags |