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

History | View | Annotate | Download (14.6 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 boolean allowArgNames() {
155
      return false;
156
    }
157
    
158
    @Override
159
    public Object call(Interpreter interpreter, Codes args) throws Exception {
160
        return null;
161
    }
162
    
163
    protected int getInt(Object args[], int n) {
164
        if( args.length < n  ) {
165
            throw new IllegalArgumentException(I18N.Required_argument_XargnX_and_only_found_XargcX_in_call_to_XIdentifierX(name(), args.length, n));
166
        }
167
        Object value = args[n];
168
        if( value == null ) {
169
            throw new IllegalArgumentException(I18N.Illegal_null_value_for_argument_XargnX_of_XIdentifierX_function(name(), n));
170
        }
171
        if( !(value instanceof Number) ) {
172
            String type = value.getClass().getCanonicalName();
173
            throw new IllegalArgumentException(
174
                    I18N.The_type_of_the_argument_XargnX_for_the_XIdentifierX_function_is_incorrect(name(), n) + " " +
175
                    I18N.Expected_XexpectedX_and_found_XfoundX("Number",type)
176
            );
177
        }
178
        return ((Number)value).intValue();
179
    }
180

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

    
199
    protected double getDouble(Object args[], int n) {
200
        if( args.length < n  ) {
201
            throw new IllegalArgumentException(I18N.Required_argument_XargnX_and_only_found_XargcX_in_call_to_XIdentifierX(name(), args.length, n));
202
        }
203
        Object value = args[n];
204
        if( value == null ) {
205
            throw new IllegalArgumentException(I18N.Illegal_null_value_for_argument_XargnX_of_XIdentifierX_function(name(), n));
206
        }
207
        if( !(value instanceof Number) ) {
208
            String type = value.getClass().getCanonicalName();
209
            throw new IllegalArgumentException(
210
                    I18N.The_type_of_the_argument_XargnX_for_the_XIdentifierX_function_is_incorrect(name(), n) + " " +
211
                    I18N.Expected_XexpectedX_and_found_XfoundX("Number",type)
212
            );
213
        }
214
        return ((Number)value).doubleValue();
215
    }
216
    
217
    protected String getStr(Object args[], int n) {
218
        if( args.length < n  ) {
219
            throw new IllegalArgumentException(I18N.Required_argument_XargnX_and_only_found_XargcX_in_call_to_XIdentifierX(name(), args.length, n));
220
        }
221
        return Objects.toString(args[n], "");
222
    }
223
    
224
    protected File getFile(Object args[], int n) {
225
        if( args.length < n  ) {
226
            throw new IllegalArgumentException(I18N.Required_argument_XargnX_and_only_found_XargcX_in_call_to_XIdentifierX(name(), args.length, n));
227
        }
228
        Object arg = args[n];
229
        if( arg == null ) {
230
            return null;
231
        }
232
        if( arg instanceof File ) {
233
            return (File)arg;
234
        }
235
        if( arg instanceof URL ) {
236
            try {
237
                return new File(((URL)arg).toURI());
238
            } catch (URISyntaxException ex) {
239
                return null;
240
            }
241
        }
242
        if( arg instanceof URI ) {
243
            return new File(((URI)arg));
244
        }
245
        String s = Objects.toString(arg, null);
246
        if( s == null ) {
247
            return null;
248
        }
249
        File f = new File(s);
250
        return f;
251
    }
252
    
253
    protected Object getObject(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 args[n];
258
    }
259
    
260
    protected Object getObject(Interpreter interpreter, Codes args, int n) {
261
        if( args.size() < n  ) {
262
            throw new IllegalArgumentException(I18N.Required_argument_XargnX_and_only_found_XargcX_in_call_to_XIdentifierX(name(), args.size(), n));
263
        }
264
        Code arg = args.get(n);
265
        if( arg==null ) {
266
            return null;
267
        }
268
        Object value = interpreter.run(arg);
269
        return value;
270
    }
271
    
272
    protected Object getObject(Interpreter interpreter, Codes args, String name) {
273
        Code arg = args.get(name);
274
        if( arg==null ) {
275
            return null;
276
        }
277
        Object value = interpreter.run(arg);
278
        return value;
279
    }
280
    
281
    protected Object getObject(Interpreter interpreter, Codes args, String name, int index) {
282
        Code arg = args.get(name+index);
283
        if( arg==null ) {
284
            return null;
285
        }
286
        Object value = interpreter.run(arg);
287
        return value;
288
    }
289
    
290
    protected Date getDate(Object[] args, int n) {
291
        if( args.length < n  ) {
292
            throw new IllegalArgumentException(I18N.Required_argument_XargnX_and_only_found_XargcX_in_call_to_XIdentifierX(name(), args.length, n));
293
        }
294
        Object value = args[n];
295
        if( value == null ) {
296
            return null;
297
        }
298
        if( !(value instanceof Date) ) {
299
            String type = value.getClass().getCanonicalName();
300
            throw new IllegalArgumentException(
301
                    I18N.The_type_of_the_argument_XargnX_for_the_XIdentifierX_function_is_incorrect(name(), n) + " " +
302
                    I18N.Expected_XexpectedX_and_found_XfoundX("Date",type)
303
            );
304
        }
305
        return (Date)value;
306
    }
307
    
308
    protected LocalDateTime getLocalDateTime(Object[] args, int n) {
309
        if( args.length < n  ) {
310
            throw new IllegalArgumentException(I18N.Required_argument_XargnX_and_only_found_XargcX_in_call_to_XIdentifierX(name(), args.length, n));
311
        }
312
        Object value = args[n];
313
        if( value == null ) {
314
            return null;
315
        }
316
        if( value instanceof Date ) {
317
            Date date = ((Date)value);
318
            return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
319
        }
320
        if( value instanceof LocalDateTime ) {
321
            return (LocalDateTime) value;
322
        }
323
        if( value instanceof TemporalAccessor ) {
324
            return LocalDateTime.from(((TemporalAccessor)value));
325
        }
326
        String type = value.getClass().getCanonicalName();
327
        throw new IllegalArgumentException(
328
                I18N.The_type_of_the_argument_XargnX_for_the_XIdentifierX_function_is_incorrect(name(), n) + " " +
329
                I18N.Expected_XexpectedX_and_found_XfoundX("Temporal/Date",type)
330
        );
331
    }
332
    
333
    protected boolean getBoolean(Object args[], int n, Double accuracy) {
334
        if( args.length < n  ) {
335
            throw new IllegalArgumentException(I18N.Required_argument_XargnX_and_only_found_XargcX_in_call_to_XIdentifierX(name(), args.length, n));
336
        }
337
        Object value = args[n];
338
        return toBoolean(value, accuracy);
339
    }
340

    
341
    protected boolean getBoolean(Interpreter interpreter, Codes args, int n) {
342
        Object value = getObject(interpreter, args, n);
343
        return toBoolean(value, interpreter.getAccuracy());
344
    }
345

    
346
    protected boolean toBoolean(Object value, Double accuracy) {
347
        if( value == null ) {
348
            return false;
349
        }
350
        if( value instanceof Boolean ) {
351
            return (Boolean)value;
352
        }        
353
        if( value instanceof Number ) {
354
            return MathUtils.compareTo(
355
                ((Number) value).doubleValue(), 
356
                0,
357
                accuracy==null? MathUtils.EPSILON:accuracy
358
            ) == 0;
359
        }
360
        return BooleanUtils.toBoolean(value.toString());
361
    } 
362

    
363
    private void load_from_resource() {
364
        String lang = Locale.getDefault().getLanguage();
365
        URL url = this.getClass().getResource("/org/gvsig/expressionevaluator/functions/"+lang+"/"+this.name()+".json");
366
        if( url == null ) {
367
            url = this.getClass().getResource("/org/gvsig/expressionevaluator/functions/en/"+this.name()+".json");
368
            if( url == null ) {
369
                return;
370
            }
371
        }
372
        InputStream is = null;
373
        JSONObject json;
374
        try {
375
            is = url.openStream();
376
            List<String> lines = IOUtils.readLines(is);
377
            json = new JSONObject(StringUtils.join(lines,  "\n"));
378
        } catch (Exception ex) {
379
            return;
380
        } finally {
381
            IOUtils.closeQuietly(is);
382
        }
383
        
384
        if( json.has("group") ) {
385
            this.group = json.getString("group");
386
        }
387
        if( json.has("description") ) {
388
            Object x = json.get("description");
389
            if( x instanceof String ) {
390
                this.description = (String) x;
391
            } else if( x instanceof JSONArray ) {
392
                StringBuilder builder = new StringBuilder();
393
                for (int i = 0; i < ((JSONArray)x).length(); i++) {
394
                    if( i>0 ) {
395
                        builder.append(" ");
396
                    }
397
                    builder.append(((JSONArray)x).getString(i));
398
                }
399
                this.description = builder.toString();
400
            } else {
401
                this.description = x.toString();
402
            }
403
            this.description = StringUtils.replace(
404
                    this.description, 
405
                    "@@@", 
406
                    url.toString()
407
            );
408
        }
409
        if( json.has("template") ) {
410
            this.template = json.getString("template");
411
        }
412
        if( json.has("returnType") ) {
413
            this.returnType = json.getString("returnType");
414
        }
415
        if( json.has("sqlCompatible") ) {
416
            this.sqlCompatible = json.getBoolean("sqlCompatible");
417
        }
418
        if( json.has("args") ) {
419
            JSONArray x = json.getJSONArray("args");
420
            String[] args = new String[x.length()];
421
            for (int i = 0; i < x.length(); i++) {
422
                args[i] = x.getString(i);
423
            }
424
            this.descriptionArgs = args;
425
        }
426
        if( json.has("alias") ) {
427
            JSONArray x = json.getJSONArray("alias");
428
            for (int i = 0; i < x.length(); i++) {
429
                this.addAlias(x.getString(i));
430
            }
431
        }
432
    }
433
}