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

History | View | Annotate | Download (34.3 KB)

1
/**
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
package org.gvsig.fmap.dal.feature.impl;
25

    
26
import java.lang.ref.WeakReference;
27
import java.util.ArrayList;
28
import java.util.Arrays;
29
import java.util.Collections;
30
import java.util.Comparator;
31
import java.util.HashSet;
32
import java.util.Iterator;
33
import java.util.LinkedHashSet;
34
import java.util.List;
35
import java.util.Set;
36
import java.util.function.Predicate;
37
import java.util.zip.CRC32;
38
import org.apache.commons.lang3.ArrayUtils;
39
import org.apache.commons.lang3.StringUtils;
40

    
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
import org.gvsig.fmap.dal.feature.FeatureAttributeEmulator;
49
import org.gvsig.fmap.dal.feature.FeatureRules;
50
import org.gvsig.fmap.dal.feature.FeatureStore;
51
import org.gvsig.fmap.dal.feature.FeatureType;
52
import org.gvsig.tools.ToolsLocator;
53
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
import org.gvsig.tools.dynobject.DynStruct_v2;
60
import org.gvsig.tools.dynobject.Tags;
61
import org.gvsig.tools.dynobject.exception.DynMethodException;
62
import org.gvsig.tools.dynobject.exception.DynObjectValidateException;
63
import org.gvsig.tools.dynobject.impl.DefaultTags;
64
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
import org.gvsig.tools.util.ChainedIterator;
69

    
70
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

    
79
    /**
80
     *
81
     */
82
    private static final long serialVersionUID = -7988721447349282215L;
83

    
84
    public static final RecentUsedsAttributesImpl RECENTS_USEDS = new RecentUsedsAttributesImpl();
85

    
86
    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

    
99
    private List srsList = null;
100
    private WeakReference storeRef;
101
    private boolean requiredFields;
102

    
103
    private String description;
104
    private String label;
105
    private Tags tags;
106

    
107
    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

    
122
    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

    
131
    protected DefaultFeatureType(FeatureStore store) {
132
        this(store, (String) null);
133
    }
134

    
135
    protected DefaultFeatureType(DefaultFeatureType other) {
136
        this(other.getStore(), (String) null);
137
        copyFrom(other, true);
138
    }
139

    
140
    protected DefaultFeatureType(DefaultFeatureType other,
141
            boolean copyAttributes) {
142
        this(other.getStore(), (String) null);
143
        this.copyFrom(other, copyAttributes);
144
    }
145

    
146
    @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
        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
                DefaultFeatureAttributeDescriptor copy = this.getCopyAttributeDescriptor(attr);
163
                super.add(copy);
164
            }
165
            this.pk = null;
166
        }
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
    
186
    protected DefaultFeatureAttributeDescriptor getCopyAttributeDescriptor(DefaultFeatureAttributeDescriptor src) {
187
        DefaultFeatureAttributeDescriptor copy = new DefaultFeatureAttributeDescriptor(src);
188
        copy.setFeatureType(this);
189
        return copy;
190
    }
191

    
192
    @Override
193
    public String getId() {
194
        return this.id;
195
    }
196

    
197
    @Override
198
    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

    
210
    @Override
211
    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
        }
220
        return null;
221
    }
222

    
223
    @Override
224
    public FeatureAttributeDescriptor getAttributeDescriptor(int index) {
225
        return (FeatureAttributeDescriptor) super.get(index);
226
    }
227

    
228
    @Override
229
    public FeatureType getCopy() {
230
        return new DefaultFeatureType(this);
231
    }
232

    
233
    @Override
234
    public Object clone() {
235
        return this.getCopy();
236
    }
237

    
238
    public int getDefaultGeometryAttributeIndex() {
239
        return this.defaultGeometryAttributeIndex;
240
    }
241

    
242
    public String getDefaultGeometryAttributeName() {
243
        return this.defaultGeometryAttributeName;
244
    }
