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

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

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

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

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

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

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

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

    
150
  public DefaultFeatureAttributeDescriptor() {
151
    // Usada en la persistencia
152
  }
153

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

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

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

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

    
265
    // TODO: ? Habria que clonarlos ?
266
    this.availableValuesMethod = other.availableValuesMethod;
267
    this.calculateMethod = other.calculateMethod;
268
    this.relationType = other.relationType;
269
    this.locale = other.locale;
270
  }
271

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

    
282
  @Override
283
  public String getDataTypeName() {
284
    if (this.getDataType() == null) {
285
      return "(unknow)";
286
    }
287
    return this.getDataType().getName();
288
  }
289

    
290
  @Override
291
  public DefaultFeatureAttributeDescriptor getCopy() {
292
    return new DefaultFeatureAttributeDescriptor(this);
293
  }
294

    
295
  @Override
296
  public Object clone() throws CloneNotSupportedException {
297
    return new DefaultFeatureAttributeDescriptor(this);
298
  }
299

    
300
  @Override
301
  public boolean allowNull() {
302
    return allowNull;
303
  }
304

    
305
  public Locale getLocale() {
306
    return this.locale;
307
  }
308

    
309
  @Override
310
  public DataType getDataType() {
311
    if (featureAttributeGetter != null) {
312
      return featureAttributeGetter.getDataType();
313
    }
314
    return this.dataType;
315
  }
316

    
317
  public FeatureAttributeDescriptor setDataType(int type) {
318
    this.dataType = ToolsLocator.getDataTypesManager().get(type);
319
    return this;
320
  }
321

    
322
  @Override
323
  public DateFormat getDateFormat() {
324
    return this.dateFormat;
325
  }
326

    
327
  @Override
328
  public Object getDefaultValue() {
329
    return this.defaultValue;
330
  }
331

    
332
  @Override
333
  public Object getDefaultValueCoerced() {
334
    try {
335
      Object value = this.defaultValue;
336
      if (value == null) {
337
        return null;
338
      }
339
      if (ExpressionUtils.isDynamicText(value.toString())) {
340
        value = ExpressionUtils.evaluateDynamicText(value.toString());
341
      }
342
      return this.getDataType().coerce(value);
343
    } catch (CoercionException ex) {
344
      return null;
345
    }
346
  }
347

    
348
  @Override
349
  public Evaluator getEvaluator() {
350
    return this.evaluator;
351
  }
352

    
353
  @Override
354
  public int getGeometryType() {
355
    if (this.dataType.getType() != DataTypes.GEOMETRY) {
356
      return Geometry.TYPES.UNKNOWN;
357
    }
358
    return this.geometryType;
359
  }
360

    
361
  @Override
362
  public int getGeometrySubType() {
363
    if (this.dataType.getType() != DataTypes.GEOMETRY) {
364
      return Geometry.SUBTYPES.UNKNOWN;
365
    }
366
    return this.geometrySubType;
367
  }
368

    
369
  @Override
370
  public GeometryType getGeomType() {
371
    if (this.dataType.getType() != DataTypes.GEOMETRY) {
372
      return null;
373
    }
374
    if (this.geomType == null) {
375
      try {
376
        this.geomType
377
                = GeometryLocator.getGeometryManager().getGeometryType(
378
                        this.geometryType, this.geometrySubType);
379
      } catch (GeometryException e) {
380
        throw new RuntimeException(
381
                "Error getting geometry type with type = "
382
                + this.geometryType + ", subtype = "
383
                + this.geometrySubType, e);
384
      }
385
    }
386
    return this.geomType;
387
  }
388

    
389
  @Override
390
  public int getIndex() {
391
    return this.index;
392
  }
393

    
394
  protected FeatureAttributeDescriptor setIndex(int index) {
395
    this.index = index;
396
    return this;
397
  }
398

    
399
  @Override
400
  public int getMaximumOccurrences() {
401
    return this.maximumOccurrences;
402
  }
403

    
404
  @Override
405
  public int getMinimumOccurrences() {
406
    return this.minimumOccurrences;
407
  }
408

    
409
  @Override
410
  public String getName() {
411
    return this.name;
412
  }
413

    
414
  public FeatureAttributeDescriptor setName(String name) {
415
//        LOGGER.info(String.format("FeatureAttributeDescriptor[%08x] set name [%s].", this.hashCode(), name));
416
    this.name = name;
417
    return this;
418
  }
419

    
420
  @Override
421
  public Class getObjectClass() {
422
    if (getDataType().getType() == DataTypes.OBJECT) {
423
      return objectClass;
424
    }
425
    return getDataType().getDefaultClass();
426
  }
