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

History | View | Annotate | Download (44.3 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 = Locale.ENGLISH;
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
  public Locale getLocale() {
310
    return this.locale;
311
  }
312

    
313
  @Override
314
  public DataType getDataType() {
315
    if (featureAttributeGetter != null) {
316
      return featureAttributeGetter.getDataType();
317
    }
318
    return this.dataType;
319
  }
320

    
321
  public FeatureAttributeDescriptor setDataType(int type) {
322
    this.dataType = ToolsLocator.getDataTypesManager().get(type);
323
    return this;
324
  }
325

    
326
  @Override
327
  public DateFormat getDateFormat() {
328
    return this.dateFormat;
329
  }
330

    
331
  @Override
332
  public Object getDefaultValue() {
333
    return this.defaultValue;
334
  }
335

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

    
352
  @Override
353
  public Evaluator getEvaluator() {
354
    return this.evaluator;
355
  }
356

    
357
  @Override
358
  public int getGeometryType() {
359
    if (this.dataType.getType() != DataTypes.GEOMETRY) {
360
      return Geometry.TYPES.UNKNOWN;
361
    }
362
    return this.geometryType;
363
  }
364

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

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

    
393
  @Override
394
  public int getIndex() {
395
    return this.index;
396
  }
397

    
398
  protected FeatureAttributeDescriptor setIndex(int index) {
399
    this.index = index;
400
    return this;
401
  }
402

    
403
  @Override
404
  public int getMaximumOccurrences() {
405
    return this.maximumOccurrences;
406
  }
407

    
408
  @Override
409
  public int getMinimumOccurrences() {
410
    return this.minimumOccurrences;
411
  }
412

    
413
  @Override
414
  public String getName() {
415
    return this.name;
416
  }
417

    
418
  public FeatureAttributeDescriptor setName(String name) {
419
//        LOGGER.info(String.format("FeatureAttributeDescriptor[%08x] set name [%s].", this.hashCode(), name));
420
    this.name = name;
421
    return this;
422
  }
423

    
424
  @Override
425
  public Class getObjectClass() {
426
    if (getDataType().getType() == DataTypes.OBJECT) {
427
      return objectClass;
428
    }
429
    return getDataType().getDefaultClass();
430
  }
431

    
432
  @Override
433
  public int getPrecision() {
434
    return this.precision;
435
  }
436

    
437
  @Override
438
  public int getScale() {
439
    return this.scale;
440
  }
441

    
442
  @Override
443
  public Coercion getCoercion() {
444
    return this.getDataType().getCoercion();
445
  }
446

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

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

    
481
  @Override
482
  public int getRoundMode() {
483
    return this.roundMode;
484
  }
485

    
486
  @Override
487
  public IProjection getSRS() {
488
    return this.SRS;
489
  }
490

    
491
  @Override
492
  public Interval getInterval() {
493
    return this.interval;
494
  }
495

    
496
  public IProjection getSRS(WeakReference storeRef) {
497
    if (this.SRS == null) {
498
      FeatureStore store = (FeatureStore) storeRef.get();
499
      this.SRS = (IProjection) store.getDynValue(DataStore.METADATA_CRS);
500
    }
501
    return this.SRS;
502
  }
503

    
504
  @Override
505
  public int getSize() {
506
    return this.size;
507
  }
508

    
509
  @Override
510
  public boolean isPrimaryKey() {
511
    return this.primaryKey;
512
  }
513

    
514
  @Override
515
  public boolean isReadOnly() {
516
    if (this.readOnly) {
517
      return true;
518
    }
519
    return this.isComputed();
520
  }
521

    
522
  @Override
523
  public Object getAdditionalInfo(String infoName) {
524
    if (this.additionalInfo == null) {
525
      return null;
526
    }
527
    return this.additionalInfo.get(infoName);
528
  }
529

    
530
  @Override
531
  public boolean isAutomatic() {
532
    return this.isAutomatic;
533
  }
534

    
535
  @Override
536
  public boolean equals(Object obj) {
537
    if (this == obj) {
538
      return true;
539
    }
540
    if (!(obj instanceof DefaultFeatureAttributeDescriptor)) {
541
      return false;
542
    }
543
    DefaultFeatureAttributeDescriptor other
544
            = (DefaultFeatureAttributeDescriptor) obj;
545

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

    
550
    if (this.index != other.index) {
551
      return false;
552
    }
553

    
554
    if (!Objects.equals(this.name, other.name)) {
555
      return false;
556
    }
557

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

    
562
    if (this.size != other.size) {
563
      return false;
564
    }
565

    
566
    if (!Objects.equals(this.defaultValue, other.defaultValue)) {
567
      return false;
568
    }
569

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
626
    return true;
627
  }
628

    
629
  @Override
630
  public void loadFromState(PersistentState state)
631
          throws PersistenceException {
632
    allowNull = state.getBoolean("allowNull");
633
    dataType = ToolsLocator.getDataTypesManager().get(state.getInt("dataType"));
634
    dataProfile = state.getString("dataProfile");
635

    
636
//        FIXME: dateFormat;
637
    try {
638
      defaultValue = dataType.coerce(state.get("defaultValue"));
639
    } catch (CoercionException ex) {
640
    }
641

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

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

    
699
    description = state.getString("description");
700
    minValue = state.get("minValue");
701
    maxValue = state.get("maxValue");
702
    label = state.getString("label");
703
    order = state.getInt("order");
704
    hidden = state.getBoolean("hidden");
705
    groupName = state.getString("groupName");
706
    relationType = state.getInt("relationType");
707

    
708
    foreingKey = (DefaultForeingKey) state.get("foreingKey");
709
    if (foreingKey != null) {
710
      this.foreingKey.setDescriptor(this);
711
    }
712
    tags = (Tags) state.get("tags");
713
    if (tags == null) {
714
      this.tags = new DefaultTags();
715
    }
716
  }
717

    
718
  @Override
719
  public void saveToState(PersistentState state) throws PersistenceException {
720
    Coercion toString = ToolsLocator.getDataTypesManager().getCoercion(DataTypes.STRING);
721
    
722
    state.set("allowNull", allowNull);
723
    state.set("dataType", dataType.getType());
724
    state.set("dataProfile", dataProfile);
725

    
726
//        FIXME: dateFormat;
727
    state.set("defaultValue", Objects.toString(defaultValue, null));
728

    
729
    state.set("index", index);
730
    state.set("maximumOccurrences", maximumOccurrences);
731
    state.set("minimumOccurrences", minimumOccurrences);
732
    state.set("size", size);
733
    state.set("name", name);
734
    state.set("objectClass", objectClass == null ? null : objectClass.getName());
735
    state.set("precision", precision);
736
    state.set("scale", scale);
737
    state.set("roundMode", roundMode);
738
    try {
739
      state.set("locale", toString.coerce(this.locale));
740
    } catch (CoercionException ex) {
741
      state.setNull("locale");
742
    }
743
    state.set("evaluator", evaluator);
744

    
745
    state.set("primaryKey", primaryKey);
746
    state.set("readOnly", readOnly);
747
    state.set("SRS", SRS);
748
    GeometryType theGeomType = this.getGeomType();
749
    if (theGeomType == null) {
750
      state.set("geometryType", Geometry.TYPES.UNKNOWN);
751
      state.set("geometrySubType", Geometry.SUBTYPES.UNKNOWN);
752
    } else {
753
      state.set("geometryType", theGeomType.getType());
754
      state.set("geometrySubType", theGeomType.getSubType());
755
    }
756

    
757
//      FIXME: additionalInfo
758
    state.set("isAutomatic", isAutomatic);
759
    state.set("isTime", isTime);
760
    if (this.interval == null) {
761
      state.setNull("interval_start");
762
      state.setNull("interval_end");
763
    } else {
764
      state.set("interval_start", ((RelativeInterval) interval).getStart().toMillis());
765
      state.set("interval_end", ((RelativeInterval) interval).getEnd().toMillis());
766
    }
767
    state.set("SRS", SRS);
768

    
769
//      FIXME: featureAttributeGetter
770
    if (featureAttributeEmulator instanceof Persistent) {
771
      state.set("featureAttributeEmulator", featureAttributeEmulator);
772
    } else {
773
      state.setNull("featureAttributeEmulator");
774
    }
775

    
776
    state.set("indexed", indexed);
777
    state.set("isIndexAscending", isIndexAscending);
778
    state.set("allowIndexDuplicateds", allowIndexDuplicateds);
779

    
780
    if (this.availableValues == null) {
781
      state.setNull("availableValues");
782
    } else {
783
      Map<String, Object> values = new LinkedHashMap<>();
784
      for (DynObjectValueItem value : availableValues) {
785
        values.put(value.getLabel(), value.getValue());
786
      }
787
      state.set("availableValues", values);
788
    }
789
    state.set("description", description);
790
    state.set("minValue", minValue);
791
    state.set("maxValue", maxValue);
792
    state.set("label", label);
793
    state.set("order", order);
794
    state.set("hidden", hidden);
795
    state.set("groupName", groupName);
796
    state.set("relationType", relationType);
797

    
798
    state.set("foreingKey", this.foreingKey);
799
    state.set("tags", this.tags);
800

    
801
  }
802

    
803
  private static final String FEATATTRDESC_PERSISTENCE_DEFINITION_NAME = "FeatureAttributeDescriptor";
804

    
805
  public static void registerPersistenceDefinition() {
806
    PersistenceManager manager = ToolsLocator.getPersistenceManager();
807

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

    
860
      definition.addDynFieldObject("foreingKey")
861
              .setClassOfValue(DefaultForeingKey.class);
862

    
863
      definition.addDynFieldObject("tags")
864
              .setClassOfValue(Tags.class);
865

    
866
    }
867
  }
