Statistics
| Revision:

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 @ 44592

History | View | Annotate | Download (8.66 KB)

1
package org.gvsig.expressionevaluator.impl.function.programming;
2

    
3
import java.lang.reflect.Method;
4
import java.util.ArrayList;
5
import java.util.Arrays;
6
import java.util.List;
7
import java.util.Objects;
8
import org.apache.commons.lang3.Range;
9
import org.apache.commons.lang3.StringUtils;
10
import org.gvsig.expressionevaluator.Code;
11
import org.gvsig.expressionevaluator.Codes;
12
import org.gvsig.expressionevaluator.Function;
13
import org.gvsig.expressionevaluator.Interpreter;
14
import org.gvsig.expressionevaluator.spi.AbstractFunction;
15
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
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

    
25
public class CreateFnFunction extends AbstractFunction {
26
    
27
    public static final String NAME = "CREATE_FUNCTION";
28

    
29
    public CreateFnFunction() {
30
        super(Function.GROUP_PROGRAMMING, 
31
                NAME, 
32
                Range.between(2, 6),
33
                null,
34
                null,
35
                null,
36
                "Object",
37
                false
38
        );
39
    }
40

    
41
    @Override
42
    public boolean useArgumentsInsteadObjects() {
43
        return true;
44
    }
45

    
46
    @Override
47
    public boolean allowConstantFolding() {
48
        return false;
49
    }
50
    
51
    @Override
52
    public Object call(Interpreter interpreter, Object[] args) throws Exception {
53
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
54
    }
55
    
56
    @Override
57
    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
        }
62
        MutableSymbolTable symbolTable = (MutableSymbolTable) interpreter.getSymbolTable();
63
        
64
        String name;
65
        List<String> argNames;
66
        Code body = null;
67
        String script_path = null;
68
        String script_function = null;
69
        String language = null;
70
        // name, body
71
        // name, args, body
72
        // name, script_name, script_func, lang
73
        // name, args, script_name, script_func, lang
74
        switch(args.size()) {
75
            case 2:
76
                name = (String) getObject(interpreter, args, 0);
77
                argNames = null;
78
                body = args.get(1);
79
                break;
80
            case 3:
81
                name = (String) getObject(interpreter, args, 0);
82
                if( args.get(1)==null ) {
83
                    argNames = null;
84
                } else {
85
                    argNames = (List<String>) getObject(interpreter, args, 1);
86
                }
87
                body = args.get(2);
88
                break;
89
            case 6:
90
                name = (String) getObject(interpreter, args, 0);
91
                if( args.get(1)==null ) {
92
                    argNames = null;
93
                } else {
94
                    argNames = (List<String>) getObject(interpreter, args, 1);
95
                }
96
                body = args.get(2);
97
                script_path = (args.get(3)==null)? null:((String)((Code.Constant)args.get(3)).value());
98
                script_function = (args.get(4)==null)? null:((String)((Code.Constant)args.get(4)).value());
99
                language = (args.get(5)==null)? null:((String)((Code.Constant)args.get(5)).value()).toLowerCase();
100
                break;
101
            default:
102
                throw new ExpressionRuntimeException("Incorrect number of arguments");
103
        }
104
        Function fn;
105
        if( body!=null ) {
106
            fn = new UserFunction(name, argNames, body);
107
            symbolTable.addFunction(fn);
108
            return fn;
109
        }
110
        if( StringUtils.isBlank(script_path) || StringUtils.isBlank(script_function) ) {
111
            throw new ExpressionRuntimeException("boydy and, script path or script function, are empty.");
112
        }
113
        if( StringUtils.isBlank(language) ) {
114
            language = "script";
115
        }
116
        switch(language.toLowerCase()) {
117
            case "script":
118
                fn = new ExternalFunction(name, script_path, script_function);
119
                symbolTable.addFunction(fn);
120
                return fn;
121
            case "java":
122
                fn = new JavaFunction(name, script_path, script_function);
123
                symbolTable.addFunction(fn);
124
                return fn;
125
        }
