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

History | View | Annotate | Download (14.6 KB)

1
package org.gvsig.expressionevaluator.spi;
2

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

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

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

    
60
    protected AbstractFunction(String group, String name, Range argc, String description, String template) {
61
        this(group, name, argc, description, template, null, null);
62
    }
63

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

    
68
    @Override
69
    public String name() {
70
        return this.name;
71
    }
72

    
73
    @Override
74
    public String returnType() {
75
        return this.returnType;
76
    }
77

    
78
    @Override
79
    public String group() {
80
        return this.group;
81
    }
82

    
83
    @Override
84
    public Range argc() {
85
        return argc;
86
    }
87

    
88
    @Override
89
    public String description() {
90
        return description;
91
    }
92

    
93
    @Override
94
    public String[] descriptionArgs() {
95
        return descriptionArgs;
96
    }
97

    
98
    @Override
99
    public void addAlias(String name) {
100
        if( StringUtils.isBlank(name) ) {
101
            return;
102
        }
103
        if( this.alias == null ) {
104
            this.alias = new ArrayList<>();
105
        }
106
        if( this.alias.contains(name) ) {
107
            return;
108
        }
109
        this.alias.add(name);
110
    }
111

    
112
    @Override
113
    public List<String> aliases() {
114
        return this.alias;
115
    }
116

    
117
    @Override
118
    public String template() {
119
        return this.template;
120
    }
121

    
122
    @Override
123
    public boolean isOperator() {
124
        return false;
125
    }
126

    
127
    @Override
128
    public boolean useArgumentsInsteadObjects() {
129
        return false;
130
    }
131

    
132
    @Override
133
    public boolean isSQLCompatible() {
134
        return sqlCompatible;
135
    }
136

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

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

    
183
    protected double getDouble(Object args[], int n) {
184
        if( args.length < n  ) {
185
            throw new IllegalArgumentException(I18N.Required_argument_XargnX_and_only_found_XargcX_in_call_to_XIdentifierX(name(), args.length, n));
186
        }
187
        Object value = args[n];
188
        if( value == null ) {
189
            throw new IllegalArgumentException(I18N.Illegal_null_value_for_argument_XargnX_of_XIdentifierX_function(name(), n));
190
        }
191
        if( !(value instanceof Number) ) {
192
            String type = value.getClass().getCanonicalName();
193
            throw new IllegalArgumentException(
194
                    I18N.The_type_of_the_argument_XargnX_for_the_XIdentifierX_function_is_incorrect(name(), n) + " " +
195
                    I18N.Expected_XexpectedX_and_found_XfoundX("Number",type)
196
            );
197
        }
198
        return ((Number)value).doubleValue();
199
    }
200
    
201
    protected String getStr(Object args[], int n) {
202
        if( args.length < n  ) {
203
            throw new IllegalArgumentException(I18N.Required_argument_XargnX_and_only_found_XargcX_in_call_to_XIdentifierX(name(), args.length, n));
204
        }
205
        return Objects.toString(args[n], "");
206
    }
207
    
208
    protected Object getObject(Object args[], int n) {
209
        if( args.length < n  ) {
210
            throw new IllegalArgumentException(I18N.Required_argument_XargnX_and_only_found_XargcX_in_call_to_XIdentifierX(name(), args.length, n));
211
        }
212
        return args[n];
213
    }
214
    
215
    protected Object getObject(Interpreter interpreter, Codes args, int n) {
216
        if( args.size() < n  ) {
217
            throw new IllegalArgumentException(I18N.Required_argument_XargnX_and_only_found_XargcX_in_call_to_XIdentifierX(name(), args.size(), n));
218
        }
219
        Code arg = args.get(n);
220
        Object value = interpreter.run(arg);
221
        return value;
222
    }
223
    
224
    protected Geometry getGeom(Object[] args, int n) {
225
        return this.getGeom(args, n, false);
226
    }
227
    