245

    
246
    public int getDefaultTimeAttributeIndex() {
247
        return this.defaultTimeAttributeIndex;
248
    }
249

    
250
    public String getDefaultTimeAttributeName() {
251
        return this.defaultTimeAttributeName;
252
    }
253

    
254
    public EditableFeatureType getEditable() {
255
        return new DefaultEditableFeatureType(this);
256
    }
257

    
258
    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
        }
267
        return -1;
268
    }
269

    
270
    public FeatureRules getRules() {
271
        return this.rules;
272
    }
273

    
274
    public boolean hasEvaluators() {
275
        return this.hasEvaluators;
276
    }
277

    
278
    public boolean hasEmulators() {
279
        return this.hasEmulators;
280
    }
281

    
282
    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
                }
311
            }
312
            this.srsList = Collections.unmodifiableList(tmp);
313
        }
314
        return this.srsList;
315
    }
316

    
317
    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() throws DataException {
331
        return new SubtypeFeatureType(this, null, null, true);
332
    }
333

    
334
    public FeatureType getSubtype(String[] names) throws DataException {
335
        return this.getSubtype(names, null, true);
336
    }
337

    
338
    public FeatureType getSubtype(String[] names, String[] constantsNames) throws DataException {
339
        return this.getSubtype(names, constantsNames, true);
340
    }
341

    
342
    public FeatureType getSubtype(String[] names, String[] constantsNames, boolean includePk) throws DataException {
343
        if (ArrayUtils.isEmpty(names) && ArrayUtils.isEmpty(constantsNames)) {
344
            return (FeatureType) this.clone();
345
        }
346
        return new SubtypeFeatureType(this, names, constantsNames,includePk);
347
    }
348

    
349
    public boolean isSubtypeOf(FeatureType featureType) {
350
        return false;
351
    }
352

    
353
    @Override
354
    public List<FeatureAttributeDescriptor> toList() {
355
        return Collections.unmodifiableList(this);
356
    }
357

    
358
    @Override
359
    public Tags getTags() {
360
        return this.tags;
361
    }
362

    
363
    @Override
364
    public String getLabel() {
365
        return this.label;
366
    }
367

    
368
    @Override
369
    public void setLabel(String label) {
370
        this.label = label;
371
    }
372

    
373
    @Override
374
    public DynField addDynField(String name, int type) {
375
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
376
    }
