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

History | View | Annotate | Download (37.7 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.LinkedHashMap;
32
import java.util.List;
33
import java.util.Map;
34

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

    
54
public class DynClassImportHelper {
55

    
56
    private static final Logger LOG = LoggerFactory
57
            .getLogger(DynClassImportHelper.class);
58

    
59
    private static final String VERSION_VALUE = "1.0.0";
60

    
61
    private static final String DEFINITIONS_TAG = "definitions";
62
    private static final String VERSION_TAG = "version";
63
    private static final String CLASSES_TAG = "classes";
64

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

    
75
    private static final String FIELD_TAG = "field";
76
    private static final String FIELD_NAME_TAG = "name";
77
    private static final String FIELD_DESCRIPTION_TAG = "description";
78
    private static final String FIELD_SUBTYPE_TAG = "subtype";
79
    private static final String FIELD_TYPE_TAG = "type";
80
    private static final String FIELD_ISMANDATORY_TAG = "mandatory";
81
    private static final String FIELD_ISPERSISTENT_TAG = "persistent";
82
    private static final String FIELD_MINVALUE_TAG = "minValue";
83
    private static final String FIELD_MAXVALUE_TAG = "maxValue";
84

    
85
    private static final String FIELD_CLASSOFVALUE_TAG = "classOfValue";
86
    private static final String FIELD_CLASSOFITEMS_TAG = "classOfItems";
87
    private static final String FIELD_TYPEOFITEMS_TAG = "typeOfItems";
88

    
89
    private static final String FIELD_DEFAULTVALUE_TAG = "defaultValue";
90
    private static final String FIELD_AVALILABLEVALUES_TAG = "availableValues";
91
    private static final String FIELD_GROUP_TAG = "group";
92
    private static final String FIELD_ORDER_TAG = "order";
93
    private static final String FIELD_HIDDEN_TAG = "hidden";
94
    private static final String FIELD_LABEL_TAG = "label";
95
    private static final String FIELD_TAGS_TAG = "tags";
96
    private static final String VALUEITEM_TAGNAME_TAG = "name";
97

    
98
    private static final String VALUEITEM_TAG = "valueItem";
99
    private static final String VALUEITEM_LABEL_TAG = "label";
100
    private static final String VALUEITEM_VALUE_TAG = "value";
101

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

    
104
    private Map dynClasses = null;
105

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

    
114
    }
115

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

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

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

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

    
133
        XmlPullParser parser = factory.newPullParser();
134

    
135
        parser.setInput(resource, null);
136

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

    
140
    private class Definitions extends HashMap implements Map {
141

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
309
            } else if ( tagName.equalsIgnoreCase(CLASS_EXTENDS_TAG) ) {
310
                parser.nextTag();
311
                while ( !(parser.getEventType() == XmlPullParser.END_TAG && parser
312
                        .getName().equals(CLASS_EXTENDS_TAG)) ) {
313
                    checkEndDocument(parser);
314
                    superClasses
315
                            .add(importSuperClass(parser, defaultNamespace));
316
                    parser.nextTag();
317
                }
318

    
319
            } else if ( tagName.equalsIgnoreCase(FIELD_TAGS_TAG) ) {
320
                parser.nextTag();
321
                tagsValues = new ArrayList();
322
                while ( !(parser.getEventType() == XmlPullParser.END_TAG && parser
323
                        .getName().equals(FIELD_TAGS_TAG)) ) {
324
                    checkEndDocument(parser);
325
                    tagsValues.add(importValueItem(parser, VALUEITEM_TAGNAME_TAG));
326
                    parser.nextTag();
327
                }
328

    
329
            } else {
330
                break;
331
            }
332
            parser.require(XmlPullParser.END_TAG, null, tagName);
333
            parser.nextTag();
334
        }
335
        parser.require(XmlPullParser.START_TAG, null, CLASS_FIELDS_TAG);
336
        parser.nextTag();
337

    
338
        //
339
        // Create dynclass
340
        //
341
        if ( values.get(CLASS_NAME_TAG) == null ) {
342
            throw new NeedTagOrAttributeException(parser, CLASS_NAME_TAG);
343
        }
344
        if ( values.get(CLASS_NAMESPACE_TAG) == null ) {
345
            values.put(CLASS_NAMESPACE_TAG, defaultNamespace);
346
        }
