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

History | View | Annotate | Download (31.5 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
        if( !StringUtils.isBlank(functionDescription) ) {
167
            html.append("<b>").append(i18n.getTranslation("_Description")).append("</b><br>\n");
168
            html.append(functionDescription.replace("\n", "<br>")).append("<br>\n");
169
        }            
170

    
171
        html.append("</html>\n");
172
        return html.toString();
173
    }
174

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

    
189
    @Override
190
    public List<String> aliases() {
191
        return this.alias;
192
    }
193

    
194
    @Override
195
    public String template() {
196
        return this.template;
197
    }
198

    
199
    @Override
200
    public boolean isOperator() {
201
        return false;
202
    }
203

    
204
    @Override
205
    public boolean isHidden() {
206
      return false;
207
    }
208
    
209
    @Override
210
    public boolean useArgumentsInsteadObjects() {
211
        return false;
212
    }
213

    
214
    @Override
215
    public boolean isSQLCompatible() {
216
        return sqlCompatible;
217
    }
218

    
219
    @Override
220
    public boolean allowConstantFolding() {
221
        return false;
222
    }
223

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

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

    
255
    protected long getLong(Object args[], int n) {
256
        if( args.length < n  ) {
257
            throw new IllegalArgumentException(I18N.Required_argument_XargnX_and_only_found_XargcX_in_call_to_XIdentifierX(name(), args.length, n));
258
        }
259
        return getLong(args[n],n);
260
    }
261

    
262
    protected long getLong(Object value, int n) {
263
        if( value == null ) {
264
            throw new IllegalArgumentException(I18N.Illegal_null_value_for_argument_XargnX_of_XIdentifierX_function(name(), n));
265
        }
266
        if( !(value instanceof Number) ) {
267
            String type = value.getClass().getCanonicalName();
268
            throw new IllegalArgumentException(
269
                    I18N.The_type_of_the_argument_XargnX_for_the_XIdentifierX_function_is_incorrect(name(), n) + " " +
270
                    I18N.Expected_XexpectedX_and_found_XfoundX("Number",type)
271
            );
272
        }
273
        return ((Number)value).longValue();
274
    }
275

    
276
    protected double getDouble(Object args[], int n) {
277
        if( args.length < n  ) {
278
            throw new IllegalArgumentException(I18N.Required_argument_XargnX_and_only_found_XargcX_in_call_to_XIdentifierX(name(), args.length, n));
279
        }
280
        return getDouble(args[n],n);
281
    }
282

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

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

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

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

    
415
    protected JsonArray getJsonArray(Object args[], int n) {
416
        if( args.length < n  ) {
417
            throw new IllegalArgumentException(I18N.Required_argument_XargnX_and_only_found_XargcX_in_call_to_XIdentifierX(name(), args.length, n));
418
        }
419
        return getJsonArray(args[n],n);
420
    }
421

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

    
441
    protected JsonStructure getJsonStructure(Object args[], int n) {
442
        if( args.length < n  ) {
443
            throw new IllegalArgumentException(I18N.Required_argument_XargnX_and_only_found_XargcX_in_call_to_XIdentifierX(name(), args.length, n));
444
        }
445
        return getJsonStructure(args[n],n);
446
    }
447

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

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

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

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

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

    
589
    protected boolean getBoolean(Object args[], int n) {
590
        if( args.length < n  ) {
591
            throw new IllegalArgumentException(I18N.Required_argument_XargnX_and_only_found_XargcX_in_call_to_XIdentifierX(name(), args.length, n));
592
        }
593
        return getBoolean(args[n], n, MathUtils.EPSILON);
594
    }
595

    
596
    protected boolean getBoolean(Object value, int n) {
597
        return getBoolean(value, n, MathUtils.EPSILON);
598
    }
599

    
600
    protected boolean getBoolean(Object value, int n, Double accuracy) {
601
        return toBoolean(value, accuracy);
602
    }
603

    
604
    protected boolean getBoolean(Interpreter interpreter, Codes args, int n) {
605
        Object value = getObject(interpreter, args, n);
606
        return toBoolean(value, interpreter.getAccuracy());
607
    }
608

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

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

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

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

    
678
                @Override
679
                public Object get64(long index) {
680
                    return ((GetItem64) value).get64((int) index);
681
                }
682
            };
683
        }
684
        return list;
685
    }
686
    
687

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

    
834
    @Override
835
    public String toString(Codes args, Formatter<Code> formatter) {
836
        return null;
837
    }
838

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

    
849
    }
850

    
851
    protected void checkFloatValue(float value) {
852
        if (Float.isInfinite(value)) {
853
            throw new OutOfRangeException(value, Float.MIN_VALUE, Float.MAX_VALUE);
854
        }
855

    
856
    }
857

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

    
872
    }
873
    
874
    
875
}