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

History | View | Annotate | Download (15.1 KB)

1
package org.gvsig.tools.dynobject.impl;
2

    
3
import java.io.IOException;
4
import java.io.InputStream;
5
import java.util.Arrays;
6
import java.util.Collections;
7
import java.util.HashMap;
8
import java.util.HashSet;
9
import java.util.Iterator;
10
import java.util.List;
11
import java.util.Map;
12
import java.util.Set;
13

    
14
import org.gvsig.tools.ToolsLocator;
15
import org.gvsig.tools.dynobject.DynClass;
16
import org.gvsig.tools.dynobject.DynMethod;
17
import org.gvsig.tools.dynobject.DynObject;
18
import org.gvsig.tools.dynobject.DynObjectManager;
19
import org.gvsig.tools.dynobject.DynStruct;
20
import org.gvsig.tools.dynobject.exception.DuplicateDynClassException;
21
import org.gvsig.tools.dynobject.exception.DynMethodException;
22
import org.gvsig.tools.dynobject.exception.DynMethodIllegalCodeException;
23
import org.gvsig.tools.dynobject.exception.DynMethodNotSupportedException;
24
import org.gvsig.tools.dynobject.exception.IllegalDynMethodException;
25
import org.gvsig.tools.dynobject.exception.IllegalDynMethodInvocationException;
26
import org.xmlpull.v1.XmlPullParser;
27
import org.xmlpull.v1.XmlPullParserException;
28

    
29
public class DefaultDynObjectManager implements DynObjectManager {
30

    
31
        private static DefaultDynObjectManager manager = null;
32

    
33
        private class MethodInfo {
34
                int code;
35
                DynClass dynClass;
36
                DynMethod dynMethod;
37
                Class theClass;
38

    
39
                MethodInfo(Class theClass, DynClass dynClass, DynMethod dynMethod, int code) {
40
                        this.code = code;
41
                        this.dynClass = dynClass;
42
                        this.dynMethod = dynMethod;
43
                        this.theClass = theClass;
44
                }
45

    
46
                String getKey() {
47
                        return DefaultDynObjectManager.getKey(theClass, dynClass, dynMethod);
48
                }
49

    
50
                void check(Class theClass, int code) throws DynMethodException {
51
                        if( code != this.code) {
52
                                throw new DynMethodIllegalCodeException(dynMethod.getName(),this.code, code);
53
                        }
54
                        if( theClass != null ) {
55
                                if( this.theClass == null ) {
56
                                        throw new IllegalDynMethodInvocationException(dynMethod.getName(), theClass);
57
                                }
58
                                if (!this.theClass.isAssignableFrom(theClass)) {
59
                                        throw new IllegalDynMethodInvocationException(dynMethod.getName(),theClass);
60
                                }
61
                        }
62
                }
63

    
64
                void check(DynClass dynClass, int code) throws DynMethodException  {
65
                        if( code != this.code) {
66
                                throw new DynMethodIllegalCodeException(dynMethod.getName(),this.code, code);
67
                        }
68
                        if( dynClass != null ) {
69
                                if( this.dynClass == null ) {
70
                                        throw new IllegalDynMethodInvocationException(dynMethod.getName(), dynClass);
71
                                }
72
                                if( dynClass != this.dynClass || !dynClass.getName().equalsIgnoreCase(this.dynClass.getName()) ) {
73
                                        throw new IllegalDynMethodInvocationException(dynMethod.getName(), dynClass);
74
                                }
75
                        }
76
                }
77
        }
78

    
79
        private class ClassesNamespaces  {
80
                private Map defaultNamespace;
81
                private Map namespaces;
82
                
83
                ClassesNamespaces() {
84
                        this.namespaces = new HashMap();
85
                        this.defaultNamespace = new HashMap();
86
                }
87
                
88
                public Map addNamespace(String name) {
89
                        Map namespace = new HashMap();
90
                        this.namespaces.put(name.toLowerCase(), namespace);
91
                        return namespace;
92
                }
93
                
94
                public Map getNamespace(String name) {
95
                        return (Map) this.namespaces.get(name.toLowerCase());
96
                }
97

    
98
                public void clear() {
99
                        this.defaultNamespace.clear();
100
                        this.namespaces.clear();
101
                }
102

    
103
                public boolean containsClass(String name) {
104
                        name = name.toLowerCase();
105
                        if( this.defaultNamespace.containsKey(name)) {
106
                                return true;
107
                        }
108
                        
109
                        Iterator it = this.namespaces.values().iterator();
110
                        while( it.hasNext() ) {
111
                                Map names = (Map)it.next();
112
                                if( names.containsKey(name)) {
113
                                        return true;
114
                                }
115
                        }
116
                        return false;
117
                }
118

    
119
                public boolean containsClass(String namespace, String name) {
120
                        name = name.toLowerCase();
121
                        if( namespace == null ) {
122
                                return this.defaultNamespace.containsKey(name);
123
                        }
124
                        Map space = this.getNamespace(namespace);
125
                        if( space == null ) {
126
                                return false;
127
                        }
128
                        return space.containsKey(name);
129
                }
130

    
131
                public boolean containsClass(DynClass dynClass) {
132
                        if( this.defaultNamespace.containsValue(dynClass)) {
133
                                return true;
134
                        }
135
                        
136
                        Iterator it = this.namespaces.values().iterator();
137
                        while( it.hasNext() ) {
138
                                Map names = (Map)it.next();
139
                                if( names.containsValue(dynClass)) {
140
                                        return true;
141
                                }
142
                        }
143
                        return false;
144
                }
145

    
146
                public DynClass get(String name, String namespace) {
147
                        if( namespace == null ) {
148
                                return (DynClass) this.defaultNamespace.get(name.toLowerCase());
149
                        }
150
                        Map space = this.getNamespace(namespace);
151
                        if( space == null ) {
152
                                return null;
153
                        }
154
                        return (DynClass) space.get(name.toLowerCase());
155
                }
156
                
157
                public Set keySet() {
158
                        Set keyset = new HashSet();
159
                        Iterator it = this.iterator();
160
                        while( it.hasNext() ) {
161
                                DynClass dynClass = (DynClass) it.next();
162
                                keyset.add( dynClass.getFullName()) ;
163
                        }
164
                        return keyset;
165
                }
166

    
167
                public Iterator iterator() {
168
                        final class MyIterator implements Iterator {
169
                                Iterator current;
170
                                Iterator others;
171
                                MyIterator(Iterator main, Iterator others) {
172
                                        this.current = main;
173
                                        this.others = others;
174
                                }
175
                                public boolean hasNext() {
176
                                        if( this.current.hasNext() ) {
177
                                                return true;
178
                                        }
179
                                        while( this.others.hasNext() )  {
180
                                                this.current = (Iterator) others.next();
181
                                                if( this.current.hasNext() ) {
182
                                                        return true;
183
                                                }
184
                                        }
185
                                        return false;
186
                                }
187
                                
188
                                public Object next() {
189
                                        if( this.current.hasNext() ) {
190
                                                return this.current.next();
191
                                        }
192
                                        while( this.others.hasNext() )  {
193
                                                this.current = (Iterator) others.next();
194
                                                if( this.current.hasNext() ) {
195
                                                        return this.current.next();
196
                                                }
197
                                        }
198
                                        return null;
199
                                }
200
                                
201
                                public void remove() {
202
                                        throw new UnsupportedOperationException();
203
                                }
204
                        }
205
                        
206
                        return new MyIterator(this.defaultNamespace.values().iterator(), this.namespaces.values().iterator());
207
                }
208
                
209
                public Object add(DynStruct dynClass) {
210
                        String name = dynClass.getName().toLowerCase();
211
                        Map namespace;
212
                        if( dynClass.getNamespace() != null ) {
213
                                namespace = (Map) this.getNamespace(dynClass.getNamespace());
214
                                if( namespace == null ) {
215
                                        namespace = this.addNamespace(dynClass.getNamespace());
216
                                }
217
                        } else {
218
                                namespace = this.defaultNamespace;
219
                        }
220
                        if( namespace.containsKey(name) ) {
221
                                throw new DuplicateDynClassException(dynClass);
222
                        }
223
                        return namespace.put(name, dynClass);
224
                }
225
                
226
                public void remove(DynStruct dynClass) {
227
                        String name = dynClass.getName().toLowerCase();
228
                        Map namespace;
229
                        if( dynClass.getNamespace() != null ) {
230
                                namespace = (Map) this.getNamespace(dynClass.getNamespace());
231
                                if( namespace == null ) {
232
                                        namespace = this.addNamespace(dynClass.getNamespace());
233
                                }
234
                        } else {
235
                                namespace = this.defaultNamespace;
236
                        }
237
                        if( namespace.containsKey(name) ) {
238
                                namespace.remove(name);
239
                        }
240
                }
241
                
242
                public int size() {
243
                        int count = this.defaultNamespace.size();
244
                        
245
                        Iterator it = this.namespaces.values().iterator();
246
                        while( it.hasNext() ) {
247
                                Map names = (Map)it.next();
248
                                count += names.size();
249
                        }
250
                        return count;
251
                }
252

    
253
                
254
        }
255
        
256
        private Map anonymousClasses;
257
        private ClassesNamespaces classes;
258
        private Map methodsMap;
259
        private MethodInfo[] methods;
260

    
261
        public static DefaultDynObjectManager getManager() {
262
                if (manager == null) {
263
                        manager = new DefaultDynObjectManager();
264
                }
265
                return manager;
266
        }
267

    
268
    static String getKey(Class theClass, DynClass dynClass, DynMethod dynMethod) {
269
            return DefaultDynObjectManager.getKey(theClass, dynClass, dynMethod.getName());
270
    }
271

    
272
    static String getKey(Class theClass, DynClass dynClass, String methodName) {
273
                if( dynClass == null ) {
274
                        return theClass.getName() + ":" + methodName;
275
                } else {
276
                        return dynClass.getName() + ":" + methodName;
277
                }
278
    }
279

    
280

    
281
        public DefaultDynObjectManager() {
282
                this.classes = new ClassesNamespaces();
283
                this.anonymousClasses = new HashMap();
284
                this.methodsMap = new HashMap();
285
                this.methods = null;
286
        }
287

    
288
        public DynClass createDynClass(String name, String description) {
289
                return new DefaultDynClass(this, name, description);
290
        }
291

    
292
        public DynClass createDynClass(String namespace, String name, String description) {
293
                return new DefaultDynClass(this, namespace, name, description);
294
        }
295

    
296
        public void add(DynClass dynClass) {
297
                this.classes.add( dynClass);
298
        }
299

    
300
        public DynClass add(String name, String description) {
301
                DynClass dynClass = (DynClass) this.classes.get(name.toLowerCase(), null);
302
                if (dynClass == null) {
303
                        dynClass = this.createDynClass(name, description);
304
                        this.add(dynClass);
305
                }
306
                return dynClass;
307
        }
308

    
309
        public DynClass add(String name) {
310
                return this.add(name, null);
311
        }
312

    
313
        public void remove(DynStruct dynClass)  {
314
                this.classes.remove(dynClass);
315
        }
316

    
317
        public static String  getFullName(String namespace, String name) {
318
            if( namespace == null ) {
319
                    return name;
320
            }
321
            return namespace + ":" + name;
322
    }
323

    
324
        public static String[] splitFullName(String fullname) {
325
                String[] name = new String[] { null, fullname };
326
                int x=fullname.indexOf(':');
327
                if( x>-1 ) {
328
                        name[0] = fullname.substring(0, x);
329
                        name[1] = fullname.substring(x+1);
330
                }
331
                return name;
332
                
333
        }
334
        
335
        public DynClass get(String theName) {
336
                String[] name = splitFullName(theName);
337
                return this.get(name[0],name[1]);
338
        }
339

    
340
        public DynClass get(String namespace, String name ) {
341
                return (DynClass) this.classes.get(name,namespace);
342
        }
343

    
344
        public DynClass get(DynClass[] superClasses) {
345
                StringBuffer name = new StringBuffer();
346
                for( int i=0; i<superClasses.length; i++) {
347
                        name.append(superClasses[i].getName()).append("+");
348
                }
349
                DefaultDynClass dynClass = (DefaultDynClass) this.anonymousClasses.get(name.toString());
350
                if( dynClass == null ) {
351
                        dynClass = new DefaultDynClass(this, name.toString(), null, superClasses);
352
                        dynClass.setAnonymous(true);
353
                }
354
                return dynClass;
355
        }
356

    
357
        public int getCount() {
358
                return this.classes.size();
359
        }
360

    
361
        public List getNames() {
362
                String[] names = (String[]) this.classes.keySet().toArray();
363
                Arrays.sort(names);
364
                return Collections.unmodifiableList(Arrays.asList(names));
365
        }
366

    
367
        public boolean has(String name) {
368
                return this.classes.containsClass(name);
369
        }
370

    
371
        public boolean has(String namespace ,String name) {
372
                return this.classes.containsClass(namespace, name);
373
        }
374

    
375
        public Iterator interator() {
376
                return this.classes.iterator();
377
        }
378
        public DynObject createDynObject(String dynClassName) {
379
                String[] name = splitFullName(dynClassName); 
380
                return this.createDynObject(name[1], name[0]);
381
        }
382

    
383
        public DynObject createDynObject(String dynClassName, String namespace) {
384
                
385
                DynClass dynClass = (DynClass) this.classes.get(dynClassName, namespace);
386
                if (dynClass == null) {
387
                        throw new IllegalArgumentException(dynClassName);
388
                }
389
                return this.createDynObject(dynClass);
390
        }
391

    
392
        public DynObject createDynObject(DynStruct dynClass) {
393
                return new DefaultDynObject(dynClass);
394
        }
395

    
396
        public void consolide() {
397
                Iterator it = this.classes.iterator();
398
                while( it.hasNext() ) {
399
                        DefaultDynClass dc = (DefaultDynClass) it.next();
400
                        dc.consolide();
401
                }
402
                it = this.anonymousClasses.values().iterator();
403
                while( it.hasNext() ) {
404
                        DefaultDynClass dc = (DefaultDynClass) it.next();
405
                        dc.consolide();
406
                }
407
        }
408

    
409

    
410
        public int registerDynMethod(DynClass dynClass, DynMethod dynMethod) {
411
                ((DefaultDynClass)dynClass).addMethod(dynMethod);
412
                return registerDynMethod(null, dynClass, dynMethod);
413
        }
414

    
415
        public int registerDynMethod(Class theClass, DynMethod dynMethod) {
416
                return registerDynMethod(theClass, null, dynMethod);
417
        }
418

    
419
        int registerDynMethod(Class theClass, DynClass dynClass, DynMethod dynMethod) {
420
                MethodInfo info = new MethodInfo(theClass, dynClass, dynMethod, 0);
421
                MethodInfo oldInfo = (MethodInfo) methodsMap.get(info.getKey());
422
                if (oldInfo != null) {
423
                        // Update the method info
424
                        oldInfo.dynClass = dynClass;
425
                        oldInfo.dynMethod = dynMethod;
426
                        return oldInfo.code;
427
                }
428
                if (methods == null) {
429
                        methods = new MethodInfo[1];
430
                        info.code = 0;
431
                } else {
432
                        MethodInfo[] temp1 = new MethodInfo[methods.length + 1];
433
                        System.arraycopy(methods, 0, temp1, 0, methods.length);
434
                        info.code = temp1.length - 1;
435
                        methods = temp1;
436
                }
437
                methods[info.code] = info;
438
                methodsMap.put(info.getKey(), info);
439

    
440
                return info.code;
441
        }
442

    
443
        public Object invokeDynMethod(Object self, int code, DynObject context) throws DynMethodException{
444

    
445
                try {
446
                        /*
447
                         * Intentamos ejecutar la operacion, y si peta ya haremos las
448
                         * comprobaciones oportunas para lanzar la excepcion que toque.
449
                         *
450
                         * Asi evitamos codigo de comprobacion para los casos que valla bien
451
                         * que deberian ser la mayoria.
452
                         */
453
                        return methods[code].dynMethod.invoke(self, context);
454
                } catch (RuntimeException e) {
455
                        getDynMethod(self, code);
456
                        throw e;
457
                } catch (DynMethodException e) {
458
                        getDynMethod(self, code);
459
                        throw e;
460
                }
461

    
462
        }
463

    
464
        public int getDynMethodCode(DynClass dynClass, String methodName) throws DynMethodException  {
465
                String key = DefaultDynObjectManager.getKey(null, dynClass, methodName);
466
                MethodInfo info = (MethodInfo) methodsMap.get(key);
467
                if( info == null ) {
468
                        throw new IllegalDynMethodException(methodName, dynClass);
469
                }
470
                info.check(dynClass, info.code);
471
                return info.code;
472
        }
473

    
474
        public int getDynMethodCode(Class theClass, String methodName) throws DynMethodException {
475
                String key = DefaultDynObjectManager.getKey(theClass, null, methodName);
476
                MethodInfo info = (MethodInfo) methodsMap.get(key);
477
                if( info == null ) {
478
                        throw new IllegalDynMethodException(methodName, theClass);
479
                }
480
                info.check(theClass, info.code);
481
                return info.code;
482
        }
483

    
484
        public DynMethod getDynMethod(int code) throws DynMethodException {
485
                if (code >= methods.length) {
486
                        throw new DynMethodNotSupportedException(code, "{null}");
487
                }
488
                MethodInfo info = methods[code];
489
                info.check((Class)null, code);
490
                return info.dynMethod;
491
        }
492

    
493
        public DynMethod getDynMethod(Object obj, int code)
494
                        throws DynMethodException {
495
                return getDynMethod(obj.getClass(), code);
496
        }
497

    
498
        public DynMethod getDynMethod(Class theClass, int code)
499
                        throws DynMethodException {
500
                if (code >= methods.length) {
501
                        throw new DynMethodNotSupportedException(code, theClass.getName());
502
                }
503
                MethodInfo info = methods[code];
504
                info.check(theClass, code);
505
                return info.dynMethod;
506
        }
507

    
508
        public DynMethod getDynMethod(DynClass dynClass, int code)
509
                        throws DynMethodException {
510
                if (code >= methods.length) {
511
                        throw new DynMethodNotSupportedException(code, dynClass.getName());
512
                }
513
                MethodInfo info = methods[code];
514
                info.check(dynClass, code);
515
                return info.dynMethod;
516
        }
517

    
518
        public DynMethod getDynMethod(DynObject dynObject, int code)
519
                        throws DynMethodException {
520
                return getDynMethod(dynObject.getDynClass(), code);
521
        }
522

    
523
        public void validate(DynObject object) {
524
                // TODO
525
                return;
526
        }
527
        
528
        public Class getDefaultClassOfType(int type) {
529
                return ToolsLocator.getDataTypesManager().getDefaultClass(type);
530
        }
531

    
532
        public Map importDynClassDefinitions(InputStream resource,
533
                        ClassLoader loader) throws XmlPullParserException, IOException {
534
                return new DynClassImportHelper().importDefinitions(resource, loader, null);
535
        }
536

    
537
        public Map importDynClassDefinitions(XmlPullParser parser,
538
                        ClassLoader loader, String defaultNamespace) throws XmlPullParserException, IOException {
539
                return new DynClassImportHelper().importDefinitions(parser, loader, defaultNamespace);
540
        }
541

    
542
        public Map importDynClassDefinitions(InputStream resource,
543
                        ClassLoader loader, String defaultNamespace)
544
                        throws XmlPullParserException, IOException {
545
                return new DynClassImportHelper().importDefinitions(resource, loader, defaultNamespace);
546
        }
547
        
548
}