svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.library / org.gvsig.expressionevaluator / org.gvsig.expressionevaluator.lib / org.gvsig.expressionevaluator.lib.impl / src / main / java / org / gvsig / expressionevaluator / impl / function / programming / CreateFnFunction.java @ 44533
History | View | Annotate | Download (8.33 KB)
1 | 44138 | jjdelcerro | package org.gvsig.expressionevaluator.impl.function.programming; |
---|---|---|---|
2 | 43512 | jjdelcerro | |
3 | 44533 | jjdelcerro | import java.lang.reflect.Method; |
4 | 44389 | jjdelcerro | import java.util.ArrayList; |
5 | import java.util.Arrays; |
||
6 | 44138 | jjdelcerro | import java.util.List; |
7 | 44533 | jjdelcerro | import java.util.Objects; |
8 | 43512 | jjdelcerro | import org.apache.commons.lang3.Range; |
9 | 44533 | jjdelcerro | import org.apache.commons.lang3.StringUtils; |
10 | 44138 | jjdelcerro | import org.gvsig.expressionevaluator.Code; |
11 | import org.gvsig.expressionevaluator.Codes; |
||
12 | 43939 | jjdelcerro | import org.gvsig.expressionevaluator.Function; |
13 | 43521 | jjdelcerro | import org.gvsig.expressionevaluator.Interpreter; |
14 | 43512 | jjdelcerro | import org.gvsig.expressionevaluator.spi.AbstractFunction; |
15 | 44138 | jjdelcerro | import org.gvsig.expressionevaluator.ExpressionEvaluatorLocator; |
16 | import org.gvsig.expressionevaluator.ExpressionEvaluatorManager; |
||
17 | import org.gvsig.expressionevaluator.ExpressionRuntimeException; |
||
18 | import org.gvsig.expressionevaluator.MutableSymbolTable; |
||
19 | import org.gvsig.expressionevaluator.SymbolTable; |
||
20 | 44533 | jjdelcerro | import org.gvsig.tools.ToolsLocator; |
21 | import org.gvsig.tools.resourcesstorage.ResourcesStorage; |
||
22 | import org.gvsig.tools.script.Script; |
||
23 | import org.gvsig.tools.script.ScriptManager; |
||
24 | 43512 | jjdelcerro | |
25 | 44138 | jjdelcerro | public class CreateFnFunction extends AbstractFunction { |
26 | |||
27 | public static final String NAME = "CREATE_FUNCTION"; |
||
28 | 43512 | jjdelcerro | |
29 | 44138 | jjdelcerro | public CreateFnFunction() {
|
30 | super(Function.GROUP_PROGRAMMING,
|
||
31 | NAME, |
||
32 | 44533 | jjdelcerro | Range.between(2, 6), |
33 | 44098 | jjdelcerro | null,
|
34 | 44138 | jjdelcerro | null,
|
35 | null,
|
||
36 | 44098 | jjdelcerro | "Object",
|
37 | false
|
||
38 | 43939 | jjdelcerro | ); |
39 | 43512 | jjdelcerro | } |
40 | |||
41 | @Override
|
||
42 | 43939 | jjdelcerro | public boolean useArgumentsInsteadObjects() { |
43 | return true; |
||
44 | } |
||
45 | |||
46 | @Override
|
||
47 | 44138 | jjdelcerro | public boolean allowConstantFolding() { |
48 | return false; |
||
49 | } |
||
50 | |||
51 | @Override
|
||
52 | 43521 | jjdelcerro | public Object call(Interpreter interpreter, Object[] args) throws Exception { |
53 | 43939 | jjdelcerro | throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. |
54 | } |
||
55 | |||
56 | @Override
|
||
57 | 44138 | jjdelcerro | public Object call(Interpreter interpreter, Codes args) throws Exception { |
58 | // FNAME, PARAM-NAMES, BODY
|
||
59 | if( !(interpreter.getSymbolTable() instanceof MutableSymbolTable) ) { |
||
60 | throw new ExpressionRuntimeException("The use of user functions require a mutable symbol table."); |
||
61 | 43512 | jjdelcerro | } |
62 | 44138 | jjdelcerro | MutableSymbolTable symbolTable = (MutableSymbolTable) interpreter.getSymbolTable(); |
63 | |||
64 | String name;
|
||
65 | List<String> argNames; |
||
66 | 44533 | jjdelcerro | Code body = null;
|
67 | String script_path = null; |
||
68 | String script_function = null; |
||
69 | String language = null; |
||
70 | 44138 | jjdelcerro | switch(args.size()) {
|
71 | case 2: |
||
72 | name = (String) getObject(interpreter, args, 0); |
||
73 | argNames = null;
|
||
74 | body = args.get(1);
|
||
75 | break;
|
||
76 | case 3: |
||
77 | name = (String) getObject(interpreter, args, 0); |
||
78 | if( args.get(1)==null ) { |
||
79 | argNames = null;
|
||
80 | } else {
|
||
81 | argNames = (List<String>) getObject(interpreter, args, 1); |
||
82 | } |
||
83 | body = args.get(2);
|
||
84 | break;
|
||
85 | 44533 | jjdelcerro | case 6: |
86 | name = (String) getObject(interpreter, args, 0); |
||
87 | if( args.get(1)==null ) { |
||
88 | argNames = null;
|
||
89 | } else {
|
||
90 | argNames = (List<String>) getObject(interpreter, args, 1); |
||
91 | } |
||
92 | body = args.get(2);
|
||
93 | script_path = Objects.toString(args.get(2),null); |
||
94 | script_function = Objects.toString(args.get(3),null); |
||
95 | language = Objects.toString(args.get(4),null); |
||
96 | break;
|
||
97 | 44138 | jjdelcerro | default:
|
98 | throw new ExpressionRuntimeException("Incorrect number of arguments"); |
||
99 | } |
||
100 | 44533 | jjdelcerro | Function fn; |
101 | if( body!=null ) { |
||
102 | fn = new UserFunction(name, argNames, body);
|
||
103 | symbolTable.addFunction(fn); |
||
104 | return fn;
|
||
105 | } |
||
106 | if( StringUtils.isBlank(script_path) || StringUtils.isBlank(script_function) ) {
|
||
107 | throw new ExpressionRuntimeException("boydy and, script path or script function, are empty."); |
||
108 | } |
||
109 | if( StringUtils.isBlank(language) ) {
|
||
110 | language = "script";
|
||
111 | } |
||
112 | switch(language.toLowerCase()) {
|
||
113 | case "script": |
||
114 | fn = new ExternalFunction(name, script_path, script_function);
|
||
115 | symbolTable.addFunction(fn); |
||
116 | return fn;
|
||
117 | case "java": |
||
118 | fn = new JavaFunction(name, script_path, script_function);
|
||
119 | symbolTable.addFunction(fn); |
||
120 | return fn;
|
||
121 | } |
||
122 | throw new ExpressionRuntimeException("Unsupported language '"+language+"."); |
||
123 | 43512 | jjdelcerro | } |
124 | |||
125 | 44138 | jjdelcerro | private static class UserFunction extends AbstractFunction { |
126 | |||
127 | private final Code body; |
||
128 | private final List<String> argNames; |
||
129 | |||
130 | public UserFunction(String name, List<String> argNames, Code body) { |
||
131 | super(GROUP_OTHER, name, Range.between(0, Integer.MAX_VALUE)); |
||
132 | this.argNames = argNames;
|
||
133 | this.body = body;
|
||
134 | } |
||
135 | |||
136 | @Override
|
||
137 | public Object call(Interpreter interpreter, Object[] args) throws Exception { |
||
138 | Object value;
|
||
139 | ExpressionEvaluatorManager manager = ExpressionEvaluatorLocator.getManager(); |
||
140 | MutableSymbolTable localSymbolTable = manager.createSymbolTable(); |
||
141 | 44389 | jjdelcerro | |
142 | List $args = new ArrayList(); |
||
143 | if( args != null ) { |
||
144 | $args.addAll(Arrays.asList(args)); |
||
145 | } |
||
146 | localSymbolTable.setVar("$ARGS", $args); |
||
147 | |||
148 | 44138 | jjdelcerro | int max;
|
149 | if( this.argNames==null ) { |
||
150 | max = 0;
|
||
151 | } else {
|
||
152 | max = Math.min(this.argNames.size(), args.length); |
||
153 | } |
||
154 | for (int i = 0; i < max; i++) { |
||
155 | localSymbolTable.setVar(this.argNames.get(i), args[i]);
|
||
156 | } |
||
157 | SymbolTable savedSymbolTable = interpreter.getSymbolTable(); |
||
158 | localSymbolTable.addSymbolTable(savedSymbolTable); |
||
159 | try {
|
||
160 | interpreter.setSymbolTable(localSymbolTable); |
||
161 | value = interpreter.run(this.body);
|
||
162 | } finally {
|
||
163 | interpreter.setSymbolTable(savedSymbolTable); |
||
164 | } |
||
165 | return value;
|
||
166 | } |
||
167 | |||
168 | } |
||
169 | |||
170 | 44533 | jjdelcerro | private static class ExternalFunction extends AbstractFunction { |
171 | |||
172 | private final String script_path; |
||
173 | private final String script_function; |
||
174 | |||
175 | public ExternalFunction(String name, String script_path, String script_function) { |
||
176 | super(GROUP_OTHER, name, Range.between(0, Integer.MAX_VALUE)); |
||
177 | this.script_path = script_path;
|
||
178 | this.script_function = script_function;
|
||
179 | } |
||
180 | |||
181 | @Override
|
||
182 | public Object call(Interpreter interpreter, Object[] args) throws Exception { |
||
183 | ScriptManager scriptManager = ToolsLocator.getScriptManager(); |
||
184 | ExpressionEvaluatorManager expressionManager = ExpressionEvaluatorLocator.getExpressionEvaluatorManager(); |
||
185 | ResourcesStorage resourcesStorage = expressionManager.getScriptsResourcesStorage(); |
||
186 | Script sc = scriptManager.loadScript(resourcesStorage, script_path); |
||
187 | if( sc == null ) { |
||
188 | throw new ExpressionRuntimeException("Can't locate '"+this.script_path+"'."); |
||
189 | } |
||
190 | Object r = sc.invokeFunction(this.script_function, args); |
||
191 | return r;
|
||
192 | } |
||
193 | |||
194 | } |
||
195 | |||
196 | private static class JavaFunction extends AbstractFunction { |
||
197 | |||
198 | private final String fullClassName; |
||
199 | private final String methodName; |
||
200 | |||
201 | public JavaFunction(String name, String fullClassName, String methodName) { |
||
202 | super(GROUP_OTHER, name, Range.between(0, Integer.MAX_VALUE)); |
||
203 | this.fullClassName = fullClassName;
|
||
204 | this.methodName = methodName;
|
||
205 | } |
||
206 | |||
207 | @Override
|
||
208 | public Object call(Interpreter interpreter, Object[] args) throws Exception { |
||
209 | Class[] parameterTypes = new Class[args.length]; |
||
210 | for (int i = 0; i < args.length; i++) { |
||
211 | if( args[i]==null ) { |
||
212 | parameterTypes[i] = null;
|
||
213 | } else {
|
||
214 | parameterTypes[i] = args[i].getClass(); |
||
215 | } |
||
216 | } |
||
217 | Class<?> theClass = Class.forName(this.fullClassName); |
||
218 | Method method = theClass.getMethod(this.methodName, parameterTypes); |
||
219 | Object value = method.invoke(null, args); |
||
220 | return value;
|
||
221 | } |
||
222 | |||
223 | } |
||
224 | |||
225 | 43512 | jjdelcerro | } |