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 / DefaultFeatureType.java @ 44753

History | View | Annotate | Download (39.5 KB)

1 40559 jjdelcerro
/**
2
 * gvSIG. Desktop Geographic Information System.
3
 *
4
 * Copyright (C) 2007-2013 gvSIG Association.
5
 *
6
 * This program is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU General Public License
8
 * as published by the Free Software Foundation; either version 3
9
 * of the License, or (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19
 * MA  02110-1301, USA.
20
 *
21
 * For any additional information, do not hesitate to contact us
22
 * at info AT gvsig.com, or visit our website www.gvsig.com.
23
 */
24 40435 jjdelcerro
package org.gvsig.fmap.dal.feature.impl;
25
26 44716 jjdelcerro
import java.io.File;
27 40435 jjdelcerro
import java.lang.ref.WeakReference;
28
import java.util.ArrayList;
29 41342 jjdelcerro
import java.util.Arrays;
30 40435 jjdelcerro
import java.util.Collections;
31 44498 omartinez
import java.util.Date;
32 43981 omartinez
import java.util.HashSet;
33 40435 jjdelcerro
import java.util.Iterator;
34 43998 jjdelcerro
import java.util.LinkedHashSet;
35 40435 jjdelcerro
import java.util.List;
36 44716 jjdelcerro
import java.util.Objects;
37 43981 omartinez
import java.util.Set;
38 44262 jjdelcerro
import java.util.function.Predicate;
39 43610 jjdelcerro
import java.util.zip.CRC32;
40 43358 jjdelcerro
import org.apache.commons.lang3.ArrayUtils;
41 43377 jjdelcerro
import org.apache.commons.lang3.StringUtils;
42 40435 jjdelcerro
43
import org.cresques.cts.IProjection;
44
45
import org.gvsig.fmap.dal.DataTypes;
46
import org.gvsig.fmap.dal.exception.DataException;
47 44753 omartinez
import org.gvsig.fmap.dal.feature.EditableFeatureAttributeDescriptor;
48 40435 jjdelcerro
import org.gvsig.fmap.dal.feature.EditableFeatureType;
49
import org.gvsig.fmap.dal.feature.Feature;
50
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
51 41342 jjdelcerro
import org.gvsig.fmap.dal.feature.FeatureAttributeEmulator;
52 44753 omartinez
import org.gvsig.fmap.dal.feature.FeatureExtraColumn;
53 40435 jjdelcerro
import org.gvsig.fmap.dal.feature.FeatureRules;
54 43739 jjdelcerro
import org.gvsig.fmap.dal.feature.FeatureStore;
55 40435 jjdelcerro
import org.gvsig.fmap.dal.feature.FeatureType;
56 44190 jjdelcerro
import org.gvsig.tools.ToolsLocator;
57 40435 jjdelcerro
import org.gvsig.tools.dynobject.DynClass;
58
import org.gvsig.tools.dynobject.DynField;
59
import org.gvsig.tools.dynobject.DynMethod;
60
import org.gvsig.tools.dynobject.DynObject;
61
import org.gvsig.tools.dynobject.DynObjectValueItem;
62
import org.gvsig.tools.dynobject.DynStruct;
63 44253 jjdelcerro
import org.gvsig.tools.dynobject.DynStruct_v2;
64
import org.gvsig.tools.dynobject.Tags;
65 40435 jjdelcerro
import org.gvsig.tools.dynobject.exception.DynMethodException;
66
import org.gvsig.tools.dynobject.exception.DynObjectValidateException;
67 44253 jjdelcerro
import org.gvsig.tools.dynobject.impl.DefaultTags;
68 44498 omartinez
import org.gvsig.tools.i18n.I18nManager;
69 44190 jjdelcerro
import org.gvsig.tools.persistence.PersistenceManager;
70
import org.gvsig.tools.persistence.Persistent;
71
import org.gvsig.tools.persistence.PersistentState;
72
import org.gvsig.tools.persistence.exception.PersistenceException;
73 40435 jjdelcerro
74 44716 jjdelcerro
@SuppressWarnings("UseSpecificCatch")
75 44253 jjdelcerro
public class DefaultFeatureType
76
        extends ArrayList<FeatureAttributeDescriptor>
77
        implements
78
        FeatureType,
79
        Persistent,
80
        DynClass,
81
        DynStruct_v2,
