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

History | View | Annotate | Download (36.9 KB)

1 40559 jjdelcerro
/**
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 40435 jjdelcerro
package org.gvsig.fmap.dal.feature.impl;
25
26
import java.lang.ref.WeakReference;
27 44669 jjdelcerro
import java.math.BigDecimal;
28 44655 jjdelcerro
import java.time.format.DateTimeFormatter;
29 43550 jjdelcerro
import java.util.ArrayList;
30 40435 jjdelcerro
import java.util.Date;
31
import java.util.Iterator;
32
import java.util.List;
33 43550 jjdelcerro
import java.util.Map;
34 44655 jjdelcerro
import java.util.Objects;
35
import javax.json.Json;
36
import javax.json.JsonObject;
37
import javax.json.JsonObjectBuilder;
38 44128 jjdelcerro
import org.apache.commons.lang3.StringUtils;
39 40435 jjdelcerro
import org.cresques.cts.IProjection;
40 44128 jjdelcerro
import org.gvsig.fmap.dal.DALLocator;
41 40435 jjdelcerro
import org.gvsig.fmap.dal.DataTypes;
42
import org.gvsig.fmap.dal.exception.DataEvaluatorRuntimeException;
43
import org.gvsig.fmap.dal.exception.DataException;
44 44128 jjdelcerro
import org.gvsig.fmap.dal.feature.DataProfile;
45 40435 jjdelcerro
import org.gvsig.fmap.dal.feature.EditableFeature;
46
import org.gvsig.fmap.dal.feature.Feature;
47
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
48 41335 jjdelcerro
import org.gvsig.fmap.dal.feature.FeatureAttributeEmulator;
49
import org.gvsig.fmap.dal.feature.FeatureAttributeGetter;
50 40435 jjdelcerro
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 42775 jjdelcerro
import org.gvsig.fmap.dal.feature.impl.dynobjectutils.DynObjectFeatureFacade;
56 43729 fdiaz
import org.gvsig.fmap.dal.feature.spi.DefaultFeatureProvider;
57 40435 jjdelcerro
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.timesupport.Instant;
61
import org.gvsig.timesupport.Interval;
62 44086 jjdelcerro
import org.gvsig.timesupport.Time;
63 40435 jjdelcerro
import org.gvsig.tools.ToolsLocator;
64
import org.gvsig.tools.dataTypes.CoercionException;
65
import org.gvsig.tools.dataTypes.DataTypesManager;
66
import org.gvsig.tools.dynobject.DynObject;
67
import org.gvsig.tools.evaluator.Evaluator;
68
import org.gvsig.tools.evaluator.EvaluatorData;
69
import org.gvsig.tools.evaluator.EvaluatorException;
70
import org.gvsig.tools.exception.BaseException;
71
import org.gvsig.tools.exception.BaseRuntimeException;
72 40876 jjdelcerro
import org.gvsig.tools.lang.Cloneable;
73 40435 jjdelcerro
74 40876 jjdelcerro
public class DefaultFeature implements Feature, EvaluatorData, Cloneable {
75 40435 jjdelcerro
76 43729 fdiaz
        private static DataTypesManager dataTypesManager = null;
77 40435 jjdelcerro
        protected FeatureProvider data;
78
        protected FeatureReference reference;
79
        private WeakReference storeRef;
80 43729 fdiaz
81 40435 jjdelcerro
        private boolean inserted = false;
82
83
    /*
84
         * Usar con mucha precaucion o mejor no usar. Lo precisa el
85
         * DefaultFeatureSet en la ordenacion.
86
         */
87
        public DefaultFeature(FeatureStore store) {
88
                this.storeRef = new WeakReference(store);
89
                this.reference = null;
90
        }
91
92
        public DefaultFeature(FeatureStore store, FeatureProvider data) {
93
                this.data = data;
94
                this.storeRef = new WeakReference(store);
95
                this.reference = null;
96
                this.inserted = !data.isNew();
97
        }
98
99
        DefaultFeature(DefaultFeature feature) {
100
                this.data = feature.data.getCopy();
101
                this.storeRef = feature.storeRef;
102
                this.reference = feature.reference;
103
                this.inserted = feature.isInserted();
104
        }
105
106 43729 fdiaz
    public DefaultFeature(FeatureType targetType, Feature sourceFeature) {
107
        DefaultFeature defaultFeature = (DefaultFeature)sourceFeature;
108
        this.data = new DefaultFeatureProvider(targetType, (DefaultFeatureProvider)defaultFeature.getData());
109
        this.storeRef = defaultFeature.storeRef;
110
        this.reference = defaultFeature.reference;
111
        this.inserted = defaultFeature.isInserted();
112
113
        FeatureType sourceType = sourceFeature.getType();
114
115
        for (FeatureAttributeDescriptor targetAttrDescriptor : targetType) {
116 44641 jjdelcerro
            if ( targetAttrDescriptor.isComputed() ) {
117 43729 fdiaz
                 continue;
118
            }
119
            int sourceIndex = sourceType.getIndex(targetAttrDescriptor.getName());
120
            if (sourceIndex<0){
121
                continue;
122
            }
123
            Object value = sourceFeature.get(sourceIndex);
124
            if (value == null && !targetAttrDescriptor.allowNull()) {
125
                continue;
126
            }
127 44641 jjdelcerro
            this.setforced(targetAttrDescriptor.getIndex(), targetAttrDescriptor,value);
128 43729 fdiaz
        }
129
    }
130
131 40435 jjdelcerro
        public void setData(FeatureProvider data) {
132
                this.data = data;
133
                this.reference = null;
134 43729 fdiaz
                this.inserted = true;
135 40435 jjdelcerro
        }
136
137
        public FeatureProvider getData() {
138
                return this.data;
139
        }
