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

History | View | Annotate | Download (31.7 KB)

1
package org.gvsig.expressionevaluator.spi;
2

    
3
import java.io.File;
4
import java.math.BigDecimal;
5
import java.net.MalformedURLException;
6
import java.net.URI;
7
import java.net.URISyntaxException;
8
import java.net.URL;
9
import java.nio.charset.StandardCharsets;
10
import java.time.LocalDate;
11
import java.time.LocalDateTime;
12
import java.time.ZoneId;
13
import java.time.ZoneOffset;
14
import java.time.temporal.TemporalAccessor;
15
import java.util.ArrayList;
16
import java.util.Date;
17
import java.util.List;
18
import java.util.Locale;
19
import java.util.Objects;
20
import java.util.regex.Matcher;
21
import java.util.regex.Pattern;
22
import javax.json.JsonArray;
23
import javax.json.JsonObject;
24
import javax.json.JsonStructure;
25
import org.apache.commons.io.FilenameUtils;
26
import org.apache.commons.io.IOUtils;
27
import org.apache.commons.lang3.BooleanUtils;
28
import org.apache.commons.lang3.Range;
29
import org.apache.commons.lang3.StringUtils;
30
import org.apache.commons.math.exception.OutOfRangeException;
31
import org.apache.commons.math.util.MathUtils;
32
import org.gvsig.expressionevaluator.Code;
33
import org.gvsig.expressionevaluator.Codes;
34
import org.gvsig.expressionevaluator.ExpressionBuilder;
35
import org.gvsig.expressionevaluator.ExpressionRuntimeException;
36
import org.gvsig.expressionevaluator.Formatter;
37
import org.gvsig.expressionevaluator.Function;
38
import org.gvsig.expressionevaluator.I18N;
39
import org.gvsig.expressionevaluator.Interpreter;
40
import org.gvsig.tools.ToolsLocator;
41
import org.gvsig.tools.dataTypes.DataTypeUtils;
42
import org.gvsig.tools.i18n.I18nManager;
43
import org.gvsig.tools.util.GetItem;
44
import org.gvsig.tools.util.GetItem64;
45
import org.gvsig.tools.util.GetItemWithSize64;
46
import org.gvsig.tools.util.Size;
47
import org.gvsig.tools.util.Size64;
48
//import org.gvsig.fmap.geom.Geometry;
49
//import org.gvsig.fmap.geom.primitive.Point;
50
import org.json.JSONArray;
51
import org.json.JSONObject;
52
import org.slf4j.Logger;
53
import org.slf4j.LoggerFactory;
54

    
55
@SuppressWarnings("UseSpecificCatch")
56
public abstract class AbstractFunction implements Function {
57
 
58
    protected static Logger LOGGER = LoggerFactory.getLogger(AbstractFunction.class);
59
    
60
    private final String name;
61
    private String group;
62
    private Range argc;
63
    private String description;
64
    private String[] descriptionArgs;
65
    private List<String> alias;
66
    private String template;
67
    private String returnType;
68
    private boolean sqlCompatible;
69

    
70
    protected AbstractFunction(String group, String name, Range argc, String description, String template, String[] descriptionArgs, String returnType, boolean sqlCompatible) {
71
        this.name = name;
72
        this.group = group;
73
        this.argc = argc;
74
        this.description = description;
75
        this.template = template;
76
        this.descriptionArgs = descriptionArgs;
77
        this.returnType = returnType;
78
        this.sqlCompatible = sqlCompatible;
79
        load_from_resource();
80
    }
81
    protected AbstractFunction(String group, String name, Range argc, String description, String template, String[] descriptionArgs, String returnType) {
82
        this(group, name, argc, description, template, descriptionArgs, returnType, false);
83
    }
84
    
85
    protected AbstractFunction(String group, String name, Range argc, String description, String template, String[] descriptionArgs) {
86
        this(group, name, argc, description, template, null, null);
87
    }
88

    
89
    protected AbstractFunction(String group, String name, Range argc, String description, String template) {
90
        this(group, name, argc, description, template, null, null);
91
    }
92

    
93
    protected AbstractFunction(String group, String name, Range argc) {
94
        this(group, name, argc, null, null, null, null);
95
    }
96

    
97
    @Override
98
    public String name() {
99
        return this.name;
100
    }
101

    
102
    @Override
103
    public String returnType() {
104
        return this.returnType;
105
    }
106

    
107
    @Override
108
    public String group() {
109
        return this.group;
110
    }
111

    
112
    @Override
113
    public Range argc() {
114
        return argc;
115
    }
116

    
117
    @Override
118
    public String description() {
119
        if( StringUtils.equalsIgnoreCase(System.getProperty("ExpressionEvaluatorReloadFunctionResources"), "true")) {
120
            load_from_resource();
121
        }
122
        return description;
123
    }
124

    
125
    @Override
126
    public String[] descriptionArgs() {
127
        return descriptionArgs;
128
    }
129

    
130
    @Override
131
    public String getFullDescription() {
132
        I18nManager i18n = ToolsLocator.getI18nManager();
133

    
134
        StringBuilder html = new StringBuilder();
135
        html.append("<html>\n");
136

    
137
        // Lo primero llamamos a description() para forzar la recarga de los
138
        // recursos si fuese necesaria.
139
        String functionDescription = this.description();
140

    
141
        html.append("<b>").append(i18n.getTranslation("_Function")).append("</b> ").append(this.name()).append("<br>\n<br>\n");
142
        List<String> aliases = this.aliases();
143
        if( aliases!=null && !aliases.isEmpty() ) {
144
            html.append("<b>").append(i18n.getTranslation("_Aliases")).append(":</b> ").append("<ul>\n");
145
            for (String theAlias : aliases) {
146
                html.append("<li>").append(theAlias).append("</li>\n");
147
            }
148
            html.append("</ul>\n");
149
        }
150
        html.append("<b>").append(i18n.getTranslation("_Return")).append("</b> ");
151
        html.append(StringUtils.isEmpty(this.returnType()) ? "Objec" : this.returnType());
152
        html.append("<br>\n");
153
        html.append("<b>").append(i18n.getTranslation("_Template")).append("</b> ");
154
        html.append(StringUtils.isEmpty(this.template()) ? this.name() + "()" : this.template());
155
        html.append("<br>\n");
156

    
157
        String[] args = this.descriptionArgs();
158
        if (args != null) {
159
            html.append("<b>").append(i18n.getTranslation("_Arguments")).append(":</b> ").append("<ul>\n");
160
            for (String arg : args) {
161
                html.append("<li>").append(arg).append("</li>\n");
162
            }
163
            html.append("</ul>\n");
164
            html.append("<br>\n");
165
        }
166

    
167
        html.append("<b>").append(i18n.getTranslation("_SQL_compatible")).append("</b> ");
168
        html.append(this.isSQLCompatible()).append("<br>\n");
169

    
170
        if( !StringUtils.isBlank(functionDescription) ) {
171
            html.append("<b>").append(i18n.getTranslation("_Description")).append("</b><br>\n");
172
            html.append(functionDescription.replace("\n", "<br>")).append("<br>\n");
173
        }            
174

    
175
        html.append("</html>\n");
176
        return html.toString();
177
    }
178

    
179
    @Override
180
    public void addAlias(String name) {
181
        if( StringUtils.isBlank(name) ) {
182
            return;
183
        }
184
        if( this.alias == null ) {
185
            this.alias = new ArrayList<>();
186
        }
187
        if( this.alias.contains(name) ) {
188
            return;
189
        }
190
        this.alias.add(name);
191
    }
192

    
193
    @Override
194
    public List<String> aliases() {
195
        return this.alias;
196
    }
197

    
198
    @Override
199
    public String template() {
200
        return this.template;
201
    }
202

    
203
    @Override
204
    public boolean isOperator() {
205
        return false;
206
    }
207

    
208
    @Override
209
    public boolean isHidden() {
210
      return false;
211
    }
212
    
213
    @Override
214
    public boolean useArgumentsInsteadObjects() {
215
        return false;
216
    }
217

    
218
    @Override
219
    public boolean isSQLCompatible() {
220
        return sqlCompatible;
221
    }
222

    
223
    @Override
224
    public boolean allowConstantFolding() {
225
        return false;
226
    }
227

    
228
    @Override
229
    public Object call(Interpreter interpreter, Codes args) throws Exception {
230
        return null;
231
    }
232
    
233
    protected int getInt(Object args[], int n) {
234
        if( args.length < n  ) {
235
            throw new IllegalArgumentException(I18N.Required_argument_XargnX_and_only_found_XargcX_in_call_to_XIdentifierX(name(), args.length, n));
236
        }
237
        return getInt(args[n],n);
238
    }
239

    
240
    protected int getInt(Object value, int n) {
241
        if( value == null ) {
242
            throw new IllegalArgumentException(I18N.Illegal_null_value_for_argument_XargnX_of_XIdentifierX_function(name(), n));
243
        }
244
        if( !(value instanceof Number) ) {
245
            String type = value.getClass().getCanonicalName();
246
            throw new IllegalArgumentException(
247
                    I18N.The_type_of_the_argument_XargnX_for_the_XIdentifierX_function_is_incorrect(name(), n) + " " +
248
                    I18N.Expected_XexpectedX_and_found_XfoundX("Number",type)
249
            );
250
        }
251
        return ((Number)value).intValue();
252
    }
253
    
254
    protected int getInt(Interpreter interpreter, Codes args, int n) {
255
        Object value = getObject(interpreter, args, n);
256
        return getInt(value, n);
257
    }    
258

    
259
    protected long getLong(Object args[], int n) {
260
        if( args.length < n  ) {
261
            throw new IllegalArgumentException(I18N.Required_argument_XargnX_and_only_found_XargcX_in_call_to_XIdentifierX(name(), args.length, n));
262
        }
263
        return getLong(args[n],n);
264
    }
265

    
266
    protected long getLong(Object value, int n) {
267
        if( value == null ) {
268
            throw new IllegalArgumentException(I18N.Illegal_null_value_for_argument_XargnX_of_XIdentifierX_function(name(), n));
269
        }
270
        if( !(value instanceof Number) ) {
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("Number",type)
275
            );
276
        }
277
        return ((Number)value).longValue();
278
    }
