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

History | View | Annotate | Download (27.7 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.gvsig.tools.ToolsLocator;
35
import org.gvsig.tools.dataTypes.DataTypes;
36
import org.gvsig.tools.dynobject.AbstractDynMethod;
37
import org.gvsig.tools.dynobject.DynClass;
38
import org.gvsig.tools.dynobject.DynClassName;
39
import org.gvsig.tools.dynobject.DynClass_v2;
40
import org.gvsig.tools.dynobject.DynField;
41
import org.gvsig.tools.dynobject.DynMethod;
42
import org.gvsig.tools.dynobject.DynObject;
43
import org.gvsig.tools.dynobject.DynObjectException;
44
import org.gvsig.tools.dynobject.DynObjectManager;
45
import org.gvsig.tools.dynobject.DynObjectValueItem;
46
import org.gvsig.tools.dynobject.DynStruct;
47
import org.gvsig.tools.dynobject.Tags;
48
import org.gvsig.tools.dynobject.exception.DynClassNotFoundException;
49
import org.gvsig.tools.dynobject.exception.DynFieldNotFoundException;
50
import org.gvsig.tools.dynobject.exception.DynFieldValidateException;
51
import org.gvsig.tools.dynobject.exception.DynMethodException;
52
import org.gvsig.tools.dynobject.exception.DynMethodNotSupportedException;
53
import org.gvsig.tools.dynobject.exception.DynObjectValidateException;
54
import org.gvsig.tools.exception.ListBaseException;
55
import org.gvsig.tools.script.Script;
56

    
57
public class DefaultDynClass implements DynClass_v2{
58

    
59
    public class FieldAndIndex {
60

    
61
        DefaultDynField field;
62
        int index;
63

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

    
69
        public int getIndex() {
70
            return this.index;
71
        }
72

    
73
        public DefaultDynField getDynField() {
74
            return this.field;
75
        }
76
    }
77

    
78
    public class MethodAndIndex {
79

    
80
        DynMethod method;
81
        int index;
82

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

    
88
        public int getIndex() {
89
            return this.index;
90
        }
91

    
92
        public DynMethod getDynMethod() {
93
            return this.method;
94
        }
95
    }
96

    
97
    
98
    DynObjectManager manager;
99

    
100
    private DynClassName name;
101
    private String description;
102

    
103
    private boolean isAnonymous;
104

    
105
    private Map classes;
106
    private Map declaredFieldsMap;
107
    private Map declaredMethodsMap;
108

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

    
119
    private final Tags tags = new DefaultTags();
120
    private String label = null;
121

    
122
    private Script script = null;
123
    
124
    @SuppressWarnings("OverridableMethodCallInConstructor")
125
    public DefaultDynClass(String name) {
126
        this((DynObjectManager)null, (DynClassName)null, (String)null);
127
        this.setName( new DefaultDynClassName(name));
128
    }
129

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

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

    
144
    public DefaultDynClass(DynObjectManager manager, DynClassName name,
145
        String description) {
146
        if( manager == null ) {
147
            manager = ToolsLocator.getDynObjectManager();
148
        }
149
        
150
        this.isAnonymous = false;
151
        this.classes = new LinkedHashMap();
152
        this.declaredFieldsMap = new HashMap();
153
        this.declaredMethodsMap = new HashMap();
154

    
155
        this.forceConsolide();  
156

    
157
        this.manager = manager;
158
        this.name = name;
159
        this.description = description;
160
    }
161
    
162
    public void setName(DynClassName name) {
163
        this.name = name;
164
    }
165
 
166
    @Override
167
    public String getName() {
168
        return this.name.getName();
169
    }
170

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

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

    
181
    @Override
182
    public String toString() {
183
        StringBuilder buffer = new StringBuilder();
184

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

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

    
202
    public DynObjectManager getManager() {
203
        return this.manager;
204
    }
205

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
359
        this.forceConsolide();
360
    }
361

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
515
    public void setAnonymous(boolean isAnonymous) {
516
        this.isAnonymous = isAnonymous;
517
    }
518

    
519
    public boolean isAnonymous() {
520
        return isAnonymous;
521
    }
522

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

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

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

    
544
    void addMethod(DynMethod dynMethod) {
545
        declaredMethodsMap.put(dynMethod.getName(), dynMethod);
546
        this.forceConsolide();
547
    }
548

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

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

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

    
577
    private class ScriptMethod extends AbstractDynMethod {
578
        private final Script script;
579

    
580
        public ScriptMethod(Script script, String methodName) {
581
            super(methodName);
582
            this.script = script;
583
        }
584
        
585
        @Override
586
        public Object invoke(DynObject self, Object[] args) throws DynMethodException {
587
            try {
588
                return this.script.invokeFunction(this.getName(), args);
589
            } catch (NoSuchMethodException ex) {
590
                throw new DynMethodNotSupportedException(this.getName(),DefaultDynClass.this.getName());
591
            }
592
        }
593

    
594
    }
595
    
596
    @Override
597
    public DynMethod getDynMethod(int code) throws DynMethodException {
598
        return this.manager.getDynMethod(code);
599
    }
600

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
691
    @Override
692
    public DynField addDynFieldObject(String name) {
693
        return addDynField(name,DataTypes.OBJECT);
694
    }
695
    
696
    @Override
697
    public DynField addDynFieldChoice(String name, int type,
698
        Object defaultValue, DynObjectValueItem[] values) {
699
        return addDynFieldChoice(name, type, defaultValue, values, false, true);
700
    }
701

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

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

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

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

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

    
740

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

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

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

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

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

    
768

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

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

    
779
    public void check() throws ListBaseException {
780
        ListBaseException exceptions = null;
781

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

    
800
    public static class CheckDynClassListException extends ListBaseException {
801

    
802
        /**
803
                 * 
804
                 */
805
        private static final long serialVersionUID = 9042601577056507657L;
806

    
807
        public static class CheckDynClassException extends DynObjectException {
808

    
809
            /**
810
                         * 
811
                         */
812
            private static final long serialVersionUID = -1447120375445458639L;
813

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

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

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

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

    
854
    private boolean isExtendable(Set superClassesSet, DynStruct dynStruct) {
855

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

    
860
        return !superClassesSet.contains(dynStruct);
861
    }
862

    
863
    @Override
864
    public boolean isExtendable(DynStruct dynStruct) {
865

    
866
        if (dynStruct == null) {
867
            return false;
868
        }
869

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

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

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

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

    
900
    public void extend(DynStruct[] structs) {
901
        if (structs != null) {
902
            for (DynStruct struct : structs) {
903
                extend(struct);
904
            }
905
            this.consolide();
906
        }
907
    }
908
    
909
    @Override
910
    public Tags getTags() {
911
            return tags;
912
    }
913

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

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

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