126
        throw new ExpressionRuntimeException("Unsupported language '"+language+".");
127
    }
128
    
129
    private static class UserFunction extends AbstractFunction {
130

    
131
        private final Code body;
132
        private final List<String> argNames;
133

    
134
        public UserFunction(String name, List<String> argNames, Code body) {
135
            super(GROUP_OTHER, name, Range.between(0, Integer.MAX_VALUE));
136
            this.argNames = argNames;
137
            this.body = body;
138
        }
139
        
140
        @Override
141
        public Object call(Interpreter interpreter, Object[] args) throws Exception {
142
            Object value;
143
            ExpressionEvaluatorManager manager = ExpressionEvaluatorLocator.getManager();
144
            MutableSymbolTable localSymbolTable = manager.createSymbolTable();
145
            
146
            List $args = new ArrayList();
147
            if( args != null ) {
148
                $args.addAll(Arrays.asList(args));
149
            }
150
            localSymbolTable.setVar("$ARGS", $args);
151
            
152
            int max;
153
            if( this.argNames==null ) {
154
                max = 0;
155
            } else {
156
                max = Math.min(this.argNames.size(), args.length);
157
            }
158
            for (int i = 0; i < max; i++) {
159
                localSymbolTable.setVar(this.argNames.get(i), args[i]);
160
            }
161
            SymbolTable savedSymbolTable = interpreter.getSymbolTable();
162
            localSymbolTable.addSymbolTable(savedSymbolTable);
163
            try {
164
                interpreter.setSymbolTable(localSymbolTable);
165
                value = interpreter.run(this.body);
166
            } finally {
167
                interpreter.setSymbolTable(savedSymbolTable);
168
            }
169
            return value;
170
        }
171
        
172
    }
173
    
174
    private static class ExternalFunction extends AbstractFunction {
175

    
176
        private final String script_path;
177
        private final String script_function;
178
        private final Script script;
179

    
180
        public ExternalFunction(String name, String script_path, String script_function) {
181
            super(GROUP_OTHER, name, Range.between(0, Integer.MAX_VALUE));
182
            this.script_path = script_path;
183
            this.script_function = script_function;
184
            ScriptManager scriptManager = ToolsLocator.getScriptManager();
185
            ExpressionEvaluatorManager expressionManager = ExpressionEvaluatorLocator.getExpressionEvaluatorManager();
186
            ResourcesStorage resourcesStorage = expressionManager.getScriptsResourcesStorage();
187
            this.script = scriptManager.loadScript(resourcesStorage, script_path);
188
            if( this.script == null ) {
189
                throw new ExpressionRuntimeException("Can't locate '"+this.script_path+"'.");
190
            }
191
        }
192
        
193
        @Override
194
        public Object call(Interpreter interpreter, Object[] args) throws Exception {
195
            Object r = this.script.invokeFunction(this.script_function, args);
196
            return r;
197
        }
198
        
199
    }
200

    
201
    private static class JavaFunction extends AbstractFunction {
202

    
203
        private final String fullClassName;
204
        private final String methodName;
205

    
206
        public JavaFunction(String name, String fullClassName, String methodName) {
207
            super(GROUP_OTHER, name, Range.between(0, Integer.MAX_VALUE));
208
            this.fullClassName = fullClassName;
209
            this.methodName = methodName;
210
        }
211
        
212
        @Override
213
        public Object call(Interpreter interpreter, Object[] args) throws Exception {
214
            Class[] parameterTypes = new Class[args.length];
215
            for (int i = 0; i < args.length; i++) {
216
                if( args[i]==null ) {
217
                    parameterTypes[i] = null;
218
                } else {
219
                    parameterTypes[i] = args[i].getClass();
220
                }
221
            }
222
            Class<?> theClass = Class.forName(this.fullClassName);
223
            Method method = theClass.getMethod(this.methodName, parameterTypes);
224
            Object value = method.invoke(null, args);
225
            return value;
226
        }
227
        
228
    }
229

    
230
}