279

    
280
    protected double getDouble(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
        return getDouble(args[n],n);
285
    }
286

    
287
    protected double getDouble(Object value, int arg) {
288
        if( value == null ) {
289
            throw new IllegalArgumentException(I18N.Illegal_null_value_for_argument_XargnX_of_XIdentifierX_function(name(), arg));
290
        }
291
        if( !(value instanceof Number) ) {
292
            String type = value.getClass().getCanonicalName();
293
            throw new IllegalArgumentException(
294
                    I18N.The_type_of_the_argument_XargnX_for_the_XIdentifierX_function_is_incorrect(name(), arg) + " " +
295
                    I18N.Expected_XexpectedX_and_found_XfoundX("Number",type)
296
            );
297
        }
298
        return ((Number)value).doubleValue();
299
    }
300
    
301
    protected BigDecimal getBigDecimal(Object value, int arg) {
302
        if( value == null ) {
303
            throw new IllegalArgumentException(I18N.Illegal_null_value_for_argument_XargnX_of_XIdentifierX_function(name(), arg));
304
        }
305
        if( !(value instanceof Number) ) {
306
            String type = value.getClass().getCanonicalName();
307
            throw new IllegalArgumentException(
308
                    I18N.The_type_of_the_argument_XargnX_for_the_XIdentifierX_function_is_incorrect(name(), arg) + " " +
309
                    I18N.Expected_XexpectedX_and_found_XfoundX("Number",type)
310
            );
311
        }
312
        if(value instanceof Long || value instanceof Integer || value instanceof Short || value instanceof Byte) {
313
            return BigDecimal.valueOf(((Number) value).longValue());
314
        }
315
        return BigDecimal.valueOf(((Number) value).doubleValue());
316
    }
