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

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