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 / DefaultFeature.java @ 46050

History | View | Annotate | Download (50.1 KB)

1
/**
2
 * gvSIG. Desktop Geographic Information System.
3
 *
4
 * Copyright (C) 2007-2013 gvSIG Association.
5
 *
6
 * This program is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU General Public License
8
 * as published by the Free Software Foundation; either version 3
9
 * of the License, or (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19
 * MA  02110-1301, USA.
20
 *
21
 * For any additional information, do not hesitate to contact us
22
 * at info AT gvsig.com, or visit our website www.gvsig.com.
23
 */
24
package org.gvsig.fmap.dal.feature.impl;
25

    
26
import java.lang.ref.WeakReference;
27
import java.math.BigDecimal;
28
import java.time.LocalDateTime;
29
import java.time.ZoneId;
30
import java.time.format.DateTimeFormatter;
31
import java.util.ArrayList;
32
import java.util.Date;
33
import java.util.HashMap;
34
import java.util.Iterator;
35
import java.util.List;
36
import java.util.Map;
37
import java.util.Objects;
38
import java.util.function.Predicate;
39
import javax.json.JsonObject;
40
import org.apache.commons.lang3.ArrayUtils;
41
import org.apache.commons.lang3.StringUtils;
42
import org.cresques.cts.IProjection;
43
import org.gvsig.expressionevaluator.ExpressionUtils;
44
import org.gvsig.fmap.dal.DALLocator;
45
import org.gvsig.fmap.dal.DataTypes;
46
import org.gvsig.fmap.dal.exception.DataEvaluatorRuntimeException;
47
import org.gvsig.fmap.dal.exception.DataException;
48
import org.gvsig.fmap.dal.feature.DataProfile;
49
import org.gvsig.fmap.dal.feature.EditableFeature;
50
import org.gvsig.fmap.dal.feature.EditableFeatureAttributeDescriptor;
51
import org.gvsig.fmap.dal.feature.Feature;
52
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
53
import org.gvsig.fmap.dal.feature.FeatureAttributeEmulator;
54
import org.gvsig.fmap.dal.feature.FeatureAttributeGetter;
55
import org.gvsig.fmap.dal.feature.FeatureExtraColumns;
56
import org.gvsig.fmap.dal.feature.FeatureReference;
57
import org.gvsig.fmap.dal.feature.FeatureStore;
58
import org.gvsig.fmap.dal.feature.FeatureType;
59
import org.gvsig.fmap.dal.feature.exception.IllegalValueException;
60
import org.gvsig.fmap.dal.feature.exception.SetReadOnlyAttributeException;
61
import org.gvsig.fmap.dal.feature.impl.dynobjectutils.DynObjectFeatureFacade;
62
import org.gvsig.fmap.dal.feature.impl.featurereference.FeatureReferenceFactory;
63
import org.gvsig.fmap.dal.feature.spi.DefaultFeatureProvider;
64
import org.gvsig.fmap.dal.feature.spi.FeatureProvider;
65
import org.gvsig.fmap.geom.Geometry;
66
import org.gvsig.fmap.geom.primitive.Envelope;
67
import org.gvsig.json.Json;
68
import org.gvsig.json.JsonObjectBuilder;
69
import org.gvsig.tools.ToolsLocator;
70
import org.gvsig.tools.dataTypes.Coercion;
71
import org.gvsig.tools.dataTypes.CoercionException;
72
import org.gvsig.tools.dataTypes.DataType;
73
import org.gvsig.tools.dataTypes.DataTypesManager;
74
import org.gvsig.tools.dynobject.DynObject;
75
import org.gvsig.tools.evaluator.Evaluator;
76
import org.gvsig.tools.evaluator.EvaluatorData;
77
import org.gvsig.tools.evaluator.EvaluatorException;
78
import org.gvsig.tools.exception.BaseException;
79
import org.gvsig.tools.exception.BaseRuntimeException;
80
import org.gvsig.tools.lang.Cloneable;
81
import org.slf4j.Logger;
82
import org.slf4j.LoggerFactory;
83

    
84
@SuppressWarnings("UseSpecificCatch")
85
public class DefaultFeature implements Feature, EvaluatorData, Cloneable {
86

    
87
    private static final Logger LOGGER = LoggerFactory.getLogger(DefaultFeature.class);
88

    
89
    private static DataTypesManager dataTypesManager = null;
90
    protected FeatureProvider data;
91
    protected FeatureReference reference;
92
    private WeakReference storeRef;
93

    
94
    private boolean inserted = false;
95
    private Object[] extraValuesData;
96
    private Map<String, Object> extraValues; // not persistent
97

    
98
    /*
99
         * Usar con mucha precaucion o mejor no usar. Lo precisa el
100
         * DefaultFeatureSet en la ordenacion.
101
     */
102
    public DefaultFeature(FeatureStore store) {
103
        this.storeRef = new WeakReference(store);
104
        this.reference = null;
105
    }
106

    
107
    public DefaultFeature(FeatureStore store, FeatureProvider data) {
108
        this.data = data;
109
        this.extraValuesData = null;
110
        this.storeRef = new WeakReference(store);
111
        this.reference = null;
112
        this.inserted = !data.isNew();
113
    }
114

    
115
    DefaultFeature(DefaultFeature feature) {
116
        this.data = feature.data.getCopy();
117
        this.extraValuesData = ArrayUtils.clone(feature.extraValuesData);
118
        this.storeRef = feature.storeRef;
119
        this.reference = feature.reference;
120
        this.inserted = feature.isInserted();
121
    }
122

    
123
    public DefaultFeature(FeatureType targetType, Feature sourceFeature) {
124
        DefaultFeature defaultFeature = (DefaultFeature) sourceFeature;
125
        this.data = new DefaultFeatureProvider(targetType, (DefaultFeatureProvider) defaultFeature.getData());
126
        this.extraValuesData = null;
127
        this.storeRef = defaultFeature.storeRef;
128
        this.reference = defaultFeature.reference;
129
        this.inserted = defaultFeature.isInserted();
130

    
131
        FeatureType sourceType = sourceFeature.getType();
132

    
133
        for (FeatureAttributeDescriptor targetAttrDescriptor : targetType) {
134
            if (targetAttrDescriptor.isComputed()) {
135
                continue;
136
            }
137
            int sourceIndex = sourceType.getIndex(targetAttrDescriptor.getName());
138
            if (sourceIndex < 0) {
139
                continue;
140
            }
141
            Object value = sourceFeature.get(sourceIndex);
142
            if (value == null && !targetAttrDescriptor.allowNull()) {
143
                continue;
144
            }
145
            this.setforced(targetAttrDescriptor.getIndex(), targetAttrDescriptor, value);
146
        }
147
    }
148

    
149
    public void setData(FeatureProvider data) {
150
        this.data = data;
151
        this.extraValuesData = null;
152
        this.reference = null;
153
        this.inserted = true;
154
    }
155

    
156
    public FeatureProvider getData() {
157
        return this.data;
158
    }
159

    
160
    protected DataTypesManager getDataTypesManager() {
161
        if (dataTypesManager == null) {
162
            dataTypesManager = ToolsLocator.getDataTypesManager();
163
        }
164
        return dataTypesManager;
165
    }
166

    
167
    public boolean canSetValue(String name) {
168
        return this.canSetValue(this.getType().getAttributeDescriptor(name), null);
169
    }
170

    
171
    public boolean canSetValue(FeatureAttributeDescriptor attr,Predicate<FeatureAttributeDescriptor> filter) {
172
        // helper function to use in copyFrom
173
        if (attr==null  ) {
174
            return false;
175
        }
176
        if (attr.isAutomatic()  || attr.isComputed() ) {
177
            return false;
178
        }
179
        if( this.isInserted() &&  attr.isReadOnly()) {
180
            return false;
181
        }
182
        if( filter!=null && !filter.test(attr) ) {
183
            return false;
184
        }
185
        return true;
186
    }
187

    
188
    protected void set(FeatureAttributeDescriptor attribute, Object value) {
189
        int i = attribute.getIndex();
190

    
191
        if( this.isInserted() ) {
192
            if (attribute.isReadOnly()) {
193
                throw new SetReadOnlyAttributeException(attribute.getName(), this.getType());
194
            }
195
        } else {
196
            if (attribute.isComputed()) {
197
                throw new SetReadOnlyAttributeException(attribute.getName(), this.getType());
198
            }
199
        }
200
        FeatureAttributeEmulator emulator = attribute.getFeatureAttributeEmulator();
201
        if (emulator != null) {
202
            emulator.set((EditableFeature) this, value);
203
            return;
204
        }
205

    
206
        if (value == null) {
207
            if (!attribute.allowNull()) {
208
                if (!attribute.isAutomatic()) {
209
                    throw new IllegalValueException(attribute, value);
210
                }
211
            }
212
            this.data.set(i, null);
213
            return;
214

    
215
        }
216

    
217
        if (attribute.getFeatureAttributeGetter() != null) {
218
            value = attribute.getFeatureAttributeGetter().setter(value);
219
        }
220
        this.setforced(i, attribute, value);
221
    }
222

    
223
    private void setforced(int i, FeatureAttributeDescriptor attribute, Object value) {
224

    
225
        Class objectClass = attribute.getObjectClass();
226
        if (objectClass != null) {
227
            if (objectClass.isInstance(value)) {
228
                if (attribute.getType() == DataTypes.DECIMAL) {
229
                    BigDecimal d = (BigDecimal) value;
230
                    if (d.scale() == attribute.getScale() && d.precision() <= attribute.getPrecision()) {
231
                        this.data.set(i, value);
232
                        return;
233
                    }
234
                } else if (attribute.getType() == DataTypes.GEOMETRY) {
235
                    if (!attribute.getGeomType().equals(((Geometry) value).getGeometryType())) {
236
                        try {
237
                            Coercion coercer = attribute.getDataType().getCoercion();
238
                            value = coercer.coerce(value, attribute.getCoercionContext());
239
                        } catch (CoercionException e) {
240
                            throw new IllegalArgumentException("Can't convert to "
241
                                    + attribute.getDataType().getName()
242
                                    + " from '"
243
                                    + value == null ? "NULL" : value.getClass().getName()
244
                                            + "' with value '"
245
                                            + Objects.toString(value)
246
                                            + "' and context '"
247
                                            + attribute.getCoercionContext()
248
                                            + "'.");
249
                        }
250
                    } 
251
                    this.data.set(i, value);
252
                    return;
253
                } else {
254
                    this.data.set(i, value);
255
                    return;
256
                }
257
            }
258
            DataProfile dataProfile = attribute.getDataProfile();
259
            if (dataProfile != null) {
260
                try {
261
                    value = dataProfile.coerce(
262
                            attribute.getDataType(),
263
                            value,
264
                            attribute.getTags()
265
                    );
266
                } catch (CoercionException e) {
267

    
268
                }
269
            }
270
            try {
271
                Coercion coercer = attribute.getDataType().getCoercion();
272
                if (attribute.getType() == DataTypes.STRING && value instanceof Boolean) {
273
                    value = coercer.coerce(value, attribute.getCoercionContext());
274
                    value = StringUtils.left((String) value, attribute.getSize());
275
                } else {
276
                    value = coercer.coerce(value, attribute.getCoercionContext());
277
                }
278
            } catch (CoercionException e) {
279
                throw new IllegalArgumentException("Can't convert to "
280
                        + attribute.getDataType().getName()
281
                        + " from '"
282
                        + value == null ? "NULL" : value.getClass().getName()
283
                                + "' with value '"
284
                                + Objects.toString(value)
285
                                + "' and context '"
286
                                + attribute.getCoercionContext()
287
                                + "'.");
288
            }
289
        }
290
        this.data.set(i, value);
291
    }
292

    
293
    private Object get(int index, Class theClass, int type) {
294
        Object value = this.get(index);
295
        if (theClass.isInstance(value)) {
296
            return value;
297
        }
298
        try {
299
            return this.getDataTypesManager().coerce(type, value);
300
        } catch (CoercionException e) {
301

    
302
            if (value == null) {
303
                return null;
304
            }
305
            throw new IllegalArgumentException(
306
                    "Can't convert to " + theClass.getName()
307
                    + " from '" + value.getClass().getName()
308
                    + "' with value '" + value.toString() + "'.");
309
        }
310
    }
311

    
312
    public void initializeValues() {
313
        FeatureType type = this.getType();
314
        for (FeatureAttributeDescriptor attribute : type) {
315
            if (attribute.isAutomatic() || attribute.isReadOnly()
316
                    || attribute.isComputed()) {
317
                continue;
318
            }
319
            if (attribute.getDefaultValue() == null && !attribute.allowNull()) {
320
                continue;
321
            }
322
            Object value = attribute.getDefaultValue();
323
            if (value instanceof CharSequence) {
324
                String s = ((CharSequence) value).toString();
325
                if (ExpressionUtils.isDynamicText(s)) {
326
                    try {
327
                        value = ExpressionUtils.evaluateDynamicText(s);
328
                    } catch (Throwable th) {
329
                        value = null;
330
                    }
331
                }
332
            }
333
            this.set(attribute, value);
334
        }
335
    }
336

    
337
    public void clear() {
338
        initializeValues();
339
    }
340

    
341
    public void initializeValues(Feature feature) {
342
        FeatureType myType = this.getType();
343
        FeatureType type = feature.getType();
344
        extraValuesData = null;
345
        for (FeatureAttributeDescriptor attribute : type) {
346
            FeatureAttributeDescriptor myAttribute = myType.getAttributeDescriptor(attribute.getName());
347
            if (myAttribute != null) {
348
                this.set(myAttribute, feature.get(attribute.getIndex()));
349
            }
350
        }
351
    }
352

    
353
    @Override
354
    public FeatureStore getStore() {
355
        return (FeatureStore) this.storeRef.get();
356
    }
357

    
358
    @Override
359
    public FeatureType getType() {
360
        return this.data.getType();
361
    }
362

    
363
    @Override
364
    public EditableFeature getEditable() {
365
        return new DefaultEditableFeature(this);
366
    }
367

    
368
    @Override
369
    public Feature getCopy() {
370
        return new DefaultFeature(this);
371
    }
372

    
373
    @Override
374
    @SuppressWarnings("CloneDoesntCallSuperClone")
375
    public Object clone() throws CloneNotSupportedException {
376
        return new DefaultFeature(this);
377
    }
378

    
379
    @Override
380
    public FeatureReference getReference() {
381
        if (this.reference == null) {
382
            if (!isInserted()) {
383
                return null;
384
            }
385
            reference = FeatureReferenceFactory.createFromFeature(this);
386
        }
387
        return this.reference;
388
    }
389

    
390
    @Override
391
    public Object getOrDefault(String name, Object defaultValue) {
392
        int index = this.data.getType().getIndex(name);
393
        if (index < 0) {
394
            return defaultValue;
395
        }
396
        return this.get(index);
397
    }
398
    
399
    @Override
400
    public Object getOrDefault(String name, int type, Object defaultValue) {
401
        DataType dataType = ToolsLocator.getDataTypesManager().get(type);
402
        return getOrDefault(name, dataType, defaultValue);
403
    }
404
    
405
    @Override
406
    public Object getOrDefault(String name, DataType type, Object defaultValue) {
407
        int index = this.data.getType().getIndex(name);
408
        if (index < 0) {
409
            return defaultValue;
410
        }
411
        try {
412
            Object value = this.get(index);
413
            if(value == null){
414
                return defaultValue;
415
            }
416
            return type.coerce(value);
417
        } catch (Throwable th) {
418
            return defaultValue;
419
        }
420
    }
421

    
422
    @Override
423
    public String getStringOrDefault(String name, String defaultValue) {
424
        int index = this.data.getType().getIndex(name);
425
        if (index < 0) {
426
            return defaultValue;
427
        }
428
        try {
429
            return (String) this.get(index);
430
        } catch (Throwable th) {
431
            return defaultValue;
432
        }
433
    }
434

    
435
    @Override
436
    public boolean getBooleanOrDefault(String name, boolean defaultValue) {
437
        int index = this.data.getType().getIndex(name);
438
        if (index < 0) {
439
            return defaultValue;
440
        }
441
        try {
442
            return this.getBoolean(index);
443
        } catch (Throwable th) {
444
            return defaultValue;
445
        }
446
    }
447

    
448
    @Override
449
    public int getIntOrDefault(String name, int defaultValue) {
450
        int index = this.data.getType().getIndex(name);
451
        if (index < 0) {
452
            return defaultValue;
453
        }
454
        try {
455
            return this.getInt(index);
456
        } catch (Throwable th) {
457
            return defaultValue;
458
        }
459
    }
460

    
461
    @Override
462
    public long getLongOrDefault(String name, long defaultValue) {
463
        int index = this.data.getType().getIndex(name);
464
        if (index < 0) {
465
            return defaultValue;
466
        }
467
        try {
468
            return this.getLong(index);
469
        } catch (Throwable th) {
470
            return defaultValue;
471
        }
472
    }
473

    
474
    @Override
475
    public float getFloatOrDefault(String name, float defaultValue) {
476
        int index = this.data.getType().getIndex(name);
477
        if (index < 0) {
478
            return defaultValue;
479
        }
480
        try {
481
            return this.getFloat(index);
482
        } catch (Throwable th) {
483
            return defaultValue;
484
        }
485
    }
486

    
487
    @Override
488
    public double getDoubleOrDefault(String name, double defaultValue) {
489
        int index = this.data.getType().getIndex(name);
490
        if (index < 0) {
491
            return defaultValue;
492
        }
493
        try {
494
            return this.getDouble(index);
495
        } catch (Throwable th) {
496
            return defaultValue;
497
        }
498
    }
499

    
500
    @Override
501
    public BigDecimal getDecimalOrDefault(String name, BigDecimal defaultValue) {
502
        int index = this.data.getType().getIndex(name);
503
        if (index < 0) {
504
            return defaultValue;
505
        }
506
        try {
507
            return this.getDecimal(index);
508
        } catch (Throwable th) {
509
            return defaultValue;
510
        }
511
    }
512

    
513
    @Override
514
    public Date getDateOrDefault(String name, Date defaultValue) {
515
        int index = this.data.getType().getIndex(name);
516
        if (index < 0) {
517
            return defaultValue;
518
        }
519
        try {
520
            return this.getDate(index);
521
        } catch (Throwable th) {
522
            return defaultValue;
523
        }
524
    }
525

    
526
    @Override
527
    public Object getOrDefault(int index, Object defaultValue) {
528
        if (index < 0 || index >= this.data.getType().size()) {
529
            return defaultValue;
530
        }
531
        try {
532
            return this.get(index);
533
        } catch (Throwable th) {
534
            return defaultValue;
535
        }
536
    }
537

    
538
    @Override
539
    public String getStringOrDefault(int index, String defaultValue) {
540
        if (index < 0 || index >= this.data.getType().size()) {
541
            return defaultValue;
542
        }
543
        try {
544
            return this.getString(index);
545
        } catch (Throwable th) {
546
            return defaultValue;
547
        }
548
    }
549

    
550
    @Override
551
    public boolean getBooleanOrDefault(int index, boolean defaultValue) {
552
        if (index < 0 || index >= this.data.getType().size()) {
553
            return defaultValue;
554
        }
555
        try {
556
            return this.getBoolean(index);
557
        } catch (Throwable th) {
558
            return defaultValue;
559
        }
560
    }
561

    
562
    @Override
563
    public int getIntOrDefault(int index, int defaultValue) {
564
        if (index < 0 || index >= this.data.getType().size()) {
565
            return defaultValue;
566
        }
567
        try {
568
            return this.getInt(index);
569
        } catch (Throwable th) {
570
            return defaultValue;
571
        }
572
    }
573

    
574
    @Override
575
    public long getLongOrDefault(int index, long defaultValue) {
576
        if (index < 0 || index >= this.data.getType().size()) {
577
            return defaultValue;
578
        }
579
        try {
580
            return this.getLong(index);
581
        } catch (Throwable th) {
582
            return defaultValue;
583
        }
584
    }
585

    
586
    @Override
587
    public float getFloatOrDefault(int index, float defaultValue) {
588
        if (index < 0 || index >= this.data.getType().size()) {
589
            return defaultValue;
590
        }
591
        try {
592
            return this.getFloat(index);
593
        } catch (Throwable th) {
594
            return defaultValue;
595
        }
596
    }
597

    
598
    @Override
599
    public double getDoubleOrDefault(int index, double defaultValue) {
600
        if (index < 0 || index >= this.data.getType().size()) {
601
            return defaultValue;
602
        }
603
        try {
604
            return this.getDouble(index);
605
        } catch (Throwable th) {
606
            return defaultValue;
607
        }
608
    }
609

    
610
    @Override
611
    public BigDecimal getDecimalOrDefault(int index, BigDecimal defaultValue) {
612
        if (index < 0 || index >= this.data.getType().size()) {
613
            return defaultValue;
614
        }
615
        try {
616
            return this.getDecimal(index);
617
        } catch (Throwable th) {
618
            return defaultValue;
619
        }
620
    }
621

    
622
    @Override
623
    public Date getDateOrDefault(int index, Date defaultValue) {
624
        if (index < 0 || index >= this.data.getType().size()) {
625
            return defaultValue;
626
        }
627
        try {
628
            return this.getDate(index);
629
        } catch (Throwable th) {
630
            return defaultValue;
631
        }
632
    }
633

    
634
    @Override
635
    public void validate(int check) throws DataException {
636
        ((DefaultFeatureType) this.data.getType()).validateFeature(this, check);
637
    }
638

    
639
    class UnableToGetReferenceException extends BaseRuntimeException {
640

    
641
        /**
642
         *
643
         */
644
        private static final long serialVersionUID = 1812805035204824163L;
645

    
646
        /**
647
         * @param exception
648
         */
649
        @SuppressWarnings("OverridableMethodCallInConstructor")
650
        public UnableToGetReferenceException(BaseException exception) {
651
            super("Unable to get reference", "_UnableToGetReferenceException",
652
                    serialVersionUID);
653
            this.initCause(exception);
654

    
655
        }
656

    
657
    }
658

    
659
    @Override
660
    public List getSRSs() {
661
        // TODO Auto-generated method stub
662
        return null;
663
    }
664

    
665
    @Override
666
    public Envelope getDefaultEnvelope() {
667
        Envelope envelope = this.data.getDefaultEnvelope();
668
        if (envelope == null) {
669
            int i = this.data.getType().getDefaultGeometryAttributeIndex();
670
            if (i < 0) {
671
                return null;
672
            }
673
            Geometry geom = this.getDefaultGeometry();
674
            if (geom != null) {
675
                envelope = geom.getEnvelope();
676
            }
677
        }
678
        return envelope;
679
    }
680

    
681
    @Override
682
    public Geometry getDefaultGeometry() {
683
        Geometry geom = this.data.getDefaultGeometry();
684
        if (geom == null) {
685
            int i = this.data.getType().getDefaultGeometryAttributeIndex();
686
            if (i < 0) {
687
                return null;
688
            }
689
            Object x = this.get(i);
690
            if (x instanceof Geometry) {
691
                geom = (Geometry) x;
692
            } else {
693
                geom = this.getGeometry(i);
694
            }
695
        }
696
        if (geom != null) {
697
            if (geom.getProjection() == null) {
698
                FeatureType type = this.getType();
699
                DefaultFeatureAttributeDescriptor attrdesc = (DefaultFeatureAttributeDescriptor) type.get(type.getDefaultGeometryAttributeIndex());
700
                IProjection proj = attrdesc.getSRS(this.storeRef);
701
                geom.setProjection(proj);
702
            }
703
        }
704
        return geom;
705
    }
706

    
707
//    @Override
708
//    public Time getDefaultTime() {
709
//            Time time = this.data.getDefaultTime();
710
//        if( time == null ) {
711
//            int i = this.data.getType().getDefaultTimeAttributeIndex();
712
//            Object x = this.get(i);
713
//            if( x instanceof Time ) {
714
//                time = (Time) x;
715
//            } else {
716
//                time = this.getTime(i);
717
//            }
718
//        }
719
//        return time;
720
//    }
721
//
722
    @Override
723
    public IProjection getDefaultSRS() {
724
        IProjection srs = this.data.getType().getDefaultSRS();
725
        if (srs == null) {
726
            FeatureType type = this.getType();
727
            DefaultFeatureAttributeDescriptor attrdesc = (DefaultFeatureAttributeDescriptor) type.get(type.getDefaultGeometryAttributeIndex());
728
            srs = attrdesc.getSRS(this.storeRef);
729
        }
730
        return srs;
731
    }
732

    
733
    @Override
734
    public List getGeometries() {
735
        // TODO Auto-generated method stub
736
        return null;
737
    }
738

    
739
    @Override
740
    public Object getFromProfile(int index) {
741
        FeatureAttributeDescriptor descriptor = this.data.getType().getAttributeDescriptor(index);
742
        Object value = this.get(index);
743
        String profileName = descriptor.getDataProfileName();
744
        if (StringUtils.isBlank(profileName)) {
745
            return value;
746
        }
747
        DataProfile profile = DALLocator.getDataManager().getDataProfile(profileName);
748
        if (profile == null) {
749
            return value;
750
        }
751
        return profile.createData(value, descriptor.getTags());
752
    }
753

    
754
    @Override
755
    public Object getFromProfile(String name) {
756
        FeatureAttributeDescriptor descriptor = this.data.getType().getAttributeDescriptor(name);
757
        return this.getFromProfile(descriptor.getIndex());
758
    }
759

    
760
    @Override
761
    public Object get(String name) {
762
        int index = this.data.getType().getIndex(name);
763
        if (index < 0) {
764
            // buscamos en los extra cols
765
            if (hasExtraColumnValue(name)) {
766
                return getExtraColumnValue(name);
767
            }
768
            if (hasExtraValue(name)) {
769
                return getExtraValue(name);
770
            }
771
            // y si esta ahi return
772
            throw new IllegalArgumentException("Attribute name '" + name + "' not found in the feature.");
773
        }
774
        return this.get(index);
775
    }
776

    
777
    @Override
778
    public boolean isNull(int index) {
779
        FeatureType type = this.data.getType();
780
        if (index < 0 || index >= type.size()) {
781
            throw new IllegalArgumentException("Attribute index '" + index + "' out of range (0 to " + this.data.getType().size() + ".");
782
        }
783
        FeatureAttributeDescriptor attribute = type.getAttributeDescriptor(index);
784
        if (!this.data.getType().hasEvaluators()) {
785
            return this.data.get(index) == null;
786
        }
787
        Evaluator eval = attribute.getEvaluator();
788
        if (eval == null) {
789
            return this.data.get(index) == null;
790
        }
791
        Object value = this.data.get(index);
792
        if (value != null) {
793
            return true;
794
        }
795
        try {
796
            value = eval.evaluate(this);
797
        } catch (EvaluatorException e) {
798
            throw new DataEvaluatorRuntimeException(e);
799
        }
800
        this.data.set(index, value);
801
        return value == null;
802
    }
803

    
804
    @Override
805
    public boolean isNull(String name) {
806
        int index = this.data.getType().getIndex(name);
807
        if (index < 0) {
808
            throw new IllegalArgumentException("Attribute name '" + name + "' not found in the feature.");
809
        }
810
        return this.isNull(index);
811
    }
812

    
813
    public boolean has_key(String key) {
814
        Object x = this.getType().get(key);
815
        return x != null;
816
    }
817

    
818
    public List<String> keys() {
819
        List<String> ks = new ArrayList<>();
820
        for (FeatureAttributeDescriptor attr : this.getType()) {
821
            ks.add(attr.getName());
822
        }
823
        return ks;
824
    }
825

    
826
    public Iterator<String> iterkeys() {
827
        final Iterator it = this.getType().iterator();
828
        return new Iterator<String>() {
829
            @Override
830
            public boolean hasNext() {
831
                return it.hasNext();
832
            }
833

    
834
            @Override
835
            public String next() {
836
                return ((FeatureAttributeDescriptor) it.next()).getName();
837
            }
838

    
839
            @Override
840
            public void remove() {
841
                throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
842
            }
843
        };
844
    }
845

    
846
    public Iterator iteritems() {
847
        final Iterator it = this.getType().iterator();
848
        return new Iterator<Map.Entry>() {
849
            @Override
850
            public boolean hasNext() {
851
                return it.hasNext();
852
            }
853

    
854
            @Override
855
            public Map.Entry next() {
856
                final String name = ((FeatureAttributeDescriptor) it.next()).getName();
857
                return new Map.Entry<String, Object>() {
858
                    @Override
859
                    public String getKey() {
860
                        return name;
861
                    }
862

    
863
                    @Override
864
                    public Object getValue() {
865
                        return get(name);
866
                    }
867

    
868
                    @Override
869
                    public Object setValue(Object value) {
870
                        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
871
                    }
872

    
873
                };
874
            }
875

    
876
            @Override
877
            public void remove() {
878
                throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
879
            }
880
        };
881
    }
882

    
883
    @Override
884
    public Object get(int index) {
885
        FeatureType type = this.data.getType();
886
        if (index < 0 || index >= type.size()) {
887
            throw new IllegalArgumentException("Attribute index '" + index + "' out of range (0 to " + this.data.getType().size() + ".");
888
        }
889
        Object value = this.data.get(index);
890
        FeatureAttributeDescriptor attribute = type.getAttributeDescriptor(index);
891
        if (type.hasEvaluators()) {
892
            Evaluator eval = attribute.getEvaluator();
893
            if (eval != null) {
894
                if (value == null) { // Ya hemos calculado el campo ?
895
                    // FIXME: para comprobar si esta calculado usar un array especifico.
896
                    try {
897
                        value = eval.evaluate(this);
898
                    } catch (EvaluatorException e) {
899
                        throw new DataEvaluatorRuntimeException(e);
900
                    }
901
                    this.data.set(index, value);
902
                }
903
            }
904
        }
905
        value = get(attribute, value);
906
        return value;
907
    }
908

    
909
    private Object get(FeatureAttributeDescriptor featureAttributeDescriptor, Object value) {
910
        FeatureAttributeEmulator emulator = featureAttributeDescriptor.getFeatureAttributeEmulator();
911
        if (emulator != null) {
912
//            int index = featureAttributeDescriptor.getIndex();
913
//            value = this.data.get(index);
914
//            if( value==null ) {
915
            value = this.getExtraValue(featureAttributeDescriptor.getName());
916
            if (value==null) {
917
                value = emulator.get(this);
918
            }
919
//                this.data.set(index,value);
920
//            }
921
        } else {
922
            FeatureAttributeGetter getter = featureAttributeDescriptor.getFeatureAttributeGetter();
923
            if (getter != null) {
924
                value = getter.getter(value);
925
            }
926
        }
927
        value = coerce(featureAttributeDescriptor, value);
928
        return value;
929
    }
930
    
931
    private Object coerce(FeatureAttributeDescriptor attr, Object value) {
932
        DataType dataType = attr.getDataType();
933
        Class<? extends DataType> theClass = dataType.getDefaultClass();
934
        if (theClass != null && !theClass.isInstance(value)) {
935
            try {
936
                value = this.getDataTypesManager().coerce(dataType.getType(), value);
937
            } catch (CoercionException e) {
938
                throw new IllegalArgumentException(
939
                        "Can't convert to " + theClass.getSimpleName()
940
                        + " from '" + value.getClass().getSimpleName()
941
                        + "' with value '" + value.toString() + "'.");
942
            }
943
        }
944
        if (attr.getType() == DataTypes.GEOMETRY) {
945
            if (value != null) {
946
                Geometry geom = (Geometry) value;
947
                if (geom.getProjection() == null) {
948
                    IProjection proj = ((DefaultFeatureAttributeDescriptor) attr).getSRS(this.storeRef);
949
                    geom.setProjection(proj);
950
                }
951
            }
952
        }
953
        return value;
954
    }
955

    
956
    @Override
957
    public byte[] getByteArray(String name) {
958
        return this.getByteArray(this.data.getType().getIndex(name));
959
    }
960

    
961
    @Override
962
    public byte[] getByteArray(int index) {
963
        return (byte[]) this.get(index);
964
    }
965

    
966
    @Override
967
    public Object[] getArray(String name) {
968
        return this.getArray(this.data.getType().getIndex(name));
969
    }
970

    
971
    @Override
972
    public Object[] getArray(int index) {
973
        return (Object[]) this.get(index);
974
    }
975

    
976
    @Override
977
    public boolean getBoolean(String name) {
978
        return this.getBoolean(this.data.getType().getIndex(name));
979
    }
980

    
981
    @Override
982
    public boolean getBoolean(int index) {
983
        Boolean value = ((Boolean) this.get(index, Boolean.class, DataTypes.BOOLEAN));
984
        if (value == null) {
985
            return false;
986
        }
987
        return value;
988
    }
989

    
990
    @Override
991
    public byte getByte(String name) {
992
        return this.getByte(this.data.getType().getIndex(name));
993
    }
994

    
995
    @Override
996
    public byte getByte(int index) {
997
        Byte value = ((Byte) this.get(index, Byte.class, DataTypes.BYTE));
998
        if (value == null) {
999
            return 0;
1000
        }
1001
        return value;
1002
    }
1003

    
1004
    @Override
1005
    public java.sql.Date getDate(String name) {
1006
        return this.getDate(this.data.getType().getIndex(name));
1007
    }
1008

    
1009
    @Override
1010
    public java.sql.Date getDate(int index) {
1011
        java.sql.Date value = ((java.sql.Date) this.get(index, java.sql.Date.class, DataTypes.DATE));
1012
        return value;
1013
    }
1014

    
1015
    @Override
1016
    public java.sql.Time getTime(String name) {
1017
        return this.getTime(this.data.getType().getIndex(name));
1018
    }
1019

    
1020
    @Override
1021
    public java.sql.Time getTime(int index) {
1022
        java.sql.Time value = ((java.sql.Time) this.get(index, java.sql.Time.class, DataTypes.TIME));
1023
        return value;
1024
    }
1025

    
1026
    @Override
1027
    public java.sql.Timestamp getTimestamp(String name) {
1028
        return this.getTimestamp(this.data.getType().getIndex(name));
1029
    }
1030

    
1031
    @Override
1032
    public java.sql.Timestamp getTimestamp(int index) {
1033
        java.sql.Timestamp value = ((java.sql.Timestamp) this.get(index, java.sql.Timestamp.class, DataTypes.TIMESTAMP));
1034
        return value;
1035
    }
1036

    
1037
    @Override
1038
    public double getDouble(String name) {
1039
        return this.getDouble(this.data.getType().getIndex(name));
1040
    }
1041

    
1042
    @Override
1043
    public double getDouble(int index) {
1044

    
1045
        Double value = ((Double) this.get(index, Double.class, DataTypes.DOUBLE));
1046
        if (value == null) {
1047
            return 0;
1048
        }
1049
        return value;
1050
    }
1051

    
1052
    @Override
1053
    public BigDecimal getDecimal(String name) {
1054
        return this.getDecimal(this.data.getType().getIndex(name));
1055
    }
1056

    
1057
    @Override
1058
    public BigDecimal getDecimal(int index) {
1059
        BigDecimal value = ((BigDecimal) this.get(index, BigDecimal.class, DataTypes.DECIMAL));
1060
        return value;
1061
    }
1062

    
1063
    @Override
1064
    public Feature getFeature(String name) {
1065
        return this.getFeature(this.data.getType().getIndex(name));
1066
    }
1067

    
1068
    @Override
1069
    public Feature getFeature(int index) {
1070
        return (Feature) this.get(index);
1071
    }
1072

    
1073
    @Override
1074
    public float getFloat(String name) {
1075
        return this.getFloat(this.data.getType().getIndex(name));
1076
    }
1077

    
1078
    @Override
1079
    public float getFloat(int index) {
1080
        Float value = ((Float) this.get(index, Float.class, DataTypes.FLOAT));
1081
        if (value == null) {
1082
            return 0;
1083
        }
1084
        return value;
1085
    }
1086

    
1087
    @Override
1088
    public Geometry getGeometry(String name) {
1089
        return this.getGeometry(this.data.getType().getIndex(name));
1090
    }
1091

    
1092
    @Override
1093
    public Geometry getGeometry(int index) {
1094
        return (Geometry) this.get(index, Geometry.class, DataTypes.GEOMETRY);
1095
    }
1096

    
1097
    @Override
1098
    public int getInt(String name) {
1099
        return this.getInt(this.data.getType().getIndex(name));
1100
    }
1101

    
1102
    @Override
1103
    public int getInt(int index) {
1104
        Integer value = ((Integer) this.get(index, Integer.class, DataTypes.INT));
1105
        if (value == null) {
1106
            return 0;
1107
        }
1108
        return value;
1109
    }
1110

    
1111
    @Override
1112
    public long getLong(String name) {
1113
        return this.getLong(this.data.getType().getIndex(name));
1114
    }
1115

    
1116
    @Override
1117
    public long getLong(int index) {
1118
        Long value = ((Long) this.get(index, Long.class, DataTypes.LONG));
1119
        if (value == null) {
1120
            return 0;
1121
        }
1122
        return value;
1123
    }
1124

    
1125
    @Override
1126
    public String getString(String name) {
1127
        return this.getString(this.data.getType().getIndex(name));
1128
    }
1129

    
1130
    @Override
1131
    public String getString(int index) {
1132
        return (String) this.get(index, String.class, DataTypes.STRING);
1133
    }
1134

    
1135
    @Override
1136
    public Object getContextValue(String name) {
1137
        name = name.toLowerCase();
1138
        if (name.equals("store")) {
1139
            return this.getStore();
1140
        }
1141

    
1142
        if (name.equals("featuretype")) {
1143
            return this.data.getType();
1144
        }
1145

    
1146
        if (name.equals("feature")) {
1147
            return this;
1148
        }
1149

    
1150
        throw new IllegalArgumentException(name);
1151
    }
1152

    
1153
    @Override
1154
    public Iterator getDataNames() {
1155
        class DataNamesIterator implements Iterator {
1156

    
1157
            Iterator attributeIteraror;
1158

    
1159
            DataNamesIterator(DefaultFeature feature) {
1160
                this.attributeIteraror = feature.getType().iterator();
1161
            }
1162

    
1163
            @Override
1164
            public boolean hasNext() {
1165
                return this.attributeIteraror.hasNext();
1166
            }
1167

    
1168
            @Override
1169
            public Object next() {
1170
                return ((FeatureAttributeDescriptor) this.attributeIteraror
1171
                        .next()).getName();
1172
            }
1173

    
1174
            @Override
1175
            public void remove() {
1176
                throw new UnsupportedOperationException();
1177
            }
1178

    
1179
        }
1180
        return new DataNamesIterator(this);
1181
    }
1182

    
1183
    @Override
1184
    public Object getDataValue(String name) {
1185
        name = name.toLowerCase();
1186
        try {
1187
            return get(name);
1188
        } catch (IllegalArgumentException ex) {
1189
            if ("defaultgeometry".equalsIgnoreCase(name)) {
1190
                return this.getDefaultGeometry();
1191
            }
1192
            throw ex;
1193
        }
1194
    }
1195

    
1196
    @Override
1197
    public Iterator getDataValues() {
1198
        class DataValuesIterator implements Iterator {
1199

    
1200
            DefaultFeature feature;
1201
            int current = 0;
1202

    
1203
            DataValuesIterator(DefaultFeature feature) {
1204
                this.feature = feature;
1205
            }
1206

    
1207
            @Override
1208
            public boolean hasNext() {
1209
                return current < feature.getType().size() - 1;
1210
            }
1211

    
1212
            @Override
1213
            public Object next() {
1214
                return feature.get(current++);
1215
            }
1216

    
1217
            @Override
1218
            public void remove() {
1219
                throw new UnsupportedOperationException();
1220
            }
1221

    
1222
        }
1223
        return new DataValuesIterator(this);
1224
    }
1225

    
1226
    @Override
1227
    public boolean hasContextValue(String name) {
1228
        name = name.toLowerCase();
1229
        if (name.equals("store")) {
1230
            return true;
1231
        }
1232

    
1233
        if (name.equals("featuretype")) {
1234
            return true;
1235
        }
1236

    
1237
        return name.equals("feature");
1238
    }
1239

    
1240
    @Override
1241
    public boolean hasDataValue(String name) {
1242
        return this.hasValue(name);
1243
    }
1244

    
1245
//    @Override
1246
//    public Time getTime(int index) {
1247
//        return ((Time) this.get(index,Time.class,DataTypes.INSTANT));
1248
//    }
1249
//
1250
//    @Override
1251
//    public Time getTime(String name) {
1252
//        return this.getInstant(this.data.getType().getIndex(name));
1253
//    }
1254
//
1255
//    @Override
1256
//    public Instant getInstant(int index) {
1257
//        return ((Instant) this.get(index,Instant.class,DataTypes.INSTANT));
1258
//    }
1259
//
1260
//    @Override
1261
//    public Instant getInstant(String name) {
1262
//        return this.getInstant(this.data.getType().getIndex(name));
1263
//    }
1264
//
1265
//    @Override
1266
//    public Interval getInterval(int index) {
1267
//        return ((Interval) this.get(index,Interval.class,DataTypes.INTERVAL));
1268
//    }
1269
//
1270
//    @Override
1271
//    public Interval getInterval(String name) {
1272
//        return this.getInterval(this.data.getType().getIndex(name));
1273
//    }
1274
//
1275
    @Override
1276
    public DynObject getAsDynObject() {
1277
        DynObjectFeatureFacade facade = new DynObjectFeatureFacade(this);
1278
        return facade;
1279
    }
1280

    
1281
    @Override
1282
    public String toString() {
1283
        StringBuilder builder = new StringBuilder();
1284
        FeatureAttributeDescriptor[] attributeDescriptors
1285
                = getType().getAttributeDescriptors();
1286
        for (int i = 0; i < attributeDescriptors.length; i++) {
1287
            String name = attributeDescriptors[i].getName();
1288
            Object value = get(name);
1289
            builder.append(value);
1290
            if (i < attributeDescriptors.length - 1) {
1291
                builder.append(", ");
1292
            }
1293
        }
1294
        return builder.toString();
1295
    }
1296

    
1297
    /**
1298
     * It is a new feature that has already been inserted into the store but has not yet been saved to disk
1299
     * 
1300
     * @return the inserted
1301
     */
1302
    public boolean isInserted() {
1303
        return inserted;
1304
    }
1305

    
1306
    /**
1307
     * If true, marks the feature as already inserted in the vault but has not yet been saved to disk
1308
     * 
1309
     * @param inserted the inserted to set
1310
     */
1311
    public void setInserted(boolean inserted) {
1312
        this.inserted = inserted;
1313
//        this.data.setNew(!inserted);
1314
    }
1315

    
1316
    @Override
1317
    public EvaluatorData getEvaluatorData() {
1318
        return this;
1319
    }
1320

    
1321
    @Override
1322
    public int size() {
1323
        return this.data.getType().size();
1324
    }
1325

    
1326
    public boolean isEmpty() {
1327
        return false;
1328
    }
1329

    
1330
    public Iterator<String> iterator() {
1331
        final Iterator<FeatureAttributeDescriptor> x = this.data.getType().iterator();
1332
        return new Iterator<String>() {
1333
            @Override
1334
            public boolean hasNext() {
1335
                return x.hasNext();
1336
            }
1337

    
1338
            @Override
1339
            public String next() {
1340
                return x.next().getName();
1341
            }
1342
        };
1343
    }
1344

    
1345
    public boolean containsKey(String key) {
1346
        return this.data.getType().get(key) != null;
1347
    }
1348

    
1349
    @Override
1350
    public String getLabelOfValue(String name) {
1351
        FeatureAttributeDescriptor attrdesc = this.data.getType().getAttributeDescriptor(name);
1352
        Object value;
1353
        if (attrdesc == null) { // extra column
1354
            FeatureExtraColumns extraColumns = this.data.getType().getExtraColumns();
1355
            if (extraColumns==null) {
1356
                return name;
1357
            }
1358
            attrdesc = extraColumns.get(name);
1359
            if(attrdesc==null) {
1360
                return name;
1361
            }
1362
           value = this.get(name);
1363
        } else {
1364
           value = this.get(attrdesc.getIndex());
1365
        }
1366
        String label = attrdesc.getLabelOfValue(value);
1367
        return label;
1368
    }
1369

    
1370
    @Override
1371
    public void setExtraValue(String name, Object value) {
1372
        if (this.extraValues == null) {
1373
            this.extraValues = new HashMap<>();
1374
        }
1375
        this.extraValues.put(name, value);
1376
    }
1377

    
1378
    public Object getExtraColumnValue(String name) {
1379
        Object value;
1380
        FeatureExtraColumns columns = this.getType().getExtraColumns();
1381
        int index = columns.getIndexOf(name);
1382
        if (this.extraValues != null) {
1383
            if (this.extraValues.containsKey(name)) {
1384
                value = this.extraValues.get(name);
1385
                if (index >= 0){
1386
                    EditableFeatureAttributeDescriptor attrdesc = columns.get(index);
1387
                    value = coerce(attrdesc, value);
1388
                }
1389
                return value;
1390
            }
1391
        }
1392
        if (index < 0) {
1393
            throw new RuntimeException("Not extra column value found");
1394
        }
1395
        if (extraValuesData == null) {
1396
            extraValuesData = new Object[columns.size()];
1397
        }
1398
        EditableFeatureAttributeDescriptor attrdesc = columns.get(index);
1399
        value = extraValuesData[index];
1400
        if (value != null) {
1401
            return value;
1402
        }
1403
        value = this.getExtraValue(name);
1404
        if (value == null && !this.hasExtraValue(name) && attrdesc.getFeatureAttributeEmulator() != null) {
1405
            value = attrdesc.getFeatureAttributeEmulator().get(this);
1406
            value = coerce(attrdesc, value);
1407
            extraValuesData[index] = value;
1408
        } else {
1409
            value = coerce(attrdesc, value);
1410
            extraValuesData[index] = value;
1411
        }
1412
        
1413
        return value;
1414
    }
1415

    
1416
    @Override
1417
    public Object getExtraValue(String name) {
1418
        Object value = this.data.getExtraValue(name);
1419
        return value;
1420
    }
1421

    
1422
    @Override
1423
    public boolean hasExtraValue(String name) {
1424
        return this.data.hasExtraValue(name);
1425
    }
1426

    
1427
    private boolean hasExtraColumnValue(String name) {
1428
        if (this.extraValues != null) {
1429
            if (this.extraValues.containsKey(name)) {
1430
                return true;
1431
            }
1432
        }
1433
        FeatureExtraColumns columns = this.getType().getExtraColumns();
1434
        int index = columns.getIndexOf(name);
1435
        if (index >= 0) {
1436
            return true;
1437
        }
1438
        return false;
1439
    }
1440

    
1441
    private EditableFeatureAttributeDescriptor getExtraColumn(String name) {
1442
        FeatureExtraColumns columns = this.getType().getExtraColumns();
1443
        return columns.get(name);
1444
    }
1445

    
1446
    @Override
1447
    public boolean hasValue(String name) {
1448
        name = name.toLowerCase();
1449
        return this.data.getType().getIndex(name) >= 0
1450
                || hasExtraValue(name)
1451
                || hasExtraColumnValue(name);
1452
    }
1453

    
1454
    @Override
1455
    public Object getExtraValue(int index) {
1456
        return this.data.getExtraValue(index);
1457
    }
1458

    
1459
    @Override
1460
    public JsonObject toJson() {
1461
        JsonObjectBuilder builder = this.toJsonBuilder();
1462
        return builder.build();
1463
    }
1464

    
1465
    @Override
1466
    public JsonObjectBuilder toJsonBuilder() {
1467
        JsonObjectBuilder builder = Json.createObjectBuilder();
1468
        Date date;
1469
        Geometry geom;
1470
        FeatureType ft = this.getType();
1471
        for (FeatureAttributeDescriptor desc : ft) {
1472
            if (desc.isComputed()) {
1473
                continue;
1474
            }
1475
            if(this.isNull(desc.getName())){
1476
                builder.addNull(desc.getName());
1477
                continue;
1478
            }
1479
            switch (desc.getType()) {
1480
                case DataTypes.GEOMETRY:
1481
                    geom = this.getGeometry(desc.getIndex());
1482
                    if (geom != null) {
1483
                        builder.add(desc.getName(), geom.convertToHexWKBQuietly());
1484
                    }
1485
                    break;
1486
                case DataTypes.BOOLEAN:
1487
                    builder.add(desc.getName(), this.getBoolean(desc.getIndex()));
1488
                    break;
1489
                case DataTypes.BYTE:
1490
                    builder.add(desc.getName(), this.getByte(desc.getIndex()));
1491
                    break;
1492
                case DataTypes.INT:
1493
                    builder.add(desc.getName(), this.getInt(desc.getIndex()));
1494
                    break;
1495
                case DataTypes.LONG:
1496
                    builder.add(desc.getName(), this.getLong(desc.getIndex()));
1497
                    break;
1498
                case DataTypes.DOUBLE:
1499
                    builder.add(desc.getName(), this.getDouble(desc.getIndex()));
1500
                    break;
1501
                case DataTypes.FLOAT:
1502
                    builder.add(desc.getName(), this.getFloat(desc.getIndex()));
1503
                    break;
1504
                case DataTypes.DATE:
1505
                    // Format date as ISO 8601
1506
                    date = this.getDate(desc.getIndex());
1507
                    if (date == null) {
1508
                        builder.addNull(desc.getName());
1509
                    } else {
1510
                        LocalDateTime localDateTime = LocalDateTime.ofInstant(new Date(date.getTime()).toInstant(), ZoneId.systemDefault());
1511
                        String value = DateTimeFormatter.ISO_DATE.format(localDateTime);
1512
                        builder.add(desc.getName(), value);
1513
                    }
1514
                    break;
1515
                case DataTypes.TIMESTAMP:
1516
                    // Format date as ISO 8601
1517
                    date = this.getTimestamp(desc.getIndex());
1518
                    if (date == null) {
1519
                        builder.addNull(desc.getName());
1520
                    } else {
1521
                        LocalDateTime localDateTime = LocalDateTime.ofInstant(new Date(date.getTime()).toInstant(), ZoneId.systemDefault());
1522
                        String value = DateTimeFormatter.ISO_DATE_TIME.format(localDateTime);
1523
                        builder.add(desc.getName(), value);
1524
                    }
1525
                    break;
1526
                case DataTypes.TIME:
1527
                    // Format date as ISO 8601
1528
                    date = this.getTime(desc.getIndex());
1529
                    if (date == null) {
1530
                        builder.addNull(desc.getName());
1531
                    } else {
1532
                        LocalDateTime localDateTime = LocalDateTime.ofInstant(new Date(date.getTime()).toInstant(), ZoneId.systemDefault());
1533
                        String value = DateTimeFormatter.ISO_TIME.format(localDateTime);
1534
                        builder.add(desc.getName(), value);
1535
                    }
1536
                    break;
1537
                default:
1538
                    builder.add(desc.getName(), this.getStringOrDefault(desc.getIndex(), ""));
1539
            }
1540
        }
1541
        return builder;
1542
    }
1543

    
1544
    @Override
1545
    public List<String> getKeys() {
1546
        List<String> l = new ArrayList<>();
1547
        for (FeatureAttributeDescriptor descriptor : this.getType()) {
1548
            l.add(descriptor.getName());
1549
        }
1550
        return l;
1551
    }
1552

    
1553
    @Override
1554
    public String format(String name) {
1555
        int index = this.data.getType().getIndex(name);
1556
        if (index < 0) {
1557
            // buscamos en los extra cols
1558
            FeatureAttributeDescriptor attribute = this.getExtraColumn(name);
1559
            if( attribute!=null ) {
1560
                Object value = getExtraColumnValue(name);
1561
                return attribute.format(value);
1562
            }
1563
            throw new IllegalArgumentException("Attribute name '" + name + "' not found in the feature.");
1564
        }
1565
        return this.format(index);
1566
    }
1567

    
1568
    @Override
1569
    public String format(int index) {
1570
        Object value = this.get(index);
1571
        FeatureType type = this.data.getType();
1572
        FeatureAttributeDescriptor attribute = type.getAttributeDescriptor(index);
1573
        return attribute.format(value);
1574
    }
1575

    
1576
    
1577
}