317
    
318
    protected float getFloat(Object args[], int n) {
319
        if( args.length < n  ) {
320
            throw new IllegalArgumentException(I18N.Required_argument_XargnX_and_only_found_XargcX_in_call_to_XIdentifierX(name(), args.length, n));
321
        }
322
        return getFloat(args[n],n);
323
    }
324

    
325
    protected float getFloat(Object value, int arg) {
326
        if( value == null ) {
327
            throw new IllegalArgumentException(I18N.Illegal_null_value_for_argument_XargnX_of_XIdentifierX_function(name(), arg));
328
        }
329
        if( !(value instanceof Number) ) {
330
            String type = value.getClass().getCanonicalName();
331
            throw new IllegalArgumentException(
332
                    I18N.The_type_of_the_argument_XargnX_for_the_XIdentifierX_function_is_incorrect(name(), arg) + " " +
333
                    I18N.Expected_XexpectedX_and_found_XfoundX("Number",type)
334
            );
335
        }
336
        return ((Number)value).floatValue();
337
    }
338
    
339
    protected String getStr(Object args[], int n) {
340
        if( args.length < n  ) {
341
            throw new IllegalArgumentException(I18N.Required_argument_XargnX_and_only_found_XargcX_in_call_to_XIdentifierX(name(), args.length, n));
342
        }
343
        return getStr(args[n],n);
344
    }