377

    
378
    class SubtypeFeatureType extends DefaultFeatureType {
379

    
380
        /**
381
         *
382
         */
383
        private static final long serialVersionUID = 6913732960073922540L;
384
        WeakReference parent;
385

    
386
        SubtypeFeatureType(DefaultFeatureType parent, String[] names, String[] constantsNames, boolean includePk)
387
                throws DataException {
388
            super(parent, false);
389
            DefaultFeatureAttributeDescriptor attrcopy;
390
            Set<String> attrnames = new LinkedHashSet<>();
391
            Set<String> requiredAttrnames = new HashSet<>();
392

    
393
            if (ArrayUtils.isEmpty(names)) {
394
                for (FeatureAttributeDescriptor attrdesc : parent) {
395
                    attrnames.add(attrdesc.getName());
396
                }
397
            } else {
398
                attrnames.addAll(Arrays.asList(names));
399
                requiredAttrnames.addAll(Arrays.asList(names));
400
            }
401
            // Add required fields for emulated fields
402
            if (parent.hasEmulators) {
403
                for (FeatureAttributeDescriptor attrdesc : parent) {
404
                    FeatureAttributeEmulator emulator = attrdesc.getFeatureAttributeEmulator();
405
                    if (emulator != null) {
406
                        String ss[] = emulator.getRequiredFieldNames();
407
                        if (ss != null) {
408
                            attrnames.addAll(Arrays.asList(ss));
409
                            requiredAttrnames.addAll(Arrays.asList(ss));
410
                        }
411
                    }
412
                }
413
            }
414
            // Add missing pk fiels
415
            if (includePk && !parent.hasOID()) {
416
                for (FeatureAttributeDescriptor attrdesc : parent) {
417
                    if (attrdesc.isPrimaryKey()) {
418
                        attrnames.add(attrdesc.getName());
419
                        requiredAttrnames.add(attrdesc.getName());
420
                    }
421
                }
422
            }
423

    
424
            // Copy attributes
425
            int i = 0;
426
            for (String name : attrnames) {
427
                DefaultFeatureAttributeDescriptor attr = (DefaultFeatureAttributeDescriptor) parent.get(name);
428
                if (attr == null) {
429
                    throw new SubtypeFeatureTypeNameException(name, parent.getId());
430
                }
431
                attrcopy = new DefaultFeatureAttributeDescriptor(attr);
432
                this.add(attrcopy);
433
                attrcopy.index = i++;
434
            }
435

    
436
            // Set the consttants attributes.
437
            if (!ArrayUtils.isEmpty(constantsNames)) {
438
                for (String name : constantsNames) {
439
                    if (!requiredAttrnames.contains(name)) {
440
                        DefaultFeatureAttributeDescriptor attr = (DefaultFeatureAttributeDescriptor) this.get(name);
441
                        attr.setConstantValue(true);
442
                    }
443
                }
444
            }
445

    
446
            this.defaultGeometryAttributeIndex = this.getIndex(this.defaultGeometryAttributeName);
447
            if (this.defaultGeometryAttributeIndex < 0) {
448
                this.defaultGeometryAttributeName = null;
449
            }
450
            this.defaultTimeAttributeIndex = this.getIndex(this.defaultTimeAttributeName);
451
            if (this.defaultTimeAttributeIndex < 0) {
452
                this.defaultTimeAttributeName = null;
453
            }
454
            this.parent = new WeakReference(parent);
455
        }
456

    
457
        public FeatureType getSubtype(String[] names, boolean includePk) throws DataException {
458
            return new SubtypeFeatureType((DefaultFeatureType) this.parent
459
                    .get(), names, null, includePk);
460
        }
461

    
462
        public boolean isSubtypeOf(FeatureType featureType) {
463
            if (featureType == null) {
464
                return false;
465
            }
466
            FeatureType parent = (FeatureType) this.parent.get();
467
            return featureType.equals(parent);
468
        }
469

    
470
        public EditableFeatureType getEditable() {
471
            throw new UnsupportedOperationException();
472
        }
473
    }
474

    
475
    public class SubtypeFeatureTypeNameException extends DataException {
476

    
477
        /**
478
         *
479
         */
480
        private static final long serialVersionUID = -4414242486723260101L;
481
        private final static String MESSAGE_FORMAT = "Attribute name '%(name)' not found in type (%(type)).";
482
        private final static String MESSAGE_KEY = "_SubtypeFeatureTypeNameException";
483

    
484
        public SubtypeFeatureTypeNameException(String name, String type) {
485
            super(MESSAGE_FORMAT, MESSAGE_KEY, serialVersionUID);
486
            setValue("name", name);
487
            setValue("type", type);
488
        }
489
    }
490

    
491
    public boolean hasOID() {
492
        return hasOID;
493
    }
494

    
495
    public String toString() {
496
        StringBuffer s = new StringBuffer();
497
        s.append(this.getId());
498
        s.append(":[");
499
        String attName;
500
        for (int i = 0; i < size(); i++) {
501
            attName = ((FeatureAttributeDescriptor) get(i)).getName().toString();
502
            s.append(attName);
503
            if (i < size() - 1) {
504
                s.append(',');
505
            }
506
        }
507
        s.append(']');
508
        return s.toString();
509
    }
510

    
511
    public Iterator<FeatureAttributeDescriptor> iterator() {
512
        return getIterator(super.iterator());
513
    }
