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

History | View | Annotate | Download (16.5 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 isHidden() {
135
      return false;
136
    }
137
    
138
    @Override
139
    public boolean useArgumentsInsteadObjects() {
140
        return false;
141
    }
142

    
143
    @Override
144
    public boolean isSQLCompatible() {
145
        return sqlCompatible;
146
    }
147

    
148
    @Override
149
    public boolean allowConstantFolding() {
150
        return false;
151
    }
152

    
153
    @Override
154
    public Object call(Interpreter interpreter, Codes args) throws Exception {
155
        return null;
156
    }
157
    
158
    protected int getInt(Object args[], int n) {
159
        if( args.length < n  ) {
160
            throw new IllegalArgumentException(I18N.Required_argument_XargnX_and_only_found_XargcX_in_call_to_XIdentifierX(name(), args.length, n));
161
        }
162
        return getInt(args[n],n);
163
    }
164

    
165
    protected int getInt(Object value, int n) {
166
        if( value == null ) {
167
            throw new IllegalArgumentException(I18N.Illegal_null_value_for_argument_XargnX_of_XIdentifierX_function(name(), n));
168
        }
169
        if( !(value instanceof Number) ) {
170
            String type = value.getClass().getCanonicalName();
171
            throw new IllegalArgumentException(
172
                    I18N.The_type_of_the_argument_XargnX_for_the_XIdentifierX_function_is_incorrect(name(), n) + " " +
173
                    I18N.Expected_XexpectedX_and_found_XfoundX("Number",type)
174
            );
175
        }
176
        return ((Number)value).intValue();
177
    }
178

    
179
    protected long getLong(Object args[], int n) {
180
        if( args.length < n  ) {
181
            throw new IllegalArgumentException(I18N.Required_argument_XargnX_and_only_found_XargcX_in_call_to_XIdentifierX(name(), args.length, n));
182
        }
183
        return getLong(args[n],n);
184
    }
185

    
186
    protected long getLong(Object value, int n) {
187
        if( value == null ) {
188
            throw new IllegalArgumentException(I18N.Illegal_null_value_for_argument_XargnX_of_XIdentifierX_function(name(), n));
189
        }
190
        if( !(value instanceof Number) ) {
191
            String type = value.getClass().getCanonicalName();
192
            throw new IllegalArgumentException(
193
                    I18N.The_type_of_the_argument_XargnX_for_the_XIdentifierX_function_is_incorrect(name(), n) + " " +
194
                    I18N.Expected_XexpectedX_and_found_XfoundX("Number",type)
195
            );
196
        }
197
        return ((Number)value).longValue();
198
    }
199

    
200
    protected double getDouble(Object args[], int n) {
201
        if( args.length < n  ) {
202
            throw new IllegalArgumentException(I18N.Required_argument_XargnX_and_only_found_XargcX_in_call_to_XIdentifierX(name(), args.length, n));
203
        }
204
        return getDouble(args[n],n);
205
    }
206

    
207
    protected double getDouble(Object value, int arg) {
208
        if( value == null ) {
209
            throw new IllegalArgumentException(I18N.Illegal_null_value_for_argument_XargnX_of_XIdentifierX_function(name(), arg));
210
        }
211
        if( !(value instanceof Number) ) {
212
            String type = value.getClass().getCanonicalName();
213
            throw new IllegalArgumentException(
214
                    I18N.The_type_of_the_argument_XargnX_for_the_XIdentifierX_function_is_incorrect(name(), arg) + " " +
215
                    I18N.Expected_XexpectedX_and_found_XfoundX("Number",type)
216
            );
217
        }
218
        return ((Number)value).doubleValue();
219
    }
220
    
221
    protected float getFloat(Object args[], int n) {
222
        if( args.length < n  ) {
223
            throw new IllegalArgumentException(I18N.Required_argument_XargnX_and_only_found_XargcX_in_call_to_XIdentifierX(name(), args.length, n));
224
        }
225
        return getFloat(args[n],n);
226
    }
227

    
228
    protected float getFloat(Object value, int arg) {
229
        if( value == null ) {
230
            throw new IllegalArgumentException(I18N.Illegal_null_value_for_argument_XargnX_of_XIdentifierX_function(name(), arg));
231
        }
232
        if( !(value instanceof Number) ) {
233
            String type = value.getClass().getCanonicalName();
234
            throw new IllegalArgumentException(
235
                    I18N.The_type_of_the_argument_XargnX_for_the_XIdentifierX_function_is_incorrect(name(), arg) + " " +
236
                    I18N.Expected_XexpectedX_and_found_XfoundX("Number",type)
237
            );
238
        }
239
        return ((Number)value).floatValue();
240
    }
241
    
242
    protected String getStr(Object args[], int n) {
243
        if( args.length < n  ) {
244
            throw new IllegalArgumentException(I18N.Required_argument_XargnX_and_only_found_XargcX_in_call_to_XIdentifierX(name(), args.length, n));
245
        }
246
        return getStr(args[n],n);
247
    }
248
    
249
    protected String getStr(Object value, int n) {
250
        return Objects.toString(value, "");
251
    }
252
    
253
    protected File getFile(Object args[], int n) {
254
        if( args.length < n  ) {
255
            throw new IllegalArgumentException(I18N.Required_argument_XargnX_and_only_found_XargcX_in_call_to_XIdentifierX(name(), args.length, n));
256
        }
257
        return getFile(args[n],n);
258
    }
259
    
260
    protected File getFile(Object value, int n) {
261
        if( value == null ) {
262
            return null;
263
        }
264
        if( value instanceof File ) {
265
            return (File)value;
266
        }
267
        if( value instanceof URL ) {
268
            try {
269
                return new File(((URL)value).toURI());
270
            } catch (URISyntaxException ex) {
271
                return null;
272
            }
273
        }
274
        if( value instanceof URI ) {
275
            return new File(((URI)value));
276
        }
277
        String s = Objects.toString(value, null);
278
        if( s == null ) {
279
            return null;
280
        }
281
        File f = new File(s);
282
        return f;
283
    }
284
    
285
    protected Object getObject(Object args[], int n) {
286
        if( args.length < n  ) {
287
            throw new IllegalArgumentException(I18N.Required_argument_XargnX_and_only_found_XargcX_in_call_to_XIdentifierX(name(), args.length, n));
288
        }
289
        return args[n];
290
    }
291
    
292
    protected Object getObject(Interpreter interpreter, Codes args, int n) {
293
        if( args.size() < n  ) {
294
            throw new IllegalArgumentException(I18N.Required_argument_XargnX_and_only_found_XargcX_in_call_to_XIdentifierX(name(), args.size(), n));
295
        }
296
        Code arg = args.get(n);
297
        if( arg==null ) {
298
            return null;
299
        }
300
        Object value = interpreter.run(arg);
301
        return value;
302
    }
303
    
304
    protected Comparable getComparable(Object[] args, int n) {
305
        if( args.length < n  ) {
306
            throw new IllegalArgumentException(I18N.Required_argument_XargnX_and_only_found_XargcX_in_call_to_XIdentifierX(name(), args.length, n));
307
        }
308
        return getComparable(args[n],n);
309
    }
310
    
311
    protected Comparable getComparable(Object value, int n) {
312
        if( value == null ) {
313
            return null;
314
        }
315
        if( !(value instanceof Comparable) ) {
316
            String type = value.getClass().getCanonicalName();
317
            throw new IllegalArgumentException(
318
                    I18N.The_type_of_the_argument_XargnX_for_the_XIdentifierX_function_is_incorrect(name(), n) + " " +
319
                    I18N.Expected_XexpectedX_and_found_XfoundX("Comparable",type)
320
            );
321
        }
322
        return (Comparable)value;
323
    }
324

    
325
    protected Comparable getDate(Object[] args, int n) {
326
        if( args.length < n  ) {
327
            throw new IllegalArgumentException(I18N.Required_argument_XargnX_and_only_found_XargcX_in_call_to_XIdentifierX(name(), args.length, n));
328
        }
329
        return getDate(args[n],n);
330
    }
331
    
332
    protected Date getDate(Object value, int n) {
333
        if( value == null ) {
334
            return null;
335
        }
336
        if( !(value instanceof Date) ) {
337
            String type = value.getClass().getCanonicalName();
338
            throw new IllegalArgumentException(
339
                    I18N.The_type_of_the_argument_XargnX_for_the_XIdentifierX_function_is_incorrect(name(), n) + " " +
340
                    I18N.Expected_XexpectedX_and_found_XfoundX("Date",type)
341
            );
342
        }
343
        return (Date)value;
344
    }
345
    
346
    protected LocalDateTime getLocalDateTime(Object[] args, int n) {
347
        if( args.length < n  ) {
348
            throw new IllegalArgumentException(I18N.Required_argument_XargnX_and_only_found_XargcX_in_call_to_XIdentifierX(name(), args.length, n));
349
        }
350
        return getLocalDateTime(args[n],n);
351
    }
352
    
353
    protected LocalDateTime getLocalDateTime(Object value, int n) {
354
        if( value == null ) {
355
            return null;
356
        }
357
        if( value instanceof Date ) {
358
            Date date = ((Date)value);
359
            return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
360
        }
361
        if( value instanceof LocalDateTime ) {
362
            return (LocalDateTime) value;
363
        }
364
        if( value instanceof TemporalAccessor ) {
365
            return LocalDateTime.from(((TemporalAccessor)value));
366
        }
367
        String type = value.getClass().getCanonicalName();
368
        throw new IllegalArgumentException(
369
                I18N.The_type_of_the_argument_XargnX_for_the_XIdentifierX_function_is_incorrect(name(), n) + " " +
370
                I18N.Expected_XexpectedX_and_found_XfoundX("Temporal/Date",type)
371
        );
372
    }
373
    
374
    protected boolean getBoolean(Object args[], int n, Double accuracy) {
375
        if( args.length < n  ) {
376
            throw new IllegalArgumentException(I18N.Required_argument_XargnX_and_only_found_XargcX_in_call_to_XIdentifierX(name(), args.length, n));
377
        }
378
        return getBoolean(args[n], n, accuracy);
379
    }
380

    
381
    protected boolean getBoolean(Object value, int n) {
382
        return getBoolean(value, n, MathUtils.EPSILON);
383
    }
384

    
385
    protected boolean getBoolean(Object value, int n, Double accuracy) {
386
        return toBoolean(value, accuracy);
387
    }
388

    
389
    protected boolean getBoolean(Interpreter interpreter, Codes args, int n) {
390
        Object value = getObject(interpreter, args, n);
391
        return toBoolean(value, interpreter.getAccuracy());
392
    }
393

    
394
    protected boolean toBoolean(Object value, Double accuracy) {
395
        if( value == null ) {
396
            return false;
397
        }
398
        if( value instanceof Boolean ) {
399
            return (Boolean)value;
400
        }        
401
        if( value instanceof Number ) {
402
            return MathUtils.compareTo(
403
                ((Number) value).doubleValue(), 
404
                0,
405
                accuracy==null? MathUtils.EPSILON:accuracy
406
            ) == 0;
407
        }
408
        return BooleanUtils.toBoolean(value.toString());
409
    } 
410

    
411
    private void load_from_resource() {
412
        String lang = Locale.getDefault().getLanguage();
413
        URL url = this.getClass().getResource("/org/gvsig/expressionevaluator/functions/"+lang+"/"+this.name()+".json");
414
        if( url == null ) {
415
            url = this.getClass().getResource("/org/gvsig/expressionevaluator/functions/en/"+this.name()+".json");
416
            if( url == null ) {
417
                return;
418
            }
419
        }
420
        InputStream is = null;
421
        JSONObject json;
422
        try {
423
            is = url.openStream();
424
            List<String> lines = IOUtils.readLines(is);
425
            json = new JSONObject(StringUtils.join(lines,  "\n"));
426
        } catch (Exception ex) {
427
            return;
428
        } finally {
429
            IOUtils.closeQuietly(is);
430
        }
431
        
432
        if( json.has("group") ) {
433
            this.group = json.getString("group");
434
        }
435
        if( json.has("description") ) {
436
            Object x = json.get("description");
437
            if( x instanceof String ) {
438
                this.description = (String) x;
439
            } else if( x instanceof JSONArray ) {
440
                StringBuilder builder = new StringBuilder();
441
                for (int i = 0; i < ((JSONArray)x).length(); i++) {
442
                    if( i>0 ) {
443
                        builder.append(" ");
444
                    }
445
                    builder.append(((JSONArray)x).getString(i));
446
                }
447
                this.description = builder.toString();
448
            } else {
449
                this.description = Objects.toString(x, null);
450
            }
451
            this.description = StringUtils.replace(
452
                    this.description, 
453
                    "@@@", 
454
                    url.toString()
455
            );
456
        }
457
        if( json.has("template") ) {
458
            this.template = json.getString("template");
459
        }
460
        if( json.has("returnType") ) {
461
            this.returnType = json.getString("returnType");
462
        }
463
        if( json.has("sqlCompatible") ) {
464
            this.sqlCompatible = json.getBoolean("sqlCompatible");
465
        }
466
        if( json.has("args") ) {
467
            JSONArray x = json.getJSONArray("args");
468
            String[] args = new String[x.length()];
469
            for (int i = 0; i < x.length(); i++) {
470
                args[i] = x.getString(i);
471
            }
472
            this.descriptionArgs = args;
473
        }
474
        if( json.has("alias") ) {
475
            JSONArray x = json.getJSONArray("alias");
476
            for (int i = 0; i < x.length(); i++) {
477
                this.addAlias(x.getString(i));
478
            }
479
        }
480
    }
481
}