427

    
428
  @Override
429
  public int getPrecision() {
430
    return this.precision;
431
  }
432

    
433
  @Override
434
  public int getScale() {
435
    return this.scale;
436
  }
437

    
438
  @Override
439
  public Coercion getCoercion() {
440
    return this.getDataType().getCoercion();
441
  }
442

    
443
  @Override
444
  public MathContext getMathContext() {
445
    if (this.mathContext == null) {
446
      if (this.getDataType().isNumeric()) {
447
        this.mathContext = new MathContext(
448
                this.getPrecision(),
449
                RoundingMode.valueOf(this.getRoundMode())
450
        );
451
      } else {
452
        this.mathContext = MathContext.UNLIMITED;
453
      }
454
    }
455
    return this.mathContext;
456
  }
457

    
458
  @Override
459
  public CoercionContext getCoercionContext() {
460
    if (this.coerceContext == null) {
461
      if (this.getDataType().isNumeric()) {
462
        this.coerceContext = DataTypeUtils.coerceContextDecimal(
463
                this.getLocale(),
464
                this.getPrecision(),
465
                this.getScale(),
466
                this.getRoundMode()
467
        );
468
      } else {
469
        this.coerceContext = DataTypeUtils.coerceContextLocale(
470
                this.getLocale()
471
        );
472
      }
473
    }
474
    return this.coerceContext;
475
  }
476

    
477
  @Override
478
  public int getRoundMode() {
479
    return this.roundMode;
480
  }
481

    
482
  @Override
483
  public IProjection getSRS() {
484
    return this.SRS;
485
  }
486

    
487
  @Override
488
  public Interval getInterval() {
489
    return this.interval;
490
  }
491

    
492
  public IProjection getSRS(WeakReference storeRef) {
493
    if (this.SRS == null) {
494
      FeatureStore store = (FeatureStore) storeRef.get();
495
      this.SRS = (IProjection) store.getDynValue(DataStore.METADATA_CRS);
496
    }
497
    return this.SRS;
498
  }
499

    
500
  @Override
501
  public int getSize() {
502
    return this.size;
503
  }
504

    
505
  @Override
506
  public boolean isPrimaryKey() {
507
    return this.primaryKey;
508
  }
509

    
510
  @Override
511
  public boolean isReadOnly() {
512
    if (this.readOnly) {
513
      return true;
514
    }
515
    return this.isComputed();
516
  }
517

    
518
  @Override
519
  public Object getAdditionalInfo(String infoName) {
520
    if (this.additionalInfo == null) {
521
      return null;
522
    }
523
    return this.additionalInfo.get(infoName);
524
  }
525

    
526
  @Override
527
  public boolean isAutomatic() {
528
    return this.isAutomatic;
529
  }
530

    
531
  @Override
532
  public boolean equals(Object obj) {
533
    if (this == obj) {
534
      return true;
535
    }
536
    if (!(obj instanceof DefaultFeatureAttributeDescriptor)) {
537
      return false;
538
    }
539
    DefaultFeatureAttributeDescriptor other
540
            = (DefaultFeatureAttributeDescriptor) obj;
541

    
542
    if (this.allowNull != other.allowNull) {
543
      return false;
544
    }
545

    
546
    if (this.index != other.index) {
547
      return false;
548
    }
549

    
550
    if (!Objects.equals(this.name, other.name)) {
551
      return false;
552
    }
553

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

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

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

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

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

    
574
    if (this.readOnly != other.readOnly) {
575
      return false;
576
    }
577

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

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

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

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

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

    
598
    if (!Objects.equals(this.evaluator, other.evaluator)) {
599
      return false;
600
    }
601

    
602
    if (!Objects.equals(this.featureAttributeEmulator, other.featureAttributeEmulator)) {
603
      return false;
604
    }
605

    
606
    if (!Objects.equals(this.SRS, other.SRS)) {
607
      return false;
608
    }
609

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

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

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

    
622
    return true;
623
  }
624

    
625
  @Override
626
  public void loadFromState(PersistentState state)