514

    
515
    protected Iterator getIterator(Iterator iter) {
516
        return new DelegatedIterator(iter);
517
    }
518

    
519
    protected class DelegatedIterator implements Iterator {
520

    
521
        protected Iterator iterator;
522

    
523
        public DelegatedIterator(Iterator iter) {
524
            this.iterator = iter;
525
        }
526

    
527
        public boolean hasNext() {
528
            return iterator.hasNext();
529
        }
530

    
531
        public Object next() {
532
            return iterator.next();
533
        }
534

    
535
        public void remove() {
536
            throw new UnsupportedOperationException();
537
        }
538

    
539
    }
540

    
541
    public boolean allowAutomaticValues() {
542
        return this.allowAtomaticValues;
543
    }
544

    
545
    public FeatureAttributeDescriptor[] getAttributeDescriptors() {
546
        return (FeatureAttributeDescriptor[]) super
547
                .toArray(new FeatureAttributeDescriptor[super.size()]);
548
    }
549

    
550
    public FeatureAttributeDescriptor[] getPrimaryKey() {
551
        if (pk == null) {
552
            List pks = new ArrayList();
553
            Iterator iter = super.iterator();
554
            FeatureAttributeDescriptor attr;
555
            while (iter.hasNext()) {
556
                attr = (FeatureAttributeDescriptor) iter.next();
557
                if (attr.isPrimaryKey()) {
558
                    pks.add(attr);
559
                }
560
            }
561
            if (pks.isEmpty()) {
562
                pk = new FeatureAttributeDescriptor[0];
563
            } else {
564
                pk = (FeatureAttributeDescriptor[]) pks.toArray(new FeatureAttributeDescriptor[pks.size()]);
565
            }
566
        }
567
        return pk;
568
    }
569

    
570
    public FeatureAttributeDescriptor getDefaultGeometryAttribute() {
571
        if (this.defaultGeometryAttributeIndex < 0) {
572
            return null;
573
        }
574
        return (FeatureAttributeDescriptor) super
575
                .get(this.defaultGeometryAttributeIndex);
576
    }
577

    
578
    public boolean equals(Object o) {
579
        if (this == o) {
580
            return true;
581
        }
582
        if (!(o instanceof DefaultFeatureType)) {
583
            return false;
584
        }
585
        DefaultFeatureType other = (DefaultFeatureType) o;
586
        if (!this.id.equals(other.id)) {
587
            return false;
588
        }
589
        if (this.size() != other.size()) {
590
            return false;
591
        }
592
        FeatureAttributeDescriptor attr, attrOther;
593
        Iterator iter, iterOther;
594
        iter = this.iterator();
595
        iterOther = other.iterator();
596
        while (iter.hasNext()) {
597
            attr = (FeatureAttributeDescriptor) iter.next();
598
            attrOther = (FeatureAttributeDescriptor) iterOther.next();
599
            if (!attr.equals(attrOther)) {
600
                return false;
601
            }
602
        }
603

    
604
        if (!StringUtils.equals(defaultGeometryAttributeName, other.defaultGeometryAttributeName)) {
605
            return false;
606
        }
607
        if (!StringUtils.equals(defaultTimeAttributeName, other.defaultTimeAttributeName)) {
608
            return false;
609
        }
610
        return true;
611

    
612
    }
613

    
614
    /**
615
     * Start of DynClass interface implementation READONLY
616
     */
617
    public DynField addDynField(String name) {
618
        throw new UnsupportedOperationException();
619
    }
620

    
621
    public DynField getDeclaredDynField(String name) {
622
        return (DynField) getAttributeDescriptor(name);
623
    }
624

    
625
    public DynField[] getDeclaredDynFields() {
626
        return (DynField[]) getAttributeDescriptors();
627
    }
628

    
629
    public String getDescription() {
630
        return this.description;
631
    }
632

    
633
    public DynField getDynField(String name) {
634
        return (DynField) getAttributeDescriptor(name);
635
    }
