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

History | View | Annotate | Download (51.5 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
    private Object get(String name, Class theClass, int type) {
761
        Object value = this.get(name);
762
        if (theClass.isInstance(value)) {
763
            return value;
764
        }
765
        try {
766
            return this.getDataTypesManager().coerce(type, value);
767
        } catch (CoercionException e) {
768

    
769
            if (value == null) {
770
                return null;
771
            }
772
            throw new IllegalArgumentException(
773
                    "Can't convert to " + theClass.getName()
774
                    + " from '" + value.getClass().getName()
775
                    + "' with value '" + value.toString() + "'.");
776
        }
777
    }
778

    
779
    @Override
780
    public Object get(String name) {
781
        int index = this.data.getType().getIndex(name);
782
        if (index < 0) {
783
            // buscamos en los extra cols
784
            if (hasExtraColumnValue(name)) {
785
                return getExtraColumnValue(name);
786
            }
787
            if (hasExtraValue(name)) {
788
                return getExtraValue(name);
789
            }
790
            // y si esta ahi return
791
            throw new IllegalArgumentException("Attribute name '" + name + "' not found in the feature.");
792
        }
793
        return this.get(index);
794
    }
795

    
796
    @Override
797
    public boolean isNull(int index) {
798
        FeatureType type = this.data.getType();
799
        if (index < 0 || index >= type.size()) {
800
            throw new IllegalArgumentException("Attribute index '" + index + "' out of range (0 to " + this.data.getType().size() + ".");
801
        }
802
        FeatureAttributeDescriptor attribute = type.getAttributeDescriptor(index);
803
        if (!this.data.getType().hasEvaluators()) {
804
            return this.data.get(index) == null;
805
        }
806
        Evaluator eval = attribute.getEvaluator();
807
        if (eval == null) {
808
            return this.data.get(index) == null;
809
        }
810
        Object value = this.data.get(index);
811
        if (value != null) {
812
            return true;
813
        }
814
        try {
815
            value = eval.evaluate(this);
816
        } catch (EvaluatorException e) {
817
            throw new DataEvaluatorRuntimeException(e);
818
        }
819
        this.data.set(index, value);
820
        return value == null;
821
    }
822

    
823
    @Override
824
    public boolean isNull(String name) {
825
        int index = this.data.getType().getIndex(name);
826
        if (index < 0) {
827
            throw new IllegalArgumentException("Attribute name '" + name + "' not found in the feature.");
828
        }
829
        return this.isNull(index);
830
    }
831

    
832
    public boolean has_key(String key) {
833
        Object x = this.getType().get(key);
834
        return x != null;
835
    }
836

    
837
    public List<String> keys() {
838
        List<String> ks = new ArrayList<>();
839
        for (FeatureAttributeDescriptor attr : this.getType()) {
840
            ks.add(attr.getName());
841
        }
842
        return ks;
843
    }
844

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

    
853
            @Override
854
            public String next() {
855
                return ((FeatureAttributeDescriptor) it.next()).getName();
856
            }
857

    
858
            @Override
859
            public void remove() {
860
                throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
861
            }
862
        };
863
    }
864

    
865
    public Iterator iteritems() {
866
        final Iterator it = this.getType().iterator();
867
        return new Iterator<Map.Entry>() {
868
            @Override
869
            public boolean hasNext() {
870
                return it.hasNext();
871
            }
872

    
873
            @Override
874
            public Map.Entry next() {
875
                final String name = ((FeatureAttributeDescriptor) it.next()).getName();
876
                return new Map.Entry<String, Object>() {
877
                    @Override
878
                    public String getKey() {
879
                        return name;
880
                    }
881

    
882
                    @Override
883
                    public Object getValue() {
884
                        return get(name);
885
                    }
886

    
887
                    @Override
888
                    public Object setValue(Object value) {
889
                        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
890
                    }
891

    
892
                };
893
            }
894

    
895
            @Override
896
            public void remove() {
897
                throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
898
            }
899
        };
900
    }
901

    
902
    @Override