140
141
        protected DataTypesManager getDataTypesManager() {
142
                if( dataTypesManager==null ) {
143
                        dataTypesManager = ToolsLocator.getDataTypesManager();
144
                }
145
                return dataTypesManager;
146
        }
147
148 44641 jjdelcerro
    protected void set(FeatureAttributeDescriptor attribute, Object value) {
149 41335 jjdelcerro
        int i = attribute.getIndex();
150 40435 jjdelcerro
151 41335 jjdelcerro
        if ( attribute.isReadOnly() ) {
152 41823 jjdelcerro
            throw new SetReadOnlyAttributeException(attribute.getName(), this.getType());
153 41335 jjdelcerro
        }
154
        FeatureAttributeEmulator emulator = attribute.getFeatureAttributeEmulator();
155
        if( emulator!= null ) {
156
            emulator.set((EditableFeature) this,value);
157
            return;
158
        }
159 43729 fdiaz
160 41335 jjdelcerro
        if ( value == null ) {
161
            if ( !attribute.allowNull() ) {
162
                if ( !attribute.isAutomatic() ) {
163
                    throw new IllegalValueException(attribute, value);
164
                }
165
            }
166
            this.data.set(i, null);
167
            return;
168 40435 jjdelcerro
169 41335 jjdelcerro
        }
170 40435 jjdelcerro
171 41335 jjdelcerro
        if ( attribute.getFeatureAttributeGetter() != null ) {
172
            value = attribute.getFeatureAttributeGetter().setter(value);
173 40435 jjdelcerro
        }
174 44641 jjdelcerro
        this.setforced(i, attribute, value);
175
    }
176 41335 jjdelcerro
177 44641 jjdelcerro
    private void setforced(int i, FeatureAttributeDescriptor attribute, Object value) {
178
179 42218 jjdelcerro
        Class objectClass = attribute.getObjectClass();
180
        if( objectClass!=null ) {
181
            if ( objectClass.isInstance(value) ) {
182
                this.data.set(i, value);
183
                return;
184 44448 jjdelcerro
            } else {
185
                DataProfile dataProfile = attribute.getDataProfile();
186
                if( dataProfile!=null ) {
187
                    try {
188
                        value = dataProfile.coerce(
189
                                attribute.getDataType(),
190
                                value,
191
                                attribute.getTags()
192
                        );
193
                    } catch (CoercionException e) {
194
195
                    }
196
                }
197 42218 jjdelcerro
                try {
198 44670 omartinez
                    value= attribute.getDataType().getCoercion().coerce(value, attribute.getCoercionContext());
199 42218 jjdelcerro
                } catch (CoercionException e) {
200
                    throw new IllegalArgumentException("Can't convert to "
201 44448 jjdelcerro
                            + attribute.getDataType().getName()
202
                            + " from '"
203 42218 jjdelcerro
                            + value.getClass().getName() + "' with value '"
204
                            + value.toString() + "'.");
205
                }
206 40435 jjdelcerro
            }
207 41335 jjdelcerro
        }
208 40435 jjdelcerro
        this.data.set(i, value);
209
    }
210 43729 fdiaz
211 40435 jjdelcerro
    private Object get(int index,Class theClass, int type) {
212
        Object value = this.get(index);
213
        if( theClass.isInstance(value) ) {
214
            return value;
215
        }
216
        try {
217
            return this.getDataTypesManager().coerce(type, value);
218
        } catch (CoercionException e) {
219 43729 fdiaz
220 40435 jjdelcerro
            if (value == null) {
221
                return null;
222
            }
223
            throw new IllegalArgumentException(
224
                    "Can't convert to "+theClass.getName()+
225
                    " from '"+value.getClass().getName()+
226
                    "' with value '"+value.toString()+"'.");
227
        }
228
    }
229 43729 fdiaz
230 40435 jjdelcerro
    public void initializeValues() {
231
        FeatureType type = this.getType();
232 44297 jjdelcerro
        for (FeatureAttributeDescriptor attribute : type) {
233 40435 jjdelcerro
            if (attribute.isAutomatic() || attribute.isReadOnly()
234 44203 jjdelcerro
                    || attribute.isComputed() ) {
235 40435 jjdelcerro
                continue;
236
            }
237
            if (attribute.getDefaultValue() == null && !attribute.allowNull()) {
238
                continue;
239
            }
240
            this.set(attribute, attribute.getDefaultValue());
241
        }
242
    }
243
244
    public void clear() {
245
        initializeValues();
246
    }
247
248
    public void initializeValues(Feature feature) {
249
        FeatureType myType=this.getType();
250
        FeatureType type =feature.getType();
251 44297 jjdelcerro
        for (FeatureAttributeDescriptor attribute : type) {
252 40435 jjdelcerro
            FeatureAttributeDescriptor myAttribute=myType.getAttributeDescriptor(attribute.getName());
253
            if (myAttribute != null) {
254
                this.set(myAttribute, feature.get(attribute.getIndex()));
255
            }
256
        }
257
    }
258
259
260 44297 jjdelcerro
    @Override
261 40435 jjdelcerro
    public FeatureStore getStore() {
262
        return (FeatureStore) this.storeRef.get();
263
    }
264
265 44297 jjdelcerro
    @Override
266 40435 jjdelcerro
    public FeatureType getType() {
267
        return this.data.getType();
268
    }
269
270 44297 jjdelcerro
    @Override
271 40435 jjdelcerro
    public EditableFeature getEditable() {
272
        return new DefaultEditableFeature(this);
273
    }
274
275 44297 jjdelcerro
    @Override
276 40435 jjdelcerro
    public Feature getCopy() {
277
        return new DefaultFeature(this);
278
    }
279 43729 fdiaz
280 44297 jjdelcerro
    @Override
281
    @SuppressWarnings("CloneDoesntCallSuperClone")