636

    
637
    public DynField[] getDynFields() {
638
        return (DynField[]) getAttributeDescriptors();
639
    }
640

    
641
    public String getName() {
642
        return this.id + "_" + internalID;
643
    }
644

    
645
    public void removeDynField(String name) {
646
        throw new UnsupportedOperationException();
647

    
648
    }
649

    
650
    public void addDynMethod(DynMethod dynMethod) {
651
        throw new UnsupportedOperationException();
652

    
653
    }
654

    
655
    public void extend(DynClass dynClass) {
656
        throw new UnsupportedOperationException();
657

    
658
    }
659

    
660
    public void extend(String dynClassName) {
661
        throw new UnsupportedOperationException();
662

    
663
    }
664

    
665
    public void extend(String namespace, String dynClassName) {
666
        throw new UnsupportedOperationException();
667

    
668
    }
669

    
670
    public DynMethod getDeclaredDynMethod(String name)
671
            throws DynMethodException {
672
        return null;
673
    }
674

    
675
    public DynMethod[] getDeclaredDynMethods() throws DynMethodException {
676
        return null;
677
    }
678

    
679
    public DynMethod getDynMethod(String name) throws DynMethodException {
680
        return null;
681
    }
682

    
683
    public DynMethod getDynMethod(int code) throws DynMethodException {
684
        return null;
685
    }
686

    
687
    public DynMethod[] getDynMethods() throws DynMethodException {
688
        return null;
689
    }
690

    
691
    public DynClass[] getSuperDynClasses() {
692
        return null;
693
    }
694

    
695
    public boolean isInstance(DynObject dynObject) {
696
        if (dynObject.getDynClass().getName() == getName()) {
697
            return true;
698
        }
699
        return false;
700
    }
701

    
702
    public DynObject newInstance() {
703

    
704
        throw new UnsupportedOperationException();
705
    }
706

    
707
    public void removeDynMethod(String name) {
708
        throw new UnsupportedOperationException();
709

    
710
    }
711

    
712
    public DynField addDynFieldChoice(String name, int type,
713
            Object defaultValue, DynObjectValueItem[] values,
714
            boolean mandatory, boolean persistent) {
715
        throw new UnsupportedOperationException();
716
    }
717

    
718
    public DynField addDynFieldRange(String name, int type,
719
            Object defaultValue, Object min, Object max, boolean mandatory,
720
            boolean persistent) {
721
        throw new UnsupportedOperationException();
722
    }
723

    
724
    public DynField addDynFieldSingle(String name, int type,
725
            Object defaultValue, boolean mandatory, boolean persistent) {
726
        throw new UnsupportedOperationException();
727
    }
728

    
729
    public void validate(DynObject object) throws DynObjectValidateException {
730
        //FIXME: not sure it's the correct code
731
        if (object instanceof Feature) {
732
            Feature fea = (Feature) object;
733
            if (fea.getType().equals(this)) {
734
                return;
735
            }
736
        }
737
        throw new DynObjectValidateException(this.id);
738
    }
739

    
740
    public DynField addDynFieldLong(String name) {
741
        throw new UnsupportedOperationException();
742
    }
743

    
744
    public DynField addDynFieldChoice(String name, int type,
745
            Object defaultValue, DynObjectValueItem[] values) {
746
        throw new UnsupportedOperationException();
747
    }
748

    
749
    public DynField addDynFieldRange(String name, int type,
750
            Object defaultValue, Object min, Object max) {
751
        throw new UnsupportedOperationException();
752
    }
753

    
754
    public DynField addDynFieldSingle(String name, int type, Object defaultValue) {
755
        throw new UnsupportedOperationException();
756
    }
757

    
758
    public DynField addDynFieldString(String name) {
759
        throw new UnsupportedOperationException();
760
    }
761

    
762
    public DynField addDynFieldInt(String name) {
763
        throw new UnsupportedOperationException();
764
    }
