Statistics
| Revision:

gvsig-tools / org.gvsig.tools / library / trunk / org.gvsig.tools / org.gvsig.tools.lib / src / main / java / org / gvsig / tools / dynobject / impl / DynClassImportHelper.java @ 112

History | View | Annotate | Download (16.1 KB)

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

    
3
import java.io.IOException;
4
import java.io.InputStream;
5
import java.util.ArrayList;
6
import java.util.HashMap;
7
import java.util.Iterator;
8
import java.util.List;
9
import java.util.Map;
10

    
11
import org.gvsig.tools.ToolsLocator;
12
import org.gvsig.tools.dataTypes.CoercionException;
13
import org.gvsig.tools.dynobject.DynClass;
14
import org.gvsig.tools.dynobject.DynField;
15
import org.gvsig.tools.dynobject.DynObjectManager;
16
import org.gvsig.tools.dynobject.DynObjectValueItem;
17
import org.gvsig.tools.dynobject.exception.DynFieldIsNotAContainerException;
18
import org.xmlpull.v1.XmlPullParser;
19
import org.xmlpull.v1.XmlPullParserException;
20

    
21
public class DynClassImportHelper {
22

    
23
        private static final String VERSION_VALUE = "1.0.0";
24
        
25
        private static final String DEFINITIONS_TAG = "definitions";
26
        private static final String VERSION_TAG = "version";
27
        private static final String CLASSES_TAG = "classes";
28
        
29
        private static final String CLASS_TAG = "class";
30
        private static final String CLASS_NAME_TAG = "name";
31
        private static final String CLASS_NAMESPACE_TAG = "namespace";
32
        private static final String CLASS_DESCRIPTION_TAG = "description";
33
        private static final String CLASS_SUPERCLASSNAMES_TAG = "superClassNames";
34
        private static final String CLASS_SUPERCLASSNAME_TAG = "superClassName";
35
        private static final String CLASS_EXTENDS_TAG = "extends";
36
        private static final String CLASS_EXTENDS_CLASS_TAG = "class";
37
        private static final String CLASS_FIELDS_TAG = "fields";
38
        
39
        private static final String FIELD_TAG = "field";
40
        private static final String FIELD_NAME_TAG = "name";
41
        private static final String FIELD_DESCRIPTION_TAG = "description";
42
        private static final String FIELD_SUBTYPE_TAG = "subtype";
43
        private static final String FIELD_TYPE_TAG = "type";
44
        private static final String FIELD_ISMANDATORY_TAG = "mandatory";
45
        private static final String FIELD_ISPERSISTENT_TAG = "persistent";
46
        private static final String FIELD_MINVALUE_TAG = "minValue";
47
        private static final String FIELD_MAXVALUE_TAG = "maxValue";
48
        private static final String FIELD_CLASSOFVALUE_TAG = "classOfValue";
49
        private static final String FIELD_DEFAULTVALUE_TAG = "defaultValue";
50
//        private static final String FIELD_TYPEOFAVALILABLEVALUES_TAG = "typeOfAvailableValues";
51
        private static final String FIELD_AVALILABLEVALUES_TAG = "availableValues";
52
        private static final String FIELD_GROUP_TAG = "group";
53
        private static final String FIELD_ORDER_TAG = "order";
54

    
55
        private static final String VALUEITEM_TAG = "valueItem";
56
        private static final String VALUEITEM_LABEL_TAG = "label";
57
        private static final String VALUEITEM_VALUE_TAG = "value";
58
        
59
        public Map importDefinitions(InputStream resource, ClassLoader loader) throws XmlPullParserException, IOException {
60

    
61
                XmlPullParser parser = ToolsLocator.getXmlPullParser();
62
                
63
                parser.setInput(resource, null);
64
                
65
                return importDefinitions(parser, loader);
66
        }
67
        
68
        public Map importDefinitions(XmlPullParser parser, ClassLoader loader) throws XmlPullParserException, IOException {
69
                Map dynClasses = new HashMap();
70
                String version = null;
71
                
72
                if( loader == null ) {
73
                        loader = this.getClass().getClassLoader();
74
                }
75
                parser.nextTag();
76
                parser.require(XmlPullParser.START_TAG, null, DEFINITIONS_TAG);
77
                for( int i=0;i<parser.getAttributeCount(); i++) {
78
                        String name = parser.getAttributeName(i);
79
                        if( name.equalsIgnoreCase(VERSION_TAG) ) {
80
                                version = parser.getAttributeValue(i);
81
                        } else {
82
                                // FIXME: throw exception
83
                        }
84
                }
85
                parser.nextTag();
86
                if( parser.getName().equalsIgnoreCase(VERSION_TAG) ) {
87
                        parser.require(XmlPullParser.START_TAG, null, VERSION_TAG);
88
                        version = parser.nextText();
89
                        if (!version.trim().equals(VERSION_VALUE) ) {
90
                                throw new UnsupportedClassVersionError();
91
                        }
92
                        parser.require(XmlPullParser.END_TAG, "", VERSION_TAG);
93
                        parser.nextTag();
94
                }
95
                
96
                parser.require(XmlPullParser.START_TAG, "", CLASSES_TAG);
97
                parser.nextTag();
98
                while ( !( parser.getEventType() == XmlPullParser.END_TAG && 
99
                                   parser.getName().equals(CLASSES_TAG))) {
100
                        checkEndDocument(parser);
101
                        DynClass dynClass = importDynClass(parser, loader);
102
                        if( dynClasses.get(dynClass.getName())!=null ) {
103
                                throw new DuplicateDynClassException(parser, dynClass.getName());
104
                        }
105
                        dynClasses.put(dynClass.getName(), dynClass);
106
                }
107
                parser.require(XmlPullParser.END_TAG, "", CLASSES_TAG);
108
                parser.nextTag();
109

    
110
                parser.require(XmlPullParser.END_TAG, "", DEFINITIONS_TAG);
111
                parser.next();
112

    
113
                parser.require(XmlPullParser.END_DOCUMENT, null, null);
114
                return dynClasses;
115
        }
116

    
117
        private DynClass importDynClass(XmlPullParser parser, ClassLoader loader) throws XmlPullParserException, IOException {
118
                DynObjectManager manager = ToolsLocator.getDynObjectManager();
119
                DynClass dynClass; 
120
                List superClassNames = new ArrayList();
121
                Map values = new HashMap();
122
                
123
                parser.require(XmlPullParser.START_TAG, null, CLASS_TAG);
124
                //
125
                // Collect class attributes from tag attributes
126
                //
127
                for( int i=0; i<parser.getAttributeCount(); i++ ) {
128
                        values.put(parser.getAttributeName(i), parser.getAttributeValue(i));
129
                }
130
                parser.nextTag();
131

    
132
                while ( !( parser.getEventType() == XmlPullParser.END_TAG && 
133
                                   parser.getName().equals(CLASSES_TAG))) {
134
                        checkEndDocument(parser);
135

    
136
                        parser.require(XmlPullParser.START_TAG, null, null);
137
                        String tagName = parser.getName();
138
                        if( tagName.equalsIgnoreCase(CLASS_DESCRIPTION_TAG)) {
139
                                values.put(CLASS_DESCRIPTION_TAG, parser.nextText());
140

    
141
                        } else if( tagName.equalsIgnoreCase(CLASS_NAME_TAG)) {
142
                                values.put(CLASS_NAME_TAG, parser.nextText());
143
                                
144
                        } else if( tagName.equalsIgnoreCase(CLASS_NAMESPACE_TAG)) {
145
                                values.put(CLASS_NAMESPACE_TAG, parser.nextText());
146

    
147
                        } else if( tagName.equalsIgnoreCase(CLASS_SUPERCLASSNAMES_TAG) ) {
148
                                parser.nextTag();
149
                                while ( !( parser.getEventType() == XmlPullParser.END_TAG && 
150
                                                   parser.getName().equals(CLASS_SUPERCLASSNAMES_TAG))) {
151
                                        checkEndDocument(parser);
152
                                        parser.require(XmlPullParser.START_TAG, "", CLASS_SUPERCLASSNAME_TAG);
153
                                        superClassNames.add(parser.nextText());
154
                                        parser.require(XmlPullParser.END_TAG, null, CLASS_SUPERCLASSNAME_TAG);
155
                                        parser.nextTag();
156
                                }
157
                                
158
                        } else if( tagName.equalsIgnoreCase(CLASS_EXTENDS_TAG) ) { // == CLASS_SUPERCLASSNAMES_TAG
159
                                parser.nextTag();
160
                                while ( !( parser.getEventType() == XmlPullParser.END_TAG && 
161
                                                   parser.getName().equals(CLASS_EXTENDS_TAG))) {
162
                                        checkEndDocument(parser);
163
                                        parser.require(XmlPullParser.START_TAG, "", CLASS_EXTENDS_CLASS_TAG);
164
                                        superClassNames.add(parser.nextText());
165
                                        parser.require(XmlPullParser.END_TAG, null, CLASS_EXTENDS_CLASS_TAG);
166
                                        parser.nextTag();
167
                                }
168
                        } else {
169
                                break;
170
                        }
171
                        parser.require(XmlPullParser.END_TAG, null, tagName);
172
                        parser.nextTag();
173
                }
174
                parser.require(XmlPullParser.START_TAG, null, CLASS_FIELDS_TAG);
175
                parser.nextTag();
176

    
177
                //
178
                // Create dynclass
179
                //
180
                if( values.get(CLASS_NAME_TAG) == null ) {
181
                        throw new BadDefinitionFormatException();
182
                }
183
                dynClass = manager.createDynClass(
184
                        (String)values.get(CLASS_NAMESPACE_TAG),
185
                        (String)values.get(CLASS_NAME_TAG),
186
                        (String)values.get(CLASS_DESCRIPTION_TAG)
187
                );
188
                for( int i=0; i<superClassNames.size(); i++) {
189
                        dynClass.extend((String)superClassNames.get(i));
190
                }
191

    
192
                //
193
                // Parse and load fields of dynclass
194
                //
195
                while ( !( parser.getEventType() == XmlPullParser.END_TAG && 
196
                                   parser.getName().equals(CLASS_FIELDS_TAG))) {
197
                        checkEndDocument(parser);
198
            importDynField(parser, dynClass, loader);
199
                    parser.nextTag();
200
                }
201
                parser.require(XmlPullParser.END_TAG, null, CLASS_FIELDS_TAG);
202
                parser.nextTag();
203

    
204
                parser.require(XmlPullParser.END_TAG, null, CLASS_TAG);
205
                parser.nextTag();
206
                return dynClass;
207
        }
208
        
209
        private void importDynField(XmlPullParser parser, DynClass dynClass, ClassLoader loader) throws XmlPullParserException, IOException {
210
                DynField field;
211
                List availableValues = new ArrayList();
212
                Map values = new HashMap();
213

    
214
                parser.require(XmlPullParser.START_TAG, null, FIELD_TAG);
215
                //
216
                // Collect field attributes from tag attributes
217
                //
218
                for( int i=0; i<parser.getAttributeCount(); i++ ) {
219
                        values.put(parser.getAttributeName(i), parser.getAttributeValue(i));
220
                }
221
                parser.nextTag();
222

    
223
                //
224
                // Collect field attributes from tags
225
                //
226
                while ( !( parser.getEventType() == XmlPullParser.END_TAG && 
227
                                   parser.getName().equals(FIELD_TAG))) {
228
                        checkEndDocument(parser);
229

    
230
                        parser.require(XmlPullParser.START_TAG, null, null);
231
                        String name = parser.getName();
232
                        if( name.equalsIgnoreCase(FIELD_NAME_TAG)) {
233
                                values.put(FIELD_NAME_TAG, parser.nextText());
234
                                
235
                        } else if( name.equalsIgnoreCase(FIELD_DESCRIPTION_TAG)) {
236
                                values.put(FIELD_DESCRIPTION_TAG, parser.nextText());
237

    
238
                        } else if( name.equalsIgnoreCase(FIELD_TYPE_TAG)) {
239
                                values.put(FIELD_TYPE_TAG, parser.nextText());
240
                                
241
                        } else if( name.equalsIgnoreCase(FIELD_SUBTYPE_TAG)) {
242
                                values.put(FIELD_SUBTYPE_TAG, parser.nextText());
243
                                
244
                        } else if( name.equalsIgnoreCase(FIELD_GROUP_TAG)) {
245
                                values.put(FIELD_GROUP_TAG, parser.nextText());
246
                                
247
                        } else if( name.equalsIgnoreCase(FIELD_ORDER_TAG)) {
248
                                values.put(FIELD_ORDER_TAG, parser.nextText());
249
                                
250
                        } else if( name.equalsIgnoreCase(FIELD_ISMANDATORY_TAG)) {
251
                                values.put(FIELD_ISMANDATORY_TAG, parser.nextText());
252
                                
253
                        } else if( name.equalsIgnoreCase(FIELD_ISPERSISTENT_TAG)) {
254
                                values.put(FIELD_ISPERSISTENT_TAG, parser.nextText());
255
                                
256
                        } else if( name.equalsIgnoreCase(FIELD_MINVALUE_TAG)) {
257
                                values.put(FIELD_MINVALUE_TAG, parser.nextText());
258
                                
259
                        } else if( name.equalsIgnoreCase(FIELD_MAXVALUE_TAG)) {
260
                                values.put(FIELD_MAXVALUE_TAG, parser.nextText());
261
                                
262
                        } else if( name.equalsIgnoreCase(FIELD_CLASSOFVALUE_TAG)) {
263
                                values.put(FIELD_CLASSOFVALUE_TAG, parser.nextText());
264
                                
265
                        } else if( name.equalsIgnoreCase(FIELD_DEFAULTVALUE_TAG)) {
266
                                values.put(FIELD_DEFAULTVALUE_TAG, parser.nextText());
267
                                
268
                        } else if( name.equalsIgnoreCase(FIELD_AVALILABLEVALUES_TAG)) {
269
                                parser.nextTag();
270
                                while ( !( parser.getEventType() == XmlPullParser.END_TAG && 
271
                                                   parser.getName().equals(FIELD_AVALILABLEVALUES_TAG))) {
272
                                        checkEndDocument(parser);
273
                                        availableValues.add(importValueItem(parser));
274
                                        parser.nextTag();
275
                                }
276
                                
277
                        } else {
278
                                break;
279
                        }
280
                        parser.require(XmlPullParser.END_TAG, null, name);
281
                        parser.nextTag();
282
                }
283
                parser.require(XmlPullParser.END_TAG, null, FIELD_TAG);
284

    
285
                
286
                if( values.get(FIELD_NAME_TAG)==null ) {
287
                        throw new BadDefinitionFormatException();
288
                }
289

    
290
                //
291
                // Create the field
292
                //
293
                field = dynClass.addDynField((String)values.get(FIELD_NAME_TAG));
294
                
295
                //
296
                // Load values in the field
297
                //
298
                Iterator names = values.keySet().iterator();
299
                while( names.hasNext() ) {
300
                        String name = (String) names.next();
301
                        String value = (String)values.get(name);
302
                        if( name.equalsIgnoreCase(FIELD_DESCRIPTION_TAG)) {
303
                                field.setDescription(value);
304

    
305
                        } else if( name.equalsIgnoreCase(FIELD_TYPE_TAG)) {
306
                                field.setType( ToolsLocator.getDataTypesManager().getType(value) );
307
                                
308
                        } else if( name.equalsIgnoreCase(FIELD_SUBTYPE_TAG)) {
309
                                field.setSubtype(value);
310
                                
311
                        } else if( name.equalsIgnoreCase(FIELD_GROUP_TAG)) {
312
                                field.setGroup(value);
313
                                
314
                        } else if( name.equalsIgnoreCase(FIELD_ORDER_TAG)) {
315
                                field.setOrder( Integer.parseInt(value));
316
                                
317
                        } else if( name.equalsIgnoreCase(FIELD_ISMANDATORY_TAG)) {
318
                                field.setMandatory(Boolean.parseBoolean(value));
319
                                
320
                        } else if( name.equalsIgnoreCase(FIELD_ISPERSISTENT_TAG)) {
321
                                 field.setPersistent(Boolean.parseBoolean(value));
322
                                
323
                        } else if( name.equalsIgnoreCase(FIELD_CLASSOFVALUE_TAG)) {
324
                                try {
325
                                        field.setClassOfValue( Class.forName(value, true, loader) );
326
                                } catch (DynFieldIsNotAContainerException e) {
327
                                        throw new IncompatibleAttributeValueException(parser, FIELD_NAME_TAG);
328
                                } catch (ClassNotFoundException e) {
329
                                        throw new CantLocateClassException(parser, FIELD_NAME_TAG);
330
                                }
331
                                
332
                        } else if( name.equalsIgnoreCase(FIELD_MINVALUE_TAG)) {
333
                                // Do nothing
334
                                
335
                        } else if( name.equalsIgnoreCase(FIELD_MAXVALUE_TAG)) {
336
                                // Do nothing
337
                                
338
                        } else if( name.equalsIgnoreCase(FIELD_DEFAULTVALUE_TAG)) {
339
                                // Do nothing
340
                                
341
                        } else if( name.equalsIgnoreCase(FIELD_AVALILABLEVALUES_TAG)) {
342
                                // Do nothing
343

    
344
                        } else if( name.equalsIgnoreCase(FIELD_NAME_TAG)) {
345
                                // Do nothing
346

    
347
                        } else {
348
                                throw new BadDefinitionFormatException();
349
                        }
350
                }
351

    
352
                try {
353
                        //
354
                        // Coerce the the min/max/default/available values to the type of
355
                        // the field
356
                        //
357
                        for (int i = 0; i < availableValues.size(); i++) {
358
                                PairValueLabel pair = (PairValueLabel) availableValues.get(i);
359
                                if (pair.label == null) {
360
                                        if (pair.value == null) {
361
                                                pair.label = "null";
362
                                        } else {
363
                                                pair.label = pair.value.toString();
364
                                        }
365
                                }
366
                                availableValues.set(i, new DynObjectValueItem(field.coerce(pair.value), pair.label));
367
                        }
368
                        field.setAvailableValues(availableValues);
369
                        field.setMaxValue(field.coerce(values.get(FIELD_MAXVALUE_TAG)));
370
                        field.setMinValue(field.coerce(values.get(FIELD_MINVALUE_TAG)));
371
                        field.setDefaultDynValue(field.coerce(values.get(FIELD_DEFAULTVALUE_TAG)));
372
                } catch (CoercionException e) {
373
                        throw new ParseCoerceException(e, parser);
374
                }
375
        }
376

    
377
        private class PairValueLabel {
378
                String label=null;
379
                String value=null;
380
        }
381
        
382
        private PairValueLabel importValueItem(XmlPullParser parser) throws XmlPullParserException, IOException {
383
                PairValueLabel pair = new PairValueLabel();
384
                
385
                if( parser.getName().equalsIgnoreCase(VALUEITEM_TAG)) {
386
                        parser.require(XmlPullParser.START_TAG, null, VALUEITEM_TAG);
387
                        for( int i=0; i<parser.getAttributeCount(); i++) {
388
                                String name = parser.getAttributeName(i);
389
                                if( name.equalsIgnoreCase(VALUEITEM_LABEL_TAG)) {
390
                                        pair.label = parser.getAttributeValue(i);
391
                                } else if( name.equalsIgnoreCase(VALUEITEM_VALUE_TAG)) {
392
                                        pair.value = parser.getAttributeValue(i);
393
                                } else {
394
                                        // FIXME: throw exception
395
                                }
396
                        }
397
                        parser.nextTag();
398
        
399
                        while ( !( parser.getEventType() == XmlPullParser.END_TAG && 
400
                                           parser.getName().equals(VALUEITEM_TAG))) {
401
                                checkEndDocument(parser);
402
                                parser.require(XmlPullParser.START_TAG, null, null);
403
                                String name = parser.getName();
404
                                if( name.equalsIgnoreCase(VALUEITEM_LABEL_TAG)) {
405
                                        pair.label = parser.nextText();
406
                                } else if( name.equalsIgnoreCase(VALUEITEM_VALUE_TAG)) {
407
                                        pair.value = parser.nextText();
408
                                } else {
409
                                        break;
410
                                }
411
                                parser.require(XmlPullParser.END_TAG, null, name);
412
                                parser.nextTag();
413
                        }
414
                        parser.require(XmlPullParser.END_TAG, null, VALUEITEM_TAG);
415
                } else {
416
                        parser.require(XmlPullParser.START_TAG, null, VALUEITEM_VALUE_TAG);
417
                        for( int i=0; i<parser.getAttributeCount(); i++) {
418
                                String name = parser.getAttributeName(i);
419
                                if( name.equalsIgnoreCase(VALUEITEM_LABEL_TAG)) {
420
                                        pair.label = parser.getAttributeValue(i);
421
                                } else {
422
                                        // FIXME: throw exception
423
                                }
424
                        }
425
                        pair.value = parser.nextText();
426
                        parser.require(XmlPullParser.END_TAG, null, VALUEITEM_VALUE_TAG);
427
                }
428
                return pair;
429
        }
430
        
431
        private void checkEndDocument(XmlPullParser parser) throws XmlPullParserException {
432
                if (parser.getEventType() == XmlPullParser.END_DOCUMENT) {
433
                        throw new BadDefinitionFormatException();
434
                }
435

    
436
        }
437
        public static class DuplicateDynClassException extends RuntimeException { 
438
                /**
439
                 * 
440
                 */
441
                private static final long serialVersionUID = 3653024321140806121L;
442

    
443
                public DuplicateDynClassException(XmlPullParser parser, String name) { }
444
        }
445
        
446
        public static class BadDefinitionFormatException extends RuntimeException { 
447
                /**
448
                 * 
449
                 */
450
                private static final long serialVersionUID = -808282903423455613L;
451

    
452
                public BadDefinitionFormatException() { }
453
        }
454
        
455
        public static class CantLocateClassException extends RuntimeException { 
456
                /**
457
                 * 
458
                 */
459
                private static final long serialVersionUID = 5733585544096433612L;
460

    
461
                public CantLocateClassException(XmlPullParser parser, String tagname) { }
462
        }
463

    
464
        public static class IncompatibleAttributeValueException extends RuntimeException { 
465
                /**
466
                 * 
467
                 */
468
                private static final long serialVersionUID = 2646530094487375049L;
469

    
470
                public IncompatibleAttributeValueException(XmlPullParser parser, String tagname) { }
471
        }
472

    
473
        public static class ParseCoerceException extends RuntimeException { 
474

    
475
                /**
476
                 * 
477
                 */
478
                private static final long serialVersionUID = 1447718822981628834L;
479

    
480
                public ParseCoerceException(Throwable cause, XmlPullParser parser) { }
481
        }
482

    
483

    
484
}