282 40876 jjdelcerro
    public Object clone() throws CloneNotSupportedException {
283
        return new DefaultFeature(this);
284
    }
285 40435 jjdelcerro
286 44297 jjdelcerro
    @Override
287 40435 jjdelcerro
    public FeatureReference getReference() {
288
        if (this.reference == null) {
289
            if (!isInserted()) {
290
                return null;
291
            }
292
            reference = new DefaultFeatureReference(this);
293
        }
294
        return this.reference;
295
    }
296
297 44331 jjdelcerro
    @Override
298
    public Object getOrDefault(String name, Object defaultValue) {
299
        int index = this.data.getType().getIndex(name);
300
        if( index < 0 ) {
301
            return defaultValue;
302
        }
303
        return this.get(index);
304
    }
305
306
    @Override
307
    public String getStringOrDefault(String name, String defaultValue) {
308
        int index = this.data.getType().getIndex(name);
309
        if( index < 0 ) {
310
            return defaultValue;
311
        }
312
        try {
313
            return (String) this.get(index);
314
        } catch(Throwable th) {
315
            return defaultValue;
316
        }
317
    }
318
319
    @Override
320
    public int getIntOrDefault(String name, int defaultValue) {
321
        int index = this.data.getType().getIndex(name);
322
        if( index < 0 ) {
323
            return defaultValue;
324
        }
325
        try {
326
            return (int) this.get(index);
327
        } catch(Throwable th) {
328
            return defaultValue;
329
        }
330
    }
331
332
    @Override
333
    public long getLongOrDefault(String name, long defaultValue) {
334
        int index = this.data.getType().getIndex(name);
335
        if( index < 0 ) {
336
            return defaultValue;
337
        }
338
        try {
339
            return (long) this.get(index);
340
        } catch(Throwable th) {
341
            return defaultValue;
342
        }
343
    }
344
345
    @Override
346
    public float getFloatOrDefault(String name, float defaultValue) {
347
        int index = this.data.getType().getIndex(name);
348
        if( index < 0 ) {
349
            return defaultValue;
350
        }
351
        try {
352
            return (float) this.get(index);
353
        } catch(Throwable th) {
354
            return defaultValue;
355
        }
356
    }
357
358
    @Override
359
    public double getDoubleOrDefault(String name, double defaultValue) {
360
        int index = this.data.getType().getIndex(name);
361
        if( index < 0 ) {
362
            return defaultValue;
363
        }
364
        try {
365
            return (double) this.get(index);
366
        } catch(Throwable th) {
367
            return defaultValue;
368
        }
369
    }
370
371
    @Override
372 44669 jjdelcerro
    public BigDecimal getDecimalOrDefault(String name, BigDecimal defaultValue) {
373
        int index = this.data.getType().getIndex(name);
374
        if( index < 0 ) {
375
            return defaultValue;
376
        }
377
        try {
378
            return (BigDecimal) this.get(index);
379
        } catch(Throwable th) {
380
            return defaultValue;
381
        }
382
    }
383
384
    @Override
385 44331 jjdelcerro
    public Date getDateOrDefault(String name, Date defaultValue) {
386
        int index = this.data.getType().getIndex(name);
387
        if( index < 0 ) {
388
            return defaultValue;
389
        }
390
        try {
391
            return (Date) this.get(index);
392
        } catch(Throwable th) {
393
            return defaultValue;
394
        }
395
    }
396
397
    @Override
398
    public Object getOrDefault(int index, Object defaultValue) {
399
        if( index < 0 || index >= this.data.getType().size() ) {
400
            return defaultValue;
401
        }
402
        try {
403
            return this.get(index);
404
        } catch(Throwable th) {
405
            return defaultValue;
406
        }
407
    }
408
409
    @Override
410
    public String getStringOrDefault(int index, String defaultValue) {
411
        if( index < 0 || index >= this.data.getType().size() ) {
412
            return defaultValue;
413
        }
414
        try {
415
            return (String) this.get(index);
416
        } catch(Throwable th) {
417
            return defaultValue;
418
        }
419
    }
420
421
    @Override
422
    public int getIntOrDefault(int index, int defaultValue) {
423
        if( index < 0 || index >= this.data.getType().size() ) {
424
            return defaultValue;
425
        }
426
        try {
427
            return (int) this.get(index);
428
        } catch(Throwable th) {
429
            return defaultValue;
430
        }
431
    }
432
433
    @Override
434
    public long getLongOrDefault(int index, long defaultValue) {
435
        if( index < 0 || index >= this.data.getType().size() ) {
436
            return defaultValue;
437
        }
438
        try {
439
            return (long) this.get(index);
440
        } catch(Throwable th) {
441
            return defaultValue;
442
        }
443
    }
444
445
    @Override
446
    public float getFloatOrDefault(int index, float defaultValue) {
447
        if( index < 0 || index >= this.data.getType().size() ) {
448
            return defaultValue;
449
        }
450
        try {
451
            return (float) this.get(index);
452
        } catch(Throwable th) {
453
            return defaultValue;
454
        }
455
    }
456
457
    @Override
458
    public double getDoubleOrDefault(int index, double defaultValue) {
459
        if( index < 0 || index >= this.data.getType().size() ) {
460
            return defaultValue;
461
        }
462
        try {
463
            return (double) this.get(index);
464
        } catch(Throwable th) {
465
            return defaultValue;
466
        }
467
    }
468
469
    @Override
470 44669 jjdelcerro
    public BigDecimal getDecimalOrDefault(int index, BigDecimal defaultValue) {
471
        if( index < 0 || index >= this.data.getType().size() ) {
472
            return defaultValue;
473
        }
474
        try {
475
            return (BigDecimal) this.get(index);
476
        } catch(Throwable th) {
477
            return defaultValue;
478
        }
479
    }
480
481
    @Override
