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

History | View | Annotate | Download (34.2 KB)

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