82
        org.gvsig.tools.lang.Cloneable {
83 40435 jjdelcerro
84 44253 jjdelcerro
    /**
85
     *
86
     */
87
    private static final long serialVersionUID = -7988721447349282215L;
88 40435 jjdelcerro
89 44262 jjdelcerro
    public static final RecentUsedsAttributesImpl RECENTS_USEDS = new RecentUsedsAttributesImpl();
90
91 44253 jjdelcerro
    private DefaultFeatureRules rules;
92
    protected boolean hasEvaluators;
93
    protected boolean hasEmulators;
94
    protected String defaultGeometryAttributeName;
95
    protected String defaultTimeAttributeName;
96
    protected int defaultGeometryAttributeIndex;
97
    protected int defaultTimeAttributeIndex;
98
    private String id;
99
    protected boolean hasOID;
100
    protected boolean allowAtomaticValues;
101
    protected FeatureAttributeDescriptor[] pk = null;
102
    protected String internalID = null;
103 40435 jjdelcerro
104 44253 jjdelcerro
    private List srsList = null;
105
    private WeakReference storeRef;
106
    private boolean requiredFields;
107 40435 jjdelcerro
108 44253 jjdelcerro
    private String description;
109
    private String label;
110
    private Tags tags;
111 44753 omartinez
//    private List<FeatureAttributeDescriptor> descriptors;
112
    private FeatureExtraColumn extraColumn;
113 40435 jjdelcerro
114 44253 jjdelcerro
    public DefaultFeatureType() {
115
        // Usado en la persistencia.
116
        this.internalID = Integer.toHexString((int) (Math.random() * 100000)).toUpperCase();
117
        this.id = id = "default";
118
        this.rules = new DefaultFeatureRules();
119
        this.hasEvaluators = false;
120
        this.hasEmulators = false;
121
        this.defaultGeometryAttributeName = null;
122
        this.defaultTimeAttributeName = null;
123
        this.defaultGeometryAttributeIndex = -1;
124
        this.defaultTimeAttributeIndex = -1;
125
        this.allowAtomaticValues = false;
126
        this.tags = new DefaultTags();
127 44753 omartinez
        this.extraColumn = new DefaultFeatureExtraColumn();
128 44253 jjdelcerro
    }
129 40435 jjdelcerro
130 44253 jjdelcerro
    protected DefaultFeatureType(FeatureStore store, String id) {
131
        this();
132
        if (StringUtils.isEmpty(id)) {
133
            id = "default";
134
        }
135
        this.id = id;
136
        setStore(store);
137
    }
138 40435 jjdelcerro
139 44253 jjdelcerro
    protected DefaultFeatureType(FeatureStore store) {
140
        this(store, (String) null);
141
    }
142 43555 fdiaz
143 44253 jjdelcerro
    protected DefaultFeatureType(DefaultFeatureType other) {
144
        this(other.getStore(), (String) null);
145 44318 jjdelcerro
        copyFrom(other, true);
146 44253 jjdelcerro
    }
147 40435 jjdelcerro
148 44253 jjdelcerro
    protected DefaultFeatureType(DefaultFeatureType other,
149
            boolean copyAttributes) {
150
        this(other.getStore(), (String) null);
151 44318 jjdelcerro
        this.copyFrom(other, copyAttributes);
152 44253 jjdelcerro
    }
153 40435 jjdelcerro
154 44318 jjdelcerro
    @Override
155
    public void copyFrom(FeatureType other) {
156
        String internalIDSaved = this.internalID;
157
        String idSaved = this.id;
158
        copyFrom((DefaultFeatureType) other, true);
159
        this.id = idSaved;
160
        this.internalID = internalIDSaved;
161
    }
162
163 44505 jjdelcerro
    protected void addAll(FeatureType attributes) {
164
        for (FeatureAttributeDescriptor attribute : attributes) {
165
            DefaultFeatureAttributeDescriptor copy = this.getCopyAttributeDescriptor((DefaultFeatureAttributeDescriptor) attribute);
166
            super.add(copy);
167
        }
168
        DefaultFeatureType ft = (DefaultFeatureType) attributes;
169
        this.pk = null;
170
        this.defaultGeometryAttributeName = ft.defaultGeometryAttributeName;
171
        this.defaultTimeAttributeName = ft.defaultTimeAttributeName;
172
        this.defaultGeometryAttributeIndex = ft.defaultGeometryAttributeIndex;
173
        this.defaultTimeAttributeIndex = ft.defaultTimeAttributeIndex;
174
    }
175
176 44318 jjdelcerro
    protected void copyFrom(DefaultFeatureType other, boolean copyAttributes) {
177 44253 jjdelcerro
        this.id = other.getId();
178
        if (copyAttributes) {
179 44505 jjdelcerro
            this.addAll((FeatureType)other);
180 44253 jjdelcerro
        }
181 44506 jjdelcerro
        this.defaultGeometryAttributeName = other.defaultGeometryAttributeName;
182
        this.defaultTimeAttributeName = other.defaultTimeAttributeName;
183
        this.defaultGeometryAttributeIndex = other.defaultGeometryAttributeIndex;
184
        this.defaultTimeAttributeIndex = other.defaultTimeAttributeIndex;
185 44505 jjdelcerro
186 44253 jjdelcerro
        this.hasEvaluators = other.hasEvaluators;
187
        this.hasEmulators = other.hasEmulators;
188
        this.rules = (DefaultFeatureRules) other.rules.getCopy();
189
        this.hasOID = other.hasOID;
190
        this.id = other.id; // XXX ???? copiar o no esto????
191
        this.internalID = other.internalID;
192
        this.label = other.label;
193
        this.description = other.description;
194
        try {
195
            this.tags = (Tags) other.tags.clone();
196
        } catch (CloneNotSupportedException ex) {
197
198
        }
199
    }
200 44318 jjdelcerro
201
    protected DefaultFeatureAttributeDescriptor getCopyAttributeDescriptor(DefaultFeatureAttributeDescriptor src) {
202
        DefaultFeatureAttributeDescriptor copy = new DefaultFeatureAttributeDescriptor(src);
203
        copy.setFeatureType(this);
204
        return copy;
205 44253 jjdelcerro
    }
206 40435 jjdelcerro
207 44318 jjdelcerro
    @Override
208 44253 jjdelcerro
    public String getId() {
209
        return this.id;
210
    }
211 40435 jjdelcerro
212 44318 jjdelcerro
    @Override
213 44253 jjdelcerro
    public Object get(String name) {
214
        FeatureAttributeDescriptor attr;
215
        Iterator iter = this.iterator();
216
        while (iter.hasNext()) {
217
            attr = (FeatureAttributeDescriptor) iter.next();
218
            if (attr.getName().equalsIgnoreCase(name)) {
219
                return attr;
220
            }
221
        }
222
        return null;
223
    }
224 40435 jjdelcerro
225 44318 jjdelcerro
    @Override
226 44253 jjdelcerro
    public FeatureAttributeDescriptor getAttributeDescriptor(String name) {
227
        FeatureAttributeDescriptor attr;
228
        Iterator iter = this.iterator();
229
        while (iter.hasNext()) {
230
            attr = (FeatureAttributeDescriptor) iter.next();
231
            if (attr.getName().equalsIgnoreCase(name)) {
232
                return attr;
233
            }
234 42700 jjdelcerro
        }
235 44253 jjdelcerro
        return null;
236
    }
237 40435 jjdelcerro
238 44318 jjdelcerro
    @Override
239 44253 jjdelcerro
    public FeatureAttributeDescriptor getAttributeDescriptor(int index) {
240
        return (FeatureAttributeDescriptor) super.get(index);
241
    }
242 40435 jjdelcerro
243 44318 jjdelcerro
    @Override
244 44686 jjdelcerro
    public String getAttributeName(int index) {
245
      try {
246
        return super.get(index).getName();
247
      } catch(Exception ex) {
248
        return null;
249
      }
250
    }
251
252
    @Override
253 44253 jjdelcerro
    public FeatureType getCopy() {
254
        return new DefaultFeatureType(this);
255
    }
256 40435 jjdelcerro
257 44318 jjdelcerro
    @Override
258 44253 jjdelcerro
    public Object clone() {
259
        return this.getCopy();
260
    }
261 44077 jjdelcerro
262 44583 omartinez
    @Override
263 44253 jjdelcerro
    public int getDefaultGeometryAttributeIndex() {
264
        return this.defaultGeometryAttributeIndex;
265
    }
266 44077 jjdelcerro
267 44583 omartinez
    @Override
268 44253 jjdelcerro
    public String getDefaultGeometryAttributeName() {
269
        return this.defaultGeometryAttributeName;
270
    }
271 40435 jjdelcerro
272 44583 omartinez
    @Override
273 44253 jjdelcerro
    public int getDefaultTimeAttributeIndex() {
274
        return this.defaultTimeAttributeIndex;
275
    }
276 40435 jjdelcerro
277 44583 omartinez
    @Override
278 44253 jjdelcerro
    public String getDefaultTimeAttributeName() {
279
        return this.defaultTimeAttributeName;
280
    }
281 40435 jjdelcerro
282 44583 omartinez
    @Override
283 44253 jjdelcerro
    public EditableFeatureType getEditable() {
284
        return new DefaultEditableFeatureType(this);
285
    }
286 40435 jjdelcerro
287 44583 omartinez
    @Override
288 44253 jjdelcerro
    public int getIndex(String name) {
289
        FeatureAttributeDescriptor attr;
290
        Iterator iter = this.iterator();
291
        while (iter.hasNext()) {
292
            attr = (FeatureAttributeDescriptor) iter.next();
293
            if (attr.getName().equalsIgnoreCase(name)) {
294
                return attr.getIndex();
295
            }
296 43998 jjdelcerro
        }
297 44253 jjdelcerro
        return -1;
298
    }
299 41342 jjdelcerro
300 44583 omartinez
    @Override
301 44253 jjdelcerro
    public FeatureRules getRules() {
302
        return this.rules;
303
    }
304 40435 jjdelcerro
305 44583 omartinez
    @Override
306 44253 jjdelcerro
    public boolean hasEvaluators() {
307
        return this.hasEvaluators;
308
    }
309 40435 jjdelcerro
310 44253 jjdelcerro
    public boolean hasEmulators() {
311
        return this.hasEmulators;
312
    }
313 40435 jjdelcerro
314 44253 jjdelcerro
    public boolean hasRequiredFields() {
315
        return this.requiredFields;
316
    }
317
318 44583 omartinez
    @Override
319 44253 jjdelcerro
    public List getSRSs() {
320
        if (this.srsList == null) {
321
            ArrayList tmp = new ArrayList();
322
            Iterator iter = iterator();
323
            Iterator tmpIter;
324
            boolean allreadyHave;
325
            IProjection tmpSRS;
326
            FeatureAttributeDescriptor attr;
327
            while (iter.hasNext()) {
328
                attr = (FeatureAttributeDescriptor) iter.next();
329
                if (attr.getDataType().getType() == DataTypes.GEOMETRY
330
                        && attr.getSRS() != null) {
331
                    allreadyHave = false;
332
                    tmpIter = tmp.iterator();
333
                    while (tmpIter.hasNext()) {
334
                        tmpSRS = (IProjection) tmpIter.next();
335
                        if (tmpSRS.getAbrev().equals(attr.getSRS().getAbrev())) {
336
                            allreadyHave = true;
337
                            break;
338
                        }
339
                    }
340
                    if (!allreadyHave) {
341
                        tmp.add(attr.getSRS());
342
                    }
343 41212 jjdelcerro
                }
344 44253 jjdelcerro
            }
345
            this.srsList = Collections.unmodifiableList(tmp);
346
        }
347
        return this.srsList;
348
    }
349 40435 jjdelcerro
350 44583 omartinez
    @Override
351 44253 jjdelcerro
    public IProjection getDefaultSRS() {
352
        if (this.getDefaultGeometryAttributeIndex() < 0) {
353
            return null;
354
        }
355
        return this.getAttributeDescriptor(
356
                this.getDefaultGeometryAttributeIndex()).getSRS();
357
    }
358
359
    public void validateFeature(Feature feature, int mode) throws DataException {
360
        DefaultFeatureRules rules = (DefaultFeatureRules) this.getRules();
361
        rules.validate(feature, mode);
362
    }
363
364 44374 jjdelcerro
    public FeatureType getSubtype() throws DataException {
365
        return new SubtypeFeatureType(this, null, null, true);
366
    }
367
368 44253 jjdelcerro
    public FeatureType getSubtype(String[] names) throws DataException {
369 44374 jjdelcerro
        return this.getSubtype(names, null, true);
370 44253 jjdelcerro
    }
371 41212 jjdelcerro
372 44253 jjdelcerro
    public FeatureType getSubtype(String[] names, String[] constantsNames) throws DataException {
373 44374 jjdelcerro
        return this.getSubtype(names, constantsNames, true);
374
    }
375
376
    public FeatureType getSubtype(String[] names, String[] constantsNames, boolean includePk) throws DataException {
377 44253 jjdelcerro
        if (ArrayUtils.isEmpty(names) && ArrayUtils.isEmpty(constantsNames)) {
378
            return (FeatureType) this.clone();
379
        }
380 44374 jjdelcerro
        return new SubtypeFeatureType(this, names, constantsNames,includePk);
381 44253 jjdelcerro
    }
382 43998 jjdelcerro
383 44253 jjdelcerro
    public boolean isSubtypeOf(FeatureType featureType) {
384
        return false;
385
    }
386
387 44149 jjdelcerro
    @Override
388
    public List<FeatureAttributeDescriptor> toList() {
389
        return Collections.unmodifiableList(this);
390
    }
391 40435 jjdelcerro
392 44253 jjdelcerro
    @Override
393
    public Tags getTags() {
394
        return this.tags;
395
    }
396 40435 jjdelcerro
397 44253 jjdelcerro
    @Override
398
    public String getLabel() {
399
        return this.label;
400
    }
401
402
    @Override
403
    public void setLabel(String label) {
404
        this.label = label;
405
    }
406
407
    @Override
408
    public DynField addDynField(String name, int type) {
409
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
410
    }
411
412 44753 omartinez
    @Override
413
    public FeatureExtraColumn getExtraColumn() {
414
        return extraColumn;
415
    }
416
417
    public void setExtraColumn(FeatureExtraColumn extraColumn) { //List<FeatureAttributeDescriptor> descriptors) {
418
          this.extraColumn = extraColumn;
419
    }
420
421 44253 jjdelcerro
    class SubtypeFeatureType extends DefaultFeatureType {
422
423
        /**
424
         *
425
         */
426
        private static final long serialVersionUID = 6913732960073922540L;
427
        WeakReference parent;
428
429 44374 jjdelcerro
        SubtypeFeatureType(DefaultFeatureType parent, String[] names, String[] constantsNames, boolean includePk)
430 44253 jjdelcerro
                throws DataException {
431
            super(parent, false);
432
            DefaultFeatureAttributeDescriptor attrcopy;
433
            Set<String> attrnames = new LinkedHashSet<>();
434
            Set<String> requiredAttrnames = new HashSet<>();
435
436
            if (ArrayUtils.isEmpty(names)) {
437
                for (FeatureAttributeDescriptor attrdesc : parent) {
438 44376 jjdelcerro
                    attrnames.add(attrdesc.getName().toLowerCase());
439 44253 jjdelcerro
                }
440 44376 jjdelcerro
            } else {
441 44253 jjdelcerro
                attrnames.addAll(Arrays.asList(names));
442
                requiredAttrnames.addAll(Arrays.asList(names));
443
            }
444
            // Add required fields for emulated fields
445
            if (parent.hasEmulators) {
446 44376 jjdelcerro
                // Ojo, este bucle falla cuando hay un campo calculado que depende
447
                // de otro campo calculado.
448 44253 jjdelcerro
                for (FeatureAttributeDescriptor attrdesc : parent) {
449
                    FeatureAttributeEmulator emulator = attrdesc.getFeatureAttributeEmulator();
450 44376 jjdelcerro
                    if (emulator != null && attrnames.contains(attrdesc.getName().toLowerCase())) {
451
                        String theNames[] = emulator.getRequiredFieldNames();
452
                        if (names != null) {
453
                            for (String name : theNames) {
454
                                name = name.toLowerCase();
455
                                attrnames.add(name);
456
                                requiredAttrnames.add(name);
457
                            }
458 43998 jjdelcerro
                        }
459
                    }
460 44253 jjdelcerro
                }
461
            }
462
            // Add missing pk fiels
463 44374 jjdelcerro
            if (includePk && !parent.hasOID()) {
464 44253 jjdelcerro
                for (FeatureAttributeDescriptor attrdesc : parent) {
465
                    if (attrdesc.isPrimaryKey()) {
466 44376 jjdelcerro
                        String name = attrdesc.getName().toLowerCase();
467
                        attrnames.add(name);
468
                        requiredAttrnames.add(name);
469 43998 jjdelcerro
                    }
470 44253 jjdelcerro
                }
471
            }
472 41212 jjdelcerro
473 44253 jjdelcerro
            // Copy attributes
474
            int i = 0;
475
            for (String name : attrnames) {
476
                DefaultFeatureAttributeDescriptor attr = (DefaultFeatureAttributeDescriptor) parent.get(name);
477
                if (attr == null) {
478
                    throw new SubtypeFeatureTypeNameException(name, parent.getId());
479
                }
480
                attrcopy = new DefaultFeatureAttributeDescriptor(attr);
481
                this.add(attrcopy);
482
                attrcopy.index = i++;
483
            }
484
485 44376 jjdelcerro
            // Set the constants attributes.
486 44253 jjdelcerro
            if (!ArrayUtils.isEmpty(constantsNames)) {
487
                for (String name : constantsNames) {
488 44583 omartinez
                    if (!requiredAttrnames.contains(name.toLowerCase())) {
489 44253 jjdelcerro
                        DefaultFeatureAttributeDescriptor attr = (DefaultFeatureAttributeDescriptor) this.get(name);
490
                        attr.setConstantValue(true);
491 41342 jjdelcerro
                    }
492
                }
493 44253 jjdelcerro
            }
494 40435 jjdelcerro
495 44253 jjdelcerro
            this.defaultGeometryAttributeIndex = this.getIndex(this.defaultGeometryAttributeName);
496
            if (this.defaultGeometryAttributeIndex < 0) {
497
                this.defaultGeometryAttributeName = null;
498
            }
499
            this.defaultTimeAttributeIndex = this.getIndex(this.defaultTimeAttributeName);
500
            if (this.defaultTimeAttributeIndex < 0) {
501
                this.defaultTimeAttributeName = null;
502
            }
503
            this.parent = new WeakReference(parent);
504
        }
505 40435 jjdelcerro
506 44374 jjdelcerro
        public FeatureType getSubtype(String[] names, boolean includePk) throws DataException {
507 44253 jjdelcerro
            return new SubtypeFeatureType((DefaultFeatureType) this.parent
508 44374 jjdelcerro
                    .get(), names, null, includePk);
509 44253 jjdelcerro
        }
510 40435 jjdelcerro
511 44253 jjdelcerro
        public boolean isSubtypeOf(FeatureType featureType) {
512
            if (featureType == null) {
513
                return false;
514
            }
515
            FeatureType parent = (FeatureType) this.parent.get();
516
            return featureType.equals(parent);
517
        }
518 40435 jjdelcerro
519 44253 jjdelcerro
        public EditableFeatureType getEditable() {
520
            throw new UnsupportedOperationException();
521
        }
522
    }
523 40435 jjdelcerro
524 44253 jjdelcerro
    public class SubtypeFeatureTypeNameException extends DataException {
525 40435 jjdelcerro
526 44253 jjdelcerro
        /**
527
         *
528
         */
529
        private static final long serialVersionUID = -4414242486723260101L;
530
        private final static String MESSAGE_FORMAT = "Attribute name '%(name)' not found in type (%(type)).";
531
        private final static String MESSAGE_KEY = "_SubtypeFeatureTypeNameException";
532 40435 jjdelcerro
533 44253 jjdelcerro
        public SubtypeFeatureTypeNameException(String name, String type) {
534
            super(MESSAGE_FORMAT, MESSAGE_KEY, serialVersionUID);
535
            setValue("name", name);
536
            setValue("type", type);
537
        }
538
    }
539 40435 jjdelcerro
540 44253 jjdelcerro
    public boolean hasOID() {
541
        return hasOID;
542
    }
543 40435 jjdelcerro
544 44583 omartinez
    @Override
545 44253 jjdelcerro
    public String toString() {
546
        StringBuffer s = new StringBuffer();
547
        s.append(this.getId());
548
        s.append(":[");
549
        String attName;
550
        for (int i = 0; i < size(); i++) {
551
            attName = ((FeatureAttributeDescriptor) get(i)).getName().toString();
552
            s.append(attName);
553
            if (i < size() - 1) {
554
                s.append(',');
555
            }
556
        }
557
        s.append(']');
558
        return s.toString();
559
    }
560 40435 jjdelcerro
561 44583 omartinez
    @Override
562 44253 jjdelcerro
    public Iterator<FeatureAttributeDescriptor> iterator() {
563
        return getIterator(super.iterator());
564
    }
565 40435 jjdelcerro
566 44253 jjdelcerro
    protected Iterator getIterator(Iterator iter) {
567
        return new DelegatedIterator(iter);
568
    }
569 40435 jjdelcerro
570 44253 jjdelcerro
    protected class DelegatedIterator implements Iterator {
571 40435 jjdelcerro
572 44253 jjdelcerro
        protected Iterator iterator;
573 40435 jjdelcerro
574 44253 jjdelcerro
        public DelegatedIterator(Iterator iter) {
575
            this.iterator = iter;
576
        }
577 40435 jjdelcerro
578 44583 omartinez
        @Override
579 44253 jjdelcerro
        public boolean hasNext() {
580
            return iterator.hasNext();
581
        }
582 40435 jjdelcerro
583 44583 omartinez
        @Override
584 44253 jjdelcerro
        public Object next() {
585
            return iterator.next();
586
        }
587 40435 jjdelcerro
588 44583 omartinez
        @Override
589 44253 jjdelcerro
        public void remove() {
590
            throw new UnsupportedOperationException();
591
        }
592 40435 jjdelcerro
593 44253 jjdelcerro
    }
594 40435 jjdelcerro
595 44583 omartinez
    @Override
596 44253 jjdelcerro
    public boolean allowAutomaticValues() {
597
        return this.allowAtomaticValues;
598
    }
599
600 44583 omartinez
    @Override
601 44253 jjdelcerro
    public FeatureAttributeDescriptor[] getAttributeDescriptors() {
602
        return (FeatureAttributeDescriptor[]) super
603
                .toArray(new FeatureAttributeDescriptor[super.size()]);
604
    }
605
606 44435 jjdelcerro
    @Override
607
    public boolean hasPrimaryKey() {
608
        if( pk!=null ) {
609
            return pk.length>0;
610
        }
611
        for (FeatureAttributeDescriptor attr : this) {
612
            if( attr.isPrimaryKey() ) {
613
                return true;
614
            }
615
        }
616
        return false;
617
    }
618
619
    @Override
620
    public boolean supportReferences() {
621
        return this.hasOID() || this.hasPrimaryKey();
622
    }
623
624
    @Override
625 44253 jjdelcerro
    public FeatureAttributeDescriptor[] getPrimaryKey() {
626
        if (pk == null) {
627
            List pks = new ArrayList();
628
            Iterator iter = super.iterator();
629
            FeatureAttributeDescriptor attr;
630
            while (iter.hasNext()) {
631
                attr = (FeatureAttributeDescriptor) iter.next();
632
                if (attr.isPrimaryKey()) {
633
                    pks.add(attr);
634
                }
635
            }
636
            if (pks.isEmpty()) {
637 43358 jjdelcerro
                pk = new FeatureAttributeDescriptor[0];
638
            } else {
639 44253 jjdelcerro
                pk = (FeatureAttributeDescriptor[]) pks.toArray(new FeatureAttributeDescriptor[pks.size()]);
640 43358 jjdelcerro
            }
641 44253 jjdelcerro
        }
642
        return pk;
643
    }
644 40435 jjdelcerro
645 44253 jjdelcerro
    public FeatureAttributeDescriptor getDefaultGeometryAttribute() {
646
        if (this.defaultGeometryAttributeIndex < 0) {
647
            return null;
648
        }
649
        return (FeatureAttributeDescriptor) super
650
                .get(this.defaultGeometryAttributeIndex);
651
    }
652 40435 jjdelcerro
653 44583 omartinez
    @Override
654 44253 jjdelcerro
    public boolean equals(Object o) {
655
        if (this == o) {
656
            return true;
657
        }
658
        if (!(o instanceof DefaultFeatureType)) {
659
            return false;
660
        }
661
        DefaultFeatureType other = (DefaultFeatureType) o;
662
        if (!this.id.equals(other.id)) {
663
            return false;
664
        }
665
        if (this.size() != other.size()) {
666
            return false;
667
        }
668
        FeatureAttributeDescriptor attr, attrOther;
669
        Iterator iter, iterOther;
670
        iter = this.iterator();
671
        iterOther = other.iterator();
672
        while (iter.hasNext()) {
673
            attr = (FeatureAttributeDescriptor) iter.next();
674
            attrOther = (FeatureAttributeDescriptor) iterOther.next();
675
            if (!attr.equals(attrOther)) {
676 44077 jjdelcerro
                return false;
677
            }
678 44253 jjdelcerro
        }
679 40435 jjdelcerro
680 44253 jjdelcerro
        if (!StringUtils.equals(defaultGeometryAttributeName, other.defaultGeometryAttributeName)) {
681
            return false;
682
        }
683
        if (!StringUtils.equals(defaultTimeAttributeName, other.defaultTimeAttributeName)) {
684
            return false;
685
        }
686
        return true;
687 40435 jjdelcerro
688 44253 jjdelcerro
    }
689 40435 jjdelcerro
690 44253 jjdelcerro
    /**
691
     * Start of DynClass interface implementation READONLY
692
     */
693 44583 omartinez
    @Override
694 44253 jjdelcerro
    public DynField addDynField(String name) {
695
        throw new UnsupportedOperationException();
696
    }
697 40435 jjdelcerro
698 44583 omartinez
    @Override
699 44253 jjdelcerro
    public DynField getDeclaredDynField(String name) {
700
        return (DynField) getAttributeDescriptor(name);
701
    }
702 40435 jjdelcerro
703 44583 omartinez
    @Override
704 44253 jjdelcerro
    public DynField[] getDeclaredDynFields() {
705
        return (DynField[]) getAttributeDescriptors();
706
    }
707 40435 jjdelcerro
708 44583 omartinez
    @Override
709 44253 jjdelcerro
    public String getDescription() {
710
        return this.description;
711
    }
712 40435 jjdelcerro
713 44583 omartinez
    @Override
714 44253 jjdelcerro
    public DynField getDynField(String name) {
715
        return (DynField) getAttributeDescriptor(name);
716
    }
717 40435 jjdelcerro
718 44583 omartinez
    @Override
719 44253 jjdelcerro
    public DynField[] getDynFields() {
720
        return (DynField[]) getAttributeDescriptors();
721
    }
722 40435 jjdelcerro
723 44583 omartinez
    @Override
724 44253 jjdelcerro
    public String getName() {
725
        return this.id + "_" + internalID;
726
    }
727 40435 jjdelcerro
728 44583 omartinez
    @Override
729 44253 jjdelcerro
    public void removeDynField(String name) {
730
        throw new UnsupportedOperationException();
731 40435 jjdelcerro
732 44253 jjdelcerro
    }
733 40435 jjdelcerro
734 44583 omartinez
    @Override
735 44253 jjdelcerro
    public void addDynMethod(DynMethod dynMethod) {
736
        throw new UnsupportedOperationException();
737 40435 jjdelcerro
738 44253 jjdelcerro
    }
739 40435 jjdelcerro
740 44253 jjdelcerro
    public void extend(DynClass dynClass) {
741
        throw new UnsupportedOperationException();
742 40435 jjdelcerro
743 44253 jjdelcerro
    }
744 40435 jjdelcerro
745 44583 omartinez
    @Override
746 44253 jjdelcerro
    public void extend(String dynClassName) {
747
        throw new UnsupportedOperationException();
748 40435 jjdelcerro
749 44253 jjdelcerro
    }
750 40435 jjdelcerro
751 44583 omartinez
    @Override
752 44253 jjdelcerro
    public void extend(String namespace, String dynClassName) {
753
        throw new UnsupportedOperationException();
754 40435 jjdelcerro
755 44253 jjdelcerro
    }
756 40435 jjdelcerro
757 44583 omartinez
    @Override
758 44253 jjdelcerro
    public DynMethod getDeclaredDynMethod(String name)
759
            throws DynMethodException {
760
        return null;
761
    }
762 40435 jjdelcerro
763 44583 omartinez
    @Override
764 44253 jjdelcerro
    public DynMethod[] getDeclaredDynMethods() throws DynMethodException {
765
        return null;
766
    }
767 40435 jjdelcerro
768 44583 omartinez
    @Override
769 44253 jjdelcerro
    public DynMethod getDynMethod(String name) throws DynMethodException {
770
        return null;
771
    }
772 40435 jjdelcerro
773 44583 omartinez
    @Override
774 44253 jjdelcerro
    public DynMethod getDynMethod(int code) throws DynMethodException {
775
        return null;
776
    }
777 40435 jjdelcerro
778 44583 omartinez
    @Override
779 44253 jjdelcerro
    public DynMethod[] getDynMethods() throws DynMethodException {
780
        return null;
781
    }
782 40435 jjdelcerro
783 44583 omartinez
    @Override
784 44253 jjdelcerro
    public DynClass[] getSuperDynClasses() {
785
        return null;
786
    }
787 40435 jjdelcerro
788 44583 omartinez
    @Override
789 44253 jjdelcerro
    public boolean isInstance(DynObject dynObject) {
790
        if (dynObject.getDynClass().getName() == getName()) {
791
            return true;
792
        }
793
        return false;
794
    }
795 40435 jjdelcerro
796 44583 omartinez
    @Override
797 44253 jjdelcerro
    public DynObject newInstance() {
798 40435 jjdelcerro
799 44253 jjdelcerro
        throw new UnsupportedOperationException();
800
    }
801 40435 jjdelcerro
802 44583 omartinez
    @Override
803 44253 jjdelcerro
    public void removeDynMethod(String name) {
804
        throw new UnsupportedOperationException();
805 40435 jjdelcerro
806 44253 jjdelcerro
    }
807 40435 jjdelcerro
808 44583 omartinez
    @Override
809 44253 jjdelcerro
    public DynField addDynFieldChoice(String name, int type,
810
            Object defaultValue, DynObjectValueItem[] values,
811
            boolean mandatory, boolean persistent) {
812
        throw new UnsupportedOperationException();
813
    }
814 40435 jjdelcerro
815 44583 omartinez
    @Override
816 44253 jjdelcerro
    public DynField addDynFieldRange(String name, int type,
817
            Object defaultValue, Object min, Object max, boolean mandatory,
818
            boolean persistent) {
819
        throw new UnsupportedOperationException();
820
    }
821 40435 jjdelcerro
822 44583 omartinez
    @Override
823 44253 jjdelcerro
    public DynField addDynFieldSingle(String name, int type,
824
            Object defaultValue, boolean mandatory, boolean persistent) {
825
        throw new UnsupportedOperationException();
826
    }
827 40435 jjdelcerro
828 44583 omartinez
    @Override
829 44253 jjdelcerro
    public void validate(DynObject object) throws DynObjectValidateException {
830
        //FIXME: not sure it's the correct code
831
        if (object instanceof Feature) {
832
            Feature fea = (Feature) object;
833
            if (fea.getType().equals(this)) {
834
                return;
835
            }
836
        }
837
        throw new DynObjectValidateException(this.id);
838
    }
839 40435 jjdelcerro
840 44583 omartinez
    @Override
841 44253 jjdelcerro
    public DynField addDynFieldLong(String name) {
842
        throw new UnsupportedOperationException();
843
    }
844 40435 jjdelcerro
845 44583 omartinez
    @Override
846 44253 jjdelcerro
    public DynField addDynFieldChoice(String name, int type,
847
            Object defaultValue, DynObjectValueItem[] values) {
848
        throw new UnsupportedOperationException();
849
    }
850 40435 jjdelcerro
851 44583 omartinez
    @Override
852 44253 jjdelcerro
    public DynField addDynFieldRange(String name, int type,
853
            Object defaultValue, Object min, Object max) {
854
        throw new UnsupportedOperationException();
855
    }
856 40435 jjdelcerro
857 44583 omartinez
    @Override
858 44253 jjdelcerro
    public DynField addDynFieldSingle(String name, int type, Object defaultValue) {
859
        throw new UnsupportedOperationException();
860
    }
861 40435 jjdelcerro
862 44583 omartinez
    @Override
863 44253 jjdelcerro
    public DynField addDynFieldString(String name) {
864
        throw new UnsupportedOperationException();
865
    }
866 43555 fdiaz
867 44583 omartinez
    @Override
868 44253 jjdelcerro
    public DynField addDynFieldInt(String name) {
869
        throw new UnsupportedOperationException();
870
    }
871 43555 fdiaz
872 44583 omartinez
    @Override
873 44253 jjdelcerro
    public DynField addDynFieldDouble(String name) {
874
        throw new UnsupportedOperationException();
875
    }
876 43555 fdiaz
877 44583 omartinez
    @Override
878 44253 jjdelcerro
    public DynField addDynFieldFloat(String name) {
879
        throw new UnsupportedOperationException();
880
    }
881 40435 jjdelcerro
882 44253 jjdelcerro
    public DynField addDynFieldBoolean(String name) {
883
        throw new UnsupportedOperationException();
884
    }
885 40435 jjdelcerro
886 44583 omartinez
    @Override
887 44253 jjdelcerro
    public DynField addDynFieldList(String name) {
888
        throw new UnsupportedOperationException();
889
    }
890 40435 jjdelcerro
891 44583 omartinez
    @Override
892 44253 jjdelcerro
    public DynField addDynFieldMap(String name) {
893
        throw new UnsupportedOperationException();
894
    }
895 40435 jjdelcerro
896 44583 omartinez
    @Override
897 44253 jjdelcerro
    public DynField addDynFieldObject(String name) {
898
        throw new UnsupportedOperationException();
899
    }
900 40435 jjdelcerro
901 44583 omartinez
    @Override
902 44253 jjdelcerro
    public DynField addDynFieldSet(String name) {
903
        throw new UnsupportedOperationException();
904
    }
905 40435 jjdelcerro
906 44583 omartinez
    @Override
907 44253 jjdelcerro
    public DynField addDynFieldArray(String name) {
908
        throw new UnsupportedOperationException();
909
    }
910 40435 jjdelcerro
911 44583 omartinez
    @Override
912 44253 jjdelcerro
    public DynField addDynFieldDate(String name) {
913
        throw new UnsupportedOperationException();
914
    }
915 40435 jjdelcerro
916 44583 omartinez
    @Override
917 44253 jjdelcerro
    public void extend(DynStruct struct) {
918
        throw new UnsupportedOperationException();
919
    }
920 40435 jjdelcerro
921 44583 omartinez
    @Override
922 44253 jjdelcerro
    public String getFullName() {
923 40435 jjdelcerro
        // TODO: usar el DynClassName
924 44253 jjdelcerro
        return this.id;
925
    }
926 40435 jjdelcerro
927 44583 omartinez
    @Override
928 44253 jjdelcerro
    public String getNamespace() {
929
        return "DALFeature";
930
    }
931 40435 jjdelcerro
932 44583 omartinez
    @Override
933 44253 jjdelcerro
    public DynStruct[] getSuperDynStructs() {
934
        return null;
935
    }
936 40435 jjdelcerro
937 44583 omartinez
    @Override
938 44253 jjdelcerro
    public void setDescription(String description) {
939
        this.description = description;
940
    }
941 40435 jjdelcerro
942 44583 omartinez
    @Override
943 44253 jjdelcerro
    public void setNamespace(String namespace) {
944
        throw new UnsupportedOperationException();
945
    }
946 40435 jjdelcerro
947 44583 omartinez
    @Override
948 44253 jjdelcerro
    public DynField addDynFieldFile(String name) {
949
        throw new UnsupportedOperationException();
950
    }
951 40435 jjdelcerro
952 44583 omartinez
    @Override
953 44253 jjdelcerro
    public DynField addDynFieldFolder(String name) {
954
        throw new UnsupportedOperationException();
955
    }
956 40435 jjdelcerro
957 44583 omartinez
    @Override
958 44253 jjdelcerro
    public DynField addDynFieldURL(String name) {
959
        throw new UnsupportedOperationException();
960
    }
961 40435 jjdelcerro
962 44583 omartinez
    @Override
963 44253 jjdelcerro
    public DynField addDynFieldURI(String name) {
964
        throw new UnsupportedOperationException();
965
    }
966 40435 jjdelcerro
967 44583 omartinez
    @Override
968 40435 jjdelcerro
    public boolean isExtendable(DynStruct dynStruct) {
969
        return false;
970
    }
971
972 44253 jjdelcerro
    public void extend(DynStruct[] structs) {
973
        // TODO Auto-generated method stub
974 43555 fdiaz
975 44253 jjdelcerro
    }
976 40435 jjdelcerro
977 44583 omartinez
    @Override
978 44253 jjdelcerro
    public void remove(DynStruct superDynStruct) {
979
        // TODO Auto-generated method stub
980 43555 fdiaz
981 44253 jjdelcerro
    }
982 40435 jjdelcerro
983 44253 jjdelcerro
    public void removeAll(DynStruct[] superDynStruct) {
984
        // TODO Auto-generated method stub
985 43555 fdiaz
986 44253 jjdelcerro
    }
987 40435 jjdelcerro
988 44583 omartinez
    @Override
989 44253 jjdelcerro
    public FeatureAttributeDescriptor getDefaultTimeAttribute() {
990
        if (this.defaultTimeAttributeIndex < 0) {
991
            return null;
992
        }
993
        return (FeatureAttributeDescriptor) super
994
                .get(this.defaultTimeAttributeIndex);
995
    }
996 43610 jjdelcerro
997
    public void setDefaultTimeAttributeName(String name) {
998
        if (name == null || name.length() == 0) {
999
            this.defaultTimeAttributeIndex = -1;
1000
            return;
1001
        }
1002
        DefaultFeatureAttributeDescriptor attr = (DefaultFeatureAttributeDescriptor) this.get(name);
1003
        if (attr == null) {
1004
            throw new IllegalArgumentException("Attribute '" + name + "' not found.");
1005
        }
1006 44253 jjdelcerro
        if (attr.getIndex() < 0) {
1007 43610 jjdelcerro
            fixAll();
1008
        }
1009
        this.defaultTimeAttributeIndex = attr.getIndex();
1010
    }
1011 44253 jjdelcerro
1012 43610 jjdelcerro
    protected void fixAll() {
1013
        int i = 0;
1014
        Iterator iter = super.iterator();
1015
        DefaultFeatureAttributeDescriptor attr;
1016
1017
        while (iter.hasNext()) {
1018
            attr = (DefaultFeatureAttributeDescriptor) iter.next();
1019 44253 jjdelcerro
            if (attr.getOder() < 1) {
1020
                attr.setOrder(i * 10);
1021 44202 jjdelcerro
            }
1022 43610 jjdelcerro
            attr.setIndex(i++);
1023 44094 jjdelcerro
            attr.fixAll();
1024 43610 jjdelcerro
            if (attr.getEvaluator() != null) {
1025
                this.hasEvaluators = true;
1026
            }
1027
            if (attr.getFeatureAttributeEmulator() != null) {
1028
                this.hasEmulators = true;
1029 43998 jjdelcerro
                String[] x = attr.getFeatureAttributeEmulator().getRequiredFieldNames();
1030 44253 jjdelcerro
                if (!ArrayUtils.isEmpty(x)) {
1031 43998 jjdelcerro
                    this.requiredFields = true;
1032
                }
1033 43610 jjdelcerro
            }
1034 44253 jjdelcerro
            switch (attr.getType()) {
1035 44090 jjdelcerro
                case DataTypes.GEOMETRY:
1036 44253 jjdelcerro
                    if (this.defaultGeometryAttributeName == null) {
1037 44090 jjdelcerro
                        this.defaultGeometryAttributeName = attr.getName();
1038
                    }
1039
                    break;
1040
                case DataTypes.INSTANT:
1041
                case DataTypes.INTERVAL:
1042
                case DataTypes.DATE:
1043 44253 jjdelcerro
                    if (this.defaultTimeAttributeName == null && attr.isTime()) {
1044 44090 jjdelcerro
                        this.defaultTimeAttributeName = attr.getName();
1045
                    }
1046
                    break;
1047 43610 jjdelcerro
            }
1048
        }
1049
        if (this.defaultGeometryAttributeName != null) {
1050
            this.defaultGeometryAttributeIndex = this.getIndex(this.defaultGeometryAttributeName);
1051
        }
1052 44077 jjdelcerro
        if (this.defaultTimeAttributeName != null) {
1053
            this.defaultTimeAttributeIndex = this.getIndex(this.defaultTimeAttributeName);
1054
        }
1055 43610 jjdelcerro
        this.internalID = Long.toHexString(this.getCRC());
1056 44253 jjdelcerro
1057 43610 jjdelcerro
    }
1058 44253 jjdelcerro
1059 43610 jjdelcerro
    protected long getCRC() {
1060
        StringBuffer buffer = new StringBuffer();
1061
        for (int i = 0; i < this.size(); i++) {
1062
            FeatureAttributeDescriptor x = this.getAttributeDescriptor(i);
1063
            buffer.append(x.getName());
1064
            buffer.append(x.getDataTypeName());
1065
            buffer.append(x.getSize());
1066
        }
1067
        CRC32 crc = new CRC32();
1068
        byte[] data = buffer.toString().getBytes();
1069
        crc.update(data);
1070
        return crc.getValue();
1071
    }
1072 43739 jjdelcerro
1073
    @Override
1074
    public FeatureStore getStore() {
1075 44253 jjdelcerro
        if (this.storeRef == null) {
1076 43739 jjdelcerro
            return null;
1077
        }
1078
        return (FeatureStore) this.storeRef.get();
1079
    }
1080 44253 jjdelcerro
1081 44190 jjdelcerro
    public void setStore(FeatureStore store) {
1082 44253 jjdelcerro
        if (store == null) {
1083
            this.storeRef = null;
1084 44190 jjdelcerro
        } else {
1085
            this.storeRef = new WeakReference(store);
1086
        }
1087
    }
1088 43739 jjdelcerro
1089 44190 jjdelcerro
    @Override
1090 44262 jjdelcerro
    public List<FeatureAttributeDescriptor> getFilteredAttributes(
1091
            Predicate<FeatureAttributeDescriptor> filter,
1092
            int max
1093
    ) {
1094
        List<FeatureAttributeDescriptor> attrs = new ArrayList<>();
1095
        for (FeatureAttributeDescriptor attribute : this) {
1096
            if (filter.test(attribute)) {
1097
                attrs.add(attribute);
1098
            }
1099
        }
1100
        return attrs;
1101
    }
1102
1103
    @Override
1104
    public List<FeatureAttributeDescriptor> getRecentUseds() {
1105
        return RECENTS_USEDS.getAttributes(this);
1106
    }
1107
1108
    @Override
1109 44190 jjdelcerro
    public void loadFromState(PersistentState state)
1110
            throws PersistenceException {
1111
1112
//        FIXME: rules
1113
        hasEvaluators = state.getBoolean("hasEvaluators");
1114
        hasEmulators = state.getBoolean("hasEmulators");
1115
        defaultGeometryAttributeName = state.getString("defaultGeometryAttributeName");
1116
        defaultTimeAttributeName = state.getString("defaultTimeAttributeName");
1117
        defaultGeometryAttributeIndex = state.getInt("defaultGeometryAttributeIndex");
1118
        defaultTimeAttributeIndex = state.getInt("defaultTimeAttributeIndex");
1119
        id = state.getString("id");
1120
        hasOID = state.getBoolean("hasOID");
1121
        allowAtomaticValues = state.getBoolean("allowAtomaticValues");
1122
1123
        requiredFields = state.getBoolean("requiredFields");
1124
        internalID = state.getString("internalID");
1125 44262 jjdelcerro
        tags = (Tags) state.get("tags");
1126
        if( tags == null ) {
1127
            this.tags = new DefaultTags();
1128
        }
1129 44253 jjdelcerro
1130 44190 jjdelcerro
        List<FeatureAttributeDescriptor> elements = state.getList("elements");
1131
        for (FeatureAttributeDescriptor element : elements) {
1132 44253 jjdelcerro
            ((DefaultFeatureAttributeDescriptor) element).setFeatureType(this);
1133 44190 jjdelcerro
            super.add(element);
1134
        }
1135 44261 jjdelcerro
        this.pk = null;
1136 44190 jjdelcerro
        this.fixAll();
1137
    }
1138
1139
    @Override
1140
    public void saveToState(PersistentState state) throws PersistenceException {
1141
1142
//        FIXME: rules
1143
        state.set("hasEvaluators", hasEvaluators);
1144
        state.set("hasEmulators", hasEmulators);
1145
        state.set("defaultGeometryAttributeName", defaultGeometryAttributeName);
1146
        state.set("defaultTimeAttributeName", defaultTimeAttributeName);
1147
        state.set("defaultGeometryAttributeIndex", defaultGeometryAttributeIndex);
1148
        state.set("defaultTimeAttributeIndex", defaultTimeAttributeIndex);
1149
        state.set("id", id);
1150
        state.set("hasOID", hasOID);
1151
        state.set("allowAtomaticValues", allowAtomaticValues);
1152
1153
        state.set("requiredFields", requiredFields);
1154
        state.set("internalID", internalID);
1155 44253 jjdelcerro
1156 44190 jjdelcerro
        List<FeatureAttributeDescriptor> elements = new ArrayList<>();
1157
        elements.addAll(this);
1158
        state.set("elements", elements);
1159 44262 jjdelcerro
        state.set("tags", tags);
1160 44253 jjdelcerro
1161 44190 jjdelcerro
    }
1162 44253 jjdelcerro
1163 44190 jjdelcerro
    private static final String FEATTYPE_PERSISTENCE_DEFINITION_NAME = "FeatureType";
1164
1165
    public static void registerPersistenceDefinition() {
1166
        PersistenceManager manager = ToolsLocator.getPersistenceManager();
1167 44253 jjdelcerro
1168 44190 jjdelcerro
        if (manager.getDefinition(FEATTYPE_PERSISTENCE_DEFINITION_NAME)
1169
                == null) {
1170
            DynStruct definition = manager.addDefinition(DefaultFeatureType.class,
1171
                    FEATTYPE_PERSISTENCE_DEFINITION_NAME,
1172
                    FEATTYPE_PERSISTENCE_DEFINITION_NAME
1173 44253 jjdelcerro
                    + " persistent definition",
1174 44190 jjdelcerro
                    null,
1175
                    null
1176
            );
1177
//            definition.addDynFieldObject("rules");
1178
            definition.addDynFieldBoolean("hasEvaluators");
1179
            definition.addDynFieldBoolean("hasEmulators");
1180
            definition.addDynFieldString("defaultGeometryAttributeName");
1181
            definition.addDynFieldString("defaultTimeAttributeName");
1182
            definition.addDynFieldInt("defaultGeometryAttributeIndex");
1183
            definition.addDynFieldInt("defaultTimeAttributeIndex");
1184
            definition.addDynFieldString("id");
1185
            definition.addDynFieldBoolean("hasOID");
1186
            definition.addDynFieldBoolean("allowAtomaticValues");
1187 44253 jjdelcerro
1188 44190 jjdelcerro
            definition.addDynFieldBoolean("requiredFields");
1189 44253 jjdelcerro
            definition.addDynFieldString("internalID");
1190 44190 jjdelcerro
1191
            definition.addDynFieldList("elements")
1192 44253 jjdelcerro
                    .setClassOfItems(FeatureAttributeDescriptor.class);
1193 44262 jjdelcerro
1194
            definition.addDynFieldObject("tags")
1195
                    .setClassOfValue(Tags.class);
1196
1197 44190 jjdelcerro
        }
1198
    }
1199
1200 44439 jjdelcerro
    @Override
1201
    public FeatureStore getAsFeatureStore() {
1202
        FeatureStore store = FeatureTypeToStoreProviderAdapter.createFeatureStore(this);
1203
        return store;
1204
    }
1205 44498 omartinez
1206
1207 44583 omartinez
    @Override
1208 44498 omartinez
    public String getNewFieldName() {
1209
        I18nManager i18n = ToolsLocator.getI18nManager();
1210
        String prefix = i18n.getTranslation("_Field");
1211
        String fieldName;
1212
        for (int i = 1; i < 1000; i++) {
1213 44583 omartinez
            fieldName = prefix+i;
1214 44498 omartinez
            if( this.get(fieldName)==null ) {
1215
                return fieldName;
1216
            }
1217
        }
1218 44583 omartinez
        fieldName = prefix + (new Date()).getTime();
1219 44498 omartinez
        return fieldName;
1220
    }
1221 44500 omartinez
1222 44583 omartinez
    @Override
1223 44500 omartinez
   public FeatureType getOriginalFeatureType()  {
1224
        DefaultFeatureStore store = (DefaultFeatureStore) this.getStore();
1225
        if (store==null) {
1226
            return null;
1227
        }
1228
        return store.getOriginalFeatureType(this);
1229
    }
1230 44501 jjdelcerro
    @Override
1231
    public boolean hasOnlyMetadataChanges(FeatureType old) {
1232
        if( old == null ) {
1233
            throw new NullPointerException();
1234
        }
1235
        // Si hay campos nuevos -> false
1236
        for (FeatureAttributeDescriptor attr : this) {
1237 44507 omartinez
            if(!attr.isComputed() && old.getAttributeDescriptor(attr.getName())==null) {
1238 44501 jjdelcerro
                return false;
1239
            }
1240
        }
1241
1242
        // Si se ha eliminado algun campo -> false
1243
        for (FeatureAttributeDescriptor attr : old) {
1244 44507 omartinez
            if(!attr.isComputed() && this.getAttributeDescriptor(attr.getName())==null ) {
1245 44501 jjdelcerro
                return false;
1246
            }
1247
        }
1248
1249
        // No hay campos nuevos ni se ha eliminado ninguno, asi que comparamos
1250
        // los campos uno a uno.
1251
        for (FeatureAttributeDescriptor attr : this) {
1252
            FeatureAttributeDescriptor attrold = old.getAttributeDescriptor(attr.getName());
1253 44507 omartinez
            if(!attr.isComputed() && !attr.hasOnlyMetadataChanges(attrold) ) {
1254 44501 jjdelcerro
                return false;
1255
            }
1256
        }
1257
        return true;
1258
    }
1259 44716 jjdelcerro
1260
    public void writeAsDALFile(File file) {
1261
      try {
1262
        DALFile dalFile = DALFile.getDALFile();
1263
        dalFile.setFeatureType(this);
1264
        if( !dalFile.isEmpty() ) {
1265
          dalFile.write(file);
1266
        }
1267
      } catch (Exception ex) {
1268
        throw new RuntimeException("Can't write as DAL file ("+Objects.toString(file)+").", ex);
1269
      }
1270
    }
1271 44253 jjdelcerro
}