482 44331 jjdelcerro
    public Date getDateOrDefault(int index, Date defaultValue) {
483
        if( index < 0 || index >= this.data.getType().size() ) {
484
            return defaultValue;
485
        }
486
        try {
487
            return (Date) this.get(index);
488
        } catch(Throwable th) {
489
            return defaultValue;
490
        }
491
    }
492
493 40435 jjdelcerro
    class UnableToGetReferenceException extends BaseRuntimeException {
494
495
        /**
496 43729 fdiaz
         *
497 40435 jjdelcerro
         */
498
        private static final long serialVersionUID = 1812805035204824163L;
499
500
        /**
501
         * @param exception
502
         */
503
        public UnableToGetReferenceException(BaseException exception) {
504
            super("Unable to get reference", "_UnableToGetReferenceException",
505
                serialVersionUID);
506
            this.initCause(exception);
507 43729 fdiaz
508 40435 jjdelcerro
        }
509 43729 fdiaz
510 40435 jjdelcerro
    }
511 43729 fdiaz
512 44297 jjdelcerro
    @Override
513 41251 jjdelcerro
    public void validate(int mode) throws DataException  {
514 40435 jjdelcerro
        ((DefaultFeatureType) this.data.getType()).validateFeature(this, mode);
515
    }
516
517 44297 jjdelcerro
    @Override
518 40435 jjdelcerro
    public List getSRSs() {
519
        // TODO Auto-generated method stub
520
        return null;
521
    }
522
523 44297 jjdelcerro
    @Override
524 40435 jjdelcerro
    public Envelope getDefaultEnvelope() {
525 41342 jjdelcerro
        Envelope envelope = this.data.getDefaultEnvelope();
526
        if( envelope == null ) {
527 44618 jjdelcerro
            int i = this.data.getType().getDefaultGeometryAttributeIndex();
528
            if( i<0 ) {
529
                return null;
530
            }
531 41342 jjdelcerro
            Geometry geom = this.getDefaultGeometry();
532 41348 jjdelcerro
            if( geom!=null ) {
533
                envelope = geom.getEnvelope();
534
            }
535 41342 jjdelcerro
        }
536
        return envelope;
537 40435 jjdelcerro
    }
538
539 44022 jjdelcerro
    @Override
540 40435 jjdelcerro
    public Geometry getDefaultGeometry() {
541 41058 jjdelcerro
            Geometry geom = this.data.getDefaultGeometry();
542 44022 jjdelcerro
        if( geom == null ) {
543
            int i = this.data.getType().getDefaultGeometryAttributeIndex();
544 44618 jjdelcerro
            if( i<0 ) {
545
                return null;
546
            }
547 44022 jjdelcerro
            Object x = this.get(i);
548
            if( x instanceof Geometry ) {
549
                geom = (Geometry) x;
550
            } else {
551
                geom = this.getGeometry(i);
552
            }
553 43420 jjdelcerro
        }
554 44022 jjdelcerro
        if( geom != null ) {
555
            if( geom.getProjection()==null ) {
556
                FeatureType type = this.getType();
557
                DefaultFeatureAttributeDescriptor attrdesc = (DefaultFeatureAttributeDescriptor) type.get(type.getDefaultGeometryAttributeIndex());
558
                IProjection proj = attrdesc.getSRS(this.storeRef);
559
                geom.setProjection(proj);
560
            }
561
        }
562
        return geom;
563 40435 jjdelcerro
    }
564
565 44086 jjdelcerro
    @Override
566
    public Time getDefaultTime() {
567
            Time time = this.data.getDefaultTime();
568
        if( time == null ) {
569
            int i = this.data.getType().getDefaultTimeAttributeIndex();
570
            Object x = this.get(i);
571
            if( x instanceof Time ) {
572
                time = (Time) x;
573
            } else {
574
                time = this.getTime(i);
575
            }
576
        }
577
        return time;
578
    }
579
580 44297 jjdelcerro
    @Override
581 40435 jjdelcerro
    public IProjection getDefaultSRS() {
582 44022 jjdelcerro
        IProjection srs = this.data.getType().getDefaultSRS();
583
        if( srs == null ) {
584
            FeatureType type = this.getType();
585
            DefaultFeatureAttributeDescriptor attrdesc = (DefaultFeatureAttributeDescriptor) type.get(type.getDefaultGeometryAttributeIndex());
586
            srs = attrdesc.getSRS(this.storeRef);
587
        }
588
        return srs;
589 40435 jjdelcerro
    }
590
591 44297 jjdelcerro
    @Override
592 40435 jjdelcerro
    public List getGeometries() {
593
        // TODO Auto-generated method stub
594
        return null;
595
    }
596
597 44128 jjdelcerro
    @Override
598
    public Object getFromProfile(int index) {
599
        FeatureAttributeDescriptor descriptor = this.data.getType().getAttributeDescriptor(index);
600
        Object value = this.get(index);
601
        String profileName = descriptor.getDataProfileName();
602
        if( StringUtils.isBlank(profileName) ) {
603
            return value;
604
        }
605
        DataProfile profile = DALLocator.getDataManager().getDataProfile(profileName);
606
        if( profile==null ) {
607
            return value;
608
        }
609 44253 jjdelcerro
        return profile.createData(value, descriptor.getTags());
610 44128 jjdelcerro
    }
611
612
    @Override
613
    public Object getFromProfile(String name) {
614
        FeatureAttributeDescriptor descriptor = this.data.getType().getAttributeDescriptor(name);
615
        return this.getFromProfile(descriptor.getIndex());
616
    }
617
618 44297 jjdelcerro
    @Override
619 40435 jjdelcerro
    public Object get(String name) {
620
        int index = this.data.getType().getIndex(name);
621
        if( index < 0 ) {
622
            throw new IllegalArgumentException("Attribute name '"+name+"' not found in the feature.");
623
        }
624
        return this.get(index);
625
    }
