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

History | View | Annotate | Download (8.33 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
        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
            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
            default:
98
                throw new ExpressionRuntimeException("Incorrect number of arguments");
99
        }
100
        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
    }
124
    
125
    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
            
142
            List $args = new ArrayList();
143
            if( args != null ) {
144
                $args.addAll(Arrays.asList(args));
145
            }
146
            localSymbolTable.setVar("$ARGS", $args);
147
            
148
            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
    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
}