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

History | View | Annotate | Download (40 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.Iterator;
32
import java.util.List;
33
import java.util.Map;
34
import java.util.Objects;
35
import javax.json.Json;
36
import javax.json.JsonObject;
37
import javax.json.JsonObjectBuilder;
38
import org.apache.commons.lang3.ArrayUtils;
39
import org.apache.commons.lang3.StringUtils;
40
import org.cresques.cts.IProjection;
41
import org.gvsig.expressionevaluator.ExpressionEvaluatorManager;
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.FeatureExtraColumn;
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.spi.DefaultFeatureProvider;
62
import org.gvsig.fmap.dal.feature.spi.FeatureProvider;
63
import org.gvsig.fmap.geom.Geometry;
64
import org.gvsig.fmap.geom.primitive.Envelope;
65
import org.gvsig.tools.ToolsLocator;
66
import org.gvsig.tools.dataTypes.Coercion;
67
import org.gvsig.tools.dataTypes.CoercionException;
68
import org.gvsig.tools.dataTypes.DataTypesManager;
69
import org.gvsig.tools.dynobject.DynObject;
70
import org.gvsig.tools.evaluator.Evaluator;
71
import org.gvsig.tools.evaluator.EvaluatorData;
72
import org.gvsig.tools.evaluator.EvaluatorException;
73
import org.gvsig.tools.exception.BaseException;
74
import org.gvsig.tools.exception.BaseRuntimeException;
75
import org.gvsig.tools.lang.Cloneable;
76

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

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

    
85
        private boolean inserted = false;
86
        private Object[] extraValuesData;
87

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

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

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

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

    
121
        FeatureType sourceType = sourceFeature.getType();
122

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

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

    
146
        public FeatureProvider getData() {
147
                return this.data;
148
        }
149

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

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

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

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

    
178
        }
179

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

    
186
    private void setforced(int i, FeatureAttributeDescriptor attribute, Object value) {
187

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

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

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

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

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

    
276
    public void clear() {
277
        initializeValues();
278
    }
279

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

    
292

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
526
    class UnableToGetReferenceException extends BaseRuntimeException {
527

    
528
        /**
529
         *
530
         */
531
        private static final long serialVersionUID = 1812805035204824163L;
532

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

    
542
        }
543

    
544
    }
545

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
757
                };
758
            }
759

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

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

    
797
    private Object get(FeatureAttributeDescriptor featureAttributeDescriptor, Object value){
798
        FeatureAttributeEmulator emulator = featureAttributeDescriptor.getFeatureAttributeEmulator();
799
        if( emulator != null ) {
800
//            int index = featureAttributeDescriptor.getIndex();
801
//            value = this.data.get(index);
802
//            if( value==null ) {
803
                value = emulator.get(this);
804
//                this.data.set(index,value);
805
//            }
806
        } else {
807
            FeatureAttributeGetter getter = featureAttributeDescriptor.getFeatureAttributeGetter();
808
            if( getter != null ) {
809
                value = getter.getter(value);
810
            }
811
        }
812
        if( featureAttributeDescriptor.getType()==DataTypes.GEOMETRY ) {
813
            if( value != null ) {
814
                Geometry geom = (Geometry)value;
815
                if( geom.getProjection()==null ) {
816
                    IProjection proj = ((DefaultFeatureAttributeDescriptor)featureAttributeDescriptor).getSRS(this.storeRef);
817
                    geom.setProjection(proj);
818
                }
819
            }
820
        }
821
        return value;
822
    }
823

    
824
    @Override
825
    public byte[] getByteArray(String name) {
826
        return this.getByteArray(this.data.getType().getIndex(name));
827
    }
828

    
829
    @Override
830
    public byte[] getByteArray(int index) {
831
        return (byte[]) this.get(index);
832
    }
833

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

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

    
844
    @Override
845
    public boolean getBoolean(String name) {
846
        return this.getBoolean(this.data.getType().getIndex(name));
847
    }
848

    
849
    @Override
850
    public boolean getBoolean(int index) {
851
        Boolean value = ((Boolean) this.get(index,Boolean.class,DataTypes.BOOLEAN));
852
        if (value == null) {
853
            return false;
854
        }
855
        return value;
856
    }