903
    public Object get(int index) {
904
        FeatureType type = this.data.getType();
905
        if (index < 0 || index >= type.size()) {
906
            throw new IllegalArgumentException("Attribute index '" + index + "' out of range (0 to " + this.data.getType().size() + ".");
907
        }
908
        Object value = this.data.get(index);
909
        FeatureAttributeDescriptor attribute = type.getAttributeDescriptor(index);
910
        if (type.hasEvaluators()) {
911
            Evaluator eval = attribute.getEvaluator();
912
            if (eval != null) {
913
                if (value == null) { // Ya hemos calculado el campo ?
914
                    // FIXME: para comprobar si esta calculado usar un array especifico.
915
                    try {
916
                        value = eval.evaluate(this);
917
                    } catch (EvaluatorException e) {
918
                        throw new DataEvaluatorRuntimeException(e);
919
                    }
920
                    this.data.set(index, value);
921
                }
922
            }
923
        }
924
        value = get(attribute, value);
925
        return value;
926
    }
927

    
928
    private Object get(FeatureAttributeDescriptor featureAttributeDescriptor, Object value) {
929
        FeatureAttributeEmulator emulator = featureAttributeDescriptor.getFeatureAttributeEmulator();
930
        if (emulator != null) {
931
//            int index = featureAttributeDescriptor.getIndex();
932
//            value = this.data.get(index);
933
//            if( value==null ) {
934
            value = this.getExtraValue(featureAttributeDescriptor.getName());
935
            if (value==null) {
936
                value = emulator.get(this);
937
            }
938
//                this.data.set(index,value);
939
//            }
940
        } else {
941
            FeatureAttributeGetter getter = featureAttributeDescriptor.getFeatureAttributeGetter();
942
            if (getter != null) {
943
                value = getter.getter(value);
944
            }
945
        }
946
        value = coerce(featureAttributeDescriptor, value);
947
        return value;
948
    }
949
    
950
    private Object coerce(FeatureAttributeDescriptor attr, Object value) {
951
        DataType dataType = attr.getDataType();
952
        Class<? extends DataType> theClass = dataType.getDefaultClass();
953
        if (theClass != null && !theClass.isInstance(value)) {
954
            try {
955
                value = this.getDataTypesManager().coerce(dataType.getType(), value);
956
            } catch (CoercionException e) {
957
                throw new IllegalArgumentException(
958
                        "Can't convert to " + theClass.getSimpleName()
959
                        + " from '" + value.getClass().getSimpleName()
960
                        + "' with value '" + value.toString() + "'.");
961
            }
962
        }
963
        if (attr.getType() == DataTypes.GEOMETRY) {
964
            if (value != null) {
965
                Geometry geom = (Geometry) value;
966
                if (geom.getProjection() == null) {
967
                    IProjection proj = ((DefaultFeatureAttributeDescriptor) attr).getSRS(this.storeRef);
968
                    geom.setProjection(proj);
969
                }
970
            }
971
        }
972
        return value;
973
    }
974

    
975
    @Override
976
    public byte[] getByteArray(String name) {
977
        return (byte[]) this.get(name);
978
    }
979

    
980
    @Override
981
    public byte[] getByteArray(int index) {
982
        return (byte[]) this.get(index);
983
    }
984

    
985
    @Override
986
    public Object[] getArray(String name) {
987
        return (Object[]) this.get(name);
988
    }
989

    
990
    @Override
991
    public Object[] getArray(int index) {
992
        return (Object[]) this.get(index);
993
    }
994

    
995
    @Override
996
    public boolean getBoolean(String name) {
997
        Boolean value = ((Boolean) this.get(name, Boolean.class, DataTypes.BOOLEAN));
998
        if (value == null) {
999
            return false;
1000
        }
1001
        return value;
1002
    }
1003

    
1004
    @Override
1005
    public boolean getBoolean(int index) {
1006
        Boolean value = ((Boolean) this.get(index, Boolean.class, DataTypes.BOOLEAN));
1007
        if (value == null) {
1008
            return false;
1009
        }
1010
        return value;
1011
    }
1012

    
1013
    @Override
1014
    public byte getByte(String name) {
1015
        Byte value = ((Byte) this.get(name, Byte.class, DataTypes.BYTE));
1016
        if (value == null) {
1017
            return 0;
1018
        }
1019
        return value;
1020
    }
1021

    
1022
    @Override
