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

History | View | Annotate | Download (7.64 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 org.apache.commons.lang3.Range;
8
import org.apache.commons.lang3.StringUtils;
9
import org.gvsig.expressionevaluator.Code;
10
import org.gvsig.expressionevaluator.Codes;
11
import org.gvsig.expressionevaluator.Function;
12
import org.gvsig.expressionevaluator.Interpreter;
13
import org.gvsig.expressionevaluator.spi.AbstractFunction;
14
import org.gvsig.expressionevaluator.ExpressionEvaluatorLocator;
15
import org.gvsig.expressionevaluator.ExpressionEvaluatorManager;
16
import org.gvsig.expressionevaluator.ExpressionRuntimeException;
17
import org.gvsig.expressionevaluator.MutableSymbolTable;
18
import org.gvsig.expressionevaluator.SymbolTable;
19
import org.gvsig.tools.ToolsLocator;
20
import org.gvsig.tools.resourcesstorage.ResourcesStorage;
21
import org.gvsig.tools.script.Script;
22
import org.gvsig.tools.script.ScriptManager;
23

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

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

    
40
    @Override
41
    public boolean isHidden() {
42
      return true;
43
    }
44
    
45
    @Override
46
    public boolean useArgumentsInsteadObjects() {
47
        return true;
48
    }
49

    
50
    @Override
51
    public boolean allowConstantFolding() {
52
        return false;
53
    }
54

    
55
    @Override
56
    public boolean allowArgNames() {
57
      return true;
58
    }
59
    
60
    @Override
61
    public Object call(Interpreter interpreter, Object[] args) throws Exception {
62
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
63
    }
64
    
65
    @Override
66
    public Object call(Interpreter interpreter, Codes args) throws Exception {
67
        if( !(interpreter.getSymbolTable() instanceof MutableSymbolTable) ) {
68
            throw new ExpressionRuntimeException("The use of user functions require a mutable symbol table.");
69
        }
70
        MutableSymbolTable symbolTable = (MutableSymbolTable) interpreter.getSymbolTable();
71
        
72
        String name = (String) getObject(interpreter, args, "FUNCTION_NAME");
73
        List<String> argNames = (List<String>) getObject(interpreter, args, "PARAMETERS");
74
        Code body = args.get("BODY");
75
        String script_path = (String) getObject(interpreter, args, "SCRIPT_PATH");
76
        String script_function = (String) getObject(interpreter, args, "SCRIPT_FUNCTION");
77
        String language = (String) getObject(interpreter, args, "LANGUAGE");
78
        Function fn;
79
        if( body!=null ) {
80
            fn = new UserFunction(name, argNames, body);
81
            symbolTable.addFunction(fn);
82
            return fn;
83
        }
84
        if( StringUtils.isBlank(script_path) || StringUtils.isBlank(script_function) ) {
85
            throw new ExpressionRuntimeException("boydy and, script path or script function, are empty.");
86
        }
87
        if( StringUtils.isBlank(language) ) {
88
            language = "script";
89
        }
90
        switch(language.toLowerCase()) {
91
            case "script":
92
                fn = new ExternalFunction(name, script_path, script_function);
93
                symbolTable.addFunction(fn);
94
                return fn;
95
            case "java":
96
                fn = new JavaFunction(name, script_path, script_function);
97
                symbolTable.addFunction(fn);
98
                return fn;
99
        }
100
        throw new ExpressionRuntimeException("Unsupported language '"+language+".");
101
    }
102
    
103
    private static class UserFunction extends AbstractFunction {
104

    
105
        private final Code body;
106
        private final List<String> argNames;
107

    
108
        public UserFunction(String name, List<String> argNames, Code body) {
109
            super(GROUP_OTHER, name, Range.between(0, Integer.MAX_VALUE));
110
            this.argNames = argNames;
111
            this.body = body;
112
        }
113

    
114
        @Override
115
        public boolean allowArgNames() {
116
          return true;
117
        }
118

    
119
        @Override
120
        public Object call(Interpreter interpreter, Object[] args) throws Exception {
121
            Object value;
122
            ExpressionEvaluatorManager manager = ExpressionEvaluatorLocator.getManager();
123
            MutableSymbolTable localSymbolTable = manager.createSymbolTable();
124
            
125
            List $args = new ArrayList();
126
            if( args != null ) {
127
                $args.addAll(Arrays.asList(args));
128
            }
129
            localSymbolTable.setVar("$ARGS", $args);
130
            
131
            int max;
132
            if( this.argNames==null ) {
133
                max = 0;
134
            } else {
135
                max = Math.min(this.argNames.size(), args.length);
136
            }
137
            for (int i = 0; i < max; i++) {
138
                localSymbolTable.setVar(this.argNames.get(i), args[i]);
139
            }
140
            SymbolTable savedSymbolTable = interpreter.getSymbolTable();
141
            localSymbolTable.addSymbolTable(savedSymbolTable);
142
            try {
143
                interpreter.setSymbolTable(localSymbolTable);
144
                value = interpreter.run(this.body);
145
            } finally {
146
                interpreter.setSymbolTable(savedSymbolTable);
147
            }
148
            return value;
149
        }
150
        
151
    }
152
    
153
    private static class ExternalFunction extends AbstractFunction {
154

    
155
        private final String script_path;
156
        private final String script_function;
157
        private final Script script;
158

    
159
        public ExternalFunction(String name, String script_path, String script_function) {
160
            super(GROUP_OTHER, name, Range.between(0, Integer.MAX_VALUE));
161
            this.script_path = script_path;
162
            this.script_function = script_function;
163
            ScriptManager scriptManager = ToolsLocator.getScriptManager();
164
            ExpressionEvaluatorManager expressionManager = ExpressionEvaluatorLocator.getExpressionEvaluatorManager();
165
            ResourcesStorage resourcesStorage = expressionManager.getScriptsResourcesStorage();
166
            this.script = scriptManager.loadScript(resourcesStorage, script_path);
167
            if( this.script == null ) {
168
                throw new ExpressionRuntimeException("Can't locate '"+this.script_path+"'.");
169
            }
170
        }
171
        
172
        @Override
173
        public Object call(Interpreter interpreter, Object[] args) throws Exception {
174
            Object r = this.script.invokeFunction(this.script_function, args);
175
            return r;
176
        }
177
        
178
    }
179

    
180
    private static class JavaFunction extends AbstractFunction {
181

    
182
        private final String fullClassName;
183
        private final String methodName;
184

    
185
        public JavaFunction(String name, String fullClassName, String methodName) {
186
            super(GROUP_OTHER, name, Range.between(0, Integer.MAX_VALUE));
187
            this.fullClassName = fullClassName;
188
            this.methodName = methodName;
189
        }
190
        
191
        @Override
192
        public Object call(Interpreter interpreter, Object[] args) throws Exception {
193
            Class[] parameterTypes = new Class[args.length];
194
            for (int i = 0; i < args.length; i++) {
195
                if( args[i]==null ) {
196
                    parameterTypes[i] = null;
197
                } else {
198
                    parameterTypes[i] = args[i].getClass();
199
                }
200
            }
201
            Class<?> theClass = Class.forName(this.fullClassName);
202
            Method method = theClass.getMethod(this.methodName, parameterTypes);
203
            Object value = method.invoke(null, args);
204
            return value;
205
        }
206
        
207
    }
208

    
209
}