626 44669 jjdelcerro
627
    @Override
628
    public boolean isNull(int index) {
629
        FeatureType type = this.data.getType();
630
        if( index <0 || index >= type.size() ) {
631
            throw new IllegalArgumentException("Attribute index '"+index+"' out of range (0 to "+this.data.getType().size()+".");
632
        }
633
        FeatureAttributeDescriptor attribute = type.getAttributeDescriptor(index);
634
        if (!this.data.getType().hasEvaluators()) {
635
            return this.data.get(index)==null;
636
        }
637
        Evaluator eval = attribute.getEvaluator();
638
        if (eval == null) {
639
            return this.data.get(index)==null;
640
        }
641
        Object value = this.data.get(index);
642
        if (value != null) {
643
            return true;
644
        }
645
        try {
646
            value = eval.evaluate(this);
647
        } catch (EvaluatorException e) {
648
            throw new DataEvaluatorRuntimeException(e);
649
        }
650
        this.data.set(index, value);
651
        return value==null;
652
    }
653
654
    @Override
655
    public boolean isNull(String name) {
656
        int index = this.data.getType().getIndex(name);
657
        if( index < 0 ) {
658
            throw new IllegalArgumentException("Attribute name '"+name+"' not found in the feature.");
659
        }
660
        return this.isNull(index);
661
    }
662 43729 fdiaz
663 43550 jjdelcerro
    public boolean has_key(String key) {
664
        Object x = this.getType().get(key);
665
        return x != null;
666
    }
667 43729 fdiaz
668 43550 jjdelcerro
    public List<String> keys() {
669
        List<String> ks = new ArrayList<>();
670
        for( FeatureAttributeDescriptor attr : this.getType()) {
671
            ks.add(attr.getName());
672
        }
673
        return ks;
674
    }
675 43729 fdiaz
676 43550 jjdelcerro
    public Iterator<String> iterkeys() {
677
        final Iterator it = this.getType().iterator();
678
        return new Iterator<String>() {
679
            @Override
680
            public boolean hasNext() {
681
                return it.hasNext();
682
            }
683 40435 jjdelcerro
684 43550 jjdelcerro
            @Override
685
            public String next() {
686
                return ((FeatureAttributeDescriptor)it.next()).getName();
687
            }
688 43561 jjdelcerro
689
            @Override
690
            public void remove() {
691
                throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
692
            }
693 43550 jjdelcerro
        };
694
    }
695 40435 jjdelcerro
696 43550 jjdelcerro
    public Iterator iteritems() {
697
        final Iterator it = this.getType().iterator();
698
        return new Iterator<Map.Entry>() {
699
            @Override
700
            public boolean hasNext() {
701
                return it.hasNext();
702
            }
703
704
            @Override
705
            public Map.Entry next() {
706
                final String name = ((FeatureAttributeDescriptor)it.next()).getName();
707
                return new Map.Entry<String, Object>() {
708
                    @Override
709
                    public String getKey() {
710
                        return name;
711
                    }
712
713
                    @Override
714
                    public Object getValue() {
715
                        return get(name);
716
                    }
717
718
                    @Override
719
                    public Object setValue(Object value) {
720
                        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
721
                    }
722 43729 fdiaz
723 43550 jjdelcerro
                };
724
            }
725 43561 jjdelcerro
726
            @Override
727
            public void remove() {
728
                throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
729
            }
730 43729 fdiaz
        };
731 43550 jjdelcerro
    }
732
733
    @Override
734 40435 jjdelcerro
    public Object get(int index) {
735
        FeatureType type = this.data.getType();
736
        if( index <0 || index >= type.size() ) {
737
            throw new IllegalArgumentException("Attribute index '"+index+"' out of range (0 to "+this.data.getType().size()+".");
738
        }
739
        FeatureAttributeDescriptor attribute = type.getAttributeDescriptor(index);
740
        if (!this.data.getType().hasEvaluators()) {
741 43729 fdiaz
            return get(attribute, this.data.get(index));
742
        }
743 40435 jjdelcerro
        Evaluator eval = attribute.getEvaluator();
744
        if (eval == null) {
745
            return this.data.get(index);
746
        } else {
747
            Object value = this.data.get(index);
748
            if (value != null) { // FIXME: para comprobar si esta calculado usar
749
                // un array
750
                // especifico.
751
                return get(attribute, this.data.get(index));
752
            }
753
            try {
754
                value = eval.evaluate(this);
755
            } catch (EvaluatorException e) {
756
                throw new DataEvaluatorRuntimeException(e);
757
            }
758
            this.data.set(index, value);
759
            return  get(attribute, value);
760 43729 fdiaz
        }
761 40435 jjdelcerro
    }
762
763
    private Object get(FeatureAttributeDescriptor featureAttributeDescriptor, Object value){
764 41335 jjdelcerro
        FeatureAttributeEmulator emulator = featureAttributeDescriptor.getFeatureAttributeEmulator();
765
        if( emulator != null ) {
766 44226 jjdelcerro
//            int index = featureAttributeDescriptor.getIndex();
767
//            value = this.data.get(index);
768
//            if( value==null ) {
769 44203 jjdelcerro
                value = emulator.get(this);
770 44226 jjdelcerro
//                this.data.set(index,value);
771
//            }
772 44022 jjdelcerro
        } else {
773
            FeatureAttributeGetter getter = featureAttributeDescriptor.getFeatureAttributeGetter();
774
            if( getter != null ) {
775
                value = getter.getter(value);
776
            }
777 40435 jjdelcerro
        }
778 44022 jjdelcerro
        if( featureAttributeDescriptor.getType()==DataTypes.GEOMETRY ) {
779
            if( value != null ) {
780
                Geometry geom = (Geometry)value;
781
                if( geom.getProjection()==null ) {
782
                    IProjection proj = ((DefaultFeatureAttributeDescriptor)featureAttributeDescriptor).getSRS(this.storeRef);
783
                    geom.setProjection(proj);
784
                }
785
            }
786 41335 jjdelcerro
        }
787
        return value;
788 40435 jjdelcerro
    }