1023
    public byte getByte(int index) {
1024
        Byte value = ((Byte) this.get(index, Byte.class, DataTypes.BYTE));
1025
        if (value == null) {
1026
            return 0;
1027
        }
1028
        return value;
1029
    }
1030

    
1031
    @Override
1032
    public java.sql.Date getDate(String name) {
1033
        java.sql.Date value = ((java.sql.Date) this.get(name, java.sql.Date.class, DataTypes.DATE));
1034
        return value;
1035
    }
1036

    
1037
    @Override
1038
    public java.sql.Date getDate(int index) {
1039
        java.sql.Date value = ((java.sql.Date) this.get(index, java.sql.Date.class, DataTypes.DATE));
1040
        return value;
1041
    }
1042

    
1043
    @Override
1044
    public java.sql.Time getTime(String name) {
1045
        java.sql.Time value = ((java.sql.Time) this.get(name, java.sql.Time.class, DataTypes.TIME));
1046
        return value;
1047
    }
1048

    
1049
    @Override
1050
    public java.sql.Time getTime(int index) {
1051
        java.sql.Time value = ((java.sql.Time) this.get(index, java.sql.Time.class, DataTypes.TIME));
1052
        return value;
1053
    }
1054

    
1055
    @Override
1056
    public java.sql.Timestamp getTimestamp(String name) {
1057
        java.sql.Timestamp value = ((java.sql.Timestamp) this.get(name, java.sql.Timestamp.class, DataTypes.TIMESTAMP));
1058
        return value;
1059
    }
1060

    
1061
    @Override
1062
    public java.sql.Timestamp getTimestamp(int index) {
1063
        java.sql.Timestamp value = ((java.sql.Timestamp) this.get(index, java.sql.Timestamp.class, DataTypes.TIMESTAMP));
1064
        return value;
1065
    }
1066

    
1067
    @Override
1068
    public double getDouble(String name) {
1069
        Double value = ((Double) this.get(name, Double.class, DataTypes.DOUBLE));
1070
        if (value == null) {
1071
            return 0;
1072
        }
1073
        return value;
1074
    }
1075

    
1076
    @Override
1077
    public double getDouble(int index) {
1078

    
1079
        Double value = ((Double) this.get(index, Double.class, DataTypes.DOUBLE));
1080
        if (value == null) {
1081
            return 0;
1082
        }
1083
        return value;
1084
    }
1085

    
1086
    @Override
1087
    public BigDecimal getDecimal(String name) {
1088
        BigDecimal value = ((BigDecimal) this.get(name, BigDecimal.class, DataTypes.DECIMAL));
1089
        return value;
1090
    }
1091

    
1092
    @Override
1093
    public BigDecimal getDecimal(int index) {
1094
        BigDecimal value = ((BigDecimal) this.get(index, BigDecimal.class, DataTypes.DECIMAL));
1095
        return value;
1096
    }
1097

    
1098
    @Override
1099
    public Feature getFeature(String name) {
1100
        return this.getFeature(this.data.getType().getIndex(name));
1101
    }
1102

    
1103
    @Override
1104
    public Feature getFeature(int index) {
1105
        return (Feature) this.get(index);
1106
    }
1107

    
1108
    @Override
1109
    public float getFloat(String name) {
1110
        Float value = ((Float) this.get(name, Float.class, DataTypes.FLOAT));
1111
        if (value == null) {
1112
            return 0;
1113
        }
1114
        return value;
1115
    }
1116

    
1117
    @Override
1118
    public float getFloat(int index) {
1119
        Float value = ((Float) this.get(index, Float.class, DataTypes.FLOAT));
1120
        if (value == null) {
1121
            return 0;
1122
        }
1123
        return value;
1124
    }
1125

    
1126
    @Override
1127
    public Geometry getGeometry(String name) {
1128
        return (Geometry) this.get(name, Geometry.class, DataTypes.GEOMETRY);
1129
    }
1130

    
1131
    @Override
1132
    public Geometry getGeometry(int index) {
1133
        return (Geometry) this.get(index, Geometry.class, DataTypes.GEOMETRY);
1134
    }
1135

    
1136
    @Override
