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

History | View | Annotate | Download (14.2 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
                        return (DynClass) space.get(name.toLowerCase());
152
                }
153
                
154
                public Set keySet() {
155
                        Set keyset = new HashSet();
156
                        Iterator it = this.iterator();
157
                        while( it.hasNext() ) {
158
                                DynClass dynClass = (DynClass) it.next();
159
                                keyset.add( dynClass.getFullName()) ;
160
                        }
161
                        return keyset;
162
                }
163

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

    
250
                
251
        }
252
        
253
        private Map anonymousClasses;
254
        private ClassesNamespaces classes;
255
        private Map methodsMap;
256
        private MethodInfo[] methods;
257

    
258
        public static DefaultDynObjectManager getManager() {
259
                if (manager == null) {
260
                        manager = new DefaultDynObjectManager();
261
                }
262
                return manager;
263
        }
264

    
265
    static String getKey(Class theClass, DynClass dynClass, DynMethod dynMethod) {
266
            return DefaultDynObjectManager.getKey(theClass, dynClass, dynMethod.getName());
267
    }
268

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

    
277

    
278
        public DefaultDynObjectManager() {
279
                this.classes = new ClassesNamespaces();
280
                this.anonymousClasses = new HashMap();
281
                this.methodsMap = new HashMap();
282
                this.methods = null;
283
        }
284

    
285
        public DynClass createDynClass(String name, String description) {
286
                return new DefaultDynClass(this, name, description);
287
        }
288

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

    
293
        public void add(DynClass dynClass) {
294
                this.classes.add( dynClass);
295
        }
296

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

    
306
        public DynClass add(String name) {
307
                return this.add(name, null);
308
        }
309

    
310
        public void remove(DynStruct dynClass)  {
311
                this.classes.remove(dynClass);
312
        }
313
        
314
        public DynClass get(String name) {
315
                return this.get(name,null);
316
        }
317

    
318
        public DynClass get(String namespace, String name ) {
319
                return (DynClass) this.classes.get(name,namespace);
320
        }
321

    
322
        public DynClass get(DynClass[] superClasses) {
323
                StringBuffer name = new StringBuffer();
324
                for( int i=0; i<superClasses.length; i++) {
325
                        name.append(superClasses[i].getName()).append("+");
326
                }
327
                DefaultDynClass dynClass = (DefaultDynClass) this.anonymousClasses.get(name.toString());
328
                if( dynClass == null ) {
329
                        dynClass = new DefaultDynClass(this, name.toString(), null, superClasses);
330
                        dynClass.setAnonymous(true);
331
                }
332
                return dynClass;
333
        }
334

    
335
        public int getCount() {
336
                return this.classes.size();
337
        }
338

    
339
        public List getNames() {
340
                String[] names = (String[]) this.classes.keySet().toArray();
341
                Arrays.sort(names);
342
                return Collections.unmodifiableList(Arrays.asList(names));
343
        }
344

    
345
        public boolean has(String name) {
346
                return this.classes.containsClass(name);
347
        }
348

    
349
        public boolean has(String namespace ,String name) {
350
                return this.classes.containsClass(namespace, name);
351
        }
352

    
353
        public Iterator interator() {
354
                return this.classes.iterator();
355
        }
356
        public DynObject createDynObject(String dynClassName) {
357
                return this.createDynObject(dynClassName, null);
358
        }
359

    
360
        public DynObject createDynObject(String dynClassName, String namespace) {
361
                
362
                DynClass dynClass = (DynClass) this.classes.get(dynClassName, namespace);
363
                if (dynClass == null) {
364
                        throw new IllegalArgumentException(dynClassName);
365
                }
366
                return this.createDynObject(dynClass);
367
        }
368

    
369
        public DynObject createDynObject(DynClass dynClass) {
370
                return new DefaultDynObject(dynClass);
371
        }
372

    
373
        public void consolide() {
374
                Iterator it = this.classes.iterator();
375
                while( it.hasNext() ) {
376
                        DefaultDynClass dc = (DefaultDynClass) it.next();
377
                        dc.consolide();
378
                }
379
                it = this.anonymousClasses.values().iterator();
380
                while( it.hasNext() ) {
381
                        DefaultDynClass dc = (DefaultDynClass) it.next();
382
                        dc.consolide();
383
                }
384
        }
385

    
386

    
387
        public int registerDynMethod(DynClass dynClass, DynMethod dynMethod) {
388
                ((DefaultDynClass)dynClass).addMethod(dynMethod);
389
                return registerDynMethod(null, dynClass, dynMethod);
390
        }
