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

History | View | Annotate | Download (23.3 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.IOException;
27
import java.io.InputStream;
28
import java.util.ArrayList;
29
import java.util.Arrays;
30
import java.util.Collections;
31
import java.util.HashMap;
32
import java.util.HashSet;
33
import java.util.Iterator;
34
import java.util.List;
35
import java.util.Map;
36
import java.util.Set;
37

    
38
import org.gvsig.tools.ToolsLocator;
39
import org.gvsig.tools.dynobject.DynClass;
40
import org.gvsig.tools.dynobject.DynClassName;
41
import org.gvsig.tools.dynobject.DynField;
42
import org.gvsig.tools.dynobject.DynMethod;
43
import org.gvsig.tools.dynobject.DynObject;
44
import org.gvsig.tools.dynobject.DynObjectManager;
45
import org.gvsig.tools.dynobject.DynObjectPagingHelper;
46
import org.gvsig.tools.dynobject.DynObjectRuntimeException;
47
import org.gvsig.tools.dynobject.DynObjectSet;
48
import org.gvsig.tools.dynobject.DynStruct;
49
import org.gvsig.tools.dynobject.exception.DuplicateDynClassException;
50
import org.gvsig.tools.dynobject.exception.DynMethodException;
51
import org.gvsig.tools.dynobject.exception.DynMethodIllegalCodeException;
52
import org.gvsig.tools.dynobject.exception.DynMethodNotSupportedException;
53
import org.gvsig.tools.dynobject.exception.IllegalDynMethodException;
54
import org.gvsig.tools.dynobject.exception.IllegalDynMethodInvocationException;
55
import org.gvsig.tools.exception.BaseException;
56
import org.slf4j.Logger;
57
import org.slf4j.LoggerFactory;
58
import org.xmlpull.v1.XmlPullParser;
59
import org.xmlpull.v1.XmlPullParserException;
60

    
61
/**
62
 * Default {@link DynObjectManager} implementation.
63
 * 
64
 * @author gvSIG Team
65
 * @version $Id$
66
 */
67
public class DefaultDynObjectManager implements DynObjectManager {
68

    
69
    private final static Logger LOG = LoggerFactory
70
        .getLogger(DefaultDynObjectManager.class);
71

    
72
    private static DefaultDynObjectManager manager = null;
73

    
74
    private class MethodInfo {
75

    
76
        int code;
77
        DynClass dynClass;
78
        DynMethod dynMethod;
79
        Class theClass;
80

    
81
        MethodInfo(Class theClass, DynClass dynClass, DynMethod dynMethod,
82
            int code) {
83
            this.code = code;
84
            this.dynClass = dynClass;
85
            this.dynMethod = dynMethod;
86
            this.theClass = theClass;
87
        }
88

    
89
        String getKey() {
90
            return DefaultDynObjectManager
91
                .getKey(theClass, dynClass, dynMethod);
92
        }
93

    
94
        void check(Class theClass, int code) throws DynMethodException {
95
            if (code != this.code) {
96
                throw new DynMethodIllegalCodeException(dynMethod.getName(),
97
                    this.code, code);
98
            }
99
            if (theClass != null) {
100
                if (this.theClass == null) {
101
                    throw new IllegalDynMethodInvocationException(
102
                        dynMethod.getName(), theClass);
103
                }
104
                if (!this.theClass.isAssignableFrom(theClass)) {
105
                    throw new IllegalDynMethodInvocationException(
106
                        dynMethod.getName(), theClass);
107
                }
108
            }
109
        }
110

    
111
        void check(DynClass dynClass, int code) throws DynMethodException {
112
            if (code != this.code) {
113
                throw new DynMethodIllegalCodeException(dynMethod.getName(),
114
                    this.code, code);
115
            }
116
            if (dynClass != null) {
117
                if (this.dynClass == null) {
118
                    throw new IllegalDynMethodInvocationException(
119
                        dynMethod.getName(), dynClass);
120
                }
121
                if (dynClass != this.dynClass
122
                    || !dynClass.getName().equalsIgnoreCase(
123
                        this.dynClass.getName())) {
124
                    throw new IllegalDynMethodInvocationException(
125
                        dynMethod.getName(), dynClass);
126
                }
127
            }
128
        }
129
    }
130

    
131
    private class ClassesNamespaces {
132

    
133
        private Map defaultNamespace;
134
        private Map namespaces;
135

    
136
        ClassesNamespaces() {
137
            this.namespaces = new HashMap();
138
            this.defaultNamespace = new HashMap();
139
        }
140

    
141
        public Map addNamespace(String name) {
142
            Map namespace = new HashMap();
143
            this.namespaces.put(name.toLowerCase(), namespace);
144
            return namespace;
145
        }
146

    
147
        public Map getNamespace(String name) {
148
            return (Map) this.namespaces.get(name.toLowerCase());
149
        }
150

    
151
//        public void clear() {
152
//            this.defaultNamespace.clear();
153
//            this.namespaces.clear();
154
//        }
155

    
156
        public boolean containsClass(String name) {
157
            name = name.toLowerCase();
158
            if (this.defaultNamespace.containsKey(name)) {
159
                return true;
160
            }
161

    
162
            Iterator it = this.namespaces.values().iterator();
163
            while (it.hasNext()) {
164
                Map names = (Map) it.next();
165
                if (names.containsKey(name)) {
166
                    return true;
167
                }
168
            }
169
            return false;
170
        }
171

    
172
        public boolean containsClass(String namespace, String name) {
173
            name = name.toLowerCase();
174
            if (namespace == null) {
175
                return this.defaultNamespace.containsKey(name);
176
            }
177
            Map space = this.getNamespace(namespace);
178
            if (space == null) {
179
                return false;
180
            }
181
            return space.containsKey(name);
182
        }
183

    
184
//        public boolean containsClass(DynClass dynClass) {
185
//            if (this.defaultNamespace.containsValue(dynClass)) {
186
//                return true;
187
//            }
188
//
189
//            Iterator it = this.namespaces.values().iterator();
190
//            while (it.hasNext()) {
191
//                Map names = (Map) it.next();
192
//                if (names.containsValue(dynClass)) {
193
//                    return true;
194
//                }
195
//            }
196
//            return false;
197
//        }
198

    
199
        public DynClass get(String name, String namespace) {
200
            if (namespace == null) {
201
                return (DynClass) this.defaultNamespace.get(name.toLowerCase());
202
            }
203
            Map space = this.getNamespace(namespace);
204
            if (space == null) {
205
                return null;
206
            }
207
            DynClassName className = new DefaultDynClassName(name);
208
            if (className.getNamespace()==null){
209
                return (DynClass) space.get(name.toLowerCase());
210
            }
211
            if (!namespace.equalsIgnoreCase(className.getNamespace())){
212
                    return null;
213
            }
214
            return (DynClass) space.get(className.getName().toLowerCase());
215
        }
216

    
217
        public Set keySet() {
218
            Set keyset = new HashSet();
219
            Iterator it = this.iterator();
220
            while (it.hasNext()) {
221
                DynClass dynClass = (DynClass) it.next();
222
                keyset.add(dynClass.getFullName());
223
            }
224
            return keyset;
225
        }
226

    
227
        public Iterator iterator() {
228
            final class MyIterator implements Iterator {
229

    
230
                Iterator current;
231
                Iterator others;
232

    
233
                MyIterator(Iterator main, Iterator others) {
234
                    this.current = main;
235
                    this.others = others;
236
                }
237

    
238
                public boolean hasNext() {
239
                    if (this.current.hasNext()) {
240
                        return true;
241
                    }
242
                    while (this.others.hasNext()) { 
243
                        Object obj = others.next();
244
                        this.current = (Iterator) ((HashMap) obj).values().iterator();
245
                        if (this.current.hasNext()) {
246
                            return true;
247
                        }
248
                    }
249
                    return false;
250
                }
251

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

    
266
                public void remove() {
267
                    throw new UnsupportedOperationException();
268
                }
269
            }
270

    
271
            return new MyIterator(this.defaultNamespace.values().iterator(),
272
                this.namespaces.values().iterator());
273
        }
274

    
275
        public Object add(DynStruct dynClass) {
276
            String name = dynClass.getName().toLowerCase();
277
            Map namespace;
278
            if (dynClass.getNamespace() != null) {
279
                namespace = (Map) this.getNamespace(dynClass.getNamespace());
280
                if (namespace == null) {
281
                    namespace = this.addNamespace(dynClass.getNamespace());
282
                }
283
            } else {
284
                namespace = this.defaultNamespace;
285
            }
286
            if (namespace.containsKey(name)) {
287
                throw new DuplicateDynClassException(dynClass);
288
            }
289
            return namespace.put(name, dynClass);
290
        }
291

    
292
        public void remove(DynStruct dynClass) {
293
            String name = dynClass.getName().toLowerCase();
294
            Map namespace;
295
            if (dynClass.getNamespace() != null) {
296
                namespace = (Map) this.getNamespace(dynClass.getNamespace());
297
                if (namespace == null) {
298
                    namespace = this.addNamespace(dynClass.getNamespace());
299
                }
300
            } else {
301
                namespace = this.defaultNamespace;
302
            }
303
            if (namespace.containsKey(name)) {
304
                namespace.remove(name);
305
            }
306
        }
307

    
308
        public int size() {
309
            int count = this.defaultNamespace.size();
310

    
311
            Iterator it = this.namespaces.values().iterator();
312
            while (it.hasNext()) {
313
                Map names = (Map) it.next();
314
                count += names.size();
315
            }
316
            return count;
317
        }
318

    
319
    }
320

    
321
    private Map anonymousClasses;
322
    private ClassesNamespaces classes;
323
    private Map methodsMap;
324
    private MethodInfo[] methods;
325

    
326
    public static DefaultDynObjectManager getManager() {
327
        if (manager == null) {
328
            manager = new DefaultDynObjectManager();
329
        }
330
        return manager;
331
    }
332

    
333
    static String getKey(Class theClass, DynClass dynClass, DynMethod dynMethod) {
334
        return DefaultDynObjectManager.getKey(theClass, dynClass,
335
            dynMethod.getName());
336
    }
337

    
338
    static String getKey(Class theClass, DynClass dynClass, String methodName) {
339
        if (dynClass == null) {
340
            return theClass.getName() + ":" + methodName;
341
        } else {
342
            return dynClass.getName() + ":" + methodName;
343
        }
344
    }
345

    
346
    public DefaultDynObjectManager() {
347
        this.classes = new ClassesNamespaces();
348
        this.anonymousClasses = new HashMap();
349
        this.methodsMap = new HashMap();
350
        this.methods = null;
351
    }
352

    
353
    public DynClass createDynClass(String name, String description) {
354
        return new DefaultDynClass(this, name, description);
355
    }
356

    
357
    public DynClass createDynClass(String namespace, String name,
358
        String description) {
359
        return new DefaultDynClass(this, namespace, name, description);
360
    }
361

    
362
    public void add(DynClass dynClass) {
363
        try {
364
            ((DefaultDynClass) dynClass).check();
365
        } catch (Exception ex) {
366
            throw new DynObjectRuntimeException(ex);
367
        }
368
        this.classes.add(dynClass);
369
        LOG.trace("Add DynClass definition {}.",
370
            new Object[] { dynClass.getFullName() });
371

    
372
    }
373

    
374
    public DynClass add(String name, String description) {
375
        DynClass dynClass =
376
            (DynClass) this.classes.get(name.toLowerCase(), null);
377
        if (dynClass == null) {
378
            dynClass = this.createDynClass(name, description);
379
            this.add(dynClass);
380
        }
381
        return dynClass;
382
    }
383

    
384
    public DynClass add(String name) {
385
        return this.add(name, null);
386
    }
387

    
388
    public void remove(DynStruct dynClass) {
389
        this.classes.remove(dynClass);
390
    }
391

    
392
    // public static String getFullName(String namespace, String name) {
393
    // if( namespace == null ) {
394
    // return name;
395
    // }
396
    // return namespace + ":" + name;
397
    // }
398
    // public static String[] splitFullName(String fullname) {
399
    // String[] name = new String[] { null, fullname };
400
    // int x=fullname.indexOf(':');
401
    // if( x>-1 ) {
402
    // name[0] = fullname.substring(0, x);
403
    // name[1] = fullname.substring(x+1);
404
    // }
405
    // return name;
406
    //
407
    // }
408

    
409
    public DynClass get(String theName) {
410
        DynClassName name = createDynClassName(theName);
411
        return this.get(name.getNamespace(), name.getName());
412
    }
413

    
414
    public DynClass get(String namespace, String name) {
415
        return (DynClass) this.classes.get(name, namespace);
416
    }
417

    
418
    public DynClass get(DynClass[] superClasses) {
419
        StringBuffer name = new StringBuffer();
420
        for (int i = 0; i < superClasses.length; i++) {
421
            name.append(superClasses[i].getName()).append("+");
422
        }
423
        DefaultDynClass dynClass =
424
            (DefaultDynClass) this.anonymousClasses.get(name.toString());
425
        if (dynClass == null) {
426
            dynClass =
427
                new DefaultDynClass(this, name.toString(), null, superClasses);
428
            dynClass.setAnonymous(true);
429
        }
430
        return dynClass;
431
    }
432

    
433
    public int getCount() {
434
        return this.classes.size();
435
    }
436

    
437
    public List getNames() {
438
        String[] names = (String[]) this.classes.keySet().toArray();
439
        Arrays.sort(names);
440
        return Collections.unmodifiableList(Arrays.asList(names));
441
    }
442

    
443
    public boolean has(String name) {
444
        return this.classes.containsClass(name);
445
    }
446

    
447
    public boolean has(String namespace, String name) {
448
        return this.classes.containsClass(namespace, name);
449
    }
450

    
451
    public Iterator iterator() {
452
        return this.classes.iterator();
453
    }
454

    
455
    public DynObject createDynObject(String dynClassName) {
456
        DynClassName name = createDynClassName(dynClassName);
457
        return this.createDynObject(name.getName(), name.getNamespace());
458
    }
459

    
460
    public DynObject createDynObject(String dynClassName, String namespace) {
461

    
462
        DynClass dynClass =
463
            (DynClass) this.classes.get(dynClassName, namespace);
464
        if (dynClass == null) {
465
            throw new IllegalArgumentException("Can't locate class '"
466
                + createDynClassName(namespace, dynClassName).getFullName()
467
                + "'.");
468
        }
469
        return this.createDynObject(dynClass);
470
    }
471

    
472
    public DynObject createDynObject(DynStruct dynClass) {
473
        return new DefaultDynObject(dynClass);
474
    }
475

    
476
    public void consolide() {
477
        Iterator it = this.classes.iterator();
478
        while (it.hasNext()) {
479
            DefaultDynClass dc = (DefaultDynClass) it.next();
480
            dc.consolide();
481
        }
482
        it = this.anonymousClasses.values().iterator();
483
        while (it.hasNext()) {
484
            DefaultDynClass dc = (DefaultDynClass) it.next();
485
            dc.consolide();
486
        }
487
    }
488

    
489
    public int registerDynMethod(DynClass dynClass, DynMethod dynMethod) {
490
        ((DefaultDynClass) dynClass).addMethod(dynMethod);
491
        return registerDynMethod(null, dynClass, dynMethod);
492
    }
493

    
494
    public int registerDynMethod(Class theClass, DynMethod dynMethod) {
495
        return registerDynMethod(theClass, null, dynMethod);
496
    }
497

    
498
    int registerDynMethod(Class theClass, DynClass dynClass, DynMethod dynMethod) {
499
        MethodInfo info = new MethodInfo(theClass, dynClass, dynMethod, 0);
500
        MethodInfo oldInfo = (MethodInfo) methodsMap.get(info.getKey());
501
        if (oldInfo != null) {
502
            // Update the method info
503
            oldInfo.dynClass = dynClass;
504
            oldInfo.dynMethod = dynMethod;
505
            return oldInfo.code;
506
        }
507
        if (methods == null) {
508
            methods = new MethodInfo[1];
509
            info.code = 0;
510
        } else {
511
            MethodInfo[] temp1 = new MethodInfo[methods.length + 1];
512
            System.arraycopy(methods, 0, temp1, 0, methods.length);
513
            info.code = temp1.length - 1;
514
            methods = temp1;
515
        }
516
        methods[info.code] = info;
517
        methodsMap.put(info.getKey(), info);
518

    
519
        return info.code;
520
    }
521

    
522
    public Object invokeDynMethod(Object self, int code, DynObject context)
523
        throws DynMethodException {
524

    
525
        try {
526
            /*
527
             * Intentamos ejecutar la operacion, y si peta ya haremos las
528
             * comprobaciones oportunas para lanzar la excepcion que toque.
529
             * 
530
             * Asi evitamos codigo de comprobacion para los casos que valla bien
531
             * que deberian ser la mayoria.
532
             */
533
            return methods[code].dynMethod.invoke(self, context);
534
        } catch (RuntimeException e) {
535
            getDynMethod(self, code);
536
            throw e;
537
        } catch (DynMethodException e) {
538
            getDynMethod(self, code);
539
            throw e;
540
        }
541

    
542
    }
543

    
544
    public int getDynMethodCode(DynClass dynClass, String methodName)
545
        throws DynMethodException {
546
        String key = DefaultDynObjectManager.getKey(null, dynClass, methodName);
547
        MethodInfo info = (MethodInfo) methodsMap.get(key);
548
        if (info == null) {
549
            throw new IllegalDynMethodException(methodName, dynClass);
550
        }
551
        info.check(dynClass, info.code);
552
        return info.code;
553
    }
554

    
555
    public int getDynMethodCode(Class theClass, String methodName)
556
        throws DynMethodException {
557
        String key = DefaultDynObjectManager.getKey(theClass, null, methodName);
558
        MethodInfo info = (MethodInfo) methodsMap.get(key);
559
        if (info == null) {
560
            throw new IllegalDynMethodException(methodName, theClass);
561
        }
562
        info.check(theClass, info.code);
563
        return info.code;
564
    }
565

    
566
    public DynMethod getDynMethod(int code) throws DynMethodException {
567
        if (code >= methods.length) {
568
            throw new DynMethodNotSupportedException(code, "{null}");
569
        }
570
        MethodInfo info = methods[code];
571
        info.check((Class) null, code);
572
        return info.dynMethod;
573
    }
574

    
575
    public DynMethod getDynMethod(Object obj, int code)
576
        throws DynMethodException {
577
        return getDynMethod(obj.getClass(), code);
578
    }
579

    
580
    public DynMethod getDynMethod(Class theClass, int code)
581
        throws DynMethodException {
582
        if (code >= methods.length) {
583
            throw new DynMethodNotSupportedException(code, theClass.getName());
584
        }
585
        MethodInfo info = methods[code];
586
        info.check(theClass, code);
587
        return info.dynMethod;
588
    }
589

    
590
    public DynMethod getDynMethod(DynClass dynClass, int code)
591
        throws DynMethodException {
592
        if (code >= methods.length) {
593
            throw new DynMethodNotSupportedException(code, dynClass.getName());
594
        }
595
        MethodInfo info = methods[code];
596
        info.check(dynClass, code);
597
        return info.dynMethod;
598
    }
599

    
600
    public DynMethod getDynMethod(DynObject dynObject, int code)
601
        throws DynMethodException {
602
        return getDynMethod(dynObject.getDynClass(), code);
603
    }
604

    
605
    public void validate(DynObject object) {
606
        // TODO
607
        return;
608
    }
609

    
610
    public Class getDefaultClassOfType(int type) {
611
        return ToolsLocator.getDataTypesManager().getDefaultClass(type);
612
    }
613

    
614
    public Map importDynClassDefinitions(InputStream resource,
615
        ClassLoader loader) throws XmlPullParserException, IOException {
616
        return new DynClassImportHelper().importDefinitions(resource, loader,
617
            null);
618
    }
619

    
620
    public Map importDynClassDefinitions(XmlPullParser parser,
621
        ClassLoader loader, String defaultNamespace)
622
        throws XmlPullParserException, IOException {
623
        return new DynClassImportHelper().importDefinitions(parser, loader,
624
            defaultNamespace);
625
    }
626

    
627
    public Map importDynClassDefinitions(InputStream resource,
628
        ClassLoader loader, String defaultNamespace)
629
        throws XmlPullParserException, IOException {
630
        return new DynClassImportHelper().importDefinitions(resource, loader,
631
            defaultNamespace);
632
    }
633

    
634
    public DynObjectPagingHelper createDynObjectPagingHelper(DynObjectSet set)
635
        throws BaseException {
636
        return new DefaultDynObjectPagingHelper(set); 
637
    }
638

    
639
    public DynObjectPagingHelper createDynObjectPagingHelper(DynObjectSet set,
640
        int pageSize) throws BaseException {
641
        return new DefaultDynObjectPagingHelper(set, pageSize);
642
    }
643

    
644
    public DynClassName createDynClassName(String namespace, String name) {
645
        return new DefaultDynClassName(namespace, name);
646
    }
647

    
648
    public DynClassName createDynClassName(String name) {
649
        return new DefaultDynClassName(name);
650
    }
651

    
652
    public Iterator iterator(String nameSpace) {
653
        return iterator(nameSpace, false);
654
    }
655

    
656
    private Iterator iterator(String nameSpace, boolean exactMatchingRequired) {
657

    
658
        List list = new ArrayList();
659
        Iterator it = this.classes.iterator();
660

    
661
        if (nameSpace == null) {
662
            nameSpace = "";
663
        }
664

    
665
        while( it.hasNext() ) {
666
            
667
            Object obj = it.next();
668
            DynStruct dynStruct = (DynStruct) obj;
669
            String dynNameSpace = dynStruct.getNamespace();
670
            if ((dynNameSpace == null) || (dynNameSpace.equals(""))) {
671
                dynNameSpace = null;
672
            } else {
673
                dynNameSpace = dynNameSpace.toLowerCase();
674
            }
675
            nameSpace = nameSpace.toLowerCase();
676
            if (exactMatchingRequired) {
677
                if (nameSpace.equalsIgnoreCase(dynNameSpace)) {
678
                    list.add(dynStruct);
679
                }
680
            } else {
681
                if ((dynNameSpace != null)
682
                    && (nameSpace.indexOf(dynNameSpace) > -1)) {
683
                    list.add(dynStruct);
684
                }
685
            }
686
        }
687
        return list.iterator();
688
    }
689

    
690
    public String getAttributeValue(Object obj, String name) {
691
            if( obj instanceof DefaultDynField ) {
692
                    if( "label".equalsIgnoreCase(name) ) {
693
                            return ((DefaultDynField)obj).getLabel();
694
                    }
695
            }
696
            return null;
697
    }
698

    
699
    public void setAttributeValue(Object obj, String name, Object value) {
700
            if( obj instanceof DefaultDynField ) {
701
                    if( "label".equalsIgnoreCase(name) ) {
702
                            ((DefaultDynField)obj).setLabel((String) value);
703
                    }
704
            }
705
    }
706
}