1137
    public int getInt(String name) {
1138
        Integer value = ((Integer) this.get(name, Integer.class, DataTypes.INT));
1139
        if (value == null) {
1140
            return 0;
1141
        }
1142
        return value;
1143
    }
1144

    
1145
    @Override
1146
    public int getInt(int index) {
1147
        Integer value = ((Integer) this.get(index, Integer.class, DataTypes.INT));
1148
        if (value == null) {
1149
            return 0;
1150
        }
1151
        return value;
1152
    }
1153

    
1154
    @Override
1155
    public long getLong(String name) {
1156
        Long value = ((Long) this.get(name, Long.class, DataTypes.LONG));
1157
        if (value == null) {
1158
            return 0;
1159
        }
1160
        return value;
1161
    }
1162

    
1163
    @Override
1164
    public long getLong(int index) {
1165
        Long value = ((Long) this.get(index, Long.class, DataTypes.LONG));
1166
        if (value == null) {
1167
            return 0;
1168
        }
1169
        return value;
1170
    }
1171

    
1172
    @Override
1173
    public String getString(String name) {
1174
        return (String) this.get(name, String.class, DataTypes.STRING);
1175
    }
1176

    
1177
    @Override
1178
    public String getString(int index) {
1179
        return (String) this.get(index, String.class, DataTypes.STRING);
1180
    }
1181

    
1182
    @Override
1183
    public Object getContextValue(String name) {
1184
        name = name.toLowerCase();
1185
        if (name.equals("store")) {
1186
            return this.getStore();
1187
        }
1188

    
1189
        if (name.equals("featuretype")) {
1190
            return this.data.getType();
1191
        }
1192

    
1193
        if (name.equals("feature")) {
1194
            return this;
1195
        }
1196

    
1197
        throw new IllegalArgumentException(name);
1198
    }
1199

    
1200
    @Override
1201
    public Iterator getDataNames() {
1202
        class DataNamesIterator implements Iterator {
1203

    
1204
            Iterator attributeIteraror;
1205

    
1206
            DataNamesIterator(DefaultFeature feature) {
1207
                this.attributeIteraror = feature.getType().iterator();
1208
            }
1209

    
1210
            @Override
1211
            public boolean hasNext() {
1212
                return this.attributeIteraror.hasNext();
1213
            }
1214

    
1215
            @Override
1216
            public Object next() {
1217
                return ((FeatureAttributeDescriptor) this.attributeIteraror
1218
                        .next()).getName();
1219
            }
1220

    
1221
            @Override
1222
            public void remove() {
1223
                throw new UnsupportedOperationException();
1224
            }
1225

    
1226
        }
1227
        return new DataNamesIterator(this);
1228
    }
1229

    
1230
    @Override
1231
    public Object getDataValue(String name) {
1232
        name = name.toLowerCase();
1233
        try {
1234
            return get(name);
1235
        } catch (IllegalArgumentException ex) {
1236
            if ("defaultgeometry".equalsIgnoreCase(name)) {
1237
                return this.getDefaultGeometry();
1238
            }
1239
            throw ex;
1240
        }
1241
    }
1242

    
1243
    @Override
1244
    public Iterator getDataValues() {
1245
        class DataValuesIterator implements Iterator {
1246

    
1247
            DefaultFeature feature;
1248
            int current = 0;
1249

    
1250
            DataValuesIterator(DefaultFeature feature) {
1251
                this.feature = feature;
1252
            }
1253

    
1254
            @Override
1255
            public boolean hasNext() {
1256
                return current < feature.getType().size() - 1;
1257
            }
1258

    
1259
            @Override
1260
            public Object next() {
1261
                return feature.get(current++);
1262
            }
1263

    
1264
            @Override
1265
            public void remove() {
1266
                throw new UnsupportedOperationException();
1267
            }
1268

    
1269
        }
1270
        return new DataValuesIterator(this);
1271
    }
1272

    
1273
    @Override
1274
    public boolean hasContextValue(String name) {
1275
        name = name.toLowerCase();
1276
        if (name.equals("store")) {
1277
            return true;
1278
        }
1279

    
1280
        if (name.equals("featuretype")) {
1281
            return true;
1282
        }
1283

    
1284
        return name.equals("feature");
1285
    }