391

    
392
        public int registerDynMethod(Class theClass, DynMethod dynMethod) {
393
                return registerDynMethod(theClass, null, dynMethod);
394
        }
395

    
396
        int registerDynMethod(Class theClass, DynClass dynClass, DynMethod dynMethod) {
397
                MethodInfo info = new MethodInfo(theClass, dynClass, dynMethod, 0);
398
                MethodInfo oldInfo = (MethodInfo) methodsMap.get(info.getKey());
399
                if (oldInfo != null) {
400
                        // Update the method info
401
                        oldInfo.dynClass = dynClass;
402
                        oldInfo.dynMethod = dynMethod;
403
                        return oldInfo.code;
404
                }
405
                if (methods == null) {
406
                        methods = new MethodInfo[1];
407
                        info.code = 0;
408
                } else {
409
                        MethodInfo[] temp1 = new MethodInfo[methods.length + 1];
410
                        System.arraycopy(methods, 0, temp1, 0, methods.length);
411
                        info.code = temp1.length - 1;
412
                        methods = temp1;
413
                }
414
                methods[info.code] = info;
415
                methodsMap.put(info.getKey(), info);
416

    
417
                return info.code;
418
        }
419

    
420
        public Object invokeDynMethod(Object self, int code, DynObject context) throws DynMethodException{
421

    
422
                try {
423
                        /*
424
                         * Intentamos ejecutar la operacion, y si peta ya haremos las
425
                         * comprobaciones oportunas para lanzar la excepcion que toque.
426
                         *
427
                         * Asi evitamos codigo de comprobacion para los casos que valla bien
428
                         * que deberian ser la mayoria.
429
                         */
430
                        return methods[code].dynMethod.invoke(self, context);
431
                } catch (RuntimeException e) {
432
                        getDynMethod(self, code);
433
                        throw e;
434
                } catch (DynMethodException e) {
435
                        getDynMethod(self, code);
436
                        throw e;
437
                }
438

    
439
        }
440

    
441
        public int getDynMethodCode(DynClass dynClass, String methodName) throws DynMethodException  {
442
                String key = DefaultDynObjectManager.getKey(null, dynClass, methodName);
443
                MethodInfo info = (MethodInfo) methodsMap.get(key);
444
                if( info == null ) {
445
                        throw new IllegalDynMethodException(methodName, dynClass);
446
                }
447
                info.check(dynClass, info.code);
448
                return info.code;
449
        }
450

    
451
        public int getDynMethodCode(Class theClass, String methodName) throws DynMethodException {
452
                String key = DefaultDynObjectManager.getKey(theClass, null, methodName);
453
                MethodInfo info = (MethodInfo) methodsMap.get(key);
454
                if( info == null ) {
455
                        throw new IllegalDynMethodException(methodName, theClass);
456
                }
457
                info.check(theClass, info.code);
458
                return info.code;
459
        }
460

    
461
        public DynMethod getDynMethod(int code) throws DynMethodException {
462
                if (code >= methods.length) {
463
                        throw new DynMethodNotSupportedException(code, "{null}");
464
                }
465
                MethodInfo info = methods[code];
466
                info.check((Class)null, code);
467
                return info.dynMethod;
468
        }
469

    
470
        public DynMethod getDynMethod(Object obj, int code)
471
                        throws DynMethodException {
472
                return getDynMethod(obj.getClass(), code);
473
        }
474

    
475
        public DynMethod getDynMethod(Class theClass, int code)
476
                        throws DynMethodException {
477
                if (code >= methods.length) {
478
                        throw new DynMethodNotSupportedException(code, theClass.getName());
479
                }
480
                MethodInfo info = methods[code];
481
                info.check(theClass, code);
482
                return info.dynMethod;
483
        }
484

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

    
495
        public DynMethod getDynMethod(DynObject dynObject, int code)
496
                        throws DynMethodException {
497
                return getDynMethod(dynObject.getDynClass(), code);
498
        }
499

    
500
        public void validate(DynObject object) {
501
                // TODO
502
                return;
503
        }
504
        
505
        public Class getDefaultClassOfType(int type) {
506
                return ToolsLocator.getDataTypesManager().getDefaultClass(type);
507
        }
508

    
509
        public Map importDynClassDefinitions(InputStream resource,
510
                        ClassLoader loader) throws XmlPullParserException, IOException {
511
                return new DynClassImportHelper().importDefinitions(resource, loader);
512
        }
513

    
514
        public Map importDynClassDefinitions(XmlPullParser parser,
515
                        ClassLoader loader) throws XmlPullParserException, IOException {
516
                return new DynClassImportHelper().importDefinitions(parser, loader);
517
        }
518
}