789
790 44297 jjdelcerro
    @Override
791
    public byte[] getByteArray(String name) {
792
        return this.getByteArray(this.data.getType().getIndex(name));
793
    }
794
795
    @Override
796
    public byte[] getByteArray(int index) {
797
        return (byte[]) this.get(index);
798
    }
799
800
    @Override
801 40435 jjdelcerro
    public Object[] getArray(String name) {
802
        return this.getArray(this.data.getType().getIndex(name));
803
    }
804
805 44297 jjdelcerro
    @Override
806 40435 jjdelcerro
    public Object[] getArray(int index) {
807
        return (Object[]) this.get(index);
808
    }
809
810 44297 jjdelcerro
    @Override
811 40435 jjdelcerro
    public boolean getBoolean(String name) {
812
        return this.getBoolean(this.data.getType().getIndex(name));
813
    }
814
815 44297 jjdelcerro
    @Override
816 40435 jjdelcerro
    public boolean getBoolean(int index) {
817
        Boolean value = ((Boolean) this.get(index,Boolean.class,DataTypes.BOOLEAN));
818
        if (value == null) {
819
            return false;
820
        }
821 44297 jjdelcerro
        return value;
822 40435 jjdelcerro
    }
823
824 44297 jjdelcerro
    @Override
825 40435 jjdelcerro
    public byte getByte(String name) {
826
        return this.getByte(this.data.getType().getIndex(name));
827
    }
828
829 44297 jjdelcerro
    @Override
830 40435 jjdelcerro
    public byte getByte(int index) {
831
        Byte value = ((Byte) this.get(index,Byte.class,DataTypes.BYTE));
832
        if (value == null) {
833
            return 0;
834
        }
835 44297 jjdelcerro
        return value;
836 40435 jjdelcerro
    }
837
838 44297 jjdelcerro
    @Override
839 40435 jjdelcerro
    public Date getDate(String name) {
840
        return this.getDate(this.data.getType().getIndex(name));
841
    }
842
843 44297 jjdelcerro
    @Override
844 40435 jjdelcerro
    public Date getDate(int index) {
845
        Date value = ((Date) this.get(index,Date.class,DataTypes.DATE));
846
847
        return value;
848
    }
849
850 44297 jjdelcerro
    @Override
851 40435 jjdelcerro
    public double getDouble(String name) {
852
        return this.getDouble(this.data.getType().getIndex(name));
853
    }
854
855 44297 jjdelcerro
    @Override
856 40435 jjdelcerro
    public double getDouble(int index) {
857 43729 fdiaz
858 40435 jjdelcerro
        Double value = ((Double) this.get(index,Double.class,DataTypes.DOUBLE));
859
        if (value == null) {
860
            return 0;
861
        }
862 44297 jjdelcerro
        return value;
863 40435 jjdelcerro
    }
864
865 44297 jjdelcerro
    @Override
866 44669 jjdelcerro
    public BigDecimal getDecimal(String name) {
867
        return this.getDecimal(this.data.getType().getIndex(name));
868
    }
869
870
    @Override
871
    public BigDecimal getDecimal(int index) {
872
873
        BigDecimal value = ((BigDecimal) this.get(index,BigDecimal.class,DataTypes.DECIMAL));
874
        if (value == null) {
875
            return BigDecimal.ZERO;
876
        }
877
        return value;
878
    }
879
880
    @Override
881 40435 jjdelcerro
    public Feature getFeature(String name) {
882
        return this.getFeature(this.data.getType().getIndex(name));
883
    }
884
885 44297 jjdelcerro
    @Override
886 40435 jjdelcerro
    public Feature getFeature(int index) {
887
        return (Feature) this.get(index);
888
    }
889
890 44297 jjdelcerro
    @Override
891 40435 jjdelcerro
    public float getFloat(String name) {
892
        return this.getFloat(this.data.getType().getIndex(name));
893
    }
894
895 44297 jjdelcerro
    @Override
896 40435 jjdelcerro
    public float getFloat(int index) {
897
        Float value = ((Float) this.get(index,Float.class,DataTypes.FLOAT));
898
        if (value == null) {
899
            return 0;
900
        }
901 44297 jjdelcerro
        return value;
902 40435 jjdelcerro
    }
903
904 44297 jjdelcerro
    @Override
905 40435 jjdelcerro
    public Geometry getGeometry(String name) {
906
        return this.getGeometry(this.data.getType().getIndex(name));
907
    }
908
909 44297 jjdelcerro
    @Override
910 40435 jjdelcerro
    public Geometry getGeometry(int index) {
911
        return (Geometry) this.get(index,Geometry.class,DataTypes.GEOMETRY);
912
    }
913
914 44297 jjdelcerro
    @Override
915 40435 jjdelcerro
    public int getInt(String name) {
916
        return this.getInt(this.data.getType().getIndex(name));
917
    }
918
919 44297 jjdelcerro
    @Override
920 40435 jjdelcerro
    public int getInt(int index) {
921
        Integer value = ((Integer) this.get(index,Integer.class,DataTypes.INT));
922
        if (value == null) {
923
            return 0;
924
        }
925 44297 jjdelcerro
        return value;
926 40435 jjdelcerro
    }
927
928 44297 jjdelcerro
    @Override
929 40435 jjdelcerro
    public long getLong(String name) {
930
        return this.getLong(this.data.getType().getIndex(name));
931
    }
932
933 44297 jjdelcerro
    @Override