345
    
346
    protected String getStr(Object value, int n) {
347
        return Objects.toString(value, ""); //No est? claro si deber?a ser "" o null
348
    }
349
    
350
    protected File getFile(Object args[], int n) {
351
        if( args.length < n  ) {
352
            throw new IllegalArgumentException(I18N.Required_argument_XargnX_and_only_found_XargcX_in_call_to_XIdentifierX(name(), args.length, n));
353
        }
354
        return getFile(args[n],n);
355
    }
356
    
357
    protected File getFile(Object value, int n) {
358
        if( value == null ) {
359
            return null;
360
        }
361
        if( value instanceof File ) {
362
            return (File)value;
363
        }
364
        if( value instanceof URL ) {
365
            try {
366
                return new File(((URL)value).toURI());
367
            } catch (URISyntaxException ex) {
368
                return null;
369
            }
370
        }
371
        if( value instanceof URI ) {
372
            return new File(((URI)value));
373
        }
374
        String s = Objects.toString(value, null);
375
        if( s == null ) {
376
            return null;
377
        }
378
        File f = new File(s);
379
        return f;
380
    }
381

    
382
    protected boolean isNull(Object args[], int n) {
383
        return getObject(args, n)==null;
384
    }
385
    
386
    protected Object getObject(Object args[], int n) {
387
        if( args.length < n  ) {
388
            throw new IllegalArgumentException(I18N.Required_argument_XargnX_and_only_found_XargcX_in_call_to_XIdentifierX(name(), args.length, n));
389
        }
390
        return args[n];
391
    }
392
    
393
    protected JsonObject getJsonObject(Object args[], int n) {
394
        if( args.length < n  ) {
395
            throw new IllegalArgumentException(I18N.Required_argument_XargnX_and_only_found_XargcX_in_call_to_XIdentifierX(name(), args.length, n));
396
        }
397
        return getJsonObject(args[n],n);
398
    }
399

    
400
    protected JsonObject getJsonObject(Object value, int n) {
401
        if( value == null ) {
402
            throw new IllegalArgumentException(I18N.Illegal_null_value_for_argument_XargnX_of_XIdentifierX_function(name(), n));
403
        }
404
        if( !(value instanceof JSONObject) ) {
405
            try {
406
                value = JsonUtils.toJsonObject(value);
407
            } catch(Throwable th) {
408
                String type = value.getClass().getCanonicalName();
409
                throw new IllegalArgumentException(
410
                    I18N.The_type_of_the_argument_XargnX_for_the_XIdentifierX_function_is_incorrect(name(), n) + " " +
411
                    I18N.Expected_XexpectedX_and_found_XfoundX("JsonObject",type),
412
                    th
413
                );
414
            }
415
        }
416
        return (JsonObject) value;
417
    }
418

    
419
    protected JsonArray getJsonArray(Object args[], int n) {
420
        if( args.length < n  ) {
421
            throw new IllegalArgumentException(I18N.Required_argument_XargnX_and_only_found_XargcX_in_call_to_XIdentifierX(name(), args.length, n));
422
        }
423
        return getJsonArray(args[n],n);
424
    }
425

    
426
    protected JsonArray getJsonArray(Object value, int n) {
427
        if( value == null ) {
428
            throw new IllegalArgumentException(I18N.Illegal_null_value_for_argument_XargnX_of_XIdentifierX_function(name(), n));
429
        }
430
        if( !(value instanceof JsonArray) ) {
431
            try {
432
                value = JsonUtils.toJsonArray(value);
433
            } catch(Throwable th) {
434
                String type = value.getClass().getCanonicalName();
435
                throw new IllegalArgumentException(
436
                    I18N.The_type_of_the_argument_XargnX_for_the_XIdentifierX_function_is_incorrect(name(), n) + " " +
437
                    I18N.Expected_XexpectedX_and_found_XfoundX("JsonObject",type),
438
                    th
439
                );
440
            }
441
        }
442
        return (JsonArray) value;
443
    }