868

    
869
  /*
870
     * Start of DynField interface Implementation
871
     *
872
   */
873
  @Override
874
  public Tags getTags() {
875
    return tags;
876
  }
877

    
878
  @Override
879
  public boolean hasConstantAvailableValues() {
880
    return this.availableValues != null;
881
  }
882

    
883
  @Override
884
  public DynObjectValueItem[] getAvailableValues() {
885
    if (this.availableValues == null) {
886
      if (this.isForeingKey() && this.foreingKey.isClosedList()) {
887
        return this.foreingKey.getAvailableValues(null);
888
      }
889
    }
890
    return this.availableValues;
891
  }
892

    
893
  @Override
894
  public String getLabelOfValue(Object value) {
895
    if (this.labelOfValueMap != null) {
896
      String theLabel = this.labelOfValueMap.get(value);
897
      if (theLabel == null) {
898
        theLabel = Objects.toString(value, "");
899
      }
900
      return theLabel;
901
    }
902
    DynObjectValueItem[] values = this.getAvailableValues();
903
    if (values == null) {
904
      return Objects.toString(value, "");
905
    }
906
    Map<Object, String> map = new LinkedHashMap<>();
907
    for (DynObjectValueItem theValue : values) {
908
      map.put(theValue.getValue(), theValue.getLabel());
909
    }
910
    this.labelOfValueMap = map;
911
    String theLabel = this.labelOfValueMap.get(value);
912
    if (theLabel == null) {
913
      theLabel = Objects.toString(value, "");
914
    }
915
    return theLabel;
916
  }
