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

History | View | Annotate | Download (30.4 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.HashMap;
30
import java.util.Iterator;
31
import java.util.List;
32
import java.util.Map;
33

    
34
import org.gvsig.tools.ToolsLocator;
35
import org.gvsig.tools.dataTypes.CoercionException;
36
import org.gvsig.tools.dataTypes.DataTypes;
37
import org.gvsig.tools.dynobject.DynClass;
38
import org.gvsig.tools.dynobject.DynClassName;
39
import org.gvsig.tools.dynobject.DynField_v2;
40
import org.gvsig.tools.dynobject.DynObjectManager;
41
import org.gvsig.tools.dynobject.DynObjectRuntimeException;
42
import org.gvsig.tools.dynobject.DynObjectValueItem;
43
import org.gvsig.tools.dynobject.exception.DynFieldIsNotAContainerException;
44
import org.gvsig.tools.exception.BaseRuntimeException;
45
import org.gvsig.tools.exception.ListBaseException;
46
import org.slf4j.Logger;
47
import org.slf4j.LoggerFactory;
48
import org.xmlpull.v1.XmlPullParser;
49
import org.xmlpull.v1.XmlPullParserException;
50
import org.xmlpull.v1.XmlPullParserFactory;
51

    
52
public class DynClassImportHelper {
53

    
54
        private static final Logger LOG = LoggerFactory
55
                        .getLogger(DynClassImportHelper.class);
56

    
57
        private static final String VERSION_VALUE = "1.0.0";
58

    
59
        private static final String DEFINITIONS_TAG = "definitions";
60
        private static final String VERSION_TAG = "version";
61
        private static final String CLASSES_TAG = "classes";
62

    
63
        private static final String CLASS_TAG = "class";
64
        private static final String CLASS_NAME_TAG = "name";
65
        private static final String CLASS_NAMESPACE_TAG = "namespace";
66
        private static final String CLASS_DESCRIPTION_TAG = "description";
67
        private static final String CLASS_SUPERCLASSNAMES_TAG = "superClassNames";
68
        private static final String CLASS_SUPERCLASSNAME_TAG = "superClassName";
69
        private static final String CLASS_EXTENDS_TAG = "extends";
70
        private static final String CLASS_EXTENDS_CLASS_TAG = "class";
71
        private static final String CLASS_FIELDS_TAG = "fields";
72

    
73
        private static final String FIELD_TAG = "field";
74
        private static final String FIELD_NAME_TAG = "name";
75
        private static final String FIELD_DESCRIPTION_TAG = "description";
76
        private static final String FIELD_SUBTYPE_TAG = "subtype";
77
        private static final String FIELD_TYPE_TAG = "type";
78
        private static final String FIELD_ISMANDATORY_TAG = "mandatory";
79
        private static final String FIELD_ISPERSISTENT_TAG = "persistent";
80
        private static final String FIELD_MINVALUE_TAG = "minValue";
81
        private static final String FIELD_MAXVALUE_TAG = "maxValue";
82
        private static final String FIELD_CLASSOFVALUE_TAG = "classOfValue";
83
        private static final String FIELD_CLASSOFITEMS_TAG = "classOfItems";
84
        private static final String FIELD_ELEMENTTYPE_TAG = "elementType";
85
        private static final String FIELD_STRUCTUSEDWHENISDYNOBJECT_TAG = "StructWhenTypeIsDynObject";
86
        private static final String FIELD_DEFAULTVALUE_TAG = "defaultValue";
87
        // private static final String FIELD_TYPEOFAVALILABLEVALUES_TAG =
88
        // "typeOfAvailableValues";
89
        private static final String FIELD_AVALILABLEVALUES_TAG = "availableValues";
90
        private static final String FIELD_GROUP_TAG = "group";
91
        private static final String FIELD_ORDER_TAG = "order";
92
        private static final String FIELD_HIDDEN_TAG = "hidden";
93
        private static final String FIELD_LABEL_TAG = "label";
94
        private static final String FIELD_TAGS_TAG = "tags";
95
        private static final String VALUEITEM_TAGNAME_TAG = "name";
96
        
97
        private static final String VALUEITEM_TAG = "valueItem";
98
        private static final String VALUEITEM_LABEL_TAG = "label";
99
        private static final String VALUEITEM_VALUE_TAG = "value";
100

    
101
        private DynObjectManager manager = ToolsLocator.getDynObjectManager();
102

    
103
        private Map dynClasses = null;
104
        
105
        private String getNullWhenEmptyString(String value) {
106
                if (value != null) {
107
                        if (value.trim().length() == 0) {
108
                                return null;
109
                        }
110
                }
111
                return value;
112

    
113
        }
114

    
115
        private String nextText(XmlPullParser parser)
116
                        throws XmlPullParserException, IOException {
117
                return getNullWhenEmptyString(parser.nextText());
118
        }
119

    
120
        private String getAttributeValue(XmlPullParser parser, int i)
121
                        throws XmlPullParserException, IOException {
122
                return getNullWhenEmptyString(parser.getAttributeValue(i));
123
        }
124

    
125
        public Map importDefinitions(InputStream resource, ClassLoader loader,
126
                        String defaultNamespace) throws XmlPullParserException, IOException {
127

    
128
                XmlPullParserFactory factory = XmlPullParserFactory.newInstance(
129
                                ToolsLocator.getInstance().getXmlPullParserFactoryClassNames(),
130
                                null);
131

    
132
                XmlPullParser parser = factory.newPullParser();
133

    
134
                parser.setInput(resource, null);
135

    
136
                return importDefinitions(parser, loader, defaultNamespace);
137
        }
138

    
139
        private class Definitions extends HashMap implements Map {
140

    
141
                /**
142
                 * 
143
                 */
144
                private static final long serialVersionUID = -3322643637478345069L;
145

    
146
                public Object put(Object key, Object value) {
147
                        return super.put(((String) key).toLowerCase(), value);
148
                }
149

    
150
                public Object get(Object theName) {
151
                        DynClass definition;
152
                        definition = (DynClass) super.get(((String) theName).toLowerCase());
153
                        if (definition != null) {
154
                                return definition;
155
                        }
156
                        // No ha encontrado la clase pedida, podria ser que el namespace
157
                        // no coincida, vamos a buscarla ignorando el namespace en caso
158
                        // de que este no se haya indicado.
159
                        DynClassName name = manager.createDynClassName((String) theName);
160
                        if (name.getNamespace() == null) {
161
                                // No han especificado namespace, asi que busco la primera
162
                                // que tenga como nombre el indicado independientemente del
163
                                // namespace que tenga.
164
                                Iterator it = this.values().iterator();
165
                                while (it.hasNext()) {
166
                                        definition = (DynClass) it.next();
167
                                        if (definition.getName().equalsIgnoreCase(name.getName())) {
168
                                                return definition;
169
                                        }
170
                                }
171
                        } else {
172
                                // Han especificaso un namespace, asi que voy a buscar una que
173
                                // no tenga namespace y su nombre concuerde.
174
                                Iterator it = this.values().iterator();
175
                                while (it.hasNext()) {
176
                                        definition = (DynClass) it.next();
177
                                        if (definition.getNamespace() == null
178
                                                        && definition.getName().equalsIgnoreCase(
179
                                                                        name.getName())) {
180
                                                return definition;
181
                                        }
182
                                }
183
                        }
184
                        return null;
185
                }
186

    
187
                public boolean containsKey(Object key) {
188
                        String lowerKey = ((String) key).toLowerCase();
189
                        if (super.containsKey(lowerKey)) {
190
                                return true;
191
                        }
192
                        Object value = this.get(lowerKey);
193
                        return value != null;
194
                }
195
        }
196

    
197
        public Map importDefinitions(XmlPullParser parser, ClassLoader loader,
198
                        String defaultNamespace) throws XmlPullParserException, IOException {
199
                dynClasses = new Definitions();
200
                String version = null;
201

    
202
                if (loader == null) {
203
                        loader = this.getClass().getClassLoader();
204
                }
205
                parser.nextTag();
206
                parser.require(XmlPullParser.START_TAG, null, DEFINITIONS_TAG);
207
                for (int i = 0; i < parser.getAttributeCount(); i++) {
208
                        String name = parser.getAttributeName(i);
209
                        if (name.equalsIgnoreCase(VERSION_TAG)) {
210
                                version = this.getAttributeValue(parser, i);
211
                        } else {
212
                                throw new WrongVersionException(parser);
213
                        }
214
                }
215
                parser.nextTag();
216
                if (parser.getName().equalsIgnoreCase(VERSION_TAG)) {
217
                        parser.require(XmlPullParser.START_TAG, null, VERSION_TAG);
218
                        version = parser.nextText();
219
                        if (!version.trim().equals(VERSION_VALUE)) {
220
                                throw new UnsupportedClassVersionError();
221
                        }
222
                        parser.require(XmlPullParser.END_TAG, "", VERSION_TAG);
223
                        parser.nextTag();
224
                }
225

    
226
                parser.require(XmlPullParser.START_TAG, "", CLASSES_TAG);
227
                parser.nextTag();
228
                while (!(parser.getEventType() == XmlPullParser.END_TAG && parser
229
                                .getName().equals(CLASSES_TAG))) {
230
                        checkEndDocument(parser);
231
                        DynClass dynClass = importDynClass(parser, loader,
232
                                        defaultNamespace, dynClasses);
233
                        try {
234
                                ((DefaultDynClass) dynClass).check();
235
                        } catch (ListBaseException e) {
236
                                throw new DynObjectRuntimeException(e);
237
                        }
238
                        if (dynClasses.get(dynClass.getFullName()) != null) {
239
                                throw new DuplicateDynClassException(parser,
240
                                                dynClass.getFullName());
241
                        }
242
                        dynClasses.put(dynClass.getFullName(), dynClass);
243
                }
244
                parser.require(XmlPullParser.END_TAG, "", CLASSES_TAG);
245
                parser.nextTag();
246

    
247
                parser.require(XmlPullParser.END_TAG, "", DEFINITIONS_TAG);
248
                parser.next();
249

    
250
                parser.require(XmlPullParser.END_DOCUMENT, null, null);
251
                LOG.debug("Imported classes {}", new Object[] { getKeys(dynClasses) });
252
                return dynClasses;
253
        }
254

    
255
        private String getKeys(Map theMap) {
256
                List l = new ArrayList(theMap.keySet());
257
                return l.toString();
258
        }
259

    
260
        private DynClass importDynClass(XmlPullParser parser, ClassLoader loader,
261
                        String defaultNamespace, Map classes)
262
                        throws XmlPullParserException, IOException {
263
                DynObjectManager manager = ToolsLocator.getDynObjectManager();
264
                DynClass dynClass;
265
                List superClasses = new ArrayList();
266
                Map values = new HashMap();
267

    
268
                parser.require(XmlPullParser.START_TAG, null, CLASS_TAG);
269
                //
270
                // Collect class attributes from tag attributes
271
                //
272
                for (int i = 0; i < parser.getAttributeCount(); i++) {
273
                        values.put(parser.getAttributeName(i),
274
                                        this.getAttributeValue(parser, i));
275
                }
276
                parser.nextTag();
277

    
278
                while (!(parser.getEventType() == XmlPullParser.END_TAG && parser
279
                                .getName().equals(CLASSES_TAG))) {
280
                        checkEndDocument(parser);
281

    
282
                        parser.require(XmlPullParser.START_TAG, null, null);
283
                        String tagName = parser.getName();
284
                        if (tagName.equalsIgnoreCase(CLASS_DESCRIPTION_TAG)) {
285
                                values.put(CLASS_DESCRIPTION_TAG, this.nextText(parser));
286

    
287
                        } else if (tagName.equalsIgnoreCase(CLASS_NAME_TAG)) {
288
                                values.put(CLASS_NAME_TAG, this.nextText(parser));
289

    
290
                        } else if (tagName.equalsIgnoreCase(CLASS_NAMESPACE_TAG)) {
291
                                values.put(CLASS_NAMESPACE_TAG, this.nextText(parser));
292

    
293
                        } else if (tagName.equalsIgnoreCase(CLASS_SUPERCLASSNAMES_TAG)) {
294
                                parser.nextTag();
295
                                while (!(parser.getEventType() == XmlPullParser.END_TAG && parser
296
                                                .getName().equals(CLASS_SUPERCLASSNAMES_TAG))) {
297
                                        checkEndDocument(parser);
298
                                        parser.require(XmlPullParser.START_TAG, "",
299
                                                        CLASS_SUPERCLASSNAME_TAG);
300
                                        superClasses.add(manager.createDynClassName(
301
                                                        defaultNamespace, this.nextText(parser)));
302
                                        parser.require(XmlPullParser.END_TAG, null,
303
                                                        CLASS_SUPERCLASSNAME_TAG);
304
                                        parser.nextTag();
305
                                }
306

    
307
                        } else if (tagName.equalsIgnoreCase(CLASS_EXTENDS_TAG)) {
308
                                parser.nextTag();
309
                                while (!(parser.getEventType() == XmlPullParser.END_TAG && parser
310
                                                .getName().equals(CLASS_EXTENDS_TAG))) {
311
                                        checkEndDocument(parser);
312
                                        superClasses
313
                                                        .add(importSuperClass(parser, defaultNamespace));
314
                                        parser.nextTag();
315
                                }
316
                        } else {
317
                                break;
318
                        }
319
                        parser.require(XmlPullParser.END_TAG, null, tagName);
320
                        parser.nextTag();
321
                }
322
                parser.require(XmlPullParser.START_TAG, null, CLASS_FIELDS_TAG);
323
                parser.nextTag();
324

    
325
                //
326
                // Create dynclass
327
                //
328
                if (values.get(CLASS_NAME_TAG) == null) {
329
                        throw new NeedTagOrAttributeException(parser, CLASS_NAME_TAG);
330
                }
331
                if (values.get(CLASS_NAMESPACE_TAG) == null) {
332
                        values.put(CLASS_NAMESPACE_TAG, defaultNamespace);
333
                }
334
                dynClass = manager.createDynClass(
335
                                (String) values.get(CLASS_NAMESPACE_TAG),
336
                                (String) values.get(CLASS_NAME_TAG),
337
                                (String) values.get(CLASS_DESCRIPTION_TAG));
338
                for (int i = 0; i < superClasses.size(); i++) {
339
                        DynClassName superClass = (DynClassName) superClasses.get(i);
340
                        if (superClass.getName() == null) {
341
                                throw new NeedTagOrAttributeException(parser, CLASS_NAME_TAG);
342
                        }
343
                        DynClass superDynClass = (DynClass) classes.get(superClass
344
                                        .getFullName());
345
                        if (superDynClass == null) {
346
                                superDynClass = ToolsLocator.getDynObjectManager().get(
347
                                                superClass.getNamespace(), superClass.getName());
348
                                if (superDynClass == null) {
349
                                        throw new CantLocateDynClassException(parser,
350
                                                        superClass.getFullName());
351
                                }
352
                        }
353
                        dynClass.extend(superDynClass);
354
                }
355

    
356
                //
357
                // Parse and load fields of dynclass
358
                //
359
                while (!(parser.getEventType() == XmlPullParser.END_TAG && parser
360
                                .getName().equals(CLASS_FIELDS_TAG))) {
361
                        checkEndDocument(parser);
362
                        importDynField(parser, dynClass, loader);
363
                        parser.nextTag();
364
                }
365
                parser.require(XmlPullParser.END_TAG, null, CLASS_FIELDS_TAG);
366
                parser.nextTag();
367

    
368
                parser.require(XmlPullParser.END_TAG, null, CLASS_TAG);
369
                parser.nextTag();
370
                return dynClass;
371
        }
372

    
373
        private DynClassName importSuperClass(XmlPullParser parser,
374
                        String defaultNamespace) throws XmlPullParserException, IOException {
375

    
376
                String name = null;
377
                String namespace = defaultNamespace;
378

    
379
                parser.require(XmlPullParser.START_TAG, null, CLASS_EXTENDS_CLASS_TAG);
380
                for (int i = 0; i < parser.getAttributeCount(); i++) {
381
                        String attrname = parser.getAttributeName(i);
382
                        if (attrname.equalsIgnoreCase(CLASS_NAME_TAG)) {
383
                                name = this.getAttributeValue(parser, i);
384
                        } else if (attrname.equalsIgnoreCase(CLASS_NAMESPACE_TAG)) {
385
                                namespace = this.getAttributeValue(parser, i);
386
                        } else {
387
                                throw new UnexpectedTagOrAttributeException(parser, attrname);
388
                        }
389
                }
390
                if (name == null) {
391
                        name = this.nextText(parser);
392
                } else {
393
                        parser.nextTag();
394
                }
395
                parser.require(XmlPullParser.END_TAG, null, CLASS_EXTENDS_CLASS_TAG);
396
                DynClassName dynClassName = manager.createDynClassName(namespace, name);
397
                return dynClassName;
398
        }
399

    
400
        private void importDynField(XmlPullParser parser, DynClass dynClass,
401
                        ClassLoader loader) throws XmlPullParserException, IOException {
402
                DynField_v2 field;
403
                List availableValues = null;
404
                List tagsValues = null;
405
                Map values = new HashMap();
406

    
407
                parser.require(XmlPullParser.START_TAG, null, FIELD_TAG);
408
                //
409
                // Collect field attributes from tag attributes
410
                //
411
                for (int i = 0; i < parser.getAttributeCount(); i++) {
412
                        values.put(parser.getAttributeName(i),
413
                                        this.getAttributeValue(parser, i));
414
                }
415
                parser.nextTag();
416

    
417
                //
418
                // Collect field attributes from tags
419
                //
420
                while (!(parser.getEventType() == XmlPullParser.END_TAG && parser
421
                                .getName().equals(FIELD_TAG))) {
422
                        checkEndDocument(parser);
423

    
424
                        parser.require(XmlPullParser.START_TAG, null, null);
425
                        String name = parser.getName();
426
                        if (name.equalsIgnoreCase(FIELD_NAME_TAG)) {
427
                                values.put(FIELD_NAME_TAG, this.nextText(parser));
428

    
429
                        } else if (name.equalsIgnoreCase(FIELD_DESCRIPTION_TAG)) {
430
                                values.put(FIELD_DESCRIPTION_TAG, this.nextText(parser));
431

    
432
                        } else if (name.equalsIgnoreCase(FIELD_TYPE_TAG)) {
433
                                values.put(FIELD_TYPE_TAG, this.nextText(parser));
434

    
435
                        } else if (name.equalsIgnoreCase(FIELD_SUBTYPE_TAG)) {
436
                                values.put(FIELD_SUBTYPE_TAG, this.nextText(parser));
437

    
438
                        } else if (name.equalsIgnoreCase(FIELD_GROUP_TAG)) {
439
                                values.put(FIELD_GROUP_TAG, this.nextText(parser));
440

    
441
                        } else if (name.equalsIgnoreCase(FIELD_LABEL_TAG)) {
442
                                values.put(FIELD_LABEL_TAG, this.nextText(parser));
443

    
444
                        } else if (name.equalsIgnoreCase(FIELD_ORDER_TAG)) {
445
                                values.put(FIELD_ORDER_TAG, this.nextText(parser));
446

    
447
                        } else if (name.equalsIgnoreCase(FIELD_ISMANDATORY_TAG)) {
448
                                values.put(FIELD_ISMANDATORY_TAG, this.nextText(parser));
449

    
450
                        } else if (name.equalsIgnoreCase(FIELD_ISPERSISTENT_TAG)) {
451
                                values.put(FIELD_ISPERSISTENT_TAG, this.nextText(parser));
452

    
453
                        } else if (name.equalsIgnoreCase(FIELD_MINVALUE_TAG)) {
454
                                values.put(FIELD_MINVALUE_TAG, this.nextText(parser));
455

    
456
                        } else if (name.equalsIgnoreCase(FIELD_MAXVALUE_TAG)) {
457
                                values.put(FIELD_MAXVALUE_TAG, this.nextText(parser));
458

    
459
                        } else if (name.equalsIgnoreCase(FIELD_CLASSOFVALUE_TAG)) {
460
                                values.put(FIELD_CLASSOFVALUE_TAG, this.nextText(parser));
461

    
462
                        } else if (name.equalsIgnoreCase(FIELD_CLASSOFITEMS_TAG)) {
463
                                values.put(FIELD_CLASSOFITEMS_TAG, this.nextText(parser));
464

    
465
                        } else if (name.equalsIgnoreCase(FIELD_DEFAULTVALUE_TAG)) {
466
                                values.put(FIELD_DEFAULTVALUE_TAG, this.nextText(parser));
467

    
468
                        } else if (name.equalsIgnoreCase(FIELD_HIDDEN_TAG)) {
469
                                values.put(FIELD_HIDDEN_TAG, this.nextText(parser));
470

    
471
                        } else if (name.equalsIgnoreCase(FIELD_AVALILABLEVALUES_TAG)) {
472
                                parser.nextTag();
473
                                availableValues = new ArrayList();
474
                                while (!(parser.getEventType() == XmlPullParser.END_TAG && parser
475
                                                .getName().equals(FIELD_AVALILABLEVALUES_TAG))) {
476
                                        checkEndDocument(parser);
477
                                        availableValues.add(importValueItem(parser, VALUEITEM_LABEL_TAG));
478
                                        parser.nextTag();
479
                                }
480

    
481
                        } else if (name.equalsIgnoreCase(FIELD_TAGS_TAG)) {
482
                                parser.nextTag();
483
                                tagsValues = new ArrayList();
484
                                while (!(parser.getEventType() == XmlPullParser.END_TAG && parser
485
                                                .getName().equals(FIELD_TAGS_TAG))) {
486
                                        checkEndDocument(parser);
487
                                        tagsValues.add(importValueItem(parser, VALUEITEM_TAGNAME_TAG));
488
                                        parser.nextTag();
489
                                }
490

    
491
                        } else {
492
                                break;
493
                        }
494
                        parser.require(XmlPullParser.END_TAG, null, name);
495
                        parser.nextTag();
496
                }
497
                parser.require(XmlPullParser.END_TAG, null, FIELD_TAG);
498

    
499
                if (values.get(FIELD_NAME_TAG) == null) {
500
                        throw new NeedTagOrAttributeException(parser, FIELD_NAME_TAG);
501
                }
502

    
503
                //
504
                // Create the field
505
                //
506
                field = (DynField_v2) dynClass.addDynField((String) values.get(FIELD_NAME_TAG));
507

    
508
                //
509
                // Setting type and subtype first
510
                //
511

    
512
                String name = FIELD_TYPE_TAG;
513
                String value = (String) values.get(name);
514
                if (value != null) {
515
                        int type = ToolsLocator.getDataTypesManager().getType(value);
516
                        if (type == DataTypes.INVALID) {
517
                                throw new InvalidFieldTypeException(parser, value);
518
                        }
519
                        field.setType(type);
520
                        name = FIELD_CLASSOFVALUE_TAG;
521
                        value = (String) values.get(name);
522
                        if (value != null) {
523
                                try {
524
                                        Class klass;
525
                                        LOG.debug("Intentando cargar clase '" + value + "'.");
526
                                        klass = Class.forName(value, true, loader);
527
                                        field.setClassOfValue(klass);
528
                                } catch (DynFieldIsNotAContainerException e) {
529
                                        LOG.warn("No se ha encontrado la clase '" + value + "'.", e);
530
                                        throw new IncompatibleAttributeValueException(parser,
531
                                                        FIELD_NAME_TAG);
532
                                } catch (ClassNotFoundException e) {
533
                                        LOG.warn("No se ha encontrado la clase '" + value + "'.", e);
534
                                        throw new CantLocateClassException(parser, FIELD_NAME_TAG);
535
                                }
536
                        }
537
                        name = FIELD_CLASSOFITEMS_TAG;
538
                        value = (String) values.get(name);
539
                        if (value != null) {
540
                                try {
541
                                        Class klass;
542
                                        klass = Class.forName(value, true, loader);
543
                                        field.setClassOfValue(klass);
544
                                } catch (DynFieldIsNotAContainerException e) {
545
                                        throw new IncompatibleAttributeValueException(parser,
546
                        FIELD_NAME_TAG, value);
547
                                } catch (ClassNotFoundException e) {
548
                    throw new CantLocateClassException(parser, FIELD_NAME_TAG,
549
                        value);
550
                                }
551
                        }
552
                }
553

    
554
                name = FIELD_SUBTYPE_TAG;
555
                value = (String) values.get(name);
556
                if (value != null) {
557
                        try {
558
                                field.setSubtype(value);
559
                        } catch (IllegalArgumentException e) {
560
                                // Ignore exception
561
                        }
562
                }
563

    
564
                //
565
                // Load other values in the field
566
                //
567
                Iterator names = values.keySet().iterator();
568
                while (names.hasNext()) {
569
                        name = (String) names.next();
570
                        value = (String) values.get(name);
571
                        if (value == null) {
572
                                continue;
573
                        }
574
                        if (name.equalsIgnoreCase(FIELD_NAME_TAG)) {
575
                                // Do nothing
576

    
577
                        } else if (name.equalsIgnoreCase(FIELD_DESCRIPTION_TAG)) {
578
                                field.setDescription(value);
579

    
580
                        } else if (name.equalsIgnoreCase(FIELD_TYPE_TAG)) {
581
                                // Do nothing
582
                        } else if (name.equalsIgnoreCase(FIELD_SUBTYPE_TAG)) {
583
                                // Do nothing
584
                        } else if (name.equalsIgnoreCase(FIELD_GROUP_TAG)) {
585
                                field.setGroup(value);
586

    
587
                        } else if (name.equalsIgnoreCase(FIELD_LABEL_TAG)) {
588
                                this.manager.setAttributeValue(field, "label", value);
589

    
590
                        } else if (name.equalsIgnoreCase(FIELD_ORDER_TAG)) {
591
                                field.setOrder(Integer.parseInt(value));
592

    
593
                        } else if (name.equalsIgnoreCase(FIELD_ISMANDATORY_TAG)) {
594
                                field.setMandatory(new Boolean(value).booleanValue());
595

    
596
                        } else if (name.equalsIgnoreCase(FIELD_ISPERSISTENT_TAG)) {
597
                                field.setPersistent(new Boolean(value).booleanValue());
598

    
599
                        } else if (name.equalsIgnoreCase(FIELD_HIDDEN_TAG)) {
600
                                field.setHidden(new Boolean(value).booleanValue());
601

    
602
                        } else if (name.equalsIgnoreCase(FIELD_MINVALUE_TAG)) {
603
                                field.setMinValue(value);
604

    
605
                        } else if (name.equalsIgnoreCase(FIELD_MAXVALUE_TAG)) {
606
                                field.setMaxValue(value);
607
                                
608
                        } else if (name.equalsIgnoreCase(FIELD_DEFAULTVALUE_TAG)) {
609
                                field.setDefaultFieldValue(value);
610

    
611
                        } else if (name.equalsIgnoreCase(FIELD_ELEMENTTYPE_TAG)) {
612
                                DynClass dynStruct = (DynClass) dynClasses.get(value);
613
                                if(dynStruct==null){
614
                                        dynStruct = this.manager.get(value);
615
                                }
616
                                if(dynStruct==null){
617
                                        LOG.warn("No se ha encontrado la dynClass '" + value + "'.");
618
                                        throw new IncompatibleAttributeValueException(parser,
619
                                                        FIELD_ELEMENTTYPE_TAG);
620
                                }
621
                                field.setElementsType(dynStruct);
622

    
623
                        } else if (name.equalsIgnoreCase(FIELD_STRUCTUSEDWHENISDYNOBJECT_TAG)) {
624
                                DynClass dynStruct = (DynClass) dynClasses.get(value);
625
                                if(dynStruct==null){
626
                                        dynStruct = this.manager.get(value);
627
                                }
628
                                if(dynStruct==null){
629
                                        LOG.warn("No se ha encontrado la dynClass '" + value + "'.");
630
                                        throw new IncompatibleAttributeValueException(parser,
631
                                                        FIELD_STRUCTUSEDWHENISDYNOBJECT_TAG);
632
                                }
633
                                field.setStructWhenTypeIsDynObject(dynStruct);
634

    
635
                        } else if (name.equalsIgnoreCase(FIELD_AVALILABLEVALUES_TAG)) {
636
                                // Do nothing
637

    
638
                        } else if (name.equalsIgnoreCase(FIELD_CLASSOFVALUE_TAG)) {
639
                                // Do nothing
640

    
641
                        } else if (name.equalsIgnoreCase(FIELD_CLASSOFITEMS_TAG)) {
642
                                // Do nothing
643

    
644
                        } else {
645
                                throw new UnexpectedTagOrAttributeException(parser, name);
646
                        }
647
                }
648

    
649
                try {
650
                        //
651
                        // Coerce the min/max/default/available values to the type of
652
                        // the field
653
                        //
654
                        if (availableValues != null && !availableValues.isEmpty()) {
655
                                for (int i = 0; i < availableValues.size(); i++) {
656
                                        PairValueLabel pair = (PairValueLabel) availableValues
657
                                                        .get(i);
658
                                        if (pair.label == null) {
659
                                                if (pair.value == null) {
660
                                                        pair.label = "null";
661
                                                } else {
662
                                                        pair.label = pair.value.toString();
663
                                                }
664
                                        }
665
                                        availableValues.set(i,
666
                                                        new DynObjectValueItem(field.coerce(pair.value),
667
                                                                        pair.label));
668
                                }
669
                                field.setAvailableValues(availableValues);
670
                        }
671
                        if (tagsValues != null && !tagsValues.isEmpty()) {
672
                                for (int i = 0; i < tagsValues.size(); i++) {
673
                                        PairValueLabel pair = (PairValueLabel) tagsValues.get(i);
674
                                        if (pair.label != null) {
675
                                                field.setTag(pair.label, pair.value);
676
                                        }
677
                                }
678
                        }                        
679
                        field.setMaxValue(field.coerce(values.get(FIELD_MAXVALUE_TAG)));
680
                        field.setMinValue(field.coerce(values.get(FIELD_MINVALUE_TAG)));
681
                        field.setDefaultFieldValue(field.coerce(values
682
                                        .get(FIELD_DEFAULTVALUE_TAG)));
683
                } catch (CoercionException e) {
684
                        throw new ParseCoerceException(e, parser);
685
                }
686
        }
687

    
688
        private class PairValueLabel {
689
                String label = null;
690
                String value = null;
691
        }
692

    
693
        private PairValueLabel importValueItem(XmlPullParser parser, String attributeName)
694
                        throws XmlPullParserException, IOException {
695
                PairValueLabel pair = new PairValueLabel();
696

    
697
                if (parser.getName().equalsIgnoreCase(VALUEITEM_TAG)) {
698
                        parser.require(XmlPullParser.START_TAG, null, VALUEITEM_TAG);
699
                        for (int i = 0; i < parser.getAttributeCount(); i++) {
700
                                String name = parser.getAttributeName(i);
701
                                if (name.equalsIgnoreCase(attributeName)) {
702
                                        pair.label = this.getAttributeValue(parser, i);
703
                                } else if (name.equalsIgnoreCase(VALUEITEM_VALUE_TAG)) {
704
                                        pair.value = this.getAttributeValue(parser, i);
705
                                } else {
706
                                        throw new UnexpectedTagOrAttributeException(parser, name);
707
                                }
708
                        }
709
                        parser.nextTag();
710

    
711
                        while (!(parser.getEventType() == XmlPullParser.END_TAG && parser
712
                                        .getName().equals(VALUEITEM_TAG))) {
713
                                checkEndDocument(parser);
714
                                parser.require(XmlPullParser.START_TAG, null, null);
715
                                String name = parser.getName();
716
                                if (name.equalsIgnoreCase(attributeName)) {
717
                                        pair.label = this.nextText(parser);
718
                                } else if (name.equalsIgnoreCase(VALUEITEM_VALUE_TAG)) {
719
                                        pair.value = this.nextText(parser);
720
                                } else {
721
                                        break;
722
                                }
723
                                parser.require(XmlPullParser.END_TAG, null, name);
724
                                parser.nextTag();
725
                        }
726
                        parser.require(XmlPullParser.END_TAG, null, VALUEITEM_TAG);
727
                } else {
728
                        parser.require(XmlPullParser.START_TAG, null, VALUEITEM_VALUE_TAG);
729
                        for (int i = 0; i < parser.getAttributeCount(); i++) {
730
                                String name = parser.getAttributeName(i);
731
                                if (name.equalsIgnoreCase(attributeName)) {
732
                                        pair.label = parser.getAttributeValue(i);
733
                                } else if (name.equalsIgnoreCase(VALUEITEM_VALUE_TAG)) {
734
                                        pair.value = this.getAttributeValue(parser, i);
735
                                } else {
736
                                        throw new UnexpectedTagOrAttributeException(parser, name);
737
                                }
738
                        }
739
                        if(pair.value == null){
740
                                pair.value = parser.nextText();
741
                        }else{
742
                                pair.value += parser.nextText();
743
                        }
744
                        parser.require(XmlPullParser.END_TAG, null, VALUEITEM_VALUE_TAG);
745
                }
746
                return pair;
747
        }
748

    
749
        private void checkEndDocument(XmlPullParser parser)
750
                        throws XmlPullParserException {
751
                if (parser.getEventType() == XmlPullParser.END_DOCUMENT) {
752
                        throw new UnexpectedTagOrAttributeException(parser,
753
                                        "(end-of-document)");
754
                }
755

    
756
        }
757

    
758
        public static abstract class ImportDynClassesException extends
759
                        BaseRuntimeException {
760

    
761
                /**
762
                 * 
763
                 */
764
                private static final long serialVersionUID = 3346283395112730192L;
765

    
766
                /**
767
                 * Don't call this constructor form subclasses.
768
                 * 
769
                 * @param parser
770
                 */
771
                public ImportDynClassesException(XmlPullParser parser) {
772
                        super(
773
                                        "Error importing classes from file at line %(line) column %(column).",
774
                                        "_Error_importing_classes_from_file_at_line_XlineX_column_XcolumnX",
775
                                        serialVersionUID);
776
                }
777

    
778
                protected ImportDynClassesException(XmlPullParser parser, String msg,
779
                                String key, long code) {
780
                        super(
781
                                        "Error importing classes from file at line %(line) column %(column). "
782
                                                        + msg, key, code);
783
                        this.setValue("line", new Integer(parser.getLineNumber()));
784
                        this.setValue("column", new Integer(parser.getColumnNumber()));
785
                }
786
        }
787

    
788
        public static class DuplicateDynClassException extends
789
                        ImportDynClassesException {
790
                /**
791
                 * 
792
                 */
793
                private static final long serialVersionUID = 3653024321140806121L;
794

    
795
                public DuplicateDynClassException(XmlPullParser parser, String name) {
796
                        super(parser, "Duplicate DynClass definition for '%(name)'.",
797
                                        "_Duplicate_DynClass_definition_for_XnameX",
798
                                        serialVersionUID);
799
                        this.setValue("name", name);
800
                }
801
        }
802

    
803
        public static class InvalidFieldTypeException extends
804
                        ImportDynClassesException {
805

    
806
                /**
807
                 * 
808
                 */
809
                private static final long serialVersionUID = 8501343258053356775L;
810

    
811
                public InvalidFieldTypeException(XmlPullParser parser, String value) {
812
                        super(parser, "Invalid field type '%(value)'.",
813
                                        "_Invalid_field_type_XvalueX", serialVersionUID);
814
                        this.setValue("value", value);
815
                }
816
        }
817

    
818
        public static class UnexpectedTagOrAttributeException extends
819
                        ImportDynClassesException {
820
                /**
821
                 * 
822
                 */
823
                private static final long serialVersionUID = -808282903423455613L;
824

    
825
                public UnexpectedTagOrAttributeException(XmlPullParser parser,
826
                                String tag) {
827
                        super(parser, "Unexpected tag or attribute '%(tag)'.",
828
                                        "_Unexpected_tag_or_attribute_XtagX", serialVersionUID);
829
                        this.setValue("tag", tag);
830
                }
831
        }
832

    
833
        public static class NeedTagOrAttributeException extends
834
                        ImportDynClassesException {
835
                /**
836
                 * 
837
                 */
838
                private static final long serialVersionUID = -808282903423455613L;
839

    
840
                public NeedTagOrAttributeException(XmlPullParser parser, String tag) {
841
                        super(parser, "Need tag or attribute '%(tag)'.",
842
                                        "_Need_tag_or_attribute_XtagX", serialVersionUID);
843
                        this.setValue("tag", tag);
844
                }
845
        }
846

    
847
        public static class CantLocateClassException extends
848
                        ImportDynClassesException {
849
                /**
850
                 * 
851
                 */
852
                private static final long serialVersionUID = 5733585544096433612L;
853

    
854
        public CantLocateClassException(XmlPullParser parser, String tagname) {
855
            super(parser, "Can't locate class named in attribute '%(name)'.",
856
                "_Cant_locate_class_XnameX", serialVersionUID);
857
            this.setValue("name", tagname);
858
        }
859

    
860
        public CantLocateClassException(XmlPullParser parser, String tagname,
861
            String className) {
862
            super(parser, "Can't locate class named in attribute '%(name)' "
863
                + "whose name is '%(className)'.", "_Cant_locate_class_XnameX",
864
                serialVersionUID);
865
            this.setValue("name", tagname);
866
            this.setValue("className", className);
867
        }
868
        }
869

    
870
        public static class CantLocateDynClassException extends
871
                        ImportDynClassesException {
872

    
873
                /**
874
                 * 
875
                 */
876
                private static final long serialVersionUID = 6286170415562358806L;
877

    
878
                public CantLocateDynClassException(XmlPullParser parser, String tagname) {
879
                        super(parser,
880
                                        "Can't locate DynClass '%(name). Look at the extends tag.",
881
                                        "_Cant_locate_DynClass_XnameX", serialVersionUID);
882
                        this.setValue("name", tagname);
883
                }
884
        }
885

    
886
        public static class IncompatibleAttributeValueException extends
887
                        ImportDynClassesException {
888
                /**
889
                 * 
890
                 */
891
                private static final long serialVersionUID = 2646530094487375049L;
892

    
893
                public IncompatibleAttributeValueException(XmlPullParser parser,
894
                                String name) {
895
            super(parser, "Incompatible attribute value for field '%(name)'.",
896
                                        "_Incompatible_attribute_value_for_field_XnameX",
897
                                        serialVersionUID);
898
                        this.setValue("name", name);
899
                }
900

    
901
        public IncompatibleAttributeValueException(XmlPullParser parser,
902
            String name, String value) {
903
            super(
904
                parser,
905
                "Incompatible attribute value '%(value)', for field '%(name)'.",
906
                "_Incompatible_attribute_value_for_field_XnameX",
907
                serialVersionUID);
908
            this.setValue("name", name);
909
            this.setValue("value", value);
910
        }
911
        }
912

    
913
        public static class ParseCoerceException extends ImportDynClassesException {
914

    
915
                /**
916
                 * 
917
                 */
918
                private static final long serialVersionUID = 1447718822981628834L;
919

    
920
                public ParseCoerceException(Throwable cause, XmlPullParser parser) {
921
                        super(parser, "Can't convert value.", "_Cant_convert_value",
922
                                        serialVersionUID);
923
                        this.initCause(cause);
924
                }
925
        }
926

    
927
        public static class WrongVersionException extends ImportDynClassesException {
928

    
929
                private static final long serialVersionUID = 6620589308398698367L;
930

    
931
                public WrongVersionException(XmlPullParser parser) {
932
                        super(parser, "Wrong format version.", "_Wrong_format_version",
933
                                        serialVersionUID);
934
                }
935
        }
936

    
937
}