444

    
445
    protected JsonStructure getJsonStructure(Object args[], int n) {
446
        if( args.length < n  ) {
447
            throw new IllegalArgumentException(I18N.Required_argument_XargnX_and_only_found_XargcX_in_call_to_XIdentifierX(name(), args.length, n));
448
        }
449
        return getJsonStructure(args[n],n);
450
    }
451

    
452
    protected JsonStructure getJsonStructure(Object value, int n) {
453
        if( value == null ) {
454
            throw new IllegalArgumentException(I18N.Illegal_null_value_for_argument_XargnX_of_XIdentifierX_function(name(), n));
455
        }
456
        if( !(value instanceof JsonStructure) ) {
457
            try {
458
                value = JsonUtils.toJson(value);
459
            } catch(Throwable th) {
460
                String type = value.getClass().getCanonicalName();
461
                throw new IllegalArgumentException(
462
                    I18N.The_type_of_the_argument_XargnX_for_the_XIdentifierX_function_is_incorrect(name(), n) + " " +
463
                    I18N.Expected_XexpectedX_and_found_XfoundX("JsonObject",type),
464
                    th
465
                );
466
            }
467
        }
468
        return (JsonStructure) value;
469
    }
470

    
471
    protected Object getObject(Interpreter interpreter, Codes args, int n) {
472
        if( args.size() < n  ) {
473
            throw new IllegalArgumentException(I18N.Required_argument_XargnX_and_only_found_XargcX_in_call_to_XIdentifierX(name(), args.size(), n));
474
        }
475
        Code arg = args.get(n);
476
        if( arg==null ) {
477
            return null;
478
        }
479
        Object value = null;
480
        try {
481
            value = interpreter.runCode(arg);
482
        } catch(RuntimeException ex) {
483
            throw ex;
484
        } catch(Exception ex) {
485
            throw new ExpressionRuntimeException(arg, "", ex);
486
        }
487

    
488
        return value;
489
    }
490
    
491
    protected Comparable getComparable(Object[] args, int n) {
492
        if( args.length < n  ) {
493
            throw new IllegalArgumentException(I18N.Required_argument_XargnX_and_only_found_XargcX_in_call_to_XIdentifierX(name(), args.length, n));
494
        }
495
        return getComparable(args[n],n);
496
    }
497
    
498
    protected Comparable getComparable(Object value, int n) {
499
        if( value == null ) {
500
            return null;
501
        }
502
        if( !(value instanceof Comparable) ) {
503
            String type = value.getClass().getCanonicalName();
504
            throw new IllegalArgumentException(
505
                    I18N.The_type_of_the_argument_XargnX_for_the_XIdentifierX_function_is_incorrect(name(), n) + " " +
506
                    I18N.Expected_XexpectedX_and_found_XfoundX("Comparable",type)
507
            );
508
        }
509
        return (Comparable)value;
510
    }
511

    
512
    protected Comparable getDate(Object[] args, int n) {
513
        if( args.length < n  ) {
514
            throw new IllegalArgumentException(I18N.Required_argument_XargnX_and_only_found_XargcX_in_call_to_XIdentifierX(name(), args.length, n));
515
        }
516
        return getDate(args[n],n);
517
    }
518
    
519
    protected Date getDate(Object value, int n) {
520
        if( value == null ) {
521
            return null;
522
        }
523
        if( !(value instanceof Date) ) {
524
            String type = value.getClass().getCanonicalName();
525
            throw new IllegalArgumentException(
526
                    I18N.The_type_of_the_argument_XargnX_for_the_XIdentifierX_function_is_incorrect(name(), n) + " " +
527
                    I18N.Expected_XexpectedX_and_found_XfoundX("Date",type)
528
            );
529
        }
530
        return (Date)value;
531
    }
532
    
533
    protected LocalDateTime getLocalDateTime(Object[] args, int n) {
534
        if( args.length < n  ) {
535
            throw new IllegalArgumentException(I18N.Required_argument_XargnX_and_only_found_XargcX_in_call_to_XIdentifierX(name(), args.length, n));
536
        }
537
        return getLocalDateTime(args[n],n);
538
    }
