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

History | View | Annotate | Download (37.5 KB)

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

    
26
import java.lang.ref.WeakReference;
27
import java.math.BigDecimal;
28
import java.time.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.StringUtils;
39
import org.cresques.cts.IProjection;
40
import org.gvsig.fmap.dal.DALLocator;
41
import org.gvsig.fmap.dal.DataTypes;
42
import org.gvsig.fmap.dal.exception.DataEvaluatorRuntimeException;
43
import org.gvsig.fmap.dal.exception.DataException;
44
import org.gvsig.fmap.dal.feature.DataProfile;
45
import org.gvsig.fmap.dal.feature.EditableFeature;
46
import org.gvsig.fmap.dal.feature.Feature;
47
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
48
import org.gvsig.fmap.dal.feature.FeatureAttributeEmulator;
49
import org.gvsig.fmap.dal.feature.FeatureAttributeGetter;
50
import org.gvsig.fmap.dal.feature.FeatureReference;
51
import org.gvsig.fmap.dal.feature.FeatureStore;
52
import org.gvsig.fmap.dal.feature.FeatureType;
53
import org.gvsig.fmap.dal.feature.exception.IllegalValueException;
54
import org.gvsig.fmap.dal.feature.exception.SetReadOnlyAttributeException;
55
import org.gvsig.fmap.dal.feature.impl.dynobjectutils.DynObjectFeatureFacade;
56
import org.gvsig.fmap.dal.feature.spi.DefaultFeatureProvider;
57
import org.gvsig.fmap.dal.feature.spi.FeatureProvider;
58
import org.gvsig.fmap.geom.Geometry;
59
import org.gvsig.fmap.geom.primitive.Envelope;
60
import org.gvsig.tools.ToolsLocator;
61
import org.gvsig.tools.dataTypes.CoercionException;
62
import org.gvsig.tools.dataTypes.DataTypesManager;
63
import org.gvsig.tools.dynobject.DynObject;
64
import org.gvsig.tools.evaluator.Evaluator;
65
import org.gvsig.tools.evaluator.EvaluatorData;
66
import org.gvsig.tools.evaluator.EvaluatorException;
67
import org.gvsig.tools.exception.BaseException;
68
import org.gvsig.tools.exception.BaseRuntimeException;
69
import org.gvsig.tools.lang.Cloneable;
70

    
71
public class DefaultFeature implements Feature, EvaluatorData, Cloneable {
72

    
73
        private static DataTypesManager dataTypesManager = null;
74
        protected FeatureProvider data;
75
        protected FeatureReference reference;
76
        private WeakReference storeRef;
77

    
78
        private boolean inserted = false;
79

    
80
    /*
81
         * Usar con mucha precaucion o mejor no usar. Lo precisa el
82
         * DefaultFeatureSet en la ordenacion.
83
         */
84
        public DefaultFeature(FeatureStore store) {
85
                this.storeRef = new WeakReference(store);
86
                this.reference = null;
87
        }
88

    
89
        public DefaultFeature(FeatureStore store, FeatureProvider data) {
90
                this.data = data;
91
                this.storeRef = new WeakReference(store);
92
                this.reference = null;
93
                this.inserted = !data.isNew();
94
        }
95

    
96
        DefaultFeature(DefaultFeature feature) {
97
                this.data = feature.data.getCopy();
98
                this.storeRef = feature.storeRef;
99
                this.reference = feature.reference;
100
                this.inserted = feature.isInserted();
101
        }
102

    
103
    public DefaultFeature(FeatureType targetType, Feature sourceFeature) {
104
        DefaultFeature defaultFeature = (DefaultFeature)sourceFeature;
105
        this.data = new DefaultFeatureProvider(targetType, (DefaultFeatureProvider)defaultFeature.getData());
106
        this.storeRef = defaultFeature.storeRef;
107
        this.reference = defaultFeature.reference;
108
        this.inserted = defaultFeature.isInserted();
109

    
110
        FeatureType sourceType = sourceFeature.getType();
111

    
112
        for (FeatureAttributeDescriptor targetAttrDescriptor : targetType) {
113
            if ( targetAttrDescriptor.isComputed() ) {
114
                 continue;
115
            }
116
            int sourceIndex = sourceType.getIndex(targetAttrDescriptor.getName());
117
            if (sourceIndex<0){
118
                continue;
119
            }
120
            Object value = sourceFeature.get(sourceIndex);
121
            if (value == null && !targetAttrDescriptor.allowNull()) {
122
                continue;
123
            }
124
            this.setforced(targetAttrDescriptor.getIndex(), targetAttrDescriptor,value);
125
        }
126
    }
127

    
128
        public void setData(FeatureProvider data) {
129
                this.data = data;
130
                this.reference = null;
131
                this.inserted = true;
132
        }
133

    
134
        public FeatureProvider getData() {
135
                return this.data;
136
        }
137

    
138
        protected DataTypesManager getDataTypesManager() {
139
                if( dataTypesManager==null ) {
140
                        dataTypesManager = ToolsLocator.getDataTypesManager();
141
                }
142
                return dataTypesManager;
143
        }
144

    
145
    protected void set(FeatureAttributeDescriptor attribute, Object value) {
146
        int i = attribute.getIndex();
147

    
148
        if ( attribute.isReadOnly() ) {
149
            throw new SetReadOnlyAttributeException(attribute.getName(), this.getType());
150
        }
151
        FeatureAttributeEmulator emulator = attribute.getFeatureAttributeEmulator();
152
        if( emulator!= null ) {
153
            emulator.set((EditableFeature) this,value);
154
            return;
155
        }
156

    
157
        if ( value == null ) {
158
            if ( !attribute.allowNull() ) {
159
                if ( !attribute.isAutomatic() ) {
160
                    throw new IllegalValueException(attribute, value);
161
                }
162
            }
163
            this.data.set(i, null);
164
            return;
165

    
166
        }
167

    
168
        if ( attribute.getFeatureAttributeGetter() != null ) {
169
            value = attribute.getFeatureAttributeGetter().setter(value);
170
        }
171
        this.setforced(i, attribute, value);
172
    }
173

    
174
    private void setforced(int i, FeatureAttributeDescriptor attribute, Object value) {
175

    
176
        Class objectClass = attribute.getObjectClass();
177
        if( objectClass!=null ) {
178
            if ( objectClass.isInstance(value) ) {
179
                this.data.set(i, value);
180
                return;
181
            } else {
182
                DataProfile dataProfile = attribute.getDataProfile();
183
                if( dataProfile!=null ) {
184
                    try {
185
                        value = dataProfile.coerce(
186
                                attribute.getDataType(),
187
                                value, 
188
                                attribute.getTags()
189
                        );
190
                    } catch (CoercionException e) {
191
                        
192
                    }
193
                } 
194
                try {
195
                    value= attribute.getDataType().getCoercion().coerce(value, attribute.getCoercionContext());
196
                } catch (CoercionException e) {
197
                    throw new IllegalArgumentException("Can't convert to "
198
                            + attribute.getDataType().getName()
199
                            + " from '"
200
                            + value.getClass().getName() + "' with value '"
201
                            + value.toString() + "'.");
202
                }
203
            }
204
        }
205
        this.data.set(i, value);
206
    }
207

    
208
    private Object get(int index,Class theClass, int type) {
209
        Object value = this.get(index);
210
        if( theClass.isInstance(value) ) {
211
            return value;
212
        }
213
        try {
214
            return this.getDataTypesManager().coerce(type, value);
215
        } catch (CoercionException e) {
216

    
217
            if (value == null) {
218
                return null;
219
            }
220
            throw new IllegalArgumentException(
221
                    "Can't convert to "+theClass.getName()+
222
                    " from '"+value.getClass().getName()+
223
                    "' with value '"+value.toString()+"'.");
224
        }
225
    }
226

    
227
    public void initializeValues() {
228
        FeatureType type = this.getType();
229
        for (FeatureAttributeDescriptor attribute : type) {
230
            if (attribute.isAutomatic() || attribute.isReadOnly()
231
                    || attribute.isComputed() ) {
232
                continue;
233
            }
234
            if (attribute.getDefaultValue() == null && !attribute.allowNull()) {
235
                continue;
236
            }
237
            this.set(attribute, attribute.getDefaultValue());
238
        }
239
    }
240

    
241
    public void clear() {
242
        initializeValues();
243
    }
244

    
245
    public void initializeValues(Feature feature) {
246
        FeatureType myType=this.getType();
247
        FeatureType type =feature.getType();
248
        for (FeatureAttributeDescriptor attribute : type) {
249
            FeatureAttributeDescriptor myAttribute=myType.getAttributeDescriptor(attribute.getName());
250
            if (myAttribute != null) {
251
                this.set(myAttribute, feature.get(attribute.getIndex()));
252
            }
253
        }
254
    }
255

    
256

    
257
    @Override
258
    public FeatureStore getStore() {
259
        return (FeatureStore) this.storeRef.get();
260
    }
261

    
262
    @Override
263
    public FeatureType getType() {
264
        return this.data.getType();
265
    }
266

    
267
    @Override
268
    public EditableFeature getEditable() {
269
        return new DefaultEditableFeature(this);
270
    }
271

    
272
    @Override
273
    public Feature getCopy() {
274
        return new DefaultFeature(this);
275
    }
276

    
277
    @Override
278
    @SuppressWarnings("CloneDoesntCallSuperClone")
279
    public Object clone() throws CloneNotSupportedException {
280
        return new DefaultFeature(this);
281
    }
282

    
283
    @Override
284
    public FeatureReference getReference() {
285
        if (this.reference == null) {
286
            if (!isInserted()) {
287
                return null;
288
            }
289
            reference = new DefaultFeatureReference(this);
290
        }
291
        return this.reference;
292
    }
293

    
294
    @Override
295
    public Object getOrDefault(String name, Object defaultValue) {
296
        int index = this.data.getType().getIndex(name);
297
        if( index < 0 ) {
298
            return defaultValue;
299
        }
300
        return this.get(index);
301
    }
302

    
303
    @Override
304
    public String getStringOrDefault(String name, String defaultValue) {
305
        int index = this.data.getType().getIndex(name);
306
        if( index < 0 ) {
307
            return defaultValue;
308
        }
309
        try {
310
            return (String) this.get(index);
311
        } catch(Throwable th) {
312
            return defaultValue;
313
        }
314
    }
315

    
316
    @Override
317
    public int getIntOrDefault(String name, int defaultValue) {
318
        int index = this.data.getType().getIndex(name);
319
        if( index < 0 ) {
320
            return defaultValue;
321
        }
322
        try {
323
            return (int) this.get(index);
324
        } catch(Throwable th) {
325
            return defaultValue;
326
        }
327
    }
328

    
329
    @Override
330
    public long getLongOrDefault(String name, long defaultValue) {
331
        int index = this.data.getType().getIndex(name);
332
        if( index < 0 ) {
333
            return defaultValue;
334
        }
335
        try {
336
            return (long) this.get(index);
337
        } catch(Throwable th) {
338
            return defaultValue;
339
        }
340
    }
341

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

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

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

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

    
394
    @Override
395
    public Object getOrDefault(int index, Object defaultValue) {
396
        if( index < 0 || index >= this.data.getType().size() ) {
397
            return defaultValue;
398
        }
399
        try {
400
            return this.get(index);
401
        } catch(Throwable th) {
402
            return defaultValue;
403
        }
404
    }
405

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

    
418
    @Override
419
    public int getIntOrDefault(int index, int defaultValue) {
420
        if( index < 0 || index >= this.data.getType().size() ) {
421
            return defaultValue;
422
        }
423
        try {
424
            return (int) this.get(index);
425
        } catch(Throwable th) {
426
            return defaultValue;
427
        }
428
    }
429

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

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

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

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

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

    
490
    class UnableToGetReferenceException extends BaseRuntimeException {
491

    
492
        /**
493
         *
494
         */
495
        private static final long serialVersionUID = 1812805035204824163L;
496

    
497
        /**
498
         * @param exception
499
         */
500
        public UnableToGetReferenceException(BaseException exception) {
501
            super("Unable to get reference", "_UnableToGetReferenceException",
502
                serialVersionUID);
503
            this.initCause(exception);
504

    
505
        }
506

    
507
    }
508

    
509
    @Override
510
    public void validate(int mode) throws DataException  {
511
        ((DefaultFeatureType) this.data.getType()).validateFeature(this, mode);
512
    }
513

    
514
    @Override
515
    public List getSRSs() {
516
        // TODO Auto-generated method stub
517
        return null;
518
    }
519

    
520
    @Override
521
    public Envelope getDefaultEnvelope() {
522
        Envelope envelope = this.data.getDefaultEnvelope();
523
        if( envelope == null ) {
524
            int i = this.data.getType().getDefaultGeometryAttributeIndex();
525
            if( i<0 ) {
526
                return null;
527
            }
528
            Geometry geom = this.getDefaultGeometry();
529
            if( geom!=null ) {
530
                envelope = geom.getEnvelope();
531
            }
532
        }
533
        return envelope;
534
    }
535

    
536
    @Override
537
    public Geometry getDefaultGeometry() {
538
            Geometry geom = this.data.getDefaultGeometry();
539
        if( geom == null ) {
540
            int i = this.data.getType().getDefaultGeometryAttributeIndex();
541
            if( i<0 ) {
542
                return null;
543
            }
544
            Object x = this.get(i);
545
            if( x instanceof Geometry ) {
546
                geom = (Geometry) x;
547
            } else {
548
                geom = this.getGeometry(i);
549
            }
550
        }
551
        if( geom != null ) {
552
            if( geom.getProjection()==null ) {
553
                FeatureType type = this.getType();
554
                DefaultFeatureAttributeDescriptor attrdesc = (DefaultFeatureAttributeDescriptor) type.get(type.getDefaultGeometryAttributeIndex());
555
                IProjection proj = attrdesc.getSRS(this.storeRef);
556
                geom.setProjection(proj);
557
            }
558
        }
559
        return geom;
560
    }
561

    
562
//    @Override
563
//    public Time getDefaultTime() {
564
//            Time time = this.data.getDefaultTime();
565
//        if( time == null ) {
566
//            int i = this.data.getType().getDefaultTimeAttributeIndex();
567
//            Object x = this.get(i);
568
//            if( x instanceof Time ) {
569
//                time = (Time) x;
570
//            } else {
571
//                time = this.getTime(i);
572
//            }
573
//        }
574
//        return time;
575
//    }
576
//
577
    @Override
578
    public IProjection getDefaultSRS() {
579
        IProjection srs = this.data.getType().getDefaultSRS();
580
        if( srs == null ) {
581
            FeatureType type = this.getType();
582
            DefaultFeatureAttributeDescriptor attrdesc = (DefaultFeatureAttributeDescriptor) type.get(type.getDefaultGeometryAttributeIndex());
583
            srs = attrdesc.getSRS(this.storeRef);
584
        }
585
        return srs;
586
    }
587

    
588
    @Override
589
    public List getGeometries() {
590
        // TODO Auto-generated method stub
591
        return null;
592
    }
593

    
594
    @Override
595
    public Object getFromProfile(int index) {
596
        FeatureAttributeDescriptor descriptor = this.data.getType().getAttributeDescriptor(index);
597
        Object value = this.get(index);
598
        String profileName = descriptor.getDataProfileName();
599
        if( StringUtils.isBlank(profileName) ) {
600
            return value;
601
        }
602
        DataProfile profile = DALLocator.getDataManager().getDataProfile(profileName);
603
        if( profile==null ) {
604
            return value;
605
        }
606
        return profile.createData(value, descriptor.getTags());
607
    }
608

    
609
    @Override
610
    public Object getFromProfile(String name) {
611
        FeatureAttributeDescriptor descriptor = this.data.getType().getAttributeDescriptor(name);
612
        return this.getFromProfile(descriptor.getIndex());
613
    }
614

    
615
    @Override
616
    public Object get(String name) {
617
        int index = this.data.getType().getIndex(name);
618
        if( index < 0 ) {
619
            throw new IllegalArgumentException("Attribute name '"+name+"' not found in the feature.");
620
        }
621
        return this.get(index);
622
    }
623
    
624
    @Override
625
    public boolean isNull(int index) {
626
        FeatureType type = this.data.getType();
627
        if( index <0 || index >= type.size() ) {
628
            throw new IllegalArgumentException("Attribute index '"+index+"' out of range (0 to "+this.data.getType().size()+".");
629
        }
630
        FeatureAttributeDescriptor attribute = type.getAttributeDescriptor(index);
631
        if (!this.data.getType().hasEvaluators()) {
632
            return this.data.get(index)==null;
633
        }
634
        Evaluator eval = attribute.getEvaluator();
635
        if (eval == null) {
636
            return this.data.get(index)==null;
637
        }
638
        Object value = this.data.get(index);
639
        if (value != null) {
640
            return true;
641
        }
642
        try {
643
            value = eval.evaluate(this);
644
        } catch (EvaluatorException e) {
645
            throw new DataEvaluatorRuntimeException(e);
646
        }
647
        this.data.set(index, value);
648
        return value==null;
649
    }
650
    
651
    @Override
652
    public boolean isNull(String name) {
653
        int index = this.data.getType().getIndex(name);
654
        if( index < 0 ) {
655
            throw new IllegalArgumentException("Attribute name '"+name+"' not found in the feature.");
656
        }
657
        return this.isNull(index);
658
    }
659

    
660
    public boolean has_key(String key) {
661
        Object x = this.getType().get(key);
662
        return x != null;
663
    }
664

    
665
    public List<String> keys() {
666
        List<String> ks = new ArrayList<>();
667
        for( FeatureAttributeDescriptor attr : this.getType()) {
668
            ks.add(attr.getName());
669
        }
670
        return ks;
671
    }
672

    
673
    public Iterator<String> iterkeys() {
674
        final Iterator it = this.getType().iterator();
675
        return new Iterator<String>() {
676
            @Override
677
            public boolean hasNext() {
678
                return it.hasNext();
679
            }
680

    
681
            @Override
682
            public String next() {
683
                return ((FeatureAttributeDescriptor)it.next()).getName();
684
            }
685

    
686
            @Override
687
            public void remove() {
688
                throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
689
            }
690
        };
691
    }
692

    
693
    public Iterator iteritems() {
694
        final Iterator it = this.getType().iterator();
695
        return new Iterator<Map.Entry>() {
696
            @Override
697
            public boolean hasNext() {
698
                return it.hasNext();
699
            }
700

    
701
            @Override
702
            public Map.Entry next() {
703
                final String name = ((FeatureAttributeDescriptor)it.next()).getName();
704
                return new Map.Entry<String, Object>() {
705
                    @Override
706
                    public String getKey() {
707
                        return name;
708
                    }
709

    
710
                    @Override
711
                    public Object getValue() {
712
                        return get(name);
713
                    }
714

    
715
                    @Override
716
                    public Object setValue(Object value) {
717
                        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
718
                    }
719

    
720
                };
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
    @Override
731
    public Object get(int index) {
732
        FeatureType type = this.data.getType();
733
        if( index <0 || index >= type.size() ) {
734
            throw new IllegalArgumentException("Attribute index '"+index+"' out of range (0 to "+this.data.getType().size()+".");
735
        }
736
        FeatureAttributeDescriptor attribute = type.getAttributeDescriptor(index);
737
        if (!this.data.getType().hasEvaluators()) {
738
            return get(attribute, this.data.get(index));
739
        }
740
        Evaluator eval = attribute.getEvaluator();
741
        if (eval == null) {
742
            return this.data.get(index);
743
        } else {
744
            Object value = this.data.get(index);
745
            if (value != null) { // FIXME: para comprobar si esta calculado usar
746
                // un array
747
                // especifico.
748
                return get(attribute, this.data.get(index));
749
            }
750
            try {
751
                value = eval.evaluate(this);
752
            } catch (EvaluatorException e) {
753
                throw new DataEvaluatorRuntimeException(e);
754
            }
755
            this.data.set(index, value);
756
            return  get(attribute, value);
757
        }
758
    }
759

    
760
    private Object get(FeatureAttributeDescriptor featureAttributeDescriptor, Object value){
761
        FeatureAttributeEmulator emulator = featureAttributeDescriptor.getFeatureAttributeEmulator();
762
        if( emulator != null ) {
763
//            int index = featureAttributeDescriptor.getIndex();
764
//            value = this.data.get(index);
765
//            if( value==null ) {
766
                value = emulator.get(this);
767
//                this.data.set(index,value);
768
//            }
769
        } else {
770
            FeatureAttributeGetter getter = featureAttributeDescriptor.getFeatureAttributeGetter();
771
            if( getter != null ) {
772
                value = getter.getter(value);
773
            }
774
        }
775
        if( featureAttributeDescriptor.getType()==DataTypes.GEOMETRY ) {
776
            if( value != null ) {
777
                Geometry geom = (Geometry)value;
778
                if( geom.getProjection()==null ) {
779
                    IProjection proj = ((DefaultFeatureAttributeDescriptor)featureAttributeDescriptor).getSRS(this.storeRef);
780
                    geom.setProjection(proj);
781
                }
782
            }
783
        }
784
        return value;
785
    }
786

    
787
    @Override
788
    public byte[] getByteArray(String name) {
789
        return this.getByteArray(this.data.getType().getIndex(name));
790
    }
791

    
792
    @Override
793
    public byte[] getByteArray(int index) {
794
        return (byte[]) this.get(index);
795
    }
796

    
797
    @Override
798
    public Object[] getArray(String name) {
799
        return this.getArray(this.data.getType().getIndex(name));
800
    }
801

    
802
    @Override
803
    public Object[] getArray(int index) {
804
        return (Object[]) this.get(index);
805
    }
806

    
807
    @Override
808
    public boolean getBoolean(String name) {
809
        return this.getBoolean(this.data.getType().getIndex(name));
810
    }
811

    
812
    @Override
813
    public boolean getBoolean(int index) {
814
        Boolean value = ((Boolean) this.get(index,Boolean.class,DataTypes.BOOLEAN));
815
        if (value == null) {
816
            return false;
817
        }
818
        return value;
819
    }
820

    
821
    @Override
822
    public byte getByte(String name) {
823
        return this.getByte(this.data.getType().getIndex(name));
824
    }
825

    
826
    @Override
827
    public byte getByte(int index) {
828
        Byte value = ((Byte) this.get(index,Byte.class,DataTypes.BYTE));
829
        if (value == null) {
830
            return 0;
831
        }
832
        return value;
833
    }
834

    
835
    @Override
836
    public Date getDate(String name) {
837
        return this.getDate(this.data.getType().getIndex(name));
838
    }
839

    
840
    @Override
841
    public Date getDate(int index) {
842
        Date value = ((Date) this.get(index,java.sql.Date.class,DataTypes.DATE));
843
        return value;
844
    }
845

    
846
    @Override
847
    public Date getTime(String name) {
848
        return this.getTime(this.data.getType().getIndex(name));
849
    }
850

    
851
    @Override
852
    public Date getTime(int index) {
853
        Date value = ((Date) this.get(index,java.sql.Time.class,DataTypes.TIME));
854
        return value;
855
    }
856

    
857
    @Override
858
    public Date getTimestamp(String name) {
859
        return this.getTimestamp(this.data.getType().getIndex(name));
860
    }
861

    
862
    @Override
863
    public Date getTimestamp(int index) {
864
        Date value = ((Date) this.get(index,java.sql.Timestamp.class,DataTypes.TIMESTAMP));
865
        return value;
866
    }
867

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

    
873
    @Override
874
    public double getDouble(int index) {
875

    
876
        Double value = ((Double) this.get(index,Double.class,DataTypes.DOUBLE));
877
        if (value == null) {
878
            return 0;
879
        }
880
        return value;
881
    }
882

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

    
888
    @Override
889
    public BigDecimal getDecimal(int index) {
890

    
891
        BigDecimal value = ((BigDecimal) this.get(index,BigDecimal.class,DataTypes.DECIMAL));
892
        if (value == null) {
893
            return BigDecimal.ZERO;
894
        }
895
        return value;
896
    }
897

    
898
    @Override
899
    public Feature getFeature(String name) {
900
        return this.getFeature(this.data.getType().getIndex(name));
901
    }
902

    
903
    @Override
904
    public Feature getFeature(int index) {
905
        return (Feature) this.get(index);
906
    }
907

    
908
    @Override
909
    public float getFloat(String name) {
910
        return this.getFloat(this.data.getType().getIndex(name));
911
    }
912

    
913
    @Override
914
    public float getFloat(int index) {
915
        Float value = ((Float) this.get(index,Float.class,DataTypes.FLOAT));
916
        if (value == null) {
917
            return 0;
918
        }
919
        return value;
920
    }
921

    
922
    @Override
923
    public Geometry getGeometry(String name) {
924
        return this.getGeometry(this.data.getType().getIndex(name));
925
    }
926

    
927
    @Override
928
    public Geometry getGeometry(int index) {
929
        return (Geometry) this.get(index,Geometry.class,DataTypes.GEOMETRY);
930
    }
931

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

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

    
946
    @Override
947
    public long getLong(String name) {
948
        return this.getLong(this.data.getType().getIndex(name));
949
    }
950

    
951
    @Override
952
    public long getLong(int index) {
953
        Long value = ((Long) this.get(index,Long.class,DataTypes.LONG));
954
        if (value == null) {
955
            return 0;
956
        }
957
        return value;
958
    }
959

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

    
965
    @Override
966
    public String getString(int index) {
967
        return (String) this.get(index,String.class,DataTypes.STRING);
968
    }
969

    
970
    @Override
971
    public Object getContextValue(String name) {
972
        name = name.toLowerCase();
973
        if (name.equals("store")) {
974
            return this.getStore();
975
        }
976

    
977
        if (name.equals("featuretype")) {
978
            return this.data.getType();
979
        }
980

    
981
        if (name.equals("feature")) {
982
            return this;
983
        }
984

    
985
        throw new IllegalArgumentException(name);
986
    }
987

    
988
    @Override
989
    public Iterator getDataNames() {
990
        class DataNamesIterator implements Iterator {
991
            Iterator attributeIteraror;
992

    
993
            DataNamesIterator(DefaultFeature feature) {
994
                this.attributeIteraror = feature.getType().iterator();
995
            }
996

    
997
            @Override
998
            public boolean hasNext() {
999
                return this.attributeIteraror.hasNext();
1000
            }
1001

    
1002
            @Override
1003
            public Object next() {
1004
                return ((FeatureAttributeDescriptor) this.attributeIteraror
1005
                        .next()).getName();
1006
            }
1007

    
1008
            @Override
1009
            public void remove() {
1010
                throw new UnsupportedOperationException();
1011
            }
1012

    
1013
        }
1014
        return new DataNamesIterator(this);
1015
    }
1016

    
1017
    @Override
1018
    public Object getDataValue(String name) {
1019
        name = name.toLowerCase();
1020
        try {
1021
            return get(name);
1022
        } catch (IllegalArgumentException ex) {
1023
            if( "defaultgeometry".equalsIgnoreCase(name )) {
1024
                return this.getDefaultGeometry();
1025
            }
1026
            throw ex;
1027
        }
1028
    }
1029

    
1030
    @Override
1031
    public Iterator getDataValues() {
1032
        class DataValuesIterator implements Iterator {
1033
            DefaultFeature feature;
1034
            int current = 0;
1035

    
1036
            DataValuesIterator(DefaultFeature feature) {
1037
                this.feature = feature;
1038
            }
1039

    
1040
            @Override
1041
            public boolean hasNext() {
1042
                return current < feature.getType().size() - 1;
1043
            }
1044

    
1045
            @Override
1046
            public Object next() {
1047
                return feature.get(current++);
1048
            }
1049

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

    
1055
        }
1056
        return new DataValuesIterator(this);
1057
    }
1058

    
1059
    @Override
1060
    public boolean hasContextValue(String name) {
1061
        name = name.toLowerCase();
1062
        if (name.equals("store")) {
1063
            return true;
1064
        }
1065

    
1066
        if (name.equals("featuretype")) {
1067
            return true;
1068
        }
1069

    
1070
        return name.equals("feature");
1071
    }
1072

    
1073
    @Override
1074
    public boolean hasDataValue(String name) {
1075
        name = name.toLowerCase();
1076
        return this.data.getType().getIndex(name) >= 0;
1077
    }
1078

    
1079
//    @Override
1080
//    public Time getTime(int index) {
1081
//        return ((Time) this.get(index,Time.class,DataTypes.INSTANT));
1082
//    }
1083
//
1084
//    @Override
1085
//    public Time getTime(String name) {
1086
//        return this.getInstant(this.data.getType().getIndex(name));
1087
//    }
1088
//
1089
//    @Override
1090
//    public Instant getInstant(int index) {
1091
//        return ((Instant) this.get(index,Instant.class,DataTypes.INSTANT));
1092
//    }
1093
//
1094
//    @Override
1095
//    public Instant getInstant(String name) {
1096
//        return this.getInstant(this.data.getType().getIndex(name));
1097
//    }
1098
//
1099
//    @Override
1100
//    public Interval getInterval(int index) {
1101
//        return ((Interval) this.get(index,Interval.class,DataTypes.INTERVAL));
1102
//    }
1103
//
1104
//    @Override
1105
//    public Interval getInterval(String name) {
1106
//        return this.getInterval(this.data.getType().getIndex(name));
1107
//    }
1108
//
1109
    @Override
1110
    public DynObject getAsDynObject() {
1111
        DynObjectFeatureFacade facade = new DynObjectFeatureFacade(this);
1112
        return facade;
1113
    }
1114

    
1115
    @Override
1116
    public String toString() {
1117
            StringBuilder builder = new StringBuilder();
1118
        FeatureAttributeDescriptor[] attributeDescriptors =
1119
            getType().getAttributeDescriptors();
1120
        for (int i = 0; i < attributeDescriptors.length; i++) {
1121
            String name = attributeDescriptors[i].getName();
1122
            Object value = get(name);
1123
            builder.append(value);
1124
            if (i < attributeDescriptors.length - 1) {
1125
                builder.append(", ");
1126
            }
1127
        }
1128
        return builder.toString();
1129
    }
1130

    
1131

    
1132

    
1133

    
1134
        /**
1135
     * @return the inserted
1136
     */
1137
    public boolean isInserted() {
1138
        return inserted;
1139
    }
1140

    
1141

    
1142
    /**
1143
     * @param inserted the inserted to set
1144
     */
1145
    public void setInserted(boolean inserted) {
1146
        this.inserted = inserted;
1147
    }
1148

    
1149
        @Override
1150
    public EvaluatorData getEvaluatorData() {
1151
        return this;
1152
    }
1153

    
1154
    public int size() {
1155
        return this.data.getType().size();
1156
    }
1157
    
1158
    public boolean isEmpty() {
1159
        return false;
1160
    }
1161

    
1162
    public Iterator<String> iterator() {
1163
        final Iterator<FeatureAttributeDescriptor> x = this.data.getType().iterator();
1164
        return new Iterator<String>() {
1165
            @Override
1166
            public boolean hasNext() {
1167
                return x.hasNext();
1168
            }
1169

    
1170
            @Override
1171
            public String next() {
1172
                return x.next().getName();
1173
            }
1174
        };
1175
    }
1176
    
1177
    public boolean containsKey(String key) {
1178
        return this.data.getType().get(key)!=null;
1179
    }
1180

    
1181
    @Override
1182
    public String getLabelOfValue(String name) {
1183
        FeatureAttributeDescriptor attrdesc = this.data.getType().getAttributeDescriptor(name);
1184
        if( attrdesc==null ) {
1185
            throw new IllegalArgumentException("Attribute name '"+name+"' not found in the feature.");
1186
        }
1187
        Object value = this.get(attrdesc.getIndex());
1188
        String label = attrdesc.getLabelOfValue(value);
1189
        return label;
1190
    }
1191

    
1192
    @Override
1193
    public Object getExtraValue(String name) {
1194
        return this.data.getExtraValue(name);
1195
    }
1196

    
1197
    public boolean hasExtraValue(String name) {
1198
        return this.data.hasExtraValue(name);
1199
    }
1200
    
1201
    @Override
1202
    public Object getExtraValue(int index) {
1203
        return this.data.getExtraValue(index);
1204
    }
1205

    
1206
    public JsonObject toJSON() {
1207
        JsonObjectBuilder builder = Json.createObjectBuilder();
1208
        
1209
        FeatureType ft = this.getType();
1210
        for (FeatureAttributeDescriptor desc : ft) {
1211
            if (desc.isComputed()) {
1212
                continue;
1213
            }
1214
            switch(desc.getType()) {
1215
                case DataTypes.GEOMETRY:
1216
                    {
1217
                        try {
1218
                            builder.add(desc.getName(), this.getGeometry(desc.getIndex()).convertToWKT());
1219
                        } catch (Exception ex) {
1220
                            throw new RuntimeException("Can't convert geometry to WKT.", ex);
1221
                        }
1222
                    }
1223
                    break;
1224
                case DataTypes.BOOLEAN:
1225
                    builder.add(desc.getName(), this.getBoolean(desc.getIndex()));
1226
                    break;
1227
                case DataTypes.BYTE:
1228
                    builder.add(desc.getName(), this.getByte(desc.getIndex()));
1229
                    break;
1230
                case DataTypes.INT:
1231
                    builder.add(desc.getName(), this.getInt(desc.getIndex()));
1232
                    break;
1233
                case DataTypes.LONG:
1234
                    builder.add(desc.getName(), this.getLong(desc.getIndex()));
1235
                    break;
1236
                case DataTypes.DOUBLE:
1237
                    builder.add(desc.getName(), this.getDouble(desc.getIndex()));
1238
                    break;
1239
                case DataTypes.FLOAT:
1240
                    builder.add(desc.getName(), this.getFloat(desc.getIndex()));
1241
                    break;
1242
                case DataTypes.DATE:
1243
                    // Format date as ISO 8601
1244
                    Date date = this.getDate(desc.getIndex());
1245
                    String value = DateTimeFormatter.ISO_DATE_TIME.format(date.toInstant());
1246
                    builder.add(desc.getName(), value);
1247
                    break;
1248
                default:
1249
                    builder.add(desc.getName(), Objects.toString(this.get(desc.getIndex()),""));
1250
            }
1251
        }        
1252
        return builder.build();
1253
    }
1254

    
1255
}