857

    
858
    @Override
859
    public byte getByte(String name) {
860
        return this.getByte(this.data.getType().getIndex(name));
861
    }
862

    
863
    @Override
864
    public byte getByte(int index) {
865
        Byte value = ((Byte) this.get(index,Byte.class,DataTypes.BYTE));
866
        if (value == null) {
867
            return 0;
868
        }
869
        return value;
870
    }
871

    
872
    @Override
873
    public Date getDate(String name) {
874
        return this.getDate(this.data.getType().getIndex(name));
875
    }
876

    
877
    @Override
878
    public Date getDate(int index) {
879
        Date value = ((Date) this.get(index,java.sql.Date.class,DataTypes.DATE));
880
        return value;
881
    }
882

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

    
888
    @Override
889
    public Date getTime(int index) {
890
        Date value = ((Date) this.get(index,java.sql.Time.class,DataTypes.TIME));
891
        return value;
892
    }
893

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

    
899
    @Override
900
    public Date getTimestamp(int index) {
901
        Date value = ((Date) this.get(index,java.sql.Timestamp.class,DataTypes.TIMESTAMP));
902
        return value;
903
    }
904

    
905
    @Override
906
    public double getDouble(String name) {
907
        return this.getDouble(this.data.getType().getIndex(name));
908
    }
909

    
910
    @Override
911
    public double getDouble(int index) {
912

    
913
        Double value = ((Double) this.get(index,Double.class,DataTypes.DOUBLE));
914
        if (value == null) {
915
            return 0;
916
        }
917
        return value;
918
    }
919

    
920
    @Override
921
    public BigDecimal getDecimal(String name) {
922
        return this.getDecimal(this.data.getType().getIndex(name));
923
    }
924

    
925
    @Override
926
    public BigDecimal getDecimal(int index) {
927

    
928
        BigDecimal value = ((BigDecimal) this.get(index,BigDecimal.class,DataTypes.DECIMAL));
929
        if (value == null) {
930
            return BigDecimal.ZERO;
931
        }
932
        return value;
933
    }
934

    
935
    @Override
936
    public Feature getFeature(String name) {
937
        return this.getFeature(this.data.getType().getIndex(name));
938
    }
939

    
940
    @Override
941
    public Feature getFeature(int index) {
942
        return (Feature) this.get(index);
943
    }
944

    
945
    @Override
946
    public float getFloat(String name) {
947
        return this.getFloat(this.data.getType().getIndex(name));
948
    }
949

    
950
    @Override
951
    public float getFloat(int index) {
952
        Float value = ((Float) this.get(index,Float.class,DataTypes.FLOAT));
953
        if (value == null) {
954
            return 0;
955
        }
956
        return value;
957
    }
958

    
959
    @Override
960
    public Geometry getGeometry(String name) {
961
        return this.getGeometry(this.data.getType().getIndex(name));
962
    }
963

    
964
    @Override
965
    public Geometry getGeometry(int index) {
966
        return (Geometry) this.get(index,Geometry.class,DataTypes.GEOMETRY);
967
    }
968

    
969
    @Override
970
    public int getInt(String name) {
971
        return this.getInt(this.data.getType().getIndex(name));
972
    }
973

    
974
    @Override
975
    public int getInt(int index) {
976
        Integer value = ((Integer) this.get(index,Integer.class,DataTypes.INT));
977
        if (value == null) {
978
            return 0;
979
        }
980
        return value;
981
    }
982

    
983
    @Override
984
    public long getLong(String name) {
985
        return this.getLong(this.data.getType().getIndex(name));
986
    }
987

    
988
    @Override
989
    public long getLong(int index) {
990
        Long value = ((Long) this.get(index,Long.class,DataTypes.LONG));
991
        if (value == null) {
992
            return 0;
993
        }
994
        return value;
995
    }
996

    
997
    @Override
998
    public String getString(String name) {
999
        return this.getString(this.data.getType().getIndex(name));
1000
    }
1001

    
1002
    @Override
1003
    public String getString(int index) {
1004
        return (String) this.get(index,String.class,DataTypes.STRING);
1005
    }
1006

    
1007
    @Override
