Statistics
| Revision:

svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.compat.cdc / org.gvsig.fmap.dal / org.gvsig.fmap.dal.impl / src / main / java / org / gvsig / fmap / dal / feature / impl / DefaultFeatureAttributeDescriptor.java @ 44202

History | View | Annotate | Download (37.1 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 modify it under
7
 * the terms of the GNU General Public License as published by the Free Software
8
 * Foundation; either version 3 of the License, or (at your option) any later
9
 * version.
10
 *
11
 * This program is distributed in the hope that it will be useful, but WITHOUT
12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
14
 * details.
15
 *
16
 * You should have received a copy of the GNU General Public License along with
17
 * this program; if not, write to the Free Software Foundation, Inc., 51
18
 * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19
 *
20
 * For any additional information, do not hesitate to contact us at info AT
21
 * gvsig.com, or visit our website www.gvsig.com.
22
 */
23
package org.gvsig.fmap.dal.feature.impl;
24

    
25
import java.lang.ref.WeakReference;
26
import java.text.DateFormat;
27
import java.util.HashMap;
28
import java.util.Iterator;
29
import java.util.List;
30
import java.util.Map;
31
import java.util.Map.Entry;
32
import java.util.Objects;
33
import org.apache.commons.lang3.ArrayUtils;
34
import org.apache.commons.lang3.StringUtils;
35
import org.cresques.cts.IProjection;
36
import org.gvsig.fmap.dal.DataStore;
37
import org.gvsig.fmap.dal.DataTypes;
38
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
39
import org.gvsig.fmap.dal.feature.FeatureAttributeEmulator;
40
import org.gvsig.fmap.dal.feature.FeatureAttributeGetter;
41
import org.gvsig.fmap.dal.feature.FeatureStore;
42
import org.gvsig.fmap.dal.feature.FeatureType;
43
import org.gvsig.fmap.geom.Geometry;
44
import org.gvsig.fmap.geom.GeometryException;
45
import org.gvsig.fmap.geom.GeometryLocator;
46
import org.gvsig.fmap.geom.GeometryUtils;
47
import org.gvsig.fmap.geom.type.GeometryType;
48
import org.gvsig.timesupport.Interval;
49
import org.gvsig.timesupport.RelativeInterval;
50
import org.gvsig.timesupport.TimeSupportLocator;
51
import org.gvsig.tools.ToolsLocator;
52
import org.gvsig.tools.dataTypes.CoercionException;
53
import org.gvsig.tools.dataTypes.DataType;
54
import org.gvsig.tools.dynobject.DynField;
55
import org.gvsig.tools.dynobject.DynField_LabelAttribute;
56
import org.gvsig.tools.dynobject.DynField_v2;
57
import org.gvsig.tools.dynobject.DynMethod;
58
import org.gvsig.tools.dynobject.DynObject;
59
import org.gvsig.tools.dynobject.DynObjectValueItem;
60
import org.gvsig.tools.dynobject.DynStruct;
61
import org.gvsig.tools.dynobject.Tags;
62
import org.gvsig.tools.dynobject.exception.DynFieldIsNotAContainerException;
63
import org.gvsig.tools.dynobject.exception.DynFieldValidateException;
64
import org.gvsig.tools.dynobject.exception.DynMethodException;
65
import org.gvsig.tools.dynobject.impl.DefaultTags;
66
import org.gvsig.tools.evaluator.AbstractEvaluator;
67
import org.gvsig.tools.evaluator.Evaluator;
68
import org.gvsig.tools.evaluator.EvaluatorData;
69
import org.gvsig.tools.evaluator.EvaluatorException;
70
import org.gvsig.tools.persistence.PersistenceManager;
71
import org.gvsig.tools.persistence.Persistent;
72
import org.gvsig.tools.persistence.PersistentState;
73
import org.gvsig.tools.persistence.exception.PersistenceException;
74
import org.slf4j.Logger;
75
import org.slf4j.LoggerFactory;
76

    
77
public class DefaultFeatureAttributeDescriptor implements
78
        FeatureAttributeDescriptor, Persistent, DynField_v2, DynField_LabelAttribute {
79

    
80
    protected static final Logger LOGGER = LoggerFactory.getLogger(DefaultFeatureAttributeDescriptor.class);
81
    
82
    protected boolean allowNull;
83
    protected DataType dataType;
84
    protected String dataProfile; 
85
    protected DateFormat dateFormat;
86
    protected Object defaultValue;
87
    protected int index;
88
    protected int maximumOccurrences;
89
    protected int minimumOccurrences;
90
    protected int size;
91
    protected String name;
92
    protected Class objectClass;
93
    protected int precision;
94
    protected Evaluator evaluator;
95
    protected boolean primaryKey;
96
    protected boolean readOnly;
97
    protected IProjection SRS;
98
    protected GeometryType geomType;
99
    protected int geometryType;
100
    protected int geometrySubType;
101
    protected Map additionalInfo;
102
    protected boolean isAutomatic;
103
    protected boolean isTime = false;
104
    protected Interval interval;
105
    protected FeatureAttributeGetter featureAttributeGetter = null;
106
    protected FeatureAttributeEmulator featureAttributeEmulator = null;
107
    protected boolean indexed = false;
108
    protected boolean isIndexAscending = true;
109
    protected boolean allowIndexDuplicateds = true;
110

    
111
    protected DynObjectValueItem[] availableValues;
112
    protected String description;
113
    protected Object minValue;
114
    protected Object maxValue;
115
    protected String label;
116
    protected int order;
117
    protected boolean hidden;
118
    protected String groupName;
119
    protected Tags tags = new DefaultTags();
120
    private DynMethod availableValuesMethod;
121
    private DynMethod calculateMethod;
122
    private WeakReference typeRef;
123

    
124
    public DefaultFeatureAttributeDescriptor() {
125
        // Usada en la persistencia
126
    }
127

    
128
    protected DefaultFeatureAttributeDescriptor(FeatureType type) {
129
        setFeatureType(type);
130
        this.allowNull = true;
131
        this.dataType = null;
132
        this.dateFormat = null;
133
        this.defaultValue = null;
134
        this.index = -1;
135
        this.maximumOccurrences = 0;
136
        this.minimumOccurrences = 0;
137
        this.size = 0;
138
        this.name = null;
139
        this.objectClass = null;
140
        this.precision = 0;
141
        this.evaluator = null;
142
        this.primaryKey = false;
143
        this.readOnly = false;
144
        this.SRS = null;
145
        this.geometryType = Geometry.TYPES.NULL;
146
        this.geometrySubType = Geometry.SUBTYPES.UNKNOWN;
147
        this.additionalInfo = null;
148
        this.isAutomatic = false;
149
        this.hidden = false;
150
    }
151

    
152
    protected DefaultFeatureAttributeDescriptor(
153
            DefaultFeatureAttributeDescriptor other
154
        ) {
155
        copyFrom(other);
156
    }
157
    
158
    @Override
159
    public void copyFrom(DynField other1) {
160
        if( !(other1 instanceof DefaultFeatureAttributeDescriptor) ) {
161
            throw new IllegalArgumentException("Can't copy from a non DefaultFeatureAttributeDescriptor");
162
        }
163
        DefaultFeatureAttributeDescriptor other = (DefaultFeatureAttributeDescriptor) other1;
164
        this.typeRef = other.typeRef;
165
        this.allowNull = other.allowNull;
166
        this.dataType = other.dataType;
167
        this.dateFormat = other.dateFormat;
168
        this.defaultValue = other.defaultValue;
169
        this.index = other.index;
170
        this.maximumOccurrences = other.maximumOccurrences;
171
        this.minimumOccurrences = other.minimumOccurrences;
172
        this.size = other.size;
173
        this.name = other.name;
174
        this.objectClass = other.objectClass;
175
        this.precision = other.precision;
176
        this.evaluator = other.evaluator;
177
        this.primaryKey = other.primaryKey;
178
        this.readOnly = other.readOnly;
179
        this.SRS = other.SRS;
180
        this.geometryType = other.geometryType;
181
        this.geometrySubType = other.geometrySubType;
182
        this.geomType = other.geomType;
183
        if (other.additionalInfo != null) {
184
            Iterator iter = other.additionalInfo.entrySet().iterator();
185
            Map.Entry entry;
186
            this.additionalInfo = new HashMap();
187
            while (iter.hasNext()) {
188
                entry = (Entry) iter.next();
189
                this.additionalInfo.put(entry.getKey(), entry.getValue());
190
            }
191
        } else {
192
            this.additionalInfo = null;
193
        }
194
        this.isAutomatic = other.isAutomatic;
195
        this.isTime = other.isTime;
196
        this.featureAttributeEmulator = other.featureAttributeEmulator;
197
        this.indexed = other.indexed;
198
        this.isIndexAscending = other.isIndexAscending;
199
        this.allowIndexDuplicateds = other.allowIndexDuplicateds;
200
        this.hidden = other.hidden;
201
        this.dataProfile = other.dataProfile;
202
        
203
        this.availableValues = other.availableValues;
204
        this.description = other.description;
205
        this.minValue = other.minValue;
206
        this.maxValue = other.maxValue;
207
        this.label = other.label;
208
        this.order = other.order;
209
        this.groupName = other.groupName;
210
        if( other.tags==null ) {
211
            this.tags = null;
212
        } else {
213
            try {
214
                this.tags = (Tags) other.tags.clone();
215
            } catch (Exception ex) {
216
            }
217
        }
218
        // TODO: ? Habria que clonarlos ?
219
        this.availableValuesMethod = other.availableValuesMethod;
220
        this.calculateMethod = other.calculateMethod;
221
    }
222
    
223
    public void setFeatureType(FeatureType type) {
224
        // Usada en la persistencia
225
        if( type == null ) {
226
            this.typeRef = null;
227
        } else {
228
            this.typeRef = new WeakReference(type);
229
        }
230
    }
231
    
232
    @Override
233
    public String getDataTypeName() {
234
        if (this.getDataType() == null) {
235
            return "(unknow)";
236
        }
237
        return this.getDataType().getName();
238
    }
239

    
240
    @Override
241
    public FeatureAttributeDescriptor getCopy() {
242
        return new DefaultFeatureAttributeDescriptor(this);
243
    }
244

    
245
    @Override
246
    public Object clone() throws CloneNotSupportedException {
247
        return new DefaultFeatureAttributeDescriptor(this);
248
    }
249
    
250
    @Override
251
    public boolean allowNull() {
252
        return allowNull;
253
    }
254

    
255
    @Override
256
    public DataType getDataType() {
257
        if (featureAttributeGetter != null) {
258
            return featureAttributeGetter.getDataType();
259
        }
260
        return this.dataType;
261
    }
262

    
263
    public FeatureAttributeDescriptor setDataType(int type) {
264
        this.dataType = ToolsLocator.getDataTypesManager().get(type);
265
        return this;
266
    }
267

    
268
    @Override
269
    public DateFormat getDateFormat() {
270
        return this.dateFormat;
271
    }
272

    
273
    @Override
274
    public Object getDefaultValue() {
275
        return this.defaultValue;
276
    }
277

    
278
    @Override
279
    public Evaluator getEvaluator() {
280
        return this.evaluator;
281
    }
282

    
283
    @Override
284
    public int getGeometryType() {
285
        if( this.dataType.getType()!=DataTypes.GEOMETRY ) {
286
            return Geometry.TYPES.UNKNOWN;
287
        }
288
        return this.geometryType;
289
    }
290

    
291
    @Override
292
    public int getGeometrySubType() {
293
        if( this.dataType.getType()!=DataTypes.GEOMETRY ) {
294
            return Geometry.SUBTYPES.UNKNOWN;
295
        }
296
        return this.geometrySubType;
297
    }
298

    
299
    @Override
300
    public GeometryType getGeomType() {
301
        if( this.dataType.getType()!=DataTypes.GEOMETRY ) {
302
            return null;
303
        }
304
        if (this.geomType == null) {
305
            try {
306
                this.geomType
307
                        = GeometryLocator.getGeometryManager().getGeometryType(
308
                                this.geometryType, this.geometrySubType);
309
            } catch (GeometryException e) {
310
                throw new RuntimeException(
311
                        "Error getting geometry type with type = "
312
                        + this.geometryType + ", subtype = "
313
                        + this.geometrySubType, e);
314
            }
315
        }
316
        return this.geomType;
317
    }
318

    
319
    @Override
320
    public int getIndex() {
321
        return this.index;
322
    }
323

    
324
    protected FeatureAttributeDescriptor setIndex(int index) {
325
        this.index = index;
326
        return this;
327
    }
328

    
329
    @Override
330
    public int getMaximumOccurrences() {
331
        return this.maximumOccurrences;
332
    }
333

    
334
    @Override
335
    public int getMinimumOccurrences() {
336
        return this.minimumOccurrences;
337
    }
338

    
339
    @Override
340
    public String getName() {
341
        return this.name;
342
    }
343
    
344
    public FeatureAttributeDescriptor setName(String name) {
345
        this.name = name;
346
        return this;
347
    }
348
    
349
    @Override
350
    public Class getObjectClass() {
351
        if (getDataType().getType() == DataTypes.OBJECT) {
352
            return objectClass;
353
        }
354
        return getDataType().getDefaultClass();
355
    }
356

    
357
    @Override
358
    public int getPrecision() {
359
        return this.precision;
360
    }
361

    
362
    @Override
363
    public IProjection getSRS() {
364
        return this.SRS;
365
    }
366

    
367
    @Override
368
    public Interval getInterval() {
369
        return this.interval;
370
    }
371

    
372
    public IProjection getSRS(WeakReference storeRef) {
373
        if( this.SRS==null ) {
374
            FeatureStore store = (FeatureStore) storeRef.get();
375
            this.SRS = (IProjection) store.getDynValue(DataStore.METADATA_CRS);
376
        }
377
        return this.SRS;
378
    }
379

    
380

    
381
    @Override
382
    public int getSize() {
383
        return this.size;
384
    }
385

    
386
    @Override
387
    public boolean isPrimaryKey() {
388
        return this.primaryKey;
389
    }
390

    
391
    @Override
392
    public boolean isReadOnly() {
393
        if (this.readOnly) {
394
            return true;
395
        }
396
        if (this.getEvaluator() != null) {
397
            return true;
398
        }
399
        if (this.featureAttributeEmulator != null) {
400
            return !this.featureAttributeEmulator.allowSetting();
401
        }
402
        return false;
403
    }
404

    
405
    @Override
406
    public Object getAdditionalInfo(String infoName) {
407
        if (this.additionalInfo == null) {
408
            return null;
409
        }
410
        return this.additionalInfo.get(infoName);
411
    }
412

    
413
    @Override
414
    public boolean isAutomatic() {
415
        return this.isAutomatic;
416
    }
417

    
418
    @Override
419
    public boolean equals(Object obj) {
420
        if (this == obj) {
421
            return true;
422
        }
423
        if (!(obj instanceof DefaultFeatureAttributeDescriptor)) {
424
            return false;
425
        }
426
        DefaultFeatureAttributeDescriptor other
427
                = (DefaultFeatureAttributeDescriptor) obj;
428

    
429
        if (this.allowNull != other.allowNull) {
430
            return false;
431
        }
432

    
433
        if (this.index != other.index) {
434
            return false;
435
        }
436

    
437
        if (!Objects.equals(this.name, other.name)) {
438
            return false;
439
        }
440

    
441
        if (this.getDataType() != other.getDataType()) {
442
            return false;
443
        }
444

    
445
        if (this.size != other.size) {
446
            return false;
447
        }
448

    
449
        if (!Objects.equals(this.defaultValue, other.defaultValue)) {
450
            return false;
451
        }
452

    
453
        if (this.primaryKey != other.primaryKey) {
454
            return false;
455
        }
456

    
457
        if (this.isAutomatic != other.isAutomatic) {
458
            return false;
459
        }
460

    
461
        if (this.readOnly != other.readOnly) {
462
            return false;
463
        }
464

    
465
        if (this.precision != other.precision) {
466
            return false;
467
        }
468

    
469
        if (this.maximumOccurrences != other.maximumOccurrences) {
470
            return false;
471
        }
472

    
473
        if (this.minimumOccurrences != other.minimumOccurrences) {
474
            return false;
475
        }
476

    
477
        if (this.geometryType != other.geometryType) {
478
            return false;
479
        }
480

    
481
        if (this.geometrySubType != other.geometrySubType) {
482
            return false;
483
        }
484

    
485
        if (!Objects.equals(this.evaluator, other.evaluator)) {
486
            return false;
487
        }
488

    
489
        if (!Objects.equals(this.featureAttributeEmulator, other.featureAttributeEmulator)) {
490
            return false;
491
        }
492

    
493
        if (!Objects.equals(this.SRS, other.SRS)) {
494
            return false;
495
        }
496

    
497
        if (!Objects.equals(this.dateFormat, other.dateFormat)) {
498
            return false;
499
        }
500

    
501
        if (!Objects.equals(this.objectClass, other.objectClass)) {
502
            return false;
503
        }
504

    
505
        if (!Objects.equals(this.dataProfile, other.dataProfile)) {
506
            return false;
507
        }
508

    
509
        return true;
510
    }
511

    
512
    @Override
513
    public void loadFromState(PersistentState state)
514
            throws PersistenceException {
515
        allowNull = state.getBoolean("allowNull");
516
        dataType = ToolsLocator.getDataTypesManager().get(state.getInt("dataType"));
517
        dataProfile = state.getString("dataProfile");
518
        
519
//        FIXME: dateFormat;
520
        try {
521
            defaultValue = dataType.coerce(state.get("defaultValue"));
522
        } catch (CoercionException ex) {
523
        }
524

    
525
        index = state.getInt("index");
526
        maximumOccurrences = state.getInt("maximumOccurrences");
527
        minimumOccurrences = state.getInt("minimumOccurrences");
528
        size = state.getInt("size");
529
        name = state.getString("name");
530
        try {
531
            String objectClassName = state.getString("objectClass"); 
532
            if( !StringUtils.isBlank(objectClassName) ) { 
533
                objectClass = Class.forName(objectClassName); 
534
            }
535
        } catch (Throwable e) {
536
            LOGGER.warn("Can't restore the objectClass of the FeatureAttributreDescriptor", e);
537
        }
538
        precision = state.getInt("precision");
539
        evaluator = (Evaluator) state.get("evaluator");
540
        primaryKey = state.getBoolean("primaryKey");
541
        readOnly = state.getBoolean("readOnly");
542
        SRS = (IProjection) state.get("SRS");
543
        geometryType = state.getInt("geometryType");
544
        geometrySubType = state.getInt("geometrySubType");
545
        if( geometryType!=Geometry.TYPES.UNKNOWN && 
546
                geometrySubType!=Geometry.SUBTYPES.UNKNOWN ) {
547
            geomType = GeometryUtils.getGeometryType(
548
                    geometryType, 
549
                    geometrySubType
550
            );
551
        }
552
//        additionalInfo = (Map) state.get("aditionalInfo");
553
        isAutomatic = state.getBoolean("isAutomatic");
554
        isTime = state.getBoolean("isTime");
555
        if( state.hasValue("intervalStart") ) {
556
            long intervalStart = state.getLong("interval_start");
557
            long intervalEnd = state.getLong("interval_end");
558
            interval = TimeSupportLocator.getManager().createRelativeInterval(intervalStart, intervalEnd);
559
        } else {
560
            interval = null;
561
        }
562
        featureAttributeEmulator = (FeatureAttributeEmulator) state.get("featureAttributeEmulator");
563
        indexed = state.getBoolean("indexed");
564
        isIndexAscending = state.getBoolean("isIndexAscending");
565
        allowIndexDuplicateds = state.getBoolean("allowIndexDuplicateds");
566

    
567
        Map<String,Object> values = state.getMap("availableValues");
568
        if( values == null || values.isEmpty()  ) {
569
            this.availableValues = null;
570
        } else {
571
            this.availableValues = new DynObjectValueItem[values.size()];
572
            int n = 0;
573
            for (Entry<String, Object> entry : values.entrySet()) {
574
                this.availableValues[n++] = new DynObjectValueItem(entry.getValue(), entry.getKey());
575
            }
576
        }
577
        
578
        description = state.getString("description");
579
        minValue = state.get("minValue");
580
        maxValue = state.get("maxValue");
581
        label = state.getString("label");
582
        order = state.getInt("order");
583
        hidden = state.getBoolean("hidden");
584
        groupName = state.getString("groupName");
585
    }
586

    
587
    @Override
588
    public void saveToState(PersistentState state) throws PersistenceException {
589
        state.set("allowNull", allowNull);
590
        state.set("dataType", dataType.getType());
591
        state.set("dataProfile", dataProfile);
592
        
593
//        FIXME: dateFormat;
594

    
595
        state.set("defaultValue", Objects.toString(defaultValue));
596

    
597
        state.set("index", index);
598
        state.set("maximumOccurrences", maximumOccurrences);
599
        state.set("minimumOccurrences", minimumOccurrences);
600
        state.set("size", size);
601
        state.set("name", name);
602
        state.set("objectClass", objectClass==null? null:objectClass.getName());
603
        state.set("precision", precision);
604
        state.set("evaluator", evaluator);
605
        
606
        state.set("primaryKey", primaryKey);
607
        state.set("readOnly", readOnly);
608
        state.set("SRS", SRS);
609
        GeometryType theGeomType = this.getGeomType();
610
        if( theGeomType==null ) {
611
            state.set("geometryType", Geometry.TYPES.UNKNOWN);
612
            state.set("geometrySubType", Geometry.SUBTYPES.UNKNOWN);
613
        } else {
614
            state.set("geometryType", theGeomType.getType());
615
            state.set("geometrySubType", theGeomType.getSubType());
616
        }
617

    
618
//      FIXME: additionalInfo
619

    
620
        state.set("isAutomatic", isAutomatic);
621
        state.set("isTime", isTime);
622
        if( this.interval==null ) {
623
            state.setNull("interval_start");
624
            state.setNull("interval_end");
625
        } else {
626
            state.set("interval_start", ((RelativeInterval)interval).getStart().toMillis());
627
            state.set("interval_end", ((RelativeInterval)interval).getEnd().toMillis());
628
        }
629
        state.set("SRS", SRS);
630

    
631
//      FIXME: featureAttributeGetter
632

    
633
        if( featureAttributeEmulator instanceof Persistent ) {
634
            state.set("featureAttributeEmulator", featureAttributeEmulator);
635
        } else {
636
            state.setNull("featureAttributeEmulator");
637
        }
638

    
639
        state.set("indexed", indexed);
640
        state.set("isIndexAscending", isIndexAscending);
641
        state.set("allowIndexDuplicateds", allowIndexDuplicateds);
642
        
643
        if( this.availableValues==null ) {
644
            state.setNull("availableValues");
645
        } else {
646
            Map<String,Object> values = new HashMap<>();
647
            for (DynObjectValueItem value : availableValues) {
648
                values.put(value.getLabel(),value.getValue());
649
            }
650
            state.set("availableValues", values);
651
        }
652
        state.set("description", description);
653
        state.set("minValue", minValue);
654
        state.set("maxValue", maxValue);
655
        state.set("label", label);
656
        state.set("order", order);
657
        state.set("hidden", hidden);
658
        state.set("groupName", groupName);
659

    
660
    }
661
    
662
    private static final String FEATATTRDESC_PERSISTENCE_DEFINITION_NAME = "FeatureAttributeDescriptor";
663

    
664
    public static void registerPersistenceDefinition() {
665
        PersistenceManager manager = ToolsLocator.getPersistenceManager();
666
        
667

    
668
        if (manager.getDefinition(FEATATTRDESC_PERSISTENCE_DEFINITION_NAME)
669
                == null) {
670
            DynStruct definition = manager.addDefinition(DefaultFeatureAttributeDescriptor.class,
671
                    FEATATTRDESC_PERSISTENCE_DEFINITION_NAME,
672
                    FEATATTRDESC_PERSISTENCE_DEFINITION_NAME
673
                        + " persistent definition",
674
                    null,
675
                    null
676
            );
677
            definition.addDynFieldBoolean("allowNull");
678
            definition.addDynFieldInt("dataType");
679
            definition.addDynFieldString("dataProfile");
680
//            definition.addDynFieldString("dateFormat");
681
            definition.addDynFieldString("defaultValue");
682
            definition.addDynFieldInt("index");
683
            definition.addDynFieldInt("maximumOccurrences");
684
            definition.addDynFieldInt("minimumOccurrences");
685
            definition.addDynFieldInt("size");
686
            definition.addDynFieldString("name");
687
            definition.addDynFieldString("objectClass");
688
            definition.addDynFieldInt("precision");
689
            definition.addDynFieldObject("evaluator")
690
                    .setClassOfValue(Evaluator.class);
691
            definition.addDynFieldBoolean("primaryKey");
692
            definition.addDynFieldBoolean("readOnly");
693
            definition.addDynFieldObject("SRS")
694
                    .setClassOfValue(IProjection.class);
695
            definition.addDynFieldInt("geometryType");
696
            definition.addDynFieldInt("geometrySubType");
697
//            definition.addDynFieldMap("additionalInfo");
698
            definition.addDynFieldBoolean("isAutomatic");
699
            definition.addDynFieldBoolean("isTime");
700
            definition.addDynFieldLong("interval_start");
701
            definition.addDynFieldLong("interval_end");
702
            definition.addDynFieldObject("featureAttributeEmulator")
703
                    .setClassOfValue(FeatureAttributeEmulator.class);
704
            definition.addDynFieldBoolean("indexed");
705
            definition.addDynFieldBoolean("isIndexAscending");
706
            definition.addDynFieldBoolean("allowIndexDuplicateds");
707
            definition.addDynFieldMap("availableValues");
708
            definition.addDynFieldString("description");
709
            definition.addDynFieldObject("minValue");
710
            definition.addDynFieldObject("maxValue");
711
            definition.addDynFieldString("label");
712
            definition.addDynFieldInt("order");
713
            definition.addDynFieldBoolean("hidden");
714
            definition.addDynFieldString("groupName");
715
        }
716
    }
717

    
718
    
719
    /*
720
     * Start of DynField interface Implementation
721
     *
722
     */
723

    
724
    @Override
725
    public Tags getTags() {
726
        return tags;
727
    }
728

    
729
    @Override
730
    public DynObjectValueItem[] getAvailableValues() {
731
        return this.availableValues;
732
    }
733

    
734
    @Override
735
    public String getDescription() {
736
        if( this.description == null ) {
737
            return getName();
738
        }
739
        return this.description;
740
    }
741

    
742
    @Override
743
    public Object getMaxValue() {
744
        return this.maxValue;
745
    }
746

    
747
    @Override
748
    public Object getMinValue() {
749
        return this.minValue;
750
    }
751

    
752
    @Override
753
    public int getTheTypeOfAvailableValues() {
754
        return 1;
755
    }
756

    
757
    @Override
758
    public int getType() {
759
        if (featureAttributeGetter != null) {
760
            return featureAttributeGetter.getDataType().getType();
761
        }
762
        return getDataType().getType();
763
    }
764

    
765
    @Override
766
    public boolean isMandatory() {
767
        return !allowNull() || isPrimaryKey();
768
    }
769

    
770
    @Override
771
    public boolean isPersistent() {
772
        return false;
773
    }
774

    
775
    @Override
776
    public DynField setAvailableValues(DynObjectValueItem[] values) {
777
        if ( ArrayUtils.isEmpty(values) ) {
778
            this.availableValues = null;
779
        } else {
780
            this.availableValues = values;
781
        }
782
        return this;
783
    }
784

    
785
    @Override
786
    public DynField setDescription(String description) {
787
        this.description = description;
788
        return this;
789
    }
790

    
791
    @Override
792
    public DynField setMandatory(boolean mandatory) {
793
        throw new UnsupportedOperationException();
794
    }
795

    
796
    @Override
797
    public DynField setMaxValue(Object maxValue) {
798
        try {
799
            this.maxValue = this.coerce(maxValue);
800
        } catch (CoercionException e) {
801
            throw new IllegalArgumentException(e);
802
        }
803
        return this;
804
    }
805

    
806
    @Override
807
    public DynField setMinValue(Object minValue) {
808
        try {
809
            this.maxValue = this.coerce(minValue);
810
        } catch (CoercionException e) {
811
            throw new IllegalArgumentException(e);
812
        }
813
        return this;
814
    }
815

    
816
    @Override
817
    public DynField setPersistent(boolean persistent) {
818
        throw new UnsupportedOperationException();
819
    }
820

    
821
    @Override
822
    public DynField setTheTypeOfAvailableValues(int type) {
823
        throw new UnsupportedOperationException();
824
    }
825

    
826
    @Override
827
    public DynField setType(int type) {
828
        throw new UnsupportedOperationException();
829
    }
830

    
831
    @Override
832
    public DynField setDefaultDynValue(Object defaultValue) {
833
        throw new UnsupportedOperationException();
834
    }
835

    
836
    @Override
837
    public Class getClassOfValue() {
838
        return null;
839
    }
840

    
841
    @Override
842
    public DynField getElementsType() {
843
        return null;
844
    }
845

    
846
    @Override
847
    public DynField setClassOfValue(Class theClass)
848
            throws DynFieldIsNotAContainerException {
849
        throw new UnsupportedOperationException();
850
    }
851

    
852
    @Override
853
    public DynField setElementsType(DynStruct type)
854
            throws DynFieldIsNotAContainerException {
855
        throw new UnsupportedOperationException();
856
    }
857

    
858
    @Override
859
    public DynField setElementsType(int type)
860
            throws DynFieldIsNotAContainerException {
861
        throw new UnsupportedOperationException();
862
    }
863

    
864
    public FeatureAttributeDescriptor setDataProfileName(String dataProfile) {
865
        this.dataProfile = dataProfile;
866
        return this;
867
    }
868

    
869
    @Override
870
    public String getDataProfileName() {
871
        return dataProfile;
872
    }
873

    
874
    @Override
875
    public void validate(Object value) throws DynFieldValidateException {
876

    
877
        if (value == null && !this.allowNull()) {
878
            throw new DynFieldValidateException(value, this, null);
879
        }
880

    
881
        try {
882
            this.dataType.coerce(value);
883
        } catch (CoercionException e) {
884
            throw new DynFieldValidateException(value, this, e);
885
        }
886

    
887
        /*
888
         * Other checks will be needed
889
         */
890
    }
891

    
892
    @Override
893
    public String getSubtype() {
894
        if (featureAttributeGetter != null) {
895
            return featureAttributeGetter.getDataType().getSubtype();
896
        }
897
        return this.dataType.getSubtype();
898
    }
899

    
900
    @Override
901
    public Object coerce(Object value) throws CoercionException {
902
        if ( value == null ) {
903
            return value; // O debe devolver this.defaultValue
904
        }
905
        try {
906
            return this.getDataType().coerce(value);
907
        } catch(Exception ex){
908
            throw new RuntimeException(ex);
909
        }
910
    }
911

    
912
    @Override
913
    public DynField setAvailableValues(List values) {
914
        if (  values == null || values.isEmpty() ) {
915
            this.availableValues = null;
916
        } else {
917
            this.availableValues = (DynObjectValueItem[]) values.toArray(
918
                new DynObjectValueItem[values.size()]
919
            );
920
        }
921
        return this;
922
    }
923

    
924
    @Override
925
    public String getGroup() {
926
        return this.groupName;
927
    }
928

    
929
    @Override
930
    public int getOder() {
931
        return this.order;
932
    }
933

    
934
    @Override
935
    public String getLabel() {
936
        if( this.label == null ) {
937
            return this.getName();
938
        }
939
        return this.label;
940
    }
941

    
942
    @Override
943
    public DynField setLabel(String label) {
944
        this.label = label;
945
        return this;
946
    }
947

    
948
    @Override
949
    public DynField setGroup(String groupName) {
950
        this.groupName = groupName;
951
        return this;
952
    }
953

    
954
    @Override
955
    public DynField setOrder(int order) {
956
        this.order = order;
957
        return this;
958
    }
959

    
960
    @Override
961
    public DynField setHidden(boolean hidden) {
962
        this.hidden = hidden;
963
        return this;
964
    }
965

    
966
    @Override
967
    public boolean isHidden() {
968
        return this.hidden;
969
    }
970

    
971
    @Override
972
    public DynField setReadOnly(boolean arg0) {
973
        throw new UnsupportedOperationException();
974
    }
975

    
976
    @Override
977
    public boolean isContainer() {
978
        return false;
979
    }
980

    
981
    @Override
982
    public Class getClassOfItems() {
983
        return null;
984
    }
985

    
986
    @Override
987
    public DynField setDefaultFieldValue(Object defaultValue) {
988
        throw new UnsupportedOperationException();
989
    }
990

    
991
    @Override
992
    public DynField setClassOfItems(Class theClass) {
993
        throw new UnsupportedOperationException();
994
    }
995

    
996
    @Override
997
    public DynField setType(DataType type) {
998
        throw new UnsupportedOperationException();
999
    }
1000

    
1001
    @Override
1002
    public DynField setSubtype(String subtype) {
1003
        throw new UnsupportedOperationException();
1004
    }
1005

    
1006
    @Override
1007
    public boolean isTime() {
1008
        return isTime;
1009
    }
1010

    
1011
    @Override
1012
    public FeatureAttributeGetter getFeatureAttributeGetter() {
1013
        return featureAttributeGetter;
1014
    }
1015

    
1016
    @Override
1017
    public void setFeatureAttributeGetter(
1018
            FeatureAttributeGetter featureAttributeTransform) {
1019
        this.featureAttributeGetter = featureAttributeTransform;
1020
    }
1021

    
1022
    @Override
1023
    public FeatureAttributeEmulator getFeatureAttributeEmulator() {
1024
        return this.featureAttributeEmulator;
1025
    }
1026

    
1027
    public FeatureAttributeDescriptor setFeatureAttributeEmulator(FeatureAttributeEmulator featureAttributeEmulator) {
1028
        this.featureAttributeEmulator = featureAttributeEmulator;
1029
        return this;
1030
    }
1031
        
1032
    @Override
1033
    public boolean isIndexed() {
1034
        return this.indexed;
1035
    }
1036

    
1037
    @Override
1038
    public boolean allowIndexDuplicateds() {
1039
        return this.allowIndexDuplicateds;
1040
    }
1041

    
1042
    @Override
1043
    public boolean isIndexAscending() {
1044
        return this.isIndexAscending;
1045
    }
1046

    
1047
    @Override
1048
    public DynField setClassOfValue(DynStruct dynStrct) {
1049
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
1050
    }
1051

    
1052
    @Override
1053
    public DynField setClassOfValue(String theClassNameOfValue) {
1054
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
1055
    }
1056

    
1057
    @Override
1058
    public String getClassNameOfValue() {
1059
        return null;
1060
    }
1061

    
1062
    @Override
1063
    public DynStruct getDynClassOfValue() {
1064
        return null;
1065
    }
1066

    
1067
    @Override
1068
    public DynField setTypeOfItems(int type) {
1069
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
1070
    }
1071

    
1072
    @Override
1073
    public int getTypeOfItems() {
1074
        return DataTypes.INVALID;
1075
    }
1076

    
1077
    @Override
1078
    public DynField setClassOfItems(DynStruct dynStrct) {
1079
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
1080
    }
1081

    
1082
    @Override
1083
    public DynField setClassOfItems(String theClassNameOfValue) {
1084
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
1085
    }
1086

    
1087
    @Override
1088
    public String getClassNameOfItems() {
1089
        return null;
1090
    }
1091

    
1092
    @Override
1093
    public DynStruct getDynClassOfItems() {
1094
        return null;
1095
    }
1096

    
1097
    @Override
1098
    public DynField setRelationType(int relationType) {
1099
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
1100
    }
1101

    
1102
    @Override
1103
    public int getRelationType() {
1104
        return RELATION_TYPE_NONE;
1105
    }
1106

    
1107
    @Override
1108
    public DynField setAvailableValues(DynMethod availableValuesMethod) {
1109
        this.availableValuesMethod = availableValuesMethod;
1110
        return this;
1111
    }
1112

    
1113
    @Override
1114
    public DynObjectValueItem[] getAvailableValues(DynObject self) {
1115
        if( this.availableValuesMethod != null ) {
1116
            DynObjectValueItem[] values;
1117
            try {
1118
                values = (DynObjectValueItem[]) this.availableValuesMethod.invoke(self,new Object[] {this});
1119
            } catch (DynMethodException ex) {
1120
                return this.availableValues;
1121
            }
1122
            if( values != null ) {
1123
                return values;
1124
            }
1125
        }
1126
        return this.availableValues;
1127
    }
1128

    
1129
    @Override
1130
    public DynMethod getAvailableValuesMethod() {
1131
        return this.availableValuesMethod;
1132
    }
1133

    
1134
    @Override
1135
    public boolean isAvailableValuesCalculated() {
1136
        return this.availableValuesMethod!=null;
1137
    }
1138

    
1139
    @Override
1140
    public DynMethod getCalculateMethod() {
1141
        return this.calculateMethod;
1142
    }
1143

    
1144
    @Override
1145
    public DynField setCalculateMethod(DynMethod method) {
1146
        this.calculateMethod = method;
1147
        return this;
1148
    }
1149
    
1150
    @Override
1151
    public boolean isCalculated() {
1152
        return this.calculateMethod != null;
1153
    }
1154
    
1155
    @Override
1156
    public Object getCalculatedValue(DynObject self) {
1157
        try {
1158
            return this.calculateMethod.invoke(self, new Object[] { this });
1159
        } catch (DynMethodException ex) {
1160
            throw new RuntimeException(ex);
1161
        }
1162
    }
1163

    
1164
    @Override
1165
    public DynField setValidateElements(boolean validate) {
1166
        return this;
1167
    }
1168

    
1169
    @Override
1170
    public boolean getValidateElements() {
1171
        return false;
1172
    }
1173

    
1174
    private class ConstantValueEvaluator extends AbstractEvaluator {
1175

    
1176
        @Override
1177
        public Object evaluate(EvaluatorData data) throws EvaluatorException {
1178
            return defaultValue;
1179
        }
1180

    
1181
        @Override
1182
        public String getName() {
1183
            return "Constant attribute " + name;
1184
        }
1185
    }
1186

    
1187
    public void setConstantValue(boolean isConstantValue) {
1188
        if (isConstantValue) {
1189
            /* Cuando un attributo tiene asociado un evaluador, este se interpreta
1190
             * como que no debe cargarse de la fuente de datos subyacente, siendo
1191
             * el evaluador el que se encarga de proporcionar su valor.
1192
             * Nos limitamos a asignar un evaluador que retorna simpre el valor
1193
             * por defecto para ese attributo.
1194
             */
1195
            this.evaluator = new ConstantValueEvaluator();
1196
        } else {
1197
            this.evaluator = null;
1198
        }
1199
    }
1200

    
1201
    @Override
1202
    public boolean isComputed() {
1203
        return featureAttributeEmulator!=null || evaluator!=null || isCalculated();
1204
    }
1205

    
1206
    @Override
1207
    public FeatureStore getStore() {
1208
        FeatureType ftype = this.getFeatureType();
1209
        if( ftype == null ) {
1210
            return null;
1211
        }
1212
        return ftype.getStore();
1213
    }
1214
    
1215
    @Override
1216
    public FeatureType getFeatureType() {
1217
        if( this.typeRef==null ) {
1218
            return null;
1219
        }
1220
        return (FeatureType) this.typeRef.get();
1221
    }
1222

    
1223
    public FeatureAttributeDescriptor setInterval(Interval interval) {
1224
        this.interval = interval;
1225
        return this;
1226
    }
1227

    
1228
    public void fixAll() {
1229
        switch(this.getType()) {
1230
            case DataTypes.INSTANT:
1231
            case DataTypes.INTERVAL:
1232
            case DataTypes.DATE:
1233
                if( this.getInterval()!=null ) {
1234
                    this.isTime = true;
1235
                }
1236
                break;
1237
        }
1238
    }
1239

    
1240
    @Override
1241
    public String[] getRequiredFieldNames() {
1242
        FeatureAttributeEmulator emulator = this.getFeatureAttributeEmulator();
1243
        if( emulator==null ) {
1244
            return null;
1245
        }
1246
        return emulator.getRequiredFieldNames();
1247
    }
1248

    
1249
}