627
          throws PersistenceException {
628
    allowNull = state.getBoolean("allowNull");
629
    dataType = ToolsLocator.getDataTypesManager().get(state.getInt("dataType"));
630
    dataProfile = state.getString("dataProfile");
631

    
632
//        FIXME: dateFormat;
633
    try {
634
      defaultValue = dataType.coerce(state.get("defaultValue"));
635
    } catch (CoercionException ex) {
636
    }
637

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

    
684
    Map<String, Object> values = state.getMap("availableValues");
685
    if (values == null || values.isEmpty()) {
686
      this.availableValues = null;
687
    } else {
688
      this.availableValues = new DynObjectValueItem[values.size()];
689
      int n = 0;
690
      for (Entry<String, Object> entry : values.entrySet()) {
691
        this.availableValues[n++] = new DynObjectValueItem(entry.getValue(), entry.getKey());
692
      }
693
    }
694

    
695
    description = state.getString("description");
696
    minValue = state.get("minValue");
697
    maxValue = state.get("maxValue");
698
    label = state.getString("label");
699
    order = state.getInt("order");
700
    hidden = state.getBoolean("hidden");
701
    groupName = state.getString("groupName");
702
    relationType = state.getInt("relationType");
703

    
704
    foreingKey = (DefaultForeingKey) state.get("foreingKey");
705
    if (foreingKey != null) {
706
      this.foreingKey.setDescriptor(this);
707
    }
708
    tags = (Tags) state.get("tags");
709
    if (tags == null) {
710
      this.tags = new DefaultTags();
711
    }
712
  }
713

    
714
  @Override
715
  public void saveToState(PersistentState state) throws PersistenceException {
716
    state.set("allowNull", allowNull);
717
    state.set("dataType", dataType.getType());
718
    state.set("dataProfile", dataProfile);
719

    
720
//        FIXME: dateFormat;
721
    state.set("defaultValue", Objects.toString(defaultValue, null));
722

    
723
    state.set("index", index);
724
    state.set("maximumOccurrences", maximumOccurrences);
725
    state.set("minimumOccurrences", minimumOccurrences);
726
    state.set("size", size);
727
    state.set("name", name);
728
    state.set("objectClass", objectClass == null ? null : objectClass.getName());
729
    state.set("precision", precision);
730
    state.set("scale", scale);
731
    state.set("roundMode", roundMode);
732
    state.set("locale", this.locale == null ? null : this.locale.toLanguageTag());
733
    state.set("evaluator", evaluator);
734

    
735
    state.set("primaryKey", primaryKey);
736
    state.set("readOnly", readOnly);
737
    state.set("SRS", SRS);
738
    GeometryType theGeomType = this.getGeomType();
739
    if (theGeomType == null) {
740
      state.set("geometryType", Geometry.TYPES.UNKNOWN);
741
      state.set("geometrySubType", Geometry.SUBTYPES.UNKNOWN);
742
    } else {
743
      state.set("geometryType", theGeomType.getType());
744
      state.set("geometrySubType", theGeomType.getSubType());
745
    }
746

    
747
//      FIXME: additionalInfo
748
    state.set("isAutomatic", isAutomatic);
749
    state.set("isTime", isTime);
750
    if (this.interval == null) {
751
      state.setNull("interval_start");
752
      state.setNull("interval_end");
753
    } else {
754
      state.set("interval_start", ((RelativeInterval) interval).getStart().toMillis());
755
      state.set("interval_end", ((RelativeInterval) interval).getEnd().toMillis());
756
    }
757
    state.set("SRS", SRS);
758

    
759
//      FIXME: featureAttributeGetter
760
    if (featureAttributeEmulator instanceof Persistent) {
761
      state.set("featureAttributeEmulator", featureAttributeEmulator);
762
    } else {
763
      state.setNull("featureAttributeEmulator");
764
    }
765

    
766
    state.set("indexed", indexed);
767
    state.set("isIndexAscending", isIndexAscending);
768
    state.set("allowIndexDuplicateds", allowIndexDuplicateds);
769

    
770
    if (this.availableValues == null) {
771
      state.setNull("availableValues");
772
    } else {
773
      Map<String, Object> values = new LinkedHashMap<>();
774
      for (DynObjectValueItem value : availableValues) {
775
        values.put(value.getLabel(), value.getValue());
776
      }
777
      state.set("availableValues", values);
778
    }
779
    state.set("description", description);
780
    state.set("minValue", minValue);
781
    state.set("maxValue", maxValue);
782
    state.set("label", label);
783
    state.set("order", order);
784
    state.set("hidden", hidden);
785
    state.set("groupName", groupName);
786
    state.set("relationType", relationType);
787

    
788
    state.set("foreingKey", this.foreingKey);
789
    state.set("tags", this.tags);
790

    
791
  }
792

    
793
  private static final String FEATATTRDESC_PERSISTENCE_DEFINITION_NAME = "FeatureAttributeDescriptor";