347
        dynClass = manager.createDynClass(
348
                (String) values.get(CLASS_NAMESPACE_TAG),
349
                (String) values.get(CLASS_NAME_TAG),
350
                (String) values.get(CLASS_DESCRIPTION_TAG));
351
        for ( int i = 0; i < superClasses.size(); i++ ) {
352
            DynClassName superClass = (DynClassName) superClasses.get(i);
353
            if ( superClass.getName() == null ) {
354
                throw new NeedTagOrAttributeException(parser, CLASS_NAME_TAG);
355
            }
356
            DynClass superDynClass = (DynClass) classes.get(superClass
357
                    .getFullName());
358
            if ( superDynClass == null ) {
359
                superDynClass = ToolsLocator.getDynObjectManager().get(
360
                        superClass.getNamespace(), superClass.getName());
361
                if ( superDynClass == null ) {
362
                    throw new CantLocateDynClassException(parser,
363
                            superClass.getFullName());
364
                }
365
            }
366
            dynClass.extend(superDynClass);
367
        }
368
        if ( tagsValues != null && !tagsValues.isEmpty() ) {
369
            if ( dynClass instanceof DynClass_v2 ) {
370
                for ( int i = 0; i < tagsValues.size(); i++ ) {
371
                    PairValueLabel pair = (PairValueLabel) tagsValues.get(i);
372
                    if ( pair.label != null ) {
373
                        ((DynClass_v2) dynClass).getTags().set(pair.label, pair.value);
374
                    }
375
                }
376
            }
377
        }
378
        //
379
        // Parse and load fields of dynclass
380
        //
381
        while ( !(parser.getEventType() == XmlPullParser.END_TAG && parser
382
                .getName().equals(CLASS_FIELDS_TAG)) ) {
383
            checkEndDocument(parser);
384
            importDynField(parser, (DynClass_v2) dynClass, loader);
385
            parser.nextTag();
386
        }
387
        parser.require(XmlPullParser.END_TAG, null, CLASS_FIELDS_TAG);
388
        parser.nextTag();
389

    
390
        parser.require(XmlPullParser.END_TAG, null, CLASS_TAG);
391
        parser.nextTag();
392
        return dynClass;
393
    }
394

    
395
    private DynClassName importSuperClass(XmlPullParser parser,
396
            String defaultNamespace) throws XmlPullParserException, IOException {
397

    
398
        String name = null;
399
        String namespace = defaultNamespace;
400

    
401
        parser.require(XmlPullParser.START_TAG, null, CLASS_EXTENDS_CLASS_TAG);
402
        for ( int i = 0; i < parser.getAttributeCount(); i++ ) {
403
            String attrname = parser.getAttributeName(i);
404
            if ( attrname.equalsIgnoreCase(CLASS_NAME_TAG) ) {
405
                name = this.getAttributeValue(parser, i);
406
            } else if ( attrname.equalsIgnoreCase(CLASS_NAMESPACE_TAG) ) {
407
                namespace = this.getAttributeValue(parser, i);
408
            } else {
409
                throw new UnexpectedTagOrAttributeException(parser, attrname);
410
            }
411
        }
412
        if ( name == null ) {
413
            name = this.nextText(parser);
414
        } else {
415
            parser.nextTag();
416
        }
417
        parser.require(XmlPullParser.END_TAG, null, CLASS_EXTENDS_CLASS_TAG);
418
        DynClassName dynClassName = manager.createDynClassName(namespace, name);
419
        return dynClassName;
420
    }