1286

    
1287
    @Override
1288
    public boolean hasDataValue(String name) {
1289
        return this.hasValue(name);
1290
    }
1291

    
1292
//    @Override
1293
//    public Time getTime(int index) {
1294
//        return ((Time) this.get(index,Time.class,DataTypes.INSTANT));
1295
//    }
1296
//
1297
//    @Override
1298
//    public Time getTime(String name) {
1299
//        return this.getInstant(this.data.getType().getIndex(name));
1300
//    }
1301
//
1302
//    @Override
1303
//    public Instant getInstant(int index) {
1304
//        return ((Instant) this.get(index,Instant.class,DataTypes.INSTANT));
1305
//    }
1306
//
1307
//    @Override
1308
//    public Instant getInstant(String name) {
1309
//        return this.getInstant(this.data.getType().getIndex(name));
1310
//    }
1311
//
1312
//    @Override
1313
//    public Interval getInterval(int index) {
1314
//        return ((Interval) this.get(index,Interval.class,DataTypes.INTERVAL));
1315
//    }
1316
//
1317
//    @Override
1318
//    public Interval getInterval(String name) {
1319
//        return this.getInterval(this.data.getType().getIndex(name));
1320
//    }
1321
//
1322
    @Override
1323
    public DynObject getAsDynObject() {
1324
        DynObjectFeatureFacade facade = new DynObjectFeatureFacade(this);
1325
        return facade;
1326
    }
1327

    
1328
    @Override
1329
    public String toString() {
1330
        StringBuilder builder = new StringBuilder();
1331
        FeatureAttributeDescriptor[] attributeDescriptors
1332
                = getType().getAttributeDescriptors();
1333
        for (int i = 0; i < attributeDescriptors.length; i++) {
1334
            String name = attributeDescriptors[i].getName();
1335
            Object value = get(name);
1336
            builder.append(value);
1337
            if (i < attributeDescriptors.length - 1) {
1338
                builder.append(", ");
1339
            }
1340
        }
1341
        return builder.toString();
1342
    }
1343

    
1344
    /**
1345
     * It is a new feature that has already been inserted into the store but has not yet been saved to disk
1346
     * 
1347
     * @return the inserted
1348
     */
1349
    public boolean isInserted() {
1350
        return inserted;
1351
    }
1352

    
1353
    /**
1354
     * If true, marks the feature as already inserted in the vault but has not yet been saved to disk
1355
     * 
1356
     * @param inserted the inserted to set
1357
     */
1358
    public void setInserted(boolean inserted) {
1359
        this.inserted = inserted;
1360
//        this.data.setNew(!inserted);
1361
    }
1362

    
1363
    @Override
1364
    public EvaluatorData getEvaluatorData() {
1365
        return this;
1366
    }
1367

    
1368
    @Override
1369
    public int size() {
1370
        return this.data.getType().size();
1371
    }
1372

    
1373
    public boolean isEmpty() {
1374
        return false;
1375
    }
1376

    
1377
    public Iterator<String> iterator() {
1378
        final Iterator<FeatureAttributeDescriptor> x = this.data.getType().iterator();
1379
        return new Iterator<String>() {
1380
            @Override
1381
            public boolean hasNext() {
1382
                return x.hasNext();
1383
            }
1384

    
1385
            @Override
1386
            public String next() {
1387
                return x.next().getName();
1388
            }
1389
        };
1390
    }
1391

    
1392
    public boolean containsKey(String key) {
1393
        return this.data.getType().get(key) != null;
1394
    }
1395

    
1396
    @Override
1397
    public String getLabelOfValue(String name) {
1398
        FeatureAttributeDescriptor attrdesc = this.data.getType().getAttributeDescriptor(name);
1399
        Object value;
1400
        if (attrdesc == null) { // extra column
1401
            FeatureExtraColumns extraColumns = this.data.getType().getExtraColumns();
1402
            if (extraColumns==null) {
1403
                return name;
1404
            }
1405
            attrdesc = extraColumns.get(name);
1406
            if(attrdesc==null) {
1407
                return name;
1408
            }
1409
           value = this.get(name);
1410
        } else {
1411
           value = this.get(attrdesc.getIndex());
1412
        }
1413
        String label = attrdesc.getLabelOfValue(value);
1414
        return label;
1415
    }