794

    
795
  public static void registerPersistenceDefinition() {
796
    PersistenceManager manager = ToolsLocator.getPersistenceManager();
797

    
798
    if (manager.getDefinition(FEATATTRDESC_PERSISTENCE_DEFINITION_NAME)
799
            == null) {
800
      DynStruct definition = manager.addDefinition(DefaultFeatureAttributeDescriptor.class,
801
              FEATATTRDESC_PERSISTENCE_DEFINITION_NAME,
802
              FEATATTRDESC_PERSISTENCE_DEFINITION_NAME
803
              + " persistent definition",
804
              null,
805
              null
806
      );
807
      definition.addDynFieldBoolean("allowNull");
808
      definition.addDynFieldInt("dataType");
809
      definition.addDynFieldString("dataProfile");
810
//            definition.addDynFieldString("dateFormat");
811
      definition.addDynFieldString("defaultValue");
812
      definition.addDynFieldInt("index");
813
      definition.addDynFieldInt("maximumOccurrences");
814
      definition.addDynFieldInt("minimumOccurrences");
815
      definition.addDynFieldInt("size");
816
      definition.addDynFieldString("name");
817
      definition.addDynFieldString("objectClass");
818
      definition.addDynFieldInt("precision");
819
      definition.addDynFieldInt("scale");
820
      definition.addDynFieldInt("roundMode");
821
      definition.addDynFieldString("locale");
822
      definition.addDynFieldObject("evaluator")
823
              .setClassOfValue(Evaluator.class);
824
      definition.addDynFieldBoolean("primaryKey");
825
      definition.addDynFieldBoolean("readOnly");
826
      definition.addDynFieldObject("SRS")
827
              .setClassOfValue(IProjection.class);
828
      definition.addDynFieldInt("geometryType");
829
      definition.addDynFieldInt("geometrySubType");
830
//            definition.addDynFieldMap("additionalInfo");
831
      definition.addDynFieldBoolean("isAutomatic");
832
      definition.addDynFieldBoolean("isTime");
833
      definition.addDynFieldLong("interval_start");
834
      definition.addDynFieldLong("interval_end");
835
      definition.addDynFieldObject("featureAttributeEmulator")
836
              .setClassOfValue(FeatureAttributeEmulator.class);
837
      definition.addDynFieldBoolean("indexed");
838
      definition.addDynFieldBoolean("isIndexAscending");
839
      definition.addDynFieldBoolean("allowIndexDuplicateds");
840
      definition.addDynFieldMap("availableValues")
841
              .setClassOfItems(Object.class);
842
      definition.addDynFieldString("description");
843
      definition.addDynFieldObject("minValue");
844
      definition.addDynFieldObject("maxValue");
845
      definition.addDynFieldString("label");
846
      definition.addDynFieldInt("order");
847
      definition.addDynFieldBoolean("hidden");
848
      definition.addDynFieldString("groupName");
849
      definition.addDynFieldInt("relationType");
850

    
851
      definition.addDynFieldObject("foreingKey")
852
              .setClassOfValue(DefaultForeingKey.class);
853

    
854
      definition.addDynFieldObject("tags")
855
              .setClassOfValue(Tags.class);
856

    
857
    }
858
  }
859

    
860
  /*
861
     * Start of DynField interface Implementation
862
     *
863
   */
864
  @Override
865
  public Tags getTags() {
866
    return tags;
867
  }
868

    
869
  @Override
870
  public DynObjectValueItem[] getAvailableValues() {
871
    if (this.availableValues == null) {
872
      if (this.isForeingKey() && this.foreingKey.isClosedList()) {
873
        return this.foreingKey.getAvailableValues(null);
874
      }
875
    }
876
    return this.availableValues;
877
  }
878

    
879
  @Override
880
  public String getLabelOfValue(Object value) {
881
    if (this.labelOfValueMap != null) {
882
      String theLabel = this.labelOfValueMap.get(value);
883
      if (theLabel == null) {
884
        theLabel = Objects.toString(value, "");
885
      }
886
      return theLabel;
887
    }
888
    DynObjectValueItem[] values = this.getAvailableValues();
889
    if (values == null) {
890
      return Objects.toString(value, "");
891
    }
892
    Map<Object, String> map = new LinkedHashMap<>();
893
    for (DynObjectValueItem theValue : values) {
894
      map.put(theValue.getValue(), theValue.getLabel());
895
    }
896
    this.labelOfValueMap = map;
897
    String theLabel = this.labelOfValueMap.get(value);
898
    if (theLabel == null) {
899
      theLabel = Objects.toString(value, "");
900
    }
901
    return theLabel;
902
  }
903

    
904
  @Override
905
  public String getDescription() {
906
    if (this.description == null) {
907
      return getName();
908
    }
909
    return this.description;
910
  }
911

    
912
  @Override
913
  public Object getMaxValue() {
914
    return this.maxValue;
915
  }
916

    
917
  @Override
