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

History | View | Annotate | Download (46.4 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 javax.json.JsonObject;
39
import org.apache.commons.lang3.ArrayUtils;
40
import org.apache.commons.lang3.StringUtils;
41
import org.cresques.cts.IProjection;
42
import org.gvsig.expressionevaluator.ExpressionUtils;
43
import org.gvsig.fmap.dal.DALLocator;
44
import org.gvsig.fmap.dal.DataTypes;
45
import org.gvsig.fmap.dal.exception.DataEvaluatorRuntimeException;
46
import org.gvsig.fmap.dal.exception.DataException;
47
import org.gvsig.fmap.dal.feature.DataProfile;
48
import org.gvsig.fmap.dal.feature.EditableFeature;
49
import org.gvsig.fmap.dal.feature.EditableFeatureAttributeDescriptor;
50
import org.gvsig.fmap.dal.feature.Feature;
51
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
52
import org.gvsig.fmap.dal.feature.FeatureAttributeEmulator;
53
import org.gvsig.fmap.dal.feature.FeatureAttributeGetter;
54
import org.gvsig.fmap.dal.feature.FeatureExtraColumns;
55
import org.gvsig.fmap.dal.feature.FeatureReference;
56
import org.gvsig.fmap.dal.feature.FeatureStore;
57
import org.gvsig.fmap.dal.feature.FeatureType;
58
import org.gvsig.fmap.dal.feature.exception.IllegalValueException;
59
import org.gvsig.fmap.dal.feature.exception.SetReadOnlyAttributeException;
60
import org.gvsig.fmap.dal.feature.impl.dynobjectutils.DynObjectFeatureFacade;
61
import org.gvsig.fmap.dal.feature.impl.featurereference.FeatureReferenceFactory;
62
import org.gvsig.fmap.dal.feature.spi.DefaultFeatureProvider;
63
import org.gvsig.fmap.dal.feature.spi.FeatureProvider;
64
import org.gvsig.fmap.geom.Geometry;
65
import org.gvsig.fmap.geom.primitive.Envelope;
66
import org.gvsig.json.Json;
67
import org.gvsig.json.JsonObjectBuilder;
68
import org.gvsig.tools.ToolsLocator;
69
import org.gvsig.tools.dataTypes.Coercion;
70
import org.gvsig.tools.dataTypes.CoercionException;
71
import org.gvsig.tools.dataTypes.DataType;
72
import org.gvsig.tools.dataTypes.DataTypesManager;
73
import org.gvsig.tools.dataTypes.impl.coercion.CoerceToString;
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
    protected void set(FeatureAttributeDescriptor attribute, Object value) {
168
        int i = attribute.getIndex();
169

    
170
        if (attribute.isReadOnly()) {
171
            throw new SetReadOnlyAttributeException(attribute.getName(), this.getType());
172
        }
173
        FeatureAttributeEmulator emulator = attribute.getFeatureAttributeEmulator();
174
        if (emulator != null) {
175
            emulator.set((EditableFeature) this, value);
176
            return;
177
        }
178

    
179
        if (value == null) {
180
            if (!attribute.allowNull()) {
181
                if (!attribute.isAutomatic()) {
182
                    throw new IllegalValueException(attribute, value);
183
                }
184
            }
185
            this.data.set(i, null);
186
            return;
187

    
188
        }
189

    
190
        if (attribute.getFeatureAttributeGetter() != null) {
191
            value = attribute.getFeatureAttributeGetter().setter(value);
192
        }
193
        this.setforced(i, attribute, value);
194
    }
195

    
196
    private void setforced(int i, FeatureAttributeDescriptor attribute, Object value) {
197

    
198
        Class objectClass = attribute.getObjectClass();
199
        if (objectClass != null) {
200
            if (objectClass.isInstance(value)) {
201
                if (attribute.getType() == DataTypes.DECIMAL) {
202
                    BigDecimal d = (BigDecimal) value;
203
                    if (d.scale() == attribute.getScale() && d.precision() <= attribute.getPrecision()) {
204
                        this.data.set(i, value);
205
                        return;
206
                    }
207
                } else if (attribute.getType() == DataTypes.GEOMETRY) {
208
                    if (!attribute.getGeomType().equals(((Geometry) value).getGeometryType())) {
209
                        try {
210
                            Coercion coercer = attribute.getDataType().getCoercion();
211
                            value = coercer.coerce(value, attribute.getCoercionContext());
212
                        } catch (CoercionException e) {
213
                            throw new IllegalArgumentException("Can't convert to "
214
                                    + attribute.getDataType().getName()
215
                                    + " from '"
216
                                    + value == null ? "NULL" : value.getClass().getName()
217
                                            + "' with value '"
218
                                            + Objects.toString(value)
219
                                            + "' and context '"
220
                                            + attribute.getCoercionContext()
221
                                            + "'.");
222
                        }
223
                    } 
224
                    this.data.set(i, value);
225
                    return;
226
                } else {
227
                    this.data.set(i, value);
228
                    return;
229
                }
230
            }
231
            DataProfile dataProfile = attribute.getDataProfile();
232
            if (dataProfile != null) {
233
                try {
234
                    value = dataProfile.coerce(
235
                            attribute.getDataType(),
236
                            value,
237
                            attribute.getTags()
238
                    );
239
                } catch (CoercionException e) {
240

    
241
                }
242
            }
243
            try {
244
                Coercion coercer = attribute.getDataType().getCoercion();
245
                if (attribute.getType() == DataTypes.STRING && value instanceof Boolean) {
246
                    value = coercer.coerce(value, attribute.getCoercionContext());
247
                    value = StringUtils.left((String) value, attribute.getSize());
248
                } else {
249
                    value = coercer.coerce(value, attribute.getCoercionContext());
250
                }
251
            } catch (CoercionException e) {
252
                throw new IllegalArgumentException("Can't convert to "
253
                        + attribute.getDataType().getName()
254
                        + " from '"
255
                        + value == null ? "NULL" : value.getClass().getName()
256
                                + "' with value '"
257
                                + Objects.toString(value)
258
                                + "' and context '"
259
                                + attribute.getCoercionContext()
260
                                + "'.");
261
            }
262
        }
263
        this.data.set(i, value);
264
    }
265

    
266
    private Object get(int index, Class theClass, int type) {
267
        Object value = this.get(index);
268
        if (theClass.isInstance(value)) {
269
            return value;
270
        }
271
        try {
272
            return this.getDataTypesManager().coerce(type, value);
273
        } catch (CoercionException e) {
274

    
275
            if (value == null) {
276
                return null;
277
            }
278
            throw new IllegalArgumentException(
279
                    "Can't convert to " + theClass.getName()
280
                    + " from '" + value.getClass().getName()
281
                    + "' with value '" + value.toString() + "'.");
282
        }
283
    }
284

    
285
    public void initializeValues() {
286
        FeatureType type = this.getType();
287
        for (FeatureAttributeDescriptor attribute : type) {
288
            if (attribute.isAutomatic() || attribute.isReadOnly()
289
                    || attribute.isComputed()) {
290
                continue;
291
            }
292
            if (attribute.getDefaultValue() == null && !attribute.allowNull()) {
293
                continue;
294
            }
295
            Object value = attribute.getDefaultValue();
296
            if (value instanceof CharSequence) {
297
                String s = ((CharSequence) value).toString();
298
                if (ExpressionUtils.isDynamicText(s)) {
299
                    try {
300
                        value = ExpressionUtils.evaluateDynamicText(s);
301
                    } catch (Throwable th) {
302
                        value = null;
303
                    }
304
                }
305
            }
306
            this.set(attribute, value);
307
        }
308
    }
309

    
310
    public void clear() {
311
        initializeValues();
312
    }
313

    
314
    public void initializeValues(Feature feature) {
315
        FeatureType myType = this.getType();
316
        FeatureType type = feature.getType();
317
        extraValuesData = null;
318
        for (FeatureAttributeDescriptor attribute : type) {
319
            FeatureAttributeDescriptor myAttribute = myType.getAttributeDescriptor(attribute.getName());
320
            if (myAttribute != null) {
321
                this.set(myAttribute, feature.get(attribute.getIndex()));
322
            }
323
        }
324
    }
325

    
326
    @Override
327
    public FeatureStore getStore() {
328
        return (FeatureStore) this.storeRef.get();
329
    }
330

    
331
    @Override
332
    public FeatureType getType() {
333
        return this.data.getType();
334
    }
335

    
336
    @Override
337
    public EditableFeature getEditable() {
338
        return new DefaultEditableFeature(this);
339
    }
340

    
341
    @Override
342
    public Feature getCopy() {
343
        return new DefaultFeature(this);
344
    }
345

    
346
    @Override
347
    @SuppressWarnings("CloneDoesntCallSuperClone")
348
    public Object clone() throws CloneNotSupportedException {
349
        return new DefaultFeature(this);
350
    }
351

    
352
    @Override
353
    public FeatureReference getReference() {
354
        if (this.reference == null) {
355
            if (!isInserted()) {
356
                return null;
357
            }
358
            reference = FeatureReferenceFactory.createFromFeature(this);
359
        }
360
        return this.reference;
361
    }
362

    
363
    @Override
364
    public Object getOrDefault(String name, Object defaultValue) {
365
        int index = this.data.getType().getIndex(name);
366
        if (index < 0) {
367
            return defaultValue;
368
        }
369
        return this.get(index);
370
    }
371

    
372
    @Override
373
    public String getStringOrDefault(String name, String defaultValue) {
374
        int index = this.data.getType().getIndex(name);
375
        if (index < 0) {
376
            return defaultValue;
377
        }
378
        try {
379
            return (String) this.get(index);
380
        } catch (Throwable th) {
381
            return defaultValue;
382
        }
383
    }
384

    
385
    @Override
386
    public boolean getBooleanOrDefault(String name, boolean defaultValue) {
387
        int index = this.data.getType().getIndex(name);
388
        if (index < 0) {
389
            return defaultValue;
390
        }
391
        try {
392
            return this.getBoolean(index);
393
        } catch (Throwable th) {
394
            return defaultValue;
395
        }
396
    }
397

    
398
    @Override
399
    public int getIntOrDefault(String name, int defaultValue) {
400
        int index = this.data.getType().getIndex(name);
401
        if (index < 0) {
402
            return defaultValue;
403
        }
404
        try {
405
            return this.getInt(index);
406
        } catch (Throwable th) {
407
            return defaultValue;
408
        }
409
    }
410

    
411
    @Override
412
    public long getLongOrDefault(String name, long defaultValue) {
413
        int index = this.data.getType().getIndex(name);
414
        if (index < 0) {
415
            return defaultValue;
416
        }
417
        try {
418
            return this.getLong(index);
419
        } catch (Throwable th) {
420
            return defaultValue;
421
        }
422
    }
423

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

    
437
    @Override
438
    public double getDoubleOrDefault(String name, double defaultValue) {
439
        int index = this.data.getType().getIndex(name);
440
        if (index < 0) {
441
            return defaultValue;
442
        }
443
        try {
444
            return this.getDouble(index);
445
        } catch (Throwable th) {
446
            return defaultValue;
447
        }
448
    }
449

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

    
463
    @Override
464
    public Date getDateOrDefault(String name, Date defaultValue) {
465
        int index = this.data.getType().getIndex(name);
466
        if (index < 0) {
467
            return defaultValue;
468
        }
469
        try {
470
            return this.getDate(index);
471
        } catch (Throwable th) {
472
            return defaultValue;
473
        }
474
    }
475

    
476
    @Override
477
    public Object getOrDefault(int index, Object defaultValue) {
478
        if (index < 0 || index >= this.data.getType().size()) {
479
            return defaultValue;
480
        }
481
        try {
482
            return this.get(index);
483
        } catch (Throwable th) {
484
            return defaultValue;
485
        }
486
    }
487

    
488
    @Override
489
    public String getStringOrDefault(int index, String defaultValue) {
490
        if (index < 0 || index >= this.data.getType().size()) {
491
            return defaultValue;
492
        }
493
        try {
494
            return this.getString(index);
495
        } catch (Throwable th) {
496
            return defaultValue;
497
        }
498
    }
499

    
500
    @Override
501
    public boolean getBooleanOrDefault(int index, boolean defaultValue) {
502
        if (index < 0 || index >= this.data.getType().size()) {
503
            return defaultValue;
504
        }
505
        try {
506
            return this.getBoolean(index);
507
        } catch (Throwable th) {
508
            return defaultValue;
509
        }
510
    }
511

    
512
    @Override
513
    public int getIntOrDefault(int index, int defaultValue) {
514
        if (index < 0 || index >= this.data.getType().size()) {
515
            return defaultValue;
516
        }
517
        try {
518
            return this.getInt(index);
519
        } catch (Throwable th) {
520
            return defaultValue;
521
        }
522
    }
523

    
524
    @Override
525
    public long getLongOrDefault(int index, long defaultValue) {
526
        if (index < 0 || index >= this.data.getType().size()) {
527
            return defaultValue;
528
        }
529
        try {
530
            return this.getLong(index);
531
        } catch (Throwable th) {
532
            return defaultValue;
533
        }
534
    }
535

    
536
    @Override
537
    public float getFloatOrDefault(int index, float defaultValue) {
538
        if (index < 0 || index >= this.data.getType().size()) {
539
            return defaultValue;
540
        }
541
        try {
542
            return this.getFloat(index);
543
        } catch (Throwable th) {
544
            return defaultValue;
545
        }
546
    }
547

    
548
    @Override
549
    public double getDoubleOrDefault(int index, double defaultValue) {
550
        if (index < 0 || index >= this.data.getType().size()) {
551
            return defaultValue;
552
        }
553
        try {
554
            return this.getDouble(index);
555
        } catch (Throwable th) {
556
            return defaultValue;
557
        }
558
    }
559

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

    
572
    @Override
573
    public Date getDateOrDefault(int index, Date defaultValue) {
574
        if (index < 0 || index >= this.data.getType().size()) {
575
            return defaultValue;
576
        }
577
        try {
578
            return this.getDate(index);
579
        } catch (Throwable th) {
580
            return defaultValue;
581
        }
582
    }
583

    
584
    class UnableToGetReferenceException extends BaseRuntimeException {
585

    
586
        /**
587
         *
588
         */
589
        private static final long serialVersionUID = 1812805035204824163L;
590

    
591
        /**
592
         * @param exception
593
         */
594
        @SuppressWarnings("OverridableMethodCallInConstructor")
595
        public UnableToGetReferenceException(BaseException exception) {
596
            super("Unable to get reference", "_UnableToGetReferenceException",
597
                    serialVersionUID);
598
            this.initCause(exception);
599

    
600
        }
601

    
602
    }
603

    
604
    @Override
605
    public void validate(int mode) throws DataException {
606
        ((DefaultFeatureType) this.data.getType()).validateFeature(this, mode);
607
    }
608

    
609
    @Override
610
    public List getSRSs() {
611
        // TODO Auto-generated method stub
612
        return null;
613
    }
614

    
615
    @Override
616
    public Envelope getDefaultEnvelope() {
617
        Envelope envelope = this.data.getDefaultEnvelope();
618
        if (envelope == null) {
619
            int i = this.data.getType().getDefaultGeometryAttributeIndex();
620
            if (i < 0) {
621
                return null;
622
            }
623
            Geometry geom = this.getDefaultGeometry();
624
            if (geom != null) {
625
                envelope = geom.getEnvelope();
626
            }
627
        }
628
        return envelope;
629
    }
630

    
631
    @Override
632
    public Geometry getDefaultGeometry() {
633
        Geometry geom = this.data.getDefaultGeometry();
634
        if (geom == null) {
635
            int i = this.data.getType().getDefaultGeometryAttributeIndex();
636
            if (i < 0) {
637
                return null;
638
            }
639
            Object x = this.get(i);
640
            if (x instanceof Geometry) {
641
                geom = (Geometry) x;
642
            } else {
643
                geom = this.getGeometry(i);
644
            }
645
        }
646
        if (geom != null) {
647
            if (geom.getProjection() == null) {
648
                FeatureType type = this.getType();
649
                DefaultFeatureAttributeDescriptor attrdesc = (DefaultFeatureAttributeDescriptor) type.get(type.getDefaultGeometryAttributeIndex());
650
                IProjection proj = attrdesc.getSRS(this.storeRef);
651
                geom.setProjection(proj);
652
            }
653
        }
654
        return geom;
655
    }
656

    
657
//    @Override
658
//    public Time getDefaultTime() {
659
//            Time time = this.data.getDefaultTime();
660
//        if( time == null ) {
661
//            int i = this.data.getType().getDefaultTimeAttributeIndex();
662
//            Object x = this.get(i);
663
//            if( x instanceof Time ) {
664
//                time = (Time) x;
665
//            } else {
666
//                time = this.getTime(i);
667
//            }
668
//        }
669
//        return time;
670
//    }
671
//
672
    @Override
673
    public IProjection getDefaultSRS() {
674
        IProjection srs = this.data.getType().getDefaultSRS();
675
        if (srs == null) {
676
            FeatureType type = this.getType();
677
            DefaultFeatureAttributeDescriptor attrdesc = (DefaultFeatureAttributeDescriptor) type.get(type.getDefaultGeometryAttributeIndex());
678
            srs = attrdesc.getSRS(this.storeRef);
679
        }
680
        return srs;
681
    }
682

    
683
    @Override
684
    public List getGeometries() {
685
        // TODO Auto-generated method stub
686
        return null;
687
    }
688

    
689
    @Override
690
    public Object getFromProfile(int index) {
691
        FeatureAttributeDescriptor descriptor = this.data.getType().getAttributeDescriptor(index);
692
        Object value = this.get(index);
693
        String profileName = descriptor.getDataProfileName();
694
        if (StringUtils.isBlank(profileName)) {
695
            return value;
696
        }
697
        DataProfile profile = DALLocator.getDataManager().getDataProfile(profileName);
698
        if (profile == null) {
699
            return value;
700
        }
701
        return profile.createData(value, descriptor.getTags());
702
    }
703

    
704
    @Override
705
    public Object getFromProfile(String name) {
706
        FeatureAttributeDescriptor descriptor = this.data.getType().getAttributeDescriptor(name);
707
        return this.getFromProfile(descriptor.getIndex());
708
    }
709

    
710
    @Override
711
    public Object get(String name) {
712
        int index = this.data.getType().getIndex(name);
713
        if (index < 0) {
714
            // buscamos en los extra cols
715
            if (hasExtraColumnValue(name)) {
716
                return getExtraColumnValue(name);
717
            }
718
            if (hasExtraValue(name)) {
719
                return getExtraValue(name);
720
            }
721
            // y si esta ahi return
722
            throw new IllegalArgumentException("Attribute name '" + name + "' not found in the feature.");
723
        }
724
        return this.get(index);
725
    }
726

    
727
    @Override
728
    public boolean isNull(int index) {
729
        FeatureType type = this.data.getType();
730
        if (index < 0 || index >= type.size()) {
731
            throw new IllegalArgumentException("Attribute index '" + index + "' out of range (0 to " + this.data.getType().size() + ".");
732
        }
733
        FeatureAttributeDescriptor attribute = type.getAttributeDescriptor(index);
734
        if (!this.data.getType().hasEvaluators()) {
735
            return this.data.get(index) == null;
736
        }
737
        Evaluator eval = attribute.getEvaluator();
738
        if (eval == null) {
739
            return this.data.get(index) == null;
740
        }
741
        Object value = this.data.get(index);
742
        if (value != null) {
743
            return true;
744
        }
745
        try {
746
            value = eval.evaluate(this);
747
        } catch (EvaluatorException e) {
748
            throw new DataEvaluatorRuntimeException(e);
749
        }
750
        this.data.set(index, value);
751
        return value == null;
752
    }
753

    
754
    @Override
755
    public boolean isNull(String name) {
756
        int index = this.data.getType().getIndex(name);
757
        if (index < 0) {
758
            throw new IllegalArgumentException("Attribute name '" + name + "' not found in the feature.");
759
        }
760
        return this.isNull(index);
761
    }
762

    
763
    public boolean has_key(String key) {
764
        Object x = this.getType().get(key);
765
        return x != null;
766
    }
767

    
768
    public List<String> keys() {
769
        List<String> ks = new ArrayList<>();
770
        for (FeatureAttributeDescriptor attr : this.getType()) {
771
            ks.add(attr.getName());
772
        }
773
        return ks;
774
    }
775

    
776
    public Iterator<String> iterkeys() {
777
        final Iterator it = this.getType().iterator();
778
        return new Iterator<String>() {
779
            @Override
780
            public boolean hasNext() {
781
                return it.hasNext();
782
            }
783

    
784
            @Override
785
            public String next() {
786
                return ((FeatureAttributeDescriptor) it.next()).getName();
787
            }
788

    
789
            @Override
790
            public void remove() {
791
                throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
792
            }
793
        };
794
    }
795

    
796
    public Iterator iteritems() {
797
        final Iterator it = this.getType().iterator();
798
        return new Iterator<Map.Entry>() {
799
            @Override
800
            public boolean hasNext() {
801
                return it.hasNext();
802
            }
803

    
804
            @Override
805
            public Map.Entry next() {
806
                final String name = ((FeatureAttributeDescriptor) it.next()).getName();
807
                return new Map.Entry<String, Object>() {
808
                    @Override
809
                    public String getKey() {
810
                        return name;
811
                    }
812

    
813
                    @Override
814
                    public Object getValue() {
815
                        return get(name);
816
                    }
817

    
818
                    @Override
819
                    public Object setValue(Object value) {
820
                        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
821
                    }
822

    
823
                };
824
            }
825

    
826
            @Override
827
            public void remove() {
828
                throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
829
            }
830
        };
831
    }
832

    
833
    @Override
834
    public Object get(int index) {
835
        FeatureType type = this.data.getType();
836
        if (index < 0 || index >= type.size()) {
837
            throw new IllegalArgumentException("Attribute index '" + index + "' out of range (0 to " + this.data.getType().size() + ".");
838
        }
839
        Object value = this.data.get(index);
840
        FeatureAttributeDescriptor attribute = type.getAttributeDescriptor(index);
841
        if (type.hasEvaluators()) {
842
            Evaluator eval = attribute.getEvaluator();
843
            if (eval != null) {
844
                if (value == null) { // Ya hemos calculado el campo ?
845
                    // FIXME: para comprobar si esta calculado usar un array especifico.
846
                    try {
847
                        value = eval.evaluate(this);
848
                    } catch (EvaluatorException e) {
849
                        throw new DataEvaluatorRuntimeException(e);
850
                    }
851
                    this.data.set(index, value);
852
                }
853
            }
854
        }
855
        value = get(attribute, value);
856
        return value;
857
    }
858

    
859
    private Object get(FeatureAttributeDescriptor featureAttributeDescriptor, Object value) {
860
        FeatureAttributeEmulator emulator = featureAttributeDescriptor.getFeatureAttributeEmulator();
861
        if (emulator != null) {
862
//            int index = featureAttributeDescriptor.getIndex();
863
//            value = this.data.get(index);
864
//            if( value==null ) {
865
            value = emulator.get(this);
866
//                this.data.set(index,value);
867
//            }
868
        } else {
869
            FeatureAttributeGetter getter = featureAttributeDescriptor.getFeatureAttributeGetter();
870
            if (getter != null) {
871
                value = getter.getter(value);
872
            }
873
        }
874
        DataType dataType = featureAttributeDescriptor.getDataType();
875
        Class<? extends DataType> theClass = dataType.getDefaultClass();
876
        if (theClass != null && !theClass.isInstance(value)) {
877
            try {
878
                value = this.getDataTypesManager().coerce(dataType.getType(), value);
879
            } catch (CoercionException e) {
880
                throw new IllegalArgumentException(
881
                        "Can't convert to " + theClass.getSimpleName()
882
                        + " from '" + value.getClass().getSimpleName()
883
                        + "' with value '" + value.toString() + "'.");
884
            }
885
        }
886
        if (featureAttributeDescriptor.getType() == DataTypes.GEOMETRY) {
887
            if (value != null) {
888
                Geometry geom = (Geometry) value;
889
                if (geom.getProjection() == null) {
890
                    IProjection proj = ((DefaultFeatureAttributeDescriptor) featureAttributeDescriptor).getSRS(this.storeRef);
891
                    geom.setProjection(proj);
892
                }
893
            }
894
        }
895
        return value;
896
    }
897

    
898
    @Override
899
    public byte[] getByteArray(String name) {
900
        return this.getByteArray(this.data.getType().getIndex(name));
901
    }
902

    
903
    @Override
904
    public byte[] getByteArray(int index) {
905
        return (byte[]) this.get(index);
906
    }
907

    
908
    @Override
909
    public Object[] getArray(String name) {
910
        return this.getArray(this.data.getType().getIndex(name));
911
    }
912

    
913
    @Override
914
    public Object[] getArray(int index) {
915
        return (Object[]) this.get(index);
916
    }
917

    
918
    @Override
919
    public boolean getBoolean(String name) {
920
        return this.getBoolean(this.data.getType().getIndex(name));
921
    }
922

    
923
    @Override
924
    public boolean getBoolean(int index) {
925
        Boolean value = ((Boolean) this.get(index, Boolean.class, DataTypes.BOOLEAN));
926
        if (value == null) {
927
            return false;
928
        }
929
        return value;
930
    }
931

    
932
    @Override
933
    public byte getByte(String name) {
934
        return this.getByte(this.data.getType().getIndex(name));
935
    }
936

    
937
    @Override
938
    public byte getByte(int index) {
939
        Byte value = ((Byte) this.get(index, Byte.class, DataTypes.BYTE));
940
        if (value == null) {
941
            return 0;
942
        }
943
        return value;
944
    }
945

    
946
    @Override
947
    public java.sql.Date getDate(String name) {
948
        return this.getDate(this.data.getType().getIndex(name));
949
    }
950

    
951
    @Override
952
    public java.sql.Date getDate(int index) {
953
        java.sql.Date value = ((java.sql.Date) this.get(index, java.sql.Date.class, DataTypes.DATE));
954
        return value;
955
    }
956

    
957
    @Override
958
    public java.sql.Time getTime(String name) {
959
        return this.getTime(this.data.getType().getIndex(name));
960
    }
961

    
962
    @Override
963
    public java.sql.Time getTime(int index) {
964
        java.sql.Time value = ((java.sql.Time) this.get(index, java.sql.Time.class, DataTypes.TIME));
965
        return value;
966
    }
967

    
968
    @Override
969
    public java.sql.Timestamp getTimestamp(String name) {
970
        return this.getTimestamp(this.data.getType().getIndex(name));
971
    }
972

    
973
    @Override
974
    public java.sql.Timestamp getTimestamp(int index) {
975
        java.sql.Timestamp value = ((java.sql.Timestamp) this.get(index, java.sql.Timestamp.class, DataTypes.TIMESTAMP));
976
        return value;
977
    }
978

    
979
    @Override
980
    public double getDouble(String name) {
981
        return this.getDouble(this.data.getType().getIndex(name));
982
    }
983

    
984
    @Override
985
    public double getDouble(int index) {
986

    
987
        Double value = ((Double) this.get(index, Double.class, DataTypes.DOUBLE));
988
        if (value == null) {
989
            return 0;
990
        }
991
        return value;
992
    }
993

    
994
    @Override
995
    public BigDecimal getDecimal(String name) {
996
        return this.getDecimal(this.data.getType().getIndex(name));
997
    }
998

    
999
    @Override
1000
    public BigDecimal getDecimal(int index) {
1001
        BigDecimal value = ((BigDecimal) this.get(index, BigDecimal.class, DataTypes.DECIMAL));
1002
        return value;
1003
    }
1004

    
1005
    @Override
1006
    public Feature getFeature(String name) {
1007
        return this.getFeature(this.data.getType().getIndex(name));
1008
    }
1009

    
1010
    @Override
1011
    public Feature getFeature(int index) {
1012
        return (Feature) this.get(index);
1013
    }
1014

    
1015
    @Override
1016
    public float getFloat(String name) {
1017
        return this.getFloat(this.data.getType().getIndex(name));
1018
    }
1019

    
1020
    @Override
1021
    public float getFloat(int index) {
1022
        Float value = ((Float) this.get(index, Float.class, DataTypes.FLOAT));
1023
        if (value == null) {
1024
            return 0;
1025
        }
1026
        return value;
1027
    }
1028

    
1029
    @Override
1030
    public Geometry getGeometry(String name) {
1031
        return this.getGeometry(this.data.getType().getIndex(name));
1032
    }
1033

    
1034
    @Override
1035
    public Geometry getGeometry(int index) {
1036
        return (Geometry) this.get(index, Geometry.class, DataTypes.GEOMETRY);
1037
    }
1038

    
1039
    @Override
1040
    public int getInt(String name) {
1041
        return this.getInt(this.data.getType().getIndex(name));
1042
    }
1043

    
1044
    @Override
1045
    public int getInt(int index) {
1046
        Integer value = ((Integer) this.get(index, Integer.class, DataTypes.INT));
1047
        if (value == null) {
1048
            return 0;
1049
        }
1050
        return value;
1051
    }
1052

    
1053
    @Override
1054
    public long getLong(String name) {
1055
        return this.getLong(this.data.getType().getIndex(name));
1056
    }
1057

    
1058
    @Override
1059
    public long getLong(int index) {
1060
        Long value = ((Long) this.get(index, Long.class, DataTypes.LONG));
1061
        if (value == null) {
1062
            return 0;
1063
        }
1064
        return value;
1065
    }
1066

    
1067
    @Override
1068
    public String getString(String name) {
1069
        return this.getString(this.data.getType().getIndex(name));
1070
    }
1071

    
1072
    @Override
1073
    public String getString(int index) {
1074
        return (String) this.get(index, String.class, DataTypes.STRING);
1075
    }
1076

    
1077
    @Override
1078
    public Object getContextValue(String name) {
1079
        name = name.toLowerCase();
1080
        if (name.equals("store")) {
1081
            return this.getStore();
1082
        }
1083

    
1084
        if (name.equals("featuretype")) {
1085
            return this.data.getType();
1086
        }
1087

    
1088
        if (name.equals("feature")) {
1089
            return this;
1090
        }
1091

    
1092
        throw new IllegalArgumentException(name);
1093
    }
1094

    
1095
    @Override
1096
    public Iterator getDataNames() {
1097
        class DataNamesIterator implements Iterator {
1098

    
1099
            Iterator attributeIteraror;
1100

    
1101
            DataNamesIterator(DefaultFeature feature) {
1102
                this.attributeIteraror = feature.getType().iterator();
1103
            }
1104

    
1105
            @Override
1106
            public boolean hasNext() {
1107
                return this.attributeIteraror.hasNext();
1108
            }
1109

    
1110
            @Override
1111
            public Object next() {
1112
                return ((FeatureAttributeDescriptor) this.attributeIteraror
1113
                        .next()).getName();
1114
            }
1115

    
1116
            @Override
1117
            public void remove() {
1118
                throw new UnsupportedOperationException();
1119
            }
1120

    
1121
        }
1122
        return new DataNamesIterator(this);
1123
    }
1124

    
1125
    @Override
1126
    public Object getDataValue(String name) {
1127
        name = name.toLowerCase();
1128
        try {
1129
            return get(name);
1130
        } catch (IllegalArgumentException ex) {
1131
            if ("defaultgeometry".equalsIgnoreCase(name)) {
1132
                return this.getDefaultGeometry();
1133
            }
1134
            throw ex;
1135
        }
1136
    }
1137

    
1138
    @Override
1139
    public Iterator getDataValues() {
1140
        class DataValuesIterator implements Iterator {
1141

    
1142
            DefaultFeature feature;
1143
            int current = 0;
1144

    
1145
            DataValuesIterator(DefaultFeature feature) {
1146
                this.feature = feature;
1147
            }
1148

    
1149
            @Override
1150
            public boolean hasNext() {
1151
                return current < feature.getType().size() - 1;
1152
            }
1153

    
1154
            @Override
1155
            public Object next() {
1156
                return feature.get(current++);
1157
            }
1158

    
1159
            @Override
1160
            public void remove() {
1161
                throw new UnsupportedOperationException();
1162
            }
1163

    
1164
        }
1165
        return new DataValuesIterator(this);
1166
    }
1167

    
1168
    @Override
1169
    public boolean hasContextValue(String name) {
1170
        name = name.toLowerCase();
1171
        if (name.equals("store")) {
1172
            return true;
1173
        }
1174

    
1175
        if (name.equals("featuretype")) {
1176
            return true;
1177
        }
1178

    
1179
        return name.equals("feature");
1180
    }
1181

    
1182
    @Override
1183
    public boolean hasDataValue(String name) {
1184
        return this.hasValue(name);
1185
    }
1186

    
1187
//    @Override
1188
//    public Time getTime(int index) {
1189
//        return ((Time) this.get(index,Time.class,DataTypes.INSTANT));
1190
//    }
1191
//
1192
//    @Override
1193
//    public Time getTime(String name) {
1194
//        return this.getInstant(this.data.getType().getIndex(name));
1195
//    }
1196
//
1197
//    @Override
1198
//    public Instant getInstant(int index) {
1199
//        return ((Instant) this.get(index,Instant.class,DataTypes.INSTANT));
1200
//    }
1201
//
1202
//    @Override
1203
//    public Instant getInstant(String name) {
1204
//        return this.getInstant(this.data.getType().getIndex(name));
1205
//    }
1206
//
1207
//    @Override
1208
//    public Interval getInterval(int index) {
1209
//        return ((Interval) this.get(index,Interval.class,DataTypes.INTERVAL));
1210
//    }
1211
//
1212
//    @Override
1213
//    public Interval getInterval(String name) {
1214
//        return this.getInterval(this.data.getType().getIndex(name));
1215
//    }
1216
//
1217
    @Override
1218
    public DynObject getAsDynObject() {
1219
        DynObjectFeatureFacade facade = new DynObjectFeatureFacade(this);
1220
        return facade;
1221
    }
1222

    
1223
    @Override
1224
    public String toString() {
1225
        StringBuilder builder = new StringBuilder();
1226
        FeatureAttributeDescriptor[] attributeDescriptors
1227
                = getType().getAttributeDescriptors();
1228
        for (int i = 0; i < attributeDescriptors.length; i++) {
1229
            String name = attributeDescriptors[i].getName();
1230
            Object value = get(name);
1231
            builder.append(value);
1232
            if (i < attributeDescriptors.length - 1) {
1233
                builder.append(", ");
1234
            }
1235
        }
1236
        return builder.toString();
1237
    }
1238

    
1239
    /**
1240
     * @return the inserted
1241
     */
1242
    public boolean isInserted() {
1243
        return inserted;
1244
    }
1245

    
1246
    /**
1247
     * @param inserted the inserted to set
1248
     */
1249
    public void setInserted(boolean inserted) {
1250
        this.inserted = inserted;
1251
//        this.data.setNew(!inserted);
1252
    }
1253

    
1254
    @Override
1255
    public EvaluatorData getEvaluatorData() {
1256
        return this;
1257
    }
1258

    
1259
    @Override
1260
    public int size() {
1261
        return this.data.getType().size();
1262
    }
1263

    
1264
    public boolean isEmpty() {
1265
        return false;
1266
    }
1267

    
1268
    public Iterator<String> iterator() {
1269
        final Iterator<FeatureAttributeDescriptor> x = this.data.getType().iterator();
1270
        return new Iterator<String>() {
1271
            @Override
1272
            public boolean hasNext() {
1273
                return x.hasNext();
1274
            }
1275

    
1276
            @Override
1277
            public String next() {
1278
                return x.next().getName();
1279
            }
1280
        };
1281
    }
1282

    
1283
    public boolean containsKey(String key) {
1284
        return this.data.getType().get(key) != null;
1285
    }
1286

    
1287
    @Override
1288
    public String getLabelOfValue(String name) {
1289
        FeatureAttributeDescriptor attrdesc = this.data.getType().getAttributeDescriptor(name);
1290
        if (attrdesc == null) {
1291
            throw new IllegalArgumentException("Attribute name '" + name + "' not found in the feature.");
1292
        }
1293
        Object value = this.get(attrdesc.getIndex());
1294
        String label = attrdesc.getLabelOfValue(value);
1295
        return label;
1296
    }
1297

    
1298
    @Override
1299
    public void setExtraValue(String name, Object value) {
1300
        if (this.extraValues == null) {
1301
            this.extraValues = new HashMap<>();
1302
        }
1303
        this.extraValues.put(name, value);
1304
    }
1305

    
1306
    public Object getExtraColumnValue(String name) {
1307
        Object value;
1308
        if (this.extraValues != null) {
1309
            if (this.extraValues.containsKey(name)) {
1310
                return this.extraValues.get(name);
1311
            }
1312
        }
1313
        FeatureExtraColumns columns = this.getType().getExtraColumns();
1314
        int index = columns.getIndexOf(name);
1315
        if (index < 0) {
1316
            throw new RuntimeException("Not extra column value found");
1317
        }
1318
        if (extraValuesData == null) {
1319
            extraValuesData = new Object[columns.size()];
1320
        }
1321
        EditableFeatureAttributeDescriptor attrdesc = columns.get(index);
1322
        value = extraValuesData[index];
1323
        if (value != null) {
1324
            return value;
1325
        }
1326
        value = this.getExtraValue(name);
1327
        extraValuesData[index] = value;
1328
        if (value == null && !this.hasExtraValue(name)) {
1329
            if (attrdesc.getFeatureAttributeEmulator() != null) {
1330
                value = attrdesc.getFeatureAttributeEmulator().get(this);
1331
                extraValuesData[index] = value;
1332
            }
1333
        }
1334
        return value;
1335
    }
1336

    
1337
    @Override
1338
    public Object getExtraValue(String name) {
1339
        Object value = this.data.getExtraValue(name);
1340
        return value;
1341
    }
1342

    
1343
    @Override
1344
    public boolean hasExtraValue(String name) {
1345
        return this.data.hasExtraValue(name);
1346
    }
1347

    
1348
    private boolean hasExtraColumnValue(String name) {
1349
        if (this.extraValues != null) {
1350
            if (this.extraValues.containsKey(name)) {
1351
                return true;
1352
            }
1353
        }
1354
        FeatureExtraColumns columns = this.getType().getExtraColumns();
1355
        int index = columns.getIndexOf(name);
1356
        if (index >= 0) {
1357
            return true;
1358
        }
1359
        return false;
1360
    }
1361

    
1362
    @Override
1363
    public boolean hasValue(String name) {
1364
        name = name.toLowerCase();
1365
        return this.data.getType().getIndex(name) >= 0
1366
                || hasExtraValue(name)
1367
                || hasExtraColumnValue(name);
1368
    }
1369

    
1370
    @Override
1371
    public Object getExtraValue(int index) {
1372
        return this.data.getExtraValue(index);
1373
    }
1374

    
1375
    @Override
1376
    public JsonObject toJson() {
1377
        JsonObjectBuilder builder = this.toJsonBuilder();
1378
        return builder.build();
1379
    }
1380

    
1381
    @Override
1382
    public JsonObjectBuilder toJsonBuilder() {
1383
        JsonObjectBuilder builder = Json.createObjectBuilder();
1384
        Date date;
1385
        Geometry geom;
1386
        FeatureType ft = this.getType();
1387
        for (FeatureAttributeDescriptor desc : ft) {
1388
            if (desc.isComputed()) {
1389
                continue;
1390
            }
1391
            switch (desc.getType()) {
1392
                case DataTypes.GEOMETRY:
1393
                    geom = this.getGeometry(desc.getIndex());
1394
                    if (geom != null) {
1395
                        builder.add(desc.getName(), geom.convertToHexWKBQuietly());
1396
                    }
1397
                    break;
1398
                case DataTypes.BOOLEAN:
1399
                    builder.add(desc.getName(), this.getBoolean(desc.getIndex()));
1400
                    break;
1401
                case DataTypes.BYTE:
1402
                    builder.add(desc.getName(), this.getByte(desc.getIndex()));
1403
                    break;
1404
                case DataTypes.INT:
1405
                    builder.add(desc.getName(), this.getInt(desc.getIndex()));
1406
                    break;
1407
                case DataTypes.LONG:
1408
                    builder.add(desc.getName(), this.getLong(desc.getIndex()));
1409
                    break;
1410
                case DataTypes.DOUBLE:
1411
                    builder.add(desc.getName(), this.getDouble(desc.getIndex()));
1412
                    break;
1413
                case DataTypes.FLOAT:
1414
                    builder.add(desc.getName(), this.getFloat(desc.getIndex()));
1415
                    break;
1416
                case DataTypes.DATE:
1417
                    // Format date as ISO 8601
1418
                    date = this.getDate(desc.getIndex());
1419
                    if (date == null) {
1420
                        builder.addNull(desc.getName());
1421
                    } else {
1422
                        LocalDateTime localDateTime = LocalDateTime.ofInstant(new Date(date.getTime()).toInstant(), ZoneId.systemDefault());
1423
                        String value = DateTimeFormatter.ISO_DATE.format(localDateTime);
1424
                        builder.add(desc.getName(), value);
1425
                    }
1426
                    break;
1427
                case DataTypes.TIMESTAMP:
1428
                    // Format date as ISO 8601
1429
                    date = this.getTimestamp(desc.getIndex());
1430
                    if (date == null) {
1431
                        builder.addNull(desc.getName());
1432
                    } else {
1433
                        LocalDateTime localDateTime = LocalDateTime.ofInstant(new Date(date.getTime()).toInstant(), ZoneId.systemDefault());
1434
                        String value = DateTimeFormatter.ISO_DATE_TIME.format(localDateTime);
1435
                        builder.add(desc.getName(), value);
1436
                    }
1437
                    break;
1438
                case DataTypes.TIME:
1439
                    // Format date as ISO 8601
1440
                    date = this.getTime(desc.getIndex());
1441
                    if (date == null) {
1442
                        builder.addNull(desc.getName());
1443
                    } else {
1444
                        LocalDateTime localDateTime = LocalDateTime.ofInstant(new Date(date.getTime()).toInstant(), ZoneId.systemDefault());
1445
                        String value = DateTimeFormatter.ISO_TIME.format(localDateTime);
1446
                        builder.add(desc.getName(), value);
1447
                    }
1448
                    break;
1449
                default:
1450
                    builder.add(desc.getName(), this.getStringOrDefault(desc.getIndex(), ""));
1451
            }
1452
        }
1453
        return builder;
1454
    }
1455

    
1456
    @Override
1457
    public List<String> getKeys() {
1458
        List<String> l = new ArrayList<>();
1459
        for (FeatureAttributeDescriptor descriptor : this.getType()) {
1460
            l.add(descriptor.getName());
1461
        }
1462
        return l;
1463
    }
1464

    
1465
}