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

History | View | Annotate | Download (28.3 KB)

1
package org.gvsig.expressionevaluator.spi;
2

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

    
49
@SuppressWarnings("UseSpecificCatch")
50
public abstract class AbstractFunction implements Function {
51
 
52
    private final String name;
53
    private String group;
54
    private Range argc;
55
    private String description;
56
    private String[] descriptionArgs;
57
    private List<String> alias;
58
    private String template;
59
    private String returnType;
60
    private boolean sqlCompatible;
61

    
62
    protected AbstractFunction(String group, String name, Range argc, String description, String template, String[] descriptionArgs, String returnType, boolean sqlCompatible) {
63
        this.name = name;
64
        this.group = group;
65
        this.argc = argc;
66
        this.description = description;
67
        this.template = template;
68
        this.descriptionArgs = descriptionArgs;
69
        this.returnType = returnType;
70
        this.sqlCompatible = sqlCompatible;
71
        load_from_resource();
72
    }
73
    protected AbstractFunction(String group, String name, Range argc, String description, String template, String[] descriptionArgs, String returnType) {
74
        this(group, name, argc, description, template, descriptionArgs, returnType, false);
75
    }
76
    
77
    protected AbstractFunction(String group, String name, Range argc, String description, String template, String[] descriptionArgs) {
78
        this(group, name, argc, description, template, null, null);
79
    }
80

    
81
    protected AbstractFunction(String group, String name, Range argc, String description, String template) {
82
        this(group, name, argc, description, template, null, null);
83
    }
84

    
85
    protected AbstractFunction(String group, String name, Range argc) {
86
        this(group, name, argc, null, null, null, null);
87
    }
88

    
89
    @Override
90
    public String name() {
91
        return this.name;
92
    }
93

    
94
    @Override
95
    public String returnType() {
96
        return this.returnType;
97
    }
98

    
99
    @Override
100
    public String group() {
101
        return this.group;
102
    }
103

    
104
    @Override
105
    public Range argc() {
106
        return argc;
107
    }
108

    
109
    @Override
110
    public String description() {
111
        if( StringUtils.equalsIgnoreCase(System.getProperty("ExpressionEvaluatorReloadFunctionResources"), "true")) {
112
            load_from_resource();
113
        }
114
        return description;
115
    }
116

    
117
    @Override
118
    public String[] descriptionArgs() {
119
        return descriptionArgs;
120
    }
121

    
122
    @Override
123
    public String getFullDescription() {
124
        I18nManager i18n = ToolsLocator.getI18nManager();
125

    
126
        StringBuilder html = new StringBuilder();
127
        html.append("<html>\n");
128

    
129
        // Lo primero llamamos a description() para forzar la recarga de los
130
        // recursos si fuese necesaria.
131
        String functionDescription = this.description();
132

    
133
        html.append("<b>").append(i18n.getTranslation("_Function")).append("</b> ").append(this.name()).append("<br>\n<br>\n");
134
        List<String> aliases = this.aliases();
135
        if( aliases!=null && !aliases.isEmpty() ) {
136
            html.append("<b>").append(i18n.getTranslation("_Aliases")).append(":</b> ").append("<ul>\n");
137
            for (String theAlias : aliases) {
138
                html.append("<li>").append(theAlias).append("</li>\n");
139
            }
140
            html.append("</ul>\n");
141
        }
142
        html.append("<b>").append(i18n.getTranslation("_Return")).append("</b> ");
143
        html.append(StringUtils.isEmpty(this.returnType()) ? "Objec" : this.returnType());
144
        html.append("<br>\n");
145
        html.append("<b>").append(i18n.getTranslation("_Template")).append("</b> ");
146
        html.append(StringUtils.isEmpty(this.template()) ? this.name() + "()" : this.template());
147
        html.append("<br>\n");
148

    
149
        String[] args = this.descriptionArgs();
150
        if (args != null) {
151
            html.append("<b>").append(i18n.getTranslation("_Arguments")).append(":</b> ").append("<ul>\n");
152
            for (String arg : args) {
153
                html.append("<li>").append(arg).append("</li>\n");
154
            }
155
            html.append("</ul>\n");
156
            html.append("<br>\n");
157
        }
158
        if( !StringUtils.isBlank(functionDescription) ) {
159
            html.append("<b>").append(i18n.getTranslation("_Description")).append("</b><br>\n");
160
            html.append(functionDescription.replace("\n", "<br>")).append("<br>\n");
161
        }            
162

    
163
        html.append("</html>\n");
164
        return html.toString();
165
    }
166

    
167
    @Override
168
    public void addAlias(String name) {
169
        if( StringUtils.isBlank(name) ) {
170
            return;
171
        }
172
        if( this.alias == null ) {
173
            this.alias = new ArrayList<>();
174
        }
175
        if( this.alias.contains(name) ) {
176
            return;
177
        }
178
        this.alias.add(name);
179
    }
180

    
181
    @Override
182
    public List<String> aliases() {
183
        return this.alias;
184
    }
185

    
186
    @Override
187
    public String template() {
188
        return this.template;
189
    }
190

    
191
    @Override
192
    public boolean isOperator() {
193
        return false;
194
    }
195

    
196
    @Override
197
    public boolean isHidden() {
198
      return false;
199
    }
200
    
201
    @Override
202
    public boolean useArgumentsInsteadObjects() {
203
        return false;
204
    }
205

    
206
    @Override
207
    public boolean isSQLCompatible() {
208
        return sqlCompatible;
209
    }
210

    
211
    @Override
212
    public boolean allowConstantFolding() {
213
        return false;
214
    }
215

    
216
    @Override
217
    public Object call(Interpreter interpreter, Codes args) throws Exception {
218
        return null;
219
    }
220
    
221
    protected int getInt(Object args[], int n) {
222
        if( args.length < n  ) {
223
            throw new IllegalArgumentException(I18N.Required_argument_XargnX_and_only_found_XargcX_in_call_to_XIdentifierX(name(), args.length, n));
224
        }
225
        return getInt(args[n],n);
226
    }
227

    
228
    protected int getInt(Object value, int n) {
229
        if( value == null ) {
230
            throw new IllegalArgumentException(I18N.Illegal_null_value_for_argument_XargnX_of_XIdentifierX_function(name(), n));
231
        }
232
        if( !(value instanceof Number) ) {
233
            String type = value.getClass().getCanonicalName();
234
            throw new IllegalArgumentException(
235
                    I18N.The_type_of_the_argument_XargnX_for_the_XIdentifierX_function_is_incorrect(name(), n) + " " +
236
                    I18N.Expected_XexpectedX_and_found_XfoundX("Number",type)
237
            );
238
        }
239
        return ((Number)value).intValue();
240
    }
241

    
242
    protected long getLong(Object args[], int n) {
243
        if( args.length < n  ) {
244
            throw new IllegalArgumentException(I18N.Required_argument_XargnX_and_only_found_XargcX_in_call_to_XIdentifierX(name(), args.length, n));
245
        }
246
        return getLong(args[n],n);
247
    }
248

    
249
    protected long getLong(Object value, int n) {
250
        if( value == null ) {
251
            throw new IllegalArgumentException(I18N.Illegal_null_value_for_argument_XargnX_of_XIdentifierX_function(name(), n));
252
        }
253
        if( !(value instanceof Number) ) {
254
            String type = value.getClass().getCanonicalName();
255
            throw new IllegalArgumentException(
256
                    I18N.The_type_of_the_argument_XargnX_for_the_XIdentifierX_function_is_incorrect(name(), n) + " " +
257
                    I18N.Expected_XexpectedX_and_found_XfoundX("Number",type)
258
            );
259
        }
260
        return ((Number)value).longValue();
261
    }
262

    
263
    protected double getDouble(Object args[], int n) {
264
        if( args.length < n  ) {
265
            throw new IllegalArgumentException(I18N.Required_argument_XargnX_and_only_found_XargcX_in_call_to_XIdentifierX(name(), args.length, n));
266
        }
267
        return getDouble(args[n],n);
268
    }
269

    
270
    protected double getDouble(Object value, int arg) {
271
        if( value == null ) {
272
            throw new IllegalArgumentException(I18N.Illegal_null_value_for_argument_XargnX_of_XIdentifierX_function(name(), arg));
273
        }
274
        if( !(value instanceof Number) ) {
275
            String type = value.getClass().getCanonicalName();
276
            throw new IllegalArgumentException(
277
                    I18N.The_type_of_the_argument_XargnX_for_the_XIdentifierX_function_is_incorrect(name(), arg) + " " +
278
                    I18N.Expected_XexpectedX_and_found_XfoundX("Number",type)
279
            );
280
        }
281
        return ((Number)value).doubleValue();
282
    }
283
    
284
    protected float getFloat(Object args[], int n) {
285
        if( args.length < n  ) {
286
            throw new IllegalArgumentException(I18N.Required_argument_XargnX_and_only_found_XargcX_in_call_to_XIdentifierX(name(), args.length, n));
287
        }
288
        return getFloat(args[n],n);
289
    }
290

    
291
    protected float getFloat(Object value, int arg) {
292
        if( value == null ) {
293
            throw new IllegalArgumentException(I18N.Illegal_null_value_for_argument_XargnX_of_XIdentifierX_function(name(), arg));
294
        }
295
        if( !(value instanceof Number) ) {
296
            String type = value.getClass().getCanonicalName();
297
            throw new IllegalArgumentException(
298
                    I18N.The_type_of_the_argument_XargnX_for_the_XIdentifierX_function_is_incorrect(name(), arg) + " " +
299
                    I18N.Expected_XexpectedX_and_found_XfoundX("Number",type)
300
            );
301
        }
302
        return ((Number)value).floatValue();
303
    }
304
    
305
    protected String getStr(Object args[], int n) {
306
        if( args.length < n  ) {
307
            throw new IllegalArgumentException(I18N.Required_argument_XargnX_and_only_found_XargcX_in_call_to_XIdentifierX(name(), args.length, n));
308
        }
309
        return getStr(args[n],n);
310
    }
311
    
312
    protected String getStr(Object value, int n) {
313
        return Objects.toString(value, "");
314
    }
315
    
316
    protected File getFile(Object args[], int n) {
317
        if( args.length < n  ) {
318
            throw new IllegalArgumentException(I18N.Required_argument_XargnX_and_only_found_XargcX_in_call_to_XIdentifierX(name(), args.length, n));
319
        }
320
        return getFile(args[n],n);
321
    }
322
    
323
    protected File getFile(Object value, int n) {
324
        if( value == null ) {
325
            return null;
326
        }
327
        if( value instanceof File ) {
328
            return (File)value;
329
        }
330
        if( value instanceof URL ) {
331
            try {
332
                return new File(((URL)value).toURI());
333
            } catch (URISyntaxException ex) {
334
                return null;
335
            }
336
        }
337
        if( value instanceof URI ) {
338
            return new File(((URI)value));
339
        }
340
        String s = Objects.toString(value, null);
341
        if( s == null ) {
342
            return null;
343
        }
344
        File f = new File(s);
345
        return f;
346
    }
347

    
348
    protected boolean isNull(Object args[], int n) {
349
        return getObject(args, n)==null;
350
    }
351
    
352
    protected Object getObject(Object args[], int n) {
353
        if( args.length < n  ) {
354
            throw new IllegalArgumentException(I18N.Required_argument_XargnX_and_only_found_XargcX_in_call_to_XIdentifierX(name(), args.length, n));
355
        }
356
        return args[n];
357
    }
358
    
359
    protected JsonObject getJsonObject(Object args[], int n) {
360
        if( args.length < n  ) {
361
            throw new IllegalArgumentException(I18N.Required_argument_XargnX_and_only_found_XargcX_in_call_to_XIdentifierX(name(), args.length, n));
362
        }
363
        return getJsonObject(args[n],n);
364
    }
365

    
366
    protected JsonObject getJsonObject(Object value, int n) {
367
        if( value == null ) {
368
            throw new IllegalArgumentException(I18N.Illegal_null_value_for_argument_XargnX_of_XIdentifierX_function(name(), n));
369
        }
370
        if( !(value instanceof JSONObject) ) {
371
            try {
372
                value = JsonUtils.toJsonObject(value);
373
            } catch(Throwable th) {
374
                String type = value.getClass().getCanonicalName();
375
                throw new IllegalArgumentException(
376
                    I18N.The_type_of_the_argument_XargnX_for_the_XIdentifierX_function_is_incorrect(name(), n) + " " +
377
                    I18N.Expected_XexpectedX_and_found_XfoundX("JsonObject",type),
378
                    th
379
                );
380
            }
381
        }
382
        return (JsonObject) value;
383
    }
384

    
385
    protected JsonArray getJsonArray(Object args[], int n) {
386
        if( args.length < n  ) {
387
            throw new IllegalArgumentException(I18N.Required_argument_XargnX_and_only_found_XargcX_in_call_to_XIdentifierX(name(), args.length, n));
388
        }
389
        return getJsonArray(args[n],n);
390
    }
391

    
392
    protected JsonArray getJsonArray(Object value, int n) {
393
        if( value == null ) {
394
            throw new IllegalArgumentException(I18N.Illegal_null_value_for_argument_XargnX_of_XIdentifierX_function(name(), n));
395
        }
396
        if( !(value instanceof JsonArray) ) {
397
            try {
398
                value = JsonUtils.toJsonArray(value);
399
            } catch(Throwable th) {
400
                String type = value.getClass().getCanonicalName();
401
                throw new IllegalArgumentException(
402
                    I18N.The_type_of_the_argument_XargnX_for_the_XIdentifierX_function_is_incorrect(name(), n) + " " +
403
                    I18N.Expected_XexpectedX_and_found_XfoundX("JsonObject",type),
404
                    th
405
                );
406
            }
407
        }
408
        return (JsonArray) value;
409
    }
410

    
411
    protected JsonStructure getJsonStructure(Object args[], int n) {
412
        if( args.length < n  ) {
413
            throw new IllegalArgumentException(I18N.Required_argument_XargnX_and_only_found_XargcX_in_call_to_XIdentifierX(name(), args.length, n));
414
        }
415
        return getJsonStructure(args[n],n);
416
    }
417

    
418
    protected JsonStructure getJsonStructure(Object value, int n) {
419
        if( value == null ) {
420
            throw new IllegalArgumentException(I18N.Illegal_null_value_for_argument_XargnX_of_XIdentifierX_function(name(), n));
421
        }
422
        if( !(value instanceof JsonStructure) ) {
423
            try {
424
                value = JsonUtils.toJson(value);
425
            } catch(Throwable th) {
426
                String type = value.getClass().getCanonicalName();
427
                throw new IllegalArgumentException(
428
                    I18N.The_type_of_the_argument_XargnX_for_the_XIdentifierX_function_is_incorrect(name(), n) + " " +
429
                    I18N.Expected_XexpectedX_and_found_XfoundX("JsonObject",type),
430
                    th
431
                );
432
            }
433
        }
434
        return (JsonStructure) value;
435
    }
436

    
437
    protected Object getObject(Interpreter interpreter, Codes args, int n) {
438
        if( args.size() < n  ) {
439
            throw new IllegalArgumentException(I18N.Required_argument_XargnX_and_only_found_XargcX_in_call_to_XIdentifierX(name(), args.size(), n));
440
        }
441
        Code arg = args.get(n);
442
        if( arg==null ) {
443
            return null;
444
        }
445
        Object value = interpreter.run(arg);
446
        return value;
447
    }
448
    
449
    protected Comparable getComparable(Object[] args, int n) {
450
        if( args.length < n  ) {
451
            throw new IllegalArgumentException(I18N.Required_argument_XargnX_and_only_found_XargcX_in_call_to_XIdentifierX(name(), args.length, n));
452
        }
453
        return getComparable(args[n],n);
454
    }
455
    
456
    protected Comparable getComparable(Object value, int n) {
457
        if( value == null ) {
458
            return null;
459
        }
460
        if( !(value instanceof Comparable) ) {
461
            String type = value.getClass().getCanonicalName();
462
            throw new IllegalArgumentException(
463
                    I18N.The_type_of_the_argument_XargnX_for_the_XIdentifierX_function_is_incorrect(name(), n) + " " +
464
                    I18N.Expected_XexpectedX_and_found_XfoundX("Comparable",type)
465
            );
466
        }
467
        return (Comparable)value;
468
    }
469

    
470
    protected Comparable getDate(Object[] args, int n) {
471
        if( args.length < n  ) {
472
            throw new IllegalArgumentException(I18N.Required_argument_XargnX_and_only_found_XargcX_in_call_to_XIdentifierX(name(), args.length, n));
473
        }
474
        return getDate(args[n],n);
475
    }
476
    
477
    protected Date getDate(Object value, int n) {
478
        if( value == null ) {
479
            return null;
480
        }
481
        if( !(value instanceof Date) ) {
482
            String type = value.getClass().getCanonicalName();
483
            throw new IllegalArgumentException(
484
                    I18N.The_type_of_the_argument_XargnX_for_the_XIdentifierX_function_is_incorrect(name(), n) + " " +
485
                    I18N.Expected_XexpectedX_and_found_XfoundX("Date",type)
486
            );
487
        }
488
        return (Date)value;
489
    }
490
    
491
    protected LocalDateTime getLocalDateTime(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 getLocalDateTime(args[n],n);
496
    }
497
    
498
    protected LocalDateTime getLocalDateTime(Object value, int n) {
499
        if( value == null ) {
500
            return null;
501
        }
502
        if( value instanceof Date ) {
503
            Date date = ((Date)value);
504
            return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
505
        }
506
        if( value instanceof LocalDateTime ) {
507
            return (LocalDateTime) value;
508
        }
509
        if( value instanceof TemporalAccessor ) {
510
            return LocalDateTime.from(((TemporalAccessor)value));
511
        }
512
        String type = value.getClass().getCanonicalName();
513
        throw new IllegalArgumentException(
514
                I18N.The_type_of_the_argument_XargnX_for_the_XIdentifierX_function_is_incorrect(name(), n) + " " +
515
                I18N.Expected_XexpectedX_and_found_XfoundX("Temporal/Date",type)
516
        );
517
    }
518

    
519
    public URL getURL(Object[] args, int index) throws MalformedURLException {
520
        Object obj = getObject(args, index);
521
        if( obj == null ) {
522
            return null;
523
        }  
524
        URL url;
525
        if( obj instanceof URL ) {
526
            url = (URL) obj;        } else if( obj instanceof CharSequence ) {
527
            url = new URL(((CharSequence)obj).toString());
528
        } else if( obj instanceof File ) {
529
            url = ((File)obj).toURI().toURL();
530
        } else if( obj instanceof URI ) {
531
            url = ((URI)obj).toURL();
532
        } else {
533
            throw new ExpressionRuntimeException("The "+this.name()+" function require a File, URI or a String and a received a '"+obj.getClass().getSimpleName()+"'.");
534
        }  
535
        return url;
536
    }
537
    
538
    protected boolean getBoolean(Object args[], int n, Double accuracy) {
539
        if( args.length < n  ) {
540
            throw new IllegalArgumentException(I18N.Required_argument_XargnX_and_only_found_XargcX_in_call_to_XIdentifierX(name(), args.length, n));
541
        }
542
        return getBoolean(args[n], n, accuracy);
543
    }
544

    
545
    protected boolean getBoolean(Object value, int n) {
546
        return getBoolean(value, n, MathUtils.EPSILON);
547
    }
548

    
549
    protected boolean getBoolean(Object value, int n, Double accuracy) {
550
        return toBoolean(value, accuracy);
551
    }
552

    
553
    protected boolean getBoolean(Interpreter interpreter, Codes args, int n) {
554
        Object value = getObject(interpreter, args, n);
555
        return toBoolean(value, interpreter.getAccuracy());
556
    }
557

    
558
    protected boolean toBoolean(Object value, Double accuracy) {
559
        if( value == null ) {
560
            return false;
561
        }
562
        if( value instanceof Boolean ) {
563
            return (Boolean)value;
564
        }        
565
        if( value instanceof Number ) {
566
            return MathUtils.compareTo(
567
                ((Number) value).doubleValue(), 
568
                0,
569
                accuracy==null? MathUtils.EPSILON:accuracy
570
            ) == 0;
571
        }
572
        return BooleanUtils.toBoolean(value.toString());
573
    } 
574
    
575
    protected GetItemWithSize64 getList(Object[] args, int index)  {
576
        Object value = getObject(args, index);
577
        if( value == null ) {
578
            return null;
579
        }  
580
        GetItemWithSize64 list = null;
581
        if (value instanceof List) {
582
            list = new GetItemWithSize64<Object>() {
583
                @Override
584
                public long size64() {
585
                    return ((List) value).size();
586
                }
587

    
588
                @Override
589
                public Object get64(long index) {
590
                    return ((List) value).get((int) index);
591
                }
592
            };
593
        } else if (value instanceof Object[]) {
594
            list = new GetItemWithSize64<Object>() {
595
                @Override
596
                public long size64() {
597
                    return ((Object[]) value).length;
598
                }
599

    
600
                @Override
601
                public Object get64(long index) {
602
                    return ((Object[]) value)[(int) index];
603
                }
604
            };
605
        } else if (value instanceof GetItemWithSize64 ) {
606
            list = (GetItemWithSize64) value;
607
            
608
        } else if (value instanceof GetItem && value instanceof Size) {
609
            list = new GetItemWithSize64<Object>() {
610
                @Override
611
                public long size64() {
612
                    return ((Size) value).size();
613
                }
614

    
615
                @Override
616
                public Object get64(long index) {
617
                    return ((GetItem) value).get((int) index);
618
                }
619
            };
620
        } else if (value instanceof GetItem64 && value instanceof Size64) {
621
            list = new GetItemWithSize64<Object>() {
622
                @Override
623
                public long size64() {
624
                    return ((Size64) value).size64();
625
                }
626

    
627
                @Override
628
                public Object get64(long index) {
629
                    return ((GetItem64) value).get64((int) index);
630
                }
631
            };
632
        }
633
        return list;
634
    }
635
    
636

    
637
    private void load_from_resource() {
638
        String lang = Locale.getDefault().getLanguage();
639
        URL url = this.getClass().getResource("/org/gvsig/expressionevaluator/functions/"+lang+"/"+this.name()+".json");
640
        if( url == null ) {
641
            url = this.getClass().getResource("/org/gvsig/expressionevaluator/functions/en/"+this.name()+".json");
642
            if( url == null ) {
643
                return;
644
            }
645
        }
646
//        InputStream is = null;
647
        JSONObject json;
648
        try {
649
//            is = url.openStream();
650
//            List<String> lines = IOUtils.readLines(is);
651
//            json = new JSONObject(StringUtils.join(lines,  "\n"));
652
            json = new JSONObject(IOUtils.toString(url));
653
        } catch (Exception ex) {
654
            return;
655
//        } finally {
656
//            IOUtils.closeQuietly(is);
657
        }
658
        
659
        if( json.has("group") ) {
660
            this.group = json.getString("group");
661
        }
662
        if( json.has("description") ) {
663
            Object x = json.get("description");
664
            if( x instanceof String ) {
665
                this.description = (String) x;
666
            } else if( x instanceof JSONArray ) {
667
                StringBuilder builder = new StringBuilder();
668
                for (int i = 0; i < ((JSONArray)x).length(); i++) {
669
                    if( i>0 ) {
670
                        builder.append(" ");
671
                    }
672
                    builder.append(((JSONArray)x).getString(i));
673
                }
674
                this.description = builder.toString();
675
            } else {
676
                this.description = Objects.toString(x, null);
677
            }
678
            this.description = process_includes(url, this.description);
679
            this.description = StringUtils.replace(
680
                    this.description, 
681
                    "@@@", 
682
                    url.toString()
683
            );
684
        }
685
        if( json.has("template") ) {
686
            this.template = json.getString("template");
687
        }
688
        if( json.has("returnType") ) {
689
            this.returnType = json.getString("returnType");
690
        }
691
        if( json.has("sqlCompatible") ) {
692
            this.sqlCompatible = json.getBoolean("sqlCompatible");
693
        }
694
        if( json.has("args") ) {
695
            JSONArray x = json.getJSONArray("args");
696
            String[] args = new String[x.length()];
697
            for (int i = 0; i < x.length(); i++) {
698
                args[i] = x.getString(i);
699
            }
700
            this.descriptionArgs = args;
701
        }
702
        if( json.has("alias") ) {
703
            JSONArray x = json.getJSONArray("alias");
704
            for (int i = 0; i < x.length(); i++) {
705
                this.addAlias(x.getString(i));
706
            }
707
        }
708
    }
709
    
710
    private String process_includes(URL pathname, String text) {
711
        Pattern p1 = Pattern.compile("[<][%]include (?<fname>[a-zA-Z0-9_$.]+)[%][>]", Pattern.DOTALL);
712
        while(true) {
713
            Matcher m = p1.matcher(text);
714
            if( m==null || !m.find()) {
715
                return text;
716
            }
717
            String path = FilenameUtils.getPathNoEndSeparator(pathname.toString());
718
            String fname = m.group("fname");
719
            URL url;
720
            String replacement;
721
            try {
722
                url = new URL(path+"/"+fname);
723
                replacement = IOUtils.toString(url);
724
//                text = m.replaceAll(replacement);
725
                StringBuilder builder = new StringBuilder(text.length()+replacement.length());
726
                builder.append(text.substring(0, m.start()));
727
                builder.append(replacement);
728
                builder.append(text.substring(m.end()));
729
                text = builder.toString();
730
            } catch (Exception ex) {
731
                return text;
732
            }
733
        }
734
    }
735
    
736
    protected static final int TYPE_INT =     0b00000001;
737
    protected static final int TYPE_LONG =    0b00000010;
738
    protected static final int TYPE_FLOAT =   0b00000100;
739
    protected static final int TYPE_DOUBLE =  0b00001000;
740
    protected static final int TYPE_BOOLEAN = 0b00010000;
741
    protected static final int TYPE_STRING =  0b00100000;
742
    protected static final int TYPE_DATE =    0b01000000;
743
    protected static final int TYPE_NULL =    0b10000000;
744
    
745
    protected int getType(Object op1, Object op2) {
746
        int r = 0;
747
        if( op1 == null ) {
748
            r |= TYPE_NULL;
749
        } else if( op1 instanceof Double ) {
750
            r |= TYPE_DOUBLE;
751
        } else if( op1 instanceof Float ) {
752
            r |= TYPE_FLOAT;
753
        } else if( op1 instanceof Long ) {
754
            r |= TYPE_LONG;
755
        } else if( op1 instanceof Integer ) {
756
            r |= TYPE_INT;
757
        } else if( op1 instanceof Boolean ) {
758
            r |= TYPE_BOOLEAN;
759
        } else if( op1 instanceof String ) {
760
            r |= TYPE_STRING;
761
        } else if( op1 instanceof Date ) {
762
            r |= TYPE_DATE;
763
        }
764
        if( op2 == null ) {
765
            r |= TYPE_NULL;
766
        } else if( op2 instanceof Double ) {
767
            r |= TYPE_DOUBLE;
768
        } else if( op2 instanceof Float ) {
769
            r |= TYPE_FLOAT;
770
        } else if( op2 instanceof Long ) {
771
            r |= TYPE_LONG;
772
        } else if( op2 instanceof Integer ) {
773
            r |= TYPE_INT;
774
        } else if( op2 instanceof Boolean ) {
775
            r |= TYPE_BOOLEAN;
776
        } else if( op2 instanceof String ) {
777
            r |= TYPE_STRING;
778
        } else if( op2 instanceof Date ) {
779
            r |= TYPE_DATE;
780
        }
781
        return r;
782
    }
783

    
784
    @Override
785
    public String toString(Codes args, Formatter<Code> formatter) {
786
        return null;
787
    }
788

    
789
}