918
  public Object getMinValue() {
919
    return this.minValue;
920
  }
921

    
922
  @Override
923
  public int getTheTypeOfAvailableValues() {
924
    return 1;
925
  }
926

    
927
  @Override
928
  public int getType() {
929
    if (featureAttributeGetter != null) {
930
      return featureAttributeGetter.getDataType().getType();
931
    }
932
    return getDataType().getType();
933
  }
934

    
935
  @Override
936
  public boolean isMandatory() {
937
    return !allowNull() || isPrimaryKey();
938
  }
939

    
940
  @Override
941
  public boolean isPersistent() {
942
    return false;
943
  }
944

    
945
  @Override
946
  public DynField setAvailableValues(DynObjectValueItem[] values) {
947
    if (ArrayUtils.isEmpty(values)) {
948
      this.availableValues = null;
949
    } else {
950
      this.availableValues = values;
951
    }
952
    return this;
953
  }
954

    
955
  @Override
956
  public DynField setDescription(String description) {
957
    this.description = description;
958
    return this;
959
  }
960

    
961
  @Override
962
  public DynField setMandatory(boolean mandatory) {
963
    throw new UnsupportedOperationException();
964
  }
965

    
966
  @Override
967
  public DynField setMaxValue(Object maxValue) {
968
    try {
969
      this.maxValue = this.coerce(maxValue);
970
    } catch (CoercionException e) {
971
      throw new IllegalArgumentException(e);
972
    }
973
    return this;
974
  }
975

    
976
  @Override
977
  public DynField setMinValue(Object minValue) {
978
    try {
979
      this.maxValue = this.coerce(minValue);
980
    } catch (CoercionException e) {
981
      throw new IllegalArgumentException(e);
982
    }
983
    return this;
984
  }
985

    
986
  @Override
987
  public DynField setPersistent(boolean persistent) {
988
    throw new UnsupportedOperationException();
989
  }
990

    
991
  @Override
992
  public DynField setTheTypeOfAvailableValues(int type) {
993
    throw new UnsupportedOperationException();
994
  }
995

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

    
1001
  @Override
1002
  public DynField setDefaultDynValue(Object defaultValue) {
1003
    throw new UnsupportedOperationException();
1004
  }
1005

    
1006
  @Override
1007
  public Class getClassOfValue() {
1008
    return null;
1009
  }
1010

    
1011
  @Override
1012
  public DynField getElementsType() {
1013
    return null;
1014
  }
1015

    
1016
  @Override
1017
  public DynField setClassOfValue(Class theClass)
1018
          throws DynFieldIsNotAContainerException {
1019
    throw new UnsupportedOperationException();
1020
  }
1021

    
1022
  @Override
1023
  public DynField setElementsType(DynStruct type)
1024
          throws DynFieldIsNotAContainerException {
1025
    throw new UnsupportedOperationException();
1026
  }
1027

    
1028
  @Override
1029
  public DynField setElementsType(int type)
1030
          throws DynFieldIsNotAContainerException {
1031
    throw new UnsupportedOperationException();
1032
  }
1033

    
1034
  public FeatureAttributeDescriptor setDataProfileName(String dataProfile) {
1035
    this.dataProfile = dataProfile;
1036
    return this;
1037
  }
1038

    
1039
  @Override
1040
  public String getDataProfileName() {
1041
    return dataProfile;
1042
  }
1043

    
1044
  @Override
1045
  public DataProfile getDataProfile() {
1046
    if (StringUtils.isBlank(dataProfile)) {
1047
      return null;
1048
    }
1049
    DataProfile profile = DALLocator.getDataManager().getDataProfile(dataProfile);
1050
    return profile;
1051
  }
1052

    
1053
  @Override
1054
  public void validate(Object value) throws DynFieldValidateException {
1055

    
1056
    if (value == null && !this.allowNull()) {
1057
      throw new DynFieldValidateException(value, this, null);
1058
    }
1059

    
1060
    try {
1061
      this.dataType.coerce(value);
1062
    } catch (CoercionException e) {
1063
      throw new DynFieldValidateException(value, this, e);
1064
    }
1065

    
1066
    /*
1067
         * Other checks will be needed
1068
     */
1069
  }
1070

    
1071
  @Override
1072
  public String getSubtype() {
1073
    if (featureAttributeGetter != null) {
1074
      return featureAttributeGetter.getDataType().getSubtype();
1075
    }
1076
    return this.dataType.getSubtype();
1077
  }
1078

    
1079
  @Override
1080
  public Object coerce(Object value) throws CoercionException {
1081
    if (value == null) {
1082
      return value; // O debe devolver this.defaultValue
1083
    }
1084
    try {
1085
      return this.getDataType().coerce(value, this.getCoercionContext());
1086
    } catch (Exception ex) {
1087
      throw new RuntimeException(ex);
1088
    }
1089
  }
