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

History | View | Annotate | Download (44.6 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.math.BigDecimal;
27
import java.math.MathContext;
28
import java.math.RoundingMode;
29
import java.text.DateFormat;
30
import java.util.HashMap;
31
import java.util.Iterator;
32
import java.util.LinkedHashMap;
33
import java.util.List;
34
import java.util.Locale;
35
import java.util.Map;
36
import java.util.Map.Entry;
37
import java.util.Objects;
38
import java.util.logging.Level;
39
import org.apache.commons.lang3.ArrayUtils;
40
import org.apache.commons.lang3.StringUtils;
41
import org.cresques.cts.IProjection;
42
import org.gvsig.expressionevaluator.ExpressionUtils;
43
import org.gvsig.fmap.dal.DALLocator;
44
import org.gvsig.fmap.dal.DataStore;
45
import org.gvsig.fmap.dal.DataTypes;
46
import org.gvsig.fmap.dal.feature.DataProfile;
47
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
48
import org.gvsig.fmap.dal.feature.FeatureAttributeEmulator;
49
import org.gvsig.fmap.dal.feature.FeatureAttributeGetter;
50
import org.gvsig.fmap.dal.feature.FeatureStore;
51
import org.gvsig.fmap.dal.feature.FeatureType;
52
import org.gvsig.fmap.dal.feature.ForeingKey;
53
import org.gvsig.fmap.geom.Geometry;
54
import org.gvsig.fmap.geom.GeometryException;
55
import org.gvsig.fmap.geom.GeometryLocator;
56
import org.gvsig.fmap.geom.GeometryUtils;
57
import org.gvsig.fmap.geom.type.GeometryType;
58
import org.gvsig.timesupport.Interval;
59
import org.gvsig.timesupport.RelativeInterval;
60
import org.gvsig.timesupport.TimeSupportLocator;
61
import org.gvsig.tools.ToolsLocator;
62
import org.gvsig.tools.dataTypes.Coercion;
63
import org.gvsig.tools.dataTypes.CoercionException;
64
import org.gvsig.tools.dataTypes.DataType;
65
import org.gvsig.tools.dataTypes.DataTypeUtils;
66
import org.gvsig.tools.dynobject.DynField;
67
import org.gvsig.tools.dynobject.DynField_LabelAttribute;
68
import org.gvsig.tools.dynobject.DynField_v2;
69
import org.gvsig.tools.dynobject.DynMethod;
70
import org.gvsig.tools.dynobject.DynObject;
71
import org.gvsig.tools.dynobject.DynObjectValueItem;
72
import org.gvsig.tools.dynobject.DynStruct;
73
import org.gvsig.tools.dynobject.Tags;
74
import org.gvsig.tools.dynobject.exception.DynFieldIsNotAContainerException;
75
import org.gvsig.tools.dynobject.exception.DynFieldValidateException;
76
import org.gvsig.tools.dynobject.exception.DynMethodException;
77
import org.gvsig.tools.dynobject.impl.DefaultTags;
78
import org.gvsig.tools.evaluator.AbstractEvaluator;
79
import org.gvsig.tools.evaluator.Evaluator;
80
import org.gvsig.tools.evaluator.EvaluatorData;
81
import org.gvsig.tools.evaluator.EvaluatorException;
82
import org.gvsig.tools.i18n.I18nManager;
83
import org.gvsig.tools.persistence.PersistenceManager;
84
import org.gvsig.tools.persistence.Persistent;
85
import org.gvsig.tools.persistence.PersistentState;
86
import org.gvsig.tools.persistence.exception.PersistenceException;
87
import org.slf4j.Logger;
88
import org.slf4j.LoggerFactory;
89
import org.gvsig.tools.dataTypes.CoercionContext;
90
import org.gvsig.tools.dataTypes.DataType.NumberPrecisionAndScale;
91

    
92
@SuppressWarnings("UseSpecificCatch")
93
public class DefaultFeatureAttributeDescriptor implements
94
        FeatureAttributeDescriptor, Persistent, DynField_v2, DynField_LabelAttribute {
95

    
96
  protected static final Logger LOGGER = LoggerFactory.getLogger(DefaultFeatureAttributeDescriptor.class);
97

    
98
  protected boolean allowNull;
99
  protected DataType dataType;
100
  protected String dataProfile;
101
  protected DateFormat dateFormat;
102
  protected Object defaultValue;
103
  protected int index;
104
  protected int maximumOccurrences;
105
  protected int minimumOccurrences;
106
  protected int size;
107
  protected String name;
108
  protected Class objectClass;
109
  protected int precision;
110
  protected int scale;
111
  protected int roundMode;
112
  protected Evaluator evaluator;
113
  protected boolean primaryKey;
114
  protected boolean readOnly;
115
  protected IProjection SRS;
116
  protected GeometryType geomType;
117
  protected int geometryType;
118
  protected int geometrySubType;
119
  protected Map additionalInfo;
120
  protected boolean isAutomatic;
121
  protected boolean isTime = false;
122
  protected Interval interval;
123
  protected FeatureAttributeGetter featureAttributeGetter = null;
124
  protected FeatureAttributeEmulator featureAttributeEmulator = null;
125
  protected boolean indexed = false;
126
  protected boolean isIndexAscending = true;
127
  protected boolean allowIndexDuplicateds = true;
128

    
129
  protected DynObjectValueItem[] availableValues;
130
  private Map<Object, String> labelOfValueMap; // No persistente
131
  protected String description;
132
  protected Object minValue;
133
  protected Object maxValue;
134
  protected String label;
135
  protected String shortLabel;
136
  protected int order;
137
  protected boolean hidden;
138
  protected String groupName;
139
  protected Tags tags = new DefaultTags();
140
  private DynMethod availableValuesMethod;
141
  private DynMethod calculateMethod;
142
  private WeakReference typeRef;
143
  protected DefaultForeingKey foreingKey = null;
144

    
145
  protected CoercionContext coerceContext = null; // not persistent
146
  protected MathContext mathContext = null; // not persistent
147

    
148
  private int relationType = RELATION_TYPE_NONE;
149
  protected Locale locale;
150

    
151
  public DefaultFeatureAttributeDescriptor() {
152
    // Usada en la persistencia
153
    this.precision = DataType.PRECISION_NONE;
154
    this.scale = DataType.SCALE_NONE;
155
    this.roundMode = BigDecimal.ROUND_HALF_UP;
156
  }
157

    
158
  protected DefaultFeatureAttributeDescriptor(FeatureType type) {
159
    this();
160
//        LOGGER.info(String.format("Created FeatureAttributeDescriptor [%08x].", this.hashCode()));
161
    setFeatureType(type);
162
    this.allowNull = true;
163
    this.dataType = null;
164
    this.dateFormat = null;
165
    this.defaultValue = null;
166
    this.index = -1;
167
    this.maximumOccurrences = 0;
168
    this.minimumOccurrences = 0;
169
    this.size = 0;
170
    this.name = null;
171
    this.objectClass = null;
172
    this.precision = DataType.PRECISION_NONE;
173
    this.scale = DataType.SCALE_NONE;
174
    this.roundMode = BigDecimal.ROUND_HALF_UP;
175
    this.evaluator = null;
176
    this.primaryKey = false;
177
    this.readOnly = false;
178
    this.SRS = null;
179
    this.geometryType = Geometry.TYPES.NULL;
180
    this.geometrySubType = Geometry.SUBTYPES.UNKNOWN;
181
    this.additionalInfo = null;
182
    this.isAutomatic = false;
183
    this.hidden = false;
184
    this.relationType = RELATION_TYPE_NONE;
185
    this.locale = null;
186
  }
187

    
188
  protected DefaultFeatureAttributeDescriptor(
189
          DefaultFeatureAttributeDescriptor other
190
  ) {
191
    this();
192
    copyFrom(other);
193
//        LOGGER.info(String.format("Created FeatureAttributeDescriptor [%08x] [%s] (copy).", this.hashCode(), this.name));
194
  }
195

    
196
  @Override
197
  public void copyFrom(DynField other1) {
198
    if (!(other1 instanceof DefaultFeatureAttributeDescriptor)) {
199
      throw new IllegalArgumentException("Can't copy from a non DefaultFeatureAttributeDescriptor");
200
    }
201
    DefaultFeatureAttributeDescriptor other = (DefaultFeatureAttributeDescriptor) other1;
202
    this.typeRef = other.typeRef;
203
    this.allowNull = other.allowNull;
204
    this.dataType = other.dataType;
205
    this.dateFormat = other.dateFormat;
206
    this.defaultValue = other.defaultValue;
207
    this.index = other.index;
208
    this.maximumOccurrences = other.maximumOccurrences;
209
    this.minimumOccurrences = other.minimumOccurrences;
210
    this.size = other.size;
211
    this.name = other.name;
212
    this.objectClass = other.objectClass;
213
    this.precision = other.precision;
214
    this.scale = other.scale;
215
    this.roundMode = other.roundMode;
216
    this.evaluator = other.evaluator;
217
    this.primaryKey = other.primaryKey;
218
    this.readOnly = other.readOnly;
219
    this.SRS = other.SRS;
220
    this.geometryType = other.geometryType;
221
    this.geometrySubType = other.geometrySubType;
222
    this.geomType = other.geomType;
223
    if (other.additionalInfo != null) {
224
      Iterator iter = other.additionalInfo.entrySet().iterator();
225
      Map.Entry entry;
226
      this.additionalInfo = new HashMap();
227
      while (iter.hasNext()) {
228
        entry = (Entry) iter.next();
229
        this.additionalInfo.put(entry.getKey(), entry.getValue());
230
      }
231
    } else {
232
      this.additionalInfo = null;
233
    }
234
    this.isAutomatic = other.isAutomatic;
235
    this.isTime = other.isTime;
236
    this.featureAttributeEmulator = other.featureAttributeEmulator;
237
    this.indexed = other.indexed;
238
    this.isIndexAscending = other.isIndexAscending;
239
    this.allowIndexDuplicateds = other.allowIndexDuplicateds;
240
    this.hidden = other.hidden;
241
    this.dataProfile = other.dataProfile;
242

    
243
    this.availableValues = other.availableValues;
244
    this.description = other.description;
245
    this.minValue = other.minValue;
246
    this.maxValue = other.maxValue;
247
    this.label = other.label;
248
    this.order = other.order;
249
    this.groupName = other.groupName;
250
    if (other.tags == null) {
251
      this.tags = null;
252
    } else {
253
      try {
254
        this.tags = (Tags) other.tags.clone();
255
      } catch (Exception ex) {
256
      }
257
    }
258
    this.foreingKey = null;
259
    if (other.foreingKey != null) {
260
      try {
261
        this.foreingKey = (DefaultForeingKey) other.foreingKey.clone();
262
      } catch (CloneNotSupportedException ex) {
263
      }
264
    }
265
    if (this.foreingKey != null) {
266
      this.foreingKey.setDescriptor(this);
267
    }
268

    
269
    // TODO: ? Habria que clonarlos ?
270
    this.availableValuesMethod = other.availableValuesMethod;
271
    this.calculateMethod = other.calculateMethod;
272
    this.relationType = other.relationType;
273
    this.locale = other.locale;
274
  }
275

    
276
  public void setFeatureType(FeatureType type) {
277
    // Usada en la persistencia
278
    if (type == null) {
279
      this.typeRef = null;
280
    } else {
281
      this.typeRef = new WeakReference(type);
282
//            LOGGER.info(String.format("FeatureAttributeDescriptor[%08x] set FeatureType [%08x], ref [%08x].", this.hashCode(), type.hashCode(), typeRef.hashCode()));
283
    }
284
  }
285

    
286
  @Override
287
  public String getDataTypeName() {
288
    if (this.getDataType() == null) {
289
      return "(unknow)";
290
    }
291
    return this.getDataType().getName();
292
  }
293

    
294
  @Override
295
  public DefaultFeatureAttributeDescriptor getCopy() {
296
    return new DefaultFeatureAttributeDescriptor(this);
297
  }
298

    
299
  @Override
300
  public Object clone() throws CloneNotSupportedException {
301
    return new DefaultFeatureAttributeDescriptor(this);
302
  }
303

    
304
  @Override
305
  public boolean allowNull() {
306
    return allowNull;
307
  }
308

    
309
  @Override
310
  public Locale getLocale() {
311
    if( this.locale == null ) {
312
      if( this.dataType.isNumeric() ) {
313
        this.locale = Locale.ENGLISH;
314
      } else {
315
        this.locale = Locale.getDefault();
316
      }
317
    }
318
    return this.locale;
319
  }
320

    
321
  @Override
322
  public DataType getDataType() {
323
    if (featureAttributeGetter != null) {
324
      return featureAttributeGetter.getDataType();
325
    }
326
    return this.dataType;
327
  }
328

    
329
  public FeatureAttributeDescriptor setDataType(int type) {
330
    this.dataType = ToolsLocator.getDataTypesManager().get(type);
331
    return this;
332
  }
333

    
334
  @Override
335
  public DateFormat getDateFormat() {
336
    return this.dateFormat;
337
  }
338

    
339
  @Override
340
  public Object getDefaultValue() {
341
    return this.defaultValue;
342
  }
343

    
344
  @Override
345
  public Object getDefaultValueCoerced() {
346
    try {
347
      Object value = this.defaultValue;
348
      if (value == null) {
349
        return null;
350
      }
351
      if (ExpressionUtils.isDynamicText(value.toString())) {
352
        value = ExpressionUtils.evaluateDynamicText(value.toString());
353
      }
354
      return this.getDataType().coerce(value);
355
    } catch (CoercionException ex) {
356
      return null;
357
    }
358
  }
359

    
360
  @Override
361
  public Evaluator getEvaluator() {
362
    return this.evaluator;
363
  }
364

    
365
  @Override
366
  public int getGeometryType() {
367
    if (this.dataType.getType() != DataTypes.GEOMETRY) {
368
      return Geometry.TYPES.UNKNOWN;
369
    }
370
    return this.geometryType;
371
  }
372

    
373
  @Override
374
  public int getGeometrySubType() {
375
    if (this.dataType.getType() != DataTypes.GEOMETRY) {
376
      return Geometry.SUBTYPES.UNKNOWN;
377
    }
378
    return this.geometrySubType;
379
  }
380

    
381
  @Override
382
  public GeometryType getGeomType() {
383
    if (this.dataType.getType() != DataTypes.GEOMETRY) {
384
      return null;
385
    }
386
    if (this.geomType == null) {
387
      try {
388
        this.geomType
389
                = GeometryLocator.getGeometryManager().getGeometryType(
390
                        this.geometryType, this.geometrySubType);
391
      } catch (GeometryException e) {
392
        throw new RuntimeException(
393
                "Error getting geometry type with type = "
394
                + this.geometryType + ", subtype = "
395
                + this.geometrySubType, e);
396
      }
397
    }
398
    return this.geomType;
399
  }
400

    
401
  @Override
402
  public int getIndex() {
403
    return this.index;
404
  }
405

    
406
  protected FeatureAttributeDescriptor setIndex(int index) {
407
    this.index = index;
408
    return this;
409
  }
410

    
411
  @Override
412
  public int getMaximumOccurrences() {
413
    return this.maximumOccurrences;
414
  }
415

    
416
  @Override
417
  public int getMinimumOccurrences() {
418
    return this.minimumOccurrences;
419
  }
420

    
421
  @Override
422
  public String getName() {
423
    return this.name;
424
  }
425

    
426
  public FeatureAttributeDescriptor setName(String name) {
427
//        LOGGER.info(String.format("FeatureAttributeDescriptor[%08x] set name [%s].", this.hashCode(), name));
428
    this.name = name;
429
    return this;
430
  }
431

    
432
  @Override
433
  public Class getObjectClass() {
434
    if (getDataType().getType() == DataTypes.OBJECT) {
435
      return objectClass;
436
    }
437
    return getDataType().getDefaultClass();
438
  }
439

    
440
  @Override
441
  public int getPrecision() {
442
    return this.precision;
443
  }
444

    
445
  @Override
446
  public int getScale() {
447
    return this.scale;
448
  }
449

    
450
  @Override
451
  public Coercion getCoercion() {
452
    return this.getDataType().getCoercion();
453
  }
454

    
455
  @Override
456
  public MathContext getMathContext() {
457
    if (this.mathContext == null) {
458
      if (this.getDataType().isNumeric()) {
459
        this.mathContext = new MathContext(
460
                this.getPrecision(),
461
                RoundingMode.valueOf(this.getRoundMode())
462
        );
463
      } else {
464
        this.mathContext = MathContext.UNLIMITED;
465
      }
466
    }
467
    return this.mathContext;
468
  }
469

    
470
  @Override
471
  public CoercionContext getCoercionContext() {
472
    if (this.coerceContext == null) {
473
      if (this.getDataType().isNumeric()) {
474
        this.coerceContext = DataTypeUtils.coerceContextDecimal(
475
                this.getLocale(),
476
                this.getPrecision(),
477
                this.getScale(),
478
                this.getRoundMode()
479
        );
480
      } else {
481
        this.coerceContext = DataTypeUtils.coerceContextLocale(
482
                this.getLocale()
483
        );
484
      }
485
    }
486
    return this.coerceContext;
487
  }
488

    
489
  @Override
490
  public int getRoundMode() {
491
    return this.roundMode;
492
  }
493

    
494
  @Override
495
  public IProjection getSRS() {
496
    return this.SRS;
497
  }
498

    
499
  @Override
500
  public Interval getInterval() {
501
    return this.interval;
502
  }
503

    
504
  public IProjection getSRS(WeakReference storeRef) {
505
    if (this.SRS == null) {
506
      FeatureStore store = (FeatureStore) storeRef.get();
507
      this.SRS = (IProjection) store.getDynValue(DataStore.METADATA_CRS);
508
    }
509
    return this.SRS;
510
  }
511

    
512
  @Override
513
  public int getSize() {
514
    return this.size;
515
  }
516

    
517
  @Override
518
  public boolean isPrimaryKey() {
519
    return this.primaryKey;
520
  }
521

    
522
  @Override
523
  public boolean isReadOnly() {
524
    if (this.readOnly) {
525
      return true;
526
    }
527
    return this.isComputed();
528
  }
529

    
530
  @Override
531
  public Object getAdditionalInfo(String infoName) {
532
    if (this.additionalInfo == null) {
533
      return null;
534
    }
535
    return this.additionalInfo.get(infoName);
536
  }
537

    
538
  @Override
539
  public boolean isAutomatic() {
540
    return this.isAutomatic;
541
  }
542

    
543
  @Override
544
  public boolean equals(Object obj) {
545
    if (this == obj) {
546
      return true;
547
    }
548
    if (!(obj instanceof DefaultFeatureAttributeDescriptor)) {
549
      return false;
550
    }
551
    DefaultFeatureAttributeDescriptor other
552
            = (DefaultFeatureAttributeDescriptor) obj;
553

    
554
    if (this.allowNull != other.allowNull) {
555
      return false;
556
    }
557

    
558
    if (this.index != other.index) {
559
      return false;
560
    }
561

    
562
    if (!Objects.equals(this.name, other.name)) {
563
      return false;
564
    }
565

    
566
    if (this.getDataType() != other.getDataType()) {
567
      return false;
568
    }
569

    
570
    if (this.size != other.size) {
571
      return false;
572
    }
573

    
574
    if (!Objects.equals(this.defaultValue, other.defaultValue)) {
575
      return false;
576
    }
577

    
578
    if (this.primaryKey != other.primaryKey) {
579
      return false;
580
    }
581

    
582
    if (this.isAutomatic != other.isAutomatic) {
583
      return false;
584
    }
585

    
586
    if (this.readOnly != other.readOnly) {
587
      return false;
588
    }
589

    
590
    if (this.precision != other.precision) {
591
      return false;
592
    }
593

    
594
    if (this.maximumOccurrences != other.maximumOccurrences) {
595
      return false;
596
    }
597

    
598
    if (this.minimumOccurrences != other.minimumOccurrences) {
599
      return false;
600
    }
601

    
602
    if (this.geometryType != other.geometryType) {
603
      return false;
604
    }
605

    
606
    if (this.geometrySubType != other.geometrySubType) {
607
      return false;
608
    }
609

    
610
    if (!Objects.equals(this.evaluator, other.evaluator)) {
611
      return false;
612
    }
613

    
614
    if (!Objects.equals(this.featureAttributeEmulator, other.featureAttributeEmulator)) {
615
      return false;
616
    }
617

    
618
    if (!Objects.equals(this.SRS, other.SRS)) {
619
      return false;
620
    }
621

    
622
    if (!Objects.equals(this.dateFormat, other.dateFormat)) {
623
      return false;
624
    }
625

    
626
    if (!Objects.equals(this.objectClass, other.objectClass)) {
627
      return false;
628
    }
629

    
630
    if (!Objects.equals(this.dataProfile, other.dataProfile)) {
631
      return false;
632
    }
633

    
634
    return true;
635
  }
636

    
637
  @Override
638
  public void loadFromState(PersistentState state)
639
          throws PersistenceException {
640
    allowNull = state.getBoolean("allowNull");
641
    dataType = ToolsLocator.getDataTypesManager().get(state.getInt("dataType"));
642
    dataProfile = state.getString("dataProfile");
643

    
644
//        FIXME: dateFormat;
645
    try {
646
      defaultValue = dataType.coerce(state.get("defaultValue"));
647
    } catch (CoercionException ex) {
648
    }
649

    
650
    index = state.getInt("index");
651
    maximumOccurrences = state.getInt("maximumOccurrences");
652
    minimumOccurrences = state.getInt("minimumOccurrences");
653
    size = state.getInt("size");
654
    name = state.getString("name");
655
    try {
656
      String objectClassName = state.getString("objectClass");
657
      if (!StringUtils.isBlank(objectClassName)) {
658
        objectClass = Class.forName(objectClassName);
659
      }
660
    } catch (Throwable e) {
661
      LOGGER.warn("Can't restore the objectClass of the FeatureAttributreDescriptor", e);
662
    }
663
    precision = state.getInt("precision");
664
    scale = state.getInt("scale");
665
    roundMode = state.getInt("roundMode");
666
    String locale_s = state.getString("locale");
667
    locale = StringUtils.isBlank(locale_s) ? null : Locale.forLanguageTag(locale_s);
668
    evaluator = (Evaluator) state.get("evaluator");
669
    primaryKey = state.getBoolean("primaryKey");
670
    readOnly = state.getBoolean("readOnly");
671
    SRS = (IProjection) state.get("SRS");
672
    geometryType = state.getInt("geometryType");
673
    geometrySubType = state.getInt("geometrySubType");
674
    if (geometryType != Geometry.TYPES.UNKNOWN
675
            && geometrySubType != Geometry.SUBTYPES.UNKNOWN) {
676
      geomType = GeometryUtils.getGeometryType(
677
              geometryType,
678
              geometrySubType
679
      );
680
    }
681
//        additionalInfo = (Map) state.get("aditionalInfo");
682
    isAutomatic = state.getBoolean("isAutomatic");
683
    isTime = state.getBoolean("isTime");
684
    if (state.hasValue("intervalStart")) {
685
      long intervalStart = state.getLong("interval_start");
686
      long intervalEnd = state.getLong("interval_end");
687
      interval = TimeSupportLocator.getManager().createRelativeInterval(intervalStart, intervalEnd);
688
    } else {
689
      interval = null;
690
    }
691
    featureAttributeEmulator = (FeatureAttributeEmulator) state.get("featureAttributeEmulator");
692
    indexed = state.getBoolean("indexed");
693
    isIndexAscending = state.getBoolean("isIndexAscending");
694
    allowIndexDuplicateds = state.getBoolean("allowIndexDuplicateds");
695

    
696
    Map<String, Object> values = state.getMap("availableValues");
697
    if (values == null || values.isEmpty()) {
698
      this.availableValues = null;
699
    } else {
700
      this.availableValues = new DynObjectValueItem[values.size()];
701
      int n = 0;
702
      for (Entry<String, Object> entry : values.entrySet()) {
703
        this.availableValues[n++] = new DynObjectValueItem(entry.getValue(), entry.getKey());
704
      }
705
    }
706

    
707
    description = state.getString("description");
708
    minValue = state.get("minValue");
709
    maxValue = state.get("maxValue");
710
    label = state.getString("label");
711
    order = state.getInt("order");
712
    hidden = state.getBoolean("hidden");
713
    groupName = state.getString("groupName");
714
    relationType = state.getInt("relationType");
715

    
716
    foreingKey = (DefaultForeingKey) state.get("foreingKey");
717
    if (foreingKey != null) {
718
      this.foreingKey.setDescriptor(this);
719
    }
720
    tags = (Tags) state.get("tags");
721
    if (tags == null) {
722
      this.tags = new DefaultTags();
723
    }
724
  }
725

    
726
  @Override
727
  public void saveToState(PersistentState state) throws PersistenceException {
728
    Coercion toString = ToolsLocator.getDataTypesManager().getCoercion(DataTypes.STRING);
729
    
730
    state.set("allowNull", allowNull);
731
    state.set("dataType", dataType.getType());
732
    state.set("dataProfile", dataProfile);
733

    
734
//        FIXME: dateFormat;
735
    state.set("defaultValue", Objects.toString(defaultValue, null));
736

    
737
    state.set("index", index);
738
    state.set("maximumOccurrences", maximumOccurrences);
739
    state.set("minimumOccurrences", minimumOccurrences);
740
    state.set("size", size);
741
    state.set("name", name);
742
    state.set("objectClass", objectClass == null ? null : objectClass.getName());
743
    state.set("precision", precision);
744
    state.set("scale", scale);
745
    state.set("roundMode", roundMode);
746
    try {
747
      if( this.locale == null ) {
748
        state.setNull("locale");
749
      } else {
750
        state.set("locale", toString.coerce(this.locale));
751
      }
752
    } catch (CoercionException ex) {
753
      state.setNull("locale");
754
    }
755
    state.set("evaluator", evaluator);
756

    
757
    state.set("primaryKey", primaryKey);
758
    state.set("readOnly", readOnly);
759
    state.set("SRS", SRS);
760
    GeometryType theGeomType = this.getGeomType();
761
    if (theGeomType == null) {
762
      state.set("geometryType", Geometry.TYPES.UNKNOWN);
763
      state.set("geometrySubType", Geometry.SUBTYPES.UNKNOWN);
764
    } else {
765
      state.set("geometryType", theGeomType.getType());
766
      state.set("geometrySubType", theGeomType.getSubType());
767
    }
768

    
769
//      FIXME: additionalInfo
770
    state.set("isAutomatic", isAutomatic);
771
    state.set("isTime", isTime);
772
    if (this.interval == null) {
773
      state.setNull("interval_start");
774
      state.setNull("interval_end");
775
    } else {
776
      state.set("interval_start", ((RelativeInterval) interval).getStart().toMillis());
777
      state.set("interval_end", ((RelativeInterval) interval).getEnd().toMillis());
778
    }
779
    state.set("SRS", SRS);
780

    
781
//      FIXME: featureAttributeGetter
782
    if (featureAttributeEmulator instanceof Persistent) {
783
      state.set("featureAttributeEmulator", featureAttributeEmulator);
784
    } else {
785
      state.setNull("featureAttributeEmulator");
786
    }
787

    
788
    state.set("indexed", indexed);
789
    state.set("isIndexAscending", isIndexAscending);
790
    state.set("allowIndexDuplicateds", allowIndexDuplicateds);
791

    
792
    if (this.availableValues == null) {
793
      state.setNull("availableValues");
794
    } else {
795
      Map<String, Object> values = new LinkedHashMap<>();
796
      for (DynObjectValueItem value : availableValues) {
797
        values.put(value.getLabel(), value.getValue());
798
      }
799
      state.set("availableValues", values);
800
    }
801
    state.set("description", description);
802
    state.set("minValue", minValue);
803
    state.set("maxValue", maxValue);
804
    state.set("label", label);
805
    state.set("order", order);
806
    state.set("hidden", hidden);
807
    state.set("groupName", groupName);
808
    state.set("relationType", relationType);
809

    
810
    state.set("foreingKey", this.foreingKey);
811
    state.set("tags", this.tags);
812

    
813
  }
814

    
815
  private static final String FEATATTRDESC_PERSISTENCE_DEFINITION_NAME = "FeatureAttributeDescriptor";
816

    
817
  public static void registerPersistenceDefinition() {
818
    PersistenceManager manager = ToolsLocator.getPersistenceManager();
819

    
820
    if (manager.getDefinition(FEATATTRDESC_PERSISTENCE_DEFINITION_NAME)
821
            == null) {
822
      DynStruct definition = manager.addDefinition(DefaultFeatureAttributeDescriptor.class,
823
              FEATATTRDESC_PERSISTENCE_DEFINITION_NAME,
824
              FEATATTRDESC_PERSISTENCE_DEFINITION_NAME
825
              + " persistent definition",
826
              null,
827
              null
828
      );
829
      definition.addDynFieldBoolean("allowNull");
830
      definition.addDynFieldInt("dataType");
831
      definition.addDynFieldString("dataProfile");
832
//            definition.addDynFieldString("dateFormat");
833
      definition.addDynFieldString("defaultValue");
834
      definition.addDynFieldInt("index");
835
      definition.addDynFieldInt("maximumOccurrences");
836
      definition.addDynFieldInt("minimumOccurrences");
837
      definition.addDynFieldInt("size");
838
      definition.addDynFieldString("name");
839
      definition.addDynFieldString("objectClass");
840
      definition.addDynFieldInt("precision");
841
      definition.addDynFieldInt("scale").setMandatory(false).setDefaultDynValue(DataType.SCALE_NONE);
842
      definition.addDynFieldInt("roundMode").setMandatory(false).setDefaultDynValue(BigDecimal.ROUND_HALF_UP);
843
      definition.addDynFieldString("locale").setMandatory(false).setDefaultDynValue("null");
844
      definition.addDynFieldObject("evaluator").setClassOfValue(Evaluator.class);
845
      definition.addDynFieldBoolean("primaryKey");
846
      definition.addDynFieldBoolean("readOnly");
847
      definition.addDynFieldObject("SRS")
848
              .setClassOfValue(IProjection.class);
849
      definition.addDynFieldInt("geometryType");
850
      definition.addDynFieldInt("geometrySubType");
851
//            definition.addDynFieldMap("additionalInfo");
852
      definition.addDynFieldBoolean("isAutomatic");
853
      definition.addDynFieldBoolean("isTime");
854
      definition.addDynFieldLong("interval_start");
855
      definition.addDynFieldLong("interval_end");
856
      definition.addDynFieldObject("featureAttributeEmulator")
857
              .setClassOfValue(FeatureAttributeEmulator.class);
858
      definition.addDynFieldBoolean("indexed");
859
      definition.addDynFieldBoolean("isIndexAscending");
860
      definition.addDynFieldBoolean("allowIndexDuplicateds");
861
      definition.addDynFieldMap("availableValues")
862
              .setClassOfItems(Object.class);
863
      definition.addDynFieldString("description");
864
      definition.addDynFieldObject("minValue");
865
      definition.addDynFieldObject("maxValue");
866
      definition.addDynFieldString("label");
867
      definition.addDynFieldInt("order");
868
      definition.addDynFieldBoolean("hidden");
869
      definition.addDynFieldString("groupName");
870
      definition.addDynFieldInt("relationType");
871

    
872
      definition.addDynFieldObject("foreingKey")
873
              .setClassOfValue(DefaultForeingKey.class);
874

    
875
      definition.addDynFieldObject("tags")
876
              .setClassOfValue(Tags.class);
877

    
878
    }
879
  }
880

    
881
  /*
882
     * Start of DynField interface Implementation
883
     *
884
   */
885
  @Override
886
  public Tags getTags() {
887
    return tags;
888
  }
889

    
890
  @Override
891
  public boolean hasConstantAvailableValues() {
892
    return this.availableValues != null;
893
  }
894

    
895
  @Override
896
  public DynObjectValueItem[] getAvailableValues() {
897
    if (this.availableValues == null) {
898
      if (this.isForeingKey() && this.foreingKey.isClosedList()) {
899
        return this.foreingKey.getAvailableValues(null);
900
      }
901
    }
902
    return this.availableValues;
903
  }
904

    
905
  @Override
906
  public String getLabelOfValue(Object value) {
907
    if (this.labelOfValueMap != null) {
908
      String theLabel = this.labelOfValueMap.get(value);
909
      if (theLabel == null) {
910
        theLabel = Objects.toString(value, "");
911
      }
912
      return theLabel;
913
    }
914
    DynObjectValueItem[] values = this.getAvailableValues();
915
    if (values == null) {
916
      return Objects.toString(value, "");
917
    }
918
    Map<Object, String> map = new LinkedHashMap<>();
919
    for (DynObjectValueItem theValue : values) {
920
      map.put(theValue.getValue(), theValue.getLabel());
921
    }
922
    this.labelOfValueMap = map;
923
    String theLabel = this.labelOfValueMap.get(value);
924
    if (theLabel == null) {
925
      theLabel = Objects.toString(value, "");
926
    }
927
    return theLabel;
928
  }
929

    
930
  @Override
931
  public String getDescription() {
932
    if (this.description == null) {
933
      return getName();
934
    }
935
    return this.description;
936
  }
937

    
938
  @Override
939
  public Object getMaxValue() {
940
    return this.maxValue;
941
  }
942

    
943
  @Override
944
  public Object getMinValue() {
945
    return this.minValue;
946
  }
947

    
948
  @Override
949
  public int getTheTypeOfAvailableValues() {
950
    return 1;
951
  }
952

    
953
  @Override
954
  public int getType() {
955
    if (featureAttributeGetter != null) {
956
      return featureAttributeGetter.getDataType().getType();
957
    }
958
    return getDataType().getType();
959
  }
960

    
961
  @Override
962
  public boolean isMandatory() {
963
    return !allowNull() || isPrimaryKey();
964
  }
965

    
966
  @Override
967
  public boolean isPersistent() {
968
    return false;
969
  }
970

    
971
  @Override
972
  public DynField setAvailableValues(DynObjectValueItem[] values) {
973
    if (ArrayUtils.isEmpty(values)) {
974
      this.availableValues = null;
975
    } else {
976
      this.availableValues = values;
977
    }
978
    return this;
979
  }
980

    
981
  @Override
982
  public DynField setDescription(String description) {
983
    this.description = description;
984
    return this;
985
  }
986

    
987
  @Override
988
  public DynField setMandatory(boolean mandatory) {
989
    throw new UnsupportedOperationException();
990
  }
991

    
992
  @Override
993
  public DynField setMaxValue(Object maxValue) {
994
    try {
995
      this.maxValue = this.coerce(maxValue);
996
    } catch (CoercionException e) {
997
      throw new IllegalArgumentException(e);
998
    }
999
    return this;
1000
  }
1001

    
1002
  @Override
1003
  public DynField setMinValue(Object minValue) {
1004
    try {
1005
      this.maxValue = this.coerce(minValue);
1006
    } catch (CoercionException e) {
1007
      throw new IllegalArgumentException(e);
1008
    }
1009
    return this;
1010
  }
1011

    
1012
  @Override
1013
  public DynField setPersistent(boolean persistent) {
1014
    throw new UnsupportedOperationException();
1015
  }
1016

    
1017
  @Override
1018
  public DynField setTheTypeOfAvailableValues(int type) {
1019
    throw new UnsupportedOperationException();
1020
  }
1021

    
1022
  @Override
1023
  public DynField setType(int type) {
1024
    throw new UnsupportedOperationException();
1025
  }
1026

    
1027
  @Override
1028
  public DynField setDefaultDynValue(Object defaultValue) {
1029
    throw new UnsupportedOperationException();
1030
  }
1031

    
1032
  @Override
1033
  public Class getClassOfValue() {
1034
    return null;
1035
  }
1036

    
1037
  @Override
1038
  public DynField getElementsType() {
1039
    return null;
1040
  }
1041

    
1042
  @Override
1043
  public DynField setClassOfValue(Class theClass)
1044
          throws DynFieldIsNotAContainerException {
1045
    throw new UnsupportedOperationException();
1046
  }
1047

    
1048
  @Override
1049
  public DynField setElementsType(DynStruct type)
1050
          throws DynFieldIsNotAContainerException {
1051
    throw new UnsupportedOperationException();
1052
  }
1053

    
1054
  @Override
1055
  public DynField setElementsType(int type)
1056
          throws DynFieldIsNotAContainerException {
1057
    throw new UnsupportedOperationException();
1058
  }
1059

    
1060
  public FeatureAttributeDescriptor setDataProfileName(String dataProfile) {
1061
    this.dataProfile = dataProfile;
1062
    return this;
1063
  }
1064

    
1065
  @Override
1066
  public String getDataProfileName() {
1067
    return dataProfile;
1068
  }
1069

    
1070
  @Override
1071
  public DataProfile getDataProfile() {
1072
    if (StringUtils.isBlank(dataProfile)) {
1073
      return null;
1074
    }
1075
    DataProfile profile = DALLocator.getDataManager().getDataProfile(dataProfile);
1076
    return profile;
1077
  }
1078

    
1079
  @Override
1080
  public void validate(Object value) throws DynFieldValidateException {
1081

    
1082
    if (value == null && !this.allowNull()) {
1083
      throw new DynFieldValidateException(value, this, null);
1084
    }
1085

    
1086
    try {
1087
      this.dataType.coerce(value);
1088
    } catch (CoercionException e) {
1089
      throw new DynFieldValidateException(value, this, e);
1090
    }
1091

    
1092
    /*
1093
         * Other checks will be needed
1094
     */
1095
  }
1096

    
1097
  @Override
1098
  public String getSubtype() {
1099
    if (featureAttributeGetter != null) {
1100
      return featureAttributeGetter.getDataType().getSubtype();
1101
    }
1102
    return this.dataType.getSubtype();
1103
  }
1104

    
1105
  @Override
1106
  public Object coerce(Object value) throws CoercionException {
1107
    if (value == null) {
1108
      return value; // O debe devolver this.defaultValue
1109
    }
1110
    try {
1111
      return this.getDataType().coerce(value, this.getCoercionContext());
1112
    } catch (Exception ex) {
1113
      throw new RuntimeException(ex);
1114
    }
1115
  }
1116

    
1117
  @Override
1118
  public DynField setAvailableValues(List values) {
1119
    if (values == null || values.isEmpty()) {
1120
      this.availableValues = null;
1121
    } else {
1122
      this.availableValues = (DynObjectValueItem[]) values.toArray(
1123
              new DynObjectValueItem[values.size()]
1124
      );
1125
    }
1126
    return this;
1127
  }
1128

    
1129
  @Override
1130
  public String getGroup() {
1131
    return this.groupName;
1132
  }
1133

    
1134
  @Override
1135
  public int getOder() {
1136
    return this.order;
1137
  }
1138

    
1139
  @Override
1140
  public String getLabel() {
1141
    if (this.label == null) {
1142
      return this.getName();
1143
    }
1144
    return this.label;
1145
  }
1146

    
1147
  @Override
1148
  public String getLocalizedLabel() {
1149
    if (StringUtils.isBlank(this.label)) {
1150
      return this.getName();
1151
    }
1152
    I18nManager i18n = ToolsLocator.getI18nManager();
1153
    return i18n.getTranslation(this.label);
1154
  }
1155

    
1156
  @Override
1157
  public DynField setLabel(String label) {
1158
    this.label = label;
1159
    return this;
1160
  }
1161

    
1162
  @Override
1163
  public DynField setShortLabel(String shortLabel) {
1164
    this.shortLabel = shortLabel;
1165
    return this;
1166
  }
1167

    
1168
  @Override
1169
  public String getShortLabel() {
1170
    return StringUtils.isBlank(shortLabel) ? getLabel() : shortLabel;
1171
  }
1172

    
1173
  @Override
1174
  public String getLocalizedShortLabel() {
1175
    if (StringUtils.isBlank(shortLabel)) {
1176
      return this.getLocalizedLabel();
1177
    }
1178
    I18nManager i18n = ToolsLocator.getI18nManager();
1179
    return i18n.getTranslation(shortLabel);
1180
  }
1181

    
1182
  @Override
1183
  public DynField setGroup(String groupName) {
1184
    this.groupName = groupName;
1185
    return this;
1186
  }
1187

    
1188
  @Override
1189
  public DynField setOrder(int order) {
1190
    this.order = order;
1191
    return this;
1192
  }
1193

    
1194
  @Override
1195
  public DynField setHidden(boolean hidden) {
1196
    this.hidden = hidden;
1197
    return this;
1198
  }
1199

    
1200
  @Override
1201
  public boolean isHidden() {
1202
    return this.hidden;
1203
  }
1204

    
1205
  @Override
1206
  public DynField setReadOnly(boolean readOnly) {
1207
    this.readOnly = readOnly;
1208
    return this;
1209
  }
1210

    
1211
  @Override
1212
  public boolean isContainer() {
1213
    return false;
1214
  }
1215

    
1216
  @Override
1217
  public Class getClassOfItems() {
1218
    return null;
1219
  }
1220

    
1221
  @Override
1222
  public DynField setDefaultFieldValue(Object defaultValue) {
1223
    throw new UnsupportedOperationException();
1224
  }
1225

    
1226
  @Override
1227
  public DynField setClassOfItems(Class theClass) {
1228
    throw new UnsupportedOperationException();
1229
  }
1230

    
1231
  @Override
1232
  public DynField setType(DataType type) {
1233
    throw new UnsupportedOperationException();
1234
  }
1235

    
1236
  @Override
1237
  public DynField setSubtype(String subtype) {
1238
    throw new UnsupportedOperationException();
1239
  }
1240

    
1241
  @Override
1242
  public boolean isTime() {
1243
    return isTime;
1244
  }
1245

    
1246
  @Override
1247
  public FeatureAttributeGetter getFeatureAttributeGetter() {
1248
    return featureAttributeGetter;
1249
  }
1250

    
1251
  @Override
1252
  public void setFeatureAttributeGetter(
1253
          FeatureAttributeGetter featureAttributeTransform) {
1254
    this.featureAttributeGetter = featureAttributeTransform;
1255
  }
1256

    
1257
  @Override
1258
  public FeatureAttributeEmulator getFeatureAttributeEmulator() {
1259
    return this.featureAttributeEmulator;
1260
  }
1261

    
1262
  public FeatureAttributeDescriptor setFeatureAttributeEmulator(FeatureAttributeEmulator featureAttributeEmulator) {
1263
    this.featureAttributeEmulator = featureAttributeEmulator;
1264
    return this;
1265
  }
1266

    
1267
  @Override
1268
  public boolean isIndexed() {
1269
    return this.indexed;
1270
  }
1271

    
1272
  @Override
1273
  public boolean isForeingKey() {
1274
    return this.foreingKey != null && this.foreingKey.isForeingKey();
1275
  }
1276

    
1277
  @Override
1278
  public ForeingKey getForeingKey() {
1279
    return this.foreingKey;
1280
  }
1281

    
1282
  @Override
1283
  public boolean allowIndexDuplicateds() {
1284
    return this.allowIndexDuplicateds;
1285
  }
1286

    
1287
  @Override
1288
  public boolean isIndexAscending() {
1289
    return this.isIndexAscending;
1290
  }
1291

    
1292
  @Override
1293
  public DynField setClassOfValue(DynStruct dynStrct) {
1294
    throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
1295
  }
1296

    
1297
  @Override
1298
  public DynField setClassOfValue(String theClassNameOfValue) {
1299
    throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
1300
  }
1301

    
1302
  @Override
1303
  public String getClassNameOfValue() {
1304
    return null;
1305
  }
1306

    
1307
  @Override
1308
  public DynStruct getDynClassOfValue() {
1309
    return null;
1310
  }
1311

    
1312
  @Override
1313
  public DynField setTypeOfItems(int type) {
1314
    throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
1315
  }
1316

    
1317
  @Override
1318
  public int getTypeOfItems() {
1319
    return DataTypes.INVALID;
1320
  }
1321

    
1322
  @Override
1323
  public DynField setClassOfItems(DynStruct dynStrct) {
1324
    throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
1325
  }
1326

    
1327
  @Override
1328
  public DynField setClassOfItems(String theClassNameOfValue) {
1329
    throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
1330
  }
1331

    
1332
  @Override
1333
  public String getClassNameOfItems() {
1334
    return null;
1335
  }
1336

    
1337
  @Override
1338
  public DynStruct getDynClassOfItems() {
1339
    return null;
1340
  }
1341

    
1342
  @Override
1343
  public DynField setRelationType(int relationType) {
1344
    this.relationType = relationType;
1345
    return this;
1346
  }
1347

    
1348
  @Override
1349
  public int getRelationType() {
1350
    return this.relationType;
1351
  }
1352

    
1353
  @Override
1354
  public DynField setAvailableValues(DynMethod availableValuesMethod) {
1355
    this.availableValuesMethod = availableValuesMethod;
1356
    return this;
1357
  }
1358

    
1359
  @Override
1360
  public DynObjectValueItem[] getAvailableValues(DynObject self) {
1361
    if (this.availableValuesMethod != null) {
1362
      DynObjectValueItem[] values;
1363
      try {
1364
        values = (DynObjectValueItem[]) this.availableValuesMethod.invoke(self, new Object[]{this});
1365
      } catch (DynMethodException ex) {
1366
        return this.availableValues;
1367
      }
1368
      if (values != null) {
1369
        return values;
1370
      }
1371
    }
1372
    return this.availableValues;
1373
  }
1374

    
1375
  @Override
1376
  public DynMethod getAvailableValuesMethod() {
1377
    return this.availableValuesMethod;
1378
  }
1379

    
1380
  @Override
1381
  public boolean isAvailableValuesCalculated() {
1382
    return this.availableValuesMethod != null;
1383
  }
1384

    
1385
  @Override
1386
  public DynMethod getCalculateMethod() {
1387
    return this.calculateMethod;
1388
  }
1389

    
1390
  @Override
1391
  public DynField setCalculateMethod(DynMethod method) {
1392
    this.calculateMethod = method;
1393
    return this;
1394
  }
1395

    
1396
  @Override
1397
  public boolean isCalculated() {
1398
    return this.calculateMethod != null;
1399
  }
1400

    
1401
  @Override
1402
  public Object getCalculatedValue(DynObject self) {
1403
    try {
1404
      return this.calculateMethod.invoke(self, new Object[]{this});
1405
    } catch (DynMethodException ex) {
1406
      throw new RuntimeException(ex);
1407
    }
1408
  }
1409

    
1410
  @Override
1411
  public DynField setValidateElements(boolean validate) {
1412
    return this;
1413
  }
1414

    
1415
  @Override
1416
  public boolean getValidateElements() {
1417
    return false;
1418
  }
1419

    
1420
  @Override
1421
  public boolean hasLabel() {
1422
    return StringUtils.isNotBlank(this.label);
1423
  }
1424

    
1425
  @Override
1426
  public boolean hasShortLabel() {
1427
    return StringUtils.isNotBlank(this.shortLabel);
1428
  }
1429

    
1430
  @Override
1431
  public boolean hasDescription() {
1432
    return StringUtils.isNotBlank(this.description);
1433
  }
1434

    
1435
  @Override
1436
  public FeatureAttributeDescriptor getValue() {
1437
    return this;
1438
  }
1439

    
1440
  private class ConstantValueEvaluator extends AbstractEvaluator {
1441

    
1442
    @Override
1443
    public Object evaluate(EvaluatorData data) throws EvaluatorException {
1444
      return defaultValue;
1445
    }
1446

    
1447
    @Override
1448
    public String getName() {
1449
      return "Constant attribute " + name;
1450
    }
1451
  }
1452

    
1453
  public void setConstantValue(boolean isConstantValue) {
1454
    if (isConstantValue) {
1455
      /* Cuando un attributo tiene asociado un evaluador, este se interpreta
1456
             * como que no debe cargarse de la fuente de datos subyacente, siendo
1457
             * el evaluador el que se encarga de proporcionar su valor.
1458
             * Nos limitamos a asignar un evaluador que retorna simpre el valor
1459
             * por defecto para ese attributo.
1460
       */
1461
      this.evaluator = new ConstantValueEvaluator();
1462
    } else {
1463
      this.evaluator = null;
1464
    }
1465
  }
1466

    
1467
  @Override
1468
  public boolean isComputed() {
1469
    return featureAttributeEmulator != null || evaluator != null || isCalculated();
1470
  }
1471

    
1472
  @Override
1473
  public FeatureStore getStore() {
1474
    FeatureType ftype = this.getFeatureType();
1475
    if (ftype == null) {
1476
      return null;
1477
    }
1478
    return ftype.getStore();
1479
  }
1480

    
1481
  @Override
1482
  public FeatureType getFeatureType() {
1483
    if (this.typeRef == null) {
1484
      return null;
1485
    }
1486
    FeatureType ftype = (FeatureType) this.typeRef.get();
1487
//        LOGGER.info(String.format("FeatureAttributeDescriptor[%08x] get FeatureType [%08x], ref [%08x].", this.hashCode(), ftype.hashCode(), typeRef.hashCode()));
1488
    return ftype;
1489
  }
1490

    
1491
  public FeatureAttributeDescriptor setInterval(Interval interval) {
1492
    this.interval = interval;
1493
    return this;
1494
  }
1495

    
1496
  public void fixAll() {
1497
    if (!this.getDataType().supportSize()) {
1498
      this.size = 0;
1499
    }
1500
    NumberPrecisionAndScale ps = this.getDataType().fixPrecisionAndScale(this.precision, this.scale);
1501
    this.precision = ps.getPrecision();
1502
    this.scale = ps.getScale();
1503

    
1504
    switch (this.getType()) {
1505
      case DataTypes.INSTANT:
1506
      case DataTypes.INTERVAL:
1507
      case DataTypes.DATE:
1508
      case DataTypes.TIME:
1509
      case DataTypes.TIMESTAMP:
1510
        if (this.getInterval() != null) {
1511
          this.isTime = true;
1512
        }
1513
        break;
1514
    }
1515
  }
1516

    
1517
  @Override
1518
  public String[] getRequiredFieldNames() {
1519
    FeatureAttributeEmulator emulator = this.getFeatureAttributeEmulator();
1520
    if (emulator == null) {
1521
      return null;
1522
    }
1523
    return emulator.getRequiredFieldNames();
1524
  }
1525

    
1526
  @Override
1527
  public void recentUsed() {
1528
    DefaultFeatureType.RECENTS_USEDS.add(this);
1529
  }
1530

    
1531
  @Override
1532
  public boolean hasOnlyMetadataChanges(FeatureAttributeDescriptor other) {
1533
    if (other == null) {
1534
      throw new NullPointerException();
1535
    }
1536
    DefaultFeatureAttributeDescriptor old = (DefaultFeatureAttributeDescriptor) other;
1537
    if (!StringUtils.equalsIgnoreCase(old.name, this.name)) {
1538
      return false;
1539
    }
1540
    if (old.isComputed() && old.isComputed() == this.isComputed()) {
1541
      return true;
1542
    }
1543
    if (this.dataType != old.dataType) {
1544
      return false;
1545
    }
1546
    if (this.size != old.size) {
1547
      return false;
1548
    }
1549
    if (this.precision != old.precision) {
1550
      return false;
1551
    }
1552
//        if( this.primaryKey != old.primaryKey ) {
1553
//            return false;
1554
//        }
1555
    if (this.geomType != old.geomType) {
1556
      return false;
1557
    }
1558
    if (this.SRS != old.SRS) {
1559
      return false;
1560
    }
1561
    if (this.isAutomatic != old.isAutomatic) {
1562
      return false;
1563
    }
1564
    return true;
1565
  }
1566

    
1567
  @Override
1568
  public Object get(String name) {
1569
    if (StringUtils.isBlank(name)) {
1570
      throw new IllegalArgumentException("Name can't be empty");
1571
    }
1572
    switch (name.toLowerCase()) {
1573
      case "isreadonly":
1574
      case "readonly":
1575
        return this.isReadOnly();
1576
      case "hidden":
1577
        return this.isHidden();
1578
      case "allownull":
1579
        return this.allowNull();
1580
      case "pk":
1581
      case "ispk":
1582
      case "primarykey":
1583
      case "isprimarykey":
1584
        return this.isPrimaryKey();
1585
      case "isautomatic":
1586
      case "automatic":
1587
        return this.isAutomatic();
1588
      case "time":
1589
      case "istime":
1590
        return this.isTime();
1591
      case "profile":
1592
        return this.getDataProfile();
1593
      case "group":
1594
        return this.getGroup();
1595
      case "description":
1596
        return this.getDescription();
1597
      case "label":
1598
        return this.getLabel();
1599
      case "shortlabel":
1600
        return this.getShortLabel();
1601
      case "expression":
1602
        return this.getFeatureAttributeEmulator();
1603
      case "size":
1604
        return this.getSize();
1605
      case "precision":
1606
        return this.getPrecision();
1607
      case "scale":
1608
        return this.getScale();
1609
      case "roundmode":
1610
        return this.getRoundMode();
1611
      case "locale":
1612
        return this.getLocale();
1613
      case "order":
1614
        return this.getOder();
1615
      case "foreingkey":
1616
        return this.getForeingKey();
1617
      case "interval":
1618
        return this.getInterval();
1619
      case "geomtype":
1620
      case "geometrytype":
1621
        return this.getGeomType();
1622
      case "srs":
1623
        return this.getSRS();
1624
      default:
1625
        throw new IllegalArgumentException("Name attribute '" + name + "' not valid.");
1626
    }
1627
  }
1628

    
1629
}