539
    
540
    protected LocalDateTime getLocalDateTime(Object value, int n) {
541
        if( value == null ) {
542
            return null;
543
        }
544
        if( value instanceof java.sql.Date) {
545
            java.sql.Date sqlDate = (java.sql.Date) value;
546
            // TODO
547
            //sqlDate.getTime() construir date
548
            LocalDate date = sqlDate.toLocalDate();
549
            return date.atStartOfDay(ZoneOffset.UTC).toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
550
        } else if( value instanceof Date ) {
551
            Date date = ((Date)value); //dataTypeUtils
552
            return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
553
        }
554
        if( value instanceof LocalDateTime ) {
555
            return (LocalDateTime) value;
556
        }
557
        if( value instanceof TemporalAccessor ) {
558
            return LocalDateTime.from(((TemporalAccessor)value));
559
        }
560
        String type = value.getClass().getCanonicalName();
561
        throw new IllegalArgumentException(
562
                I18N.The_type_of_the_argument_XargnX_for_the_XIdentifierX_function_is_incorrect(name(), n) + " " +
563
                I18N.Expected_XexpectedX_and_found_XfoundX("Temporal/Date",type)
564
        );
565
    }
566

    
567
    public URL getURL(Object[] args, int index) throws MalformedURLException {
568
        Object obj = getObject(args, index);
569
        if( obj == null ) {
570
            return null;
571
        }  
572
        URL url;
573
        if( obj instanceof URL ) {
574
            url = (URL) obj;        } else if( obj instanceof CharSequence ) {
575
            url = new URL(((CharSequence)obj).toString());
576
        } else if( obj instanceof File ) {
577
            url = ((File)obj).toURI().toURL();
578
        } else if( obj instanceof URI ) {
579
            url = ((URI)obj).toURL();
580
        } else {
581
            throw new ExpressionRuntimeException("The "+this.name()+" function require a File, URI or a String and a received a '"+obj.getClass().getSimpleName()+"'.");
582
        }  
583
        return url;
584
    }
585
    
586
    protected boolean getBoolean(Object args[], int n, Double accuracy) {
587
        if( args.length < n  ) {
588
            throw new IllegalArgumentException(I18N.Required_argument_XargnX_and_only_found_XargcX_in_call_to_XIdentifierX(name(), args.length, n));
589
        }
590
        return getBoolean(args[n], n, accuracy);
591
    }
592

    
593
    protected boolean getBoolean(Object args[], int n) {
594
        if( args.length < n  ) {
595
            throw new IllegalArgumentException(I18N.Required_argument_XargnX_and_only_found_XargcX_in_call_to_XIdentifierX(name(), args.length, n));
596
        }
597
        return getBoolean(args[n], n, MathUtils.EPSILON);
598
    }
599

    
600
    protected boolean getBoolean(Object value, int n) {
601
        return getBoolean(value, n, MathUtils.EPSILON);
602
    }
603

    
604
    protected boolean getBoolean(Object value, int n, Double accuracy) {
605
        return toBoolean(value, accuracy);
606
    }
607

    
608
    protected boolean getBoolean(Interpreter interpreter, Codes args, int n) {
609
        Object value = getObject(interpreter, args, n);
610
        return toBoolean(value, interpreter.getAccuracy());
611
    }
612

    
613
    protected boolean toBoolean(Object value, Double accuracy) {
614
        if( value == null ) {
615
            return false;
616
        }
617
        if( value instanceof Boolean ) {
618
            return (Boolean)value;
619
        }        
620
        if( value instanceof Number ) {
621
            return MathUtils.compareTo(
622
                ((Number) value).doubleValue(), 
623
                0,
624
                accuracy==null? MathUtils.EPSILON:accuracy
625
            ) == 0;
626
        }
627
        return BooleanUtils.toBoolean(value.toString());
628
    } 
629
    
