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

History | View | Annotate | Download (41.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.format.DateTimeFormatter;
29
import java.util.ArrayList;
30
import java.util.Date;
31
import java.util.HashMap;
32
import java.util.Iterator;
33
import java.util.List;
34
import java.util.Map;
35
import java.util.Objects;
36
import javax.json.Json;
37
import javax.json.JsonObject;
38
import javax.json.JsonObjectBuilder;
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.FeatureReference;
55
import org.gvsig.fmap.dal.feature.FeatureStore;
56
import org.gvsig.fmap.dal.feature.FeatureType;
57
import org.gvsig.fmap.dal.feature.exception.IllegalValueException;
58
import org.gvsig.fmap.dal.feature.exception.SetReadOnlyAttributeException;
59
import org.gvsig.fmap.dal.feature.impl.dynobjectutils.DynObjectFeatureFacade;
60
import org.gvsig.fmap.dal.feature.spi.DefaultFeatureProvider;
61
import org.gvsig.fmap.dal.feature.spi.FeatureProvider;
62
import org.gvsig.fmap.geom.Geometry;
63
import org.gvsig.fmap.geom.primitive.Envelope;
64
import org.gvsig.tools.ToolsLocator;
65
import org.gvsig.tools.dataTypes.Coercion;
66
import org.gvsig.tools.dataTypes.CoercionException;
67
import org.gvsig.tools.dataTypes.DataTypesManager;
68
import org.gvsig.tools.dynobject.DynObject;
69
import org.gvsig.tools.evaluator.Evaluator;
70
import org.gvsig.tools.evaluator.EvaluatorData;
71
import org.gvsig.tools.evaluator.EvaluatorException;
72
import org.gvsig.tools.exception.BaseException;
73
import org.gvsig.tools.exception.BaseRuntimeException;
74
import org.gvsig.tools.lang.Cloneable;
75
import org.gvsig.fmap.dal.feature.FeatureExtraColumns;
76
import org.gvsig.tools.dataTypes.DataType;
77

    
78
@SuppressWarnings("UseSpecificCatch")
79
public class DefaultFeature implements Feature, EvaluatorData, Cloneable {
80

    
81
        private static DataTypesManager dataTypesManager = null;
82
        protected FeatureProvider data;
83
        protected FeatureReference reference;
84
        private WeakReference storeRef;
85

    
86
        private boolean inserted = false;
87
  private Object[] extraValuesData;
88
  private Map<String,Object> extraValues; // not persistent
89

    
90
    /*
91
         * Usar con mucha precaucion o mejor no usar. Lo precisa el
92
         * DefaultFeatureSet en la ordenacion.
93
         */
94
        public DefaultFeature(FeatureStore store) {
95
                this.storeRef = new WeakReference(store);
96
                this.reference = null;
97
        }
98

    
99
        public DefaultFeature(FeatureStore store, FeatureProvider data) {
100
                this.data = data;
101
                this.extraValuesData = null;
102
                this.storeRef = new WeakReference(store);
103
                this.reference = null;
104
                this.inserted = !data.isNew();
105
        }
106

    
107
        DefaultFeature(DefaultFeature feature) {
108
                this.data = feature.data.getCopy();
109
                this.extraValuesData = ArrayUtils.clone(feature.extraValuesData);
110
                this.storeRef = feature.storeRef;
111
                this.reference = feature.reference;
112
                this.inserted = feature.isInserted();
113
        }
114

    
115
    public DefaultFeature(FeatureType targetType, Feature sourceFeature) {
116
        DefaultFeature defaultFeature = (DefaultFeature)sourceFeature;
117
        this.data = new DefaultFeatureProvider(targetType, (DefaultFeatureProvider)defaultFeature.getData());
118
        this.extraValuesData = null;
119
        this.storeRef = defaultFeature.storeRef;
120
        this.reference = defaultFeature.reference;
121
        this.inserted = defaultFeature.isInserted();
122

    
123
        FeatureType sourceType = sourceFeature.getType();
124

    
125
        for (FeatureAttributeDescriptor targetAttrDescriptor : targetType) {
126
            if ( targetAttrDescriptor.isComputed() ) {
127
                 continue;
128
            }
129
            int sourceIndex = sourceType.getIndex(targetAttrDescriptor.getName());
130
            if (sourceIndex<0){
131
                continue;
132
            }
133
            Object value = sourceFeature.get(sourceIndex);
134
            if (value == null && !targetAttrDescriptor.allowNull()) {
135
                continue;
136
            }
137
            this.setforced(targetAttrDescriptor.getIndex(), targetAttrDescriptor,value);
138
        }
139
    }
140

    
141
        public void setData(FeatureProvider data) {
142
                this.data = data;
143
                this.extraValuesData = null;
144
                this.reference = null;
145
                this.inserted = true;
146
        }
147

    
148
        public FeatureProvider getData() {
149
                return this.data;
150
        }
151

    
152
        protected DataTypesManager getDataTypesManager() {
153
                if( dataTypesManager==null ) {
154
                        dataTypesManager = ToolsLocator.getDataTypesManager();
155
                }
156
                return dataTypesManager;
157
        }
158

    
159
    protected void set(FeatureAttributeDescriptor attribute, Object value) {
160
        int i = attribute.getIndex();
161

    
162
        if ( attribute.isReadOnly() ) {
163
            throw new SetReadOnlyAttributeException(attribute.getName(), this.getType());
164
        }
165
        FeatureAttributeEmulator emulator = attribute.getFeatureAttributeEmulator();
166
        if( emulator!= null ) {
167
            emulator.set((EditableFeature) this,value);
168
            return;
169
        }
170

    
171
        if ( value == null ) {
172
            if ( !attribute.allowNull() ) {
173
                if ( !attribute.isAutomatic() ) {
174
                    throw new IllegalValueException(attribute, value);
175
                }
176
            }
177
            this.data.set(i, null);
178
            return;
179

    
180
        }
181

    
182
        if ( attribute.getFeatureAttributeGetter() != null ) {
183
            value = attribute.getFeatureAttributeGetter().setter(value);
184
        }
185
        this.setforced(i, attribute, value);
186
    }
187

    
188
    private void setforced(int i, FeatureAttributeDescriptor attribute, Object value) {
189

    
190
        Class objectClass = attribute.getObjectClass();
191
        if( objectClass!=null ) {
192
            if ( objectClass.isInstance(value) ) {
193
                if( attribute.getType()==DataTypes.DECIMAL ) {
194
                  BigDecimal d =  (BigDecimal) value;
195
                  if( d.scale()==attribute.getScale() && d.precision()<=attribute.getPrecision() ) {
196
                    this.data.set(i, value);
197
                    return;
198
                  }
199
                } else {
200
                  this.data.set(i, value);
201
                  return;
202
                }
203
            }
204
            DataProfile dataProfile = attribute.getDataProfile();
205
            if( dataProfile!=null ) {
206
                try {
207
                    value = dataProfile.coerce(
208
                            attribute.getDataType(),
209
                            value, 
210
                            attribute.getTags()
211
                    );
212
                } catch (CoercionException e) {
213

    
214
                }
215
            } 
216
            try {
217
                Coercion coercer = attribute.getDataType().getCoercion();
218
                value= coercer.coerce(value, attribute.getCoercionContext());
219
            } catch (CoercionException e) {
220
                throw new IllegalArgumentException("Can't convert to "
221
                        + attribute.getDataType().getName()
222
                        + " from '"
223
                        + value.getClass().getName() 
224
                        + "' with value '"
225
                        + value.toString() 
226
                        + "' and context '"
227
                        + attribute.getCoercionContext()
228
                        + "'.");
229
            }
230
        }
231
        this.data.set(i, value);
232
    }
233

    
234
    private Object get(int index,Class theClass, int type) {
235
        Object value = this.get(index);
236
        if( theClass.isInstance(value) ) {
237
            return value;
238
        }
239
        try {
240
            return this.getDataTypesManager().coerce(type, value);
241
        } catch (CoercionException e) {
242

    
243
            if (value == null) {
244
                return null;
245
            }
246
            throw new IllegalArgumentException(
247
                    "Can't convert to "+theClass.getName()+
248
                    " from '"+value.getClass().getName()+
249
                    "' with value '"+value.toString()+"'.");
250
        }
251
    }
252

    
253
    public void initializeValues() {
254
        FeatureType type = this.getType();
255
        for (FeatureAttributeDescriptor attribute : type) {
256
            if (attribute.isAutomatic() || attribute.isReadOnly()
257
                    || attribute.isComputed() ) {
258
                continue;
259
            }
260
            if (attribute.getDefaultValue() == null && !attribute.allowNull()) {
261
                continue;
262
            }
263
            Object value =  attribute.getDefaultValue();
264
            if( value instanceof CharSequence ) {
265
              String s = ((CharSequence)value).toString();
266
              if( ExpressionUtils.isDynamicText(s) ) {
267
                try {
268
                  value = ExpressionUtils.evaluateDynamicText(s);
269
                } catch(Throwable th) {
270
                  value = null;
271
                }
272
              }
273
            }
274
            this.set(attribute, value);
275
        }
276
    }
277

    
278
    public void clear() {
279
        initializeValues();
280
    }
281

    
282
    public void initializeValues(Feature feature) {
283
        FeatureType myType=this.getType();
284
        FeatureType type =feature.getType();
285
        extraValuesData = null;
286
        for (FeatureAttributeDescriptor attribute : type) {
287
            FeatureAttributeDescriptor myAttribute=myType.getAttributeDescriptor(attribute.getName());
288
            if (myAttribute != null) {
289
                this.set(myAttribute, feature.get(attribute.getIndex()));
290
            }
291
        }
292
    }
293

    
294

    
295
    @Override
296
    public FeatureStore getStore() {
297
        return (FeatureStore) this.storeRef.get();
298
    }
299

    
300
    @Override
301
    public FeatureType getType() {
302
        return this.data.getType();
303
    }
304

    
305
    @Override
306
    public EditableFeature getEditable() {
307
        return new DefaultEditableFeature(this);
308
    }
309

    
310
    @Override
311
    public Feature getCopy() {
312
        return new DefaultFeature(this);
313
    }
314

    
315
    @Override
316
    @SuppressWarnings("CloneDoesntCallSuperClone")
317
    public Object clone() throws CloneNotSupportedException {
318
        return new DefaultFeature(this);
319
    }
320

    
321
    @Override
322
    public FeatureReference getReference() {
323
        if (this.reference == null) {
324
            if (!isInserted()) {
325
                return null;
326
            }
327
            reference = new DefaultFeatureReference(this);
328
        }
329
        return this.reference;
330
    }
331

    
332
    @Override
333
    public Object getOrDefault(String name, Object defaultValue) {
334
        int index = this.data.getType().getIndex(name);
335
        if( index < 0 ) {
336
            return defaultValue;
337
        }
338
        return this.get(index);
339
    }
340

    
341
    @Override
342
    public String getStringOrDefault(String name, String defaultValue) {
343
        int index = this.data.getType().getIndex(name);
344
        if( index < 0 ) {
345
            return defaultValue;
346
        }
347
        try {
348
            return (String) this.get(index);
349
        } catch(Throwable th) {
350
            return defaultValue;
351
        }
352
    }
353

    
354
    @Override
355
    public int getIntOrDefault(String name, int defaultValue) {
356
        int index = this.data.getType().getIndex(name);
357
        if( index < 0 ) {
358
            return defaultValue;
359
        }
360
        try {
361
            return (int) this.get(index);
362
        } catch(Throwable th) {
363
            return defaultValue;
364
        }
365
    }
366

    
367
    @Override
368
    public long getLongOrDefault(String name, long defaultValue) {
369
        int index = this.data.getType().getIndex(name);
370
        if( index < 0 ) {
371
            return defaultValue;
372
        }
373
        try {
374
            return (long) this.get(index);
375
        } catch(Throwable th) {
376
            return defaultValue;
377
        }
378
    }
379

    
380
    @Override
381
    public float getFloatOrDefault(String name, float defaultValue) {
382
        int index = this.data.getType().getIndex(name);
383
        if( index < 0 ) {
384
            return defaultValue;
385
        }
386
        try {
387
            return (float) this.get(index);
388
        } catch(Throwable th) {
389
            return defaultValue;
390
        }
391
    }
392

    
393
    @Override
394
    public double getDoubleOrDefault(String name, double defaultValue) {
395
        int index = this.data.getType().getIndex(name);
396
        if( index < 0 ) {
397
            return defaultValue;
398
        }
399
        try {
400
            return (double) this.get(index);
401
        } catch(Throwable th) {
402
            return defaultValue;
403
        }
404
    }
405

    
406
    @Override
407
    public BigDecimal getDecimalOrDefault(String name, BigDecimal defaultValue) {
408
        int index = this.data.getType().getIndex(name);
409
        if( index < 0 ) {
410
            return defaultValue;
411
        }
412
        try {
413
            return (BigDecimal) this.get(index);
414
        } catch(Throwable th) {
415
            return defaultValue;
416
        }
417
    }
418

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

    
432
    @Override
433
    public Object getOrDefault(int index, Object defaultValue) {
434
        if( index < 0 || index >= this.data.getType().size() ) {
435
            return defaultValue;
436
        }
437
        try {
438
            return this.get(index);
439
        } catch(Throwable th) {
440
            return defaultValue;
441
        }
442
    }
443

    
444
    @Override
445
    public String getStringOrDefault(int index, String defaultValue) {
446
        if( index < 0 || index >= this.data.getType().size() ) {
447
            return defaultValue;
448
        }
449
        try {
450
            return (String) this.get(index);
451
        } catch(Throwable th) {
452
            return defaultValue;
453
        }
454
    }
455

    
456
    @Override
457
    public int getIntOrDefault(int index, int defaultValue) {
458
        if( index < 0 || index >= this.data.getType().size() ) {
459
            return defaultValue;
460
        }
461
        try {
462
            return (int) this.get(index);
463
        } catch(Throwable th) {
464
            return defaultValue;
465
        }
466
    }
467

    
468
    @Override
469
    public long getLongOrDefault(int index, long defaultValue) {
470
        if( index < 0 || index >= this.data.getType().size() ) {
471
            return defaultValue;
472
        }
473
        try {
474
            return (long) this.get(index);
475
        } catch(Throwable th) {
476
            return defaultValue;
477
        }
478
    }
479

    
480
    @Override
481
    public float getFloatOrDefault(int index, float defaultValue) {
482
        if( index < 0 || index >= this.data.getType().size() ) {
483
            return defaultValue;
484
        }
485
        try {
486
            return (float) this.get(index);
487
        } catch(Throwable th) {
488
            return defaultValue;
489
        }
490
    }
491

    
492
    @Override
493
    public double getDoubleOrDefault(int index, double defaultValue) {
494
        if( index < 0 || index >= this.data.getType().size() ) {
495
            return defaultValue;
496
        }
497
        try {
498
            return (double) this.get(index);
499
        } catch(Throwable th) {
500
            return defaultValue;
501
        }
502
    }
503

    
504
    @Override
505
    public BigDecimal getDecimalOrDefault(int index, BigDecimal defaultValue) {
506
        if( index < 0 || index >= this.data.getType().size() ) {
507
            return defaultValue;
508
        }
509
        try {
510
            return (BigDecimal) this.get(index);
511
        } catch(Throwable th) {
512
            return defaultValue;
513
        }
514
    }
515

    
516
    @Override
517
    public Date getDateOrDefault(int index, Date defaultValue) {
518
        if( index < 0 || index >= this.data.getType().size() ) {
519
            return defaultValue;
520
        }
521
        try {
522
            return (Date) this.get(index);
523
        } catch(Throwable th) {
524
            return defaultValue;
525
        }
526
    }
527

    
528
    class UnableToGetReferenceException extends BaseRuntimeException {
529

    
530
        /**
531
         *
532
         */
533
        private static final long serialVersionUID = 1812805035204824163L;
534

    
535
        /**
536
         * @param exception
537
         */
538
        @SuppressWarnings("OverridableMethodCallInConstructor")
539
        public UnableToGetReferenceException(BaseException exception) {
540
            super("Unable to get reference", "_UnableToGetReferenceException",
541
                serialVersionUID);
542
            this.initCause(exception);
543

    
544
        }
545

    
546
    }
547

    
548
    @Override
549
    public void validate(int mode) throws DataException  {
550
        ((DefaultFeatureType) this.data.getType()).validateFeature(this, mode);
551
    }
552

    
553
    @Override
554
    public List getSRSs() {
555
        // TODO Auto-generated method stub
556
        return null;
557
    }
558

    
559
    @Override
560
    public Envelope getDefaultEnvelope() {
561
        Envelope envelope = this.data.getDefaultEnvelope();
562
        if( envelope == null ) {
563
            int i = this.data.getType().getDefaultGeometryAttributeIndex();
564
            if( i<0 ) {
565
                return null;
566
            }
567
            Geometry geom = this.getDefaultGeometry();
568
            if( geom!=null ) {
569
                envelope = geom.getEnvelope();
570
            }
571
        }
572
        return envelope;
573
    }
574

    
575
    @Override
576
    public Geometry getDefaultGeometry() {
577
            Geometry geom = this.data.getDefaultGeometry();
578
        if( geom == null ) {
579
            int i = this.data.getType().getDefaultGeometryAttributeIndex();
580
            if( i<0 ) {
581
                return null;
582
            }
583
            Object x = this.get(i);
584
            if( x instanceof Geometry ) {
585
                geom = (Geometry) x;
586
            } else {
587
                geom = this.getGeometry(i);
588
            }
589
        }
590
        if( geom != null ) {
591
            if( geom.getProjection()==null ) {
592
                FeatureType type = this.getType();
593
                DefaultFeatureAttributeDescriptor attrdesc = (DefaultFeatureAttributeDescriptor) type.get(type.getDefaultGeometryAttributeIndex());
594
                IProjection proj = attrdesc.getSRS(this.storeRef);
595
                geom.setProjection(proj);
596
            }
597
        }
598
        return geom;
599
    }
600

    
601
//    @Override
602
//    public Time getDefaultTime() {
603
//            Time time = this.data.getDefaultTime();
604
//        if( time == null ) {
605
//            int i = this.data.getType().getDefaultTimeAttributeIndex();
606
//            Object x = this.get(i);
607
//            if( x instanceof Time ) {
608
//                time = (Time) x;
609
//            } else {
610
//                time = this.getTime(i);
611
//            }
612
//        }
613
//        return time;
614
//    }
615
//
616
    @Override
617
    public IProjection getDefaultSRS() {
618
        IProjection srs = this.data.getType().getDefaultSRS();
619
        if( srs == null ) {
620
            FeatureType type = this.getType();
621
            DefaultFeatureAttributeDescriptor attrdesc = (DefaultFeatureAttributeDescriptor) type.get(type.getDefaultGeometryAttributeIndex());
622
            srs = attrdesc.getSRS(this.storeRef);
623
        }
624
        return srs;
625
    }
626

    
627
    @Override
628
    public List getGeometries() {
629
        // TODO Auto-generated method stub
630
        return null;
631
    }
632

    
633
    @Override
634
    public Object getFromProfile(int index) {
635
        FeatureAttributeDescriptor descriptor = this.data.getType().getAttributeDescriptor(index);
636
        Object value = this.get(index);
637
        String profileName = descriptor.getDataProfileName();
638
        if( StringUtils.isBlank(profileName) ) {
639
            return value;
640
        }
641
        DataProfile profile = DALLocator.getDataManager().getDataProfile(profileName);
642
        if( profile==null ) {
643
            return value;
644
        }
645
        return profile.createData(value, descriptor.getTags());
646
    }
647

    
648
    @Override
649
    public Object getFromProfile(String name) {
650
        FeatureAttributeDescriptor descriptor = this.data.getType().getAttributeDescriptor(name);
651
        return this.getFromProfile(descriptor.getIndex());
652
    }
653

    
654
    @Override
655
    public Object get(String name) {
656
        int index = this.data.getType().getIndex(name);
657
        if( index < 0 ) {
658
            throw new IllegalArgumentException("Attribute name '"+name+"' not found in the feature.");
659
        }
660
        return this.get(index);
661
    }
662
    
663
    @Override
664
    public boolean isNull(int index) {
665
        FeatureType type = this.data.getType();
666
        if( index <0 || index >= type.size() ) {
667
            throw new IllegalArgumentException("Attribute index '"+index+"' out of range (0 to "+this.data.getType().size()+".");
668
        }
669
        FeatureAttributeDescriptor attribute = type.getAttributeDescriptor(index);
670
        if (!this.data.getType().hasEvaluators()) {
671
            return this.data.get(index)==null;
672
        }
673
        Evaluator eval = attribute.getEvaluator();
674
        if (eval == null) {
675
            return this.data.get(index)==null;
676
        }
677
        Object value = this.data.get(index);
678
        if (value != null) {
679
            return true;
680
        }
681
        try {
682
            value = eval.evaluate(this);
683
        } catch (EvaluatorException e) {
684
            throw new DataEvaluatorRuntimeException(e);
685
        }
686
        this.data.set(index, value);
687
        return value==null;
688
    }
689
    
690
    @Override
691
    public boolean isNull(String name) {
692
        int index = this.data.getType().getIndex(name);
693
        if( index < 0 ) {
694
            throw new IllegalArgumentException("Attribute name '"+name+"' not found in the feature.");
695
        }
696
        return this.isNull(index);
697
    }
698

    
699
    public boolean has_key(String key) {
700
        Object x = this.getType().get(key);
701
        return x != null;
702
    }
703

    
704
    public List<String> keys() {
705
        List<String> ks = new ArrayList<>();
706
        for( FeatureAttributeDescriptor attr : this.getType()) {
707
            ks.add(attr.getName());
708
        }
709
        return ks;
710
    }
711

    
712
    public Iterator<String> iterkeys() {
713
        final Iterator it = this.getType().iterator();
714
        return new Iterator<String>() {
715
            @Override
716
            public boolean hasNext() {
717
                return it.hasNext();
718
            }
719

    
720
            @Override
721
            public String next() {
722
                return ((FeatureAttributeDescriptor)it.next()).getName();
723
            }
724

    
725
            @Override
726
            public void remove() {
727
                throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
728
            }
729
        };
730
    }
731

    
732
    public Iterator iteritems() {
733
        final Iterator it = this.getType().iterator();
734
        return new Iterator<Map.Entry>() {
735
            @Override
736
            public boolean hasNext() {
737
                return it.hasNext();
738
            }
739

    
740
            @Override
741
            public Map.Entry next() {
742
                final String name = ((FeatureAttributeDescriptor)it.next()).getName();
743
                return new Map.Entry<String, Object>() {
744
                    @Override
745
                    public String getKey() {
746
                        return name;
747
                    }
748

    
749
                    @Override
750
                    public Object getValue() {
751
                        return get(name);
752
                    }
753

    
754
                    @Override
755
                    public Object setValue(Object value) {
756
                        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
757
                    }
758

    
759
                };
760
            }
761

    
762
            @Override
763
            public void remove() {
764
                throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
765
            }
766
        };
767
    }
768

    
769
    @Override
770
    public Object get(int index) {
771
        FeatureType type = this.data.getType();
772
        if( index <0 || index >= type.size() ) {
773
            throw new IllegalArgumentException("Attribute index '"+index+"' out of range (0 to "+this.data.getType().size()+".");
774
        }
775
        Object value = this.data.get(index);
776
        FeatureAttributeDescriptor attribute = type.getAttributeDescriptor(index);
777
        if (type.hasEvaluators()) {
778
          Evaluator eval = attribute.getEvaluator();
779
          if (eval != null) {
780
            if (value == null) { // Ya hemos calculado el campo ?
781
              // FIXME: para comprobar si esta calculado usar un array especifico.
782
              try {
783
                  value = eval.evaluate(this);
784
              } catch (EvaluatorException e) {
785
                  throw new DataEvaluatorRuntimeException(e);
786
              }
787
              this.data.set(index, value);
788
            }          
789
          }
790
        }
791
        value = get(attribute, value);
792
        return  value;
793
    }
794

    
795
    private Object get(FeatureAttributeDescriptor featureAttributeDescriptor, Object value){
796
        FeatureAttributeEmulator emulator = featureAttributeDescriptor.getFeatureAttributeEmulator();
797
        if( emulator != null ) {
798
//            int index = featureAttributeDescriptor.getIndex();
799
//            value = this.data.get(index);
800
//            if( value==null ) {
801
                value = emulator.get(this);
802
//                this.data.set(index,value);
803
//            }
804
        } else {
805
            FeatureAttributeGetter getter = featureAttributeDescriptor.getFeatureAttributeGetter();
806
            if( getter != null ) {
807
                value = getter.getter(value);
808
            }
809
        }
810
        DataType dataType = featureAttributeDescriptor.getDataType();
811
        Class<? extends DataType> theClass = dataType.getClass();
812
        if( theClass!=null && !theClass.isInstance(value) ) {
813
            try {
814
                value = this.getDataTypesManager().coerce(dataType.getType(), value);
815
            } catch (CoercionException e) {
816
                    throw new IllegalArgumentException(
817
                            "Can't convert to "+theClass.getName()+
818
                            " from '"+value.getClass().getName()+
819
                            "' with value '"+value.toString()+"'.");
820
            }
821
        }
822
        if( featureAttributeDescriptor.getType()==DataTypes.GEOMETRY ) {
823
            if( value != null ) {
824
                Geometry geom = (Geometry)value;
825
                if( geom.getProjection()==null ) {
826
                    IProjection proj = ((DefaultFeatureAttributeDescriptor)featureAttributeDescriptor).getSRS(this.storeRef);
827
                    geom.setProjection(proj);
828
                }
829
            }
830
        }
831
        return value;
832
    }
833

    
834
    @Override
835
    public byte[] getByteArray(String name) {
836
        return this.getByteArray(this.data.getType().getIndex(name));
837
    }
838

    
839
    @Override
840
    public byte[] getByteArray(int index) {
841
        return (byte[]) this.get(index);
842
    }
843

    
844
    @Override
845
    public Object[] getArray(String name) {
846
        return this.getArray(this.data.getType().getIndex(name));
847
    }
848

    
849
    @Override
850
    public Object[] getArray(int index) {
851
        return (Object[]) this.get(index);
852
    }
853

    
854
    @Override
855
    public boolean getBoolean(String name) {
856
        return this.getBoolean(this.data.getType().getIndex(name));
857
    }
858

    
859
    @Override
860
    public boolean getBoolean(int index) {
861
        Boolean value = ((Boolean) this.get(index,Boolean.class,DataTypes.BOOLEAN));
862
        if (value == null) {
863
            return false;
864
        }
865
        return value;
866
    }
867

    
868
    @Override
869
    public byte getByte(String name) {
870
        return this.getByte(this.data.getType().getIndex(name));
871
    }
872

    
873
    @Override
874
    public byte getByte(int index) {
875
        Byte value = ((Byte) this.get(index,Byte.class,DataTypes.BYTE));
876
        if (value == null) {
877
            return 0;
878
        }
879
        return value;
880
    }
881

    
882
    @Override
883
    public Date getDate(String name) {
884
        return this.getDate(this.data.getType().getIndex(name));
885
    }
886

    
887
    @Override
888
    public Date getDate(int index) {
889
        Date value = ((Date) this.get(index,java.sql.Date.class,DataTypes.DATE));
890
        return value;
891
    }
892

    
893
    @Override
894
    public Date getTime(String name) {
895
        return this.getTime(this.data.getType().getIndex(name));
896
    }
897

    
898
    @Override
899
    public Date getTime(int index) {
900
        Date value = ((Date) this.get(index,java.sql.Time.class,DataTypes.TIME));
901
        return value;
902
    }
903

    
904
    @Override
905
    public Date getTimestamp(String name) {
906
        return this.getTimestamp(this.data.getType().getIndex(name));
907
    }
908

    
909
    @Override
910
    public Date getTimestamp(int index) {
911
        Date value = ((Date) this.get(index,java.sql.Timestamp.class,DataTypes.TIMESTAMP));
912
        return value;
913
    }
914

    
915
    @Override
916
    public double getDouble(String name) {
917
        return this.getDouble(this.data.getType().getIndex(name));
918
    }
919

    
920
    @Override
921
    public double getDouble(int index) {
922

    
923
        Double value = ((Double) this.get(index,Double.class,DataTypes.DOUBLE));
924
        if (value == null) {
925
            return 0;
926
        }
927
        return value;
928
    }
929

    
930
    @Override
931
    public BigDecimal getDecimal(String name) {
932
        return this.getDecimal(this.data.getType().getIndex(name));
933
    }
934

    
935
    @Override
936
    public BigDecimal getDecimal(int index) {
937
        BigDecimal value = ((BigDecimal) this.get(index,BigDecimal.class,DataTypes.DECIMAL));
938
        return value;
939
    }
940

    
941
    @Override
942
    public Feature getFeature(String name) {
943
        return this.getFeature(this.data.getType().getIndex(name));
944
    }
945

    
946
    @Override
947
    public Feature getFeature(int index) {
948
        return (Feature) this.get(index);
949
    }
950

    
951
    @Override
952
    public float getFloat(String name) {
953
        return this.getFloat(this.data.getType().getIndex(name));
954
    }
955

    
956
    @Override
957
    public float getFloat(int index) {
958
        Float value = ((Float) this.get(index,Float.class,DataTypes.FLOAT));
959
        if (value == null) {
960
            return 0;
961
        }
962
        return value;
963
    }
964

    
965
    @Override
966
    public Geometry getGeometry(String name) {
967
        return this.getGeometry(this.data.getType().getIndex(name));
968
    }
969

    
970
    @Override
971
    public Geometry getGeometry(int index) {
972
        return (Geometry) this.get(index,Geometry.class,DataTypes.GEOMETRY);
973
    }
974

    
975
    @Override
976
    public int getInt(String name) {
977
        return this.getInt(this.data.getType().getIndex(name));
978
    }
979

    
980
    @Override
981
    public int getInt(int index) {
982
        Integer value = ((Integer) this.get(index,Integer.class,DataTypes.INT));
983
        if (value == null) {
984
            return 0;
985
        }
986
        return value;
987
    }
988

    
989
    @Override
990
    public long getLong(String name) {
991
        return this.getLong(this.data.getType().getIndex(name));
992
    }
993

    
994
    @Override
995
    public long getLong(int index) {
996
        Long value = ((Long) this.get(index,Long.class,DataTypes.LONG));
997
        if (value == null) {
998
            return 0;
999
        }
1000
        return value;
1001
    }
1002

    
1003
    @Override
1004
    public String getString(String name) {
1005
        return this.getString(this.data.getType().getIndex(name));
1006
    }
1007

    
1008
    @Override
1009
    public String getString(int index) {
1010
        return (String) this.get(index,String.class,DataTypes.STRING);
1011
    }
1012

    
1013
    @Override
1014
    public Object getContextValue(String name) {
1015
        name = name.toLowerCase();
1016
        if (name.equals("store")) {
1017
            return this.getStore();
1018
        }
1019

    
1020
        if (name.equals("featuretype")) {
1021
            return this.data.getType();
1022
        }
1023

    
1024
        if (name.equals("feature")) {
1025
            return this;
1026
        }
1027

    
1028
        throw new IllegalArgumentException(name);
1029
    }
1030

    
1031
    @Override
1032
    public Iterator getDataNames() {
1033
        class DataNamesIterator implements Iterator {
1034
            Iterator attributeIteraror;
1035

    
1036
            DataNamesIterator(DefaultFeature feature) {
1037
                this.attributeIteraror = feature.getType().iterator();
1038
            }
1039

    
1040
            @Override
1041
            public boolean hasNext() {
1042
                return this.attributeIteraror.hasNext();
1043
            }
1044

    
1045
            @Override
1046
            public Object next() {
1047
                return ((FeatureAttributeDescriptor) this.attributeIteraror
1048
                        .next()).getName();
1049
            }
1050

    
1051
            @Override
1052
            public void remove() {
1053
                throw new UnsupportedOperationException();
1054
            }
1055

    
1056
        }
1057
        return new DataNamesIterator(this);
1058
    }
1059

    
1060
    @Override
1061
    public Object getDataValue(String name) {
1062
        name = name.toLowerCase();
1063
        try {
1064
            return get(name);
1065
        } catch (IllegalArgumentException ex) {
1066
            if( "defaultgeometry".equalsIgnoreCase(name )) {
1067
                return this.getDefaultGeometry();
1068
            }
1069
            throw ex;
1070
        }
1071
    }
1072

    
1073
    @Override
1074
    public Iterator getDataValues() {
1075
        class DataValuesIterator implements Iterator {
1076
            DefaultFeature feature;
1077
            int current = 0;
1078

    
1079
            DataValuesIterator(DefaultFeature feature) {
1080
                this.feature = feature;
1081
            }
1082

    
1083
            @Override
1084
            public boolean hasNext() {
1085
                return current < feature.getType().size() - 1;
1086
            }
1087

    
1088
            @Override
1089
            public Object next() {
1090
                return feature.get(current++);
1091
            }
1092

    
1093
            @Override
1094
            public void remove() {
1095
                throw new UnsupportedOperationException();
1096
            }
1097

    
1098
        }
1099
        return new DataValuesIterator(this);
1100
    }
1101

    
1102
    @Override
1103
    public boolean hasContextValue(String name) {
1104
        name = name.toLowerCase();
1105
        if (name.equals("store")) {
1106
            return true;
1107
        }
1108

    
1109
        if (name.equals("featuretype")) {
1110
            return true;
1111
        }
1112

    
1113
        return name.equals("feature");
1114
    }
1115

    
1116
    @Override
1117
    public boolean hasDataValue(String name) {
1118
        name = name.toLowerCase();
1119
        return this.data.getType().getIndex(name) >= 0;
1120
    }
1121

    
1122
//    @Override
1123
//    public Time getTime(int index) {
1124
//        return ((Time) this.get(index,Time.class,DataTypes.INSTANT));
1125
//    }
1126
//
1127
//    @Override
1128
//    public Time getTime(String name) {
1129
//        return this.getInstant(this.data.getType().getIndex(name));
1130
//    }
1131
//
1132
//    @Override
1133
//    public Instant getInstant(int index) {
1134
//        return ((Instant) this.get(index,Instant.class,DataTypes.INSTANT));
1135
//    }
1136
//
1137
//    @Override
1138
//    public Instant getInstant(String name) {
1139
//        return this.getInstant(this.data.getType().getIndex(name));
1140
//    }
1141
//
1142
//    @Override
1143
//    public Interval getInterval(int index) {
1144
//        return ((Interval) this.get(index,Interval.class,DataTypes.INTERVAL));
1145
//    }
1146
//
1147
//    @Override
1148
//    public Interval getInterval(String name) {
1149
//        return this.getInterval(this.data.getType().getIndex(name));
1150
//    }
1151
//
1152
    @Override
1153
    public DynObject getAsDynObject() {
1154
        DynObjectFeatureFacade facade = new DynObjectFeatureFacade(this);
1155
        return facade;
1156
    }
1157

    
1158
    @Override
1159
    public String toString() {
1160
            StringBuilder builder = new StringBuilder();
1161
        FeatureAttributeDescriptor[] attributeDescriptors =
1162
            getType().getAttributeDescriptors();
1163
        for (int i = 0; i < attributeDescriptors.length; i++) {
1164
            String name = attributeDescriptors[i].getName();
1165
            Object value = get(name);
1166
            builder.append(value);
1167
            if (i < attributeDescriptors.length - 1) {
1168
                builder.append(", ");
1169
            }
1170
        }
1171
        return builder.toString();
1172
    }
1173

    
1174

    
1175

    
1176

    
1177
        /**
1178
     * @return the inserted
1179
     */
1180
    public boolean isInserted() {
1181
        return inserted;
1182
    }
1183

    
1184

    
1185
    /**
1186
     * @param inserted the inserted to set
1187
     */
1188
    public void setInserted(boolean inserted) {
1189
        this.inserted = inserted;
1190
    }
1191

    
1192
        @Override
1193
    public EvaluatorData getEvaluatorData() {
1194
        return this;
1195
    }
1196

    
1197
    @Override
1198
    public int size() {
1199
        return this.data.getType().size();
1200
    }
1201
    
1202
    public boolean isEmpty() {
1203
        return false;
1204
    }
1205

    
1206
    public Iterator<String> iterator() {
1207
        final Iterator<FeatureAttributeDescriptor> x = this.data.getType().iterator();
1208
        return new Iterator<String>() {
1209
            @Override
1210
            public boolean hasNext() {
1211
                return x.hasNext();
1212
            }
1213

    
1214
            @Override
1215
            public String next() {
1216
                return x.next().getName();
1217
            }
1218
        };
1219
    }
1220
    
1221
    public boolean containsKey(String key) {
1222
        return this.data.getType().get(key)!=null;
1223
    }
1224

    
1225
    @Override
1226
    public String getLabelOfValue(String name) {
1227
        FeatureAttributeDescriptor attrdesc = this.data.getType().getAttributeDescriptor(name);
1228
        if( attrdesc==null ) {
1229
            throw new IllegalArgumentException("Attribute name '"+name+"' not found in the feature.");
1230
        }
1231
        Object value = this.get(attrdesc.getIndex());
1232
        String label = attrdesc.getLabelOfValue(value);
1233
        return label;
1234
    }
1235
   
1236
    @Override
1237
    public void setExtraValue(String name, Object value) {
1238
      if( this.extraValues==null ) {
1239
        this.extraValues = new HashMap<>();
1240
      }
1241
      this.extraValues.put(name, value);
1242
    }
1243

    
1244
    @Override
1245
    public Object getExtraValue(String name) {
1246
        Object value;
1247
        if( this.extraValues!=null ) {
1248
          if( this.extraValues.containsKey(name) ) {
1249
            return this.extraValues.get(name);
1250
          }
1251
        }
1252
        FeatureExtraColumns columns = this.getType().getExtraColumns();
1253
        int index = columns.getIndexOf(name);
1254
        if( index >= 0 ) {
1255
          if( extraValuesData==null ) {
1256
            extraValuesData = new Object[columns.size()];
1257
            EditableFeatureAttributeDescriptor attrdesc = columns.get(index);
1258
            value = attrdesc.getFeatureAttributeEmulator().get(this);
1259
            extraValuesData[index] = value;
1260
          } else {
1261
            value = extraValuesData[index];
1262
            if( value == null ) {
1263
              EditableFeatureAttributeDescriptor attrdesc = columns.get(index);
1264
              value = attrdesc.getFeatureAttributeEmulator().get(this);
1265
              extraValuesData[index] = value;
1266
            }
1267
          }
1268
          return value;
1269
        }
1270
        value = this.data.getExtraValue(name);
1271
        return value;
1272
    }
1273

    
1274
    @Override
1275
    public boolean hasExtraValue(String name) {
1276
        if( this.extraValues!=null ) {
1277
          if( this.extraValues.containsKey(name) ) {
1278
            return true;
1279
          }
1280
        }
1281
        FeatureExtraColumns columns = this.getType().getExtraColumns();
1282
        int index = columns.getIndexOf(name);
1283
        if( index >= 0 ) {
1284
          return true;
1285
        }
1286
        return this.data.hasExtraValue(name);
1287
    }
1288
    
1289
    @Override
1290
    public Object getExtraValue(int index) {
1291
        return this.data.getExtraValue(index);
1292
    }
1293

    
1294
    public JsonObject toJSON() {
1295
        JsonObjectBuilder builder = Json.createObjectBuilder();
1296
        
1297
        FeatureType ft = this.getType();
1298
        for (FeatureAttributeDescriptor desc : ft) {
1299
            if (desc.isComputed()) {
1300
                continue;
1301
            }
1302
            switch(desc.getType()) {
1303
                case DataTypes.GEOMETRY:
1304
                    {
1305
                        try {
1306
                            builder.add(desc.getName(), this.getGeometry(desc.getIndex()).convertToWKT());
1307
                        } catch (Exception ex) {
1308
                            throw new RuntimeException("Can't convert geometry to WKT.", ex);
1309
                        }
1310
                    }
1311
                    break;
1312
                case DataTypes.BOOLEAN:
1313
                    builder.add(desc.getName(), this.getBoolean(desc.getIndex()));
1314
                    break;
1315
                case DataTypes.BYTE:
1316
                    builder.add(desc.getName(), this.getByte(desc.getIndex()));
1317
                    break;
1318
                case DataTypes.INT:
1319
                    builder.add(desc.getName(), this.getInt(desc.getIndex()));
1320
                    break;
1321
                case DataTypes.LONG:
1322
                    builder.add(desc.getName(), this.getLong(desc.getIndex()));
1323
                    break;
1324
                case DataTypes.DOUBLE:
1325
                    builder.add(desc.getName(), this.getDouble(desc.getIndex()));
1326
                    break;
1327
                case DataTypes.FLOAT:
1328
                    builder.add(desc.getName(), this.getFloat(desc.getIndex()));
1329
                    break;
1330
                case DataTypes.DATE:
1331
                    // Format date as ISO 8601
1332
                    Date date = this.getDate(desc.getIndex());
1333
                    if( date==null ) {
1334
                        builder.addNull(desc.getName());
1335
                    } else {
1336
                        String value = DateTimeFormatter.ISO_DATE_TIME.format(new Date(date.getTime()).toInstant());
1337
                        builder.add(desc.getName(), value);
1338
                    }
1339
                    break;
1340
                default:
1341
                    builder.add(desc.getName(), Objects.toString(this.get(desc.getIndex()),""));
1342
            }
1343
        }        
1344
        return builder.build();
1345
    }
1346

    
1347
    @Override
1348
    public List<String> getKeys() {
1349
      List<String> l = new ArrayList<>();
1350
      for (FeatureAttributeDescriptor descriptor : this.getType()) {
1351
        l.add(descriptor.getName());
1352
      }
1353
      return l;
1354
    }
1355

    
1356
}