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

History | View | Annotate | Download (69.8 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 46916 jjdelcerro
import java.util.HashSet;
35 40435 jjdelcerro
import java.util.Iterator;
36
import java.util.List;
37 43550 jjdelcerro
import java.util.Map;
38 44655 jjdelcerro
import java.util.Objects;
39 46916 jjdelcerro
import java.util.Set;
40 46024 jjdelcerro
import java.util.function.Predicate;
41 44655 jjdelcerro
import javax.json.JsonObject;
42 47779 fdiaz
import org.apache.commons.collections4.CollectionUtils;
43 44779 omartinez
import org.apache.commons.lang3.ArrayUtils;
44 47784 jjdelcerro
import static org.apache.commons.lang3.ObjectUtils.mode;
45 44128 jjdelcerro
import org.apache.commons.lang3.StringUtils;
46 40435 jjdelcerro
import org.cresques.cts.IProjection;
47 47078 jjdelcerro
import org.gvsig.expressionevaluator.Expression;
48
import org.gvsig.expressionevaluator.ExpressionBuilder;
49 44818 jjdelcerro
import org.gvsig.expressionevaluator.ExpressionUtils;
50 44128 jjdelcerro
import org.gvsig.fmap.dal.DALLocator;
51 40435 jjdelcerro
import org.gvsig.fmap.dal.DataTypes;
52 47189 fdiaz
import org.gvsig.fmap.dal.SupportTransactions;
53 40435 jjdelcerro
import org.gvsig.fmap.dal.exception.DataEvaluatorRuntimeException;
54
import org.gvsig.fmap.dal.exception.DataException;
55 47756 fdiaz
import org.gvsig.fmap.dal.exception.DataRuntimeException;
56 44128 jjdelcerro
import org.gvsig.fmap.dal.feature.DataProfile;
57 40435 jjdelcerro
import org.gvsig.fmap.dal.feature.EditableFeature;
58 44773 jjdelcerro
import org.gvsig.fmap.dal.feature.EditableFeatureAttributeDescriptor;
59 40435 jjdelcerro
import org.gvsig.fmap.dal.feature.Feature;
60
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
61 41335 jjdelcerro
import org.gvsig.fmap.dal.feature.FeatureAttributeEmulator;
62
import org.gvsig.fmap.dal.feature.FeatureAttributeGetter;
63 45581 fdiaz
import org.gvsig.fmap.dal.feature.FeatureExtraColumns;
64 40435 jjdelcerro
import org.gvsig.fmap.dal.feature.FeatureReference;
65
import org.gvsig.fmap.dal.feature.FeatureStore;
66
import org.gvsig.fmap.dal.feature.FeatureType;
67 46966 fdiaz
import org.gvsig.fmap.dal.feature.ForeingKey;
68 40435 jjdelcerro
import org.gvsig.fmap.dal.feature.exception.IllegalValueException;
69
import org.gvsig.fmap.dal.feature.exception.SetReadOnlyAttributeException;
70 42775 jjdelcerro
import org.gvsig.fmap.dal.feature.impl.dynobjectutils.DynObjectFeatureFacade;
71 45647 fdiaz
import org.gvsig.fmap.dal.feature.impl.featurereference.FeatureReferenceFactory;
72 43729 fdiaz
import org.gvsig.fmap.dal.feature.spi.DefaultFeatureProvider;
73 40435 jjdelcerro
import org.gvsig.fmap.dal.feature.spi.FeatureProvider;
74
import org.gvsig.fmap.geom.Geometry;
75
import org.gvsig.fmap.geom.primitive.Envelope;
76 45581 fdiaz
import org.gvsig.json.Json;
77 46916 jjdelcerro
import org.gvsig.json.JsonArrayBuilder;
78 45581 fdiaz
import org.gvsig.json.JsonObjectBuilder;
79 40435 jjdelcerro
import org.gvsig.tools.ToolsLocator;
80 44799 jjdelcerro
import org.gvsig.tools.dataTypes.Coercion;
81 40435 jjdelcerro
import org.gvsig.tools.dataTypes.CoercionException;
82 45581 fdiaz
import org.gvsig.tools.dataTypes.DataType;
83 40435 jjdelcerro
import org.gvsig.tools.dataTypes.DataTypesManager;
84 46956 fdiaz
import org.gvsig.tools.dispose.DisposeUtils;
85 46916 jjdelcerro
import org.gvsig.tools.dynobject.DynField;
86 40435 jjdelcerro
import org.gvsig.tools.dynobject.DynObject;
87 47648 jjdelcerro
import org.gvsig.tools.dynobject.Tags;
88 40435 jjdelcerro
import org.gvsig.tools.evaluator.Evaluator;
89
import org.gvsig.tools.evaluator.EvaluatorData;
90
import org.gvsig.tools.evaluator.EvaluatorException;
91
import org.gvsig.tools.exception.BaseException;
92
import org.gvsig.tools.exception.BaseRuntimeException;
93 40876 jjdelcerro
import org.gvsig.tools.lang.Cloneable;
94 46916 jjdelcerro
import org.gvsig.tools.util.Bitmask;
95 45581 fdiaz
import org.slf4j.Logger;
96
import org.slf4j.LoggerFactory;
97 40435 jjdelcerro
98 44799 jjdelcerro
@SuppressWarnings("UseSpecificCatch")
99 40876 jjdelcerro
public class DefaultFeature implements Feature, EvaluatorData, Cloneable {
100 40435 jjdelcerro
101 45581 fdiaz
    private static final Logger LOGGER = LoggerFactory.getLogger(DefaultFeature.class);
102 43729 fdiaz
103 45581 fdiaz
    private static DataTypesManager dataTypesManager = null;
104
    protected FeatureProvider data;
105
    protected FeatureReference reference;
106
    private WeakReference storeRef;
107 40435 jjdelcerro
108 45581 fdiaz
    private boolean inserted = false;
109
    private Object[] extraValuesData;
110
    private Map<String, Object> extraValues; // not persistent
111
112 40435 jjdelcerro
    /*
113
         * Usar con mucha precaucion o mejor no usar. Lo precisa el
114
         * DefaultFeatureSet en la ordenacion.
115 45581 fdiaz
     */
116
    public DefaultFeature(FeatureStore store) {
117
        this.storeRef = new WeakReference(store);
118
        this.reference = null;
119
    }
120 40435 jjdelcerro
121 45581 fdiaz
    public DefaultFeature(FeatureStore store, FeatureProvider data) {
122
        this.data = data;
123
        this.extraValuesData = null;
124
        this.storeRef = new WeakReference(store);
125
        this.reference = null;
126
        this.inserted = !data.isNew();
127
    }
128 40435 jjdelcerro
129 45581 fdiaz
    DefaultFeature(DefaultFeature feature) {
130
        this.data = feature.data.getCopy();
131
        this.extraValuesData = ArrayUtils.clone(feature.extraValuesData);
132
        this.storeRef = feature.storeRef;
133
        this.reference = feature.reference;
134
        this.inserted = feature.isInserted();
135
    }
136 40435 jjdelcerro
137 43729 fdiaz
    public DefaultFeature(FeatureType targetType, Feature sourceFeature) {
138 45581 fdiaz
        DefaultFeature defaultFeature = (DefaultFeature) sourceFeature;
139
        this.data = new DefaultFeatureProvider(targetType, (DefaultFeatureProvider) defaultFeature.getData());
140 44779 omartinez
        this.extraValuesData = null;
141 43729 fdiaz
        this.storeRef = defaultFeature.storeRef;
142
        this.reference = defaultFeature.reference;
143
        this.inserted = defaultFeature.isInserted();
144
145
        FeatureType sourceType = sourceFeature.getType();
146
147
        for (FeatureAttributeDescriptor targetAttrDescriptor : targetType) {
148 45581 fdiaz
            if (targetAttrDescriptor.isComputed()) {
149
                continue;
150 43729 fdiaz
            }
151
            int sourceIndex = sourceType.getIndex(targetAttrDescriptor.getName());
152 45581 fdiaz
            if (sourceIndex < 0) {
153 43729 fdiaz
                continue;
154
            }
155
            Object value = sourceFeature.get(sourceIndex);
156
            if (value == null && !targetAttrDescriptor.allowNull()) {
157
                continue;
158
            }
159 45581 fdiaz
            this.setforced(targetAttrDescriptor.getIndex(), targetAttrDescriptor, value);
160 43729 fdiaz
        }
161
    }
162
163 45581 fdiaz
    public void setData(FeatureProvider data) {
164
        this.data = data;
165
        this.extraValuesData = null;
166
        this.reference = null;
167
        this.inserted = true;
168
    }
169 40435 jjdelcerro
170 45581 fdiaz
    public FeatureProvider getData() {
171
        return this.data;
172
    }
173 40435 jjdelcerro
174 45581 fdiaz
    protected DataTypesManager getDataTypesManager() {
175
        if (dataTypesManager == null) {
176
            dataTypesManager = ToolsLocator.getDataTypesManager();
177
        }
178
        return dataTypesManager;
179
    }
180 40435 jjdelcerro
181 46024 jjdelcerro
    public boolean canSetValue(String name) {
182
        return this.canSetValue(this.getType().getAttributeDescriptor(name), null);
183
    }
184
185 47594 jjdelcerro
    public boolean canSetValue(FeatureAttributeDescriptor attr,Predicate<FeatureAttributeDescriptor> copy) {
186 46024 jjdelcerro
        // helper function to use in copyFrom
187
        if (attr==null  ) {
188
            return false;
189
        }
190
        if (attr.isAutomatic()  || attr.isComputed() ) {
191
            return false;
192
        }
193
        if( this.isInserted() &&  attr.isReadOnly()) {
194
            return false;
195
        }
196 47594 jjdelcerro
        if( copy!=null && !copy.test(attr) ) {
197 46024 jjdelcerro
            return false;
198
        }
199
        return true;
200
    }
201
202 44641 jjdelcerro
    protected void set(FeatureAttributeDescriptor attribute, Object value) {
203 41335 jjdelcerro
        int i = attribute.getIndex();
204 40435 jjdelcerro
205 45769 jjdelcerro
        if( this.isInserted() ) {
206
            if (attribute.isReadOnly()) {
207
                throw new SetReadOnlyAttributeException(attribute.getName(), this.getType());
208
            }
209
        } else {
210
            if (attribute.isComputed()) {
211
                throw new SetReadOnlyAttributeException(attribute.getName(), this.getType());
212
            }
213 41335 jjdelcerro
        }
214
        FeatureAttributeEmulator emulator = attribute.getFeatureAttributeEmulator();
215 45581 fdiaz
        if (emulator != null) {
216
            emulator.set((EditableFeature) this, value);
217 41335 jjdelcerro
            return;
218
        }
219 43729 fdiaz
220 45581 fdiaz
        if (value == null) {
221 47779 fdiaz
            if (this.isInserted()) {
222
                if (!attribute.allowNull()) {
223
                    if (!attribute.isAutomatic()) {
224
                        throw new IllegalValueException(attribute, value);
225
                    }
226 41335 jjdelcerro
                }
227
            }
228
            this.data.set(i, null);
229
            return;
230 40435 jjdelcerro
231 41335 jjdelcerro
        }
232 40435 jjdelcerro
233 45581 fdiaz
        if (attribute.getFeatureAttributeGetter() != null) {
234 41335 jjdelcerro
            value = attribute.getFeatureAttributeGetter().setter(value);
235 40435 jjdelcerro
        }
236 44641 jjdelcerro
        this.setforced(i, attribute, value);
237
    }
238 41335 jjdelcerro
239 44641 jjdelcerro
    private void setforced(int i, FeatureAttributeDescriptor attribute, Object value) {
240
241 42218 jjdelcerro
        Class objectClass = attribute.getObjectClass();
242 45581 fdiaz
        if (objectClass != null) {
243
            if (objectClass.isInstance(value)) {
244
                if (attribute.getType() == DataTypes.DECIMAL) {
245
                    BigDecimal d = (BigDecimal) value;
246
                    if (d.scale() == attribute.getScale() && d.precision() <= attribute.getPrecision()) {
247
                        this.data.set(i, value);
248
                        return;
249
                    }
250 45693 fdiaz
                } else if (attribute.getType() == DataTypes.GEOMETRY) {
251
                    if (!attribute.getGeomType().equals(((Geometry) value).getGeometryType())) {
252
                        try {
253
                            Coercion coercer = attribute.getDataType().getCoercion();
254
                            value = coercer.coerce(value, attribute.getCoercionContext());
255
                        } catch (CoercionException e) {
256
                            throw new IllegalArgumentException("Can't convert to "
257
                                    + attribute.getDataType().getName()
258
                                    + " from '"
259
                                    + value == null ? "NULL" : value.getClass().getName()
260
                                            + "' with value '"
261
                                            + Objects.toString(value)
262
                                            + "' and context '"
263
                                            + attribute.getCoercionContext()
264 46898 fdiaz
                                            + "'.",e);
265 45693 fdiaz
                        }
266
                    }
267
                    this.data.set(i, value);
268
                    return;
269 45581 fdiaz
                } else {
270 44799 jjdelcerro
                    this.data.set(i, value);
271
                    return;
272
                }
273
            }
274
            DataProfile dataProfile = attribute.getDataProfile();
275 45581 fdiaz
            if (dataProfile != null) {
276 42218 jjdelcerro
                try {
277 44799 jjdelcerro
                    value = dataProfile.coerce(
278
                            attribute.getDataType(),
279 45581 fdiaz
                            value,
280 44799 jjdelcerro
                            attribute.getTags()
281
                    );
282 42218 jjdelcerro
                } catch (CoercionException e) {
283 44799 jjdelcerro
284 42218 jjdelcerro
                }
285 45581 fdiaz
            }
286 44799 jjdelcerro
            try {
287
                Coercion coercer = attribute.getDataType().getCoercion();
288 45581 fdiaz
                if (attribute.getType() == DataTypes.STRING && value instanceof Boolean) {
289 45131 fdiaz
                    value = coercer.coerce(value, attribute.getCoercionContext());
290
                    value = StringUtils.left((String) value, attribute.getSize());
291
                } else {
292 45581 fdiaz
                    value = coercer.coerce(value, attribute.getCoercionContext());
293 45131 fdiaz
                }
294 44799 jjdelcerro
            } catch (CoercionException e) {
295 46715 jjdelcerro
                throw new IllegalArgumentException("Can't assign value [" +
296
                        toStringQuietly(value)+
297
                        "] of type '"+
298
                        (value == null ? "NULL" : value.getClass().getName())+
299
                        "' to field '"+
300
                        attribute.getName()+
301
                        "' of type "+
302
                        attribute.getDataType().getName()+
303
                        "."
304 46898 fdiaz
                ,e);
305 40435 jjdelcerro
            }
306 41335 jjdelcerro
        }
307 40435 jjdelcerro
        this.data.set(i, value);
308
    }
309 43729 fdiaz
310 46715 jjdelcerro
    private String toStringQuietly(Object v) {
311
        try {
312
            return Objects.toString(v);
313
        } catch(Throwable t) {
314
            return "ERROR";
315
        }
316
    }
317
318 45581 fdiaz
    private Object get(int index, Class theClass, int type) {
319 40435 jjdelcerro
        Object value = this.get(index);
320 45581 fdiaz
        if (theClass.isInstance(value)) {
321 40435 jjdelcerro
            return value;
322
        }
323
        try {
324 46893 fdiaz
            return this.getDataTypesManager().coerce(type, value, this.getType().getAttributeDescriptor(index).getCoercionContext());
325 40435 jjdelcerro
        } catch (CoercionException e) {
326 43729 fdiaz
327 40435 jjdelcerro
            if (value == null) {
328
                return null;
329
            }
330
            throw new IllegalArgumentException(
331 45581 fdiaz
                    "Can't convert to " + theClass.getName()
332
                    + " from '" + value.getClass().getName()
333
                    + "' with value '" + value.toString() + "'.");
334 40435 jjdelcerro
        }
335
    }
336 43729 fdiaz
337 40435 jjdelcerro
    public void initializeValues() {
338
        FeatureType type = this.getType();
339 44297 jjdelcerro
        for (FeatureAttributeDescriptor attribute : type) {
340 40435 jjdelcerro
            if (attribute.isAutomatic() || attribute.isReadOnly()
341 45581 fdiaz
                    || attribute.isComputed()) {
342 40435 jjdelcerro
                continue;
343
            }
344
            if (attribute.getDefaultValue() == null && !attribute.allowNull()) {
345
                continue;
346
            }
347 45581 fdiaz
            Object value = attribute.getDefaultValue();
348
            if (value instanceof CharSequence) {
349
                String s = ((CharSequence) value).toString();
350
                if (ExpressionUtils.isDynamicText(s)) {
351
                    try {
352
                        value = ExpressionUtils.evaluateDynamicText(s);
353
                    } catch (Throwable th) {
354
                        value = null;
355
                    }
356 44818 jjdelcerro
                }
357
            }
358
            this.set(attribute, value);
359 40435 jjdelcerro
        }
360
    }
361
362
    public void clear() {
363
        initializeValues();
364
    }
365
366
    public void initializeValues(Feature feature) {
367 45581 fdiaz
        FeatureType myType = this.getType();
368
        FeatureType type = feature.getType();
369 44779 omartinez
        extraValuesData = null;
370 44297 jjdelcerro
        for (FeatureAttributeDescriptor attribute : type) {
371 45581 fdiaz
            FeatureAttributeDescriptor myAttribute = myType.getAttributeDescriptor(attribute.getName());
372 40435 jjdelcerro
            if (myAttribute != null) {
373
                this.set(myAttribute, feature.get(attribute.getIndex()));
374
            }
375
        }
376
    }
377
378 44297 jjdelcerro
    @Override
379 40435 jjdelcerro
    public FeatureStore getStore() {
380
        return (FeatureStore) this.storeRef.get();
381
    }
382
383 44297 jjdelcerro
    @Override
384 40435 jjdelcerro
    public FeatureType getType() {
385
        return this.data.getType();
386
    }
387
388 44297 jjdelcerro
    @Override
389 40435 jjdelcerro
    public EditableFeature getEditable() {
390
        return new DefaultEditableFeature(this);
391
    }
392
393 44297 jjdelcerro
    @Override
394 40435 jjdelcerro
    public Feature getCopy() {
395
        return new DefaultFeature(this);
396
    }
397 43729 fdiaz
398 44297 jjdelcerro
    @Override
399
    @SuppressWarnings("CloneDoesntCallSuperClone")
400 40876 jjdelcerro
    public Object clone() throws CloneNotSupportedException {
401
        return new DefaultFeature(this);
402
    }
403 40435 jjdelcerro
404 44297 jjdelcerro
    @Override
405 40435 jjdelcerro
    public FeatureReference getReference() {
406 46706 fdiaz
        if(!this.getType().supportReferences()){
407
            return null;
408
        }
409 40435 jjdelcerro
        if (this.reference == null) {
410
            if (!isInserted()) {
411
                return null;
412
            }
413 45647 fdiaz
            reference = FeatureReferenceFactory.createFromFeature(this);
414 40435 jjdelcerro
        }
415
        return this.reference;
416
    }
417
418 44331 jjdelcerro
    @Override
419
    public Object getOrDefault(String name, Object defaultValue) {
420
        int index = this.data.getType().getIndex(name);
421 45581 fdiaz
        if (index < 0) {
422 44331 jjdelcerro
            return defaultValue;
423
        }
424
        return this.get(index);
425
    }
426 45738 fdiaz
427
    @Override
428
    public Object getOrDefault(String name, int type, Object defaultValue) {
429
        DataType dataType = ToolsLocator.getDataTypesManager().get(type);
430
        return getOrDefault(name, dataType, defaultValue);
431
    }
432
433
    @Override
434
    public Object getOrDefault(String name, DataType type, Object defaultValue) {
435
        int index = this.data.getType().getIndex(name);
436
        if (index < 0) {
437
            return defaultValue;
438
        }
439
        try {
440
            Object value = this.get(index);
441
            if(value == null){
442
                return defaultValue;
443
            }
444
            return type.coerce(value);
445
        } catch (Throwable th) {
446
            return defaultValue;
447
        }
448
    }
449 44331 jjdelcerro
450
    @Override
451
    public String getStringOrDefault(String name, String defaultValue) {
452
        int index = this.data.getType().getIndex(name);
453 45581 fdiaz
        if (index < 0) {
454 44331 jjdelcerro
            return defaultValue;
455
        }
456
        try {
457
            return (String) this.get(index);
458 45581 fdiaz
        } catch (Throwable th) {
459 44331 jjdelcerro
            return defaultValue;
460
        }
461
    }
462
463
    @Override
464 45540 jjdelcerro
    public boolean getBooleanOrDefault(String name, boolean defaultValue) {
465
        int index = this.data.getType().getIndex(name);
466 45581 fdiaz
        if (index < 0) {
467 45540 jjdelcerro
            return defaultValue;
468
        }
469
        try {
470
            return this.getBoolean(index);
471 45581 fdiaz
        } catch (Throwable th) {
472 45540 jjdelcerro
            return defaultValue;
473
        }
474
    }
475
476
    @Override
477 44331 jjdelcerro
    public int getIntOrDefault(String name, int defaultValue) {
478
        int index = this.data.getType().getIndex(name);
479 45581 fdiaz
        if (index < 0) {
480 44331 jjdelcerro
            return defaultValue;
481
        }
482
        try {
483 45540 jjdelcerro
            return this.getInt(index);
484 45581 fdiaz
        } catch (Throwable th) {
485 44331 jjdelcerro
            return defaultValue;
486
        }
487
    }
488
489
    @Override
490
    public long getLongOrDefault(String name, long defaultValue) {
491
        int index = this.data.getType().getIndex(name);
492 45581 fdiaz
        if (index < 0) {
493 44331 jjdelcerro
            return defaultValue;
494
        }
495
        try {
496 45540 jjdelcerro
            return this.getLong(index);
497 45581 fdiaz
        } catch (Throwable th) {
498 44331 jjdelcerro
            return defaultValue;
499
        }
500
    }
501
502
    @Override
503
    public float getFloatOrDefault(String name, float defaultValue) {
504
        int index = this.data.getType().getIndex(name);
505 45581 fdiaz
        if (index < 0) {
506 44331 jjdelcerro
            return defaultValue;
507
        }
508
        try {
509 45540 jjdelcerro
            return this.getFloat(index);
510 45581 fdiaz
        } catch (Throwable th) {
511 44331 jjdelcerro
            return defaultValue;
512
        }
513
    }
514
515
    @Override
516
    public double getDoubleOrDefault(String name, double defaultValue) {
517
        int index = this.data.getType().getIndex(name);
518 45581 fdiaz
        if (index < 0) {
519 44331 jjdelcerro
            return defaultValue;
520
        }
521
        try {
522 45540 jjdelcerro
            return this.getDouble(index);
523 45581 fdiaz
        } catch (Throwable th) {
524 44331 jjdelcerro
            return defaultValue;
525
        }
526
    }
527
528
    @Override
529 44669 jjdelcerro
    public BigDecimal getDecimalOrDefault(String name, BigDecimal defaultValue) {
530
        int index = this.data.getType().getIndex(name);
531 45581 fdiaz
        if (index < 0) {
532 44669 jjdelcerro
            return defaultValue;
533
        }
534
        try {
535 45540 jjdelcerro
            return this.getDecimal(index);
536 45581 fdiaz
        } catch (Throwable th) {
537 44669 jjdelcerro
            return defaultValue;
538
        }
539
    }
540
541
    @Override
542 44331 jjdelcerro
    public Date getDateOrDefault(String name, Date defaultValue) {
543
        int index = this.data.getType().getIndex(name);
544 45581 fdiaz
        if (index < 0) {
545 44331 jjdelcerro
            return defaultValue;
546
        }
547
        try {
548 45540 jjdelcerro
            return this.getDate(index);
549 45581 fdiaz
        } catch (Throwable th) {
550 44331 jjdelcerro
            return defaultValue;
551
        }
552
    }
553
554
    @Override
555
    public Object getOrDefault(int index, Object defaultValue) {
556 45581 fdiaz
        if (index < 0 || index >= this.data.getType().size()) {
557 44331 jjdelcerro
            return defaultValue;
558
        }
559
        try {
560
            return this.get(index);
561 45581 fdiaz
        } catch (Throwable th) {
562 44331 jjdelcerro
            return defaultValue;
563
        }
564
    }
565
566
    @Override
567
    public String getStringOrDefault(int index, String defaultValue) {
568 45581 fdiaz
        if (index < 0 || index >= this.data.getType().size()) {
569 44331 jjdelcerro
            return defaultValue;
570
        }
571
        try {
572 45540 jjdelcerro
            return this.getString(index);
573 45581 fdiaz
        } catch (Throwable th) {
574 44331 jjdelcerro
            return defaultValue;
575
        }
576
    }
577
578
    @Override
579 45540 jjdelcerro
    public boolean getBooleanOrDefault(int index, boolean defaultValue) {
580 45581 fdiaz
        if (index < 0 || index >= this.data.getType().size()) {
581 45540 jjdelcerro
            return defaultValue;
582
        }
583
        try {
584
            return this.getBoolean(index);
585 45581 fdiaz
        } catch (Throwable th) {
586 45540 jjdelcerro
            return defaultValue;
587
        }
588
    }
589
590
    @Override
591 44331 jjdelcerro
    public int getIntOrDefault(int index, int defaultValue) {
592 45581 fdiaz
        if (index < 0 || index >= this.data.getType().size()) {
593 44331 jjdelcerro
            return defaultValue;
594
        }
595
        try {
596 45540 jjdelcerro
            return this.getInt(index);
597 45581 fdiaz
        } catch (Throwable th) {
598 44331 jjdelcerro
            return defaultValue;
599
        }
600
    }
601
602
    @Override
603
    public long getLongOrDefault(int index, long defaultValue) {
604 45581 fdiaz
        if (index < 0 || index >= this.data.getType().size()) {
605 44331 jjdelcerro
            return defaultValue;
606
        }
607
        try {
608 45540 jjdelcerro
            return this.getLong(index);
609 45581 fdiaz
        } catch (Throwable th) {
610 44331 jjdelcerro
            return defaultValue;
611
        }
612
    }
613
614
    @Override
615
    public float getFloatOrDefault(int index, float defaultValue) {
616 45581 fdiaz
        if (index < 0 || index >= this.data.getType().size()) {
617 44331 jjdelcerro
            return defaultValue;
618
        }
619
        try {
620 45540 jjdelcerro
            return this.getFloat(index);
621 45581 fdiaz
        } catch (Throwable th) {
622 44331 jjdelcerro
            return defaultValue;
623
        }
624
    }
625
626
    @Override
627
    public double getDoubleOrDefault(int index, double defaultValue) {
628 45581 fdiaz
        if (index < 0 || index >= this.data.getType().size()) {
629 44331 jjdelcerro
            return defaultValue;
630
        }
631
        try {
632 45540 jjdelcerro
            return this.getDouble(index);
633 45581 fdiaz
        } catch (Throwable th) {
634 44331 jjdelcerro
            return defaultValue;
635
        }
636
    }
637
638
    @Override
639 44669 jjdelcerro
    public BigDecimal getDecimalOrDefault(int index, BigDecimal defaultValue) {
640 45581 fdiaz
        if (index < 0 || index >= this.data.getType().size()) {
641 44669 jjdelcerro
            return defaultValue;
642
        }
643
        try {
644 45540 jjdelcerro
            return this.getDecimal(index);
645 45581 fdiaz
        } catch (Throwable th) {
646 44669 jjdelcerro
            return defaultValue;
647
        }
648
    }
649
650
    @Override
651 44331 jjdelcerro
    public Date getDateOrDefault(int index, Date defaultValue) {
652 45581 fdiaz
        if (index < 0 || index >= this.data.getType().size()) {
653 44331 jjdelcerro
            return defaultValue;
654
        }
655
        try {
656 45540 jjdelcerro
            return this.getDate(index);
657 45581 fdiaz
        } catch (Throwable th) {
658 44331 jjdelcerro
            return defaultValue;
659
        }
660
    }
661
662 45739 jjdelcerro
    @Override
663
    public void validate(int check) throws DataException {
664
        ((DefaultFeatureType) this.data.getType()).validateFeature(this, check);
665
    }
666
667 47436 fdiaz
    @Override
668
    public boolean isBroken() {
669
        return this.data.isBroken();
670
    }
671
672 40435 jjdelcerro
    class UnableToGetReferenceException extends BaseRuntimeException {
673
674
        /**
675 43729 fdiaz
         *
676 40435 jjdelcerro
         */
677
        private static final long serialVersionUID = 1812805035204824163L;
678
679
        /**
680
         * @param exception
681
         */
682 44799 jjdelcerro
        @SuppressWarnings("OverridableMethodCallInConstructor")
683 40435 jjdelcerro
        public UnableToGetReferenceException(BaseException exception) {
684
            super("Unable to get reference", "_UnableToGetReferenceException",
685 45581 fdiaz
                    serialVersionUID);
686 40435 jjdelcerro
            this.initCause(exception);
687 43729 fdiaz
688 40435 jjdelcerro
        }
689 43729 fdiaz
690 40435 jjdelcerro
    }
691 43729 fdiaz
692 44297 jjdelcerro
    @Override
693 40435 jjdelcerro
    public List getSRSs() {
694
        // TODO Auto-generated method stub
695
        return null;
696
    }
697
698 44297 jjdelcerro
    @Override
699 40435 jjdelcerro
    public Envelope getDefaultEnvelope() {
700 41342 jjdelcerro
        Envelope envelope = this.data.getDefaultEnvelope();
701 45581 fdiaz
        if (envelope == null) {
702 44618 jjdelcerro
            int i = this.data.getType().getDefaultGeometryAttributeIndex();
703 45581 fdiaz
            if (i < 0) {
704 44618 jjdelcerro
                return null;
705
            }
706 41342 jjdelcerro
            Geometry geom = this.getDefaultGeometry();
707 45581 fdiaz
            if (geom != null) {
708 41348 jjdelcerro
                envelope = geom.getEnvelope();
709
            }
710 41342 jjdelcerro
        }
711
        return envelope;
712 40435 jjdelcerro
    }
713
714 44022 jjdelcerro
    @Override
715 40435 jjdelcerro
    public Geometry getDefaultGeometry() {
716 45581 fdiaz
        Geometry geom = this.data.getDefaultGeometry();
717
        if (geom == null) {
718 44022 jjdelcerro
            int i = this.data.getType().getDefaultGeometryAttributeIndex();
719 45581 fdiaz
            if (i < 0) {
720 44618 jjdelcerro
                return null;
721
            }
722 44022 jjdelcerro
            Object x = this.get(i);
723 45581 fdiaz
            if (x instanceof Geometry) {
724 44022 jjdelcerro
                geom = (Geometry) x;
725
            } else {
726
                geom = this.getGeometry(i);
727
            }
728 43420 jjdelcerro
        }
729 45581 fdiaz
        if (geom != null) {
730
            if (geom.getProjection() == null) {
731 44022 jjdelcerro
                FeatureType type = this.getType();
732
                DefaultFeatureAttributeDescriptor attrdesc = (DefaultFeatureAttributeDescriptor) type.get(type.getDefaultGeometryAttributeIndex());
733
                IProjection proj = attrdesc.getSRS(this.storeRef);
734
                geom.setProjection(proj);
735
            }
736
        }
737
        return geom;
738 40435 jjdelcerro
    }
739
740 44767 jjdelcerro
//    @Override
741
//    public Time getDefaultTime() {
742
//            Time time = this.data.getDefaultTime();
743
//        if( time == null ) {
744
//            int i = this.data.getType().getDefaultTimeAttributeIndex();
745
//            Object x = this.get(i);
746
//            if( x instanceof Time ) {
747
//                time = (Time) x;
748
//            } else {
749
//                time = this.getTime(i);
750
//            }
751
//        }
752
//        return time;
753
//    }
754
//
755 44086 jjdelcerro
    @Override
756 40435 jjdelcerro
    public IProjection getDefaultSRS() {
757 44022 jjdelcerro
        IProjection srs = this.data.getType().getDefaultSRS();
758 45581 fdiaz
        if (srs == null) {
759 44022 jjdelcerro
            FeatureType type = this.getType();
760
            DefaultFeatureAttributeDescriptor attrdesc = (DefaultFeatureAttributeDescriptor) type.get(type.getDefaultGeometryAttributeIndex());
761
            srs = attrdesc.getSRS(this.storeRef);
762
        }
763
        return srs;
764 40435 jjdelcerro
    }
765
766 44297 jjdelcerro
    @Override
767 40435 jjdelcerro
    public List getGeometries() {
768
        // TODO Auto-generated method stub
769
        return null;
770
    }
771
772 44128 jjdelcerro
    @Override
773
    public Object getFromProfile(int index) {
774
        FeatureAttributeDescriptor descriptor = this.data.getType().getAttributeDescriptor(index);
775
        Object value = this.get(index);
776
        String profileName = descriptor.getDataProfileName();
777 45581 fdiaz
        if (StringUtils.isBlank(profileName)) {
778 44128 jjdelcerro
            return value;
779
        }
780
        DataProfile profile = DALLocator.getDataManager().getDataProfile(profileName);
781 45581 fdiaz
        if (profile == null) {
782 44128 jjdelcerro
            return value;
783
        }
784 44253 jjdelcerro
        return profile.createData(value, descriptor.getTags());
785 44128 jjdelcerro
    }
786
787
    @Override
788
    public Object getFromProfile(String name) {
789
        FeatureAttributeDescriptor descriptor = this.data.getType().getAttributeDescriptor(name);
790
        return this.getFromProfile(descriptor.getIndex());
791
    }
792
793 46162 jjdelcerro
    private Object get(String name, Class theClass, int type) {
794
        Object value = this.get(name);
795
        if (theClass.isInstance(value)) {
796
            return value;
797
        }
798
        try {
799
            return this.getDataTypesManager().coerce(type, value);
800
        } catch (CoercionException e) {
801
802
            if (value == null) {
803
                return null;
804
            }
805
            throw new IllegalArgumentException(
806
                    "Can't convert to " + theClass.getName()
807
                    + " from '" + value.getClass().getName()
808
                    + "' with value '" + value.toString() + "'.");
809
        }
810
    }
811
812 44297 jjdelcerro
    @Override
813 40435 jjdelcerro
    public Object get(String name) {
814
        int index = this.data.getType().getIndex(name);
815 45581 fdiaz
        if (index < 0) {
816 45155 omartinez
            // buscamos en los extra cols
817 45581 fdiaz
            if (hasExtraColumnValue(name)) {
818 45155 omartinez
                return getExtraColumnValue(name);
819
            }
820
            if (hasExtraValue(name)) {
821
                return getExtraValue(name);
822
            }
823
            // y si esta ahi return
824 45581 fdiaz
            throw new IllegalArgumentException("Attribute name '" + name + "' not found in the feature.");
825 40435 jjdelcerro
        }
826
        return this.get(index);
827
    }
828 45581 fdiaz
829 44669 jjdelcerro
    @Override
830
    public boolean isNull(int index) {
831
        FeatureType type = this.data.getType();
832 45581 fdiaz
        if (index < 0 || index >= type.size()) {
833
            throw new IllegalArgumentException("Attribute index '" + index + "' out of range (0 to " + this.data.getType().size() + ".");
834 44669 jjdelcerro
        }
835
        FeatureAttributeDescriptor attribute = type.getAttributeDescriptor(index);
836
        if (!this.data.getType().hasEvaluators()) {
837 45581 fdiaz
            return this.data.get(index) == null;
838 44669 jjdelcerro
        }
839
        Evaluator eval = attribute.getEvaluator();
840
        if (eval == null) {
841 45581 fdiaz
            return this.data.get(index) == null;
842 44669 jjdelcerro
        }
843
        Object value = this.data.get(index);
844
        if (value != null) {
845
            return true;
846
        }
847
        try {
848
            value = eval.evaluate(this);
849
        } catch (EvaluatorException e) {
850
            throw new DataEvaluatorRuntimeException(e);
851
        }
852
        this.data.set(index, value);
853 45581 fdiaz
        return value == null;
854 44669 jjdelcerro
    }
855 45581 fdiaz
856 44669 jjdelcerro
    @Override
857
    public boolean isNull(String name) {
858
        int index = this.data.getType().getIndex(name);
859 45581 fdiaz
        if (index < 0) {
860
            throw new IllegalArgumentException("Attribute name '" + name + "' not found in the feature.");
861 44669 jjdelcerro
        }
862
        return this.isNull(index);
863
    }
864 43729 fdiaz
865 43550 jjdelcerro
    public boolean has_key(String key) {
866
        Object x = this.getType().get(key);
867
        return x != null;
868
    }
869 43729 fdiaz
870 43550 jjdelcerro
    public List<String> keys() {
871
        List<String> ks = new ArrayList<>();
872 45581 fdiaz
        for (FeatureAttributeDescriptor attr : this.getType()) {
873 43550 jjdelcerro
            ks.add(attr.getName());
874
        }
875
        return ks;
876
    }
877 43729 fdiaz
878 43550 jjdelcerro
    public Iterator<String> iterkeys() {
879
        final Iterator it = this.getType().iterator();
880
        return new Iterator<String>() {
881
            @Override
882
            public boolean hasNext() {
883
                return it.hasNext();
884
            }
885 40435 jjdelcerro
886 43550 jjdelcerro
            @Override
887
            public String next() {
888 45581 fdiaz
                return ((FeatureAttributeDescriptor) it.next()).getName();
889 43550 jjdelcerro
            }
890 43561 jjdelcerro
891
            @Override
892
            public void remove() {
893
                throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
894
            }
895 43550 jjdelcerro
        };
896
    }
897 40435 jjdelcerro
898 43550 jjdelcerro
    public Iterator iteritems() {
899
        final Iterator it = this.getType().iterator();
900
        return new Iterator<Map.Entry>() {
901
            @Override
902
            public boolean hasNext() {
903
                return it.hasNext();
904
            }
905
906
            @Override
907
            public Map.Entry next() {
908 45581 fdiaz
                final String name = ((FeatureAttributeDescriptor) it.next()).getName();
909 43550 jjdelcerro
                return new Map.Entry<String, Object>() {
910
                    @Override
911
                    public String getKey() {
912
                        return name;
913
                    }
914
915
                    @Override
916
                    public Object getValue() {
917
                        return get(name);
918
                    }
919
920
                    @Override
921
                    public Object setValue(Object value) {
922
                        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
923
                    }
924 43729 fdiaz
925 43550 jjdelcerro
                };
926
            }
927 43561 jjdelcerro
928
            @Override
929
            public void remove() {
930
                throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
931
            }
932 43729 fdiaz
        };
933 43550 jjdelcerro
    }
934
935
    @Override
936 40435 jjdelcerro
    public Object get(int index) {
937
        FeatureType type = this.data.getType();
938 45581 fdiaz
        if (index < 0 || index >= type.size()) {
939
            throw new IllegalArgumentException("Attribute index '" + index + "' out of range (0 to " + this.data.getType().size() + ".");
940 40435 jjdelcerro
        }
941 44840 jjdelcerro
        Object value = this.data.get(index);
942 40435 jjdelcerro
        FeatureAttributeDescriptor attribute = type.getAttributeDescriptor(index);
943 44840 jjdelcerro
        if (type.hasEvaluators()) {
944 45581 fdiaz
            Evaluator eval = attribute.getEvaluator();
945
            if (eval != null) {
946
                if (value == null) { // Ya hemos calculado el campo ?
947
                    // FIXME: para comprobar si esta calculado usar un array especifico.
948
                    try {
949
                        value = eval.evaluate(this);
950
                    } catch (EvaluatorException e) {
951
                        throw new DataEvaluatorRuntimeException(e);
952
                    }
953
                    this.data.set(index, value);
954
                }
955
            }
956 43729 fdiaz
        }
957 44840 jjdelcerro
        value = get(attribute, value);
958 45581 fdiaz
        return value;
959 40435 jjdelcerro
    }
960
961 45581 fdiaz
    private Object get(FeatureAttributeDescriptor featureAttributeDescriptor, Object value) {
962 41335 jjdelcerro
        FeatureAttributeEmulator emulator = featureAttributeDescriptor.getFeatureAttributeEmulator();
963 45581 fdiaz
        if (emulator != null) {
964 44226 jjdelcerro
//            int index = featureAttributeDescriptor.getIndex();
965
//            value = this.data.get(index);
966
//            if( value==null ) {
967 46050 omartinez
            value = this.getExtraValue(featureAttributeDescriptor.getName());
968
            if (value==null) {
969
                value = emulator.get(this);
970
            }
971 44226 jjdelcerro
//                this.data.set(index,value);
972
//            }
973 44022 jjdelcerro
        } else {
974
            FeatureAttributeGetter getter = featureAttributeDescriptor.getFeatureAttributeGetter();
975 45581 fdiaz
            if (getter != null) {
976 44022 jjdelcerro
                value = getter.getter(value);
977
            }
978 40435 jjdelcerro
        }
979 45993 omartinez
        value = coerce(featureAttributeDescriptor, value);
980
        return value;
981
    }
982
983
    private Object coerce(FeatureAttributeDescriptor attr, Object value) {
984 47091 jjdelcerro
        if( value == null ) {
985
            return null;
986
        }
987 45993 omartinez
        DataType dataType = attr.getDataType();
988 45047 jjdelcerro
        Class<? extends DataType> theClass = dataType.getDefaultClass();
989 45581 fdiaz
        if (theClass != null && !theClass.isInstance(value)) {
990 44951 omartinez
            try {
991
                value = this.getDataTypesManager().coerce(dataType.getType(), value);
992
            } catch (CoercionException e) {
993 45581 fdiaz
                throw new IllegalArgumentException(
994
                        "Can't convert to " + theClass.getSimpleName()
995 47091 jjdelcerro
                        + " from '" + value==null? "NULL":value.getClass().getSimpleName()
996
                        + "' with value '" + Objects.toString(value) + "'.");
997 44951 omartinez
            }
998
        }
999 45993 omartinez
        if (attr.getType() == DataTypes.GEOMETRY) {
1000 45581 fdiaz
            if (value != null) {
1001
                Geometry geom = (Geometry) value;
1002
                if (geom.getProjection() == null) {
1003 45993 omartinez
                    IProjection proj = ((DefaultFeatureAttributeDescriptor) attr).getSRS(this.storeRef);
1004 44022 jjdelcerro
                    geom.setProjection(proj);
1005
                }
1006
            }
1007 41335 jjdelcerro
        }
1008
        return value;
1009 40435 jjdelcerro
    }
1010
1011 44297 jjdelcerro
    @Override
1012
    public byte[] getByteArray(String name) {
1013 46162 jjdelcerro
        return (byte[]) this.get(name);
1014 44297 jjdelcerro
    }
1015
1016
    @Override
1017
    public byte[] getByteArray(int index) {
1018
        return (byte[]) this.get(index);
1019
    }
1020
1021
    @Override
1022 40435 jjdelcerro
    public Object[] getArray(String name) {
1023 46162 jjdelcerro
        return (Object[]) this.get(name);
1024 40435 jjdelcerro
    }
1025
1026 44297 jjdelcerro
    @Override
1027 40435 jjdelcerro
    public Object[] getArray(int index) {
1028
        return (Object[]) this.get(index);
1029
    }
1030
1031 44297 jjdelcerro
    @Override
1032 40435 jjdelcerro
    public boolean getBoolean(String name) {
1033 46162 jjdelcerro
        Boolean value = ((Boolean) this.get(name, Boolean.class, DataTypes.BOOLEAN));
1034
        if (value == null) {
1035
            return false;
1036
        }
1037
        return value;
1038 40435 jjdelcerro
    }
1039
1040 44297 jjdelcerro
    @Override
1041 40435 jjdelcerro
    public boolean getBoolean(int index) {
1042 45581 fdiaz
        Boolean value = ((Boolean) this.get(index, Boolean.class, DataTypes.BOOLEAN));
1043 40435 jjdelcerro
        if (value == null) {
1044
            return false;
1045
        }
1046 44297 jjdelcerro
        return value;
1047 40435 jjdelcerro
    }
1048
1049 44297 jjdelcerro
    @Override
1050 40435 jjdelcerro
    public byte getByte(String name) {
1051 46162 jjdelcerro
        Byte value = ((Byte) this.get(name, Byte.class, DataTypes.BYTE));
1052
        if (value == null) {
1053
            return 0;
1054
        }
1055
        return value;
1056 40435 jjdelcerro
    }
1057
1058 44297 jjdelcerro
    @Override
1059 40435 jjdelcerro
    public byte getByte(int index) {
1060 45581 fdiaz
        Byte value = ((Byte) this.get(index, Byte.class, DataTypes.BYTE));
1061 40435 jjdelcerro
        if (value == null) {
1062
            return 0;
1063
        }
1064 44297 jjdelcerro
        return value;
1065 40435 jjdelcerro
    }
1066
1067 44297 jjdelcerro
    @Override
1068 45425 jjdelcerro
    public java.sql.Date getDate(String name) {
1069 46162 jjdelcerro
        java.sql.Date value = ((java.sql.Date) this.get(name, java.sql.Date.class, DataTypes.DATE));
1070
        return value;
1071 40435 jjdelcerro
    }
1072
1073 44297 jjdelcerro
    @Override
1074 45425 jjdelcerro
    public java.sql.Date getDate(int index) {
1075 45581 fdiaz
        java.sql.Date value = ((java.sql.Date) this.get(index, java.sql.Date.class, DataTypes.DATE));
1076 44767 jjdelcerro
        return value;
1077
    }
1078 40435 jjdelcerro
1079 44767 jjdelcerro
    @Override
1080 45425 jjdelcerro
    public java.sql.Time getTime(String name) {
1081 46162 jjdelcerro
        java.sql.Time value = ((java.sql.Time) this.get(name, java.sql.Time.class, DataTypes.TIME));
1082
        return value;
1083 44767 jjdelcerro
    }
1084
1085
    @Override
1086 45425 jjdelcerro
    public java.sql.Time getTime(int index) {
1087 45581 fdiaz
        java.sql.Time value = ((java.sql.Time) this.get(index, java.sql.Time.class, DataTypes.TIME));
1088 40435 jjdelcerro
        return value;
1089
    }
1090
1091 44297 jjdelcerro
    @Override
1092 45425 jjdelcerro
    public java.sql.Timestamp getTimestamp(String name) {
1093 46162 jjdelcerro
        java.sql.Timestamp value = ((java.sql.Timestamp) this.get(name, java.sql.Timestamp.class, DataTypes.TIMESTAMP));
1094
        return value;
1095 44767 jjdelcerro
    }
1096
1097
    @Override
1098 45425 jjdelcerro
    public java.sql.Timestamp getTimestamp(int index) {
1099 45581 fdiaz
        java.sql.Timestamp value = ((java.sql.Timestamp) this.get(index, java.sql.Timestamp.class, DataTypes.TIMESTAMP));
1100 44767 jjdelcerro
        return value;
1101
    }
1102
1103
    @Override
1104 40435 jjdelcerro
    public double getDouble(String name) {
1105 46162 jjdelcerro
        Double value = ((Double) this.get(name, Double.class, DataTypes.DOUBLE));
1106
        if (value == null) {
1107
            return 0;
1108
        }
1109
        return value;
1110 40435 jjdelcerro
    }
1111
1112 44297 jjdelcerro
    @Override
1113 40435 jjdelcerro
    public double getDouble(int index) {
1114 43729 fdiaz
1115 45581 fdiaz
        Double value = ((Double) this.get(index, Double.class, DataTypes.DOUBLE));
1116 40435 jjdelcerro
        if (value == null) {
1117
            return 0;
1118
        }
1119 44297 jjdelcerro
        return value;
1120 40435 jjdelcerro
    }
1121
1122 44297 jjdelcerro
    @Override
1123 44669 jjdelcerro
    public BigDecimal getDecimal(String name) {
1124 46162 jjdelcerro
        BigDecimal value = ((BigDecimal) this.get(name, BigDecimal.class, DataTypes.DECIMAL));
1125
        return value;
1126 44669 jjdelcerro
    }
1127
1128
    @Override
1129
    public BigDecimal getDecimal(int index) {
1130 45581 fdiaz
        BigDecimal value = ((BigDecimal) this.get(index, BigDecimal.class, DataTypes.DECIMAL));
1131 44669 jjdelcerro
        return value;
1132
    }
1133
1134
    @Override
1135 40435 jjdelcerro
    public Feature getFeature(String name) {
1136
        return this.getFeature(this.data.getType().getIndex(name));
1137
    }
1138
1139 44297 jjdelcerro
    @Override
1140 40435 jjdelcerro
    public Feature getFeature(int index) {
1141
        return (Feature) this.get(index);
1142
    }
1143
1144 44297 jjdelcerro
    @Override
1145 40435 jjdelcerro
    public float getFloat(String name) {
1146 46162 jjdelcerro
        Float value = ((Float) this.get(name, Float.class, DataTypes.FLOAT));
1147
        if (value == null) {
1148
            return 0;
1149
        }
1150
        return value;
1151 40435 jjdelcerro
    }
1152
1153 44297 jjdelcerro
    @Override
1154 40435 jjdelcerro
    public float getFloat(int index) {
1155 45581 fdiaz
        Float value = ((Float) this.get(index, Float.class, DataTypes.FLOAT));
1156 40435 jjdelcerro
        if (value == null) {
1157
            return 0;
1158
        }
1159 44297 jjdelcerro
        return value;
1160 40435 jjdelcerro
    }
1161
1162 44297 jjdelcerro
    @Override
1163 40435 jjdelcerro
    public Geometry getGeometry(String name) {
1164 46162 jjdelcerro
        return (Geometry) this.get(name, Geometry.class, DataTypes.GEOMETRY);
1165 40435 jjdelcerro
    }
1166
1167 44297 jjdelcerro
    @Override
1168 40435 jjdelcerro
    public Geometry getGeometry(int index) {
1169 45581 fdiaz
        return (Geometry) this.get(index, Geometry.class, DataTypes.GEOMETRY);
1170 40435 jjdelcerro
    }
1171
1172 44297 jjdelcerro
    @Override
1173 40435 jjdelcerro
    public int getInt(String name) {
1174 46162 jjdelcerro
        Integer value = ((Integer) this.get(name, Integer.class, DataTypes.INT));
1175
        if (value == null) {
1176
            return 0;
1177
        }
1178
        return value;
1179 40435 jjdelcerro
    }
1180
1181 44297 jjdelcerro
    @Override
1182 40435 jjdelcerro
    public int getInt(int index) {
1183 45581 fdiaz
        Integer value = ((Integer) this.get(index, Integer.class, DataTypes.INT));
1184 40435 jjdelcerro
        if (value == null) {
1185
            return 0;
1186
        }
1187 44297 jjdelcerro
        return value;
1188 40435 jjdelcerro
    }
1189
1190 44297 jjdelcerro
    @Override
1191 40435 jjdelcerro
    public long getLong(String name) {
1192 46162 jjdelcerro
        Long value = ((Long) this.get(name, Long.class, DataTypes.LONG));
1193
        if (value == null) {
1194
            return 0;
1195
        }
1196
        return value;
1197 40435 jjdelcerro
    }
1198
1199 44297 jjdelcerro
    @Override
1200 40435 jjdelcerro
    public long getLong(int index) {
1201 45581 fdiaz
        Long value = ((Long) this.get(index, Long.class, DataTypes.LONG));
1202 40435 jjdelcerro
        if (value == null) {
1203
            return 0;
1204
        }
1205 44297 jjdelcerro
        return value;
1206 40435 jjdelcerro
    }
1207
1208 44297 jjdelcerro
    @Override
1209 40435 jjdelcerro
    public String getString(String name) {
1210 46162 jjdelcerro
        return (String) this.get(name, String.class, DataTypes.STRING);
1211 40435 jjdelcerro
    }
1212
1213 44297 jjdelcerro
    @Override
1214 40435 jjdelcerro
    public String getString(int index) {
1215 45581 fdiaz
        return (String) this.get(index, String.class, DataTypes.STRING);
1216 40435 jjdelcerro
    }
1217
1218 44297 jjdelcerro
    @Override
1219 40435 jjdelcerro
    public Object getContextValue(String name) {
1220
        name = name.toLowerCase();
1221
        if (name.equals("store")) {
1222
            return this.getStore();
1223
        }
1224
1225
        if (name.equals("featuretype")) {
1226
            return this.data.getType();
1227
        }
1228
1229
        if (name.equals("feature")) {
1230
            return this;
1231
        }
1232
1233
        throw new IllegalArgumentException(name);
1234
    }
1235
1236 44297 jjdelcerro
    @Override
1237 40435 jjdelcerro
    public Iterator getDataNames() {
1238
        class DataNamesIterator implements Iterator {
1239 45581 fdiaz
1240 40435 jjdelcerro
            Iterator attributeIteraror;
1241
1242
            DataNamesIterator(DefaultFeature feature) {
1243
                this.attributeIteraror = feature.getType().iterator();
1244
            }
1245
1246 44297 jjdelcerro
            @Override
1247 40435 jjdelcerro
            public boolean hasNext() {
1248
                return this.attributeIteraror.hasNext();
1249
            }
1250
1251 44297 jjdelcerro
            @Override
1252 40435 jjdelcerro
            public Object next() {
1253
                return ((FeatureAttributeDescriptor) this.attributeIteraror
1254
                        .next()).getName();
1255
            }
1256
1257 44297 jjdelcerro
            @Override
1258 40435 jjdelcerro
            public void remove() {
1259
                throw new UnsupportedOperationException();
1260
            }
1261
1262
        }
1263
        return new DataNamesIterator(this);
1264
    }
1265
1266 44297 jjdelcerro
    @Override
1267 40435 jjdelcerro
    public Object getDataValue(String name) {
1268
        name = name.toLowerCase();
1269 41542 jjdelcerro
        try {
1270
            return get(name);
1271
        } catch (IllegalArgumentException ex) {
1272 45581 fdiaz
            if ("defaultgeometry".equalsIgnoreCase(name)) {
1273 41542 jjdelcerro
                return this.getDefaultGeometry();
1274
            }
1275
            throw ex;
1276
        }
1277 40435 jjdelcerro
    }
1278
1279 44297 jjdelcerro
    @Override
1280 40435 jjdelcerro
    public Iterator getDataValues() {
1281
        class DataValuesIterator implements Iterator {
1282 45581 fdiaz
1283 40435 jjdelcerro
            DefaultFeature feature;
1284
            int current = 0;
1285
1286
            DataValuesIterator(DefaultFeature feature) {
1287
                this.feature = feature;
1288
            }
1289
1290 44297 jjdelcerro
            @Override
1291 40435 jjdelcerro
            public boolean hasNext() {
1292
                return current < feature.getType().size() - 1;
1293
            }
1294
1295 44297 jjdelcerro
            @Override
1296 40435 jjdelcerro
            public Object next() {
1297
                return feature.get(current++);
1298
            }
1299
1300 44297 jjdelcerro
            @Override
1301 40435 jjdelcerro
            public void remove() {
1302
                throw new UnsupportedOperationException();
1303
            }
1304
1305
        }
1306
        return new DataValuesIterator(this);
1307
    }
1308
1309 44297 jjdelcerro
    @Override
1310 40435 jjdelcerro
    public boolean hasContextValue(String name) {
1311
        name = name.toLowerCase();
1312
        if (name.equals("store")) {
1313
            return true;
1314
        }
1315
1316
        if (name.equals("featuretype")) {
1317
            return true;
1318
        }
1319
1320 44297 jjdelcerro
        return name.equals("feature");
1321 40435 jjdelcerro
    }
1322
1323 44297 jjdelcerro
    @Override
1324 40435 jjdelcerro
    public boolean hasDataValue(String name) {
1325 45218 omartinez
        return this.hasValue(name);
1326 40435 jjdelcerro
    }
1327 43729 fdiaz
1328 44767 jjdelcerro
//    @Override
1329
//    public Time getTime(int index) {
1330
//        return ((Time) this.get(index,Time.class,DataTypes.INSTANT));
1331
//    }
1332
//
1333
//    @Override
1334
//    public Time getTime(String name) {
1335
//        return this.getInstant(this.data.getType().getIndex(name));
1336
//    }
1337
//
1338
//    @Override
1339
//    public Instant getInstant(int index) {
1340
//        return ((Instant) this.get(index,Instant.class,DataTypes.INSTANT));
1341
//    }
1342
//
1343
//    @Override
1344
//    public Instant getInstant(String name) {
1345
//        return this.getInstant(this.data.getType().getIndex(name));
1346
//    }
1347
//
1348
//    @Override
1349
//    public Interval getInterval(int index) {
1350
//        return ((Interval) this.get(index,Interval.class,DataTypes.INTERVAL));
1351
//    }
1352
//
1353
//    @Override
1354
//    public Interval getInterval(String name) {
1355
//        return this.getInterval(this.data.getType().getIndex(name));
1356
//    }
1357
//
1358 44297 jjdelcerro
    @Override
1359 40435 jjdelcerro
    public DynObject getAsDynObject() {
1360 42775 jjdelcerro
        DynObjectFeatureFacade facade = new DynObjectFeatureFacade(this);
1361 40435 jjdelcerro
        return facade;
1362
    }
1363
1364 44297 jjdelcerro
    @Override
1365 40435 jjdelcerro
    public String toString() {
1366 45581 fdiaz
        StringBuilder builder = new StringBuilder();
1367
        FeatureAttributeDescriptor[] attributeDescriptors
1368
                = getType().getAttributeDescriptors();
1369 40435 jjdelcerro
        for (int i = 0; i < attributeDescriptors.length; i++) {
1370
            String name = attributeDescriptors[i].getName();
1371 44607 jjdelcerro
            Object value = get(name);
1372
            builder.append(value);
1373 40435 jjdelcerro
            if (i < attributeDescriptors.length - 1) {
1374 44297 jjdelcerro
                builder.append(", ");
1375 40435 jjdelcerro
            }
1376
        }
1377 44297 jjdelcerro
        return builder.toString();
1378 40435 jjdelcerro
    }
1379 40867 jbadia
1380 45581 fdiaz
    /**
1381 45785 fdiaz
     * It is a new feature that has already been inserted into the store but has not yet been saved to disk
1382
     *
1383 40435 jjdelcerro
     * @return the inserted
1384
     */
1385
    public boolean isInserted() {
1386
        return inserted;
1387
    }
1388
1389
    /**
1390 45785 fdiaz
     * If true, marks the feature as already inserted in the vault but has not yet been saved to disk
1391
     *
1392 40435 jjdelcerro
     * @param inserted the inserted to set
1393
     */
1394
    public void setInserted(boolean inserted) {
1395
        this.inserted = inserted;
1396 45640 jjdelcerro
//        this.data.setNew(!inserted);
1397 40435 jjdelcerro
    }
1398
1399 45581 fdiaz
    @Override
1400 40435 jjdelcerro
    public EvaluatorData getEvaluatorData() {
1401
        return this;
1402
    }
1403 43983 jjdelcerro
1404 45013 jjdelcerro
    @Override
1405 43983 jjdelcerro
    public int size() {
1406
        return this.data.getType().size();
1407
    }
1408 45581 fdiaz
1409 43983 jjdelcerro
    public boolean isEmpty() {
1410
        return false;
1411
    }
1412
1413
    public Iterator<String> iterator() {
1414
        final Iterator<FeatureAttributeDescriptor> x = this.data.getType().iterator();
1415
        return new Iterator<String>() {
1416
            @Override
1417
            public boolean hasNext() {
1418
                return x.hasNext();
1419
            }
1420
1421
            @Override
1422
            public String next() {
1423
                return x.next().getName();
1424
            }
1425
        };
1426
    }
1427 45581 fdiaz
1428 43983 jjdelcerro
    public boolean containsKey(String key) {
1429 45581 fdiaz
        return this.data.getType().get(key) != null;
1430 43983 jjdelcerro
    }
1431 44346 jjdelcerro
1432
    @Override
1433
    public String getLabelOfValue(String name) {
1434
        FeatureAttributeDescriptor attrdesc = this.data.getType().getAttributeDescriptor(name);
1435 46050 omartinez
        Object value;
1436
        if (attrdesc == null) { // extra column
1437
            FeatureExtraColumns extraColumns = this.data.getType().getExtraColumns();
1438
            if (extraColumns==null) {
1439
                return name;
1440
            }
1441
            attrdesc = extraColumns.get(name);
1442
            if(attrdesc==null) {
1443
                return name;
1444
            }
1445
           value = this.get(name);
1446
        } else {
1447
           value = this.get(attrdesc.getIndex());
1448 44346 jjdelcerro
        }
1449 46734 jjdelcerro
        String label;
1450
        try {
1451
            label = attrdesc.getLabelOfValue(value);
1452
        } catch(Throwable th) {
1453
            label = Objects.toString(value, "");
1454
        }
1455 44346 jjdelcerro
        return label;
1456
    }
1457 45581 fdiaz
1458 44858 jjdelcerro
    @Override
1459
    public void setExtraValue(String name, Object value) {
1460 45581 fdiaz
        if (this.extraValues == null) {
1461
            this.extraValues = new HashMap<>();
1462
        }
1463
        this.extraValues.put(name, value);
1464 44858 jjdelcerro
    }
1465 45581 fdiaz
1466 45155 omartinez
    public Object getExtraColumnValue(String name) {
1467 44779 omartinez
        Object value;
1468 45993 omartinez
        FeatureExtraColumns columns = this.getType().getExtraColumns();
1469
        int index = columns.getIndexOf(name);
1470 45162 omartinez
        if (this.extraValues != null) {
1471
            if (this.extraValues.containsKey(name)) {
1472 45993 omartinez
                value = this.extraValues.get(name);
1473
                if (index >= 0){
1474
                    EditableFeatureAttributeDescriptor attrdesc = columns.get(index);
1475
                    value = coerce(attrdesc, value);
1476
                }
1477
                return value;
1478 45162 omartinez
            }
1479 44858 jjdelcerro
        }
1480 45162 omartinez
        if (index < 0) {
1481
            throw new RuntimeException("Not extra column value found");
1482
        }
1483
        if (extraValuesData == null) {
1484 44779 omartinez
            extraValuesData = new Object[columns.size()];
1485 45162 omartinez
        }
1486
        EditableFeatureAttributeDescriptor attrdesc = columns.get(index);
1487
        value = extraValuesData[index];
1488 45581 fdiaz
        if (value != null) {
1489 45162 omartinez
            return value;
1490
        }
1491
        value = this.getExtraValue(name);
1492 45993 omartinez
        if (value == null && !this.hasExtraValue(name) && attrdesc.getFeatureAttributeEmulator() != null) {
1493
            value = attrdesc.getFeatureAttributeEmulator().get(this);
1494
            value = coerce(attrdesc, value);
1495
            extraValuesData[index] = value;
1496
        } else {
1497
            value = coerce(attrdesc, value);
1498
            extraValuesData[index] = value;
1499 44778 omartinez
        }
1500 45993 omartinez
1501 45162 omartinez
        return value;
1502 45155 omartinez
    }
1503
1504
    @Override
1505
    public Object getExtraValue(String name) {
1506
        Object value = this.data.getExtraValue(name);
1507 44773 jjdelcerro
        return value;
1508 44376 jjdelcerro
    }
1509 45581 fdiaz
1510 44773 jjdelcerro
    @Override
1511 44738 jjdelcerro
    public boolean hasExtraValue(String name) {
1512 45155 omartinez
        return this.data.hasExtraValue(name);
1513
    }
1514
1515
    private boolean hasExtraColumnValue(String name) {
1516 45581 fdiaz
        if (this.extraValues != null) {
1517
            if (this.extraValues.containsKey(name)) {
1518
                return true;
1519
            }
1520 44858 jjdelcerro
        }
1521 44829 omartinez
        FeatureExtraColumns columns = this.getType().getExtraColumns();
1522 44779 omartinez
        int index = columns.getIndexOf(name);
1523 45581 fdiaz
        if (index >= 0) {
1524
            return true;
1525 44779 omartinez
        }
1526 45155 omartinez
        return false;
1527 44738 jjdelcerro
    }
1528 45581 fdiaz
1529 45968 jjdelcerro
    private EditableFeatureAttributeDescriptor getExtraColumn(String name) {
1530
        FeatureExtraColumns columns = this.getType().getExtraColumns();
1531
        return columns.get(name);
1532
    }
1533
1534 44376 jjdelcerro
    @Override
1535 45218 omartinez
    public boolean hasValue(String name) {
1536
        name = name.toLowerCase();
1537 45581 fdiaz
        return this.data.getType().getIndex(name) >= 0
1538
                || hasExtraValue(name)
1539
                || hasExtraColumnValue(name);
1540 45218 omartinez
    }
1541 45581 fdiaz
1542 45218 omartinez
    @Override
1543 44376 jjdelcerro
    public Object getExtraValue(int index) {
1544
        return this.data.getExtraValue(index);
1545
    }
1546
1547 45425 jjdelcerro
    @Override
1548
    public JsonObject toJson() {
1549
        JsonObjectBuilder builder = this.toJsonBuilder();
1550
        return builder.build();
1551
    }
1552 46966 fdiaz
1553
    public JsonObject toJson(Map<String, Object> props) {
1554
        JsonObjectBuilder builder = this.toJsonBuilder(props);
1555
        return builder.build();
1556
    }
1557 45581 fdiaz
1558 45425 jjdelcerro
    @Override
1559
    public JsonObjectBuilder toJsonBuilder() {
1560 46916 jjdelcerro
        return this.toJsonBuilder(null, Bitmask.createBitmask(TOJSON_MODE_SHALLOW), null);
1561
//        JsonObjectBuilder builder = Json.createObjectBuilder();
1562
//        Date date;
1563
//        Geometry geom;
1564
//        FeatureType ft = this.getType();
1565
//        for (FeatureAttributeDescriptor desc : ft) {
1566
//            if (desc.isComputed()) {
1567
//                continue;
1568
//            }
1569
//            if(this.isNull(desc.getName())){
1570
//                builder.addNull(desc.getName());
1571
//                continue;
1572
//            }
1573
//            switch (desc.getType()) {
1574
//                case DataTypes.GEOMETRY:
1575
//                    geom = this.getGeometry(desc.getIndex());
1576
//                    if (geom != null) {
1577
//                        builder.add(desc.getName(), geom.convertToHexWKBQuietly());
1578
//                    }
1579
//                    break;
1580
//                case DataTypes.BOOLEAN:
1581
//                    builder.add(desc.getName(), this.getBoolean(desc.getIndex()));
1582
//                    break;
1583
//                case DataTypes.BYTE:
1584
//                    builder.add(desc.getName(), this.getByte(desc.getIndex()));
1585
//                    break;
1586
//                case DataTypes.INT:
1587
//                    builder.add(desc.getName(), this.getInt(desc.getIndex()));
1588
//                    break;
1589
//                case DataTypes.LONG:
1590
//                    builder.add(desc.getName(), this.getLong(desc.getIndex()));
1591
//                    break;
1592
//                case DataTypes.DOUBLE:
1593
//                    builder.add(desc.getName(), this.getDouble(desc.getIndex()));
1594
//                    break;
1595
//                case DataTypes.FLOAT:
1596
//                    builder.add(desc.getName(), this.getFloat(desc.getIndex()));
1597
//                    break;
1598
//                case DataTypes.DECIMAL:
1599
//                    builder.add(desc.getName(), this.getDecimal(desc.getIndex()));
1600
//                    break;
1601
//                case DataTypes.DATE:
1602
//                    // Format date as ISO 8601
1603
//                    date = this.getDate(desc.getIndex());
1604
//                    if (date == null) {
1605
//                        builder.addNull(desc.getName());
1606
//                    } else {
1607
//                        LocalDateTime localDateTime = LocalDateTime.ofInstant(new Date(date.getTime()).toInstant(), ZoneId.systemDefault());
1608
//                        String value = DateTimeFormatter.ISO_DATE.format(localDateTime);
1609
//                        builder.add(desc.getName(), value);
1610
//                    }
1611
//                    break;
1612
//                case DataTypes.TIMESTAMP:
1613
//                    // Format date as ISO 8601
1614
//                    date = this.getTimestamp(desc.getIndex());
1615
//                    if (date == null) {
1616
//                        builder.addNull(desc.getName());
1617
//                    } else {
1618
//                        LocalDateTime localDateTime = LocalDateTime.ofInstant(new Date(date.getTime()).toInstant(), ZoneId.systemDefault());
1619
//                        String value = DateTimeFormatter.ISO_DATE_TIME.format(localDateTime);
1620
//                        builder.add(desc.getName(), value);
1621
//                    }
1622
//                    break;
1623
//                case DataTypes.TIME:
1624
//                    // Format date as ISO 8601
1625
//                    date = this.getTime(desc.getIndex());
1626
//                    if (date == null) {
1627
//                        builder.addNull(desc.getName());
1628
//                    } else {
1629
//                        LocalDateTime localDateTime = LocalDateTime.ofInstant(new Date(date.getTime()).toInstant(), ZoneId.systemDefault());
1630
//                        String value = DateTimeFormatter.ISO_TIME.format(localDateTime);
1631
//                        builder.add(desc.getName(), value);
1632
//                    }
1633
//                    break;
1634
//                default:
1635
//                    builder.add(desc.getName(), this.getStringOrDefault(desc.getIndex(), ""));
1636
//            }
1637
//        }
1638
//        return builder;
1639
    }
1640
1641
    public static final String TOJSON_MODE = "mode";
1642 47756 fdiaz
    public static final String FORMAT_MODE = "format";
1643
1644
    public static final String FORMAT_MODE_GVSIGDESKTOP = "gvsigdesktop";
1645
    public static final String FORMAT_MODE_GEOJSON = "geojson";
1646
1647 46916 jjdelcerro
    public static final int TOJSON_MODE_SHALLOW = 0;
1648
    public static final int TOJSON_MODE_DEEP =        0b00001;
1649
    public static final int TOJSON_MODE_COMPUTEDS =   0b00010;
1650
    public static final int TOJSON_MODE_COLLECTIONS = 0b00100;
1651
1652
    @Override
1653
    public JsonObjectBuilder toJsonBuilder(Map<String, Object> props) {
1654 47756 fdiaz
        if( props == null ) {
1655
            return toJsonBuilderDefault(props);
1656
        }
1657
        String format = (String) props.getOrDefault(FORMAT_MODE,FORMAT_MODE_GVSIGDESKTOP);
1658
        switch(format.toLowerCase()) {
1659
            case FORMAT_MODE_GEOJSON:
1660
                return toJsonBuilderGeoJson(props);
1661
            case FORMAT_MODE_GVSIGDESKTOP:
1662
            default:
1663
                return toJsonBuilderDefault(props);
1664
        }
1665
    }
1666
1667
    public JsonObjectBuilder toJsonBuilderDefault(Map<String, Object> props) {
1668 46916 jjdelcerro
        Bitmask modemask = null;
1669
        Set<String> visiteds = null;
1670
        int mode = TOJSON_MODE_SHALLOW;
1671
        if( props!=null ) {
1672
            mode = (int) props.getOrDefault(TOJSON_MODE,mode);
1673
            modemask = Bitmask.createBitmask(mode);
1674
            if( modemask.isSetBits(TOJSON_MODE_DEEP) ) {
1675
                visiteds = (Set<String>) props.getOrDefault("visiteds", null);
1676
                if( visiteds == null ) {
1677
                    visiteds = new HashSet<>();
1678
                    props.put("visiteds", visiteds);
1679
                }
1680
            }
1681
        } else {
1682
            modemask = Bitmask.createBitmask(mode);
1683
        }
1684
        return this.toJsonBuilder(props, modemask, visiteds);
1685
    }
1686
1687 47756 fdiaz
    private JsonObjectBuilder toJsonBuilderGeoJson(Map<String, Object> props) {
1688
        FeatureType ft = this.getType();
1689
        Geometry geom = this.getDefaultGeometry();
1690
1691
        Bitmask mode = Bitmask.createBitmask((int) props.getOrDefault(TOJSON_MODE,TOJSON_MODE_SHALLOW));
1692
        boolean skipNulls = (boolean) props.getOrDefault("skipnulls", false);
1693 47779 fdiaz
        String[] skipFields = (String[]) props.getOrDefault("skipfields", null);
1694 47756 fdiaz
        Map<String,Object>properties = new HashMap<>();
1695
1696
        for (FeatureAttributeDescriptor desc : ft) {
1697
            if (desc.isComputed() ) {
1698
                if( !mode.isSetBits(TOJSON_MODE_COMPUTEDS) ) {
1699
                    continue;
1700
                }
1701
            }
1702 47779 fdiaz
            if(ArrayUtils.contains(skipFields, desc.getName())) {
1703 47756 fdiaz
                continue;
1704
            }
1705 47779 fdiaz
1706
            if(desc.getType() == DataTypes.GEOMETRY){
1707
                continue;
1708
            }
1709
1710 47756 fdiaz
            if( this.isNull(desc.getName()) ){
1711
                if(!skipNulls){
1712
                    properties.put(desc.getName(),null);
1713
                }
1714
                continue;
1715
            }
1716
            switch (desc.getType()) {
1717
                case DataTypes.BOOLEAN:
1718
                    properties.put(desc.getName(), this.getBoolean(desc.getIndex()));
1719
                    break;
1720
                case DataTypes.BYTE:
1721
                    properties.put(desc.getName(), this.getByte(desc.getIndex()));
1722
                    break;
1723
                case DataTypes.INT:
1724
                    properties.put(desc.getName(), this.getInt(desc.getIndex()));
1725
                    break;
1726
                case DataTypes.LONG:
1727
                    properties.put(desc.getName(), this.getLong(desc.getIndex()));
1728
                    break;
1729
                case DataTypes.DOUBLE:
1730
                    properties.put(desc.getName(), this.getDouble(desc.getIndex()));
1731
                    break;
1732
                case DataTypes.FLOAT:
1733
                    properties.put(desc.getName(), this.getFloat(desc.getIndex()));
1734
                    break;
1735
                case DataTypes.DECIMAL:
1736
                    properties.put(desc.getName(), this.getDecimal(desc.getIndex()));
1737
                    break;
1738
                case DataTypes.DATE: {
1739
                        // Format date as ISO 8601
1740
                        java.sql.Date date = this.getDate(desc.getIndex());
1741
                        LocalDateTime localDateTime = LocalDateTime.ofInstant(new Date(date.getTime()).toInstant(), ZoneId.systemDefault());
1742
                        String value = DateTimeFormatter.ISO_DATE.format(localDateTime);
1743
                        properties.put(desc.getName(), value);
1744
                    }
1745
                    break;
1746
                case DataTypes.TIMESTAMP: {
1747
                        // Format date as ISO 8601
1748
                        java.sql.Date date = this.getDate(desc.getIndex());
1749
                        LocalDateTime localDateTime = LocalDateTime.ofInstant(new Date(date.getTime()).toInstant(), ZoneId.systemDefault());
1750
                        String value = DateTimeFormatter.ISO_DATE_TIME.format(localDateTime);
1751
                        properties.put(desc.getName(), value);
1752
                    }
1753
                    break;
1754
                case DataTypes.TIME: {
1755
                        // Format date as ISO 8601
1756
                        java.sql.Date date = this.getDate(desc.getIndex());
1757
                        LocalDateTime localDateTime = LocalDateTime.ofInstant(new Date(date.getTime()).toInstant(), ZoneId.systemDefault());
1758
                        String value = DateTimeFormatter.ISO_TIME.format(localDateTime);
1759
                        properties.put(desc.getName(), value);
1760
                    }
1761
                    break;
1762
1763
1764
                default:
1765
                    properties.put(desc.getName(), this.getStringOrDefault(desc.getIndex(), ""));
1766
            }
1767
        }
1768
        String json_s;
1769
        try {
1770
            json_s = geom.convertToGeoJson(properties, (boolean) props.getOrDefault("encodecrs", true));
1771
        } catch (Exception ex) {
1772
            throw new ConvertFeatureToGeoJsonException(ex);
1773
        }
1774
        JsonObjectBuilder json = Json.createObjectBuilder(json_s);
1775
        return json;
1776
1777
    }
1778
1779
    private static class ConvertFeatureToGeoJsonException extends DataRuntimeException {
1780
1781
        private static final long serialVersionUID = -1;
1782
        private final static String MESSAGE_FORMAT = "Create GeoJson builder exception.";
1783
        private final static String MESSAGE_KEY = "_ConvertFeatureToGeoJsonException";
1784
1785
        public ConvertFeatureToGeoJsonException(Throwable cause) {
1786
            super(MESSAGE_FORMAT, cause, MESSAGE_KEY, serialVersionUID);
1787
        }
1788
1789
    }
1790
1791 46916 jjdelcerro
    private JsonObjectBuilder toJsonBuilder(Map<String, Object> props, Bitmask mode, Set<String> visiteds) {
1792 44655 jjdelcerro
        JsonObjectBuilder builder = Json.createObjectBuilder();
1793 45425 jjdelcerro
        Date date;
1794
        Geometry geom;
1795 44655 jjdelcerro
        FeatureType ft = this.getType();
1796 46916 jjdelcerro
1797 46956 fdiaz
        boolean hasVisited = false;
1798
        if(visiteds != null){
1799
            FeatureReference ref = this.getReference();
1800
            String code = ref.getCode();
1801
            hasVisited = visiteds.contains(code);
1802
            if(hasVisited){
1803
               return this.featureReferenceToJson(ref);
1804
            }
1805
            visiteds.add(code);
1806
        }
1807
1808 44655 jjdelcerro
        for (FeatureAttributeDescriptor desc : ft) {
1809 46916 jjdelcerro
            if (desc.isComputed() ) {
1810
                if( !mode.isSetBits(TOJSON_MODE_COMPUTEDS) ) {
1811
                    if( !(mode.isSetBits(TOJSON_MODE_COLLECTIONS) && desc.getType()==DataTypes.LIST) ) {
1812
                        continue;
1813
                    }
1814
                }
1815 44655 jjdelcerro
            }
1816 46956 fdiaz
            if(desc.getType() != DataTypes.LIST && this.isNull(desc.getName()) ){
1817 45738 fdiaz
                builder.addNull(desc.getName());
1818
                continue;
1819
            }
1820 46916 jjdelcerro
            if( desc.isForeingKey() && !desc.getForeingKey().isClosedList() && mode.isSetBits(TOJSON_MODE_DEEP) ) {
1821 46956 fdiaz
                if( desc.getRelationType()==DynField.RELATION_TYPE_COLLABORATION_WITH_COMPOSITION) {
1822 46916 jjdelcerro
                    Object value = this.get(desc.getName());
1823 46966 fdiaz
                    if(value != null){
1824
                        Feature f = desc.getForeingKey().getFeature(null, value);
1825
                        if(f!=null){ //Ojo, si no hay constraint no tendria porque ser un error que no se encontrara la feature
1826
                            String x = f.getReference().getCode();
1827
                            if( visiteds==null ) {
1828
                                if( f instanceof DefaultFeature ) {
1829
                                    builder.add(desc.getName(), ((DefaultFeature)f).toJsonBuilder(props, mode, visiteds));
1830
                                } else {
1831
                                    builder.add(desc.getName(), f.toJsonBuilder(props));
1832
                                }
1833
                                continue;
1834
                            } else if( !visiteds.contains(x) ) {
1835
                                if( f instanceof DefaultFeature ) {
1836
                                    builder.add(desc.getName(), ((DefaultFeature)f).toJsonBuilder(props, mode, visiteds));
1837
                                } else {
1838
                                    builder.add(desc.getName(), f.toJsonBuilder(props));
1839
                                }
1840
                                continue;
1841
                            }
1842 46916 jjdelcerro
                        }
1843
                    }
1844
                }
1845
            }
1846 45581 fdiaz
            switch (desc.getType()) {
1847 44655 jjdelcerro
                case DataTypes.GEOMETRY:
1848 45425 jjdelcerro
                    geom = this.getGeometry(desc.getIndex());
1849 45581 fdiaz
                    if (geom != null) {
1850 47648 jjdelcerro
                        geom = this.getGeometry(desc.getIndex());
1851
                        Tags tags = desc.getTags();
1852
                        switch(tags.getString("geomformat", "WKB").toUpperCase()) {
1853
                            default:
1854
                            case "WKB":
1855
                            case "HEXWKB":
1856
                                builder.add(desc.getName(), geom.convertToHexWKBQuietly());
1857
                                break;
1858
                            case "EWKB":
1859
                            case "HEXEWKB":
1860
                                builder.add(desc.getName(), geom.convertToHexEWKBQuietly());
1861
                                break;
1862
                            case "WKT":
1863
                                builder.add(desc.getName(), geom.convertToWKTQuietly());
1864
                                break;
1865
                        }
1866 44655 jjdelcerro
                    }
1867
                    break;
1868 47648 jjdelcerro
1869 44655 jjdelcerro
                case DataTypes.BOOLEAN:
1870
                    builder.add(desc.getName(), this.getBoolean(desc.getIndex()));
1871
                    break;
1872
                case DataTypes.BYTE:
1873
                    builder.add(desc.getName(), this.getByte(desc.getIndex()));
1874
                    break;
1875
                case DataTypes.INT:
1876
                    builder.add(desc.getName(), this.getInt(desc.getIndex()));
1877
                    break;
1878
                case DataTypes.LONG:
1879
                    builder.add(desc.getName(), this.getLong(desc.getIndex()));
1880
                    break;
1881
                case DataTypes.DOUBLE:
1882
                    builder.add(desc.getName(), this.getDouble(desc.getIndex()));
1883
                    break;
1884
                case DataTypes.FLOAT:
1885
                    builder.add(desc.getName(), this.getFloat(desc.getIndex()));
1886
                    break;
1887 46893 fdiaz
                case DataTypes.DECIMAL:
1888
                    builder.add(desc.getName(), this.getDecimal(desc.getIndex()));
1889
                    break;
1890 44655 jjdelcerro
                case DataTypes.DATE:
1891
                    // Format date as ISO 8601
1892 45425 jjdelcerro
                    date = this.getDate(desc.getIndex());
1893 45581 fdiaz
                    if (date == null) {
1894 45003 jjdelcerro
                        builder.addNull(desc.getName());
1895
                    } else {
1896 45023 fdiaz
                        LocalDateTime localDateTime = LocalDateTime.ofInstant(new Date(date.getTime()).toInstant(), ZoneId.systemDefault());
1897 45425 jjdelcerro
                        String value = DateTimeFormatter.ISO_DATE.format(localDateTime);
1898
                        builder.add(desc.getName(), value);
1899
                    }
1900
                    break;
1901
                case DataTypes.TIMESTAMP:
1902
                    // Format date as ISO 8601
1903
                    date = this.getTimestamp(desc.getIndex());
1904 45581 fdiaz
                    if (date == null) {
1905 45425 jjdelcerro
                        builder.addNull(desc.getName());
1906
                    } else {
1907
                        LocalDateTime localDateTime = LocalDateTime.ofInstant(new Date(date.getTime()).toInstant(), ZoneId.systemDefault());
1908 45023 fdiaz
                        String value = DateTimeFormatter.ISO_DATE_TIME.format(localDateTime);
1909 45003 jjdelcerro
                        builder.add(desc.getName(), value);
1910
                    }
1911 44655 jjdelcerro
                    break;
1912 45425 jjdelcerro
                case DataTypes.TIME:
1913
                    // Format date as ISO 8601
1914
                    date = this.getTime(desc.getIndex());
1915 45581 fdiaz
                    if (date == null) {
1916 45425 jjdelcerro
                        builder.addNull(desc.getName());
1917
                    } else {
1918
                        LocalDateTime localDateTime = LocalDateTime.ofInstant(new Date(date.getTime()).toInstant(), ZoneId.systemDefault());
1919
                        String value = DateTimeFormatter.ISO_TIME.format(localDateTime);
1920
                        builder.add(desc.getName(), value);
1921
                    }
1922
                    break;
1923 46916 jjdelcerro
                case DataTypes.LIST:
1924
                    if( mode.isSetBits(TOJSON_MODE_COLLECTIONS) ) {
1925 46956 fdiaz
                        if( desc.getRelationType()== DynField.RELATION_TYPE_AGGREGATE_WITH_COMPOSITION) {
1926 46916 jjdelcerro
                            JsonArrayBuilder arraybuilder = Json.createArrayBuilder();
1927
                            Object x = this.get(desc.getName());
1928
                            if( x instanceof List ) {
1929
                                for (Object v : (List)x) {
1930
                                    if( v instanceof DefaultFeature ) {
1931 46956 fdiaz
                                            arraybuilder.add(((DefaultFeature)v).toJsonBuilder(props, mode, visiteds));
1932 46916 jjdelcerro
                                    } else if( v instanceof Feature ) {
1933
                                        arraybuilder.add(((Feature)v).toJsonBuilder(props));
1934
                                    }
1935
                                }
1936
                            }
1937 46956 fdiaz
                            DisposeUtils.disposeQuietly(x);
1938 46916 jjdelcerro
                            builder.add(desc.getName(), arraybuilder);
1939
                        }
1940
                    }
1941
                    break;
1942
1943 44655 jjdelcerro
                default:
1944 45581 fdiaz
                    builder.add(desc.getName(), this.getStringOrDefault(desc.getIndex(), ""));
1945 44655 jjdelcerro
            }
1946 45581 fdiaz
        }
1947 45425 jjdelcerro
        return builder;
1948 44655 jjdelcerro
    }
1949 46956 fdiaz
1950
    private JsonObjectBuilder featureReferenceToJson(FeatureReference ref){
1951
        JsonObjectBuilder builder = Json.createObjectBuilder();
1952
        builder.add("$reference", ref.toJsonBuilder());
1953
        return builder;
1954
    }
1955 44376 jjdelcerro
1956 44923 jjdelcerro
    @Override
1957
    public List<String> getKeys() {
1958 45581 fdiaz
        List<String> l = new ArrayList<>();
1959
        for (FeatureAttributeDescriptor descriptor : this.getType()) {
1960
            l.add(descriptor.getName());
1961
        }
1962
        return l;
1963 44923 jjdelcerro
    }
1964
1965 45968 jjdelcerro
    @Override
1966
    public String format(String name) {
1967
        int index = this.data.getType().getIndex(name);
1968
        if (index < 0) {
1969
            // buscamos en los extra cols
1970
            FeatureAttributeDescriptor attribute = this.getExtraColumn(name);
1971
            if( attribute!=null ) {
1972
                Object value = getExtraColumnValue(name);
1973
                return attribute.format(value);
1974
            }
1975
            throw new IllegalArgumentException("Attribute name '" + name + "' not found in the feature.");
1976
        }
1977
        return this.format(index);
1978
    }
1979
1980
    @Override
1981
    public String format(int index) {
1982
        Object value = this.get(index);
1983
        FeatureType type = this.data.getType();
1984
        FeatureAttributeDescriptor attribute = type.getAttributeDescriptor(index);
1985
        return attribute.format(value);
1986
    }
1987 46966 fdiaz
1988
    @Override
1989
    public Feature getForeignFeature(String attrName) {
1990 47189 fdiaz
        ForeingKey.ContextForeingKey context = null;
1991
        try {
1992
            FeatureAttributeDescriptor attr = this.getType().getAttributeDescriptor(attrName);
1993
            if (attr == null) {
1994
                return null;
1995
            }
1996
            if (!attr.isForeingKey()) {
1997
                return null;
1998
            }
1999
            ForeingKey fk = attr.getForeingKey();
2000 47415 fdiaz
            if(fk == null){
2001
                return null;
2002
            }
2003 47189 fdiaz
            context = fk.createContext();
2004
            FeatureStore store = this.getStore();
2005
            if(store instanceof SupportTransactions){
2006
                context.setTransaction(((SupportTransactions) store).getTransaction());
2007
            }
2008
            Feature foreignfeat = fk.getFeature(context, this.get(attrName));
2009
            return foreignfeat;
2010
        } catch (Exception ex) {
2011 46966 fdiaz
            return null;
2012 47189 fdiaz
        } finally {
2013
            DisposeUtils.disposeQuietly(context);
2014 46966 fdiaz
        }
2015
    }
2016 45968 jjdelcerro
2017 47078 jjdelcerro
2018
    @Override
2019
    public Expression createFilter() {
2020
        FeatureType ftype = this.getType();
2021
        FeatureAttributeDescriptor[] pk = ftype.getPrimaryKey();
2022
        if( ArrayUtils.isEmpty(pk) ) {
2023
            return null;
2024
        }
2025
        ExpressionBuilder builder = ExpressionUtils.createExpressionBuilder();
2026
        for (FeatureAttributeDescriptor attrdesc : pk) {
2027 47088 jjdelcerro
            Object value = this.get(attrdesc.getName());
2028
            if( value == null ) {
2029 47078 jjdelcerro
                builder.and(
2030 47088 jjdelcerro
                        builder.is_null(builder.column(attrdesc.getName()))
2031
                );
2032
            } else {
2033
                builder.and(
2034 47078 jjdelcerro
                        builder.eq(
2035
                                builder.column(attrdesc.getName()),
2036 47088 jjdelcerro
                                builder.constant(value)
2037 47078 jjdelcerro
                        )
2038
                );
2039 47088 jjdelcerro
            }
2040 47078 jjdelcerro
        }
2041
        Expression filter = ExpressionUtils.createExpression(builder.toString());
2042
        return filter;
2043
    }
2044 47784 jjdelcerro
}