Statistics
| Revision:

gvsig-tools / org.gvsig.tools / library / trunk / org.gvsig.tools / org.gvsig.tools.lib / src / main / java / org / gvsig / tools / dynobject / impl / DefaultDynClass.java @ 1548

History | View | Annotate | Download (27.8 KB)

1
/**
2
 * gvSIG. Desktop Geographic Information System.
3
 *
4
 * Copyright (C) 2007-2013 gvSIG Association.
5
 *
6
 * This program is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU General Public License
8
 * as published by the Free Software Foundation; either version 2
9
 * of the License, or (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19
 * MA  02110-1301, USA.
20
 *
21
 * For any additional information, do not hesitate to contact us
22
 * at info AT gvsig.com, or visit our website www.gvsig.com.
23
 */
24
package org.gvsig.tools.dynobject.impl;
25

    
26
import java.util.Collection;
27
import java.util.HashMap;
28
import java.util.Iterator;
29
import java.util.LinkedHashMap;
30
import java.util.LinkedHashSet;
31
import java.util.Map;
32
import java.util.Set;
33

    
34
import org.apache.commons.lang3.StringUtils;
35

    
36
import org.gvsig.tools.ToolsLocator;
37
import org.gvsig.tools.dataTypes.DataTypes;
38
import org.gvsig.tools.dynobject.AbstractDynMethod;
39
import org.gvsig.tools.dynobject.DynClass;
40
import org.gvsig.tools.dynobject.DynClassName;
41
import org.gvsig.tools.dynobject.DynClass_v2;
42
import org.gvsig.tools.dynobject.DynField;
43
import org.gvsig.tools.dynobject.DynMethod;
44
import org.gvsig.tools.dynobject.DynObject;
45
import org.gvsig.tools.dynobject.DynObjectException;
46
import org.gvsig.tools.dynobject.DynObjectManager;
47
import org.gvsig.tools.dynobject.DynObjectValueItem;
48
import org.gvsig.tools.dynobject.DynStruct;
49
import org.gvsig.tools.dynobject.Tags;
50
import org.gvsig.tools.dynobject.exception.DynClassNotFoundException;
51
import org.gvsig.tools.dynobject.exception.DynFieldNotFoundException;
52
import org.gvsig.tools.dynobject.exception.DynFieldValidateException;
53
import org.gvsig.tools.dynobject.exception.DynMethodException;
54
import org.gvsig.tools.dynobject.exception.DynMethodNotSupportedException;
55
import org.gvsig.tools.dynobject.exception.DynObjectValidateException;
56
import org.gvsig.tools.exception.ListBaseException;
57
import org.gvsig.tools.script.Script;
58

    
59
public class DefaultDynClass implements DynClass_v2{
60

    
61
    public class FieldAndIndex {
62

    
63
        DefaultDynField field;
64
        int index;
65

    
66
        FieldAndIndex(DynField field, int index) {
67
            this.field = (DefaultDynField) field;
68
            this.index = index;
69
        }
70

    
71
        public int getIndex() {
72
            return this.index;
73
        }
74

    
75
        public DefaultDynField getDynField() {
76
            return this.field;
77
        }
78
    }
79

    
80
    public class MethodAndIndex {
81

    
82
        DynMethod method;
83
        int index;
84

    
85
        MethodAndIndex(DynMethod method, int index) {
86
            this.method = method;
87
            this.index = index;
88
        }
89

    
90
        public int getIndex() {
91
            return this.index;
92
        }
93

    
94
        public DynMethod getDynMethod() {
95
            return this.method;
96
        }
97
    }
98

    
99

    
100
    DynObjectManager manager;
101

    
102
    private DynClassName name;
103
    private String description;
104

    
105
    private boolean isAnonymous;
106

    
107
    private Map classes;
108
    private Map declaredFieldsMap;
109
    private Map declaredMethodsMap;
110

    
111
    // This attributes are calculated by consolide method
112
    private DefaultDynClass[] superClasses;
113
    private Map superClassesMap;
114
    private DynField[] declaredFields;
115
    private Map fieldsMap;
116
    private DynField[] fields;
117
    private DynMethod[] declaredMethods;
118
    private Map methodsMap;
119
    private DynMethod[] methods;
120

    
121
    private final Tags tags = new DefaultTags();
122
    private String label = null;
123

    
124
    private Script script = null;
125

    
126
    @SuppressWarnings("OverridableMethodCallInConstructor")
127
    public DefaultDynClass(String name) {
128
        this((DynObjectManager)null, (DynClassName)null, (String)null);
129
        this.setName( new DefaultDynClassName(name));
130
    }
131

    
132
    public DefaultDynClass(DynObjectManager manager, String name,
133
        String description) {
134
        this(manager, null, name, description);
135
    }
136

    
137
    public DefaultDynClass(DynObjectManager manager, String namespace,
138
        String name, String description) {
139
        this(
140
                manager,
141
                manager.createDynClassName(namespace, name),
142
                description
143
        );
144
    }
145

    
146
    public DefaultDynClass(DynObjectManager manager, DynClassName name,
147
        String description) {
148
        if( manager == null ) {
149
            manager = ToolsLocator.getDynObjectManager();
150
        }
151

    
152
        this.isAnonymous = false;
153
        this.classes = new LinkedHashMap();
154
        this.declaredFieldsMap = new HashMap();
155
        this.declaredMethodsMap = new HashMap();
156

    
157
        this.forceConsolide();
158

    
159
        this.manager = manager;
160
        this.name = name;
161
        this.description = description;
162
    }
163

    
164
    public void setName(DynClassName name) {
165
        this.name = name;
166
    }
167

    
168
    @Override
169
    public String getName() {
170
        return this.name.getName();
171
    }
172

    
173
    @Override
174
    public String getNamespace() {
175
        return this.name.getNamespace();
176
    }
177

    
178
    @Override
179
    public String getFullName() {
180
        return this.name.getFullName();
181
    }
182

    
183
    @Override
184
    public String toString() {
185
        StringBuilder buffer = new StringBuilder();
186

    
187
        buffer.append("DynClass").append("[").append(this.hashCode())
188
            .append("]").append("( ").append("name='")
189
            .append(this.getFullName()).append("', ").append("fields='")
190
            .append(this.declaredFieldsMap.toString()).append(" )");
191
        return buffer.toString();
192
    }
193

    
194
    public DefaultDynClass(DynObjectManager manager, String name,
195
        String description, DynClass[] superClases) {
196
        this(manager, name, description);
197
        for (DynClass dynClass : superClases) {
198
            if (!this.classes.containsKey(dynClass.getFullName())) {
199
                this.classes.put(dynClass.getFullName(), dynClass);
200
            }
201
        }
202
    }
203

    
204
    public DynObjectManager getManager() {
205
        return this.manager;
206
    }
207

    
208
    @Override
209
    public Script getScript() {
210
        return this.script;
211
    }
212

    
213
    @Override
214
    public void setScript(Script script) {
215
        this.script = script;
216
    }
217

    
218
    synchronized public void consolide() {
219
        // Use classes and decalredFieldsMap to update all.
220

    
221
        // Updates superClasses array
222
        this.superClasses =
223
            (DefaultDynClass[]) buildSuperDynClassSet().toArray(
224
                new DefaultDynClass[] {});
225

    
226
        // Updates declaredFields array
227
        this.declaredFields =
228
            (DynField[]) this.declaredFieldsMap.values().toArray(
229
                new DynField[] {});
230

    
231
        // Updates declaredMethods array
232
        this.declaredMethods =
233
            (DynMethod[]) this.declaredMethodsMap.values().toArray(
234
                new DynMethod[] {});
235

    
236
        // Updates fieldsMap
237
        this.fieldsMap = new LinkedHashMap();
238
        int index = 0;
239
        for (DynField declaredField : this.declaredFields) {
240
            this.fieldsMap.put(
241
                    declaredField.getName().toLowerCase(),
242
                    new FieldAndIndex(declaredField, index++)
243
            );
244
        }
245
        for (DefaultDynClass superClasse : this.superClasses) {
246
            Iterator it = superClasse.declaredFieldsMap.values().iterator();
247
            while (it.hasNext()) {
248
                DynField field = (DynField) it.next();
249
                if (!this.fieldsMap.containsKey(field.getName().toLowerCase())) {
250
                    this.fieldsMap.put(field.getName().toLowerCase(),
251
                            new FieldAndIndex(field, index++));
252
                }
253
            }
254
        }
255

    
256
        // Updates methodsMap
257
        this.methodsMap = new LinkedHashMap();
258
        index = 0;
259
        for (DynMethod declaredMethod : this.declaredMethods) {
260
            this.methodsMap.put(
261
                    declaredMethod.getName().toLowerCase(),
262
                    new MethodAndIndex(declaredMethod, index++)
263
            );
264
        }
265
        for (DefaultDynClass superClasse : this.superClasses) {
266
            Iterator it = superClasse.declaredMethodsMap.values().iterator();
267
            while (it.hasNext()) {
268
                DynMethod method = (DynMethod) it.next();
269
                if (!this.methodsMap.containsKey(method.getName().toLowerCase())) {
270
                    this.methodsMap.put(method.getName().toLowerCase(), new MethodAndIndex(
271
                            method, index++));
272
                }
273
            }
274
        }
275

    
276
        // Updates fields array
277
        this.fields = new DynField[this.fieldsMap.size()];
278
        int i = 0;
279
        Iterator it = this.fieldsMap.values().iterator();
280
        while (it.hasNext()) {
281
            FieldAndIndex findex = (FieldAndIndex) it.next();
282
            DynField field = findex.getDynField();
283
            fields[i++] = field;
284
        }
285

    
286
        // Updates methods array
287
        this.methods = new DynMethod[this.methodsMap.size()];
288
        i = 0;
289
        it = this.methodsMap.values().iterator();
290
        while (it.hasNext()) {
291
            MethodAndIndex mindex = (MethodAndIndex) it.next();
292
            DynMethod method = mindex.getDynMethod();
293
            methods[i++] = method;
294
        }
295

    
296
        // Updates superClassesMap
297
        this.superClassesMap = new HashMap();
298
        for (i = 0; i < this.superClasses.length; i++) {
299
            this.superClassesMap.put(this.superClasses[i].getFullName(),
300
                this.superClasses[i]);
301
        }
302
    }
303

    
304
    synchronized private void forceConsolide() {
305
        this.superClasses = null;
306
        this.superClassesMap = null;
307
        this.declaredFields = null;
308
        this.fieldsMap = null;
309
        this.fields = null;
310
        this.declaredMethods = null;
311
        this.methodsMap = null;
312
        this.methods = null;
313
    }
314

    
315
    private Set buildSuperDynClassSet() {
316
        Set dynClassParents = new LinkedHashSet();
317
        buildSuperDynClassList(this, dynClassParents);
318
        return dynClassParents;
319
    }
320

    
321
    private void buildSuperDynClassList(DefaultDynClass dynClass, Set allParents) {
322
        Collection values = dynClass.classes.values();
323
        Iterator it = values.iterator();
324
        while (it.hasNext()) {
325
            DynClass dc = (DynClass) it.next();
326
            allParents.add(dc);
327
        }
328
        it = values.iterator();
329
        while (it.hasNext()) {
330
            DefaultDynClass dc = (DefaultDynClass) it.next();
331
            buildSuperDynClassList(dc, allParents);
332
        }
333
    }
334

    
335
    public Map createValues(Map oldValues) {
336
        if (this.fields == null) {
337
            consolide();
338
        }
339
        HashMap extended = new HashMap();
340
        if (oldValues != null) {
341
            extended.putAll(oldValues);
342
        }
343
        return extended;
344
    }
345

    
346
    public void extendAll(String[] structNames) {
347
        if (structNames == null)
348
            return;
349

    
350
        for (String structName : structNames) {
351
            DynStruct dynStruct = manager.get(structName);
352
            if (dynStruct == null) {
353
                throw new DynClassNotFoundException(structName);
354
            }
355
            if (this.classes.containsKey(dynStruct.getFullName())) {
356
                continue;
357
            }
358
            this.classes.put(dynStruct.getFullName(), dynStruct);
359
        }
360

    
361
        this.forceConsolide();
362
    }
363

    
364
    @Override
365
    public void extend(DynStruct dynStruct) {
366
        if (this.classes.containsKey(dynStruct.getFullName())) {
367
            return;
368
        }
369
        this.classes.put(dynStruct.getFullName(), dynStruct);
370
        this.forceConsolide();
371
    }
372

    
373
    @Override
374
    public void extend(String structName) {
375
        DynClass dynClass = manager.get(structName);
376
        if (dynClass == null) {
377
            throw new DynClassNotFoundException(structName);
378
        }
379
        extend(dynClass);
380
    }
381

    
382
    @Override
383
    public void extend(String namespace, String structame) {
384
        DynClass dynClass = manager.get(namespace, structame);
385
        if (dynClass == null) {
386
            throw new DynClassNotFoundException(new DefaultDynClassName(
387
                structame).getFullName());
388
        }
389
        extend(dynClass);
390
    }
391

    
392
    public int getFieldIndex(String name) {
393
        if (this.fieldsMap == null) {
394
            consolide();
395
        }
396
        FieldAndIndex f =
397
            (FieldAndIndex) this.fieldsMap.get(name.toLowerCase());
398
        if (f == null) {
399
            return -1;
400
        }
401
        return f.index;
402
    }
403

    
404
    @Override
405
    public DynField getDeclaredDynField(String name) {
406
        return (DynField) this.declaredFieldsMap.get(name.toLowerCase());
407
    }
408

    
409
    @Override
410
    public DynField[] getDeclaredDynFields() {
411
        return this.declaredFields;
412
    }
413

    
414
    @Override
415
    public String getDescription() {
416
        return this.description;
417
    }
418

    
419
    @Override
420
    public DynField getDynField(String name) {
421
        if (this.fieldsMap == null) {
422
            consolide();
423
        }
424
        FieldAndIndex findex =
425
            (FieldAndIndex) fieldsMap.get(name.toLowerCase());
426
        return findex == null ? null : findex.getDynField();
427
    }
428

    
429
    public FieldAndIndex getDynFieldAndIndex(String name) {
430
        if (this.fieldsMap == null) {
431
            consolide();
432
        }
433
        return (FieldAndIndex) this.fieldsMap.get(name.toLowerCase());
434
    }
435

    
436
    @Override
437
    public DynField[] getDynFields() {
438
        if (this.fields == null) {
439
            consolide();
440
        }
441
        return this.fields;
442
    }
443

    
444
    @Override
445
    public DynField addDynField(String name) {
446
        DynField field = new DefaultDynField(name, DataTypes.STRING);
447
        return this.addDynField(field);
448
    }
449

    
450
    @Override
451
    public DynField addDynField(String name, int type) {
452
        DynField field = new DefaultDynField(name,type);
453
        return this.addDynField(field);
454
    }
455

    
456
    public DynField addDynField(DynField field) {
457
        declaredFieldsMap.put(field.getName().toLowerCase(), field);
458
        try {
459
                if( field.getOder() == 0 ) {
460
                        field.setOrder(declaredFieldsMap.size()+1 );
461
                }
462
        } catch(Exception ex) {
463
                // Ignore errors when try to add an automated order
464
        }
465
        this.forceConsolide();
466
        return field;
467
    }
468

    
469
    @Override
470
    public DynClass[] getSuperDynClasses() {
471
        if (this.superClasses == null) {
472
            consolide();
473
        }
474
        return this.superClasses;
475
    }
476

    
477
    @Override
478
    public DynStruct[] getSuperDynStructs() {
479
        return this.getSuperDynClasses();
480
    }
481

    
482
    @Override
483
    public DynObject newInstance() {
484
        return this.manager.createDynObject(this);
485
    }
486

    
487
    @Override
488
    public boolean isInstance(DynObject dynObject) {
489
        if (this.superClassesMap == null) {
490
            consolide();
491
        }
492
        DefaultDynClass objClass = (DefaultDynClass) dynObject.getDynClass();
493
        if (this.superClassesMap.containsKey(objClass.getFullName())) {
494
            return true;
495
        }
496
                if (this.getFullName().equals(objClass.getFullName())) {
497
                        return true;
498
                }
499
        if (objClass.isAnonymous) {
500
            Iterator it = objClass.classes.values().iterator();
501
            while (it.hasNext()) {
502
                DynClass dc = (DynClass) it.next();
503
                if (this.superClassesMap.containsKey(dc.getFullName())) {
504
                    return true;
505
                }
506
            }
507
        }
508
        return false;
509
    }
510

    
511
    @Override
512
    public void removeDynField(String name) {
513
        this.declaredFieldsMap.remove(name.toLowerCase());
514
        this.forceConsolide();
515
    }
516

    
517
    public void setAnonymous(boolean isAnonymous) {
518
        this.isAnonymous = isAnonymous;
519
    }
520

    
521
    public boolean isAnonymous() {
522
        return isAnonymous;
523
    }
524

    
525
    @Override
526
    public int hashCode() {
527
        return name.hashCode();
528
    }
529

    
530
    @Override
531
    public boolean equals(Object obj) {
532
        if (this == obj) {
533
            return true;
534
        }
535
        if (obj instanceof DynClass) {
536
            return this.getFullName().equals(((DynClass) obj).getFullName());
537
        }
538
        return false;
539
    }
540

    
541
    @Override
542
    public void addDynMethod(DynMethod dynMethod) {
543
        this.manager.registerDynMethod(this, dynMethod);
544
    }
545

    
546
    void addMethod(DynMethod dynMethod) {
547
        declaredMethodsMap.put(dynMethod.getName().toLowerCase(), dynMethod);
548
        this.forceConsolide();
549
    }
550

    
551
    @Override
552
    public DynMethod getDeclaredDynMethod(String name) {
553
        return (DynMethod) this.declaredMethodsMap.get(name.toLowerCase());
554
    }
555

    
556
    @Override
557
    public DynMethod[] getDeclaredDynMethods() {
558
        if (this.declaredMethods == null) {
559
            consolide();
560
        }
561
        return this.declaredMethods;
562
    }
563

    
564
    @Override
565
    public DynMethod getDynMethod(String name) throws DynMethodException {
566
        if (this.methodsMap == null) {
567
            consolide();
568
        }
569
        MethodAndIndex mindex = (MethodAndIndex) methodsMap.get(name.toLowerCase());
570
        if( mindex != null ) {
571
            return mindex.getDynMethod();
572
        }
573
        if( this.script == null || StringUtils.isEmpty(this.script.getCode()) ) {
574
            return null;
575
        }
576
        return new ScriptMethod(this.script,name);
577
    }
578

    
579
    private class ScriptMethod extends AbstractDynMethod {
580
        private final Script script;
581

    
582
        public ScriptMethod(Script script, String methodName) {
583
            super(methodName);
584
            this.script = script;
585
        }
586

    
587
        @Override
588
        public Object invoke(DynObject self, Object[] args) throws DynMethodException {
589
            try {
590
                return this.script.invokeFunction(this.getName(), args);
591
            } catch (NoSuchMethodException ex) {
592
                throw new DynMethodNotSupportedException(this.getName(),DefaultDynClass.this.getName());
593
            }
594
        }
595

    
596
    }
597

    
598
    @Override
599
    public DynMethod getDynMethod(int code) throws DynMethodException {
600
        return this.manager.getDynMethod(code);
601
    }
602

    
603
    @Override
604
    public DynMethod[] getDynMethods() {
605
        if (this.methods == null) {
606
            consolide();
607
        }
608
        return this.methods;
609
    }
610

    
611
    @Override
612
    public void removeDynMethod(String name) {
613
        // TODO Auto-generated method stub
614
    }
615

    
616
    @Override
617
    public void validate(DynObject object) throws DynObjectValidateException {
618
        DynField fields[] = this.getDynFields();
619
        DynObjectValidateException exceptions =
620
            new DynObjectValidateException(this.getFullName());
621
        for (DynField field : fields) {
622
            try {
623
                field.validate(object.getDynValue(field.getName()));
624
            } catch (DynFieldValidateException | DynFieldNotFoundException e) {
625
                exceptions.add(e);
626
            }
627
        }
628
        if (exceptions.size() > 0) {
629
            throw exceptions;
630
        }
631
    }
632

    
633
    @Override
634
    public DynField addDynFieldString(String name) {
635
        return addDynField(name,DataTypes.STRING);
636
    }
637

    
638
    @Override
639
    public DynField addDynFieldDate(String name) {
640
        return addDynField(name,DataTypes.DATE);
641
    }
642

    
643
    @Override
644
    public DynField addDynFieldInt(String name) {
645
        return addDynField(name,DataTypes.INT);
646
    }
647

    
648
    @Override
649
    public DynField addDynFieldLong(String name) {
650
        return addDynField(name,DataTypes.LONG);
651
    }
652

    
653
    @Override
654
    public DynField addDynFieldDouble(String name) {
655
        return addDynField(name,DataTypes.DOUBLE);
656
    }
657

    
658
    @Override
659
    public DynField addDynFieldFloat(String name) {
660
        return addDynField(name,DataTypes.FLOAT);
661
    }
662

    
663
    @Override
664
    public DynField addDynFieldBoolean(String name) {
665
        return addDynField(name,DataTypes.BOOLEAN);
666
    }
667

    
668
    @Override
669
    public DynField addDynFieldFolder(String name) {
670
        return addDynField(name,DataTypes.FOLDER);
671
    }
672

    
673
    @Override
674
    public DynField addDynFieldFile(String name) {
675
        return addDynField(name,DataTypes.FILE);
676
    }
677

    
678
    @Override
679
    public DynField addDynFieldURL(String name) {
680
        return addDynField(name,DataTypes.URL);
681
    }
682

    
683
    @Override
684
    public DynField addDynFieldURI(String name) {
685
        return addDynField(name,DataTypes.URI);
686
    }
687

    
688
    @Override
689
    public DynField addDynFieldArray(String name) {
690
        return addDynField(name,DataTypes.ARRAY);
691
    }
692

    
693
    @Override
694
    public DynField addDynFieldObject(String name) {
695
        return addDynField(name,DataTypes.OBJECT);
696
    }
697

    
698
    @Override
699
    public DynField addDynFieldChoice(String name, int type,
700
        Object defaultValue, DynObjectValueItem[] values) {
701
        return addDynFieldChoice(name, type, defaultValue, values, false, true);
702
    }
703

    
704
    @Override
705
    public DynField addDynFieldChoice(String name, int type,
706
        Object defaultValue, DynObjectValueItem[] values, boolean mandatory,
707
        boolean persistent) {
708
        return addDynField(name,type)
709
            .setDefaultFieldValue(defaultValue).setMandatory(mandatory)
710
            .setPersistent(persistent).setAvailableValues(values)
711
            .setDescription(description);
712
    }
713

    
714
    @Override
715
    public DynField addDynFieldRange(String name, int type,
716
        Object defaultValue, Object min, Object max) {
717
        return addDynFieldRange(name, type, defaultValue, min, max, false, true);
718
    }
719

    
720
    @Override
721
    public DynField addDynFieldRange(String name, int type,
722
        Object defaultValue, Object min, Object max, boolean mandatory,
723
        boolean persistent) {
724
        return addDynField(name,type)
725
            .setDefaultFieldValue(defaultValue).setMandatory(mandatory)
726
            .setPersistent(persistent).setMinValue(min).setMaxValue(max);
727
    }
728

    
729
    @Override
730
    public DynField addDynFieldSingle(String name, int type, Object defaultValue) {
731
        return addDynFieldSingle(name, type, defaultValue, false, true);
732
    }
733

    
734
    @Override
735
    public DynField addDynFieldSingle(String name, int type,
736
        Object defaultValue, boolean mandatory, boolean persistent) {
737
        return addDynField(name,type)
738
            .setDefaultFieldValue(defaultValue).setMandatory(mandatory)
739
            .setPersistent(persistent);
740
    }
741

    
742

    
743

    
744
        public DynField addDynFieldObject(String name, String dynObjectFullName) {
745
        return addDynField(name).setType(DataTypes.DYNOBJECT).setSubtype(dynObjectFullName);
746
    }
747

    
748
    public DynField addDynFieldObjectList(String name, String fullDynObjectName) {
749
        DynField listDynField = this.addDynFieldList(name)
750
            .setElementsType(DataTypes.DYNOBJECT)
751
            .setSubtype(fullDynObjectName);
752
        return listDynField;
753
    }
754

    
755
    @Override
756
    public DynField addDynFieldList(String name) {
757
        return addDynField(name,DataTypes.LIST);
758
    }
759

    
760
    @Override
761
    public DynField addDynFieldMap(String name) {
762
        return addDynField(name).setType(DataTypes.MAP);
763
    }
764

    
765
    @Override
766
    public DynField addDynFieldSet(String name) {
767
        return addDynField(name).setType(DataTypes.SET);
768
    }
769

    
770

    
771
    @Override
772
    public void setDescription(String description) {
773
        this.description = description;
774
    }
775

    
776
    @Override
777
    public void setNamespace(String namespace) {
778
        this.name.setNamespace(namespace);
779
    }
780

    
781
    public void check() throws ListBaseException {
782
        ListBaseException exceptions = null;
783

    
784
        if (name == null) {
785
            exceptions =
786
                CheckDynClassListException.add(exceptions, name, "name", name);
787
        }
788
        DynField[] fields = this.getDynFields();
789
        for (DynField field : fields) {
790
            try {
791
                ((DefaultDynField)field).check();
792
            }catch (Exception ex) {
793
                exceptions =
794
                        CheckDynClassListException.add(exceptions, name, ex);
795
            }
796
        }
797
        if (exceptions != null) {
798
            throw exceptions;
799
        }
800
    }
801

    
802
    public static class CheckDynClassListException extends ListBaseException {
803

    
804
        /**
805
                 *
806
                 */
807
        private static final long serialVersionUID = 9042601577056507657L;
808

    
809
        public static class CheckDynClassException extends DynObjectException {
810

    
811
            /**
812
                         *
813
                         */
814
            private static final long serialVersionUID = -1447120375445458639L;
815

    
816
            public CheckDynClassException(String attrname, Object attrvalue) {
817
                super("Wrong value %(value) for attribute %(name).",
818
                    "Wrong_value_XvalueX_for_attribute_XnameX",
819
                    serialVersionUID);
820
            }
821
        }
822

    
823
        public CheckDynClassListException(DynClassName name) {
824
            super("Inconsistent DynClass %(name) definition.",
825
                "_Inconsistent_DynClass_XnameX_definition", serialVersionUID);
826
            String s;
827
            if (name == null) {
828
                s = "[unknow]";
829
            } else {
830
                s = name.getFullName();
831
            }
832
            setValue("name", s);
833
        }
834

    
835
        @SuppressWarnings({"ThrowableInstanceNotThrown", "ThrowableInstanceNeverThrown"})
836
        public static ListBaseException add(ListBaseException exceptions,
837
            DynClassName name, String attrname, Object attrvalue) {
838
            if (exceptions == null) {
839
                exceptions = new CheckDynClassListException(name);
840
            }
841
            exceptions.add(new CheckDynClassException(attrname, attrvalue));
842
            return exceptions;
843
        }
844

    
845
        @SuppressWarnings({"ThrowableInstanceNotThrown", "ThrowableInstanceNeverThrown"})
846
        public static ListBaseException add(ListBaseException exceptions,
847
            DynClassName name, Exception ex) {
848
            if (exceptions == null) {
849
                exceptions = new CheckDynClassListException(name);
850
            }
851
            exceptions.add(ex);
852
            return exceptions;
853
        }
854
    }
855

    
856
    private boolean isExtendable(Set superClassesSet, DynStruct dynStruct) {
857

    
858
        if ((superClassesSet == null) || (superClassesSet.isEmpty())) {
859
            return true;
860
        }
861

    
862
        return !superClassesSet.contains(dynStruct);
863
    }
864

    
865
    @Override
866
    public boolean isExtendable(DynStruct dynStruct) {
867

    
868
        if (dynStruct == null) {
869
            return false;
870
        }
871

    
872
        if (this.fieldsMap == null) {
873
            consolide();
874
        }
875
        Set superClassesSet = buildSuperDynClassSet();
876
        return isExtendable(superClassesSet, dynStruct);
877
    }
878

    
879
    private void removeDynStruct(DynStruct superDynStruct) {
880
        if (this.classes.containsKey(superDynStruct.getFullName())) {
881
            this.classes.remove(superDynStruct.getFullName());
882
        }
883
    }
884

    
885
    @Override
886
    public void remove(DynStruct superDynStruct) {
887
        if (superDynStruct != null) {
888
            this.removeDynStruct(superDynStruct);
889
            this.forceConsolide();
890
        }
891
    }
892

    
893
    public void removeAll(DynStruct[] superDynStruct) {
894
        if (superDynStruct != null) {
895
            for (DynStruct superDynStruct1 : superDynStruct) {
896
                removeDynStruct(superDynStruct1);
897
            }
898
            this.consolide();
899
        }
900
    }
901

    
902
    public void extend(DynStruct[] structs) {
903
        if (structs != null) {
904
            for (DynStruct struct : structs) {
905
                extend(struct);
906
            }
907
            this.consolide();
908
        }
909
    }
910

    
911
    @Override
912
    public Tags getTags() {
913
            return tags;
914
    }
915

    
916
    @Override
917
    public String getLabel() {
918
        if( this.label == null ) {
919
            if( this.getTags().get("label") == null ) {
920
                return this.getName();
921
            }
922
            return (String) this.getTags().get("label");
923
        }
924
        return this.label;
925
    }
926

    
927
    @Override
928
    public void setLabel(String label) {
929
        this.label = label;
930
    }
931

    
932
    public void renameField(String oldname, String newName) {
933
        DefaultDynField oldfield = (DefaultDynField) this.getDynField(oldname);
934
        if( oldfield == null ) {
935
            throw new RuntimeException("field name do not exists.");
936
        }
937
        DynField newfield = this.getDynField(newName);
938
        if( newfield != null ) {
939
            throw new RuntimeException("field name already exists.");
940
        }
941
        declaredFieldsMap.remove(oldfield);
942
        oldfield.setName(newName);
943
        declaredFieldsMap.put(oldfield.getName().toLowerCase(), oldfield);
944
    }
945

    
946
}