Statistics
| Revision:

svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.library / org.gvsig.expressionevaluator / org.gvsig.expressionevaluator.lib / org.gvsig.expressionevaluator.lib.api / src / main / java / org / gvsig / expressionevaluator / spi / AbstractFunction.java @ 44644

History | View | Annotate | Download (13.9 KB)

1
package org.gvsig.expressionevaluator.spi;
2

    
3
import java.io.File;
4
import java.io.InputStream;
5
import java.net.URI;
6
import java.net.URISyntaxException;
7
import java.net.URL;
8
import java.time.LocalDateTime;
9
import java.time.ZoneId;
10
import java.time.temporal.TemporalAccessor;
11
import java.util.ArrayList;
12
import java.util.Date;
13
import java.util.List;
14
import java.util.Locale;
15
import java.util.Objects;
16
import org.apache.commons.io.IOUtils;
17
import org.apache.commons.lang3.BooleanUtils;
18
import org.apache.commons.lang3.Range;
19
import org.apache.commons.lang3.StringUtils;
20
import org.apache.commons.math.util.MathUtils;
21
import org.gvsig.expressionevaluator.Code;
22
import org.gvsig.expressionevaluator.Codes;
23
import org.gvsig.expressionevaluator.Function;
24
import org.gvsig.expressionevaluator.I18N;
25
import org.gvsig.expressionevaluator.Interpreter;
26
//import org.gvsig.fmap.geom.Geometry;
27
//import org.gvsig.fmap.geom.primitive.Point;
28
import org.json.JSONArray;
29
import org.json.JSONObject;
30

    
31
@SuppressWarnings("UseSpecificCatch")
32
public abstract class AbstractFunction implements Function {
33
 
34
    private final String name;
35
    private String group;
36
    private Range argc;
37
    private String description;
38
    private String[] descriptionArgs;
39
    private List<String> alias;
40
    private String template;
41
    private String returnType;
42
    private boolean sqlCompatible;
43

    
44
    protected AbstractFunction(String group, String name, Range argc, String description, String template, String[] descriptionArgs, String returnType, boolean sqlCompatible) {
45
        this.name = name;
46
        this.group = group;
47
        this.argc = argc;
48
        this.description = description;
49
        this.template = template;
50
        this.descriptionArgs = descriptionArgs;
51
        this.returnType = returnType;
52
        this.sqlCompatible = sqlCompatible;
53
        load_from_resource();
54
    }
55
    protected AbstractFunction(String group, String name, Range argc, String description, String template, String[] descriptionArgs, String returnType) {
56
        this(group, name, argc, description, template, descriptionArgs, returnType, false);
57
    }
58
    
59
    protected AbstractFunction(String group, String name, Range argc, String description, String template, String[] descriptionArgs) {
60
        this(group, name, argc, description, template, null, null);
61
    }
62

    
63
    protected AbstractFunction(String group, String name, Range argc, String description, String template) {
64
        this(group, name, argc, description, template, null, null);
65
    }
66

    
67
    protected AbstractFunction(String group, String name, Range argc) {
68
        this(group, name, argc, null, null, null, null);
69
    }
70

    
71
    @Override
72
    public String name() {
73
        return this.name;
74
    }
75

    
76
    @Override
77
    public String returnType() {
78
        return this.returnType;
79
    }
80

    
81
    @Override
82
    public String group() {
83
        return this.group;
84
    }
85

    
86
    @Override
87
    public Range argc() {
88
        return argc;
89
    }
90

    
91
    @Override
92
    public String description() {
93
        if( StringUtils.equalsIgnoreCase(System.getProperty("ExpressionEvaluatorReloadFunctionResources"), "true")) {
94
            load_from_resource();
95
        }
96
        return description;
97
    }
98

    
99
    @Override
100
    public String[] descriptionArgs() {
101
        return descriptionArgs;
102
    }
103

    
104
    @Override
105
    public void addAlias(String name) {
106
        if( StringUtils.isBlank(name) ) {
107
            return;
108
        }
109
        if( this.alias == null ) {
110
            this.alias = new ArrayList<>();
111
        }
112
        if( this.alias.contains(name) ) {
113
            return;
114
        }
115
        this.alias.add(name);
116
    }
117

    
118
    @Override
119
    public List<String> aliases() {
120
        return this.alias;
121
    }
122

    
123
    @Override
124
    public String template() {
125
        return this.template;
126
    }
127

    
128
    @Override
129
    public boolean isOperator() {
130
        return false;
131
    }
132

    
133
    @Override
134
    public boolean useArgumentsInsteadObjects() {
135
        return false;
136
    }
137

    
138
    @Override
139
    public boolean isSQLCompatible() {
140
        return sqlCompatible;
141
    }
142

    
143
    @Override
144
    public boolean allowConstantFolding() {
145
        return false;
146
    }
147
    
148
    @Override
149
    public Object call(Interpreter interpreter, Codes args) throws Exception {
150
        return null;
151
    }
152
    
153
    protected int getInt(Object args[], int n) {
154
        if( args.length < n  ) {
155
            throw new IllegalArgumentException(I18N.Required_argument_XargnX_and_only_found_XargcX_in_call_to_XIdentifierX(name(), args.length, n));
156
        }
157
        Object value = args[n];
158
        if( value == null ) {
159
            throw new IllegalArgumentException(I18N.Illegal_null_value_for_argument_XargnX_of_XIdentifierX_function(name(), n));
160
        }
161
        if( !(value instanceof Number) ) {
162
            String type = value.getClass().getCanonicalName();
163
            throw new IllegalArgumentException(
164
                    I18N.The_type_of_the_argument_XargnX_for_the_XIdentifierX_function_is_incorrect(name(), n) + " " +
165
                    I18N.Expected_XexpectedX_and_found_XfoundX("Number",type)
166
            );
167
        }
168
        return ((Number)value).intValue();
169
    }
170

    
171
    protected long getLong(Object args[], int n) {
172
        if( args.length < n  ) {
173
            throw new IllegalArgumentException(I18N.Required_argument_XargnX_and_only_found_XargcX_in_call_to_XIdentifierX(name(), args.length, n));
174
        }
175
        Object value = args[n];
176
        if( value == null ) {
177
            throw new IllegalArgumentException(I18N.Illegal_null_value_for_argument_XargnX_of_XIdentifierX_function(name(), n));
178
        }
179
        if( !(value instanceof Number) ) {
180
            String type = value.getClass().getCanonicalName();
181
            throw new IllegalArgumentException(
182
                    I18N.The_type_of_the_argument_XargnX_for_the_XIdentifierX_function_is_incorrect(name(), n) + " " +
183
                    I18N.Expected_XexpectedX_and_found_XfoundX("Number",type)
184
            );
185
        }
186
        return ((Number)value).longValue();
187
    }
188

    
189
    protected double getDouble(Object args[], int n) {
190
        if( args.length < n  ) {
191
            throw new IllegalArgumentException(I18N.Required_argument_XargnX_and_only_found_XargcX_in_call_to_XIdentifierX(name(), args.length, n));
192
        }
193
        Object value = args[n];
194
        if( value == null ) {
195
            throw new IllegalArgumentException(I18N.Illegal_null_value_for_argument_XargnX_of_XIdentifierX_function(name(), n));
196
        }
197
        if( !(value instanceof Number) ) {
198
            String type = value.getClass().getCanonicalName();
199
            throw new IllegalArgumentException(
200
                    I18N.The_type_of_the_argument_XargnX_for_the_XIdentifierX_function_is_incorrect(name(), n) + " " +
201
                    I18N.Expected_XexpectedX_and_found_XfoundX("Number",type)
202
            );
203
        }
204
        return ((Number)value).doubleValue();
205
    }
206
    
207
    protected String getStr(Object args[], int n) {
208
        if( args.length < n  ) {
209
            throw new IllegalArgumentException(I18N.Required_argument_XargnX_and_only_found_XargcX_in_call_to_XIdentifierX(name(), args.length, n));
210
        }
211
        return Objects.toString(args[n], "");
212
    }
213
    
214
    protected File getFile(Object args[], int n) {
215
        if( args.length < n  ) {
216
            throw new IllegalArgumentException(I18N.Required_argument_XargnX_and_only_found_XargcX_in_call_to_XIdentifierX(name(), args.length, n));
217
        }
218
        Object arg = args[n];
219
        if( arg == null ) {
220
            return null;
221
        }
222
        if( arg instanceof File ) {
223
            return (File)arg;
224
        }
225
        if( arg instanceof URL ) {
226
            try {
227
                return new File(((URL)arg).toURI());
228
            } catch (URISyntaxException ex) {
229
                return null;
230
            }
231
        }
232
        if( arg instanceof URI ) {
233
            return new File(((URI)arg));
234
        }
235
        String s = Objects.toString(arg, null);
236
        if( s == null ) {
237
            return null;
238
        }
239
        File f = new File(s);
240
        return f;
241
    }
242
    
243
    protected Object getObject(Object args[], int n) {
244
        if( args.length < n  ) {
245
            throw new IllegalArgumentException(I18N.Required_argument_XargnX_and_only_found_XargcX_in_call_to_XIdentifierX(name(), args.length, n));
246
        }
247
        return args[n];
248
    }
249
    
250
    protected Object getObject(Interpreter interpreter, Codes args, int n) {
251
        if( args.size() < n  ) {
252
            throw new IllegalArgumentException(I18N.Required_argument_XargnX_and_only_found_XargcX_in_call_to_XIdentifierX(name(), args.size(), n));
253
        }
254
        Code arg = args.get(n);
255
        if( arg==null ) {
256
            return null;
257
        }
258
        Object value = interpreter.run(arg);
259
        return value;
260
    }
261
    
262
    protected Date getDate(Object[] args, int n) {
263
        if( args.length < n  ) {
264
            throw new IllegalArgumentException(I18N.Required_argument_XargnX_and_only_found_XargcX_in_call_to_XIdentifierX(name(), args.length, n));
265
        }
266
        Object value = args[n];
267
        if( value == null ) {
268
            return null;
269
        }
270
        if( !(value instanceof Date) ) {
271
            String type = value.getClass().getCanonicalName();
272
            throw new IllegalArgumentException(
273
                    I18N.The_type_of_the_argument_XargnX_for_the_XIdentifierX_function_is_incorrect(name(), n) + " " +
274
                    I18N.Expected_XexpectedX_and_found_XfoundX("Date",type)
275
            );
276
        }
277
        return (Date)value;
278
    }
279
    
280
    protected LocalDateTime getLocalDateTime(Object[] args, int n) {
281
        if( args.length < n  ) {
282
            throw new IllegalArgumentException(I18N.Required_argument_XargnX_and_only_found_XargcX_in_call_to_XIdentifierX(name(), args.length, n));
283
        }
284
        Object value = args[n];
285
        if( value == null ) {
286
            return null;
287
        }
288
        if( value instanceof Date ) {
289
            Date date = ((Date)value);
290
            return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
291
        }
292
        if( value instanceof LocalDateTime ) {
293
            return (LocalDateTime) value;
294
        }
295
        if( value instanceof TemporalAccessor ) {
296
            return LocalDateTime.from(((TemporalAccessor)value));
297
        }
298
        String type = value.getClass().getCanonicalName();
299
        throw new IllegalArgumentException(
300
                I18N.The_type_of_the_argument_XargnX_for_the_XIdentifierX_function_is_incorrect(name(), n) + " " +
301
                I18N.Expected_XexpectedX_and_found_XfoundX("Temporal/Date",type)
302
        );
303
    }
304
    
305
    protected boolean getBoolean(Object args[], int n, Double accuracy) {
306
        if( args.length < n  ) {
307
            throw new IllegalArgumentException(I18N.Required_argument_XargnX_and_only_found_XargcX_in_call_to_XIdentifierX(name(), args.length, n));
308
        }
309
        Object value = args[n];
310
        return toBoolean(value, accuracy);
311
    }
312

    
313
    protected boolean getBoolean(Interpreter interpreter, Codes args, int n) {
314
        Object value = getObject(interpreter, args, n);
315
        return toBoolean(value, interpreter.getAccuracy());
316
    }
317

    
318
    protected boolean toBoolean(Object value, Double accuracy) {
319
        if( value == null ) {
320
            return false;
321
        }
322
        if( value instanceof Boolean ) {
323
            return (Boolean)value;
324
        }        
325
        if( value instanceof Number ) {
326
            return MathUtils.compareTo(
327
                ((Number) value).doubleValue(), 
328
                0,
329
                accuracy==null? MathUtils.EPSILON:accuracy
330
            ) == 0;
331
        }
332
        return BooleanUtils.toBoolean(value.toString());
333
    } 
334

    
335
    private void load_from_resource() {
336
        String lang = Locale.getDefault().getLanguage();
337
        URL url = this.getClass().getResource("/org/gvsig/expressionevaluator/functions/"+lang+"/"+this.name()+".json");
338
        if( url == null ) {
339
            url = this.getClass().getResource("/org/gvsig/expressionevaluator/functions/en/"+this.name()+".json");
340
            if( url == null ) {
341
                return;
342
            }
343
        }
344
        InputStream is = null;
345
        JSONObject json;
346
        try {
347
            is = url.openStream();
348
            List<String> lines = IOUtils.readLines(is);
349
            json = new JSONObject(StringUtils.join(lines,  "\n"));
350
        } catch (Exception ex) {
351
            return;
352
        } finally {
353
            IOUtils.closeQuietly(is);
354
        }
355
        
356
        if( json.has("group") ) {
357
            this.group = json.getString("group");
358
        }
359
        if( json.has("description") ) {
360
            Object x = json.get("description");
361
            if( x instanceof String ) {
362
                this.description = (String) x;
363
            } else if( x instanceof JSONArray ) {
364
                StringBuilder builder = new StringBuilder();
365
                for (int i = 0; i < ((JSONArray)x).length(); i++) {
366
                    if( i>0 ) {
367
                        builder.append(" ");
368
                    }
369
                    builder.append(((JSONArray)x).getString(i));
370
                }
371
                this.description = builder.toString();
372
            } else {
373
                this.description = x.toString();
374
            }
375
            this.description = StringUtils.replace(
376
                    this.description, 
377
                    "@@@", 
378
                    url.toString()
379
            );
380
        }
381
        if( json.has("template") ) {
382
            this.template = json.getString("template");
383
        }
384
        if( json.has("returnType") ) {
385
            this.returnType = json.getString("returnType");
386
        }
387
        if( json.has("sqlCompatible") ) {
388
            this.sqlCompatible = json.getBoolean("sqlCompatible");
389
        }
390
        if( json.has("args") ) {
391
            JSONArray x = json.getJSONArray("args");
392
            String[] args = new String[x.length()];
393
            for (int i = 0; i < x.length(); i++) {
394
                args[i] = x.getString(i);
395
            }
396
            this.descriptionArgs = args;
397
        }
398
        if( json.has("alias") ) {
399
            JSONArray x = json.getJSONArray("alias");
400
            for (int i = 0; i < x.length(); i++) {
401
                this.addAlias(x.getString(i));
402
            }
403
        }
404
    }
405
}