228
    protected Geometry getGeom(Object[] args, int n, boolean allowNull) {
229
        if( args.length < n  ) {
230
            throw new IllegalArgumentException(I18N.Required_argument_XargnX_and_only_found_XargcX_in_call_to_XIdentifierX(name(), args.length, n));
231
        }
232
        Object value = args[n];
233
        if( value == null ) {
234
            if( allowNull ) {
235
                return null;
236
            }
237
            throw new IllegalArgumentException(I18N.Illegal_null_value_for_argument_XargnX_of_XIdentifierX_function(name(), n));
238
        }
239
        if( !(value instanceof Geometry) ) {
240
            String type = value.getClass().getCanonicalName();
241
            throw new IllegalArgumentException(
242
                    I18N.The_type_of_the_argument_XargnX_for_the_XIdentifierX_function_is_incorrect(name(), n) + " " +
243
                    I18N.Expected_XexpectedX_and_found_XfoundX("Geometry",type)
244
            );
245
        }
246
        return (Geometry)value;
247
    }
248

    
249
    protected Point getPoint(Object[] args, int n) {
250
        if( args.length < n  ) {
251
            throw new IllegalArgumentException(I18N.Required_argument_XargnX_and_only_found_XargcX_in_call_to_XIdentifierX(name(), args.length, n));
252
        }
253
        Object value = args[n];
254
        if( value == null ) {
255
            return null;
256
        }
257
        if( !(value instanceof Point) ) {
258
            String type = value.getClass().getCanonicalName();
259
            throw new IllegalArgumentException(
260
                    I18N.The_type_of_the_argument_XargnX_for_the_XIdentifierX_function_is_incorrect(name(), n) + " " +
261
                    I18N.Expected_XexpectedX_and_found_XfoundX("Point",type)
262
            );
263
        }
264
        return (Point)value;
265
    }
266
    
267
    protected Date getDate(Object[] args, int n) {
268
        if( args.length < n  ) {
269
            throw new IllegalArgumentException(I18N.Required_argument_XargnX_and_only_found_XargcX_in_call_to_XIdentifierX(name(), args.length, n));
270
        }
271
        Object value = args[n];
272
        if( value == null ) {
273
            return null;
274
        }
275
        if( !(value instanceof Date) ) {
276
            String type = value.getClass().getCanonicalName();
277
            throw new IllegalArgumentException(
278
                    I18N.The_type_of_the_argument_XargnX_for_the_XIdentifierX_function_is_incorrect(name(), n) + " " +
279
                    I18N.Expected_XexpectedX_and_found_XfoundX("Date",type)
280
            );
281
        }
282
        return (Date)value;
283
    }
284
    
285
    protected LocalDateTime getLocalDateTime(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
        Object value = args[n];
290
        if( value == null ) {
291
            return null;
292
        }
293
        if( value instanceof Date ) {
294
            Date date = ((Date)value);
295
            return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
296
        }
297
        if( value instanceof LocalDateTime ) {
298
            return (LocalDateTime) value;
299
        }
300
        if( value instanceof TemporalAccessor ) {
301
            return LocalDateTime.from(((TemporalAccessor)value));
302
        }
303
        String type = value.getClass().getCanonicalName();
304
        throw new IllegalArgumentException(
305
                I18N.The_type_of_the_argument_XargnX_for_the_XIdentifierX_function_is_incorrect(name(), n) + " " +
306
                I18N.Expected_XexpectedX_and_found_XfoundX("Temporal/Date",type)
307
        );
308
    }
309
    
310
    protected boolean getBoolean(Object args[], int n, Double accuracy) {
311
        if( args.length < n  ) {
312
            throw new IllegalArgumentException(I18N.Required_argument_XargnX_and_only_found_XargcX_in_call_to_XIdentifierX(name(), args.length, n));
313
        }
314
        Object value = args[n];
315
        return toBoolean(value, accuracy);
316
    }
317

    
318
    protected boolean getBoolean(Interpreter interpreter, Codes args, int n) {
319
        Object value = getObject(interpreter, args, n);
320
        return toBoolean(value, interpreter.getAccuracy());
321
    }
322

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

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