765

    
766
    public DynField addDynFieldDouble(String name) {
767
        throw new UnsupportedOperationException();
768
    }
769

    
770
    public DynField addDynFieldFloat(String name) {
771
        throw new UnsupportedOperationException();
772
    }
773

    
774
    public DynField addDynFieldBoolean(String name) {
775
        throw new UnsupportedOperationException();
776
    }
777

    
778
    public DynField addDynFieldList(String name) {
779
        throw new UnsupportedOperationException();
780
    }
781

    
782
    public DynField addDynFieldMap(String name) {
783
        throw new UnsupportedOperationException();
784
    }
785

    
786
    public DynField addDynFieldObject(String name) {
787
        throw new UnsupportedOperationException();
788
    }
789

    
790
    public DynField addDynFieldSet(String name) {
791
        throw new UnsupportedOperationException();
792
    }
793

    
794
    public DynField addDynFieldArray(String name) {
795
        throw new UnsupportedOperationException();
796
    }
797

    
798
    public DynField addDynFieldDate(String name) {
799
        throw new UnsupportedOperationException();
800
    }
801

    
802
    public void extend(DynStruct struct) {
803
        throw new UnsupportedOperationException();
804
    }
805

    
806
    public String getFullName() {
807
        // TODO: usar el DynClassName
808
        return this.id;
809
    }
810

    
811
    public String getNamespace() {
812
        return "DALFeature";
813
    }
814

    
815
    public DynStruct[] getSuperDynStructs() {
816
        return null;
817
    }
818

    
819
    public void setDescription(String description) {
820
        this.description = description;
821
    }
822

    
823
    public void setNamespace(String namespace) {
824
        throw new UnsupportedOperationException();
825
    }
826

    
827
    public DynField addDynFieldFile(String name) {
828
        throw new UnsupportedOperationException();
829
    }
830

    
831
    public DynField addDynFieldFolder(String name) {
832
        throw new UnsupportedOperationException();
833
    }
834

    
835
    public DynField addDynFieldURL(String name) {
836
        throw new UnsupportedOperationException();
837
    }
838

    
839
    public DynField addDynFieldURI(String name) {
840
        throw new UnsupportedOperationException();
841
    }
842

    
843
    public boolean isExtendable(DynStruct dynStruct) {
844
        return false;
845
    }
846

    
847
    public void extend(DynStruct[] structs) {
848
        // TODO Auto-generated method stub
849

    
850
    }
851

    
852
    public void remove(DynStruct superDynStruct) {
853
        // TODO Auto-generated method stub
854

    
855
    }
856

    
857
    public void removeAll(DynStruct[] superDynStruct) {
858
        // TODO Auto-generated method stub
859

    
860
    }
861

    
862
    public FeatureAttributeDescriptor getDefaultTimeAttribute() {
863
        if (this.defaultTimeAttributeIndex < 0) {
864
            return null;
865
        }
866
        return (FeatureAttributeDescriptor) super
867
                .get(this.defaultTimeAttributeIndex);
868
    }
869

    
870
    public void setDefaultTimeAttributeName(String name) {
871
        if (name == null || name.length() == 0) {
872
            this.defaultTimeAttributeIndex = -1;
873
            return;
874
        }
875
        DefaultFeatureAttributeDescriptor attr = (DefaultFeatureAttributeDescriptor) this.get(name);
876
        if (attr == null) {
877
            throw new IllegalArgumentException("Attribute '" + name + "' not found.");
878
        }
879
        if (attr.getIndex() < 0) {
880
            fixAll();
881
        }
882
        this.defaultTimeAttributeIndex = attr.getIndex();
883
    }