934 40435 jjdelcerro
    public long getLong(int index) {
935
        Long value = ((Long) this.get(index,Long.class,DataTypes.LONG));
936
        if (value == null) {
937
            return 0;
938
        }
939 44297 jjdelcerro
        return value;
940 40435 jjdelcerro
    }
941
942 44297 jjdelcerro
    @Override
943 40435 jjdelcerro
    public String getString(String name) {
944
        return this.getString(this.data.getType().getIndex(name));
945
    }
946
947 44297 jjdelcerro
    @Override
948 40435 jjdelcerro
    public String getString(int index) {
949
        return (String) this.get(index,String.class,DataTypes.STRING);
950
    }
951
952 44297 jjdelcerro
    @Override
953 40435 jjdelcerro
    public Object getContextValue(String name) {
954
        name = name.toLowerCase();
955
        if (name.equals("store")) {
956
            return this.getStore();
957
        }
958
959
        if (name.equals("featuretype")) {
960
            return this.data.getType();
961
        }
962
963
        if (name.equals("feature")) {
964
            return this;
965
        }
966
967
        throw new IllegalArgumentException(name);
968
    }
969
970 44297 jjdelcerro
    @Override
971 40435 jjdelcerro
    public Iterator getDataNames() {
972
        class DataNamesIterator implements Iterator {
973
            Iterator attributeIteraror;
974
975
            DataNamesIterator(DefaultFeature feature) {
976
                this.attributeIteraror = feature.getType().iterator();
977
            }
978
979 44297 jjdelcerro
            @Override
980 40435 jjdelcerro
            public boolean hasNext() {
981
                return this.attributeIteraror.hasNext();
982
            }
983
984 44297 jjdelcerro
            @Override
985 40435 jjdelcerro
            public Object next() {
986
                return ((FeatureAttributeDescriptor) this.attributeIteraror
987
                        .next()).getName();
988
            }
989
990 44297 jjdelcerro
            @Override
991 40435 jjdelcerro
            public void remove() {
992
                throw new UnsupportedOperationException();
993
            }
994
995
        }
996
        return new DataNamesIterator(this);
997
    }
998
999 44297 jjdelcerro
    @Override
1000 40435 jjdelcerro
    public Object getDataValue(String name) {
1001
        name = name.toLowerCase();
1002 41542 jjdelcerro
        try {
1003
            return get(name);
1004
        } catch (IllegalArgumentException ex) {
1005
            if( "defaultgeometry".equalsIgnoreCase(name )) {
1006
                return this.getDefaultGeometry();
1007
            }
1008
            throw ex;
1009
        }
1010 40435 jjdelcerro
    }
1011
1012 44297 jjdelcerro
    @Override
1013 40435 jjdelcerro
    public Iterator getDataValues() {
1014
        class DataValuesIterator implements Iterator {
1015
            DefaultFeature feature;
1016
            int current = 0;
1017
1018
            DataValuesIterator(DefaultFeature feature) {
1019
                this.feature = feature;
1020
            }
1021
1022 44297 jjdelcerro
            @Override
1023 40435 jjdelcerro
            public boolean hasNext() {
1024
                return current < feature.getType().size() - 1;
1025
            }
1026
1027 44297 jjdelcerro
            @Override
1028 40435 jjdelcerro
            public Object next() {
1029
                return feature.get(current++);
1030
            }
1031
1032 44297 jjdelcerro
            @Override
1033 40435 jjdelcerro
            public void remove() {
1034
                throw new UnsupportedOperationException();
1035
            }
1036
1037
        }
1038
        return new DataValuesIterator(this);
1039
    }
1040
1041 44297 jjdelcerro
    @Override
1042 40435 jjdelcerro
    public boolean hasContextValue(String name) {
1043
        name = name.toLowerCase();
1044
        if (name.equals("store")) {
1045
            return true;
1046
        }
1047
1048
        if (name.equals("featuretype")) {
1049
            return true;
1050
        }
1051
1052 44297 jjdelcerro
        return name.equals("feature");
1053 40435 jjdelcerro
    }
1054
1055 44297 jjdelcerro
    @Override
1056 40435 jjdelcerro
    public boolean hasDataValue(String name) {
1057
        name = name.toLowerCase();
1058
        return this.data.getType().getIndex(name) >= 0;
1059
    }
1060 43729 fdiaz
1061 44297 jjdelcerro
    @Override
1062 44086 jjdelcerro
    public Time getTime(int index) {
1063
        return ((Time) this.get(index,Time.class,DataTypes.INSTANT));
1064
    }
1065
1066 44297 jjdelcerro
    @Override
1067 44086 jjdelcerro
    public Time getTime(String name) {
1068
        return this.getInstant(this.data.getType().getIndex(name));
1069
    }
1070
1071 44297 jjdelcerro
    @Override
1072 40435 jjdelcerro
    public Instant getInstant(int index) {
1073 44086 jjdelcerro
        return ((Instant) this.get(index,Instant.class,DataTypes.INSTANT));
1074 40435 jjdelcerro
    }
1075
1076 44297 jjdelcerro
    @Override
1077 40435 jjdelcerro
    public Instant getInstant(String name) {
1078
        return this.getInstant(this.data.getType().getIndex(name));
1079
    }
1080
1081 44297 jjdelcerro
    @Override
1082 40435 jjdelcerro
    public Interval getInterval(int index) {
1083 44086 jjdelcerro
        return ((Interval) this.get(index,Interval.class,DataTypes.INTERVAL));
1084 40435 jjdelcerro
    }
1085
1086 44297 jjdelcerro
    @Override
1087 40435 jjdelcerro
    public Interval getInterval(String name) {
1088
        return this.getInterval(this.data.getType().getIndex(name));
1089
    }
1090
1091 42775 jjdelcerro
    @Override