1090

    
1091
  @Override
1092
  public DynField setAvailableValues(List values) {
1093
    if (values == null || values.isEmpty()) {
1094
      this.availableValues = null;
1095
    } else {
1096
      this.availableValues = (DynObjectValueItem[]) values.toArray(
1097
              new DynObjectValueItem[values.size()]
1098
      );
1099
    }
1100
    return this;
1101
  }
1102

    
1103
  @Override
1104
  public String getGroup() {
1105
    return this.groupName;
1106
  }
1107

    
1108
  @Override
1109
  public int getOder() {
1110
    return this.order;
1111
  }
1112

    
1113
  @Override
1114
  public String getLabel() {
1115
    if (this.label == null) {
1116
      return this.getName();
1117
    }
1118
    return this.label;
1119
  }
1120

    
1121
  @Override
1122
  public String getLocalizedLabel() {
1123
    if (StringUtils.isBlank(this.label)) {
1124
      return this.getName();
1125
    }
1126
    I18nManager i18n = ToolsLocator.getI18nManager();
1127
    return i18n.getTranslation(this.label);
1128
  }
1129

    
1130
  @Override
1131
  public DynField setLabel(String label) {
1132
    this.label = label;
1133
    return this;
1134
  }
1135

    
1136
  @Override
1137
  public DynField setShortLabel(String shortLabel) {
1138
    this.shortLabel = shortLabel;
1139
    return this;
1140
  }
1141

    
1142
  @Override
1143
  public String getShortLabel() {
1144
    return StringUtils.isBlank(shortLabel) ? getLabel() : shortLabel;
1145
  }
1146

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

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

    
1162
  @Override
1163
  public DynField setOrder(int order) {
1164
    this.order = order;
1165
    return this;
1166
  }
1167

    
1168
  @Override
1169
  public DynField setHidden(boolean hidden) {
1170
    this.hidden = hidden;
1171
    return this;
1172
  }
1173

    
1174
  @Override
1175
  public boolean isHidden() {
1176
    return this.hidden;
1177
  }
1178

    
1179
  @Override
1180
  public DynField setReadOnly(boolean readOnly) {
1181
    this.readOnly = readOnly;
1182
    return this;
1183
  }
1184

    
1185
  @Override
1186
  public boolean isContainer() {
1187
    return false;
1188
  }
1189

    
1190
  @Override
1191
  public Class getClassOfItems() {
1192
    return null;
1193
  }
1194

    
1195
  @Override
1196
  public DynField setDefaultFieldValue(Object defaultValue) {
1197
    throw new UnsupportedOperationException();
1198
  }
1199

    
1200
  @Override
1201
  public DynField setClassOfItems(Class theClass) {
1202
    throw new UnsupportedOperationException();
1203
  }
1204

    
1205
  @Override
1206
  public DynField setType(DataType type) {
1207
    throw new UnsupportedOperationException();
1208
  }
1209

    
1210
  @Override
1211
  public DynField setSubtype(String subtype) {
1212
    throw new UnsupportedOperationException();
1213
  }
1214

    
1215
  @Override
1216
  public boolean isTime() {
1217
    return isTime;
1218
  }
1219

    
1220
  @Override
1221
  public FeatureAttributeGetter getFeatureAttributeGetter() {
1222
    return featureAttributeGetter;
1223
  }
1224

    
1225
  @Override
1226
  public void setFeatureAttributeGetter(
1227
          FeatureAttributeGetter featureAttributeTransform) {
1228
    this.featureAttributeGetter = featureAttributeTransform;
1229
  }
1230

    
1231
  @Override
1232
  public FeatureAttributeEmulator getFeatureAttributeEmulator() {
1233
    return this.featureAttributeEmulator;
1234
  }
1235

    
1236
  public FeatureAttributeDescriptor setFeatureAttributeEmulator(FeatureAttributeEmulator featureAttributeEmulator) {
1237
    this.featureAttributeEmulator = featureAttributeEmulator;
1238
    return this;
1239
  }
1240

    
1241
  @Override
1242
  public boolean isIndexed() {
1243
    return this.indexed;
1244
  }
1245

    
1246
  @Override
1247
  public boolean isForeingKey() {
1248
    return this.foreingKey != null && this.foreingKey.isForeingKey();
1249
  }
1250

    
1251
  @Override
1252
  public ForeingKey getForeingKey() {
1253
    return this.foreingKey;
1254
  }
1255

    
1256
  @Override