884

    
885
    protected void fixAll() {
886
        int i = 0;
887
        Iterator iter = super.iterator();
888
        DefaultFeatureAttributeDescriptor attr;
889

    
890
        while (iter.hasNext()) {
891
            attr = (DefaultFeatureAttributeDescriptor) iter.next();
892
            if (attr.getOder() < 1) {
893
                attr.setOrder(i * 10);
894
            }
895
            attr.setIndex(i++);
896
            attr.fixAll();
897
            if (attr.getEvaluator() != null) {
898
                this.hasEvaluators = true;
899
            }
900
            if (attr.getFeatureAttributeEmulator() != null) {
901
                this.hasEmulators = true;
902
                String[] x = attr.getFeatureAttributeEmulator().getRequiredFieldNames();
903
                if (!ArrayUtils.isEmpty(x)) {
904
                    this.requiredFields = true;
905
                }
906
            }
907
            switch (attr.getType()) {
908
                case DataTypes.GEOMETRY:
909
                    if (this.defaultGeometryAttributeName == null) {
910
                        this.defaultGeometryAttributeName = attr.getName();
911
                    }
912
                    break;
913
                case DataTypes.INSTANT:
914
                case DataTypes.INTERVAL:
915
                case DataTypes.DATE:
916
                    if (this.defaultTimeAttributeName == null && attr.isTime()) {
917
                        this.defaultTimeAttributeName = attr.getName();
918
                    }
919
                    break;
920
            }
921
        }
922
        if (this.defaultGeometryAttributeName != null) {
923
            this.defaultGeometryAttributeIndex = this.getIndex(this.defaultGeometryAttributeName);
924
        }
925
        if (this.defaultTimeAttributeName != null) {
926
            this.defaultTimeAttributeIndex = this.getIndex(this.defaultTimeAttributeName);
927
        }
928
        this.internalID = Long.toHexString(this.getCRC());
929

    
930
    }
931

    
932
    protected long getCRC() {
933
        StringBuffer buffer = new StringBuffer();
934
        for (int i = 0; i < this.size(); i++) {
935
            FeatureAttributeDescriptor x = this.getAttributeDescriptor(i);
936
            buffer.append(x.getName());
937
            buffer.append(x.getDataTypeName());
938
            buffer.append(x.getSize());
939
        }
940
        CRC32 crc = new CRC32();
941
        byte[] data = buffer.toString().getBytes();
942
        crc.update(data);
943
        return crc.getValue();
944
    }
945

    
946
    @Override
947
    public FeatureStore getStore() {
948
        if (this.storeRef == null) {
949
            return null;
950
        }
951
        return (FeatureStore) this.storeRef.get();
952
    }
953

    
954
    public void setStore(FeatureStore store) {
955
        if (store == null) {
956
            this.storeRef = null;
957
        } else {
958
            this.storeRef = new WeakReference(store);
959
        }
960
    }
961

    
962
    @Override
963
    public List<FeatureAttributeDescriptor> getFilteredAttributes(
964
            Predicate<FeatureAttributeDescriptor> filter,
965
            int max
966
    ) {
967
        List<FeatureAttributeDescriptor> attrs = new ArrayList<>();
968
        for (FeatureAttributeDescriptor attribute : this) {
969
            if (filter.test(attribute)) {
970
                attrs.add(attribute);
971
            }
972
        }
973
        return attrs;
974
    }
975
    
976
    @Override
977
    public List<FeatureAttributeDescriptor> getRecentUseds() {
978
        return RECENTS_USEDS.getAttributes(this);
979
    }
980
    
981
    @Override
982
    public void loadFromState(PersistentState state)