1008
    public Object getContextValue(String name) {
1009
        name = name.toLowerCase();
1010
        if (name.equals("store")) {
1011
            return this.getStore();
1012
        }
1013

    
1014
        if (name.equals("featuretype")) {
1015
            return this.data.getType();
1016
        }
1017

    
1018
        if (name.equals("feature")) {
1019
            return this;
1020
        }
1021

    
1022
        throw new IllegalArgumentException(name);
1023
    }
1024

    
1025
    @Override
1026
    public Iterator getDataNames() {
1027
        class DataNamesIterator implements Iterator {
1028
            Iterator attributeIteraror;
1029

    
1030
            DataNamesIterator(DefaultFeature feature) {
1031
                this.attributeIteraror = feature.getType().iterator();
1032
            }
1033

    
1034
            @Override
1035
            public boolean hasNext() {
1036
                return this.attributeIteraror.hasNext();
1037
            }
1038

    
1039
            @Override
1040
            public Object next() {
1041
                return ((FeatureAttributeDescriptor) this.attributeIteraror
1042
                        .next()).getName();
1043
            }
1044

    
1045
            @Override
1046
            public void remove() {
1047
                throw new UnsupportedOperationException();
1048
            }
1049

    
1050
        }
1051
        return new DataNamesIterator(this);
1052
    }
1053

    
1054
    @Override
1055
    public Object getDataValue(String name) {
1056
        name = name.toLowerCase();
1057
        try {
1058
            return get(name);
1059
        } catch (IllegalArgumentException ex) {
1060
            if( "defaultgeometry".equalsIgnoreCase(name )) {
1061
                return this.getDefaultGeometry();
1062
            }
1063
            throw ex;
1064
        }
1065
    }
1066

    
1067
    @Override
1068
    public Iterator getDataValues() {
1069
        class DataValuesIterator implements Iterator {
1070
            DefaultFeature feature;
1071
            int current = 0;
1072

    
1073
            DataValuesIterator(DefaultFeature feature) {
1074
                this.feature = feature;
1075
            }
1076

    
1077
            @Override
1078
            public boolean hasNext() {
1079
                return current < feature.getType().size() - 1;
1080
            }
1081

    
1082
            @Override
1083
            public Object next() {
1084
                return feature.get(current++);
1085
            }
1086

    
1087
            @Override
1088
            public void remove() {
1089
                throw new UnsupportedOperationException();
1090
            }
1091

    
1092
        }
1093
        return new DataValuesIterator(this);
1094
    }
1095

    
1096
    @Override
1097
    public boolean hasContextValue(String name) {
1098
        name = name.toLowerCase();
1099
        if (name.equals("store")) {
1100
            return true;
1101
        }
1102

    
1103
        if (name.equals("featuretype")) {
1104
            return true;
1105
        }
1106

    
1107
        return name.equals("feature");
1108
    }
1109

    
1110
    @Override
1111
    public boolean hasDataValue(String name) {
1112
        name = name.toLowerCase();
1113
        return this.data.getType().getIndex(name) >= 0;
1114
    }
1115

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

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

    
1168

    
1169

    
1170

    
1171
        /**
1172
     * @return the inserted
1173
     */
1174
    public boolean isInserted() {
1175
        return inserted;
1176
    }
1177

    
1178

    
1179
    /**
1180
     * @param inserted the inserted to set
1181
     */
1182
    public void setInserted(boolean inserted) {
1183
        this.inserted = inserted;
1184
    }
1185

    
1186
        @Override
1187
    public EvaluatorData getEvaluatorData() {
1188
        return this;
1189
    }
1190

    
1191
    public int size() {
1192
        return this.data.getType().size();
1193
    }
1194
    
1195
    public boolean isEmpty() {
1196
        return false;
1197
    }
1198

    
1199
    public Iterator<String> iterator() {
1200
        final Iterator<FeatureAttributeDescriptor> x = this.data.getType().iterator();
1201
        return new Iterator<String>() {
1202
            @Override
1203
            public boolean hasNext() {
1204
                return x.hasNext();
1205
            }
1206

    
1207
            @Override
1208
            public String next() {
1209
                return x.next().getName();
1210
            }
1211
        };
1212
    }
1213
    
1214
    public boolean containsKey(String key) {
1215
        return this.data.getType().get(key)!=null;
1216
    }
