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

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