983
            throws PersistenceException {
984

    
985
//        FIXME: rules
986
        hasEvaluators = state.getBoolean("hasEvaluators");
987
        hasEmulators = state.getBoolean("hasEmulators");
988
        defaultGeometryAttributeName = state.getString("defaultGeometryAttributeName");
989
        defaultTimeAttributeName = state.getString("defaultTimeAttributeName");
990
        defaultGeometryAttributeIndex = state.getInt("defaultGeometryAttributeIndex");
991
        defaultTimeAttributeIndex = state.getInt("defaultTimeAttributeIndex");
992
        id = state.getString("id");
993
        hasOID = state.getBoolean("hasOID");
994
        allowAtomaticValues = state.getBoolean("allowAtomaticValues");
995

    
996
        requiredFields = state.getBoolean("requiredFields");
997
        internalID = state.getString("internalID");
998
        tags = (Tags) state.get("tags");
999
        if( tags == null ) {
1000
            this.tags = new DefaultTags();
1001
        }
1002

    
1003
        List<FeatureAttributeDescriptor> elements = state.getList("elements");
1004
        for (FeatureAttributeDescriptor element : elements) {
1005
            ((DefaultFeatureAttributeDescriptor) element).setFeatureType(this);
1006
            super.add(element);
1007
        }
1008
        this.pk = null;
1009
        this.fixAll();
1010
    }
1011

    
1012
    @Override
1013
    public void saveToState(PersistentState state) throws PersistenceException {
1014

    
1015
//        FIXME: rules
1016
        state.set("hasEvaluators", hasEvaluators);
1017
        state.set("hasEmulators", hasEmulators);
1018
        state.set("defaultGeometryAttributeName", defaultGeometryAttributeName);
1019
        state.set("defaultTimeAttributeName", defaultTimeAttributeName);
1020
        state.set("defaultGeometryAttributeIndex", defaultGeometryAttributeIndex);
1021
        state.set("defaultTimeAttributeIndex", defaultTimeAttributeIndex);
1022
        state.set("id", id);
1023
        state.set("hasOID", hasOID);
1024
        state.set("allowAtomaticValues", allowAtomaticValues);
1025

    
1026
        state.set("requiredFields", requiredFields);
1027
        state.set("internalID", internalID);
1028

    
1029
        List<FeatureAttributeDescriptor> elements = new ArrayList<>();
1030
        elements.addAll(this);
1031
        state.set("elements", elements);
1032
        state.set("tags", tags);
1033

    
1034
    }
1035

    
1036
    private static final String FEATTYPE_PERSISTENCE_DEFINITION_NAME = "FeatureType";
1037

    
1038
    public static void registerPersistenceDefinition() {
1039
        PersistenceManager manager = ToolsLocator.getPersistenceManager();
1040

    
1041
        if (manager.getDefinition(FEATTYPE_PERSISTENCE_DEFINITION_NAME)
1042
                == null) {
1043
            DynStruct definition = manager.addDefinition(DefaultFeatureType.class,
1044
                    FEATTYPE_PERSISTENCE_DEFINITION_NAME,
1045
                    FEATTYPE_PERSISTENCE_DEFINITION_NAME
1046
                    + " persistent definition",
1047
                    null,
1048
                    null
1049
            );
1050
//            definition.addDynFieldObject("rules");
1051
            definition.addDynFieldBoolean("hasEvaluators");
1052
            definition.addDynFieldBoolean("hasEmulators");
1053
            definition.addDynFieldString("defaultGeometryAttributeName");
1054
            definition.addDynFieldString("defaultTimeAttributeName");
1055
            definition.addDynFieldInt("defaultGeometryAttributeIndex");
1056
            definition.addDynFieldInt("defaultTimeAttributeIndex");
1057
            definition.addDynFieldString("id");
1058
            definition.addDynFieldBoolean("hasOID");
1059
            definition.addDynFieldBoolean("allowAtomaticValues");
1060

    
1061
            definition.addDynFieldBoolean("requiredFields");
1062
            definition.addDynFieldString("internalID");
1063

    
1064
            definition.addDynFieldList("elements")
1065
                    .setClassOfItems(FeatureAttributeDescriptor.class);
1066

    
1067
            definition.addDynFieldObject("tags")
1068
                    .setClassOfValue(Tags.class);
1069
            
1070
        }
1071
    }
1072

    
1073
}