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

History | View | Annotate | Download (39.9 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.dal.feature.ForeingKey;
44
import org.gvsig.fmap.geom.Geometry;
45
import org.gvsig.fmap.geom.GeometryException;
46
import org.gvsig.fmap.geom.GeometryLocator;
47
import org.gvsig.fmap.geom.GeometryUtils;
48
import org.gvsig.fmap.geom.type.GeometryType;
49
import org.gvsig.timesupport.Interval;
50
import org.gvsig.timesupport.RelativeInterval;
51
import org.gvsig.timesupport.TimeSupportLocator;
52
import org.gvsig.tools.ToolsLocator;
53
import org.gvsig.tools.dataTypes.CoercionException;
54
import org.gvsig.tools.dataTypes.DataType;
55
import org.gvsig.tools.dynobject.DynField;
56
import org.gvsig.tools.dynobject.DynField_LabelAttribute;
57
import org.gvsig.tools.dynobject.DynField_v2;
58
import org.gvsig.tools.dynobject.DynMethod;
59
import org.gvsig.tools.dynobject.DynObject;
60
import org.gvsig.tools.dynobject.DynObjectValueItem;
61
import org.gvsig.tools.dynobject.DynStruct;
62
import org.gvsig.tools.dynobject.Tags;
63
import org.gvsig.tools.dynobject.exception.DynFieldIsNotAContainerException;
64
import org.gvsig.tools.dynobject.exception.DynFieldValidateException;
65
import org.gvsig.tools.dynobject.exception.DynMethodException;
66
import org.gvsig.tools.dynobject.impl.DefaultTags;
67
import org.gvsig.tools.evaluator.AbstractEvaluator;
68
import org.gvsig.tools.evaluator.Evaluator;
69
import org.gvsig.tools.evaluator.EvaluatorData;
70
import org.gvsig.tools.evaluator.EvaluatorException;
71
import org.gvsig.tools.persistence.PersistenceManager;
72
import org.gvsig.tools.persistence.Persistent;
73
import org.gvsig.tools.persistence.PersistentState;
74
import org.gvsig.tools.persistence.exception.PersistenceException;
75
import org.slf4j.Logger;
76
import org.slf4j.LoggerFactory;
77

    
78
@SuppressWarnings("UseSpecificCatch")
79
public class DefaultFeatureAttributeDescriptor implements
80
        FeatureAttributeDescriptor, Persistent, DynField_v2, DynField_LabelAttribute {
81

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

    
113
    protected DynObjectValueItem[] availableValues;
114
    protected DynObjectValueItem[] availableValuesFromForeingKey;
115
    protected String description;
116
    protected Object minValue;
117
    protected Object maxValue;
118
    protected String label;
119
    protected int order;
120
    protected boolean hidden;
121
    protected String groupName;
122
    protected Tags tags = new DefaultTags();
123
    private DynMethod availableValuesMethod;
124
    private DynMethod calculateMethod;
125
    private WeakReference typeRef;
126
    protected DefaultForeingKey foreingKey = null;
127
    
128
    private int relationType = RELATION_TYPE_NONE;
129

    
130
    public DefaultFeatureAttributeDescriptor() {
131
        // Usada en la persistencia
132
    }
133

    
134
    protected DefaultFeatureAttributeDescriptor(FeatureType type) {
135
        this();
136
//        LOGGER.info(String.format("Created FeatureAttributeDescriptor [%08x].", this.hashCode()));
137
        setFeatureType(type);
138
        this.allowNull = true;
139
        this.dataType = null;
140
        this.dateFormat = null;
141
        this.defaultValue = null;
142
        this.index = -1;
143
        this.maximumOccurrences = 0;
144
        this.minimumOccurrences = 0;
145
        this.size = 0;
146
        this.name = null;
147
        this.objectClass = null;
148
        this.precision = 0;
149
        this.evaluator = null;
150
        this.primaryKey = false;
151
        this.readOnly = false;
152
        this.SRS = null;
153
        this.geometryType = Geometry.TYPES.NULL;
154
        this.geometrySubType = Geometry.SUBTYPES.UNKNOWN;
155
        this.additionalInfo = null;
156
        this.isAutomatic = false;
157
        this.hidden = false;
158
        this.relationType = RELATION_TYPE_NONE;
159
    }
160

    
161
    protected DefaultFeatureAttributeDescriptor(
162
            DefaultFeatureAttributeDescriptor other
163
        ) {
164
        this();
165
        copyFrom(other);
166
//        LOGGER.info(String.format("Created FeatureAttributeDescriptor [%08x] [%s] (copy).", this.hashCode(), this.name));
167
    }
168
    
169
    @Override
170
    public void copyFrom(DynField other1) {
171
        if( !(other1 instanceof DefaultFeatureAttributeDescriptor) ) {
172
            throw new IllegalArgumentException("Can't copy from a non DefaultFeatureAttributeDescriptor");
173
        }
174
        DefaultFeatureAttributeDescriptor other = (DefaultFeatureAttributeDescriptor) other1;
175
        this.typeRef = other.typeRef;
176
        this.allowNull = other.allowNull;
177
        this.dataType = other.dataType;
178
        this.dateFormat = other.dateFormat;
179
        this.defaultValue = other.defaultValue;
180
        this.index = other.index;
181
        this.maximumOccurrences = other.maximumOccurrences;
182
        this.minimumOccurrences = other.minimumOccurrences;
183
        this.size = other.size;
184
        this.name = other.name;
185
        this.objectClass = other.objectClass;
186
        this.precision = other.precision;
187
        this.evaluator = other.evaluator;
188
        this.primaryKey = other.primaryKey;
189
        this.readOnly = other.readOnly;
190
        this.SRS = other.SRS;
191
        this.geometryType = other.geometryType;
192
        this.geometrySubType = other.geometrySubType;
193
        this.geomType = other.geomType;
194
        if (other.additionalInfo != null) {
195
            Iterator iter = other.additionalInfo.entrySet().iterator();
196
            Map.Entry entry;
197
            this.additionalInfo = new HashMap();
198
            while (iter.hasNext()) {
199
                entry = (Entry) iter.next();
200
                this.additionalInfo.put(entry.getKey(), entry.getValue());
201
            }
202
        } else {
203
            this.additionalInfo = null;
204
        }
205
        this.isAutomatic = other.isAutomatic;
206
        this.isTime = other.isTime;
207
        this.featureAttributeEmulator = other.featureAttributeEmulator;
208
        this.indexed = other.indexed;
209
        this.isIndexAscending = other.isIndexAscending;
210
        this.allowIndexDuplicateds = other.allowIndexDuplicateds;
211
        this.hidden = other.hidden;
212
        this.dataProfile = other.dataProfile;
213
        
214
        this.availableValues = other.availableValues;
215
        this.description = other.description;
216
        this.minValue = other.minValue;
217
        this.maxValue = other.maxValue;
218
        this.label = other.label;
219
        this.order = other.order;
220
        this.groupName = other.groupName;
221
        if( other.tags==null ) {
222
            this.tags = null;
223
        } else {
224
            try {
225
                this.tags = (Tags) other.tags.clone();
226
            } catch (Exception ex) {
227
            }
228
        }
229
        this.foreingKey = null;
230
        if( other.foreingKey!=null ) {
231
            try {
232
                this.foreingKey = (DefaultForeingKey) other.foreingKey.clone();
233
            } catch (CloneNotSupportedException ex) {
234
            }
235
        }
236
        if( this.foreingKey!=null ) {
237
            this.foreingKey.setDescriptor(this);
238
        }
239
        
240
        // TODO: ? Habria que clonarlos ?
241
        this.availableValuesMethod = other.availableValuesMethod;
242
        this.calculateMethod = other.calculateMethod;
243
        this.relationType = other.relationType;
244
    }
245
    
246
    public void setFeatureType(FeatureType type) {
247
        // Usada en la persistencia
248
        if( type == null ) {
249
            this.typeRef = null;
250
        } else {
251
            this.typeRef = new WeakReference(type);
252
//            LOGGER.info(String.format("FeatureAttributeDescriptor[%08x] set FeatureType [%08x], ref [%08x].", this.hashCode(), type.hashCode(), typeRef.hashCode()));
253
        }
254
    }
255
    
256
    @Override
257
    public String getDataTypeName() {
258
        if (this.getDataType() == null) {
259
            return "(unknow)";
260
        }
261
        return this.getDataType().getName();
262
    }
263

    
264
    @Override
265
    public FeatureAttributeDescriptor getCopy() {
266
        return new DefaultFeatureAttributeDescriptor(this);
267
    }
268

    
269
    @Override
270
    public Object clone() throws CloneNotSupportedException {
271
        return new DefaultFeatureAttributeDescriptor(this);
272
    }
273
    
274
    @Override
275
    public boolean allowNull() {
276
        return allowNull;
277
    }
278

    
279
    @Override
280
    public DataType getDataType() {
281
        if (featureAttributeGetter != null) {
282
            return featureAttributeGetter.getDataType();
283
        }
284
        return this.dataType;
285
    }
286

    
287
    public FeatureAttributeDescriptor setDataType(int type) {
288
        this.dataType = ToolsLocator.getDataTypesManager().get(type);
289
        return this;
290
    }
291

    
292
    @Override
293
    public DateFormat getDateFormat() {
294
        return this.dateFormat;
295
    }
296

    
297
    @Override
298
    public Object getDefaultValue() {
299
        return this.defaultValue;
300
    }
301

    
302
    @Override
303
    public Evaluator getEvaluator() {
304
        return this.evaluator;
305
    }
306

    
307
    @Override
308
    public int getGeometryType() {
309
        if( this.dataType.getType()!=DataTypes.GEOMETRY ) {
310
            return Geometry.TYPES.UNKNOWN;
311
        }
312
        return this.geometryType;
313
    }
314

    
315
    @Override
316
    public int getGeometrySubType() {
317
        if( this.dataType.getType()!=DataTypes.GEOMETRY ) {
318
            return Geometry.SUBTYPES.UNKNOWN;
319
        }
320
        return this.geometrySubType;
321
    }
322

    
323
    @Override
324
    public GeometryType getGeomType() {
325
        if( this.dataType.getType()!=DataTypes.GEOMETRY ) {
326
            return null;
327
        }
328
        if (this.geomType == null) {
329
            try {
330
                this.geomType
331
                        = GeometryLocator.getGeometryManager().getGeometryType(
332
                                this.geometryType, this.geometrySubType);
333
            } catch (GeometryException e) {
334
                throw new RuntimeException(
335
                        "Error getting geometry type with type = "
336
                        + this.geometryType + ", subtype = "
337
                        + this.geometrySubType, e);
338
            }
339
        }
340
        return this.geomType;
341
    }
342

    
343
    @Override
344
    public int getIndex() {
345
        return this.index;
346
    }
347

    
348
    protected FeatureAttributeDescriptor setIndex(int index) {
349
        this.index = index;
350
        return this;
351
    }
352

    
353
    @Override
354
    public int getMaximumOccurrences() {
355
        return this.maximumOccurrences;
356
    }
357

    
358
    @Override
359
    public int getMinimumOccurrences() {
360
        return this.minimumOccurrences;
361
    }
362

    
363
    @Override
364
    public String getName() {
365
        return this.name;
366
    }
367
    
368
    public FeatureAttributeDescriptor setName(String name) {
369
//        LOGGER.info(String.format("FeatureAttributeDescriptor[%08x] set name [%s].", this.hashCode(), name));
370
        this.name = name;
371
        return this;
372
    }
373
    
374
    @Override
375
    public Class getObjectClass() {
376
        if (getDataType().getType() == DataTypes.OBJECT) {
377
            return objectClass;
378
        }
379
        return getDataType().getDefaultClass();
380
    }
381

    
382
    @Override
383
    public int getPrecision() {
384
        return this.precision;
385
    }
386

    
387
    @Override
388
    public IProjection getSRS() {
389
        return this.SRS;
390
    }
391

    
392
    @Override
393
    public Interval getInterval() {
394
        return this.interval;
395
    }
396

    
397
    public IProjection getSRS(WeakReference storeRef) {
398
        if( this.SRS==null ) {
399
            FeatureStore store = (FeatureStore) storeRef.get();
400
            this.SRS = (IProjection) store.getDynValue(DataStore.METADATA_CRS);
401
        }
402
        return this.SRS;
403
    }
404

    
405

    
406
    @Override
407
    public int getSize() {
408
        return this.size;
409
    }
410

    
411
    @Override
412
    public boolean isPrimaryKey() {
413
        return this.primaryKey;
414
    }
415

    
416
    @Override
417
    public boolean isReadOnly() {
418
        if (this.readOnly) {
419
            return true;
420
        }
421
        if (this.getEvaluator() != null) {
422
            return true;
423
        }
424
        if (this.featureAttributeEmulator != null) {
425
            return !this.featureAttributeEmulator.allowSetting();
426
        }
427
        return false;
428
    }
429

    
430
    @Override
431
    public Object getAdditionalInfo(String infoName) {
432
        if (this.additionalInfo == null) {
433
            return null;
434
        }
435
        return this.additionalInfo.get(infoName);
436
    }
437

    
438
    @Override
439
    public boolean isAutomatic() {
440
        return this.isAutomatic;
441
    }
442

    
443
    @Override
444
    public boolean equals(Object obj) {
445
        if (this == obj) {
446
            return true;
447
        }
448
        if (!(obj instanceof DefaultFeatureAttributeDescriptor)) {
449
            return false;
450
        }
451
        DefaultFeatureAttributeDescriptor other
452
                = (DefaultFeatureAttributeDescriptor) obj;
453

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

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

    
462
        if (!Objects.equals(this.name, other.name)) {
463
            return false;
464
        }
465

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

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

    
474
        if (!Objects.equals(this.defaultValue, other.defaultValue)) {
475
            return false;
476
        }
477

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

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

    
486
        if (this.readOnly != other.readOnly) {
487
            return false;
488
        }
489

    
490
        if (this.precision != other.precision) {
491
            return false;
492
        }
493

    
494
        if (this.maximumOccurrences != other.maximumOccurrences) {
495
            return false;
496
        }
497

    
498
        if (this.minimumOccurrences != other.minimumOccurrences) {
499
            return false;
500
        }
501

    
502
        if (this.geometryType != other.geometryType) {
503
            return false;
504
        }
505

    
506
        if (this.geometrySubType != other.geometrySubType) {
507
            return false;
508
        }
509

    
510
        if (!Objects.equals(this.evaluator, other.evaluator)) {
511
            return false;
512
        }
513

    
514
        if (!Objects.equals(this.featureAttributeEmulator, other.featureAttributeEmulator)) {
515
            return false;
516
        }
517

    
518
        if (!Objects.equals(this.SRS, other.SRS)) {
519
            return false;
520
        }
521

    
522
        if (!Objects.equals(this.dateFormat, other.dateFormat)) {
523
            return false;
524
        }
525

    
526
        if (!Objects.equals(this.objectClass, other.objectClass)) {
527
            return false;
528
        }
529

    
530
        if (!Objects.equals(this.dataProfile, other.dataProfile)) {
531
            return false;
532
        }
533

    
534
        return true;
535
    }
536

    
537
    @Override
538
    public void loadFromState(PersistentState state)
539
            throws PersistenceException {
540
        allowNull = state.getBoolean("allowNull");
541
        dataType = ToolsLocator.getDataTypesManager().get(state.getInt("dataType"));
542
        dataProfile = state.getString("dataProfile");
543
        
544
//        FIXME: dateFormat;
545
        try {
546
            defaultValue = dataType.coerce(state.get("defaultValue"));
547
        } catch (CoercionException ex) {
548
        }
549

    
550
        index = state.getInt("index");
551
        maximumOccurrences = state.getInt("maximumOccurrences");
552
        minimumOccurrences = state.getInt("minimumOccurrences");
553
        size = state.getInt("size");
554
        name = state.getString("name");
555
        try {
556
            String objectClassName = state.getString("objectClass"); 
557
            if( !StringUtils.isBlank(objectClassName) ) { 
558
                objectClass = Class.forName(objectClassName); 
559
            }
560
        } catch (Throwable e) {
561
            LOGGER.warn("Can't restore the objectClass of the FeatureAttributreDescriptor", e);
562
        }
563
        precision = state.getInt("precision");
564
        evaluator = (Evaluator) state.get("evaluator");
565
        primaryKey = state.getBoolean("primaryKey");
566
        readOnly = state.getBoolean("readOnly");
567
        SRS = (IProjection) state.get("SRS");
568
        geometryType = state.getInt("geometryType");
569
        geometrySubType = state.getInt("geometrySubType");
570
        if( geometryType!=Geometry.TYPES.UNKNOWN && 
571
                geometrySubType!=Geometry.SUBTYPES.UNKNOWN ) {
572
            geomType = GeometryUtils.getGeometryType(
573
                    geometryType, 
574
                    geometrySubType
575
            );
576
        }
577
//        additionalInfo = (Map) state.get("aditionalInfo");
578
        isAutomatic = state.getBoolean("isAutomatic");
579
        isTime = state.getBoolean("isTime");
580
        if( state.hasValue("intervalStart") ) {
581
            long intervalStart = state.getLong("interval_start");
582
            long intervalEnd = state.getLong("interval_end");
583
            interval = TimeSupportLocator.getManager().createRelativeInterval(intervalStart, intervalEnd);
584
        } else {
585
            interval = null;
586
        }
587
        featureAttributeEmulator = (FeatureAttributeEmulator) state.get("featureAttributeEmulator");
588
        indexed = state.getBoolean("indexed");
589
        isIndexAscending = state.getBoolean("isIndexAscending");
590
        allowIndexDuplicateds = state.getBoolean("allowIndexDuplicateds");
591

    
592
        Map<String,Object> values = state.getMap("availableValues");
593
        if( values == null || values.isEmpty()  ) {
594
            this.availableValues = null;
595
        } else {
596
            this.availableValues = new DynObjectValueItem[values.size()];
597
            int n = 0;
598
            for (Entry<String, Object> entry : values.entrySet()) {
599
                this.availableValues[n++] = new DynObjectValueItem(entry.getValue(), entry.getKey());
600
            }
601
        }
602
        
603
        description = state.getString("description");
604
        minValue = state.get("minValue");
605
        maxValue = state.get("maxValue");
606
        label = state.getString("label");
607
        order = state.getInt("order");
608
        hidden = state.getBoolean("hidden");
609
        groupName = state.getString("groupName");
610
        relationType = state.getInt("relationType");
611
        
612
        foreingKey = (DefaultForeingKey) state.get("foreingKey");
613
        if( foreingKey!=null ) {
614
            this.foreingKey.setDescriptor(this);
615
        }
616
        tags = (Tags) state.get("tags");
617
        if( tags == null ) {
618
            this.tags = new DefaultTags();
619
        }
620
    }
621

    
622
    @Override
623
    public void saveToState(PersistentState state) throws PersistenceException {
624
        state.set("allowNull", allowNull);
625
        state.set("dataType", dataType.getType());
626
        state.set("dataProfile", dataProfile);
627
        
628
//        FIXME: dateFormat;
629

    
630
        state.set("defaultValue", Objects.toString(defaultValue));
631

    
632
        state.set("index", index);
633
        state.set("maximumOccurrences", maximumOccurrences);
634
        state.set("minimumOccurrences", minimumOccurrences);
635
        state.set("size", size);
636
        state.set("name", name);
637
        state.set("objectClass", objectClass==null? null:objectClass.getName());
638
        state.set("precision", precision);
639
        state.set("evaluator", evaluator);
640
        
641
        state.set("primaryKey", primaryKey);
642
        state.set("readOnly", readOnly);
643
        state.set("SRS", SRS);
644
        GeometryType theGeomType = this.getGeomType();
645
        if( theGeomType==null ) {
646
            state.set("geometryType", Geometry.TYPES.UNKNOWN);
647
            state.set("geometrySubType", Geometry.SUBTYPES.UNKNOWN);
648
        } else {
649
            state.set("geometryType", theGeomType.getType());
650
            state.set("geometrySubType", theGeomType.getSubType());
651
        }
652

    
653
//      FIXME: additionalInfo
654

    
655
        state.set("isAutomatic", isAutomatic);
656
        state.set("isTime", isTime);
657
        if( this.interval==null ) {
658
            state.setNull("interval_start");
659
            state.setNull("interval_end");
660
        } else {
661
            state.set("interval_start", ((RelativeInterval)interval).getStart().toMillis());
662
            state.set("interval_end", ((RelativeInterval)interval).getEnd().toMillis());
663
        }
664
        state.set("SRS", SRS);
665

    
666
//      FIXME: featureAttributeGetter
667

    
668
        if( featureAttributeEmulator instanceof Persistent ) {
669
            state.set("featureAttributeEmulator", featureAttributeEmulator);
670
        } else {
671
            state.setNull("featureAttributeEmulator");
672
        }
673

    
674
        state.set("indexed", indexed);
675
        state.set("isIndexAscending", isIndexAscending);
676
        state.set("allowIndexDuplicateds", allowIndexDuplicateds);
677
        
678
        if( this.availableValues==null ) {
679
            state.setNull("availableValues");
680
        } else {
681
            Map<String,Object> values = new HashMap<>();
682
            for (DynObjectValueItem value : availableValues) {
683
                values.put(value.getLabel(),value.getValue());
684
            }
685
            state.set("availableValues", values);
686
        }
687
        state.set("description", description);
688
        state.set("minValue", minValue);
689
        state.set("maxValue", maxValue);
690
        state.set("label", label);
691
        state.set("order", order);
692
        state.set("hidden", hidden);
693
        state.set("groupName", groupName);
694
        state.set("relationType",relationType);
695
        
696
        state.set("foreingKey" ,this.foreingKey);
697
        state.set("tags" ,this.tags);
698

    
699
    }
700
    
701
    private static final String FEATATTRDESC_PERSISTENCE_DEFINITION_NAME = "FeatureAttributeDescriptor";
702

    
703
    public static void registerPersistenceDefinition() {
704
        PersistenceManager manager = ToolsLocator.getPersistenceManager();
705
        
706

    
707
        if (manager.getDefinition(FEATATTRDESC_PERSISTENCE_DEFINITION_NAME)
708
                == null) {
709
            DynStruct definition = manager.addDefinition(DefaultFeatureAttributeDescriptor.class,
710
                    FEATATTRDESC_PERSISTENCE_DEFINITION_NAME,
711
                    FEATATTRDESC_PERSISTENCE_DEFINITION_NAME
712
                        + " persistent definition",
713
                    null,
714
                    null
715
            );
716
            definition.addDynFieldBoolean("allowNull");
717
            definition.addDynFieldInt("dataType");
718
            definition.addDynFieldString("dataProfile");
719
//            definition.addDynFieldString("dateFormat");
720
            definition.addDynFieldString("defaultValue");
721
            definition.addDynFieldInt("index");
722
            definition.addDynFieldInt("maximumOccurrences");
723
            definition.addDynFieldInt("minimumOccurrences");
724
            definition.addDynFieldInt("size");
725
            definition.addDynFieldString("name");
726
            definition.addDynFieldString("objectClass");
727
            definition.addDynFieldInt("precision");
728
            definition.addDynFieldObject("evaluator")
729
                    .setClassOfValue(Evaluator.class);
730
            definition.addDynFieldBoolean("primaryKey");
731
            definition.addDynFieldBoolean("readOnly");
732
            definition.addDynFieldObject("SRS")
733
                    .setClassOfValue(IProjection.class);
734
            definition.addDynFieldInt("geometryType");
735
            definition.addDynFieldInt("geometrySubType");
736
//            definition.addDynFieldMap("additionalInfo");
737
            definition.addDynFieldBoolean("isAutomatic");
738
            definition.addDynFieldBoolean("isTime");
739
            definition.addDynFieldLong("interval_start");
740
            definition.addDynFieldLong("interval_end");
741
            definition.addDynFieldObject("featureAttributeEmulator")
742
                    .setClassOfValue(FeatureAttributeEmulator.class);
743
            definition.addDynFieldBoolean("indexed");
744
            definition.addDynFieldBoolean("isIndexAscending");
745
            definition.addDynFieldBoolean("allowIndexDuplicateds");
746
            definition.addDynFieldMap("availableValues");
747
            definition.addDynFieldString("description");
748
            definition.addDynFieldObject("minValue");
749
            definition.addDynFieldObject("maxValue");
750
            definition.addDynFieldString("label");
751
            definition.addDynFieldInt("order");
752
            definition.addDynFieldBoolean("hidden");
753
            definition.addDynFieldString("groupName");
754
            definition.addDynFieldInt("relationType");
755
            
756
            definition.addDynFieldObject("foreingKey")
757
                    .setClassOfValue(DefaultForeingKey.class);
758
            
759
            definition.addDynFieldObject("tags")
760
                    .setClassOfValue(Tags.class);
761
            
762
        }
763
    }
764

    
765
    
766
    /*
767
     * Start of DynField interface Implementation
768
     *
769
     */
770

    
771
    @Override
772
    public Tags getTags() {
773
        return tags;
774
    }
775

    
776
    @Override
777
    public DynObjectValueItem[] getAvailableValues() {
778
        if( this.availableValues == null ) {
779
            if( this.availableValuesFromForeingKey==null ) {
780
                if( this.isForeingKey() && this.foreingKey.isSelectable() ) {
781
                    this.availableValuesFromForeingKey = this.foreingKey.getAvailableValues(null);
782
                }
783
                return this.availableValuesFromForeingKey;
784
            }
785
        }
786
        return this.availableValues;
787
    }
788

    
789
    @Override
790
    public String getDescription() {
791
        if( this.description == null ) {
792
            return getName();
793
        }
794
        return this.description;
795
    }
796

    
797
    @Override
798
    public Object getMaxValue() {
799
        return this.maxValue;
800
    }
801

    
802
    @Override
803
    public Object getMinValue() {
804
        return this.minValue;
805
    }
806

    
807
    @Override
808
    public int getTheTypeOfAvailableValues() {
809
        return 1;
810
    }
811

    
812
    @Override
813
    public int getType() {
814
        if (featureAttributeGetter != null) {
815
            return featureAttributeGetter.getDataType().getType();
816
        }
817
        return getDataType().getType();
818
    }
819

    
820
    @Override
821
    public boolean isMandatory() {
822
        return !allowNull() || isPrimaryKey();
823
    }
824

    
825
    @Override
826
    public boolean isPersistent() {
827
        return false;
828
    }
829

    
830
    @Override
831
    public DynField setAvailableValues(DynObjectValueItem[] values) {
832
        if ( ArrayUtils.isEmpty(values) ) {
833
            this.availableValues = null;
834
        } else {
835
            this.availableValues = values;
836
        }
837
        return this;
838
    }
839

    
840
    @Override
841
    public DynField setDescription(String description) {
842
        this.description = description;
843
        return this;
844
    }
845

    
846
    @Override
847
    public DynField setMandatory(boolean mandatory) {
848
        throw new UnsupportedOperationException();
849
    }
850

    
851
    @Override
852
    public DynField setMaxValue(Object maxValue) {
853
        try {
854
            this.maxValue = this.coerce(maxValue);
855
        } catch (CoercionException e) {
856
            throw new IllegalArgumentException(e);
857
        }
858
        return this;
859
    }
860

    
861
    @Override
862
    public DynField setMinValue(Object minValue) {
863
        try {
864
            this.maxValue = this.coerce(minValue);
865
        } catch (CoercionException e) {
866
            throw new IllegalArgumentException(e);
867
        }
868
        return this;
869
    }
870

    
871
    @Override
872
    public DynField setPersistent(boolean persistent) {
873
        throw new UnsupportedOperationException();
874
    }
875

    
876
    @Override
877
    public DynField setTheTypeOfAvailableValues(int type) {
878
        throw new UnsupportedOperationException();
879
    }
880

    
881
    @Override
882
    public DynField setType(int type) {
883
        throw new UnsupportedOperationException();
884
    }
885

    
886
    @Override
887
    public DynField setDefaultDynValue(Object defaultValue) {
888
        throw new UnsupportedOperationException();
889
    }
890

    
891
    @Override
892
    public Class getClassOfValue() {
893
        return null;
894
    }
895

    
896
    @Override
897
    public DynField getElementsType() {
898
        return null;
899
    }
900

    
901
    @Override
902
    public DynField setClassOfValue(Class theClass)
903
            throws DynFieldIsNotAContainerException {
904
        throw new UnsupportedOperationException();
905
    }
906

    
907
    @Override
908
    public DynField setElementsType(DynStruct type)
909
            throws DynFieldIsNotAContainerException {
910
        throw new UnsupportedOperationException();
911
    }
912

    
913
    @Override
914
    public DynField setElementsType(int type)
915
            throws DynFieldIsNotAContainerException {
916
        throw new UnsupportedOperationException();
917
    }
918

    
919
    public FeatureAttributeDescriptor setDataProfileName(String dataProfile) {
920
        this.dataProfile = dataProfile;
921
        return this;
922
    }
923

    
924
    @Override
925
    public String getDataProfileName() {
926
        return dataProfile;
927
    }
928

    
929
    @Override
930
    public void validate(Object value) throws DynFieldValidateException {
931

    
932
        if (value == null && !this.allowNull()) {
933
            throw new DynFieldValidateException(value, this, null);
934
        }
935

    
936
        try {
937
            this.dataType.coerce(value);
938
        } catch (CoercionException e) {
939
            throw new DynFieldValidateException(value, this, e);
940
        }
941

    
942
        /*
943
         * Other checks will be needed
944
         */
945
    }
946

    
947
    @Override
948
    public String getSubtype() {
949
        if (featureAttributeGetter != null) {
950
            return featureAttributeGetter.getDataType().getSubtype();
951
        }
952
        return this.dataType.getSubtype();
953
    }
954

    
955
    @Override
956
    public Object coerce(Object value) throws CoercionException {
957
        if ( value == null ) {
958
            return value; // O debe devolver this.defaultValue
959
        }
960
        try {
961
            return this.getDataType().coerce(value);
962
        } catch(Exception ex){
963
            throw new RuntimeException(ex);
964
        }
965
    }
966

    
967
    @Override
968
    public DynField setAvailableValues(List values) {
969
        if (  values == null || values.isEmpty() ) {
970
            this.availableValues = null;
971
        } else {
972
            this.availableValues = (DynObjectValueItem[]) values.toArray(
973
                new DynObjectValueItem[values.size()]
974
            );
975
        }
976
        return this;
977
    }
978

    
979
    @Override
980
    public String getGroup() {
981
        return this.groupName;
982
    }
983

    
984
    @Override
985
    public int getOder() {
986
        return this.order;
987
    }
988

    
989
    @Override
990
    public String getLabel() {
991
        if( this.label == null ) {
992
            return this.getName();
993
        }
994
        return this.label;
995
    }
996

    
997
    @Override
998
    public DynField setLabel(String label) {
999
        this.label = label;
1000
        return this;
1001
    }
1002

    
1003
    @Override
1004
    public DynField setGroup(String groupName) {
1005
        this.groupName = groupName;
1006
        return this;
1007
    }
1008

    
1009
    @Override
1010
    public DynField setOrder(int order) {
1011
        this.order = order;
1012
        return this;
1013
    }
1014

    
1015
    @Override
1016
    public DynField setHidden(boolean hidden) {
1017
        this.hidden = hidden;
1018
        return this;
1019
    }
1020

    
1021
    @Override
1022
    public boolean isHidden() {
1023
        return this.hidden;
1024
    }
1025

    
1026
    @Override
1027
    public DynField setReadOnly(boolean arg0) {
1028
        throw new UnsupportedOperationException();
1029
    }
1030

    
1031
    @Override
1032
    public boolean isContainer() {
1033
        return false;
1034
    }
1035

    
1036
    @Override
1037
    public Class getClassOfItems() {
1038
        return null;
1039
    }
1040

    
1041
    @Override
1042
    public DynField setDefaultFieldValue(Object defaultValue) {
1043
        throw new UnsupportedOperationException();
1044
    }
1045

    
1046
    @Override
1047
    public DynField setClassOfItems(Class theClass) {
1048
        throw new UnsupportedOperationException();
1049
    }
1050

    
1051
    @Override
1052
    public DynField setType(DataType type) {
1053
        throw new UnsupportedOperationException();
1054
    }
1055

    
1056
    @Override
1057
    public DynField setSubtype(String subtype) {
1058
        throw new UnsupportedOperationException();
1059
    }
1060

    
1061
    @Override
1062
    public boolean isTime() {
1063
        return isTime;
1064
    }
1065

    
1066
    @Override
1067
    public FeatureAttributeGetter getFeatureAttributeGetter() {
1068
        return featureAttributeGetter;
1069
    }
1070

    
1071
    @Override
1072
    public void setFeatureAttributeGetter(
1073
            FeatureAttributeGetter featureAttributeTransform) {
1074
        this.featureAttributeGetter = featureAttributeTransform;
1075
    }
1076

    
1077
    @Override
1078
    public FeatureAttributeEmulator getFeatureAttributeEmulator() {
1079
        return this.featureAttributeEmulator;
1080
    }
1081

    
1082
    public FeatureAttributeDescriptor setFeatureAttributeEmulator(FeatureAttributeEmulator featureAttributeEmulator) {
1083
        this.featureAttributeEmulator = featureAttributeEmulator;
1084
        return this;
1085
    }
1086
        
1087
    @Override
1088
    public boolean isIndexed() {
1089
        return this.indexed;
1090
    }
1091
    
1092
    public boolean isForeingKey() {
1093
        return this.foreingKey!=null && this.foreingKey.isForeingKey();
1094
    }
1095
    
1096
    public ForeingKey getForeingKey() {
1097
        return this.foreingKey;
1098
    }
1099

    
1100
    @Override
1101
    public boolean allowIndexDuplicateds() {
1102
        return this.allowIndexDuplicateds;
1103
    }
1104

    
1105
    @Override
1106
    public boolean isIndexAscending() {
1107
        return this.isIndexAscending;
1108
    }
1109

    
1110
    @Override
1111
    public DynField setClassOfValue(DynStruct dynStrct) {
1112
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
1113
    }
1114

    
1115
    @Override
1116
    public DynField setClassOfValue(String theClassNameOfValue) {
1117
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
1118
    }
1119

    
1120
    @Override
1121
    public String getClassNameOfValue() {
1122
        return null;
1123
    }
1124

    
1125
    @Override
1126
    public DynStruct getDynClassOfValue() {
1127
        return null;
1128
    }
1129

    
1130
    @Override
1131
    public DynField setTypeOfItems(int type) {
1132
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
1133
    }
1134

    
1135
    @Override
1136
    public int getTypeOfItems() {
1137
        return DataTypes.INVALID;
1138
    }
1139

    
1140
    @Override
1141
    public DynField setClassOfItems(DynStruct dynStrct) {
1142
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
1143
    }
1144

    
1145
    @Override
1146
    public DynField setClassOfItems(String theClassNameOfValue) {
1147
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
1148
    }
1149

    
1150
    @Override
1151
    public String getClassNameOfItems() {
1152
        return null;
1153
    }
1154

    
1155
    @Override
1156
    public DynStruct getDynClassOfItems() {
1157
        return null;
1158
    }
1159

    
1160
    @Override
1161
    public DynField setRelationType(int relationType) {
1162
        this.relationType = relationType;
1163
        return this;
1164
    }
1165

    
1166
    @Override
1167
    public int getRelationType() {
1168
        return this.relationType;
1169
    }
1170

    
1171
    @Override
1172
    public DynField setAvailableValues(DynMethod availableValuesMethod) {
1173
        this.availableValuesMethod = availableValuesMethod;
1174
        return this;
1175
    }
1176

    
1177
    @Override
1178
    public DynObjectValueItem[] getAvailableValues(DynObject self) {
1179
        if( this.availableValuesMethod != null ) {
1180
            DynObjectValueItem[] values;
1181
            try {
1182
                values = (DynObjectValueItem[]) this.availableValuesMethod.invoke(self,new Object[] {this});
1183
            } catch (DynMethodException ex) {
1184
                return this.availableValues;
1185
            }
1186
            if( values != null ) {
1187
                return values;
1188
            }
1189
        }
1190
        return this.availableValues;
1191
    }
1192

    
1193
    @Override
1194
    public DynMethod getAvailableValuesMethod() {
1195
        return this.availableValuesMethod;
1196
    }
1197

    
1198
    @Override
1199
    public boolean isAvailableValuesCalculated() {
1200
        return this.availableValuesMethod!=null;
1201
    }
1202

    
1203
    @Override
1204
    public DynMethod getCalculateMethod() {
1205
        return this.calculateMethod;
1206
    }
1207

    
1208
    @Override
1209
    public DynField setCalculateMethod(DynMethod method) {
1210
        this.calculateMethod = method;
1211
        return this;
1212
    }
1213
    
1214
    @Override
1215
    public boolean isCalculated() {
1216
        return this.calculateMethod != null;
1217
    }
1218
    
1219
    @Override
1220
    public Object getCalculatedValue(DynObject self) {
1221
        try {
1222
            return this.calculateMethod.invoke(self, new Object[] { this });
1223
        } catch (DynMethodException ex) {
1224
            throw new RuntimeException(ex);
1225
        }
1226
    }
1227

    
1228
    @Override
1229
    public DynField setValidateElements(boolean validate) {
1230
        return this;
1231
    }
1232

    
1233
    @Override
1234
    public boolean getValidateElements() {
1235
        return false;
1236
    }
1237

    
1238
    private class ConstantValueEvaluator extends AbstractEvaluator {
1239

    
1240
        @Override
1241
        public Object evaluate(EvaluatorData data) throws EvaluatorException {
1242
            return defaultValue;
1243
        }
1244

    
1245
        @Override
1246
        public String getName() {
1247
            return "Constant attribute " + name;
1248
        }
1249
    }
1250

    
1251
    public void setConstantValue(boolean isConstantValue) {
1252
        if (isConstantValue) {
1253
            /* Cuando un attributo tiene asociado un evaluador, este se interpreta
1254
             * como que no debe cargarse de la fuente de datos subyacente, siendo
1255
             * el evaluador el que se encarga de proporcionar su valor.
1256
             * Nos limitamos a asignar un evaluador que retorna simpre el valor
1257
             * por defecto para ese attributo.
1258
             */
1259
            this.evaluator = new ConstantValueEvaluator();
1260
        } else {
1261
            this.evaluator = null;
1262
        }
1263
    }
1264

    
1265
    @Override
1266
    public boolean isComputed() {
1267
        return featureAttributeEmulator!=null || evaluator!=null || isCalculated();
1268
    }
1269

    
1270
    @Override
1271
    public FeatureStore getStore() {
1272
        FeatureType ftype = this.getFeatureType();
1273
        if( ftype == null ) {
1274
            return null;
1275
        }
1276
        return ftype.getStore();
1277
    }
1278
    
1279
    @Override
1280
    public FeatureType getFeatureType() {
1281
        if( this.typeRef==null ) {
1282
            return null;
1283
        }
1284
        FeatureType ftype = (FeatureType) this.typeRef.get();
1285
//        LOGGER.info(String.format("FeatureAttributeDescriptor[%08x] get FeatureType [%08x], ref [%08x].", this.hashCode(), ftype.hashCode(), typeRef.hashCode()));
1286
        return ftype;
1287
    }
1288

    
1289
    public FeatureAttributeDescriptor setInterval(Interval interval) {
1290
        this.interval = interval;
1291
        return this;
1292
    }
1293

    
1294
    public void fixAll() {
1295
        switch(this.getType()) {
1296
            case DataTypes.INSTANT:
1297
            case DataTypes.INTERVAL:
1298
            case DataTypes.DATE:
1299
                if( this.getInterval()!=null ) {
1300
                    this.isTime = true;
1301
                }
1302
                break;
1303
        }
1304
    }
1305

    
1306
    @Override
1307
    public String[] getRequiredFieldNames() {
1308
        FeatureAttributeEmulator emulator = this.getFeatureAttributeEmulator();
1309
        if( emulator==null ) {
1310
            return null;
1311
        }
1312
        return emulator.getRequiredFieldNames();
1313
    }
1314

    
1315
    @Override
1316
    public void recentUsed() {
1317
        DefaultFeatureType.RECENTS_USEDS.add(this);
1318
    }
1319

    
1320
}