917

    
918
  @Override
919
  public String getDescription() {
920
    if (this.description == null) {
921
      return getName();
922
    }
923
    return this.description;
924
  }
925

    
926
  @Override
927
  public Object getMaxValue() {
928
    return this.maxValue;
929
  }
930

    
931
  @Override
932
  public Object getMinValue() {
933
    return this.minValue;
934
  }
935

    
936
  @Override
937
  public int getTheTypeOfAvailableValues() {
938
    return 1;
939
  }
940

    
941
  @Override
942
  public int getType() {
943
    if (featureAttributeGetter != null) {
944
      return featureAttributeGetter.getDataType().getType();
945
    }
946
    return getDataType().getType();
947
  }
948

    
949
  @Override
950
  public boolean isMandatory() {
951
    return !allowNull() || isPrimaryKey();
952
  }
953

    
954
  @Override
955
  public boolean isPersistent() {
956
    return false;
957
  }
958

    
959
  @Override
960
  public DynField setAvailableValues(DynObjectValueItem[] values) {
961
    if (ArrayUtils.isEmpty(values)) {
962
      this.availableValues = null;
963
    } else {
964
      this.availableValues = values;
965
    }
966
    return this;
967
  }
968

    
969
  @Override
970
  public DynField setDescription(String description) {
971
    this.description = description;
972
    return this;
973
  }
974

    
975
  @Override
