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

History | View | Annotate | Download (28.3 KB)

1
package org.gvsig.expressionevaluator.spi;
2

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

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

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

    
78
    protected AbstractFunction(String group, String name, Range argc, String description, String template) {
79
        this(group, name, argc, description, template, null, null);
80
    }
81

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

    
86
    @Override
87
    public String name() {
88
        return this.name;
89
    }
90

    
91
    @Override
92
    public String returnType() {
93
        return this.returnType;
94
    }
95

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

    
101
    @Override
102
    public Range argc() {
103
        return argc;
104
    }
105

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

    
114
    @Override
115
    public String[] descriptionArgs() {
116
        return descriptionArgs;
117
    }
118

    
119
    @Override
120
    public String getFullDescription() {
121
        I18nManager i18n = ToolsLocator.getI18nManager();
122

    
123
        StringBuilder html = new StringBuilder();
124
        html.append("<html>\n");
125

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

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

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

    
160
        html.append("</html>\n");
161
        return html.toString();
162
    }
163

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

    
178
    @Override
179
    public List<String> aliases() {
180
        return this.alias;
181
    }
182

    
183
    @Override
184
    public String template() {
185
        return this.template;
186
    }
187

    
188
    @Override
189
    public boolean isOperator() {
190
        return false;
191
    }
192

    
193
    @Override
194
    public boolean isHidden() {
195
      return false;
196
    }
197
    
198
    @Override
199
    public boolean useArgumentsInsteadObjects() {
200
        return false;
201
    }
202

    
203
    @Override
204
    public boolean isSQLCompatible() {
205
        return sqlCompatible;
206
    }
207

    
208
    @Override
209
    public boolean allowConstantFolding() {
210
        return false;
211
    }
212

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

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

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

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

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

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

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

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

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

    
382
    protected JsonArray getJsonArray(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 getJsonArray(args[n],n);
387
    }
388

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

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

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

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

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

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

    
542
    protected boolean getBoolean(Object value, int n) {
543
        return getBoolean(value, n, MathUtils.EPSILON);
544
    }
545

    
546
    protected boolean getBoolean(Object value, int n, Double accuracy) {
547
        return toBoolean(value, accuracy);
548
    }
549

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

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

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

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

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

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

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

    
781
    @Override
782
    public String toString(Codes args, Formatter<Code> formatter) {
783
        return null;
784
    }
785

    
786
    @Override
787
    public String toString() {
788
        return this.name;
789
    }
790
}