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 / DefaultFeatureAttributeDescriptor.java @ 46093

History | View | Annotate | Download (78.6 KB)

1 40559 jjdelcerro
/**
2
 * gvSIG. Desktop Geographic Information System.
3
 *
4
 * Copyright (C) 2007-2013 gvSIG Association.
5
 *
6 42561 jjdelcerro
 * This program is free software; you can redistribute it and/or modify it under
7
 * the terms of the GNU General Public License as published by the Free Software
8
 * Foundation; either version 3 of the License, or (at your option) any later
9
 * version.
10 40559 jjdelcerro
 *
11 42561 jjdelcerro
 * This program is distributed in the hope that it will be useful, but WITHOUT
12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
14
 * details.
15 40559 jjdelcerro
 *
16 42561 jjdelcerro
 * You should have received a copy of the GNU General Public License along with
17
 * this program; if not, write to the Free Software Foundation, Inc., 51
18
 * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 40559 jjdelcerro
 *
20 42561 jjdelcerro
 * For any additional information, do not hesitate to contact us at info AT
21
 * gvsig.com, or visit our website www.gvsig.com.
22 40559 jjdelcerro
 */
23 40435 jjdelcerro
package org.gvsig.fmap.dal.feature.impl;
24
25 43739 jjdelcerro
import java.lang.ref.WeakReference;
26 44669 jjdelcerro
import java.math.BigDecimal;
27
import java.math.MathContext;
28
import java.math.RoundingMode;
29 40435 jjdelcerro
import java.text.DateFormat;
30 45739 jjdelcerro
import java.util.ArrayList;
31 40435 jjdelcerro
import java.util.HashMap;
32 44349 jjdelcerro
import java.util.LinkedHashMap;
33 40435 jjdelcerro
import java.util.List;
34 44669 jjdelcerro
import java.util.Locale;
35 40435 jjdelcerro
import java.util.Map;
36
import java.util.Map.Entry;
37 44128 jjdelcerro
import java.util.Objects;
38 45425 jjdelcerro
import java.util.function.Supplier;
39 45014 jjdelcerro
import javax.json.JsonObject;
40 42563 jjdelcerro
import org.apache.commons.lang3.ArrayUtils;
41 44190 jjdelcerro
import org.apache.commons.lang3.StringUtils;
42 45014 jjdelcerro
import org.apache.commons.lang3.tuple.Pair;
43 40435 jjdelcerro
import org.cresques.cts.IProjection;
44 45014 jjdelcerro
import org.gvsig.expressionevaluator.Expression;
45 44669 jjdelcerro
import org.gvsig.expressionevaluator.ExpressionUtils;
46 45739 jjdelcerro
import org.gvsig.expressionevaluator.MutableSymbolTable;
47 44448 jjdelcerro
import org.gvsig.fmap.dal.DALLocator;
48 44022 jjdelcerro
import org.gvsig.fmap.dal.DataStore;
49 44083 jjdelcerro
import org.gvsig.fmap.dal.DataTypes;
50 45121 jjdelcerro
import org.gvsig.fmap.dal.expressionevaluator.FeatureAttributeEmulatorExpression;
51 44448 jjdelcerro
import org.gvsig.fmap.dal.feature.DataProfile;
52 45014 jjdelcerro
import org.gvsig.fmap.dal.feature.Feature;
53 40435 jjdelcerro
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
54 42563 jjdelcerro
import org.gvsig.fmap.dal.feature.FeatureAttributeEmulator;
55 40435 jjdelcerro
import org.gvsig.fmap.dal.feature.FeatureAttributeGetter;
56 43739 jjdelcerro
import org.gvsig.fmap.dal.feature.FeatureStore;
57
import org.gvsig.fmap.dal.feature.FeatureType;
58 44262 jjdelcerro
import org.gvsig.fmap.dal.feature.ForeingKey;
59 45739 jjdelcerro
import org.gvsig.fmap.dal.feature.ForeingKey.ContextForeingKey;
60 40435 jjdelcerro
import org.gvsig.fmap.geom.Geometry;
61 45673 jjdelcerro
import org.gvsig.fmap.geom.GeometryCoercionContext;
62 40435 jjdelcerro
import org.gvsig.fmap.geom.GeometryException;
63
import org.gvsig.fmap.geom.GeometryLocator;
64 44190 jjdelcerro
import org.gvsig.fmap.geom.GeometryUtils;
65 40435 jjdelcerro
import org.gvsig.fmap.geom.type.GeometryType;
66 45425 jjdelcerro
import org.gvsig.json.Json;
67
import org.gvsig.json.JsonManager;
68
import org.gvsig.json.JsonObjectBuilder;
69
import org.gvsig.json.SupportToJson;
70 44077 jjdelcerro
import org.gvsig.timesupport.Interval;
71 44190 jjdelcerro
import org.gvsig.timesupport.RelativeInterval;
72 44077 jjdelcerro
import org.gvsig.timesupport.TimeSupportLocator;
73 40435 jjdelcerro
import org.gvsig.tools.ToolsLocator;
74 44669 jjdelcerro
import org.gvsig.tools.dataTypes.Coercion;
75 45425 jjdelcerro
import org.gvsig.tools.dataTypes.CoercionContext;
76 40435 jjdelcerro
import org.gvsig.tools.dataTypes.CoercionException;
77
import org.gvsig.tools.dataTypes.DataType;
78 45425 jjdelcerro
import org.gvsig.tools.dataTypes.DataType.NumberPrecisionAndScale;
79 44669 jjdelcerro
import org.gvsig.tools.dataTypes.DataTypeUtils;
80 45739 jjdelcerro
import org.gvsig.tools.dynobject.AbstractDynMethod;
81 40435 jjdelcerro
import org.gvsig.tools.dynobject.DynField;
82 41323 jjdelcerro
import org.gvsig.tools.dynobject.DynField_LabelAttribute;
83 42563 jjdelcerro
import org.gvsig.tools.dynobject.DynField_v2;
84 42775 jjdelcerro
import org.gvsig.tools.dynobject.DynMethod;
85 42606 jjdelcerro
import org.gvsig.tools.dynobject.DynObject;
86 40435 jjdelcerro
import org.gvsig.tools.dynobject.DynObjectValueItem;
87
import org.gvsig.tools.dynobject.DynStruct;
88 42563 jjdelcerro
import org.gvsig.tools.dynobject.Tags;
89 40435 jjdelcerro
import org.gvsig.tools.dynobject.exception.DynFieldIsNotAContainerException;
90
import org.gvsig.tools.dynobject.exception.DynFieldValidateException;
91 42775 jjdelcerro
import org.gvsig.tools.dynobject.exception.DynMethodException;
92 42563 jjdelcerro
import org.gvsig.tools.dynobject.impl.DefaultTags;
93 41212 jjdelcerro
import org.gvsig.tools.evaluator.AbstractEvaluator;
94 40435 jjdelcerro
import org.gvsig.tools.evaluator.Evaluator;
95 41212 jjdelcerro
import org.gvsig.tools.evaluator.EvaluatorData;
96
import org.gvsig.tools.evaluator.EvaluatorException;
97 44338 jjdelcerro
import org.gvsig.tools.i18n.I18nManager;
98 44190 jjdelcerro
import org.gvsig.tools.persistence.PersistenceManager;
99 40435 jjdelcerro
import org.gvsig.tools.persistence.Persistent;
100
import org.gvsig.tools.persistence.PersistentState;
101
import org.gvsig.tools.persistence.exception.PersistenceException;
102 45425 jjdelcerro
import org.gvsig.tools.util.GetItemWithSize;
103
import org.gvsig.tools.util.LabeledValue;
104 44190 jjdelcerro
import org.slf4j.Logger;
105
import org.slf4j.LoggerFactory;
106 40435 jjdelcerro
107 44259 jjdelcerro
@SuppressWarnings("UseSpecificCatch")
108 40435 jjdelcerro
public class DefaultFeatureAttributeDescriptor implements
109 42563 jjdelcerro
        FeatureAttributeDescriptor, Persistent, DynField_v2, DynField_LabelAttribute {
110 40435 jjdelcerro
111 45738 fdiaz
    protected static final Logger LOGGER = LoggerFactory.getLogger(DefaultFeatureAttributeDescriptor.class);
112 40435 jjdelcerro
113 45738 fdiaz
    protected boolean allowNull;
114
    protected DataType dataType;
115
    protected String dataProfile;
116
    protected DateFormat dateFormat;
117
    protected Object defaultValue;
118
    protected int index;
119
    protected int maximumOccurrences;
120
    protected int minimumOccurrences;
121
    protected int size;
122
    protected String name;
123
    protected Class objectClass;
124
    protected int precision;
125
    protected int scale;
126
    protected int roundMode;
127
    protected Evaluator evaluator;
128
    protected boolean primaryKey;
129
    protected boolean readOnly;
130
    protected IProjection SRS;
131
    protected GeometryType geomType;
132
    protected int geometryType;
133
    protected int geometrySubType;
134
    protected Map<String, String> additionalInfo;
135
    protected boolean isAutomatic;
136
    protected boolean isTime = false;
137
    protected Interval interval;
138
    protected FeatureAttributeGetter featureAttributeGetter = null;
139
    protected FeatureAttributeEmulator featureAttributeEmulator = null;
140
    protected boolean indexed = false;
141
    protected boolean isIndexAscending = true;
142
    protected boolean allowIndexDuplicateds = true;
143 42563 jjdelcerro
144 45738 fdiaz
    protected DynObjectValueItem[] availableValues;
145
    protected DynObjectValueItem[] availableValuesCache; // No persistente
146
    protected Expression availableValuesExpression;
147
    protected boolean avoidCachingAvailableValues;
148
    private Map<Object, String> labelOfValueMap; // No persistente
149
    protected String description;
150
    protected Object minValue;
151
    protected Object maxValue;
152
    protected String label;
153
    protected String shortLabel;
154
    protected int order;
155
    protected boolean hidden;
156
    protected String groupName;
157
    protected Tags tags = new DefaultTags();
158
    private DynMethod availableValuesMethod;
159
    private DynMethod calculateMethod;
160
    private WeakReference typeRef;
161
    protected DefaultForeingKey foreingKey = null;
162 44190 jjdelcerro
163 45738 fdiaz
    protected CoercionContext coerceContext = null; // not persistent
164
    protected MathContext mathContext = null; // not persistent
165 44673 jjdelcerro
166 45738 fdiaz
    private int relationType = RELATION_TYPE_NONE;
167
    protected Locale locale;
168
    protected int displaySize;
169 45968 jjdelcerro
170
    protected String defaultFormat;
171 44673 jjdelcerro
172 45738 fdiaz
    public DefaultFeatureAttributeDescriptor() {
173
        // Usada en la persistencia
174
        this.precision = DataType.PRECISION_NONE;
175
        this.scale = DataType.SCALE_NONE;
176
        this.roundMode = BigDecimal.ROUND_HALF_UP;
177
    }
178 44673 jjdelcerro
179 45738 fdiaz
    protected DefaultFeatureAttributeDescriptor(FeatureType type) {
180
        this();
181 44259 jjdelcerro
//        LOGGER.info(String.format("Created FeatureAttributeDescriptor [%08x].", this.hashCode()));
182 45738 fdiaz
        setFeatureType(type);
183
        this.allowNull = true;
184
        this.dataType = null;
185
        this.dateFormat = null;
186
        this.defaultValue = null;
187 45991 omartinez
        this.defaultFormat = null;
188 45738 fdiaz
        this.index = -1;
189
        this.maximumOccurrences = 0;
190
        this.minimumOccurrences = 0;
191
        this.size = 0;
192
        this.name = null;
193
        this.objectClass = null;
194
        this.precision = DataType.PRECISION_NONE;
195
        this.scale = DataType.SCALE_NONE;
196
        this.roundMode = BigDecimal.ROUND_HALF_UP;
197
        this.evaluator = null;
198
        this.primaryKey = false;
199
        this.readOnly = false;
200
        this.SRS = null;
201
        this.geometryType = Geometry.TYPES.NULL;
202
        this.geometrySubType = Geometry.SUBTYPES.UNKNOWN;
203
        this.additionalInfo = null;
204
        this.isAutomatic = false;
205
        this.hidden = false;
206
        this.relationType = RELATION_TYPE_NONE;
207
        this.locale = null;
208
        this.displaySize = 0;
209
        this.avoidCachingAvailableValues = false;
210
    }
211 40435 jjdelcerro
212 45738 fdiaz
    protected DefaultFeatureAttributeDescriptor(
213
            DefaultFeatureAttributeDescriptor other
214
    ) {
215
        this();
216
        copyFrom(other);
217 44259 jjdelcerro
//        LOGGER.info(String.format("Created FeatureAttributeDescriptor [%08x] [%s] (copy).", this.hashCode(), this.name));
218 45738 fdiaz
    }
219 44673 jjdelcerro
220 45738 fdiaz
    @Override
221
    public void copyFrom(DynField other1) {
222
        if (!(other1 instanceof DefaultFeatureAttributeDescriptor)) {
223
            throw new IllegalArgumentException("Can't copy from a non DefaultFeatureAttributeDescriptor");
224 45154 jjdelcerro
        }
225 45738 fdiaz
        DefaultFeatureAttributeDescriptor other = (DefaultFeatureAttributeDescriptor) other1;
226
        this.typeRef = other.typeRef;
227
        this.allowNull = other.allowNull;
228
        this.dataType = other.dataType;
229
        this.dateFormat = other.dateFormat;
230
        this.defaultValue = other.defaultValue;
231 45991 omartinez
        this.defaultFormat = other.defaultFormat;
232 45738 fdiaz
        this.index = other.index;
233
        this.maximumOccurrences = other.maximumOccurrences;
234
        this.minimumOccurrences = other.minimumOccurrences;
235
        this.size = other.size;
236
        this.name = other.name;
237
        this.objectClass = other.objectClass;
238
        this.precision = other.precision;
239
        this.scale = other.scale;
240
        this.roundMode = other.roundMode;
241
        this.evaluator = other.evaluator;
242
        this.primaryKey = other.primaryKey;
243
        this.readOnly = other.readOnly;
244
        this.SRS = other.SRS;
245
        this.geometryType = other.geometryType;
246
        this.geometrySubType = other.geometrySubType;
247
        this.geomType = other.geomType;
248
        if (other.additionalInfo != null) {
249
            this.additionalInfo = new HashMap();
250
            for (Entry<String, String> entry : other.additionalInfo.entrySet()) {
251
                this.additionalInfo.put(entry.getKey(), entry.getValue());
252
            }
253
        } else {
254
            this.additionalInfo = null;
255
        }
256
        this.isAutomatic = other.isAutomatic;
257
        this.isTime = other.isTime;
258
        this.featureAttributeEmulator = other.featureAttributeEmulator;
259
        this.indexed = other.indexed;
260
        this.isIndexAscending = other.isIndexAscending;
261
        this.allowIndexDuplicateds = other.allowIndexDuplicateds;
262
        this.hidden = other.hidden;
263
        this.dataProfile = other.dataProfile;
264 40435 jjdelcerro
265 45738 fdiaz
        this.availableValues = other.availableValues;
266
        this.availableValuesExpression = other.availableValuesExpression;
267
        this.description = other.description;
268
        this.minValue = other.minValue;
269
        this.maxValue = other.maxValue;
270
        this.label = other.label;
271
        this.order = other.order;
272
        this.groupName = other.groupName;
273
        if (other.tags == null) {
274
            this.tags = null;
275
        } else {
276
            try {
277
                this.tags = (Tags) other.tags.clone();
278
            } catch (Exception ex) {
279
            }
280
        }
281
        this.foreingKey = null;
282
        if (other.foreingKey != null) {
283
            try {
284
                this.foreingKey = (DefaultForeingKey) other.foreingKey.clone();
285
            } catch (CloneNotSupportedException ex) {
286
            }
287
        }
288
        if (this.foreingKey != null) {
289
            this.foreingKey.setDescriptor(this);
290
        }
291
292
        // TODO: ? Habria que clonarlos ?
293
        this.availableValuesMethod = other.availableValuesMethod;
294
        this.calculateMethod = other.calculateMethod;
295
        this.relationType = other.relationType;
296
        this.locale = other.locale;
297
        this.displaySize = other.displaySize;
298
        this.avoidCachingAvailableValues = other.avoidCachingAvailableValues;
299 40435 jjdelcerro
    }
300
301 45738 fdiaz
    public void setFeatureType(FeatureType type) {
302
        // Usada en la persistencia
303
        if (type == null) {
304
            this.typeRef = null;
305
        } else {
306
            this.typeRef = new WeakReference(type);
307 44673 jjdelcerro
//            LOGGER.info(String.format("FeatureAttributeDescriptor[%08x] set FeatureType [%08x], ref [%08x].", this.hashCode(), type.hashCode(), typeRef.hashCode()));
308 45738 fdiaz
        }
309 43954 jjdelcerro
    }
310
311 45738 fdiaz
    @Override
312
    public String getDataTypeName() {
313
        if (this.getDataType() == null) {
314
            return "(unknow)";
315
        }
316
        return this.getDataType().getName();
317 40435 jjdelcerro
    }
318
319 45738 fdiaz
    @Override
320
    public DefaultFeatureAttributeDescriptor getCopy() {
321
        return new DefaultFeatureAttributeDescriptor(this);
322
    }
323 40435 jjdelcerro
324 45738 fdiaz
    @Override
325
    public Object clone() throws CloneNotSupportedException {
326
        return new DefaultFeatureAttributeDescriptor(this);
327
    }
328 44669 jjdelcerro
329 45738 fdiaz
    @Override
330
    public boolean allowNull() {
331
        return allowNull;
332
    }
333 40435 jjdelcerro
334 45738 fdiaz
    @Override
335
    public Locale getLocale() {
336 46031 omartinez
        // FIXME: Debe devolver el locale que toca ENGLISH o default,
337
        // pero no asignarlo a "locale", manteniendo el null en la variable.
338
        // Ojo que tambien habria que tocar el setLocale.
339 45739 jjdelcerro
        if (this.locale == null) {
340
            if (this.dataType.isNumeric()) {
341 46030 omartinez
                this.locale = Locale.ENGLISH; //return
342 45738 fdiaz
            } else {
343
                this.locale = Locale.getDefault();
344
            }
345
        }
346
        return this.locale;
347 44818 jjdelcerro
    }
348 40435 jjdelcerro
349 45738 fdiaz
    @Override
350
    public DataType getDataType() {
351
        if (featureAttributeGetter != null) {
352
            return featureAttributeGetter.getDataType();
353
        }
354
        return this.dataType;
355 40435 jjdelcerro
    }
356
357 45738 fdiaz
    public FeatureAttributeDescriptor setDataType(int type) {
358
        this.dataType = ToolsLocator.getDataTypesManager().get(type);
359
        return this;
360
    }
361 40435 jjdelcerro
362 45738 fdiaz
    @Override
363
    public DateFormat getDateFormat() {
364
        return this.dateFormat;
365
    }
366 40435 jjdelcerro
367 45738 fdiaz
    @Override
368
    public Object getDefaultValue() {
369
        return this.defaultValue;
370
    }
371 44673 jjdelcerro
372 45738 fdiaz
    @Override
373
    @Deprecated
374
    public Object getDefaultValueCoerced() {
375
        return getCoercedDefaultValue();
376 40435 jjdelcerro
    }
377
378 45425 jjdelcerro
    @Override
379 45738 fdiaz
    public Object getCoercedDefaultValue() {
380
        try {
381
            Object value = this.defaultValue;
382
            if (value == null) {
383
                return null;
384
            }
385
            if (ExpressionUtils.isDynamicText(value.toString())) {
386
                value = ExpressionUtils.evaluateDynamicText(value.toString());
387
            }
388
            return this.getDataType().coerce(value);
389
        } catch (CoercionException ex) {
390
            return null;
391
        }
392
    }
393
394
    @Override
395
    public Supplier getDefaultValueSupplier() {
396
        return (Supplier) this::getDefaultValueCoerced;
397
    }
398
399
    @Override
400 45425 jjdelcerro
    public DynField setDefaultValueSupplier(Supplier supplier) {
401
        //Do nothing
402
        return this;
403
    }
404 45738 fdiaz
405
    @Override
406
    public Evaluator getEvaluator() {
407
        return this.evaluator;
408
    }
409 44673 jjdelcerro
410 45738 fdiaz
    @Override
411
    public int getGeometryType() {
412
        if (this.dataType.getType() != DataTypes.GEOMETRY) {
413
            return Geometry.TYPES.UNKNOWN;
414
        }
415
        return this.geometryType;
416 40435 jjdelcerro
    }
417
418 45738 fdiaz
    @Override
419
    public int getGeometrySubType() {
420
        if (this.dataType.getType() != DataTypes.GEOMETRY) {
421
            return Geometry.SUBTYPES.UNKNOWN;
422
        }
423
        return this.geometrySubType;
424 40435 jjdelcerro
    }
425
426 45738 fdiaz
    @Override
427
    public GeometryType getGeomType() {
428
        if (this.dataType.getType() != DataTypes.GEOMETRY) {
429
            return null;
430
        }
431
        if (this.geomType == null) {
432
            try {
433
                this.geomType
434
                        = GeometryLocator.getGeometryManager().getGeometryType(
435
                                this.geometryType, this.geometrySubType);
436
            } catch (GeometryException e) {
437
                throw new RuntimeException(
438
                        "Error getting geometry type with type = "
439
                        + this.geometryType + ", subtype = "
440
                        + this.geometrySubType, e);
441
            }
442
        }
443
        return this.geomType;
444 40435 jjdelcerro
    }
445 45738 fdiaz
446
    @Override
447
    public int getIndex() {
448
        return this.index;
449 43954 jjdelcerro
    }
450 40435 jjdelcerro
451 45738 fdiaz
    protected FeatureAttributeDescriptor setIndex(int index) {
452
        this.index = index;
453
        return this;
454
    }
455 40435 jjdelcerro
456 45738 fdiaz
    @Override
457
    public int getMaximumOccurrences() {
458
        return this.maximumOccurrences;
459
    }
460 44669 jjdelcerro
461 45738 fdiaz
    @Override
462
    public int getMinimumOccurrences() {
463
        return this.minimumOccurrences;
464
    }
465 44673 jjdelcerro
466 45738 fdiaz
    @Override
467
    public String getName() {
468
        return this.name;
469
    }
470 44673 jjdelcerro
471 45738 fdiaz
    public FeatureAttributeDescriptor setName(String name) {
472 44673 jjdelcerro
//        LOGGER.info(String.format("FeatureAttributeDescriptor[%08x] set name [%s].", this.hashCode(), name));
473 45738 fdiaz
        this.name = name;
474
        return this;
475
    }
476 44673 jjdelcerro
477 45738 fdiaz
    @Override
478
    public Class getObjectClass() {
479
        if (getDataType().getType() == DataTypes.OBJECT) {
480
            return objectClass;
481
        }
482
        return getDataType().getDefaultClass();
483 44669 jjdelcerro
    }
484 44673 jjdelcerro
485 45738 fdiaz
    @Override
486
    public int getPrecision() {
487
        return this.precision;
488
    }
489 44673 jjdelcerro
490 45738 fdiaz
    @Override
491
    public int getScale() {
492
        return this.scale;
493
    }
494 44673 jjdelcerro
495 45738 fdiaz
    @Override
496
    public Coercion getCoercion() {
497
        return this.getDataType().getCoercion();
498
    }
499 44673 jjdelcerro
500 45738 fdiaz
    @Override
501
    public MathContext getMathContext() {
502
        if (this.mathContext == null) {
503
            if (this.getDataType().isNumeric()) {
504
                this.mathContext = new MathContext(
505
                        this.getPrecision(),
506
                        RoundingMode.valueOf(this.getRoundMode())
507
                );
508
            } else {
509
                this.mathContext = MathContext.UNLIMITED;
510
            }
511
        }
512
        return this.mathContext;
513 44669 jjdelcerro
    }
514 44673 jjdelcerro
515 45738 fdiaz
    @Override
516
    public CoercionContext getCoercionContext() {
517
        if (this.coerceContext == null) {
518
            if (this.getDataType().isNumeric()) {
519
                this.coerceContext = DataTypeUtils.coerceContextDecimal(
520
                        this.getLocale(),
521
                        this.getPrecision(),
522
                        this.getScale(),
523
                        this.getRoundMode()
524
                );
525 45739 jjdelcerro
            } else if (this.getType() == DataTypes.GEOMETRY) {
526 45738 fdiaz
                GeometryCoercionContext context = GeometryLocator.getGeometryManager().createGeometryCoercionContext();
527
                context.setGeometryType(this.getGeomType());
528
                context.setMode(GeometryCoercionContext.MODE_ONERROR_DONTCONVERT);
529
                this.coerceContext = context;
530 46093 fdiaz
            } else if (this.getType() == DataTypes.TIMESTAMP) {
531
//                if(this.locale != null){
532
                    this.coerceContext = DataTypeUtils.coerceContextLocale(
533
                            this.locale
534
                    );
535
//                }
536 45738 fdiaz
            } else {
537
                this.coerceContext = DataTypeUtils.coerceContextLocale(
538
                        this.getLocale()
539
                );
540
            }
541
        }
542
        return this.coerceContext;
543 44669 jjdelcerro
    }
544 44673 jjdelcerro
545 45738 fdiaz
    @Override
546
    public int getRoundMode() {
547
        return this.roundMode;
548 44669 jjdelcerro
    }
549 40435 jjdelcerro
550 45738 fdiaz
    @Override
551
    public IProjection getSRS() {
552
        return this.SRS;
553 44077 jjdelcerro
    }
554
555 45738 fdiaz
    @Override
556
    public Interval getInterval() {
557
        return this.interval;
558 44022 jjdelcerro
    }
559
560 45738 fdiaz
    public IProjection getSRS(WeakReference storeRef) {
561
        if (this.SRS == null) {
562
            FeatureStore store = (FeatureStore) storeRef.get();
563
            this.SRS = (IProjection) store.getDynValue(DataStore.METADATA_CRS);
564
        }
565
        return this.SRS;
566 40435 jjdelcerro
    }
567
568 45738 fdiaz
    @Override
569
    public int getSize() {
570
        return this.size;
571 40435 jjdelcerro
    }
572
573 45738 fdiaz
    @Override
574
    public boolean isPrimaryKey() {
575
        return this.primaryKey;
576 40435 jjdelcerro
    }
577
578 45738 fdiaz
    @Override
579
    public boolean isReadOnly() {
580
        if (this.readOnly) {
581
            return true;
582
        }
583
        return this.isComputed();
584 40435 jjdelcerro
    }
585
586 45738 fdiaz
    @Override
587
    public String getAdditionalInfo(String infoName) {
588
        if (this.additionalInfo == null) {
589
            return null;
590
        }
591
        return this.additionalInfo.get(infoName);
592 40435 jjdelcerro
    }
593
594 45738 fdiaz
    @Override
595
    public boolean isAutomatic() {
596
        return this.isAutomatic;
597 44673 jjdelcerro
    }
598 40435 jjdelcerro
599 45738 fdiaz
    @Override
600
    public boolean equals(Object obj) {
601
        if (this == obj) {
602
            return true;
603
        }
604
        if (!(obj instanceof DefaultFeatureAttributeDescriptor)) {
605
            return false;
606
        }
607
        DefaultFeatureAttributeDescriptor other
608
                = (DefaultFeatureAttributeDescriptor) obj;
609 40435 jjdelcerro
610 45738 fdiaz
        if (this.allowNull != other.allowNull) {
611
            return false;
612
        }
613 40435 jjdelcerro
614 45738 fdiaz
        if (this.index != other.index) {
615
            return false;
616
        }
617 40435 jjdelcerro
618 45738 fdiaz
        if (!Objects.equals(this.name, other.name)) {
619
            return false;
620
        }
621 40435 jjdelcerro
622 45738 fdiaz
        if (this.getDataType() != other.getDataType()) {
623
            return false;
624
        }
625 40435 jjdelcerro
626 45738 fdiaz
        if (this.size != other.size) {
627
            return false;
628
        }
629 40435 jjdelcerro
630 45738 fdiaz
        if (!Objects.equals(this.defaultValue, other.defaultValue)) {
631
            return false;
632
        }
633 45991 omartinez
        if (!Objects.equals(this.defaultFormat, other.defaultFormat)) {
634
            return false;
635
        }
636 40435 jjdelcerro
637 45738 fdiaz
        if (this.primaryKey != other.primaryKey) {
638
            return false;
639
        }
640 40435 jjdelcerro
641 45738 fdiaz
        if (this.isAutomatic != other.isAutomatic) {
642
            return false;
643
        }
644 40435 jjdelcerro
645 45738 fdiaz
        if (this.readOnly != other.readOnly) {
646
            return false;
647
        }
648 40435 jjdelcerro
649 45738 fdiaz
        if (this.precision != other.precision) {
650
            return false;
651
        }
652 40435 jjdelcerro
653 45738 fdiaz
        if (this.maximumOccurrences != other.maximumOccurrences) {
654
            return false;
655
        }
656 40435 jjdelcerro
657 45738 fdiaz
        if (this.minimumOccurrences != other.minimumOccurrences) {
658
            return false;
659
        }
660 40435 jjdelcerro
661 45738 fdiaz
        if (this.geometryType != other.geometryType) {
662
            return false;
663
        }
664 40435 jjdelcerro
665 45738 fdiaz
        if (this.geometrySubType != other.geometrySubType) {
666
            return false;
667
        }
668 40435 jjdelcerro
669 45738 fdiaz
        if (!Objects.equals(this.evaluator, other.evaluator)) {
670
            return false;
671
        }
672 40435 jjdelcerro
673 45738 fdiaz
        if (!Objects.equals(this.featureAttributeEmulator, other.featureAttributeEmulator)) {
674
            return false;
675
        }
676 40435 jjdelcerro
677 45738 fdiaz
        if (!Objects.equals(this.SRS, other.SRS)) {
678
            return false;
679
        }
680
681
        if (!Objects.equals(this.dateFormat, other.dateFormat)) {
682
            return false;
683
        }
684
685
        if (!Objects.equals(this.objectClass, other.objectClass)) {
686
            return false;
687
        }
688
689
        if (!Objects.equals(this.dataProfile, other.dataProfile)) {
690
            return false;
691
        }
692
693
        return true;
694 44673 jjdelcerro
    }
695 40435 jjdelcerro
696 45738 fdiaz
    @Override
697
    public void loadFromState(PersistentState state)
698
            throws PersistenceException {
699
        allowNull = state.getBoolean("allowNull");
700
        dataType = ToolsLocator.getDataTypesManager().get(state.getInt("dataType"));
701
        dataProfile = state.getString("dataProfile");
702
703
//        FIXME: dateFormat;
704
        try {
705
            defaultValue = dataType.coerce(state.get("defaultValue"));
706
        } catch (CoercionException ex) {
707
        }
708
709
        index = state.getInt("index");
710
        maximumOccurrences = state.getInt("maximumOccurrences");
711
        minimumOccurrences = state.getInt("minimumOccurrences");
712
        size = state.getInt("size");
713
        name = state.getString("name");
714
        try {
715
            String objectClassName = state.getString("objectClass");
716
            if (!StringUtils.isBlank(objectClassName)) {
717
                objectClass = Class.forName(objectClassName);
718
            }
719
        } catch (Throwable e) {
720
            LOGGER.warn("Can't restore the objectClass of the FeatureAttributreDescriptor", e);
721
        }
722
        precision = state.getInt("precision");
723
        scale = state.getInt("scale");
724
        roundMode = state.getInt("roundMode");
725
        String locale_s = state.getString("locale");
726
        locale = (StringUtils.isBlank(locale_s) || "null".equalsIgnoreCase(locale_s)) ? null : Locale.forLanguageTag(locale_s);
727
        evaluator = (Evaluator) state.get("evaluator");
728
        primaryKey = state.getBoolean("primaryKey");
729
        readOnly = state.getBoolean("readOnly");
730
        SRS = (IProjection) state.get("SRS");
731
        geometryType = state.getInt("geometryType");
732
        geometrySubType = state.getInt("geometrySubType");
733
        if (geometryType != Geometry.TYPES.UNKNOWN
734
                && geometrySubType != Geometry.SUBTYPES.UNKNOWN) {
735
            geomType = GeometryUtils.getGeometryType(
736
                    geometryType,
737
                    geometrySubType
738
            );
739
        }
740 44673 jjdelcerro
//        additionalInfo = (Map) state.get("aditionalInfo");
741 45738 fdiaz
        isAutomatic = state.getBoolean("isAutomatic");
742
        isTime = state.getBoolean("isTime");
743
        if (state.hasValue("intervalStart")) {
744
            long intervalStart = state.getLong("interval_start");
745
            long intervalEnd = state.getLong("interval_end");
746
            interval = TimeSupportLocator.getManager().createRelativeInterval(intervalStart, intervalEnd);
747
        } else {
748
            interval = null;
749
        }
750
        featureAttributeEmulator = (FeatureAttributeEmulator) state.get("featureAttributeEmulator");
751
        indexed = state.getBoolean("indexed");
752
        isIndexAscending = state.getBoolean("isIndexAscending");
753
        allowIndexDuplicateds = state.getBoolean("allowIndexDuplicateds");
754 44128 jjdelcerro
755 45738 fdiaz
        Map<String, Object> values = state.getMap("availableValues");
756
        if (values == null || values.isEmpty()) {
757
            this.availableValues = null;
758
        } else {
759
            this.availableValues = new DynObjectValueItem[values.size()];
760
            int n = 0;
761 45847 jjdelcerro
            Coercion coercion = this.getCoercion();
762 45738 fdiaz
            for (Entry<String, Object> entry : values.entrySet()) {
763 45847 jjdelcerro
                Object value;
764
                try {
765
                    value = coercion.coerce(entry.getValue());
766
                } catch (CoercionException ex) {
767
                    value = entry.getValue();
768
                }
769
                this.availableValues[n++] = new DynObjectValueItem(value, entry.getKey());
770 45738 fdiaz
            }
771
        }
772 40435 jjdelcerro
773 45738 fdiaz
        description = state.getString("description");
774
        minValue = state.get("minValue");
775
        maxValue = state.get("maxValue");
776
        label = state.getString("label");
777
        order = state.getInt("order");
778
        hidden = state.getBoolean("hidden");
779
        groupName = state.getString("groupName");
780
        relationType = state.getInt("relationType", RELATION_TYPE_NONE);
781 40435 jjdelcerro
782 45738 fdiaz
        foreingKey = (DefaultForeingKey) state.get("foreingKey");
783
        if (foreingKey != null) {
784
            this.foreingKey.setDescriptor(this);
785
        }
786
        tags = (Tags) state.get("tags");
787
        if (tags == null) {
788
            this.tags = new DefaultTags();
789
        }
790 45739 jjdelcerro
        displaySize = state.getInt("displaySize", 0);
791 45738 fdiaz
        availableValuesExpression = (Expression) state.get("availableValuesExpression");
792 45739 jjdelcerro
        avoidCachingAvailableValues = state.getBoolean("avoidCachingAvailableValues", false);
793 45738 fdiaz
        availableValuesCache = null;
794 45968 jjdelcerro
        defaultFormat = state.getString("defaultFormat");
795 45738 fdiaz
    }
796 44673 jjdelcerro
797 45738 fdiaz
    @Override
798
    public void saveToState(PersistentState state) throws PersistenceException {
799
        Coercion toString = ToolsLocator.getDataTypesManager().getCoercion(DataTypes.STRING);
800
801
        state.set("allowNull", allowNull);
802
        state.set("dataType", dataType.getType());
803
        state.set("dataProfile", dataProfile);
804
805 44190 jjdelcerro
//        FIXME: dateFormat;
806 45738 fdiaz
        state.set("defaultValue", Objects.toString(defaultValue, null));
807 40435 jjdelcerro
808 45738 fdiaz
        state.set("index", index);
809
        state.set("maximumOccurrences", maximumOccurrences);
810
        state.set("minimumOccurrences", minimumOccurrences);
811
        state.set("size", size);
812
        state.set("name", name);
813
        state.set("objectClass", objectClass == null ? null : objectClass.getName());
814
        state.set("precision", precision);
815
        state.set("scale", scale);
816
        state.set("roundMode", roundMode);
817 45739 jjdelcerro
        if (this.locale == null) {
818 45738 fdiaz
            state.setNull("locale");
819
        } else {
820
            state.set("locale", this.locale.toLanguageTag()); //toString.coerce(this.locale));
821
        }
822
        state.set("evaluator", evaluator);
823 40435 jjdelcerro
824 45738 fdiaz
        state.set("primaryKey", primaryKey);
825
        state.set("readOnly", readOnly);
826
        state.set("SRS", SRS);
827
        GeometryType theGeomType = this.getGeomType();
828
        if (theGeomType == null) {
829
            state.set("geometryType", Geometry.TYPES.UNKNOWN);
830
            state.set("geometrySubType", Geometry.SUBTYPES.UNKNOWN);
831
        } else {
832
            state.set("geometryType", theGeomType.getType());
833
            state.set("geometrySubType", theGeomType.getSubType());
834
        }
835 44190 jjdelcerro
836
//      FIXME: additionalInfo
837 45738 fdiaz
        state.set("isAutomatic", isAutomatic);
838
        state.set("isTime", isTime);
839
        if (this.interval == null) {
840
            state.setNull("interval_start");
841
            state.setNull("interval_end");
842
        } else {
843
            state.set("interval_start", ((RelativeInterval) interval).getStart().toMillis());
844
            state.set("interval_end", ((RelativeInterval) interval).getEnd().toMillis());
845
        }
846
        state.set("SRS", SRS);
847 44190 jjdelcerro
848
//      FIXME: featureAttributeGetter
849 45738 fdiaz
        if (featureAttributeEmulator instanceof Persistent) {
850
            state.set("featureAttributeEmulator", featureAttributeEmulator);
851
        } else {
852
            state.setNull("featureAttributeEmulator");
853
        }
854 44190 jjdelcerro
855 45738 fdiaz
        state.set("indexed", indexed);
856
        state.set("isIndexAscending", isIndexAscending);
857
        state.set("allowIndexDuplicateds", allowIndexDuplicateds);
858 44190 jjdelcerro
859 45738 fdiaz
        if (this.availableValues == null) {
860
            state.setNull("availableValues");
861
        } else {
862
            Map<String, Object> values = new LinkedHashMap<>();
863
            for (DynObjectValueItem value : availableValues) {
864 46059 jjdelcerro
                if( value!=null ) {
865
                    values.put(value.getLabel(), value.getValue());
866
                }
867 45738 fdiaz
            }
868
            state.set("availableValues", values);
869
        }
870
        state.set("description", description);
871
        state.set("minValue", minValue);
872
        state.set("maxValue", maxValue);
873
        state.set("label", label);
874
        state.set("order", order);
875
        state.set("hidden", hidden);
876
        state.set("groupName", groupName);
877
        state.set("relationType", relationType);
878 40435 jjdelcerro
879 45738 fdiaz
        state.set("foreingKey", this.foreingKey);
880
        state.set("tags", this.tags);
881 44190 jjdelcerro
882 45738 fdiaz
        state.set("displaySize", displaySize);
883
        state.set("availableValuesExpression", availableValuesExpression);
884
        state.set("avoidCachingAvailableValues", avoidCachingAvailableValues);
885 45968 jjdelcerro
        state.set("defaultFormat", defaultFormat);
886 45738 fdiaz
    }
887 44673 jjdelcerro
888 45738 fdiaz
    private static final String FEATATTRDESC_PERSISTENCE_DEFINITION_NAME = "FeatureAttributeDescriptor";
889 44673 jjdelcerro
890 45738 fdiaz
    public static void registerPersistenceDefinition() {
891
        PersistenceManager manager = ToolsLocator.getPersistenceManager();
892 44673 jjdelcerro
893 45738 fdiaz
        if (manager.getDefinition(FEATATTRDESC_PERSISTENCE_DEFINITION_NAME)
894
                == null) {
895
            DynStruct definition = manager.addDefinition(DefaultFeatureAttributeDescriptor.class,
896
                    FEATATTRDESC_PERSISTENCE_DEFINITION_NAME,
897
                    FEATATTRDESC_PERSISTENCE_DEFINITION_NAME
898
                    + " persistent definition",
899
                    null,
900
                    null
901
            );
902
            definition.addDynFieldBoolean("allowNull");
903
            definition.addDynFieldInt("dataType");
904
            definition.addDynFieldString("dataProfile");
905 44190 jjdelcerro
//            definition.addDynFieldString("dateFormat");
906 45738 fdiaz
            definition.addDynFieldString("defaultValue");
907
            definition.addDynFieldInt("index");
908
            definition.addDynFieldInt("maximumOccurrences");
909
            definition.addDynFieldInt("minimumOccurrences");
910
            definition.addDynFieldInt("size");
911
            definition.addDynFieldString("name");
912
            definition.addDynFieldString("objectClass");
913
            definition.addDynFieldInt("precision");
914
            definition.addDynFieldInt("scale").setMandatory(false).setDefaultDynValue(DataType.SCALE_NONE);
915
            definition.addDynFieldInt("roundMode").setMandatory(false).setDefaultDynValue(BigDecimal.ROUND_HALF_UP);
916
            definition.addDynFieldString("locale").setMandatory(false).setDefaultDynValue("null");
917
            definition.addDynFieldObject("evaluator").setClassOfValue(Evaluator.class);
918
            definition.addDynFieldBoolean("primaryKey");
919
            definition.addDynFieldBoolean("readOnly");
920
            definition.addDynFieldObject("SRS")
921
                    .setClassOfValue(IProjection.class);
922
            definition.addDynFieldInt("geometryType");
923
            definition.addDynFieldInt("geometrySubType");
924 44190 jjdelcerro
//            definition.addDynFieldMap("additionalInfo");
925 45738 fdiaz
            definition.addDynFieldBoolean("isAutomatic");
926
            definition.addDynFieldBoolean("isTime");
927
            definition.addDynFieldLong("interval_start");
928
            definition.addDynFieldLong("interval_end");
929
            definition.addDynFieldObject("featureAttributeEmulator")
930
                    .setClassOfValue(FeatureAttributeEmulator.class);
931
            definition.addDynFieldBoolean("indexed");
932
            definition.addDynFieldBoolean("isIndexAscending");
933
            definition.addDynFieldBoolean("allowIndexDuplicateds");
934
            definition.addDynFieldMap("availableValues")
935
                    .setClassOfItems(Object.class);
936
            definition.addDynFieldString("description");
937
            definition.addDynFieldObject("minValue");
938
            definition.addDynFieldObject("maxValue");
939
            definition.addDynFieldString("label");
940
            definition.addDynFieldInt("order");
941
            definition.addDynFieldBoolean("hidden");
942
            definition.addDynFieldBoolean("avoidCachingAvailableValues");
943
            definition.addDynFieldString("groupName");
944
            definition.addDynFieldInt("relationType");
945 44673 jjdelcerro
946 45738 fdiaz
            definition.addDynFieldObject("foreingKey")
947
                    .setClassOfValue(DefaultForeingKey.class);
948 44673 jjdelcerro
949 45738 fdiaz
            definition.addDynFieldObject("tags")
950
                    .setClassOfValue(Tags.class);
951 44673 jjdelcerro
952 45738 fdiaz
            definition.addDynFieldInt("displaySize").setMandatory(false);
953
            definition.addDynFieldObject("availableValuesExpression")
954
                    .setClassOfValue(Expression.class)
955
                    .setMandatory(false);
956 45968 jjdelcerro
            definition.addDynFieldString("defaultFormat").setMandatory(false);
957 45738 fdiaz
        }
958 44190 jjdelcerro
    }
959
960 45738 fdiaz
    /*
961 40435 jjdelcerro
     * Start of DynField interface Implementation
962 42561 jjdelcerro
     *
963 45738 fdiaz
     */
964
    @Override
965
    public Tags getTags() {
966
        return tags;
967
    }
968 42634 fdiaz
969 45739 jjdelcerro
    private Expression availableValuesFilter;
970
971 45738 fdiaz
    @Override
972 45739 jjdelcerro
    public Expression getAvailableValuesFilter() {
973
        return this.availableValuesFilter;
974
    }
975
976
    public FeatureAttributeDescriptor setAvailableValuesFilter(Expression filter) {
977
        this.availableValuesFilter = filter;
978
        return this;
979
    }
980
981 45775 jjdelcerro
    public FeatureAttributeDescriptor setAvailableValuesFilter(String filter) {
982
        this.availableValuesFilter = ExpressionUtils.createExpression(filter);
983
        return this;
984
    }
985
986 45739 jjdelcerro
    @Override
987 45738 fdiaz
    public boolean hasConstantAvailableValues() {
988
        return this.availableValues != null;
989
    }
990 44719 jjdelcerro
991 45738 fdiaz
    @Override
992
    public boolean isAvoidCachingAvailableValues() {
993
        return this.avoidCachingAvailableValues;
994
    }
995
996
    public boolean hasAvailableValues() {
997 45739 jjdelcerro
        return getAvailableValues() != null;
998 42563 jjdelcerro
    }
999 45014 jjdelcerro
1000 45738 fdiaz
    @Override
1001 45739 jjdelcerro
    public DynObjectValueItem[] getAvailableValues(DynObject context) {
1002
        if (this.availableValuesMethod != null) {
1003
            DynObjectValueItem[] values;
1004
            try {
1005
                values = (DynObjectValueItem[]) this.availableValuesMethod.invoke(context, new Object[]{this});
1006
            } catch (DynMethodException ex) {
1007
                return this.getAvailableValues();
1008
            }
1009
            if (values != null) {
1010
                return values;
1011
            }
1012
        }
1013
        Expression filter = this.availableValuesFilter;
1014
        if (!ExpressionUtils.isEmpty(filter)) {
1015
            if (this.isForeingKey() && this.foreingKey.isClosedList()) {
1016
                ContextForeingKey foreingkeyContext = this.foreingKey.createContext();
1017
                foreingkeyContext.setContextValues(context);
1018
                DynObjectValueItem[] values = this.foreingKey.getAvailableValues(foreingkeyContext);
1019
                return values;
1020
            }
1021
            MutableSymbolTable contextSymbolTable = ExpressionUtils.createSymbolTable("feature", context);
1022
            MutableSymbolTable symbolTable = ExpressionUtils.createSymbolTable();
1023
            symbolTable.addSymbolTable(contextSymbolTable);
1024
1025
            DynObjectValueItem[] allValues = this.getAvailableValues();
1026
            List<DynObjectValueItem> filteredValues = new ArrayList<>();
1027
            for (DynObjectValueItem value : allValues) {
1028
                symbolTable.setVar("$value", value.getValue());
1029
                symbolTable.setVar("$label", value.getLabel());
1030
                Object include = filter.execute(symbolTable);
1031
                if (DataTypeUtils.isFalse(include, false)) {
1032
                    continue;
1033
                }
1034
                filteredValues.add(value);
1035
            }
1036
            DynObjectValueItem[] values = filteredValues.toArray(
1037
                    new DynObjectValueItem[filteredValues.size()]
1038
            );
1039
            return values;
1040
        }
1041
        return this.getAvailableValues();
1042
    }
1043
1044
    @Override
1045
    public boolean isAvailableValuesCalculated() {
1046 45768 jjdelcerro
        if (this.availableValuesMethod != null) {
1047
            return true;
1048
        }
1049
        if (!ExpressionUtils.isEmpty(this.availableValuesFilter)) {
1050
            return true;
1051
        }
1052
        return false;
1053 45739 jjdelcerro
    }
1054
1055
    @Override
1056 45738 fdiaz
    public DynObjectValueItem[] getAvailableValues() {
1057
        DynObjectValueItem[] values = this.availableValues;
1058
1059
        if (values != null) {
1060
            return values;
1061
        }
1062
        values = this.availableValuesCache;
1063
        if (values != null) {
1064
            return values;
1065
        }
1066
        if (this.isForeingKey() && this.foreingKey.isClosedList()) {
1067
            values = this.foreingKey.getAvailableValues(null);
1068
1069 45739 jjdelcerro
        } else if (this.availableValuesExpression != null) {
1070 45738 fdiaz
            values = this.getAvailableValuesFromExpression();
1071
        }
1072 45739 jjdelcerro
        if (!this.avoidCachingAvailableValues) {
1073 45738 fdiaz
            this.availableValuesCache = values;
1074
        }
1075
        return values;
1076 45135 jjdelcerro
    }
1077 45738 fdiaz
1078 45014 jjdelcerro
    private DynObjectValueItem[] getAvailableValuesFrom(GetItemWithSize values) {
1079
        if (values.size() == 0) {
1080
            return null;
1081
        }
1082
        DynObjectValueItem[] r = null;
1083
        Object firstelement = values.get(0);
1084
        if (firstelement instanceof LabeledValue) {
1085
            r = new DynObjectValueItem[values.size()];
1086
            for (int i = 0; i < values.size(); i++) {
1087
                LabeledValue v = (LabeledValue) values.get(i);
1088
                r[i] = new DynObjectValueItem(
1089
                        v.getValue(),
1090
                        Objects.toString(v.getLabel(), Objects.toString(v.getValue(), String.valueOf(i)))
1091
                );
1092
            }
1093
        } else if (firstelement instanceof Pair) {
1094
            r = new DynObjectValueItem[values.size()];
1095
            for (int i = 0; i < values.size(); i++) {
1096
                Pair v = (Pair) values.get(i);
1097
                r[i] = new DynObjectValueItem(
1098
                        v.getValue(),
1099
                        Objects.toString(v.getKey(), Objects.toString(v.getValue(), String.valueOf(i)))
1100
                );
1101
            }
1102
        } else if (firstelement instanceof JsonObject) {
1103
            JsonObject v = (JsonObject) firstelement;
1104
            String labelname = null;
1105
            for (String theName : new String[]{
1106
                "name", "label", "key", "description"
1107
            }) {
1108
                if (v.containsKey(theName)) {
1109
                    labelname = theName;
1110
                    break;
1111
                }
1112
                if (v.containsKey(theName.toUpperCase())) {
1113
                    labelname = theName.toLowerCase();
1114
                    break;
1115
                }
1116
            }
1117
            String valuename = null;
1118
            if (v.containsKey("value")) {
1119
                valuename = "value";
1120
            }
1121
            r = new DynObjectValueItem[values.size()];
1122
            for (int i = 0; i < values.size(); i++) {
1123
                v = (JsonObject) values.get(i);
1124
                String theLabel;
1125
                Object theValue;
1126
                if (labelname == null) {
1127 45068 jjdelcerro
                    theLabel = v.toString();
1128
                } else {
1129 45014 jjdelcerro
                    theLabel = v.getString(labelname);
1130
                }
1131
                if (valuename == null) {
1132
                    theValue = v.getString(valuename);
1133
                } else {
1134
                    theValue = v;
1135
                }
1136
                r[i] = new DynObjectValueItem(theValue, theLabel);
1137
            }
1138 45068 jjdelcerro
        } else if (firstelement instanceof Map) {
1139 45739 jjdelcerro
            Map<String, Object> v = (Map<String, Object>) firstelement;
1140 45068 jjdelcerro
            String labelname = null;
1141
            for (String theName : new String[]{
1142
                "name", "label", "key", "description"
1143
            }) {
1144
                if (v.containsKey(theName)) {
1145
                    labelname = theName;
1146
                    break;
1147
                }
1148
                if (v.containsKey(theName.toUpperCase())) {
1149
                    labelname = theName.toLowerCase();
1150
                    break;
1151
                }
1152
            }
1153
            String valuename = null;
1154
            if (v.containsKey("value")) {
1155
                valuename = "value";
1156
            }
1157
            r = new DynObjectValueItem[values.size()];
1158
            for (int i = 0; i < values.size(); i++) {
1159 45739 jjdelcerro
                v = (Map<String, Object>) values.get(i);
1160 45068 jjdelcerro
                String theLabel;
1161
                Object theValue;
1162
                if (labelname == null) {
1163
                    theLabel = v.toString();
1164
                } else {
1165
                    theLabel = (String) v.get(labelname);
1166
                }
1167
                if (valuename == null) {
1168
                    theValue = v;
1169
                } else {
1170
                    theValue = v.get(valuename);
1171
                }
1172
                r[i] = new DynObjectValueItem(theValue, theLabel);
1173
            }
1174 45014 jjdelcerro
        } else if (firstelement instanceof Feature) {
1175
            Feature v = (Feature) firstelement;
1176
            FeatureType featureType = v.getType();
1177
            String valuename = null;
1178
            FeatureAttributeDescriptor[] pks = featureType.getPrimaryKey();
1179 45739 jjdelcerro
            if (pks != null && pks.length == 1) {
1180 45014 jjdelcerro
                valuename = pks[0].getName();
1181
            }
1182
            String labelname = null;
1183
            for (String theName : new String[]{
1184
                "name", "label", "key", "description"
1185
            }) {
1186 45739 jjdelcerro
                if (featureType.get(theName) != null) {
1187 45014 jjdelcerro
                    labelname = theName;
1188
                    break;
1189
                }
1190
            }
1191
            r = new DynObjectValueItem[values.size()];
1192
            for (int i = 0; i < values.size(); i++) {
1193
                v = (Feature) values.get(i);
1194
                String theLabel;
1195
                Object theValue;
1196
                if (labelname == null) {
1197 45068 jjdelcerro
                    theLabel = v.toString();
1198
                } else {
1199 45014 jjdelcerro
                    theLabel = v.getString(labelname);
1200
                }
1201 45739 jjdelcerro
                if (valuename == null) {
1202 45068 jjdelcerro
                    theValue = v.getReference().getCode();
1203
                } else {
1204 45014 jjdelcerro
                    theValue = v.get(valuename);
1205
                }
1206
                r[i] = new DynObjectValueItem(theValue, theLabel);
1207
            }
1208
        }
1209
        return r;
1210
    }
1211 42634 fdiaz
1212 45738 fdiaz
    private DynObjectValueItem[] getAvailableValuesFromExpression() {
1213 45739 jjdelcerro
        if (this.availableValuesExpression == null || this.availableValuesExpression.isEmpty()) {
1214 45738 fdiaz
            return null;
1215
        }
1216
        try {
1217
            Object value = this.availableValuesExpression.execute(null);
1218 45739 jjdelcerro
            if (value instanceof DynObjectValueItem[]) {
1219 45738 fdiaz
                return (DynObjectValueItem[]) value;
1220
            }
1221 45739 jjdelcerro
            if (value instanceof List) {
1222 45738 fdiaz
                return this.getAvailableValuesFrom(new GetItemWithSize() {
1223
                    @Override
1224
                    public Object get(int i) {
1225 45739 jjdelcerro
                        return ((List) value).get(i);
1226 45738 fdiaz
                    }
1227 45014 jjdelcerro
1228 45738 fdiaz
                    @Override
1229
                    public int size() {
1230 45739 jjdelcerro
                        return ((List) value).size();
1231 45738 fdiaz
                    }
1232
                });
1233
            }
1234 45739 jjdelcerro
        } catch (Throwable th) {
1235 45738 fdiaz
            LOGGER.warn("Can't get available values from expression", th);
1236 45068 jjdelcerro
        }
1237 45738 fdiaz
        return null;
1238
    }
1239 45014 jjdelcerro
1240 45738 fdiaz
    @Override
1241
    public Expression getAvailableValuesExpression() {
1242
        return this.availableValuesExpression;
1243
    }
1244
1245
    @Override
1246 45014 jjdelcerro
    public FeatureAttributeDescriptor setAvailableValuesExpression(String expression) {
1247
        if (StringUtils.isBlank(expression)) {
1248
            this.availableValuesExpression = null;
1249
            return this;
1250
        }
1251
        this.availableValuesExpression = ExpressionUtils.createExpression(expression);
1252
        return this;
1253
    }
1254
1255 45738 fdiaz
    @Override
1256 45014 jjdelcerro
    public FeatureAttributeDescriptor setAvailableValuesExpression(Expression expression) {
1257
        this.availableValuesExpression = expression;
1258
        return this;
1259
    }
1260 45738 fdiaz
1261
    @Override
1262
    public String getLabelOfValue(Object value) {
1263
        if (this.labelOfValueMap != null) {
1264
            String theLabel = this.labelOfValueMap.get(value);
1265
            if (theLabel == null) {
1266
                theLabel = Objects.toString(value, "");
1267
            }
1268
            return theLabel;
1269
        }
1270
        DynObjectValueItem[] values = this.getAvailableValues();
1271
        if (values == null) {
1272
            return Objects.toString(value, "");
1273
        }
1274
        Map<Object, String> map = new LinkedHashMap<>();
1275
        for (DynObjectValueItem theValue : values) {
1276
            map.put(theValue.getValue(), theValue.getLabel());
1277
        }
1278
        this.labelOfValueMap = map;
1279
        String theLabel = this.labelOfValueMap.get(value);
1280
        if (theLabel == null) {
1281
            theLabel = Objects.toString(value, "");
1282
        }
1283
        return theLabel;
1284 40435 jjdelcerro
    }
1285 45738 fdiaz
1286
    @Override
1287
    public String getDescription() {
1288
        if (this.description == null) {
1289
            return getName();
1290
        }
1291
        return this.description;
1292 44346 jjdelcerro
    }
1293 45738 fdiaz
1294
    @Override
1295
    public Object getMaxValue() {
1296
        return this.maxValue;
1297 40435 jjdelcerro
    }
1298 45738 fdiaz
1299
    @Override
1300
    public Object getMinValue() {
1301
        return this.minValue;
1302 40435 jjdelcerro
    }
1303
1304 45738 fdiaz
    @Override
1305
    public int getTheTypeOfAvailableValues() {
1306
        return 1;
1307 40435 jjdelcerro
    }
1308
1309 45738 fdiaz
    @Override
1310
    public int getType() {
1311
        if (featureAttributeGetter != null) {
1312
            return featureAttributeGetter.getDataType().getType();
1313
        }
1314
        return getDataType().getType();
1315
    }
1316 40435 jjdelcerro
1317 45738 fdiaz
    @Override
1318
    public boolean isMandatory() {
1319
        return !allowNull() || isPrimaryKey();
1320
    }
1321 40435 jjdelcerro
1322 45738 fdiaz
    @Override
1323
    public boolean isPersistent() {
1324
        return false;
1325
    }
1326 40435 jjdelcerro
1327 45738 fdiaz
    @Override
1328
    public DynField setAvailableValues(DynObjectValueItem[] values) {
1329
        if (ArrayUtils.isEmpty(values)) {
1330
            this.availableValues = null;
1331
        } else {
1332 45847 jjdelcerro
            Coercion coercion = this.getCoercion();
1333
            this.availableValues = new DynObjectValueItem[values.length];
1334
            for (int i = 0; i < values.length; i++) {
1335
                DynObjectValueItem element = values[i];
1336
                Object value;
1337
                try {
1338
                    value = coercion.coerce(element.getValue());
1339
                } catch (CoercionException ex) {
1340
                    value = element.getValue();
1341
                }
1342
                this.availableValues[i] = new DynObjectValueItem(value, element.getLabel());
1343
            }
1344 45738 fdiaz
        }
1345
        return this;
1346 40435 jjdelcerro
    }
1347
1348 45738 fdiaz
    @Override
1349
    public DynField setDescription(String description) {
1350
        this.description = description;
1351
        return this;
1352
    }
1353 40435 jjdelcerro
1354 45738 fdiaz
    @Override
1355
    public DynField setMandatory(boolean mandatory) {
1356
        throw new UnsupportedOperationException();
1357
    }
1358 40435 jjdelcerro
1359 45738 fdiaz
    @Override
1360
    public DynField setMaxValue(Object maxValue) {
1361
        try {
1362
            this.maxValue = this.coerce(maxValue);
1363
        } catch (CoercionException e) {
1364
            throw new IllegalArgumentException(e);
1365
        }
1366
        return this;
1367 40435 jjdelcerro
    }
1368
1369 45738 fdiaz
    @Override
1370
    public DynField setMinValue(Object minValue) {
1371
        try {
1372
            this.maxValue = this.coerce(minValue);
1373
        } catch (CoercionException e) {
1374
            throw new IllegalArgumentException(e);
1375
        }
1376
        return this;
1377
    }
1378 40435 jjdelcerro
1379 45738 fdiaz
    @Override
1380
    public DynField setPersistent(boolean persistent) {
1381
        throw new UnsupportedOperationException();
1382
    }
1383 40435 jjdelcerro
1384 45738 fdiaz
    @Override
1385
    public DynField setTheTypeOfAvailableValues(int type) {
1386
        throw new UnsupportedOperationException();
1387 40435 jjdelcerro
    }
1388
1389 45738 fdiaz
    @Override
1390
    public DynField setType(int type) {
1391
        throw new UnsupportedOperationException();
1392 40435 jjdelcerro
    }
1393
1394 45738 fdiaz
    @Override
1395
    @Deprecated
1396
    public DynField setDefaultDynValue(Object defaultValue) {
1397
        return this.setDefaultFieldValue(defaultValue);
1398
    }
1399 40435 jjdelcerro
1400 45738 fdiaz
    @Override
1401
    public DynField setDefaultFieldValue(Object defaultValue) {
1402
        this.defaultValue = defaultValue;
1403
        return this;
1404
    }
1405 40435 jjdelcerro
1406 45738 fdiaz
    @Override
1407
    public Class getClassOfValue() {
1408
        return null;
1409
    }
1410 40435 jjdelcerro
1411 45738 fdiaz
    @Override
1412
    public DynField getElementsType() {
1413
        return null;
1414
    }
1415 40435 jjdelcerro
1416 45738 fdiaz
    @Override
1417
    public DynField setClassOfValue(Class theClass)
1418
            throws DynFieldIsNotAContainerException {
1419
        throw new UnsupportedOperationException();
1420
    }
1421 45425 jjdelcerro
1422 45738 fdiaz
    @Override
1423
    public DynField setElementsType(DynStruct type)
1424
            throws DynFieldIsNotAContainerException {
1425
        throw new UnsupportedOperationException();
1426
    }
1427 40435 jjdelcerro
1428 45738 fdiaz
    @Override
1429
    public DynField setElementsType(int type)
1430
            throws DynFieldIsNotAContainerException {
1431
        throw new UnsupportedOperationException();
1432
    }
1433 40435 jjdelcerro
1434 45738 fdiaz
    public FeatureAttributeDescriptor setDataProfileName(String dataProfile) {
1435
        this.dataProfile = dataProfile;
1436
        return this;
1437
    }
1438 40435 jjdelcerro
1439 45738 fdiaz
    @Override
1440
    public String getDataProfileName() {
1441
        return dataProfile;
1442
    }
1443 44128 jjdelcerro
1444 45738 fdiaz
    @Override
1445
    public DataProfile getDataProfile() {
1446
        if (StringUtils.isBlank(dataProfile)) {
1447
            return null;
1448
        }
1449
        DataProfile profile = DALLocator.getDataManager().getDataProfile(dataProfile);
1450
        return profile;
1451
    }
1452 40435 jjdelcerro
1453 45738 fdiaz
    @Override
1454
    public void validate(Object value) throws DynFieldValidateException {
1455 42561 jjdelcerro
1456 45738 fdiaz
        if (value == null && !this.allowNull()) {
1457
            throw new DynFieldValidateException(value, this, null);
1458
        }
1459 42561 jjdelcerro
1460 45738 fdiaz
        try {
1461
            this.dataType.coerce(value);
1462
        } catch (CoercionException e) {
1463
            throw new DynFieldValidateException(value, this, e);
1464
        }
1465
1466
        /*
1467
         * Other checks will be needed
1468
         */
1469 40435 jjdelcerro
    }
1470
1471 45738 fdiaz
    @Override
1472
    public String getSubtype() {
1473
        if (featureAttributeGetter != null) {
1474
            return featureAttributeGetter.getDataType().getSubtype();
1475
        }
1476
        return this.dataType.getSubtype();
1477
    }
1478 40435 jjdelcerro
1479 45738 fdiaz
    @Override
1480
    public Object coerce(Object value) throws CoercionException {
1481
        if (value == null) {
1482
            return value; // O debe devolver this.defaultValue
1483
        }
1484
        try {
1485
            return this.getDataType().coerce(value, this.getCoercionContext());
1486
        } catch (Exception ex) {
1487
            throw new RuntimeException(ex);
1488
        }
1489 40435 jjdelcerro
    }
1490
1491 45738 fdiaz
    @Override
1492
    public DynField setAvailableValues(List values) {
1493
        if (values == null || values.isEmpty()) {
1494
            this.availableValues = null;
1495
        } else {
1496
            this.availableValues = (DynObjectValueItem[]) values.toArray(
1497
                    new DynObjectValueItem[values.size()]
1498
            );
1499
        }
1500
        return this;
1501 40435 jjdelcerro
    }
1502
1503 45738 fdiaz
    @Override
1504
    public String getGroup() {
1505
        return this.groupName;
1506
    }
1507 40435 jjdelcerro
1508 45738 fdiaz
    @Override
1509
    public int getOder() {
1510
        return this.order;
1511 40435 jjdelcerro
    }
1512
1513 45738 fdiaz
    @Override
1514
    public String getLabel() {
1515
        if (this.label == null) {
1516
            return this.getName();
1517
        }
1518
        return this.label;
1519 41323 jjdelcerro
    }
1520 45738 fdiaz
1521
    @Override
1522
    public String getLocalizedLabel() {
1523
        if (StringUtils.isBlank(this.label)) {
1524
            return this.getName();
1525
        }
1526
        I18nManager i18n = ToolsLocator.getI18nManager();
1527
        return i18n.getTranslation(this.label);
1528 44338 jjdelcerro
    }
1529 41323 jjdelcerro
1530 45738 fdiaz
    @Override
1531
    public DynField setLabel(String label) {
1532
        this.label = label;
1533
        return this;
1534 41323 jjdelcerro
    }
1535
1536 45738 fdiaz
    @Override
1537
    public DynField setShortLabel(String shortLabel) {
1538
        this.shortLabel = shortLabel;
1539
        return this;
1540
    }
1541 44337 jjdelcerro
1542 45738 fdiaz
    @Override
1543
    public String getShortLabel() {
1544
        return StringUtils.isBlank(shortLabel) ? getLabel() : shortLabel;
1545
    }
1546 44337 jjdelcerro
1547 45738 fdiaz
    @Override
1548
    public String getLocalizedShortLabel() {
1549
        if (StringUtils.isBlank(shortLabel)) {
1550
            return this.getLocalizedLabel();
1551
        }
1552
        I18nManager i18n = ToolsLocator.getI18nManager();
1553
        return i18n.getTranslation(shortLabel);
1554 44338 jjdelcerro
    }
1555
1556 45738 fdiaz
    @Override
1557
    public DynField setGroup(String groupName) {
1558
        this.groupName = groupName;
1559
        return this;
1560 40435 jjdelcerro
    }
1561
1562 45738 fdiaz
    @Override
1563
    public DynField setOrder(int order) {
1564
        this.order = order;
1565
        return this;
1566
    }
1567 40435 jjdelcerro
1568 45738 fdiaz
    @Override
1569
    public DynField setHidden(boolean hidden) {
1570
        this.hidden = hidden;
1571
        return this;
1572
    }
1573 40435 jjdelcerro
1574 45738 fdiaz
    @Override
1575
    public boolean isHidden() {
1576
        return this.hidden;
1577
    }
1578 40435 jjdelcerro
1579 45738 fdiaz
    @Override
1580
    public DynField setReadOnly(boolean readOnly) {
1581
        this.readOnly = readOnly;
1582
        return this;
1583 40435 jjdelcerro
    }
1584
1585 45738 fdiaz
    @Override
1586
    public boolean isContainer() {
1587
        return false;
1588
    }
1589 40435 jjdelcerro
1590 45738 fdiaz
    @Override
1591
    public Class getClassOfItems() {
1592
        return null;
1593
    }
1594 40435 jjdelcerro
1595 45738 fdiaz
    @Override
1596
    public DynField setClassOfItems(Class theClass) {
1597
        throw new UnsupportedOperationException();
1598
    }
1599 40435 jjdelcerro
1600 45738 fdiaz
    @Override
1601
    public DynField setType(DataType type) {
1602
        throw new UnsupportedOperationException();
1603
    }
1604 40435 jjdelcerro
1605 45738 fdiaz
    @Override
1606
    public DynField setSubtype(String subtype) {
1607
        throw new UnsupportedOperationException();
1608
    }
1609 40435 jjdelcerro
1610 45738 fdiaz
    @Override
1611
    public boolean isTime() {
1612
        return isTime;
1613
    }
1614 44128 jjdelcerro
1615 45738 fdiaz
    @Override
1616
    public FeatureAttributeGetter getFeatureAttributeGetter() {
1617
        return featureAttributeGetter;
1618
    }
1619 40435 jjdelcerro
1620 45738 fdiaz
    @Override
1621
    public void setFeatureAttributeGetter(
1622
            FeatureAttributeGetter featureAttributeTransform) {
1623
        this.featureAttributeGetter = featureAttributeTransform;
1624
    }
1625 41335 jjdelcerro
1626 45738 fdiaz
    @Override
1627
    public FeatureAttributeEmulator getFeatureAttributeEmulator() {
1628
        return this.featureAttributeEmulator;
1629
    }
1630 41335 jjdelcerro
1631 45738 fdiaz
    public FeatureAttributeDescriptor setFeatureAttributeEmulator(FeatureAttributeEmulator featureAttributeEmulator) {
1632
        this.featureAttributeEmulator = featureAttributeEmulator;
1633
        return this;
1634
    }
1635 41638 jjdelcerro
1636 45738 fdiaz
    @Override
1637
    public boolean isIndexed() {
1638
        return this.indexed;
1639
    }
1640 41638 jjdelcerro
1641 45738 fdiaz
    @Override
1642
    public boolean isForeingKey() {
1643
        return this.foreingKey != null && this.foreingKey.isForeingKey();
1644
    }
1645 41638 jjdelcerro
1646 45738 fdiaz
    @Override
1647
    public ForeingKey getForeingKey() {
1648
        return this.foreingKey;
1649
    }
1650 42563 jjdelcerro
1651 45738 fdiaz
    @Override
1652
    public boolean allowIndexDuplicateds() {
1653
        return this.allowIndexDuplicateds;
1654
    }
1655 42563 jjdelcerro
1656 45738 fdiaz
    @Override
1657
    public boolean isIndexAscending() {
1658
        return this.isIndexAscending;
1659
    }
1660 42563 jjdelcerro
1661 45738 fdiaz
    @Override
1662
    public DynField setClassOfValue(DynStruct dynStrct) {
1663
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
1664
    }
1665 42563 jjdelcerro
1666 45738 fdiaz
    @Override
1667
    public DynField setClassOfValue(String theClassNameOfValue) {
1668
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
1669
    }
1670 42563 jjdelcerro
1671 45738 fdiaz
    @Override
1672
    public String getClassNameOfValue() {
1673
        return null;
1674
    }
1675 42563 jjdelcerro
1676 45738 fdiaz
    @Override
1677
    public DynStruct getDynClassOfValue() {
1678
        return null;
1679
    }
1680 42563 jjdelcerro
1681 45738 fdiaz
    @Override
1682
    public DynField setTypeOfItems(int type) {
1683
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
1684
    }
1685 42563 jjdelcerro
1686 45738 fdiaz
    @Override
1687
    public int getTypeOfItems() {
1688
        return DataTypes.INVALID;
1689
    }
1690 42563 jjdelcerro
1691 45738 fdiaz
    @Override
1692
    public DynField setClassOfItems(DynStruct dynStrct) {
1693
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
1694
    }
1695 42563 jjdelcerro
1696 45738 fdiaz
    @Override
1697
    public DynField setClassOfItems(String theClassNameOfValue) {
1698
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
1699
    }
1700 42563 jjdelcerro
1701 45738 fdiaz
    @Override
1702
    public String getClassNameOfItems() {
1703
        return null;
1704
    }
1705 42563 jjdelcerro
1706 45738 fdiaz
    @Override
1707
    public DynStruct getDynClassOfItems() {
1708
        return null;
1709
    }
1710 42606 jjdelcerro
1711 45738 fdiaz
    @Override
1712
    public DynField setRelationType(int relationType) {
1713
        this.relationType = relationType;
1714
        return this;
1715
    }
1716 44673 jjdelcerro
1717 45738 fdiaz
    @Override
1718
    public int getRelationType() {
1719
        return this.relationType;
1720
    }
1721 44673 jjdelcerro
1722 45738 fdiaz
    @Override
1723
    public DynField setAvailableValues(DynMethod availableValuesMethod) {
1724
        this.availableValuesMethod = availableValuesMethod;
1725
        return this;
1726
    }
1727 44673 jjdelcerro
1728 45738 fdiaz
    @Override
1729 45739 jjdelcerro
    public DynMethod getAvailableValuesMethod() {
1730 45738 fdiaz
        if (this.availableValuesMethod != null) {
1731 45739 jjdelcerro
            return this.availableValuesMethod;
1732
        }
1733
        if (this.availableValuesFilter == null && !this.isForeingKey()) {
1734
            return null;
1735
        }
1736
        DynMethod method = new AbstractDynMethod("getAvailableValuesOf" + this.getName()) {
1737
            @Override
1738
            public Object invoke(DynObject context, Object[] args) throws DynMethodException {
1739
                return getAvailableValues(context);
1740 45738 fdiaz
            }
1741 45739 jjdelcerro
        };
1742
        return method;
1743 42606 jjdelcerro
    }
1744
1745 45738 fdiaz
    @Override
1746
    public DynMethod getCalculateMethod() {
1747
        return this.calculateMethod;
1748
    }
1749 42775 jjdelcerro
1750 45738 fdiaz
    @Override
1751
    public DynField setCalculateMethod(DynMethod method) {
1752
        this.calculateMethod = method;
1753
        return this;
1754
    }
1755 42775 jjdelcerro
1756 45738 fdiaz
    @Override
1757
    public boolean isCalculated() {
1758
        return this.calculateMethod != null;
1759
    }
1760 42775 jjdelcerro
1761 45738 fdiaz
    @Override
1762
    public Object getCalculatedValue(DynObject self) {
1763
        try {
1764
            return this.calculateMethod.invoke(self, new Object[]{this});
1765
        } catch (DynMethodException ex) {
1766
            throw new RuntimeException(ex);
1767
        }
1768 42775 jjdelcerro
    }
1769
1770 45738 fdiaz
    @Override
1771
    public DynField setValidateElements(boolean validate) {
1772
        return this;
1773
    }
1774 44579 omartinez
1775 45738 fdiaz
    @Override
1776
    public boolean getValidateElements() {
1777
        return false;
1778
    }
1779 44579 omartinez
1780 45738 fdiaz
    @Override
1781
    public boolean hasLabel() {
1782
        return StringUtils.isNotBlank(this.label);
1783
    }
1784 44579 omartinez
1785 45738 fdiaz
    @Override
1786
    public boolean hasShortLabel() {
1787
        return StringUtils.isNotBlank(this.shortLabel);
1788
    }
1789 44644 jjdelcerro
1790 45738 fdiaz
    @Override
1791
    public boolean hasDescription() {
1792
        return StringUtils.isNotBlank(this.description);
1793
    }
1794 42561 jjdelcerro
1795 45738 fdiaz
    @Override
1796
    public FeatureAttributeDescriptor getValue() {
1797
        return this;
1798
    }
1799 42561 jjdelcerro
1800 45738 fdiaz
    @Override
1801
    public int getDisplaySize() {
1802
        return this.displaySize;
1803
    }
1804 44844 jjdelcerro
1805 45258 omartinez
    @Override
1806
    public boolean isInAvailableValues(Object valueToCheck) {
1807 45739 jjdelcerro
        if (this.getAvailableValues() != null) {
1808 45258 omartinez
            for (DynObjectValueItem availableValue : this.getAvailableValues()) {
1809
                if (Objects.equals(valueToCheck, availableValue.getValue())) {
1810
                    return true;
1811
                }
1812
            }
1813
        }
1814
        return false;
1815
    }
1816
1817 45738 fdiaz
    private class ConstantValueEvaluator extends AbstractEvaluator {
1818 44673 jjdelcerro
1819 45738 fdiaz
        @Override
1820
        public Object evaluate(EvaluatorData data) throws EvaluatorException {
1821
            return defaultValue;
1822
        }
1823 41335 jjdelcerro
1824 45738 fdiaz
        @Override
1825
        public String getName() {
1826
            return "Constant attribute " + name;
1827
        }
1828 44673 jjdelcerro
    }
1829
1830 45738 fdiaz
    public void setConstantValue(boolean isConstantValue) {
1831
        if (isConstantValue) {
1832
            /* Cuando un attributo tiene asociado un evaluador, este se interpreta
1833 42634 fdiaz
             * como que no debe cargarse de la fuente de datos subyacente, siendo
1834 41212 jjdelcerro
             * el evaluador el que se encarga de proporcionar su valor.
1835
             * Nos limitamos a asignar un evaluador que retorna simpre el valor
1836
             * por defecto para ese attributo.
1837 45738 fdiaz
             */
1838
            this.evaluator = new ConstantValueEvaluator();
1839
        } else {
1840
            this.evaluator = null;
1841
        }
1842 41212 jjdelcerro
    }
1843 42561 jjdelcerro
1844 45738 fdiaz
    @Override
1845
    public boolean isComputed() {
1846
        return featureAttributeEmulator != null || evaluator != null || isCalculated();
1847
    }
1848 44673 jjdelcerro
1849 45738 fdiaz
    @Override
1850
    public FeatureStore getStore() {
1851
        FeatureType ftype = this.getFeatureType();
1852
        if (ftype == null) {
1853
            return null;
1854
        }
1855
        return ftype.getStore();
1856 43135 jjdelcerro
    }
1857 43739 jjdelcerro
1858 45738 fdiaz
    @Override
1859
    public FeatureType getFeatureType() {
1860
        if (this.typeRef == null) {
1861
            return null;
1862
        }
1863
        FeatureType ftype = (FeatureType) this.typeRef.get();
1864
//        LOGGER.info(String.format("FeatureAttributeDescriptor[%08x] get FeatureType [%08x], ref [%08x].", this.hashCode(), ftype.hashCode(), typeRef.hashCode()));
1865
        return ftype;
1866 43739 jjdelcerro
    }
1867 44094 jjdelcerro
1868 45738 fdiaz
    public FeatureAttributeDescriptor setInterval(Interval interval) {
1869
        this.interval = interval;
1870
        return this;
1871
    }
1872 44094 jjdelcerro
1873 45738 fdiaz
    public void fixAll() {
1874
        if (!this.getDataType().supportSize()) {
1875
            this.size = 0;
1876
        }
1877
        NumberPrecisionAndScale ps = this.getDataType().fixPrecisionAndScale(this.precision, this.scale);
1878
        this.precision = ps.getPrecision();
1879
        this.scale = ps.getScale();
1880
1881
        switch (this.getType()) {
1882
            case DataTypes.INSTANT:
1883
            case DataTypes.INTERVAL:
1884
            case DataTypes.DATE:
1885
            case DataTypes.TIME:
1886
            case DataTypes.TIMESTAMP:
1887
                if (this.getInterval() != null) {
1888
                    this.isTime = true;
1889
                }
1890
                break;
1891
        }
1892 44094 jjdelcerro
    }
1893
1894 45738 fdiaz
    @Override
1895
    public String[] getRequiredFieldNames() {
1896
        FeatureAttributeEmulator emulator = this.getFeatureAttributeEmulator();
1897
        if (emulator == null) {
1898
            return null;
1899 44669 jjdelcerro
        }
1900 45738 fdiaz
        return emulator.getRequiredFieldNames();
1901 44669 jjdelcerro
    }
1902 44158 jjdelcerro
1903 45738 fdiaz
    @Override
1904
    public void recentUsed() {
1905
        DefaultFeatureType.RECENTS_USEDS.add(this);
1906 44262 jjdelcerro
    }
1907
1908 45738 fdiaz
    @Override
1909
    public boolean hasOnlyMetadataChanges(FeatureAttributeDescriptor other) {
1910
        if (other == null) {
1911
            throw new NullPointerException();
1912
        }
1913
        DefaultFeatureAttributeDescriptor old = (DefaultFeatureAttributeDescriptor) other;
1914
        if (!StringUtils.equalsIgnoreCase(old.name, this.name)) {
1915
            return false;
1916
        }
1917
        if (old.isComputed() && old.isComputed() == this.isComputed()) {
1918
            return true;
1919
        }
1920
        if (this.dataType != old.dataType) {
1921
            return false;
1922
        }
1923
        if (this.size != old.size) {
1924
            return false;
1925
        }
1926
        if (this.precision != old.precision) {
1927
            return false;
1928
        }
1929 44505 jjdelcerro
//        if( this.primaryKey != old.primaryKey ) {
1930
//            return false;
1931
//        }
1932 45738 fdiaz
        if (this.geomType != old.geomType) {
1933
            return false;
1934
        }
1935
        if (this.SRS != old.SRS) {
1936
            return false;
1937
        }
1938
        if (this.isAutomatic != old.isAutomatic) {
1939
            return false;
1940
        }
1941
        return true;
1942 44501 jjdelcerro
    }
1943 44673 jjdelcerro
1944 45738 fdiaz
    private class PropertiesBuilder {
1945
1946 45121 jjdelcerro
        private String name;
1947
        private DataType type;
1948 45739 jjdelcerro
        private Map<String, String> sets;
1949 45121 jjdelcerro
        private String sep;
1950 45738 fdiaz
1951
        public PropertiesBuilder() {
1952
            this.sets = new LinkedHashMap<>();
1953
        }
1954
1955
        public void separator(String sep) {
1956
            this.sep = sep;
1957
        }
1958
1959
        public void name(String name) {
1960
            this.name = name;
1961
        }
1962
1963
        public void type(DataType type) {
1964
            this.type = type;
1965
        }
1966
1967
        public void set(String name, ForeingKey fk) {
1968 45739 jjdelcerro
            if (fk == null) {
1969 45738 fdiaz
                return;
1970
            }
1971 45739 jjdelcerro
            if (!fk.isForeingKey()) {
1972 45738 fdiaz
                return;
1973
            }
1974
            this.set(name, fk.isForeingKey());
1975 45739 jjdelcerro
            this.set(name + "_code", fk.getCodeName());
1976
            this.set(name + "_label", fk.getLabelFormula());
1977
            this.set(name + "_closedlist", fk.isClosedList());
1978
            this.set(name + "_table", fk.getTableName());
1979 45738 fdiaz
        }
1980 45121 jjdelcerro
1981 45738 fdiaz
        public void set(String name, FeatureAttributeEmulator value) {
1982 45739 jjdelcerro
            if (value == null) {
1983 45738 fdiaz
                return;
1984
            }
1985 45739 jjdelcerro
            if (value instanceof FeatureAttributeEmulatorExpression) {
1986
                this.set(name, ((FeatureAttributeEmulatorExpression) value).getExpression().getPhrase());
1987 45738 fdiaz
            }
1988
        }
1989
1990
        public void set(String name, IProjection value) {
1991 45739 jjdelcerro
            if (value == null) {
1992 45738 fdiaz
                return;
1993
            }
1994
            this.set(name, value.getAbrev());
1995
        }
1996
1997
        public void set(String name, GeometryType value) {
1998 45739 jjdelcerro
            if (value == null) {
1999 45738 fdiaz
                return;
2000
            }
2001
            this.set(name, value.getFullName().replace(":", "@"));
2002
        }
2003
2004
        public void set(String name, Object value) {
2005 45739 jjdelcerro
            if (value == null) {
2006 45738 fdiaz
                return;
2007
            }
2008
            String s = Objects.toString(value, "");
2009 45739 jjdelcerro
            if (StringUtils.isBlank(s)) {
2010 45738 fdiaz
                return;
2011
            }
2012
            this.sets.put(name, s);
2013
        }
2014
2015
        public void set(String name, Object value, Object skipValue) {
2016 45739 jjdelcerro
            if (value == null || value == skipValue) {
2017 45738 fdiaz
                return;
2018
            }
2019
            String s = Objects.toString(value, "");
2020 45739 jjdelcerro
            if (StringUtils.isBlank(s)) {
2021 45738 fdiaz
                return;
2022
            }
2023
            this.sets.put(name, s);
2024 45121 jjdelcerro
        }
2025
2026 45738 fdiaz
        @Override
2027
        public String toString() {
2028
            StringBuilder builder = new StringBuilder();
2029
            builder.append(this.name);
2030
            builder.append(sep);
2031
            builder.append(this.type.getName());
2032
            for (String key : this.sets.keySet()) {
2033
                builder.append(sep);
2034
                builder.append("set");
2035
                builder.append(sep);
2036
                builder.append(key);
2037
                builder.append("=");
2038
                builder.append(this.sets.get(key));
2039
            }
2040
            return builder.toString();
2041
        }
2042
    }
2043
2044
    private String getAll() {
2045
        PropertiesBuilder builder = new PropertiesBuilder();
2046
        builder.separator("/");
2047
        builder.name(this.name);
2048
        builder.type(this.dataType);
2049
        builder.set("size", this.size, 0);
2050 45739 jjdelcerro
        switch (this.getType()) {
2051 45738 fdiaz
            case DataTypes.BYTE:
2052
            case DataTypes.INTEGER:
2053
            case DataTypes.LONG:
2054
                break;
2055
            case DataTypes.FLOAT:
2056
            case DataTypes.DOUBLE:
2057 46093 fdiaz
                if(this.locale != null){
2058
                    builder.set("locale", this.getLocale());
2059
                }
2060 45738 fdiaz
                break;
2061
            case DataTypes.DECIMAL:
2062
                builder.set("precision", this.precision);
2063
                builder.set("scale", this.scale);
2064
                builder.set("roundMode", this.getRoundMode());
2065 46093 fdiaz
                if(this.locale != null){
2066
                    builder.set("locale", this.getLocale());
2067
                }
2068 45738 fdiaz
                break;
2069
            case DataTypes.DATE:
2070
            case DataTypes.TIME:
2071
            case DataTypes.TIMESTAMP:
2072 46093 fdiaz
                if(this.locale != null){
2073
                    builder.set("locale", this.getLocale());
2074
                }
2075 45738 fdiaz
                break;
2076
            case DataTypes.GEOMETRY:
2077
                IProjection proj = this.getSRS();
2078 45739 jjdelcerro
                if (proj != null) {
2079 45738 fdiaz
                    builder.set("srs", proj.getAbrev().replace(":", "@"));
2080
                }
2081
                GeometryType theGeomType = this.getGeomType();
2082 45739 jjdelcerro
                if (theGeomType != null) {
2083 45738 fdiaz
                    String geomTypeName = GeometryUtils.getGeometryTypeName(this.getGeomType().getType());
2084
                    String geomSubtypeName = GeometryUtils.getGeometrySubtypeName(this.getGeomType().getSubType());
2085 45739 jjdelcerro
                    builder.set("geomtype", geomTypeName + "@" + geomSubtypeName);
2086 45738 fdiaz
                }
2087
                break;
2088
        }
2089
        builder.set("hidden", this.isHidden(), false);
2090
        builder.set("readOnly", this.isReadOnly(), false);
2091
        builder.set("allowNull", this.allowNull(), true);
2092
        builder.set("pk", this.isPrimaryKey(), false);
2093
        builder.set("automatic", this.isAutomatic(), false);
2094
        builder.set("isTime", this.isTime(), false);
2095
        builder.set("profile", this.getDataProfileName());
2096
        builder.set("group", this.getGroup());
2097
        builder.set("description", this.description);
2098
        builder.set("label", this.label);
2099
        builder.set("shortLabel", this.shortLabel);
2100
        builder.set("order", this.getOder());
2101 45739 jjdelcerro
        if (this.getFeatureAttributeEmulator() instanceof FeatureAttributeEmulatorExpression) {
2102
            Expression exp = ((FeatureAttributeEmulatorExpression) this.getFeatureAttributeEmulator()).getExpression();
2103
            if (exp != null) {
2104 45738 fdiaz
                builder.set("expression", exp.getPhrase());
2105
            }
2106 45135 jjdelcerro
        }
2107 45738 fdiaz
        builder.set("isAvoidCachingAvailableValues", this.isAvoidCachingAvailableValues(), false);
2108 45739 jjdelcerro
        if (this.isForeingKey()) {
2109 45738 fdiaz
            builder.set("fk", this.isForeingKey());
2110
            builder.set("fk_table", this.getForeingKey().getTableName());
2111
            builder.set("fk_code", this.getForeingKey().getCodeName());
2112
            builder.set("fk_label", this.getForeingKey().getLabelFormula());
2113
            builder.set("fk.closedlist", this.getForeingKey().isClosedList());
2114
        }
2115
        return builder.toString();
2116 45135 jjdelcerro
    }
2117 45738 fdiaz
2118
    @Override
2119
    public Object get(String name) {
2120
        if (StringUtils.isBlank(name)) {
2121
            throw new IllegalArgumentException("Name can't be empty");
2122
        }
2123
        switch (name.trim().toLowerCase()) {
2124
            case "all":
2125
                return this.getAll();
2126
            case "isreadonly":
2127
            case "readonly":
2128
                return this.isReadOnly();
2129
            case "hidden":
2130
                return this.isHidden();
2131
            case "allownull":
2132
                return this.allowNull();
2133
            case "pk":
2134
            case "ispk":
2135
            case "primarykey":
2136
            case "isprimarykey":
2137
                return this.isPrimaryKey();
2138
            case "isautomatic":
2139
            case "automatic":
2140
                return this.isAutomatic();
2141
            case "time":
2142
            case "istime":
2143
                return this.isTime();
2144
            case "profile":
2145
                return this.getDataProfile();
2146
            case "group":
2147
                return this.getGroup();
2148
            case "description":
2149
                return this.getDescription();
2150
            case "label":
2151
                return this.getLabel();
2152
            case "shortlabel":
2153
                return this.getShortLabel();
2154
            case "isavoidcachingavailablevalues":
2155
            case "avoidcachingavailablevalues":
2156
            case "nocachingavailablevalues":
2157
                return this.isAvoidCachingAvailableValues();
2158
            case "expression":
2159
                return this.getFeatureAttributeEmulator();
2160
            case "size":
2161
                return this.getSize();
2162
            case "precision":
2163
                return this.getPrecision();
2164
            case "scale":
2165
                return this.getScale();
2166
            case "roundmode":
2167
                return this.getRoundMode();
2168
            case "locale":
2169
                return this.getLocale();
2170
            case "order":
2171
                return this.getOder();
2172
            case "isfk":
2173
            case "isforeingkey":
2174
                return this.isForeingKey();
2175
            case "fk":
2176
            case "foreingkey":
2177
                return this.getForeingKey();
2178
            case "fk_code":
2179
            case "foreingkey_code":
2180
            case "foreingkey.code":
2181
                return this.getForeingKey().getCodeName();
2182
            case "fk_label":
2183
            case "foreingkey_label":
2184
            case "foreingkey.label":
2185
                return this.getForeingKey().getLabelFormula();
2186
            case "fk.closedlist":
2187
            case "foreingkey_closedlist":
2188
            case "foreingkey.closedlist":
2189
                return this.getForeingKey().isClosedList();
2190
            case "fk_table":
2191
            case "foreingkey_table":
2192
            case "foreingkey.table":
2193
                return this.getForeingKey().getTableName();
2194
            case "interval":
2195
                return this.getInterval();
2196
            case "geomtype":
2197
            case "geometrytype":
2198
                return this.getGeomType();
2199
            case "srs":
2200
                return this.getSRS();
2201
            default:
2202
                throw new IllegalArgumentException("Name attribute '" + name + "' not valid.");
2203
        }
2204
    }
2205
2206 45044 omartinez
    public void setSRSForced(IProjection SRS) {
2207
        this.SRS = SRS;
2208
    }
2209 45738 fdiaz
2210 45154 jjdelcerro
    @Override
2211
    public JsonObject toJson() {
2212
        return this.toJsonBuilder().build();
2213
    }
2214
2215
    @Override
2216
    public JsonObjectBuilder toJsonBuilder() {
2217
        JsonObjectBuilder builder = Json.createObjectBuilder();
2218 45425 jjdelcerro
        builder.add_class(this);
2219
        builder.add("name", this.name);
2220
        builder.add("description", this.description);
2221
        builder.add("label", this.label);
2222
        builder.add("shortLabel", this.shortLabel);
2223
        builder.add("order", this.order);
2224
        builder.add("groupName", this.groupName);
2225
        builder.add("dataType", this.dataType);
2226
        builder.add("size", this.size);
2227
        builder.add("precision", this.precision);
2228
        builder.add("scale", this.scale);
2229
        builder.add("roundMode", this.roundMode);
2230 45154 jjdelcerro
2231 45425 jjdelcerro
        builder.add("allowNull", this.allowNull);
2232
        builder.add("primaryKey", this.primaryKey);
2233
        builder.add("readOnly", this.readOnly);
2234
        builder.add("isAutomatic", this.isAutomatic);
2235
        builder.add("isTime", this.isTime);
2236
        builder.add("indexed", this.indexed);
2237
        builder.add("isIndexAscending", this.isIndexAscending);
2238
        builder.add("allowIndexDuplicateds", this.allowIndexDuplicateds);
2239
        builder.add("hidden", this.hidden);
2240
        builder.add("avoidCachingAvailableValues", this.avoidCachingAvailableValues);
2241 45154 jjdelcerro
2242 45739 jjdelcerro
        builder.add("geometryType", this.getGeomType());
2243 45425 jjdelcerro
        builder.add("srs", this.getSRS());
2244 45154 jjdelcerro
2245 45425 jjdelcerro
        builder.add("relationType", this.relationType);
2246
        builder.add("displaySize", this.displaySize);
2247 46093 fdiaz
        if(this.locale == null){ //!this.hasLocale()
2248
            builder.addNull("locale");
2249
        } else {
2250
            builder.add("locale", this.getLocale());
2251
        }
2252 45425 jjdelcerro
        builder.add("expression", this.getFeatureAttributeEmulator());
2253 45739 jjdelcerro
        if (this.isForeingKey()) {
2254 45425 jjdelcerro
            builder.add("fk", this.isForeingKey());
2255
            builder.add("fk_table", this.getForeingKey().getTableName());
2256
            builder.add("fk_code", this.getForeingKey().getCodeName());
2257
            builder.add("fk_label", this.getForeingKey().getLabelFormula());
2258
            builder.add("fk_closedlist", this.getForeingKey().isClosedList());
2259 45154 jjdelcerro
        }
2260 45425 jjdelcerro
        builder.add("availableValuesExpression", this.availableValuesExpression);
2261 45789 fdiaz
        builder.add("defaultValue", Objects.toString(this.defaultValue, null));
2262 45425 jjdelcerro
        builder.add("dataProfile", this.getDataProfileName());
2263
        builder.add("tags", tags);
2264
        builder.add("availableValues", availableValues);
2265
        builder.add("additionalInfo", this.additionalInfo);
2266 45968 jjdelcerro
        builder.add("defaultFormat", this.defaultFormat);
2267 45154 jjdelcerro
        return builder;
2268
    }
2269 45738 fdiaz
2270 45425 jjdelcerro
    public void fromJson(JsonObject json) {
2271
        this.name = json.getString("name");
2272
        this.description = json.getString("description");
2273
        this.label = json.getString("label");
2274
        this.shortLabel = json.getString("shortLabel");
2275
        this.order = json.getInt("order");
2276
        this.groupName = json.getString("groupName");
2277
        this.precision = json.getInt("precision");
2278
        this.size = json.getInt("size");
2279
        this.scale = json.getInt("scale");
2280
        this.roundMode = json.getInt("roundMode");
2281 45738 fdiaz
2282
        this.allowNull = json.getBoolean("allowNull");
2283 45425 jjdelcerro
        this.primaryKey = json.getBoolean("primaryKey");
2284
        this.readOnly = json.getBoolean("readOnly");
2285
        this.isAutomatic = json.getBoolean("isAutomatic");
2286
        this.isTime = json.getBoolean("isTime");
2287
        this.indexed = json.getBoolean("indexed");
2288
        this.isIndexAscending = json.getBoolean("isIndexAscending");
2289
        this.allowIndexDuplicateds = json.getBoolean("allowIndexDuplicateds");
2290
        this.hidden = json.getBoolean("hidden");
2291
        this.avoidCachingAvailableValues = json.getBoolean("avoidCachingAvailableValues");
2292
2293
        this.relationType = json.getInt("relationType");
2294
        this.displaySize = json.getInt("displaySize");
2295
2296 45739 jjdelcerro
        this.dataType = (DataType) Json.toObject(json, "dataType");
2297 45425 jjdelcerro
        this.geomType = (GeometryType) Json.toObject(json, "geometryType");
2298
        this.SRS = (IProjection) Json.toObject(json, "srs");
2299
        this.locale = (Locale) Json.toObject(json, "locale");
2300 45739 jjdelcerro
        this.featureAttributeEmulator = (FeatureAttributeEmulator) Json.toObject(json, "expression");
2301 45425 jjdelcerro
2302
        this.tags = (Tags) Json.toObject(json, "tags");
2303 45435 fdiaz
        this.additionalInfo = Json.toMap(json, "additionalInfo");
2304 45425 jjdelcerro
        this.availableValues = (DynObjectValueItem[]) Json.toArray(json, "availableValues", new DynObjectValueItem[0]);
2305
        this.dataProfile = json.getString("dataProfile", null);
2306
        try {
2307 45778 fdiaz
            this.defaultValue = json.getString("defaultValue", null);
2308 45789 fdiaz
            if(!(this.defaultValue instanceof String && ExpressionUtils.isDynamicText((String) this.defaultValue))){
2309 45778 fdiaz
                this.defaultValue = this.coerce(this.defaultValue);
2310
            }
2311 45739 jjdelcerro
        } catch (Exception ex) {
2312
            LOGGER.warn("Can't retrive default value for attribute '" + this.name + "'.", ex);
2313 45425 jjdelcerro
        }
2314 45739 jjdelcerro
        this.availableValuesExpression = (Expression) Json.toObject(json, "availableValuesExpression");
2315
        if (json.getBoolean("fk", false)) {
2316 45425 jjdelcerro
            this.foreingKey = new DefaultForeingKey();
2317 45688 fdiaz
            this.foreingKey.setForeingKey(true);
2318 45425 jjdelcerro
            this.foreingKey.setTableName(json.getString("fk_table", null));
2319
            this.foreingKey.setCodeName(json.getString("fk_code", null));
2320
            this.foreingKey.setLabelFormula(json.getString("fk_label", null));
2321
            this.foreingKey.setClosedList(json.getBoolean("fk_closedlist", false));
2322 45688 fdiaz
        } else {
2323
            this.foreingKey = null;
2324 45425 jjdelcerro
        }
2325 45968 jjdelcerro
        this.description = json.getString("defaultFormat",null);
2326 45425 jjdelcerro
    }
2327 45738 fdiaz
2328 45425 jjdelcerro
    private static class TheJsonSerializer implements JsonManager.JsonSerializer {
2329 45738 fdiaz
2330
        public TheJsonSerializer() {
2331 45425 jjdelcerro
        }
2332
2333
        @Override
2334
        public Class getObjectClass() {
2335
            return DefaultFeatureAttributeDescriptor.class;
2336
        }
2337
2338
        @Override
2339
        public Object toObject(JsonObject json) {
2340
            DefaultFeatureAttributeDescriptor o = new DefaultFeatureAttributeDescriptor();
2341
            o.fromJson(json);
2342
            return o;
2343
        }
2344
2345
        @Override
2346
        public JsonObjectBuilder toJsonBuilder(Object value) {
2347 45739 jjdelcerro
            return ((SupportToJson) value).toJsonBuilder();
2348 45425 jjdelcerro
        }
2349 45738 fdiaz
2350 45425 jjdelcerro
    }
2351
2352
    public static void selfRegister() {
2353
        Json.registerSerializer(new TheJsonSerializer());
2354
    }
2355
2356 45968 jjdelcerro
    @Override
2357
    public String getDefaultFormat() {
2358
        return this.defaultFormat;
2359
    }
2360
2361
    @Override
2362
    public String format(Object value) {
2363
        try {
2364 45991 omartinez
            if( StringUtils.isBlank(this.defaultFormat)) {
2365 46030 omartinez
                if( this.locale==null ) { // !this.hasLocale()
2366
                    return DataTypeUtils.toString(Locale.getDefault(), value, Objects.toString(value, ""));
2367
                } else {
2368
                    return DataTypeUtils.toString(this.locale, value, Objects.toString(value, ""));
2369
                }
2370 45968 jjdelcerro
            }
2371
            return String.format(this.defaultFormat, value);
2372
        } catch(Exception ex) {
2373
            return Objects.toString(value, "");
2374
        }
2375
    }
2376
2377
2378 40435 jjdelcerro
}