976
  public DynField setMandatory(boolean mandatory) {
977
    throw new UnsupportedOperationException();
978
  }
979

    
980
  @Override
981
  public DynField setMaxValue(Object maxValue) {
982
    try {
983
      this.maxValue = this.coerce(maxValue);
984
    } catch (CoercionException e) {
985
      throw new IllegalArgumentException(e);
986
    }
987
    return this;
988
  }
989

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

    
1000
  @Override
1001
  public DynField setPersistent(boolean persistent) {
1002
    throw new UnsupportedOperationException();
1003
  }
1004

    
1005
  @Override
1006
  public DynField setTheTypeOfAvailableValues(int type) {
1007
    throw new UnsupportedOperationException();
1008
  }
1009

    
1010
  @Override
1011
  public DynField setType(int type) {
1012
    throw new UnsupportedOperationException();
1013
  }
1014

    
1015
  @Override
1016
  public DynField setDefaultDynValue(Object defaultValue) {
1017
    throw new UnsupportedOperationException();
1018
  }
1019

    
1020
  @Override
1021
  public Class getClassOfValue() {
1022
    return null;
1023
  }
1024

    
1025
  @Override
1026
  public DynField getElementsType() {
1027
    return null;
1028
  }
1029

    
1030
  @Override
1031
  public DynField setClassOfValue(Class theClass)
1032
          throws DynFieldIsNotAContainerException {
1033
    throw new UnsupportedOperationException();
1034
  }
1035

    
1036
  @Override
1037
  public DynField setElementsType(DynStruct type)
1038
          throws DynFieldIsNotAContainerException {
1039
    throw new UnsupportedOperationException();
1040
  }
1041

    
1042
  @Override
1043
  public DynField setElementsType(int type)
1044
          throws DynFieldIsNotAContainerException {
1045
    throw new UnsupportedOperationException();
1046
  }
1047

    
1048
  public FeatureAttributeDescriptor setDataProfileName(String dataProfile) {
1049
    this.dataProfile = dataProfile;
1050
    return this;
1051
  }
1052

    
1053
  @Override
1054
  public String getDataProfileName() {
1055
    return dataProfile;
1056
  }
1057

    
1058
  @Override
1059
  public DataProfile getDataProfile() {
1060
    if (StringUtils.isBlank(dataProfile)) {
1061
      return null;
1062
    }
1063
    DataProfile profile = DALLocator.getDataManager().getDataProfile(dataProfile);
1064
    return profile;
1065
  }
1066

    
1067
  @Override
1068
  public void validate(Object value) throws DynFieldValidateException {
1069

    
1070
    if (value == null && !this.allowNull()) {
1071
      throw new DynFieldValidateException(value, this, null);
1072
    }
1073

    
1074
    try {
1075
      this.dataType.coerce(value);
1076
    } catch (CoercionException e) {
1077
      throw new DynFieldValidateException(value, this, e);
1078
    }
1079

    
1080
    /*
1081
         * Other checks will be needed
1082
     */
1083
  }
1084

    
1085
  @Override
1086
  public String getSubtype() {
1087
    if (featureAttributeGetter != null) {
1088
      return featureAttributeGetter.getDataType().getSubtype();
1089
    }
1090
    return this.dataType.getSubtype();
1091
  }
1092

    
1093
  @Override
1094
  public Object coerce(Object value) throws CoercionException {
1095
    if (value == null) {
1096
      return value; // O debe devolver this.defaultValue
1097
    }
1098
    try {
1099
      return this.getDataType().coerce(value, this.getCoercionContext());
1100
    } catch (Exception ex) {
1101
      throw new RuntimeException(ex);
1102
    }
1103
  }
1104

    
1105
  @Override
1106
  public DynField setAvailableValues(List values) {
1107
    if (values == null || values.isEmpty()) {
1108
      this.availableValues = null;
1109
    } else {
1110
      this.availableValues = (DynObjectValueItem[]) values.toArray(
1111
              new DynObjectValueItem[values.size()]
1112
      );
1113
    }
1114
    return this;
1115
  }
1116

    
1117
  @Override
1118
  public String getGroup() {
1119
    return this.groupName;
1120
  }
1121

    
1122
  @Override
1123
  public int getOder() {
1124
    return this.order;
1125
  }
1126

    
1127
  @Override