630
    protected GetItemWithSize64 getList(Object[] args, int index)  {
631
        Object value = getObject(args, index);
632
        if( value == null ) {
633
            return null;
634
        }  
635
        GetItemWithSize64 list = null;
636
        if (value instanceof List) {
637
            list = new GetItemWithSize64<Object>() {
638
                @Override
639
                public long size64() {
640
                    return ((List) value).size();
641
                }
642

    
643
                @Override
644
                public Object get64(long index) {
645
                    return ((List) value).get((int) index);
646
                }
647
            };
648
        } else if (value instanceof Object[]) {
649
            list = new GetItemWithSize64<Object>() {
650
                @Override
651
                public long size64() {
652
                    return ((Object[]) value).length;
653
                }
654

    
655
                @Override
656
                public Object get64(long index) {
657
                    return ((Object[]) value)[(int) index];
658
                }
659
            };
660
        } else if (value instanceof GetItemWithSize64 ) {
661
            list = (GetItemWithSize64) value;
662
            
663
        } else if (value instanceof GetItem && value instanceof Size) {
664
            list = new GetItemWithSize64<Object>() {
665
                @Override
666
                public long size64() {
667
                    return ((Size) value).size();
668
                }
669

    
670
                @Override
671
                public Object get64(long index) {
672
                    return ((GetItem) value).get((int) index);
673
                }
674
            };
675
        } else if (value instanceof GetItem64 && value instanceof Size64) {
676
            list = new GetItemWithSize64<Object>() {
677
                @Override
678
                public long size64() {
679
                    return ((Size64) value).size64();
680
                }
681

    
682
                @Override
683
                public Object get64(long index) {
684
                    return ((GetItem64) value).get64((int) index);
685
                }
686
            };
687
        }
688
        return list;
689
    }
690
    
691

    
692
    private void load_from_resource() {
693
        String lang = Locale.getDefault().getLanguage();
694
        URL url = this.getClass().getResource("/org/gvsig/expressionevaluator/functions/"+lang+"/"+this.name()+".json");
695
        if( url == null ) {
696
            url = this.getClass().getResource("/org/gvsig/expressionevaluator/functions/en/"+this.name()+".json");
697
            if( url == null ) {
698
                return;
699
            }
700
        }
701
        JSONObject json;
702
        try {
703
            json = new JSONObject(IOUtils.toString(url, StandardCharsets.UTF_8));
704
        } catch (Exception ex) {
705
            return;
706
        }
707
        
708
        if( json.has("group") ) {
709
            this.group = json.getString("group");
710
        }
711
        if( json.has("description") ) {
712
            Object x = json.get("description");
713
            if( x instanceof String ) {
714
                this.description = (String) x;
715
            } else if( x instanceof JSONArray ) {
716
                StringBuilder builder = new StringBuilder();
717
                for (int i = 0; i < ((JSONArray)x).length(); i++) {
718
                    if( i>0 ) {
719
                        builder.append(" ");
720
                    }
721
                    builder.append(((JSONArray)x).getString(i));
722
                }
723
                this.description = builder.toString();
724
            } else {
725
                this.description = Objects.toString(x, null);
726
            }
727
            this.description = process_includes(url, this.description);
728
            this.description = StringUtils.replace(
729
                    this.description, 
730
                    "@@@", 
731
                    url.toString()
732
            );
733
        }
734
        if( json.has("template") ) {
735
            this.template = json.getString("template");
736
        }
737
        if( json.has("returnType") ) {
738
            this.returnType = json.getString("returnType");
739
        }
740
        if( json.has("sqlCompatible") ) {
741
            this.sqlCompatible = json.getBoolean("sqlCompatible");
742
        }
743
        if( json.has("args") ) {
744
            JSONArray x = json.getJSONArray("args");
745
            String[] args = new String[x.length()];
746
            for (int i = 0; i < x.length(); i++) {
747
                args[i] = x.getString(i);
748
            }
749
            this.descriptionArgs = args;
750
        }
751
        if( json.has("alias") ) {
752
            JSONArray x = json.getJSONArray("alias");
753
            for (int i = 0; i < x.length(); i++) {
754
                this.addAlias(x.getString(i));
755
            }
756
        }
757
    }
758
    