1092 40435 jjdelcerro
    public DynObject getAsDynObject() {
1093 42775 jjdelcerro
        DynObjectFeatureFacade facade = new DynObjectFeatureFacade(this);
1094 40435 jjdelcerro
        return facade;
1095
    }
1096
1097 44297 jjdelcerro
    @Override
1098 40435 jjdelcerro
    public String toString() {
1099 44297 jjdelcerro
            StringBuilder builder = new StringBuilder();
1100 40435 jjdelcerro
        FeatureAttributeDescriptor[] attributeDescriptors =
1101
            getType().getAttributeDescriptors();
1102
        for (int i = 0; i < attributeDescriptors.length; i++) {
1103
            String name = attributeDescriptors[i].getName();
1104 44607 jjdelcerro
            Object value = get(name);
1105
            builder.append(value);
1106 40435 jjdelcerro
            if (i < attributeDescriptors.length - 1) {
1107 44297 jjdelcerro
                builder.append(", ");
1108 40435 jjdelcerro
            }
1109
        }
1110 44297 jjdelcerro
        return builder.toString();
1111 40435 jjdelcerro
    }
1112 40867 jbadia
1113
1114 43729 fdiaz
1115
1116 40867 jbadia
        /**
1117 40435 jjdelcerro
     * @return the inserted
1118
     */
1119
    public boolean isInserted() {
1120
        return inserted;
1121
    }
1122
1123 43729 fdiaz
1124 40435 jjdelcerro
    /**
1125
     * @param inserted the inserted to set
1126
     */
1127
    public void setInserted(boolean inserted) {
1128
        this.inserted = inserted;
1129
    }
1130
1131 43983 jjdelcerro
        @Override
1132 40435 jjdelcerro
    public EvaluatorData getEvaluatorData() {
1133
        return this;
1134
    }
1135 43983 jjdelcerro
1136
    public int size() {
1137
        return this.data.getType().size();
1138
    }
1139
1140
    public boolean isEmpty() {
1141
        return false;
1142
    }
1143
1144
    public Iterator<String> iterator() {
1145
        final Iterator<FeatureAttributeDescriptor> x = this.data.getType().iterator();
1146
        return new Iterator<String>() {
1147
            @Override
1148
            public boolean hasNext() {
1149
                return x.hasNext();
1150
            }
1151
1152
            @Override
1153
            public String next() {
1154
                return x.next().getName();
1155
            }
1156
        };
1157
    }
1158
1159
    public boolean containsKey(String key) {
1160
        return this.data.getType().get(key)!=null;
1161
    }
1162 44346 jjdelcerro
1163
    @Override
1164
    public String getLabelOfValue(String name) {
1165
        FeatureAttributeDescriptor attrdesc = this.data.getType().getAttributeDescriptor(name);
1166
        if( attrdesc==null ) {
1167
            throw new IllegalArgumentException("Attribute name '"+name+"' not found in the feature.");
1168
        }
1169
        Object value = this.get(attrdesc.getIndex());
1170
        String label = attrdesc.getLabelOfValue(value);
1171
        return label;
1172
    }
1173 44376 jjdelcerro
1174
    @Override
1175
    public Object getExtraValue(String name) {
1176
        return this.data.getExtraValue(name);
1177
    }
1178
1179 44738 jjdelcerro
    public boolean hasExtraValue(String name) {
1180
        return this.data.hasExtraValue(name);
1181
    }
1182
1183 44376 jjdelcerro
    @Override
1184
    public Object getExtraValue(int index) {
1185
        return this.data.getExtraValue(index);
1186
    }
1187
1188 44655 jjdelcerro
    public JsonObject toJSON() {
1189
        JsonObjectBuilder builder = Json.createObjectBuilder();
1190
1191
        FeatureType ft = this.getType();
1192
        for (FeatureAttributeDescriptor desc : ft) {
1193
            if (desc.isComputed()) {
1194
                continue;
1195
            }
1196
            switch(desc.getType()) {
1197
                case DataTypes.GEOMETRY:
1198
                    {
1199
                        try {
1200
                            builder.add(desc.getName(), this.getGeometry(desc.getIndex()).convertToWKT());
1201
                        } catch (Exception ex) {
1202
                            throw new RuntimeException("Can't convert geometry to WKT.", ex);
1203
                        }
1204
                    }
1205
                    break;
1206
                case DataTypes.BOOLEAN:
1207
                    builder.add(desc.getName(), this.getBoolean(desc.getIndex()));
1208
                    break;
1209
                case DataTypes.BYTE:
1210
                    builder.add(desc.getName(), this.getByte(desc.getIndex()));
1211
                    break;
1212
                case DataTypes.INT:
1213
                    builder.add(desc.getName(), this.getInt(desc.getIndex()));
1214
                    break;
1215
                case DataTypes.LONG:
1216
                    builder.add(desc.getName(), this.getLong(desc.getIndex()));
1217
                    break;
1218
                case DataTypes.DOUBLE:
1219
                    builder.add(desc.getName(), this.getDouble(desc.getIndex()));
1220
                    break;
1221
                case DataTypes.FLOAT:
1222
                    builder.add(desc.getName(), this.getFloat(desc.getIndex()));
1223
                    break;
1224
                case DataTypes.DATE:
1225
                    // Format date as ISO 8601
1226
                    Date date = this.getDate(desc.getIndex());
1227
                    String value = DateTimeFormatter.ISO_DATE_TIME.format(date.toInstant());
1228
                    builder.add(desc.getName(), value);
1229
                    break;
1230
                default:
1231
                    builder.add(desc.getName(), Objects.toString(this.get(desc.getIndex()),""));
1232
            }
1233
        }
1234
        return builder.build();
1235
    }
1236 44376 jjdelcerro
1237 40435 jjdelcerro
}