1128
  public String getLabel() {
1129
    if (this.label == null) {
1130
      return this.getName();
1131
    }
1132
    return this.label;
1133
  }
1134

    
1135
  @Override
1136
  public String getLocalizedLabel() {
1137
    if (StringUtils.isBlank(this.label)) {
1138
      return this.getName();
1139
    }
1140
    I18nManager i18n = ToolsLocator.getI18nManager();
1141
    return i18n.getTranslation(this.label);
1142
  }
1143

    
1144
  @Override
1145
  public DynField setLabel(String label) {
1146
    this.label = label;
1147
    return this;
1148
  }
1149

    
1150
  @Override
1151
  public DynField setShortLabel(String shortLabel) {
1152
    this.shortLabel = shortLabel;
1153
    return this;
1154
  }
1155

    
1156
  @Override
1157
  public String getShortLabel() {
1158
    return StringUtils.isBlank(shortLabel) ? getLabel() : shortLabel;
1159
  }
1160

    
1161
  @Override
1162
  public String getLocalizedShortLabel() {
1163
    if (StringUtils.isBlank(shortLabel)) {
1164
      return this.getLocalizedLabel();
1165
    }
1166
    I18nManager i18n = ToolsLocator.getI18nManager();
1167
    return i18n.getTranslation(shortLabel);
1168
  }
1169

    
1170
  @Override
1171
  public DynField setGroup(String groupName) {
1172
    this.groupName = groupName;
1173
    return this;
1174
  }
1175

    
1176
  @Override
1177
  public DynField setOrder(int order) {
1178
    this.order = order;
1179
    return this;
1180
  }
1181

    
1182
  @Override
1183
  public DynField setHidden(boolean hidden) {
1184
    this.hidden = hidden;
1185
    return this;
1186
  }
1187

    
1188
  @Override
1189
  public boolean isHidden() {
1190
    return this.hidden;
1191
  }
1192

    
1193
  @Override
1194
  public DynField setReadOnly(boolean readOnly) {
1195
    this.readOnly = readOnly;
1196
    return this;
1197
  }
1198

    
1199
  @Override
1200
  public boolean isContainer() {
1201
    return false;
1202
  }
1203

    
1204
  @Override
1205
  public Class getClassOfItems() {
1206
    return null;
1207
  }
1208

    
1209
  @Override
1210
  public DynField setDefaultFieldValue(Object defaultValue) {
1211
    throw new UnsupportedOperationException();
1212
  }
1213

    
1214
  @Override
1215
  public DynField setClassOfItems(Class theClass) {
1216
    throw new UnsupportedOperationException();
1217
  }
1218

    
1219
  @Override
1220
  public DynField setType(DataType type) {
1221
    throw new UnsupportedOperationException();
1222
  }
1223

    
1224
  @Override
1225
  public DynField setSubtype(String subtype) {
1226
    throw new UnsupportedOperationException();
1227
  }
1228

    
1229
  @Override
1230
  public boolean isTime() {
1231
    return isTime;
1232
  }
1233

    
1234
  @Override
1235
  public FeatureAttributeGetter getFeatureAttributeGetter() {
1236
    return featureAttributeGetter;
1237
  }
1238

    
1239
  @Override
1240
  public void setFeatureAttributeGetter(
1241
          FeatureAttributeGetter featureAttributeTransform) {
1242
    this.featureAttributeGetter = featureAttributeTransform;
1243
  }
1244

    
1245
  @Override
1246
  public FeatureAttributeEmulator getFeatureAttributeEmulator() {
1247
    return this.featureAttributeEmulator;
1248
  }
1249

    
1250
  public FeatureAttributeDescriptor setFeatureAttributeEmulator(FeatureAttributeEmulator featureAttributeEmulator) {
1251
    this.featureAttributeEmulator = featureAttributeEmulator;
1252
    return this;
1253
  }
1254

    
1255
  @Override
1256
  public boolean isIndexed() {
1257
    return this.indexed;
1258
  }
1259

    
1260
  @Override
1261
  public boolean isForeingKey() {
1262
    return this.foreingKey != null && this.foreingKey.isForeingKey();
1263
  }
1264

    
1265
  @Override
1266
  public ForeingKey getForeingKey() {
1267
    return this.foreingKey;
1268
  }
1269

    
1270
  @Override