1257
  public boolean allowIndexDuplicateds() {
1258
    return this.allowIndexDuplicateds;
1259
  }
1260

    
1261
  @Override
1262
  public boolean isIndexAscending() {
1263
    return this.isIndexAscending;
1264
  }
1265

    
1266
  @Override
1267
  public DynField setClassOfValue(DynStruct dynStrct) {
1268
    throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
1269
  }
1270

    
1271
  @Override
1272
  public DynField setClassOfValue(String theClassNameOfValue) {
1273
    throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
1274
  }
1275

    
1276
  @Override
1277
  public String getClassNameOfValue() {
1278
    return null;
1279
  }
1280

    
1281
  @Override
1282
  public DynStruct getDynClassOfValue() {
1283
    return null;
1284
  }
1285

    
1286
  @Override
1287
  public DynField setTypeOfItems(int type) {
1288
    throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
1289
  }
1290

    
1291
  @Override
1292
  public int getTypeOfItems() {
1293
    return DataTypes.INVALID;
1294
  }
1295

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

    
1301
  @Override
1302
  public DynField setClassOfItems(String theClassNameOfValue) {
1303
    throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
1304
  }
1305

    
1306
  @Override
1307
  public String getClassNameOfItems() {
1308
    return null;
1309
  }
1310

    
1311
  @Override
1312
  public DynStruct getDynClassOfItems() {
1313
    return null;
1314
  }
1315

    
1316
  @Override
1317
  public DynField setRelationType(int relationType) {
1318
    this.relationType = relationType;
1319
    return this;
1320
  }
1321

    
1322
  @Override
1323
  public int getRelationType() {
1324
    return this.relationType;
1325
  }
1326

    
1327
  @Override
1328
  public DynField setAvailableValues(DynMethod availableValuesMethod) {
1329
    this.availableValuesMethod = availableValuesMethod;
1330
    return this;
1331
  }
1332

    
1333
  @Override
1334
  public DynObjectValueItem[] getAvailableValues(DynObject self) {
1335
    if (this.availableValuesMethod != null) {
1336
      DynObjectValueItem[] values;
1337
      try {
1338
        values = (DynObjectValueItem[]) this.availableValuesMethod.invoke(self, new Object[]{this});
1339
      } catch (DynMethodException ex) {
1340
        return this.availableValues;
1341
      }
1342
      if (values != null) {
1343
        return values;
1344
      }
1345
    }
1346
    return this.availableValues;
1347
  }
1348

    
1349
  @Override
1350
  public DynMethod getAvailableValuesMethod() {
1351
    return this.availableValuesMethod;
1352
  }
1353

    
1354
  @Override
1355
  public boolean isAvailableValuesCalculated() {
1356
    return this.availableValuesMethod != null;
1357
  }
1358

    
1359
  @Override
1360
  public DynMethod getCalculateMethod() {
1361
    return this.calculateMethod;
1362
  }
1363

    
1364
  @Override
1365
  public DynField setCalculateMethod(DynMethod method) {
1366
    this.calculateMethod = method;
1367
    return this;
1368
  }
1369

    
1370
  @Override
1371
  public boolean isCalculated() {
1372
    return this.calculateMethod != null;
1373
  }
1374

    
1375
  @Override
1376
  public Object getCalculatedValue(DynObject self) {
1377
    try {
1378
      return this.calculateMethod.invoke(self, new Object[]{this});
1379
    } catch (DynMethodException ex) {
1380
      throw new RuntimeException(ex);
1381
    }
1382
  }
1383

    
1384
  @Override
1385
  public DynField setValidateElements(boolean validate) {
1386
    return this;
1387
  }
1388

    
1389
  @Override
1390
  public boolean getValidateElements() {
1391
    return false;
1392
  }
1393

    
1394
  @Override
1395
  public boolean hasLabel() {
1396
    return StringUtils.isNotBlank(this.label);
1397
  }
1398

    
1399
  @Override
1400
  public boolean hasShortLabel() {
1401
    return StringUtils.isNotBlank(this.shortLabel);
1402
  }
1403

    
1404
  @Override
1405
  public boolean hasDescription() {
1406
    return StringUtils.isNotBlank(this.description);
1407
  }
1408

    
1409
  @Override
1410
  public FeatureAttributeDescriptor getValue() {
1411
    return this;
1412
  }
1413

    
1414
  @Override
1415
  public boolean supportSize() {
1416
    return this.getDataType().supportSize();
1417
  }
1418

    
1419
  @Override
1420
  public boolean supportPrecision() {
1421
    return this.getDataType().supportPrecision();
1422
  }
1423

    
1424
  @Override
