Statistics
| Revision:

gvsig-tools / org.gvsig.tools / library / trunk / org.gvsig.tools / org.gvsig.tools.lib / src / main / java / org / gvsig / tools / dynobject / impl / DefaultDynObjectManager.java @ 1961

History | View | Annotate | Download (29.2 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.io.File;
27
import java.io.FileNotFoundException;
28
import java.io.IOException;
29
import java.io.InputStream;
30
import java.io.OutputStream;
31
import java.util.ArrayList;
32
import java.util.Arrays;
33
import java.util.Collections;
34
import java.util.HashMap;
35
import java.util.HashSet;
36
import java.util.Iterator;
37
import java.util.List;
38
import java.util.Map;
39
import java.util.Objects;
40
import java.util.Set;
41
import org.apache.commons.lang3.StringUtils;
42

    
43
import org.gvsig.tools.ToolsLocator;
44
import org.gvsig.tools.dataTypes.DataTypes;
45
import org.gvsig.tools.dynobject.AbstractDynMethod;
46
import org.gvsig.tools.dynobject.DynClass;
47
import org.gvsig.tools.dynobject.DynClassName;
48
import org.gvsig.tools.dynobject.DynClass_v2;
49
import org.gvsig.tools.dynobject.DynField;
50
import org.gvsig.tools.dynobject.DynField_LabelAttribute;
51
import org.gvsig.tools.dynobject.DynField_v2;
52
import org.gvsig.tools.dynobject.DynMethod;
53
import org.gvsig.tools.dynobject.DynObject;
54
import org.gvsig.tools.dynobject.DynObjectEncoder;
55
import org.gvsig.tools.dynobject.DynObjectManager;
56
import org.gvsig.tools.dynobject.DynObjectPagingHelper;
57
import org.gvsig.tools.dynobject.DynObjectRuntimeException;
58
import org.gvsig.tools.dynobject.DynObjectSet;
59
import org.gvsig.tools.dynobject.DynStruct;
60
import org.gvsig.tools.dynobject.DynStruct_v2;
61
import org.gvsig.tools.dynobject.exception.DuplicateDynClassException;
62
import org.gvsig.tools.dynobject.exception.DynFieldNotFoundException;
63
import org.gvsig.tools.dynobject.exception.DynMethodException;
64
import org.gvsig.tools.dynobject.exception.DynMethodIllegalCodeException;
65
import org.gvsig.tools.dynobject.exception.DynMethodNotSupportedException;
66
import org.gvsig.tools.dynobject.exception.IllegalDynMethodException;
67
import org.gvsig.tools.dynobject.exception.IllegalDynMethodInvocationException;
68
import org.gvsig.tools.exception.BaseException;
69
import org.gvsig.tools.util.UnmodifiableBasicMap;
70
import org.gvsig.tools.util.UnmodifiableBasicMapAdapter;
71
import org.slf4j.Logger;
72
import org.slf4j.LoggerFactory;
73
import org.xmlpull.v1.XmlPullParser;
74
import org.xmlpull.v1.XmlPullParserException;
75

    
76
/**
77
 * Default {@link DynObjectManager} implementation.
78
 * 
79
 * @author gvSIG Team
80
 * @version $Id$
81
 */
82
public class DefaultDynObjectManager implements DynObjectManager {
83

    
84
    private final static Logger LOG = LoggerFactory
85
        .getLogger(DefaultDynObjectManager.class);
86

    
87
    private static DefaultDynObjectManager manager = null;
88
    
89
    private class MethodInfo {
90

    
91
        int code;
92
        DynClass dynClass;
93
        DynMethod dynMethod;
94
        Class theClass;
95

    
96
        MethodInfo(Class theClass, DynClass dynClass, DynMethod dynMethod,
97
            int code) {
98
            this.code = code;
99
            this.dynClass = dynClass;
100
            this.dynMethod = dynMethod;
101
            this.theClass = theClass;
102
        }
103

    
104
        String getKey() {
105
            return DefaultDynObjectManager
106
                .getKey(theClass, dynClass, dynMethod);
107
        }
108

    
109
        void check(Class theClass, int code) throws DynMethodException {
110
            if (code != this.code) {
111
                throw new DynMethodIllegalCodeException(dynMethod.getName(),
112
                    this.code, code);
113
            }
114
            if (theClass != null) {
115
                if (this.theClass == null) {
116
                    throw new IllegalDynMethodInvocationException(
117
                        dynMethod.getName(), theClass);
118
                }
119
                if (!this.theClass.isAssignableFrom(theClass)) {
120
                    throw new IllegalDynMethodInvocationException(
121
                        dynMethod.getName(), theClass);
122
                }
123
            }
124
        }
125

    
126
        void check(DynClass dynClass, int code) throws DynMethodException {
127
            if (code != this.code) {
128
                throw new DynMethodIllegalCodeException(dynMethod.getName(),
129
                    this.code, code);
130
            }
131
            if (dynClass != null) {
132
                if (this.dynClass == null) {
133
                    throw new IllegalDynMethodInvocationException(
134
                        dynMethod.getName(), dynClass);
135
                }
136
                if (dynClass != this.dynClass
137
                    || !dynClass.getName().equalsIgnoreCase(
138
                        this.dynClass.getName())) {
139
                    throw new IllegalDynMethodInvocationException(
140
                        dynMethod.getName(), dynClass);
141
                }
142
            }
143
        }
144
    }
145

    
146
    private class ClassesNamespaces {
147

    
148
        private Map defaultNamespace;
149
        private Map namespaces;
150

    
151
        ClassesNamespaces() {
152
            this.namespaces = new HashMap();
153
            this.defaultNamespace = new HashMap();
154
        }
155

    
156
        public Map addNamespace(String name) {
157
            Map namespace = new HashMap();
158
            this.namespaces.put(name.toLowerCase(), namespace);
159
            return namespace;
160
        }
161

    
162
        public Map getNamespace(String name) {
163
            return (Map) this.namespaces.get(name.toLowerCase());
164
        }
165

    
166
//        public void clear() {
167
//            this.defaultNamespace.clear();
168
//            this.namespaces.clear();
169
//        }
170

    
171
        public boolean containsClass(String name) {
172
            name = name.toLowerCase();
173
            if (this.defaultNamespace.containsKey(name)) {
174
                return true;
175
            }
176

    
177
            Iterator it = this.namespaces.values().iterator();
178
            while (it.hasNext()) {
179
                Map names = (Map) it.next();
180
                if (names.containsKey(name)) {
181
                    return true;
182
                }
183
            }
184
            return false;
185
        }
186

    
187
        public boolean containsClass(String namespace, String name) {
188
            name = name.toLowerCase();
189
            if (namespace == null) {
190
                return this.defaultNamespace.containsKey(name);
191
            }
192
            Map space = this.getNamespace(namespace);
193
            if (space == null) {
194
                return false;
195
            }
196
            return space.containsKey(name);
197
        }
198

    
199
//        public boolean containsClass(DynClass dynClass) {
200
//            if (this.defaultNamespace.containsValue(dynClass)) {
201
//                return true;
202
//            }
203
//
204
//            Iterator it = this.namespaces.values().iterator();
205
//            while (it.hasNext()) {
206
//                Map names = (Map) it.next();
207
//                if (names.containsValue(dynClass)) {
208
//                    return true;
209
//                }
210
//            }
211
//            return false;
212
//        }
213

    
214
        public DynClass get(String name, String namespace) {
215
            if (namespace == null) {
216
                return (DynClass) this.defaultNamespace.get(name.toLowerCase());
217
            }
218
            Map space = this.getNamespace(namespace);
219
            if (space == null) {
220
                return null;
221
            }
222
            DynClassName className = new DefaultDynClassName(name);
223
            if (className.getNamespace()==null){
224
                return (DynClass) space.get(name.toLowerCase());
225
            }
226
            if (!namespace.equalsIgnoreCase(className.getNamespace())){
227
                    return null;
228
            }
229
            return (DynClass) space.get(className.getName().toLowerCase());
230
        }
231

    
232
        public Set keySet() {
233
            Set keyset = new HashSet();
234
            Iterator it = this.iterator();
235
            while (it.hasNext()) {
236
                DynClass dynClass = (DynClass) it.next();
237
                keyset.add(dynClass.getFullName());
238
            }
239
            return keyset;
240
        }
241

    
242
        public Iterator iterator() {
243
            final class MyIterator implements Iterator {
244

    
245
                Iterator current;
246
                Iterator others;
247

    
248
                MyIterator(Iterator main, Iterator others) {
249
                    this.current = main;
250
                    this.others = others;
251
                }
252

    
253
                public boolean hasNext() {
254
                    if (this.current.hasNext()) {
255
                        return true;
256
                    }
257
                    while (this.others.hasNext()) { 
258
                        Object obj = others.next();
259
                        this.current = (Iterator) ((HashMap) obj).values().iterator();
260
                        if (this.current.hasNext()) {
261
                            return true;
262
                        }
263
                    }
264
                    return false;
265
                }
266

    
267
                public Object next() {
268
                    if (this.current.hasNext()) {
269
                        return this.current.next();
270
                    }
271
                    while (this.others.hasNext()) {
272
                        Object obj = others.next();
273
                        this.current = (Iterator) ((HashMap) obj).values().iterator();
274
                        if (this.current.hasNext()) {
275
                            return this.current.next();
276
                        }
277
                    }
278
                    return null;
279
                }
280

    
281
                public void remove() {
282
                    throw new UnsupportedOperationException();
283
                }
284
            }
285

    
286
            return new MyIterator(this.defaultNamespace.values().iterator(),
287
                this.namespaces.values().iterator());
288
        }
289

    
290
        public Object add(DynStruct dynClass) {
291
            String name = dynClass.getName().toLowerCase();
292
            Map namespace;
293
            if (dynClass.getNamespace() != null) {
294
                namespace = (Map) this.getNamespace(dynClass.getNamespace());
295
                if (namespace == null) {
296
                    namespace = this.addNamespace(dynClass.getNamespace());
297
                }
298
            } else {
299
                namespace = this.defaultNamespace;
300
            }
301
            if (namespace.containsKey(name)) {
302
                throw new DuplicateDynClassException(dynClass);
303
            }
304
            return namespace.put(name, dynClass);
305
        }
306

    
307
        public void remove(DynStruct dynClass) {
308
            String name = dynClass.getName().toLowerCase();
309
            Map namespace;
310
            if (dynClass.getNamespace() != null) {
311
                namespace = (Map) this.getNamespace(dynClass.getNamespace());
312
                if (namespace == null) {
313
                    namespace = this.addNamespace(dynClass.getNamespace());
314
                }
315
            } else {
316
                namespace = this.defaultNamespace;
317
            }
318
            if (namespace.containsKey(name)) {
319
                namespace.remove(name);
320
            }
321
        }
322

    
323
        public int size() {
324
            int count = this.defaultNamespace.size();
325

    
326
            Iterator it = this.namespaces.values().iterator();
327
            while (it.hasNext()) {
328
                Map names = (Map) it.next();
329
                count += names.size();
330
            }
331
            return count;
332
        }
333

    
334
    }
335

    
336
    private Map anonymousClasses;
337
    private ClassesNamespaces classes;
338
    private Map methodsMap;
339
    private List<MethodInfo> methods;
340
    private Map<String,String> tags;
341

    
342
    public static DefaultDynObjectManager getManager() {
343
        if (manager == null) {
344
            manager = new DefaultDynObjectManager();
345
        }
346
        return manager;
347
    }
348

    
349
    static String getKey(Class theClass, DynClass dynClass, DynMethod dynMethod) {
350
        return DefaultDynObjectManager.getKey(theClass, dynClass,
351
            dynMethod.getName());
352
    }
353

    
354
    static String getKey(Class theClass, DynClass dynClass, String methodName) {
355
        if (dynClass == null) {
356
            if( theClass == null ) {
357
                return "__anonymous__:" + methodName;
358
            } else {
359
                return theClass.getName() + ":" + methodName;
360
            }
361
        } else {
362
            return dynClass.getName() + ":" + methodName;
363
        }
364
    }
365

    
366
    public DefaultDynObjectManager() {
367
        this.classes = new ClassesNamespaces();
368
        this.anonymousClasses = new HashMap();
369
        this.methodsMap = new HashMap();
370
        this.methods = null;
371
    }
372

    
373
    public DynClass_v2 createDynClass(String name, String description) {
374
        return new DefaultDynClass(this, name, description);
375
    }
376

    
377
    public DynClass_v2 createDynClass(String namespace, String name,
378
        String description) {
379
        return new DefaultDynClass(this, namespace, name, description);
380
    }
381

    
382
    public void add(DynClass dynClass) {
383
        try {
384
            ((DefaultDynClass) dynClass).check();
385
        } catch (Exception ex) {
386
            throw new DynObjectRuntimeException(ex);
387
        }
388
        this.classes.add(dynClass);
389
        LOG.trace("Add DynClass definition {}.",
390
            new Object[] { dynClass.getFullName() });
391

    
392
    }
393

    
394
    public DynClass add(String name, String description) {
395
        DynClass dynClass =
396
            (DynClass) this.classes.get(name.toLowerCase(), null);
397
        if (dynClass == null) {
398
            dynClass = this.createDynClass(name, description);
399
            this.add(dynClass);
400
        }
401
        return dynClass;
402
    }
403

    
404
    public DynClass add(String name) {
405
        return this.add(name, null);
406
    }
407

    
408
    public void remove(DynStruct dynClass) {
409
        this.classes.remove(dynClass);
410
    }
411

    
412
    // public static String getFullName(String namespace, String name) {
413
    // if( namespace == null ) {
414
    // return name;
415
    // }
416
    // return namespace + ":" + name;
417
    // }
418
    // public static String[] splitFullName(String fullname) {
419
    // String[] name = new String[] { null, fullname };
420
    // int x=fullname.indexOf(':');
421
    // if( x>-1 ) {
422
    // name[0] = fullname.substring(0, x);
423
    // name[1] = fullname.substring(x+1);
424
    // }
425
    // return name;
426
    //
427
    // }
428

    
429
    public DynClass get(String theName) {
430
        DynClassName name = createDynClassName(theName);
431
        return this.get(name.getNamespace(), name.getName());
432
    }
433

    
434
    public DynClass get(String namespace, String name) {
435
        return (DynClass) this.classes.get(name, namespace);
436
    }
437

    
438
    public DynClass get(DynClass[] superClasses) {
439
        StringBuffer name = new StringBuffer();
440
        for (int i = 0; i < superClasses.length; i++) {
441
            name.append(superClasses[i].getName()).append("+");
442
        }
443
        DefaultDynClass dynClass =
444
            (DefaultDynClass) this.anonymousClasses.get(name.toString());
445
        if (dynClass == null) {
446
            dynClass =
447
                new DefaultDynClass(this, name.toString(), null, superClasses);
448
            dynClass.setAnonymous(true);
449
        }
450
        return dynClass;
451
    }
452

    
453
    public int getCount() {
454
        return this.classes.size();
455
    }
456

    
457
    public List getNames() {
458
        String[] names = (String[]) this.classes.keySet().toArray();
459
        Arrays.sort(names);
460
        return Collections.unmodifiableList(Arrays.asList(names));
461
    }
462

    
463
    public boolean has(String name) {
464
        return this.classes.containsClass(name);
465
    }
466

    
467
    public boolean has(String namespace, String name) {
468
        return this.classes.containsClass(namespace, name);
469
    }
470

    
471
    public Iterator iterator() {
472
        return this.classes.iterator();
473
    }
474

    
475
    public DynObject createDynObject(String dynClassName) {
476
        DynClassName name = createDynClassName(dynClassName);
477
        return this.createDynObject(name.getName(), name.getNamespace());
478
    }
479

    
480
    public DynObject createDynObject(String dynClassName, String namespace) {
481

    
482
        DynClass dynClass =
483
            (DynClass) this.classes.get(dynClassName, namespace);
484
        if (dynClass == null) {
485
            throw new IllegalArgumentException("Can't locate class '"
486
                + createDynClassName(namespace, dynClassName).getFullName()
487
                + "'.");
488
        }
489
        return this.createDynObject(dynClass);
490
    }
491

    
492
    public DynObject createDynObject(DynStruct dynClass) {
493
        return new DefaultDynObject(dynClass);
494
    }
495

    
496
    public void consolide() {
497
        Iterator it = this.classes.iterator();
498
        while (it.hasNext()) {
499
            DefaultDynClass dc = (DefaultDynClass) it.next();
500
            dc.consolide();
501
        }
502
        it = this.anonymousClasses.values().iterator();
503
        while (it.hasNext()) {
504
            DefaultDynClass dc = (DefaultDynClass) it.next();
505
            dc.consolide();
506
        }
507
    }
508

    
509
    public int registerDynMethod(DynClass dynClass, DynMethod dynMethod) {
510
        ((DefaultDynClass) dynClass).addMethod(dynMethod);
511
        return registerDynMethod(null, dynClass, dynMethod);
512
    }
513

    
514
    public int registerDynMethod(Class theClass, DynMethod dynMethod) {
515
        return registerDynMethod(theClass, null, dynMethod);
516
    }
517

    
518
    public int registerDynMethod(DynMethod dynMethod) {
519
        return registerDynMethod(null, null, dynMethod);
520
    }
521

    
522
    int registerDynMethod(Class theClass, DynClass dynClass, DynMethod dynMethod) {
523
        MethodInfo info = new MethodInfo(theClass, dynClass, dynMethod, 0);
524
        MethodInfo oldInfo = (MethodInfo) methodsMap.get(info.getKey());
525
        if (oldInfo != null) {
526
            // Update the method info
527
            oldInfo.dynClass = dynClass;
528
            oldInfo.dynMethod = dynMethod;
529
            return oldInfo.code;
530
        }
531
        if (methods == null) {
532
            methods = new ArrayList<>();
533
        }
534
        info.code = methods.size();
535
        methods.add(info);
536
        methodsMap.put(info.getKey(), info);
537
        try {
538
            if( dynMethod instanceof AbstractDynMethod && dynMethod.getCode()<0 ) {
539
                ((AbstractDynMethod)dynMethod).setCode(info.code);
540
            }
541
        } catch (DynMethodNotSupportedException ex) {
542
        }
543
        return info.code;
544
    }
545

    
546
    public Object invokeDynMethod(Object self, int code, DynObject context)
547
        throws DynMethodException {
548

    
549
        try {
550
            /*
551
             * Intentamos ejecutar la operacion, y si peta ya haremos las
552
             * comprobaciones oportunas para lanzar la excepcion que toque.
553
             * 
554
             * Asi evitamos codigo de comprobacion para los casos que valla bien
555
             * que deberian ser la mayoria.
556
             */
557
            return methods.get(code).dynMethod.invoke((DynObject)self, new Object[] {context});
558
        } catch (RuntimeException e) {
559
            getDynMethod(self, code);
560
            throw e;
561
        } catch (DynMethodException e) {
562
            getDynMethod(self, code);
563
            throw e;
564
        }
565

    
566
    }
567

    
568
    public int getDynMethodCode(DynClass dynClass, String methodName)
569
        throws DynMethodException {
570
        String key = DefaultDynObjectManager.getKey(null, dynClass, methodName);
571
        MethodInfo info = (MethodInfo) methodsMap.get(key);
572
        if (info == null) {
573
            throw new IllegalDynMethodException(methodName, dynClass);
574
        }
575
        info.check(dynClass, info.code);
576
        return info.code;
577
    }
578

    
579
    public int getDynMethodCode(Class theClass, String methodName)
580
        throws DynMethodException {
581
        String key = DefaultDynObjectManager.getKey(theClass, null, methodName);
582
        MethodInfo info = (MethodInfo) methodsMap.get(key);
583
        if (info == null) {
584
            throw new IllegalDynMethodException(methodName, theClass);
585
        }
586
        info.check(theClass, info.code);
587
        return info.code;
588
    }
589

    
590
    public DynMethod getDynMethod(int code) throws DynMethodException {
591
        if (code >= methods.size()) {
592
            throw new DynMethodNotSupportedException(code, "{null}");
593
        }
594
        MethodInfo info = methods.get(code);
595
        info.check((Class) null, code);
596
        return info.dynMethod;
597
    }
598
    
599
    @Override
600
    public DynMethod getDynMethod(String methodName) throws DynMethodException {
601
        String key = DefaultDynObjectManager.getKey(null, null, methodName);
602
        MethodInfo info = (MethodInfo) methodsMap.get(key);
603
        if (info == null) {
604
            throw new IllegalDynMethodException(methodName);
605
        }
606
        return info.dynMethod;
607
    }
608
    
609
    public DynMethod getDynMethod(Object obj, int code)
610
        throws DynMethodException {
611
        return getDynMethod(obj.getClass(), code);
612
    }
613

    
614
    public DynMethod getDynMethod(Class theClass, int code)
615
        throws DynMethodException {
616
        if (code >= methods.size()) {
617
            throw new DynMethodNotSupportedException(code, theClass.getName());
618
        }
619
        MethodInfo info = methods.get(code);
620
        info.check(theClass, code);
621
        return info.dynMethod;
622
    }
623

    
624
    public DynMethod getDynMethod(DynClass dynClass, int code)
625
        throws DynMethodException {
626
        if (code >= methods.size()) {
627
            throw new DynMethodNotSupportedException(code, dynClass.getName());
628
        }
629
        MethodInfo info = methods.get(code);
630
        info.check(dynClass, code);
631
        return info.dynMethod;
632
    }
633

    
634
    public DynMethod getDynMethod(DynObject dynObject, int code)
635
        throws DynMethodException {
636
        return getDynMethod(dynObject.getDynClass(), code);
637
    }
638

    
639
    public void validate(DynObject object) {
640
        // TODO
641
        return;
642
    }
643

    
644
    public Class getDefaultClassOfType(int type) {
645
        return ToolsLocator.getDataTypesManager().getDefaultClass(type);
646
    }
647

    
648
    public String exportSimpleDynClassDefinitions(DynClass dynClass) {
649
        DynClassExportHelper exporter = new DynClassExportHelper();
650
        return exporter.exportSimpleDefinition(dynClass);
651
    }
652
    
653
    public void exportSimpleDynClassDefinitions(File out, DynClass dynClass) throws FileNotFoundException {
654
        DynClassExportHelper exporter = new DynClassExportHelper();
655
        exporter.exportSimpleDefinition(out, dynClass);
656
    }
657
    
658
    public void exportSimpleDynClassDefinitions(OutputStream out, DynClass dynClass) {
659
        DynClassExportHelper exporter = new DynClassExportHelper();
660
        exporter.exportSimpleDefinition(out, dynClass);
661
    }
662
    
663
    public Map importDynClassDefinitions(InputStream resource,
664
        ClassLoader loader) throws XmlPullParserException, IOException {
665
        return new DynClassImportHelper().importDefinitions(resource, loader,
666
            null);
667
    }
668

    
669
    public Map importDynClassDefinitions(XmlPullParser parser,
670
        ClassLoader loader, String defaultNamespace)
671
        throws XmlPullParserException, IOException {
672
        return new DynClassImportHelper().importDefinitions(parser, loader,
673
            defaultNamespace);
674
    }
675

    
676
    public Map importDynClassDefinitions(InputStream resource,
677
        ClassLoader loader, String defaultNamespace)
678
        throws XmlPullParserException, IOException {
679
        return new DynClassImportHelper().importDefinitions(resource, loader,
680
            defaultNamespace);
681
    }
682

    
683
    public DynObjectPagingHelper createDynObjectPagingHelper(DynObjectSet set)
684
        throws BaseException {
685
        return new DefaultDynObjectPagingHelper(set); 
686
    }
687

    
688
    public DynObjectPagingHelper createDynObjectPagingHelper(DynObjectSet set,
689
        int pageSize) throws BaseException {
690
        return new DefaultDynObjectPagingHelper(set, pageSize);
691
    }
692

    
693
    public DynClassName createDynClassName(String namespace, String name) {
694
        return new DefaultDynClassName(namespace, name);
695
    }
696

    
697
    public DynClassName createDynClassName(String name) {
698
        return new DefaultDynClassName(name);
699
    }
700

    
701
    public Iterator iterator(String nameSpace) {
702
        return iterator(nameSpace, false);
703
    }
704

    
705
    private Iterator iterator(String nameSpace, boolean exactMatchingRequired) {
706

    
707
        List list = new ArrayList();
708
        Iterator it = this.classes.iterator();
709

    
710
        if (nameSpace == null) {
711
            nameSpace = "";
712
        }
713

    
714
        while( it.hasNext() ) {
715
            
716
            Object obj = it.next();
717
            DynStruct dynStruct = (DynStruct) obj;
718
            String dynNameSpace = dynStruct.getNamespace();
719
            if ((dynNameSpace == null) || (dynNameSpace.equals(""))) {
720
                dynNameSpace = null;
721
            } else {
722
                dynNameSpace = dynNameSpace.toLowerCase();
723
            }
724
            nameSpace = nameSpace.toLowerCase();
725
            if (exactMatchingRequired) {
726
                if (nameSpace.equalsIgnoreCase(dynNameSpace)) {
727
                    list.add(dynStruct);
728
                }
729
            } else {
730
                if ((dynNameSpace != null)
731
                    && (nameSpace.indexOf(dynNameSpace) > -1)) {
732
                    list.add(dynStruct);
733
                }
734
            }
735
        }
736
        return list.iterator();
737
    }
738

    
739
    public Object getAttributeValue(Object obj, String name) {
740
        if( "label".equalsIgnoreCase(name) ) {
741
            if( obj instanceof DynField_LabelAttribute ) {
742
                return ((DynField_LabelAttribute)obj).getLabel();
743
            }
744
            } else if( "StructWhenTypeIsDynObject".equalsIgnoreCase(name) ) {
745
            if( obj instanceof DynField_v2 ) {
746
                return ((DynField_v2)obj).getDynClassOfValue();
747
            }
748
            }
749
            return null;
750
    }
751

    
752
    public void setAttributeValue(Object obj, String name, Object value) {
753
        if( "label".equalsIgnoreCase(name) ) {
754
            if( obj instanceof DynField_LabelAttribute ) {
755
                ((DynField_LabelAttribute)obj).setLabel((String) value);
756
            }
757
            } else if( "StructWhenTypeIsDynObject".equalsIgnoreCase(name) ) {
758
            if( obj instanceof DynField_v2 ) {
759
                ((DynField_v2)obj).setClassOfValue((DynStruct) value);
760
            }
761
            }
762
    }
763

    
764
    @Override
765
    public DynObjectEncoder createSimpleDynObjectEncoder() {
766
        return new SimpleDynObjectEncoder();
767
    }
768

    
769
    @Override
770
    public void copy(DynObject source, DynObject target) {
771
        for (DynField field : target.getDynClass().getDynFields() ) {
772
            String name = field.getName();
773
            try {
774
                Object value = source.getDynValue(name);
775
                target.setDynValue(name, value);
776
            } catch(DynFieldNotFoundException | DefaultDynObject.CoerceValueException ex) {
777
                // if field not found in source or types are inconsistent, ignore it.
778
            }
779
        }
780
    }
781
    
782
    public boolean equals(DynObject obj1, DynObject obj2) {
783
        if( !StringUtils.equalsIgnoreCase(
784
                obj1.getDynClass().getFullName(),
785
                obj2.getDynClass().getFullName()) ) {
786
            return false;
787
        }
788
        for (DynField field : obj1.getDynClass().getDynFields() ) {
789
            String name = field.getName();
790
            if( !Objects.equals(obj1.getDynValue(name), obj2.getDynValue(name)) ) {
791
                return false;
792
            }
793
        }
794
        return true;
795
    }
796

    
797
    public int hashCode(DynObject obj) {
798
        DynField[] fields = obj.getDynClass().getDynFields();
799
        Object[] values = new Object[fields.length];
800
        int n = 0;
801
        for (DynField field : fields ) {
802
            String name = field.getName();
803
            values[n++] = obj.getDynValue(name);
804
        }
805
        return Arrays.hashCode(values);
806
    }
807
    
808
    @Override
809
    public void clear(DynObject obj) {
810
        for (DynField field : obj.getDynClass().getDynFields() ) {
811
            String name = field.getName();
812
            try {
813
                Object value = field.getDefaultValue();
814
                obj.setDynValue(name, value);
815
            } catch(DefaultDynObject.CoerceValueException ex) {
816
                // if types are inconsistent, ignore it.
817
            }
818
        }        
819
    }
820

    
821
    @Override
822
    public DynField_v2 createDynField(String name) {
823
        return new DefaultDynField(name, DataTypes.STRING);
824
    }
825

    
826
    @Override
827
    public DynClass_v2 createCopy(DynClass source) {
828
        DynClass_v2 target = this.createDynClass(
829
                source.getNamespace(),
830
                source.getName(), 
831
                source.getDescription()
832
        );
833
        if( source instanceof DynStruct_v2 ) {
834
            DynStruct_v2 source2 = (DynStruct_v2) source;
835
            target.setLabel(source2.getLabel());
836
            target.getTags().add(source2.getTags());
837
        }
838
        for (DynField sourceField : source.getDynFields()) {
839
            DynField_v2 targetField = (DynField_v2) target.addDynField(sourceField.getName());
840
            targetField.copyFrom(sourceField);
841
        }
842
        try {
843
            DynMethod[] x = source.getDynMethods();
844
            if( x!=null ) {
845
                for (DynMethod sourceMethod : x) {
846
                    target.addDynMethod(sourceMethod);
847
                }
848
            }
849
        } catch (DynMethodException ex) {
850
        }
851
        return target;
852
    }
853

    
854
    @Override
855
    public UnmodifiableBasicMap<String, String> getTags() {
856
        if( this.tags==null ) {
857
            this.tags = new HashMap<>();
858
        }
859
        return new UnmodifiableBasicMapAdapter<>(this.tags);
860
    }
861

    
862
    @Override
863
    public void registerTag(String name, String description) {
864
        if( this.tags==null ) {
865
            this.tags = new HashMap<>();
866
        }
867
        this.tags.put(name, description);
868
    }
869

    
870

    
871
}