1217

    
1218
    @Override
1219
    public String getLabelOfValue(String name) {
1220
        FeatureAttributeDescriptor attrdesc = this.data.getType().getAttributeDescriptor(name);
1221
        if( attrdesc==null ) {
1222
            throw new IllegalArgumentException("Attribute name '"+name+"' not found in the feature.");
1223
        }
1224
        Object value = this.get(attrdesc.getIndex());
1225
        String label = attrdesc.getLabelOfValue(value);
1226
        return label;
1227
    }
1228

    
1229
    
1230
      @Override
1231
    public Object getExtraValue(String name) {
1232
        Object value;
1233
        FeatureExtraColumn columns = this.getType().getExtraColumn();
1234
        int index = columns.getIndexOf(name);
1235
        if( index >= 0 ) {
1236
          if( extraValuesData==null ) {
1237
            extraValuesData = new Object[columns.size()];
1238
            EditableFeatureAttributeDescriptor attrdesc = columns.get(index);
1239
            value = attrdesc.getFeatureAttributeEmulator().get(this);
1240
            extraValuesData[index] = value;
1241
          } else {
1242
            value = extraValuesData[index];
1243
            if( value == null ) {
1244
              EditableFeatureAttributeDescriptor attrdesc = columns.get(index);
1245
              value = attrdesc.getFeatureAttributeEmulator().get(this);
1246
              extraValuesData[index] = value;
1247
            }
1248
          }
1249
          return value;
1250
        }
1251
        value = this.data.getExtraValue(name);
1252
        return value;
1253
    }
1254

    
1255
    @Override
1256
    public boolean hasExtraValue(String name) {
1257
        FeatureExtraColumn columns = this.getType().getExtraColumn();
1258
        int index = columns.getIndexOf(name);
1259
        if( index >= 0 ) {
1260
          return true;
1261
        }
1262
        return this.data.hasExtraValue(name);
1263
    }
1264
    
1265
    @Override
1266
    public Object getExtraValue(int index) {
1267
        return this.data.getExtraValue(index);
1268
    }
1269

    
1270
    public JsonObject toJSON() {
1271
        JsonObjectBuilder builder = Json.createObjectBuilder();
1272
        
1273
        FeatureType ft = this.getType();
1274
        for (FeatureAttributeDescriptor desc : ft) {
1275
            if (desc.isComputed()) {
1276
                continue;
1277
            }
1278
            switch(desc.getType()) {
1279
                case DataTypes.GEOMETRY:
1280
                    {
1281
                        try {
1282
                            builder.add(desc.getName(), this.getGeometry(desc.getIndex()).convertToWKT());
1283
                        } catch (Exception ex) {
1284
                            throw new RuntimeException("Can't convert geometry to WKT.", ex);
1285
                        }
1286
                    }
1287
                    break;
1288
                case DataTypes.BOOLEAN:
1289
                    builder.add(desc.getName(), this.getBoolean(desc.getIndex()));
1290
                    break;
1291
                case DataTypes.BYTE:
1292
                    builder.add(desc.getName(), this.getByte(desc.getIndex()));
1293
                    break;
1294
                case DataTypes.INT:
1295
                    builder.add(desc.getName(), this.getInt(desc.getIndex()));
1296
                    break;
1297
                case DataTypes.LONG:
1298
                    builder.add(desc.getName(), this.getLong(desc.getIndex()));
1299
                    break;
1300
                case DataTypes.DOUBLE:
1301
                    builder.add(desc.getName(), this.getDouble(desc.getIndex()));
1302
                    break;
1303
                case DataTypes.FLOAT:
1304
                    builder.add(desc.getName(), this.getFloat(desc.getIndex()));
1305
                    break;
1306
                case DataTypes.DATE:
1307
                    // Format date as ISO 8601
1308
                    Date date = this.getDate(desc.getIndex());
1309
                    String value = DateTimeFormatter.ISO_DATE_TIME.format(date.toInstant());
1310
                    builder.add(desc.getName(), value);
1311
                    break;
1312
                default:
1313
                    builder.add(desc.getName(), Objects.toString(this.get(desc.getIndex()),""));
1314
            }
1315
        }        
1316
        return builder.build();
1317
    }
1318

    
1319
}