1425
  public boolean supportScale() {
1426
    return this.getDataType().supportScale();
1427
  }
1428

    
1429
  private class ConstantValueEvaluator extends AbstractEvaluator {
1430

    
1431
    @Override
1432
    public Object evaluate(EvaluatorData data) throws EvaluatorException {
1433
      return defaultValue;
1434
    }
1435

    
1436
    @Override
1437
    public String getName() {
1438
      return "Constant attribute " + name;
1439
    }
1440
  }
1441

    
1442
  public void setConstantValue(boolean isConstantValue) {
1443
    if (isConstantValue) {
1444
      /* Cuando un attributo tiene asociado un evaluador, este se interpreta
1445
             * como que no debe cargarse de la fuente de datos subyacente, siendo
1446
             * el evaluador el que se encarga de proporcionar su valor.
1447
             * Nos limitamos a asignar un evaluador que retorna simpre el valor
1448
             * por defecto para ese attributo.
1449
       */
1450
      this.evaluator = new ConstantValueEvaluator();
1451
    } else {
1452
      this.evaluator = null;
1453
    }
1454
  }
1455

    
1456
  @Override
1457
  public boolean isComputed() {
1458
    return featureAttributeEmulator != null || evaluator != null || isCalculated();
1459
  }
1460

    
1461
  @Override
1462
  public FeatureStore getStore() {
1463
    FeatureType ftype = this.getFeatureType();
1464
    if (ftype == null) {
1465
      return null;
1466
    }
1467
    return ftype.getStore();
1468
  }
1469

    
1470
  @Override
1471
  public FeatureType getFeatureType() {
1472
    if (this.typeRef == null) {
1473
      return null;
1474
    }
1475
    FeatureType ftype = (FeatureType) this.typeRef.get();
1476
//        LOGGER.info(String.format("FeatureAttributeDescriptor[%08x] get FeatureType [%08x], ref [%08x].", this.hashCode(), ftype.hashCode(), typeRef.hashCode()));
1477
    return ftype;
1478
  }
1479

    
1480
  public FeatureAttributeDescriptor setInterval(Interval interval) {
1481
    this.interval = interval;
1482
    return this;
1483
  }
1484

    
1485
  public void fixAll() {
1486
    if (!this.getDataType().supportSize()) {
1487
      this.size = 0;
1488
    }
1489
    NumberPrecisionAndScale ps = this.getDataType().fixPrecisionAndScale(this.precision, this.scale);
1490
    this.precision = ps.getPrecision();
1491
    this.scale = ps.getScale();
1492

    
1493
    switch (this.getType()) {
1494
      case DataTypes.INSTANT:
1495
      case DataTypes.INTERVAL:
1496
      case DataTypes.DATE:
1497
      case DataTypes.TIME:
1498
      case DataTypes.TIMESTAMP:
1499
        if (this.getInterval() != null) {
1500
          this.isTime = true;
1501
        }
1502
        break;
1503
    }
1504
  }
1505

    
1506
  @Override
1507
  public String[] getRequiredFieldNames() {
1508
    FeatureAttributeEmulator emulator = this.getFeatureAttributeEmulator();
1509
    if (emulator == null) {
1510
      return null;
1511
    }
1512
    return emulator.getRequiredFieldNames();
1513
  }
1514

    
1515
  @Override
1516
  public void recentUsed() {
1517
    DefaultFeatureType.RECENTS_USEDS.add(this);
1518
  }
1519

    
1520
  @Override
1521
  public boolean hasOnlyMetadataChanges(FeatureAttributeDescriptor other) {
1522
    if (other == null) {
1523
      throw new NullPointerException();
1524
    }
1525
    DefaultFeatureAttributeDescriptor old = (DefaultFeatureAttributeDescriptor) other;
1526
    if (!StringUtils.equalsIgnoreCase(old.name, this.name)) {
1527
      return false;
1528
    }
1529
    if (old.isComputed() && old.isComputed() == this.isComputed()) {
1530
      return true;
1531
    }
1532
    if (this.dataType != old.dataType) {
1533
      return false;
1534
    }
1535
    if (this.size != old.size) {
1536
      return false;
1537
    }
1538
    if (this.precision != old.precision) {
1539
      return false;
1540
    }
1541
//        if( this.primaryKey != old.primaryKey ) {
1542
//            return false;
1543
//        }
1544
    if (this.geomType != old.geomType) {
1545
      return false;
1546
    }
1547
    if (this.SRS != old.SRS) {
1548
      return false;
1549
    }
1550
    if (this.isAutomatic != old.isAutomatic) {
1551
      return false;
1552
    }
1553
    return true;
1554
  }
1555

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

    
1618
}