1271
  public boolean allowIndexDuplicateds() {
1272
    return this.allowIndexDuplicateds;
1273
  }
1274

    
1275
  @Override
1276
  public boolean isIndexAscending() {
1277
    return this.isIndexAscending;
1278
  }
1279

    
1280
  @Override
1281
  public DynField setClassOfValue(DynStruct dynStrct) {
1282
    throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
1283
  }
1284

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

    
1290
  @Override
1291
  public String getClassNameOfValue() {
1292
    return null;
1293
  }
1294

    
1295
  @Override
1296
  public DynStruct getDynClassOfValue() {
1297
    return null;
1298
  }
1299

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

    
1305
  @Override
1306
  public int getTypeOfItems() {
1307
    return DataTypes.INVALID;
1308
  }
1309

    
1310
  @Override
1311
  public DynField setClassOfItems(DynStruct dynStrct) {
1312
    throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
1313
  }
1314

    
1315
  @Override
1316
  public DynField setClassOfItems(String theClassNameOfValue) {
1317
    throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
1318
  }
1319

    
1320
  @Override
1321
  public String getClassNameOfItems() {
1322
    return null;
1323
  }
1324

    
1325
  @Override
1326
  public DynStruct getDynClassOfItems() {
1327
    return null;
1328
  }
1329

    
1330
  @Override
1331
  public DynField setRelationType(int relationType) {
1332
    this.relationType = relationType;
1333
    return this;
1334
  }
1335

    
1336
  @Override
1337
  public int getRelationType() {
1338
    return this.relationType;
1339
  }
1340

    
1341
  @Override
1342
  public DynField setAvailableValues(DynMethod availableValuesMethod) {
1343
    this.availableValuesMethod = availableValuesMethod;
1344
    return this;
1345
  }
1346

    
1347
  @Override
1348
  public DynObjectValueItem[] getAvailableValues(DynObject self) {
1349
    if (this.availableValuesMethod != null) {
1350
      DynObjectValueItem[] values;
1351
      try {
1352
        values = (DynObjectValueItem[]) this.availableValuesMethod.invoke(self, new Object[]{this});
1353
      } catch (DynMethodException ex) {
1354
        return this.availableValues;
1355
      }
1356
      if (values != null) {
1357
        return values;
1358
      }
1359
    }
1360
    return this.availableValues;
1361
  }
1362

    
1363
  @Override
1364
  public DynMethod getAvailableValuesMethod() {
1365
    return this.availableValuesMethod;
1366
  }
1367

    
1368
  @Override
1369
  public boolean isAvailableValuesCalculated() {
1370
    return this.availableValuesMethod != null;
1371
  }
1372

    
1373
  @Override
1374
  public DynMethod getCalculateMethod() {
1375
    return this.calculateMethod;
1376
  }
1377

    
1378
  @Override
1379
  public DynField setCalculateMethod(DynMethod method) {
1380
    this.calculateMethod = method;
1381
    return this;
1382
  }
1383

    
1384
  @Override
1385
  public boolean isCalculated() {
1386
    return this.calculateMethod != null;
1387
  }
1388

    
1389
  @Override
1390
  public Object getCalculatedValue(DynObject self) {
1391
    try {
1392
      return this.calculateMethod.invoke(self, new Object[]{this});
1393
    } catch (DynMethodException ex) {
1394
      throw new RuntimeException(ex);
1395
    }
1396
  }
1397

    
1398
  @Override
1399
  public DynField setValidateElements(boolean validate) {
1400
    return this;
1401
  }
1402

    
1403
  @Override
1404
  public boolean getValidateElements() {
1405
    return false;
1406
  }
1407

    
1408
  @Override
1409
  public boolean hasLabel() {
1410
    return StringUtils.isNotBlank(this.label);
1411
  }
1412

    
1413
  @Override
1414
  public boolean hasShortLabel() {
1415
    return StringUtils.isNotBlank(this.shortLabel);
1416
  }
1417

    
1418
  @Override
1419
  public boolean hasDescription() {
1420
    return StringUtils.isNotBlank(this.description);
1421
  }
1422

    
1423
  @Override
1424
  public FeatureAttributeDescriptor getValue() {
1425
    return this;
1426
  }
1427

    
1428
  private class ConstantValueEvaluator extends AbstractEvaluator {
1429

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1617
}