759
    private String process_includes(URL pathname, String text) {
760
        Pattern p1 = Pattern.compile("[<][%]include (?<fname>[a-zA-Z0-9_$.]+)[%][>]", Pattern.DOTALL);
761
        while(true) {
762
            Matcher m = p1.matcher(text);
763
            if( m==null || !m.find()) {
764
                return text;
765
            }
766
            String path = FilenameUtils.getPathNoEndSeparator(pathname.toString());
767
            String fname = m.group("fname");
768
            URL url;
769
            String replacement;
770
            try {
771
                url = new URL(path+"/"+fname);
772
                replacement = IOUtils.toString(url);
773
//                text = m.replaceAll(replacement);
774
                StringBuilder builder = new StringBuilder(text.length()+replacement.length());
775
                builder.append(text.substring(0, m.start()));
776
                builder.append(replacement);
777
                builder.append(text.substring(m.end()));
778
                text = builder.toString();
779
            } catch (Exception ex) {
780
                return text;
781
            }
782
        }
783
    }
784
    
785
    protected static final int TYPE_INT =        0b000000001;
786
    protected static final int TYPE_LONG =       0b000000010;
787
    protected static final int TYPE_FLOAT =      0b000000100;
788
    protected static final int TYPE_DOUBLE =     0b000001000;
789
    protected static final int TYPE_BOOLEAN =    0b000010000;
790
    protected static final int TYPE_STRING =     0b000100000;
791
    protected static final int TYPE_DATE =       0b001000000;
792
    protected static final int TYPE_NULL =       0b010000000;
793
    protected static final int TYPE_BIGDECIMAL = 0b100000000;
794
    
795
    protected int getType(Object op1, Object op2) {
796
        int r = 0;
797
        if( op1 == null ) {
798
            r |= TYPE_NULL;
799
        } else if( op1 instanceof BigDecimal ) {
800
            r |= TYPE_BIGDECIMAL;
801
        } else if( op1 instanceof Double ) {
802
            r |= TYPE_DOUBLE;
803
        } else if( op1 instanceof Float ) {
804
            r |= TYPE_FLOAT;
805
        } else if( op1 instanceof Long ) {
806
            r |= TYPE_LONG;
807
        } else if( op1 instanceof Integer ) {
808
            r |= TYPE_INT;
809
        } else if( op1 instanceof Boolean ) {
810
            r |= TYPE_BOOLEAN;
811
        } else if( op1 instanceof String ) {
812
            r |= TYPE_STRING;
813
        } else if( op1 instanceof Date ) {
814
            r |= TYPE_DATE;
815
        }
816
        if( op2 == null ) {
817
            r |= TYPE_NULL;
818
        } else if( op2 instanceof BigDecimal ) {
819
            r |= TYPE_BIGDECIMAL;
820
        } else if( op2 instanceof Double ) {
821
            r |= TYPE_DOUBLE;
822
        } else if( op2 instanceof Float ) {
823
            r |= TYPE_FLOAT;
824
        } else if( op2 instanceof Long ) {
825
            r |= TYPE_LONG;
826
        } else if( op2 instanceof Integer ) {
827
            r |= TYPE_INT;
828
        } else if( op2 instanceof Boolean ) {
829
            r |= TYPE_BOOLEAN;
830
        } else if( op2 instanceof String ) {
831
            r |= TYPE_STRING;
832
        } else if( op2 instanceof Date ) {
833
            r |= TYPE_DATE;
834
        }
835
        return r;
836
    }
837

    
838
    @Override
839
    public String toString(Codes args, Formatter<Code> formatter) {
840
        return null;
841
    }
842

    
843
    @Override
844
    public String toString() {
845
        return this.name;
846
    }
847
    
848
    protected void checkDoubleValue(double value) {
849
        if (Double.isInfinite(value)) {
850
            throw new OutOfRangeException(value, Double.MIN_VALUE, Double.MAX_VALUE);
851
        }
852

    
853
    }
854

    
855
    protected void checkFloatValue(float value) {
856
        if (Float.isInfinite(value)) {
857
            throw new OutOfRangeException(value, Float.MIN_VALUE, Float.MAX_VALUE);
858
        }
859

    
860
    }
861

    
862
    @Override
863
    public ExpressionBuilder.Value toValue(ExpressionBuilder builder, Codes parameters) {
864
        ExpressionBuilder.Function f = builder.function(this.name());
865
        if (parameters!= null) {
866
            for (Code parameter : parameters) {
867
                if (parameter == null) {
868
                    f.parameter(null);
869
                } else {
870
                    f.parameter(parameter.toValue(builder));
871
                }
872
            }
873
        }
874
        return f;
875

    
876
    }
877
    
878
    
879
}