1416

    
1417
    @Override
1418
    public void setExtraValue(String name, Object value) {
1419
        if (this.extraValues == null) {
1420
            this.extraValues = new HashMap<>();
1421
        }
1422
        this.extraValues.put(name, value);
1423
    }
1424

    
1425
    public Object getExtraColumnValue(String name) {
1426
        Object value;
1427
        FeatureExtraColumns columns = this.getType().getExtraColumns();
1428
        int index = columns.getIndexOf(name);
1429
        if (this.extraValues != null) {
1430
            if (this.extraValues.containsKey(name)) {
1431
                value = this.extraValues.get(name);
1432
                if (index >= 0){
1433
                    EditableFeatureAttributeDescriptor attrdesc = columns.get(index);
1434
                    value = coerce(attrdesc, value);
1435
                }
1436
                return value;
1437
            }
1438
        }
1439
        if (index < 0) {
1440
            throw new RuntimeException("Not extra column value found");
1441
        }
1442
        if (extraValuesData == null) {
1443
            extraValuesData = new Object[columns.size()];
1444
        }
1445
        EditableFeatureAttributeDescriptor attrdesc = columns.get(index);
1446
        value = extraValuesData[index];
1447
        if (value != null) {
1448
            return value;
1449
        }
1450
        value = this.getExtraValue(name);
1451
        if (value == null && !this.hasExtraValue(name) && attrdesc.getFeatureAttributeEmulator() != null) {
1452
            value = attrdesc.getFeatureAttributeEmulator().get(this);
1453
            value = coerce(attrdesc, value);
1454
            extraValuesData[index] = value;
1455
        } else {
1456
            value = coerce(attrdesc, value);
1457
            extraValuesData[index] = value;
1458
        }
1459
        
1460
        return value;
1461
    }
1462

    
1463
    @Override
1464
    public Object getExtraValue(String name) {
1465
        Object value = this.data.getExtraValue(name);
1466
        return value;
1467
    }
1468

    
1469
    @Override
1470
    public boolean hasExtraValue(String name) {
1471
        return this.data.hasExtraValue(name);
1472
    }
1473

    
1474
    private boolean hasExtraColumnValue(String name) {
1475
        if (this.extraValues != null) {
1476
            if (this.extraValues.containsKey(name)) {
1477
                return true;
1478
            }
1479
        }
1480
        FeatureExtraColumns columns = this.getType().getExtraColumns();
1481
        int index = columns.getIndexOf(name);
1482
        if (index >= 0) {
1483
            return true;
1484
        }
1485
        return false;
1486
    }
1487

    
1488
    private EditableFeatureAttributeDescriptor getExtraColumn(String name) {
1489
        FeatureExtraColumns columns = this.getType().getExtraColumns();
1490
        return columns.get(name);
1491
    }
1492

    
1493
    @Override
1494
    public boolean hasValue(String name) {
1495
        name = name.toLowerCase();
1496
        return this.data.getType().getIndex(name) >= 0
1497
                || hasExtraValue(name)
1498
                || hasExtraColumnValue(name);
1499
    }
1500

    
1501
    @Override
1502
    public Object getExtraValue(int index) {
1503
        return this.data.getExtraValue(index);
1504
    }
1505

    
1506
    @Override
1507
    public JsonObject toJson() {
1508
        JsonObjectBuilder builder = this.toJsonBuilder();
1509
        return builder.build();
1510
    }
1511

    
1512
    @Override
