Statistics
| Revision:

gvsig-tools / org.gvsig.tools / library / trunk / org.gvsig.tools / org.gvsig.tools.lib / src / main / java / org / gvsig / tools / dynobject / impl / DefaultDynField.java @ 1306

History | View | Annotate | Download (22.5 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.File;
27
import java.net.URI;
28
import java.net.URL;
29
import java.util.Collection;
30
import java.util.Date;
31
import java.util.Iterator;
32
import java.util.List;
33
import java.util.Map;
34
import java.util.Set;
35
import org.apache.commons.lang3.StringUtils;
36

    
37
import org.gvsig.tools.ToolsLocator;
38
import org.gvsig.tools.dataTypes.CoercionException;
39
import org.gvsig.tools.dataTypes.DataType;
40
import org.gvsig.tools.dataTypes.DataTypes;
41
import org.gvsig.tools.dataTypes.DataTypesManager;
42
import org.gvsig.tools.dynobject.DynClass;
43
import org.gvsig.tools.dynobject.DynField;
44
import org.gvsig.tools.dynobject.DynField_v2;
45
import org.gvsig.tools.dynobject.DynObject;
46
import org.gvsig.tools.dynobject.DynObjectValueItem;
47
import org.gvsig.tools.dynobject.DynStruct;
48
import org.gvsig.tools.dynobject.Tags;
49
import org.gvsig.tools.dynobject.exception.DynFieldIsNotAContainerException;
50
import org.gvsig.tools.dynobject.exception.DynFieldRequiredValueException;
51
import org.gvsig.tools.dynobject.exception.DynFieldValidateException;
52
import org.gvsig.tools.dynobject.exception.DynObjectValidateException;
53
import org.gvsig.tools.exception.ListBaseException;
54
import org.slf4j.Logger;
55
import org.slf4j.LoggerFactory;
56

    
57
public class DefaultDynField implements DynField_v2 {
58

    
59
    public static final Logger log = LoggerFactory.getLogger(DefaultDynField.class);
60

    
61
    private String name;
62
    private String description;
63

    
64
    private ValueType type;
65

    
66
    private String subtype;
67

    
68
    private Object defaultValue;
69

    
70
    private int order;
71
    private boolean hidden;
72
    private String groupName;
73
    private DynObjectValueItem[] availableValues;
74
    private Object minValue;
75
    private Object maxValue;
76
    private boolean mandatory;
77
    private boolean persistent;
78
    private String label = null;
79

    
80
    private boolean validateElements;
81
    private boolean isReadOnly;
82
    private final Tags tags = new DefaultTags();
83

    
84
    private ValueType itemsType;
85
    private boolean validateItems;
86

    
87
//        Para implementacion futura, como minimo para implementar
88
//        un copy entre dynobject y saber cuando parar.
89
//        Los valores deberan ser algo asi como:
90
//        - Identidad/Identity, 1:1 y se copian.
91
//        - Composicion/Composition, 1:N y se copian.
92
//        - Agregacion/Aggregate, 1:N, no se copian
93
//        - Colaboracion/Collaboration, 1:1, no se copian
94
//        Y solo tendra efecto/sentido cuando el field sea de tipo
95
//        DynObject, y tal vez lista de DynObject
96
    private int relationType;
97

    
98
    public DefaultDynField(String name, int dataType) {
99
        this(name, // field name
100
                dataType, // data type
101
                null, // default value
102
                true, // persistent
103
                false // mandatory
104
        );
105
    }
106

    
107
    protected DefaultDynField(String name, int dataType, Object defaultValue,
108
            boolean persistent, boolean mandatory) {
109
        DataTypesManager datamanager = ToolsLocator.getDataTypesManager();
110

    
111
        if ( StringUtils.isBlank(name) ) {
112
            throw new IllegalArgumentException("name can't be null");
113
        }
114
        this.name = name;
115
        this.type = new ValueType(dataType);
116
        this.subtype = this.getSubtype();
117

    
118
        this.defaultValue = defaultValue;
119
        this.persistent = persistent;
120
        this.mandatory = mandatory;
121
        this.validateElements = false;
122
        this.groupName = null;
123
        this.order = 0;
124
        this.hidden = false;
125
        this.availableValues = null;
126

    
127
        this.itemsType = new ValueType(DataTypes.UNKNOWN);
128
        this.validateItems = false;
129
        this.relationType = RELATION_TYPE_NONE;
130
    }
131

    
132
    protected ValueType getValueType() {
133
        return type;
134
    }
135

    
136
    public void check() throws ListBaseException {
137
    }
138

    
139
    @Override
140
    public String toString() {
141
        StringBuilder buffer = new StringBuilder();
142

    
143
        buffer.append("DynField").append("[").append(this.hashCode())
144
                .append("]").append("( ").append("name='").append(this.name)
145
                .append("', ").append("description='").append(this.description)
146
                .append("', ").append("type='").append(this.type)
147
                .append("', ").append("subType='").append(this.subtype)
148
                .append("', ").append("mandatory='").append(this.isMandatory())
149
                .append("', ").append("defaultValue='")
150
                .append(this.getDefaultValue()).append("', ")
151
                .append("minValue='").append(this.minValue).append("', ")
152
                .append("maxValue='").append(this.maxValue).append("', ")
153
                .append("persistent='").append(this.isPersistent())
154
                .append(" )");
155
        return buffer.toString();
156
    }
157

    
158
    @Override
159
    public String getName() {
160
        return name;
161
    }
162

    
163
    public DynField setName(String name) {
164
        if ( StringUtils.isBlank(name) ) {
165
            throw new IllegalArgumentException("name can't be null");
166
        }
167
        this.name = name;
168
        return this;
169
    }
170

    
171
    @Override
172
    public DynField setDescription(String description) {
173
        this.description = description;
174
        return this;
175
    }
176

    
177
    @Override
178
    public String getDescription() {
179
        return (description == null) ? getLabel() : description;
180
    }
181

    
182
    @Override
183
    public DynField setLabel(String label) {
184
        this.label = label;
185
        return this;
186
    }
187

    
188
    @Override
189
    public String getLabel() {
190
        return (label == null) ? getName() : label;
191
    }
192

    
193
    @Override
194
    public DynField setType(int dataType) {
195
        this.type.setType(dataType);
196
        return this;
197
    }
198

    
199
    @Override
200
    public DynField setType(DataType dataType) {
201
        this.type.setType(dataType);
202
        return this;
203
    }
204

    
205
    @Override
206
    public int getType() {
207
        return this.type.getType();
208
    }
209

    
210
    @Override
211
    public DataType getDataType() {
212
        return this.type.getDataType();
213
    }
214

    
215
    @Override
216
    public DynField setSubtype(String subtype) {
217
        this.subtype = subtype;
218
        return this;
219
    }
220

    
221
    @Override
222
    public String getSubtype() {
223
        return subtype;
224
    }
225

    
226
    @Override
227
    public DynField setDefaultDynValue(Object defaultValue) {
228
        this.defaultValue = defaultValue;
229
        return this;
230
    }
231

    
232
    @Override
233
    public Object getDefaultValue() {
234
        return defaultValue;
235
    }
236

    
237
    @Override
238
    public DynField setAvailableValues(DynObjectValueItem[] availableValues) {
239
        if ( availableValues == null || availableValues.length == 0 ) {
240
            this.availableValues = null;
241
        } else {
242
            this.availableValues = availableValues;
243
        }
244
        return this;
245
    }
246

    
247
    @Override
248
    public DynField setAvailableValues(List availableValues) {
249
        if ( availableValues == null ) {
250
            this.availableValues = null;
251
        } else if ( availableValues.isEmpty() ) {
252
            this.availableValues = null;
253
        } else {
254
            this.availableValues = (DynObjectValueItem[]) availableValues
255
                    .toArray(new DynObjectValueItem[availableValues.size()]);
256
        }
257
        return this;
258
    }
259

    
260
    @Override
261
    public DynObjectValueItem[] getAvailableValues() {
262
        return availableValues;
263
    }
264

    
265
    @Override
266
    public DynField setMinValue(Object minValue) {
267
        try {
268
            this.minValue = this.coerce(minValue);
269
        } catch (CoercionException e) {
270
            throw  new IllegalArgumentException();
271
        }
272
        return this;
273
    }
274

    
275
    @Override
276
    public Object getMinValue() {
277
        return minValue;
278
    }
279

    
280
    @Override
281
    public DynField setMaxValue(Object maxValue) {
282
        try {
283
            this.maxValue = this.coerce(maxValue);
284
        } catch (CoercionException e) {
285
            throw  new IllegalArgumentException(e);
286
        }
287
        return this;
288
    }
289

    
290
    @Override
291
    public Object getMaxValue() {
292
        return maxValue;
293
    }
294

    
295
    @Override
296
    public boolean isMandatory() {
297
        return this.mandatory;
298
    }
299

    
300
    @Override
301
    public boolean isPersistent() {
302
        return this.persistent;
303
    }
304

    
305
    @Override
306
    public DynField setMandatory(boolean mandatory) {
307
        this.mandatory = mandatory;
308
        return this;
309
    }
310

    
311
    @Override
312
    public DynField setPersistent(boolean persistent) {
313
        this.persistent = persistent;
314
        return this;
315
    }
316

    
317
    @Override
318
    public DynField setTheTypeOfAvailableValues(int type) {
319
        return this; // FIXME: this method is @deprecated
320
    }
321

    
322
    @Override
323
    public int getTheTypeOfAvailableValues() {
324
        return 1; // FIXME: this method is @deprecated
325
    }
326

    
327
    @Override
328
    public boolean equals(Object obj) {
329
        if ( this == obj ) {
330
            return true;
331
        }
332
        if ( obj instanceof DynField ) {
333
            // FIXME: No esta claro que esto sea correcto.
334
            return name.equals(((DynField) obj).getName());
335
        }
336
        return false;
337
    }
338

    
339
    @Override
340
    public Class getClassOfValue() {
341
        return this.type.getClassOfValue();
342
    }
343

    
344
    @Override
345
    public DynField setClassOfValue(Class theClass) {
346
        this.type.setClassOfValue(theClass);
347
        return this;
348
    }
349

    
350
    @Override
351
    public DynField setClassOfValue(String theClassName) {
352
        this.type.setClassOfValue(theClassName);
353
        return this;
354
    }
355

    
356
    @Override
357
    public boolean isContainer() {
358
        if ( type.getDataType() == null ) {
359
            return false;
360
        }
361
        return type.getDataType().isContainer();
362
    }
363

    
364
    @Override
365
    public void validate(Object value) throws DynFieldValidateException {
366
        Comparable v;
367
        if ( value == null ) {
368
            if ( this.mandatory ) {
369
                throw new DynFieldRequiredValueException(this, value);
370
            }
371
            return;
372
        }
373

    
374
        switch (this.type.getType()) {
375
        case DataTypes.BOOLEAN:
376
            if ( !(value instanceof Boolean) ) {
377
                throw new DynFieldValidateException(value, this);
378
            }
379
            break;
380

    
381
        case DataTypes.DOUBLE:
382
            if ( !(value instanceof Double) ) {
383
                throw new DynFieldValidateException(value, this);
384
            }
385
            break;
386

    
387
        case DataTypes.FLOAT:
388
            if ( !(value instanceof Float) ) {
389
                throw new DynFieldValidateException(value, this);
390
            }
391
            break;
392

    
393
        case DataTypes.BYTE:
394
            if ( !(value instanceof Byte) ) {
395
                throw new DynFieldValidateException(value, this);
396
            }
397
            break;
398

    
399
        case DataTypes.INT:
400
            if ( !(value instanceof Integer) ) {
401
                throw new DynFieldValidateException(value, this);
402
            }
403
            break;
404

    
405
        case DataTypes.LONG:
406
            if ( !(value instanceof Long) ) {
407
                throw new DynFieldValidateException(value, this);
408
            }
409
            break;
410

    
411
        case DataTypes.STRING:
412
            if ( !(value instanceof String) ) {
413
                throw new DynFieldValidateException(value, this);
414
            }
415
            break;
416

    
417
        case DataTypes.CHAR:
418
            if ( !(value instanceof String) ) {
419
                throw new DynFieldValidateException(value, this);
420
            }
421
            if ( ((String) value).length() > 1 ) {
422
                throw new DynFieldValidateException(value, this);
423
            }
424
            break;
425

    
426
        case DataTypes.DATE:
427
            if ( !(value instanceof Date) ) {
428
                throw new DynFieldValidateException(value, this);
429
            }
430
            break;
431

    
432
        case DataTypes.TIMESTAMP:
433
            if ( !(value instanceof Date) ) {
434
                throw new DynFieldValidateException(value, this);
435
            }
436
            break;
437

    
438
        case DataTypes.TIME:
439
            if ( !(value instanceof Date) ) {
440
                throw new DynFieldValidateException(value, this);
441
            }
442
            break;
443

    
444
        case DataTypes.FILE:
445
            if ( !(value instanceof File) ) {
446
                throw new DynFieldValidateException(value, this);
447
            }
448
            break;
449
        case DataTypes.FOLDER:
450
            if ( !(value instanceof File) ) {
451
                throw new DynFieldValidateException(value, this);
452
            }
453
            break;
454
        case DataTypes.URI:
455
            if ( !(value instanceof URI) ) {
456
                throw new DynFieldValidateException(value, this);
457
            }
458
            break;
459
        case DataTypes.URL:
460
            if ( !(value instanceof URL) ) {
461
                throw new DynFieldValidateException(value, this);
462
            }
463
            break;
464

    
465
        case DataTypes.ARRAY:
466
            // TODO: falta verificar que es un array del tipo que toca.
467
            break;
468

    
469
        case DataTypes.OBJECT:
470
            if ( this.type.getClassOfValue() != null ) {
471
                if ( !this.type.getClassOfValue().isInstance(value) ) {
472
                    throw new DynFieldValidateException(value, this);
473
                }
474
            }
475
            break;
476

    
477
        case DataTypes.MAP:
478
            if ( !(value instanceof Map) ) {
479
                throw new DynFieldValidateException(value, this);
480
            }
481
            validateCollection(value);
482
            break;
483

    
484
        case DataTypes.SET:
485
            if ( !(value instanceof Set) ) {
486
                throw new DynFieldValidateException(value, this);
487
            }
488
            validateCollection(value);
489
            break;
490

    
491
        case DataTypes.LIST:
492
            if ( !(value instanceof List) ) {
493
                throw new DynFieldValidateException(value, this);
494
            }
495
            validateCollection(value);
496
            break;
497

    
498
        case DataTypes.DYNOBJECT:
499
            if ( !(value instanceof DynObject) ) {
500
                throw new DynFieldValidateException(value, this);
501
            }
502
            if ( !this.getDynClassOfValue().isInstance((DynObject) value) ) {
503
                throw new DynFieldValidateException(value, this);
504
            }
505
            try {
506
                this.getDynClassOfValue().validate((DynObject) value);
507
            } catch (DynObjectValidateException e) {
508
                throw new DynFieldValidateException(value, this, e);
509
            }
510
            break;
511

    
512
        default:
513
            if ( this.type.getDataType().isObject() ) {
514
                if ( this.type.getClassOfValue() != null ) {
515
                    if ( !this.type.getClassOfValue().isInstance(value) ) {
516
                        throw new DynFieldValidateException(value, this);
517
                    }
518
                }
519
            }
520
        }
521

    
522
        if ( this.getAvailableValues() != null ) {
523
            if ( !(value instanceof Comparable) ) {
524
                throw new DynFieldValidateException(value, this);
525
            }
526
            v = (Comparable) value;
527
            boolean ok = false;
528
            for (DynObjectValueItem availableValue : this.availableValues) {
529
                if (v.compareTo(availableValue.getValue()) == 0) {
530
                    ok = true;
531
                    break;
532
                }
533
            }
534
            if ( !ok ) {
535
                throw new DynFieldValidateException(value, this);
536
            }
537
        } else if ( this.getMaxValue() != null && this.getMinValue() != null ) {
538
            if ( !(value instanceof Comparable) ) {
539
                throw new DynFieldValidateException(value, this);
540
            }
541
            v = (Comparable) value;
542
            if ( v.compareTo(this.minValue) < 0
543
                    || v.compareTo(this.maxValue) > 0 ) {
544
                throw new DynFieldValidateException(value, this);
545
            }
546
        }
547
    }
548

    
549
    private void validateCollection(Object value) throws ValidateItemException {
550
        if ( this.validateItems ) {
551
            DynStruct dynClass = this.itemsType.getDynClassOfValue();
552
            if ( dynClass != null ) {
553
                int index = 0;
554
                Iterator it = ((Collection) value).iterator();
555
                while ( it.hasNext() ) {
556
                    try {
557
                        dynClass.validate((DynObject) it.next());
558
                        index++;
559
                    } catch (DynObjectValidateException ex) {
560
                        throw new ValidateItemException(ex, index);
561
                    }
562
                }
563
            }
564
        }
565

    
566
    }
567

    
568
    private static class ValidateItemException extends DynFieldValidateException {
569

    
570
        private static final long serialVersionUID = 9011437364983996567L;
571

    
572
        ValidateItemException(Throwable cause, int index) {
573
            super(
574
                    "Can't validate item %(index) of the collection.",
575
                    cause,
576
                    "_Cant_validate_item_%(index)_of_the_collection",
577
                    serialVersionUID
578
            );
579
            setValue("index", new Integer(index));
580
        }
581
    }
582

    
583
    @Override
584
    public Object coerce(Object value) throws CoercionException {
585
        if ( value == null ) {
586
            return value; // O debe devolver this.defaultValue
587
        }
588
        try {
589
            return this.type.getDataType().coerce(value);
590
        } catch(Exception ex){
591
            throw new RuntimeException(ex);
592
        }
593
    }
594

    
595
    @Override
596
    public String getGroup() {
597
        return this.groupName;
598
    }
599

    
600
    @Override
601
    public DynField setGroup(String groupName) {
602
        this.groupName = groupName;
603
        return this;
604
    }
605

    
606
    @Override
607
    public int getOder() {
608
        return this.order;
609
    }
610

    
611
    @Override
612
    public DynField setOrder(int order) {
613
        this.order = order;
614
        return this;
615
    }
616

    
617
    @Override
618
    public boolean isHidden() {
619
        return this.hidden;
620
    }
621

    
622
    @Override
623
    public DynField setHidden(boolean hidden) {
624
        this.hidden = hidden;
625
        return this;
626
    }
627

    
628
    @Override
629
    public boolean isReadOnly() {
630
        return this.isReadOnly;
631
    }
632

    
633
    @Override
634
    public DynField setReadOnly(boolean isReadOnly) {
635
        this.isReadOnly = isReadOnly;
636
        return this;
637
    }
638

    
639
    @Override
640
    public DynField setDefaultFieldValue(Object defaultValue) {
641
        try {
642
            this.defaultValue = this.coerce(defaultValue);
643
        } catch (CoercionException e) {
644
            throw new IllegalArgumentException(e);
645
        }
646
        return this;
647
    }
648

    
649
    @Override
650
    public Tags getTags() {
651
        return tags;
652
    }
653

    
654
    @Override
655
    public String getClassNameOfValue() {
656
        return this.type.getClassNameOfValue();
657
    }
658

    
659
    @Override
660
    public DynField setClassOfValue(DynStruct dynStruct) {
661
        this.type.setClassOfValue(dynStruct);
662
        return this;
663
    }
664

    
665
    @Override
666
    public DynStruct getDynClassOfValue() {
667
        return this.type.getDynClassOfValue();
668
    }
669

    
670
    @Override
671
    public int getRelationType() {
672
        return this.relationType;
673
    }
674

    
675
    @Override
676
    public DynField setRelationType(int relationType) {
677
        this.relationType = relationType;
678
        return this;
679
    }
680

    
681
    @Override
682
    public DynField setElementsType(int type) {
683
        this.setTypeOfItems(type);
684
        return this;
685
    }
686

    
687
    @Override
688
    public DynField setElementsType(DynStruct type) {
689
        this.setClassOfItems(type);
690
        return this;
691
    }
692

    
693
    @Override
694
    public DynField getElementsType() {
695
        throw new UnsupportedOperationException("This operation is not suported nevermore.");
696
    }
697

    
698
    @Override
699
    public DynField setClassOfItems(DynStruct dynStrct) {
700
        if ( !this.isContainer() ) {
701
            throw new IllegalStateException("Can't assign validateElements in non container.");
702
        }
703
        this.itemsType.setClassOfValue(dynStrct);
704
        return this;
705
    }
706

    
707
    @Override
708
    public DynField setClassOfItems(String theClassNameOfValue) {
709
        if ( !this.isContainer() ) {
710
            throw new IllegalStateException("Can't assign validateElements in non container.");
711
        }
712
        this.itemsType.setClassOfValue(theClassNameOfValue);
713
        return this;
714
    }
715

    
716
    @Override
717
    public String getClassNameOfItems() {
718
        if ( !this.isContainer() ) {
719
            throw new IllegalStateException("Can't assign validateElements in non container.");
720
        }
721
        return this.itemsType.getClassNameOfValue();
722
    }
723

    
724
    @Override
725
    public DynStruct getDynClassOfItems() {
726
        if ( !this.isContainer() ) {
727
            throw new IllegalStateException("Can't assign validateElements in non container.");
728
        }
729
        return this.itemsType.getDynClassOfValue();
730
    }
731

    
732
    @Override
733
    public DynField setClassOfItems(Class theClass)
734
            throws DynFieldIsNotAContainerException {
735
        if ( !this.isContainer() ) {
736
            throw new IllegalStateException("Can't assign validateElements in non container.");
737
        }
738
        this.itemsType.setClassOfValue(theClass);
739
        return this;
740
    }
741

    
742
    @Override
743
    public Class getClassOfItems() {
744
        if ( !this.isContainer() ) {
745
            throw new IllegalStateException("Can't assign validateElements in non container.");
746
        }
747
        return this.itemsType.getClassOfValue();
748
    }
749

    
750
    @Override
751
    public DynField setTypeOfItems(int type) {
752
        if ( !this.isContainer() ) {
753
            throw new IllegalStateException("Can't assign validateElements in non container.");
754
        }
755
        this.itemsType.setType(type);
756
        return this;
757
    }
758

    
759
    @Override
760
    public int getTypeOfItems() {
761
        if ( !this.isContainer() ) {
762
            throw new IllegalStateException("Can't assign validateElements in non container.");
763
        }
764
        return this.itemsType.getType();
765
    }
766

    
767
    public DynField setValidateElements(boolean validate) {
768
        if ( !this.isContainer() ) {
769
            throw new IllegalStateException("Can't assign validateElements in non container.");
770
        }
771
        this.validateItems = validate;
772
        return this;
773
    }
774

    
775
    public boolean getValidateElements() {
776
        if ( !this.isContainer() ) {
777
            throw new IllegalStateException("Can't assign validateElements in non container.");
778
        }
779
        return this.validateItems;
780
    }
781

    
782
}