421

    
422
    private void importDynField(XmlPullParser parser, DynClass_v2 dynClass,
423
            ClassLoader loader) throws XmlPullParserException, IOException {
424
        DynField_v2 field;
425
        List availableValues = null;
426
        List tagsValues = null;
427
        Map values = new LinkedHashMap();
428

    
429
        parser.require(XmlPullParser.START_TAG, null, FIELD_TAG);
430
        //
431
        // Collect field attributes from tag attributes
432
        //
433
        for ( int i = 0; i < parser.getAttributeCount(); i++ ) {
434
            values.put(parser.getAttributeName(i),
435
                    this.getAttributeValue(parser, i));
436
        }
437
        parser.nextTag();
438

    
439
        //
440
        // Collect field attributes from tags
441
        //
442
        while ( !(parser.getEventType() == XmlPullParser.END_TAG && parser
443
                .getName().equals(FIELD_TAG)) ) {
444
            checkEndDocument(parser);
445

    
446
            parser.require(XmlPullParser.START_TAG, null, null);
447
            String name = parser.getName();
448
            if ( name.equalsIgnoreCase(FIELD_NAME_TAG) ) {
449
                values.put(FIELD_NAME_TAG, this.nextText(parser));
450

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

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

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

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

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

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

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

    
472
            } else if ( name.equalsIgnoreCase(FIELD_ISPERSISTENT_TAG) ) {
473
                values.put(FIELD_ISPERSISTENT_TAG, this.nextText(parser));
474

    
475
            } else if ( name.equalsIgnoreCase(FIELD_MINVALUE_TAG) ) {
476
                values.put(FIELD_MINVALUE_TAG, this.nextText(parser));
477

    
478
            } else if ( name.equalsIgnoreCase(FIELD_MAXVALUE_TAG) ) {
479
                values.put(FIELD_MAXVALUE_TAG, this.nextText(parser));
480

    
481
            } else if ( name.equalsIgnoreCase(FIELD_CLASSOFVALUE_TAG) ) {
482
                values.put(FIELD_CLASSOFVALUE_TAG, this.nextText(parser));
483

    
484
            } else if ( name.equalsIgnoreCase(FIELD_CLASSOFITEMS_TAG) ) {
485
                values.put(FIELD_CLASSOFITEMS_TAG, this.nextText(parser));
486

    
487
            } else if ( name.equalsIgnoreCase(FIELD_DEFAULTVALUE_TAG) ) {
488
                values.put(FIELD_DEFAULTVALUE_TAG, this.nextText(parser));
489

    
490
            } else if ( name.equalsIgnoreCase(FIELD_HIDDEN_TAG) ) {
491
                values.put(FIELD_HIDDEN_TAG, this.nextText(parser));
492

    
493
            } else if ( name.equalsIgnoreCase(FIELD_AVALILABLEVALUES_TAG) ) {
494
                parser.nextTag();
495
                availableValues = new ArrayList();
496
                while ( !(parser.getEventType() == XmlPullParser.END_TAG && parser
497
                        .getName().equals(FIELD_AVALILABLEVALUES_TAG)) ) {
498
                    checkEndDocument(parser);
499
                    availableValues.add(importValueItem(parser, VALUEITEM_LABEL_TAG));
500
                    parser.nextTag();
501
                }
502

    
503
            } else if ( name.equalsIgnoreCase(FIELD_TAGS_TAG) ) {
504
                parser.nextTag();
505
                tagsValues = new ArrayList();
506
                while ( !(parser.getEventType() == XmlPullParser.END_TAG && parser
507
                        .getName().equals(FIELD_TAGS_TAG)) ) {
508
                    checkEndDocument(parser);
509
                    tagsValues.add(importValueItem(parser, VALUEITEM_TAGNAME_TAG));
510
                    parser.nextTag();
511
                }
512

    
513
            } else {
514
                break;
515
            }
516
            parser.require(XmlPullParser.END_TAG, null, name);
517
            parser.nextTag();
518
        }
519
        parser.require(XmlPullParser.END_TAG, null, FIELD_TAG);
520

    
521
        if ( values.get(FIELD_NAME_TAG) == null ) {
522
            throw new NeedTagOrAttributeException(parser, FIELD_NAME_TAG);
523
        }
524

    
525
        
526

    
527
        //
528
        // Get type and subtype first
529
        //
530
        String name = FIELD_TYPE_TAG;
531
        String value = (String) values.get(name);
532
        if ( value == null ) {
533
            throw new InvalidFieldTypeException(parser, value);
534
        }
535
        int type = ToolsLocator.getDataTypesManager().getType(value);
536
        if ( type == DataTypes.INVALID ) {
537
            throw new InvalidFieldTypeException(parser, value);
538
        }
539
        //
540
        // Create the field
541
        //
542
        field = (DynField_v2) dynClass.addDynField((String) values.get(FIELD_NAME_TAG),type);
543

    
544
        //
545
        // Load other values in the field
546
        //
547
        Iterator names = values.keySet().iterator();
548
        while ( names.hasNext() ) {
549
            name = (String) names.next();
550
            value = (String) values.get(name);
551
            if ( value == null ) {
552
                continue;
553
            }
554
            if ( name.equalsIgnoreCase(FIELD_NAME_TAG) ) {
555
                // Do nothing
556

    
557
            } else if ( name.equalsIgnoreCase(FIELD_DESCRIPTION_TAG) ) {
558
                field.setDescription(value);
559

    
560
            } else if ( name.equalsIgnoreCase(FIELD_TYPE_TAG) ) {
561
                // Do nothing
562
            } else if ( name.equalsIgnoreCase(FIELD_SUBTYPE_TAG) ) {
563
                field.setSubtype(value);
564
                
565
            } else if ( name.equalsIgnoreCase(FIELD_GROUP_TAG) ) {
566
                field.setGroup(value);
567

    
568
            } else if ( name.equalsIgnoreCase(FIELD_LABEL_TAG) ) {
569
                this.manager.setAttributeValue(field, "label", value);
570

    
571
            } else if ( name.equalsIgnoreCase(FIELD_ORDER_TAG) ) {
572
                field.setOrder(Integer.parseInt(value));
573

    
574
            } else if ( name.equalsIgnoreCase(FIELD_ISMANDATORY_TAG) ) {
575
                field.setMandatory(new Boolean(value).booleanValue());
576

    
577
            } else if ( name.equalsIgnoreCase(FIELD_ISPERSISTENT_TAG) ) {
578
                field.setPersistent(new Boolean(value).booleanValue());
579

    
580
            } else if ( name.equalsIgnoreCase(FIELD_HIDDEN_TAG) ) {
581
                field.setHidden(new Boolean(value).booleanValue());
582

    
583
            } else if ( name.equalsIgnoreCase(FIELD_MINVALUE_TAG) ) {
584
                field.setMinValue(value);
585

    
586
            } else if ( name.equalsIgnoreCase(FIELD_MAXVALUE_TAG) ) {
587
                field.setMaxValue(value);
588

    
589
            } else if ( name.equalsIgnoreCase(FIELD_DEFAULTVALUE_TAG) ) {
590
                field.setDefaultFieldValue(value);
591

    
592
            } else if ( name.equalsIgnoreCase(FIELD_TYPEOFITEMS_TAG) ) {
593
                int typeOfItems = ToolsLocator.getDataTypesManager().getType(value);
594
                if ( typeOfItems == DataTypes.INVALID ) {
595
                    throw new InvalidFieldTypeException(parser, value);
596
                }
597
                field.setTypeOfItems(typeOfItems);
598

    
599
            } else if ( name.equalsIgnoreCase(FIELD_CLASSOFITEMS_TAG) ) {
600
                if( field.getTypeOfItems()==DataTypes.DYNOBJECT ) {
601
                    DynClass dynStruct = (DynClass) dynClasses.get(value);
602
                    if ( dynStruct == null ) {
603
                        // Try to search in registered DynClasses
604
                        field.setClassOfItems(value);
605
                    } else {
606
                        field.setClassOfItems(dynStruct);
607
                    }
608
                } else {
609
                    try {
610
                        Class klass;
611
                        klass = Class.forName(value, true, loader);
612
                        field.setClassOfItems(klass);
613
                    } catch (DynFieldIsNotAContainerException e) {
614
                        LOG.warn("No se ha encontrado la clase '" + value + "'.", e);
615
                        throw new IncompatibleAttributeValueException(parser,
616
                                FIELD_NAME_TAG);
617
                    } catch (ClassNotFoundException e) {
618
                        LOG.warn("No se ha encontrado la clase '" + value + "'.", e);
619
                        throw new CantLocateClassException(parser, FIELD_CLASSOFITEMS_TAG, value);
620
                    }
621
                }
622

    
623
            } else if ( name.equalsIgnoreCase(FIELD_CLASSOFVALUE_TAG) ) {
624
                if( field.getType()==DataTypes.DYNOBJECT ) {
625
                    DynClass dynStruct = (DynClass) dynClasses.get(value);
626
                    if ( dynStruct == null ) {
627
                        // Try to search in registered DynClasses
628
                        field.setClassOfValue(value);
629
                    } else {
630
                        field.setClassOfValue(dynStruct);
631
                    }
632
                } else {
633
                    try {
634
                        Class klass;
635
                        klass = Class.forName(value, true, loader);
636
                        field.setClassOfValue(klass);
637
                    } catch (DynFieldIsNotAContainerException e) {
638
                        LOG.warn("No se ha encontrado la clase '" + value + "'.", e);
639
                        throw new IncompatibleAttributeValueException(parser,
640
                                FIELD_NAME_TAG);
641
                    } catch (ClassNotFoundException e) {
642
                        LOG.warn("No se ha encontrado la clase '" + value + "'.", e);
643
                        throw new CantLocateClassException(parser, FIELD_CLASSOFVALUE_TAG, value);
644
                    }
645
                }
646

    
647
            } else if ( name.equalsIgnoreCase(FIELD_AVALILABLEVALUES_TAG) ) {
648
                // Do nothing
649

    
650
            } else {
651
                throw new UnexpectedTagOrAttributeException(parser, name);
652
            }
653
        }
654

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

    
694
    private class PairValueLabel {
695

    
696
        String label = null;
697
        String value = null;
698
    }
699

    
700
    private PairValueLabel importValueItem(XmlPullParser parser, String attributeName)
701
            throws XmlPullParserException, IOException {
702
        PairValueLabel pair = new PairValueLabel();
703

    
704
        if ( parser.getName().equalsIgnoreCase(VALUEITEM_TAG) ) {
705
            parser.require(XmlPullParser.START_TAG, null, VALUEITEM_TAG);
706
            for ( int i = 0; i < parser.getAttributeCount(); i++ ) {
707
                String name = parser.getAttributeName(i);
708
                if ( name.equalsIgnoreCase(attributeName) ) {
709
                    pair.label = this.getAttributeValue(parser, i);
710
                } else if ( name.equalsIgnoreCase(VALUEITEM_VALUE_TAG) ) {
711
                    pair.value = this.getAttributeValue(parser, i);
712
                } else {
713
                    throw new UnexpectedTagOrAttributeException(parser, name);
714
                }
715
            }
716
            parser.nextTag();
717

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

    
756
    private void checkEndDocument(XmlPullParser parser)
757
            throws XmlPullParserException {
758
        if ( parser.getEventType() == XmlPullParser.END_DOCUMENT ) {
759
            throw new UnexpectedTagOrAttributeException(parser,
760
                    "(end-of-document)");
761
        }
762

    
763
    }
764

    
765
    public static abstract class ImportDynClassesException extends
766
            BaseRuntimeException {
767

    
768
        /**
769
         *
770
         */
771
        private static final long serialVersionUID = 3346283395112730192L;
772

    
773
        /**
774
         * Don't call this constructor form subclasses.
775
         *
776
         * @param parser
777
         */
778
        public ImportDynClassesException(XmlPullParser parser) {
779
            super(
780
                    "Error importing classes from file at line %(line) column %(column).",
781
                    "_Error_importing_classes_from_file_at_line_XlineX_column_XcolumnX",
782
                    serialVersionUID);
783
        }
784

    
785
        protected ImportDynClassesException(XmlPullParser parser, String msg,
786
                String key, long code) {
787
            super(
788
                    "Error importing classes from file at line %(line) column %(column). "
789
                    + msg, key, code);
790
            this.setValue("line", new Integer(parser.getLineNumber()));
791
            this.setValue("column", new Integer(parser.getColumnNumber()));
792
        }
793
    }
794

    
795
    public static class DuplicateDynClassException extends
796
            ImportDynClassesException {
797

    
798
        /**
799
         *
800
         */
801
        private static final long serialVersionUID = 3653024321140806121L;
802

    
803
        public DuplicateDynClassException(XmlPullParser parser, String name) {
804
            super(parser, "Duplicate DynClass definition for '%(name)'.",
805
                    "_Duplicate_DynClass_definition_for_XnameX",
806
                    serialVersionUID);
807
            this.setValue("name", name);
808
        }
809
    }
810

    
811
    public static class InvalidFieldTypeException extends
812
            ImportDynClassesException {
813

    
814
        /**
815
         *
816
         */
817
        private static final long serialVersionUID = 8501343258053356775L;
818

    
819
        public InvalidFieldTypeException(XmlPullParser parser, String value) {
820
            super(parser, "Invalid field type '%(value)'.",
821
                    "_Invalid_field_type_XvalueX", serialVersionUID);
822
            this.setValue("value", value);
823
        }
824
    }
825

    
826
    public static class UnexpectedTagOrAttributeException extends
827
            ImportDynClassesException {
828

    
829
        /**
830
         *
831
         */
832
        private static final long serialVersionUID = -808282903423455613L;
833

    
834
        public UnexpectedTagOrAttributeException(XmlPullParser parser,
835
                String tag) {
836
            super(parser, "Unexpected tag or attribute '%(tag)'.",
837
                    "_Unexpected_tag_or_attribute_XtagX", serialVersionUID);
838
            this.setValue("tag", tag);
839
        }
840
    }
841

    
842
    public static class NeedTagOrAttributeException extends
843
            ImportDynClassesException {
844

    
845
        /**
846
         *
847
         */
848
        private static final long serialVersionUID = -808282903423455613L;
849

    
850
        public NeedTagOrAttributeException(XmlPullParser parser, String tag) {
851
            super(parser, "Need tag or attribute '%(tag)'.",
852
                    "_Need_tag_or_attribute_XtagX", serialVersionUID);
853
            this.setValue("tag", tag);
854
        }
855
    }
856

    
857
    public static class CantLocateClassException extends
858
            ImportDynClassesException {
859

    
860
        /**
861
         *
862
         */
863
        private static final long serialVersionUID = 5733585544096433612L;
864

    
865
        public CantLocateClassException(XmlPullParser parser, String tagname) {
866
            super(parser, "Can't locate class named in attribute '%(name)'.",
867
                    "_Cant_locate_class_XnameX", serialVersionUID);
868
            this.setValue("name", tagname);
869
        }
870

    
871
        public CantLocateClassException(XmlPullParser parser, String tagname,
872
                String className) {
873
            super(parser, "Can't locate class named in attribute '%(name)' "
874
                    + "whose name is '%(className)'.", "_Cant_locate_class_XnameX",
875
                    serialVersionUID);
876
            this.setValue("name", tagname);
877
            this.setValue("className", className);
878
        }
879
    }
880

    
881
    public static class CantLocateDynClassException extends
882
            ImportDynClassesException {
883

    
884
        /**
885
         *
886
         */
887
        private static final long serialVersionUID = 6286170415562358806L;
888

    
889
        public CantLocateDynClassException(XmlPullParser parser, String tagname) {
890
            super(parser,
891
                    "Can't locate DynClass '%(name). Look at the extends tag.",
892
                    "_Cant_locate_DynClass_XnameX", serialVersionUID);
893
            this.setValue("name", tagname);
894
        }
895
    }
896

    
897
    public static class IncompatibleAttributeValueException extends
898
            ImportDynClassesException {
899

    
900
        /**
901
         *
902
         */
903
        private static final long serialVersionUID = 2646530094487375049L;
904

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

    
913
        public IncompatibleAttributeValueException(XmlPullParser parser,
914
                String name, String value) {
915
            super(
916
                    parser,
917
                    "Incompatible attribute value '%(value)', for field '%(name)'.",
918
                    "_Incompatible_attribute_value_for_field_XnameX",
919
                    serialVersionUID);
920
            this.setValue("name", name);
921
            this.setValue("value", value);
922
        }
923
    }
924

    
925
    public static class ParseCoerceException extends ImportDynClassesException {
926

    
927
        /**
928
         *
929
         */
930
        private static final long serialVersionUID = 1447718822981628834L;
931

    
932
        public ParseCoerceException(Throwable cause, XmlPullParser parser) {
933
            super(parser, "Can't convert value.", "_Cant_convert_value",
934
                    serialVersionUID);
935
            this.initCause(cause);
936
        }
937
    }
938

    
939
    public static class WrongVersionException extends ImportDynClassesException {
940

    
941
        private static final long serialVersionUID = 6620589308398698367L;
942

    
943
        public WrongVersionException(XmlPullParser parser) {
944
            super(parser, "Wrong format version.", "_Wrong_format_version",
945
                    serialVersionUID);
946
        }
947
    }
948

    
949
}