1513
    public JsonObjectBuilder toJsonBuilder() {
1514
        JsonObjectBuilder builder = Json.createObjectBuilder();
1515
        Date date;
1516
        Geometry geom;
1517
        FeatureType ft = this.getType();
1518
        for (FeatureAttributeDescriptor desc : ft) {
1519
            if (desc.isComputed()) {
1520
                continue;
1521
            }
1522
            if(this.isNull(desc.getName())){
1523
                builder.addNull(desc.getName());
1524
                continue;
1525
            }
1526
            switch (desc.getType()) {
1527
                case DataTypes.GEOMETRY:
1528
                    geom = this.getGeometry(desc.getIndex());
1529
                    if (geom != null) {
1530
                        builder.add(desc.getName(), geom.convertToHexWKBQuietly());
1531
                    }
1532
                    break;
1533
                case DataTypes.BOOLEAN:
1534
                    builder.add(desc.getName(), this.getBoolean(desc.getIndex()));
1535
                    break;
1536
                case DataTypes.BYTE:
1537
                    builder.add(desc.getName(), this.getByte(desc.getIndex()));
1538
                    break;
1539
                case DataTypes.INT:
1540
                    builder.add(desc.getName(), this.getInt(desc.getIndex()));
1541
                    break;
1542
                case DataTypes.LONG:
1543
                    builder.add(desc.getName(), this.getLong(desc.getIndex()));
1544
                    break;
1545
                case DataTypes.DOUBLE:
1546
                    builder.add(desc.getName(), this.getDouble(desc.getIndex()));
1547
                    break;
1548
                case DataTypes.FLOAT:
1549
                    builder.add(desc.getName(), this.getFloat(desc.getIndex()));
1550
                    break;
1551
                case DataTypes.DATE:
1552
                    // Format date as ISO 8601
1553
                    date = this.getDate(desc.getIndex());
1554
                    if (date == null) {
1555
                        builder.addNull(desc.getName());
1556
                    } else {
1557
                        LocalDateTime localDateTime = LocalDateTime.ofInstant(new Date(date.getTime()).toInstant(), ZoneId.systemDefault());
1558
                        String value = DateTimeFormatter.ISO_DATE.format(localDateTime);
1559
                        builder.add(desc.getName(), value);
1560
                    }
1561
                    break;
1562
                case DataTypes.TIMESTAMP:
1563
                    // Format date as ISO 8601
1564
                    date = this.getTimestamp(desc.getIndex());
1565
                    if (date == null) {
1566
                        builder.addNull(desc.getName());
1567
                    } else {
1568
                        LocalDateTime localDateTime = LocalDateTime.ofInstant(new Date(date.getTime()).toInstant(), ZoneId.systemDefault());
1569
                        String value = DateTimeFormatter.ISO_DATE_TIME.format(localDateTime);
1570
                        builder.add(desc.getName(), value);
1571
                    }
1572
                    break;
1573
                case DataTypes.TIME:
1574
                    // Format date as ISO 8601
1575
                    date = this.getTime(desc.getIndex());
1576
                    if (date == null) {
1577
                        builder.addNull(desc.getName());
1578
                    } else {
1579
                        LocalDateTime localDateTime = LocalDateTime.ofInstant(new Date(date.getTime()).toInstant(), ZoneId.systemDefault());
1580
                        String value = DateTimeFormatter.ISO_TIME.format(localDateTime);
1581
                        builder.add(desc.getName(), value);
1582
                    }
1583
                    break;
1584
                default:
1585
                    builder.add(desc.getName(), this.getStringOrDefault(desc.getIndex(), ""));
1586
            }
1587
        }
1588
        return builder;
1589
    }
1590

    
1591
    @Override
1592
    public List<String> getKeys() {
1593
        List<String> l = new ArrayList<>();
1594
        for (FeatureAttributeDescriptor descriptor : this.getType()) {
1595
            l.add(descriptor.getName());
1596
        }
1597
        return l;
1598
    }
1599

    
1600
    @Override
1601
    public String format(String name) {
1602
        int index = this.data.getType().getIndex(name);
1603
        if (index < 0) {
1604
            // buscamos en los extra cols
1605
            FeatureAttributeDescriptor attribute = this.getExtraColumn(name);
1606
            if( attribute!=null ) {
1607
                Object value = getExtraColumnValue(name);
1608
                return attribute.format(value);
1609
            }
1610
            throw new IllegalArgumentException("Attribute name '" + name + "' not found in the feature.");
1611
        }
1612
        return this.format(index);
1613
    }
1614

    
1615
    @Override
1616
    public String format(int index) {
1617
        Object value = this.get(index);
1618
        FeatureType type = this.data.getType();
1619
        FeatureAttributeDescriptor attribute = type.getAttributeDescriptor(index);
1620
        return attribute.format(value);
1621
    }
1622

    
1623
    
1624
}