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

History | View | Annotate | Download (33.6 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
        initialize(other, true);
138
    }
139

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

    
146
    protected void initialize(DefaultFeatureType other, boolean copyAttributes) {
147
        this.id = other.getId();
148
        if (copyAttributes) {
149
            Iterator iter = other.iterator();
150
            DefaultFeatureAttributeDescriptor attr;
151
            while (iter.hasNext()) {
152
                attr = (DefaultFeatureAttributeDescriptor) iter.next();
153
                this.intitalizeAddAttibute(attr);
154
            }
155
            this.pk = null;
156
        }
157
        this.defaultGeometryAttributeName = other.defaultGeometryAttributeName;
158
        this.defaultTimeAttributeName = other.defaultTimeAttributeName;
159
        this.hasEvaluators = other.hasEvaluators;
160
        this.hasEmulators = other.hasEmulators;
161
        this.rules = (DefaultFeatureRules) other.rules.getCopy();
162
        this.defaultGeometryAttributeIndex = other.defaultGeometryAttributeIndex;
163
        this.defaultTimeAttributeIndex = other.defaultTimeAttributeIndex;
164
        this.hasOID = other.hasOID;
165
        this.id = other.id; // XXX ???? copiar o no esto????
166
        this.internalID = other.internalID;
167
        this.label = other.label;
168
        this.description = other.description;
169
        try {
170
            this.tags = (Tags) other.tags.clone();
171
        } catch (CloneNotSupportedException ex) {
172
            
173
        }
174
    }
175

    
176
    protected void intitalizeAddAttibute(DefaultFeatureAttributeDescriptor attr) {
177
        super.add(attr.getCopy());
178
    }
179

    
180
    public String getId() {
181
        return this.id;
182
    }
183

    
184
    public Object get(String name) {
185
        FeatureAttributeDescriptor attr;
186
        Iterator iter = this.iterator();
187
        while (iter.hasNext()) {
188
            attr = (FeatureAttributeDescriptor) iter.next();
189
            if (attr.getName().equalsIgnoreCase(name)) {
190
                return attr;
191
            }
192
        }
193
        return null;
194
    }
195

    
196
    public FeatureAttributeDescriptor getAttributeDescriptor(String name) {
197
        FeatureAttributeDescriptor attr;
198
        Iterator iter = this.iterator();
199
        while (iter.hasNext()) {
200
            attr = (FeatureAttributeDescriptor) iter.next();
201
            if (attr.getName().equalsIgnoreCase(name)) {
202
                return attr;
203
            }
204
        }
205
        return null;
206
    }
207

    
208
    public FeatureAttributeDescriptor getAttributeDescriptor(int index) {
209
        return (FeatureAttributeDescriptor) super.get(index);
210
    }
211

    
212
    public FeatureType getCopy() {
213
        return new DefaultFeatureType(this);
214
    }
215

    
216
    public Object clone() {
217
        return this.getCopy();
218
    }
219

    
220
    public int getDefaultGeometryAttributeIndex() {
221
        return this.defaultGeometryAttributeIndex;
222
    }
223

    
224
    public String getDefaultGeometryAttributeName() {
225
        return this.defaultGeometryAttributeName;
226
    }
227

    
228
    public int getDefaultTimeAttributeIndex() {
229
        return this.defaultTimeAttributeIndex;
230
    }
231

    
232
    public String getDefaultTimeAttributeName() {
233
        return this.defaultTimeAttributeName;
234
    }
235

    
236
    public EditableFeatureType getEditable() {
237
        return new DefaultEditableFeatureType(this);
238
    }
239

    
240
    public int getIndex(String name) {
241
        FeatureAttributeDescriptor attr;
242
        Iterator iter = this.iterator();
243
        while (iter.hasNext()) {
244
            attr = (FeatureAttributeDescriptor) iter.next();
245
            if (attr.getName().equalsIgnoreCase(name)) {
246
                return attr.getIndex();
247
            }
248
        }
249
        return -1;
250
    }
251

    
252
    public FeatureRules getRules() {
253
        return this.rules;
254
    }
255

    
256
    public boolean hasEvaluators() {
257
        return this.hasEvaluators;
258
    }
259

    
260
    public boolean hasEmulators() {
261
        return this.hasEmulators;
262
    }
263

    
264
    public boolean hasRequiredFields() {
265
        return this.requiredFields;
266
    }
267

    
268
    public List getSRSs() {
269
        if (this.srsList == null) {
270
            ArrayList tmp = new ArrayList();
271
            Iterator iter = iterator();
272
            Iterator tmpIter;
273
            boolean allreadyHave;
274
            IProjection tmpSRS;
275
            FeatureAttributeDescriptor attr;
276
            while (iter.hasNext()) {
277
                attr = (FeatureAttributeDescriptor) iter.next();
278
                if (attr.getDataType().getType() == DataTypes.GEOMETRY
279
                        && attr.getSRS() != null) {
280
                    allreadyHave = false;
281
                    tmpIter = tmp.iterator();
282
                    while (tmpIter.hasNext()) {
283
                        tmpSRS = (IProjection) tmpIter.next();
284
                        if (tmpSRS.getAbrev().equals(attr.getSRS().getAbrev())) {
285
                            allreadyHave = true;
286
                            break;
287
                        }
288
                    }
289
                    if (!allreadyHave) {
290
                        tmp.add(attr.getSRS());
291
                    }
292
                }
293
            }
294
            this.srsList = Collections.unmodifiableList(tmp);
295
        }
296
        return this.srsList;
297
    }
298

    
299
    public IProjection getDefaultSRS() {
300
        if (this.getDefaultGeometryAttributeIndex() < 0) {
301
            return null;
302
        }
303
        return this.getAttributeDescriptor(
304
                this.getDefaultGeometryAttributeIndex()).getSRS();
305
    }
306

    
307
    public void validateFeature(Feature feature, int mode) throws DataException {
308
        DefaultFeatureRules rules = (DefaultFeatureRules) this.getRules();
309
        rules.validate(feature, mode);
310
    }
311

    
312
    public FeatureType getSubtype(String[] names) throws DataException {
313
        if (names == null || names.length < 1) {
314
            return (FeatureType) this.clone();
315
        }
316
        return new SubtypeFeatureType(this, names, null);
317
    }
318

    
319
    public FeatureType getSubtype(String[] names, String[] constantsNames) throws DataException {
320
        if (ArrayUtils.isEmpty(names) && ArrayUtils.isEmpty(constantsNames)) {
321
            return (FeatureType) this.clone();
322
        }
323
        return new SubtypeFeatureType(this, names, constantsNames);
324
    }
325

    
326
    public FeatureType getSubtype() throws DataException {
327
        return new SubtypeFeatureType(this, null, null);
328
    }
329

    
330
    public boolean isSubtypeOf(FeatureType featureType) {
331
        return false;
332
    }
333

    
334
    @Override
335
    public List<FeatureAttributeDescriptor> toList() {
336
        return Collections.unmodifiableList(this);
337
    }
338

    
339
    @Override
340
    public Tags getTags() {
341
        return this.tags;
342
    }
343

    
344
    @Override
345
    public String getLabel() {
346
        return this.label;
347
    }
348

    
349
    @Override
350
    public void setLabel(String label) {
351
        this.label = label;
352
    }
353

    
354
    @Override
355
    public DynField addDynField(String name, int type) {
356
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
357
    }
358

    
359
    class SubtypeFeatureType extends DefaultFeatureType {
360

    
361
        /**
362
         *
363
         */
364
        private static final long serialVersionUID = 6913732960073922540L;
365
        WeakReference parent;
366

    
367
        SubtypeFeatureType(DefaultFeatureType parent, String[] names, String[] constantsNames)
368
                throws DataException {
369
            super(parent, false);
370
            DefaultFeatureAttributeDescriptor attrcopy;
371
            Set<String> attrnames = new LinkedHashSet<>();
372
            Set<String> requiredAttrnames = new HashSet<>();
373

    
374
            if (ArrayUtils.isEmpty(names)) {
375
                for (FeatureAttributeDescriptor attrdesc : parent) {
376
                    attrnames.add(attrdesc.getName());
377
                }
378
            } else {
379
                attrnames.addAll(Arrays.asList(names));
380
                requiredAttrnames.addAll(Arrays.asList(names));
381
            }
382
            // Add required fields for emulated fields
383
            if (parent.hasEmulators) {
384
                for (FeatureAttributeDescriptor attrdesc : parent) {
385
                    FeatureAttributeEmulator emulator = attrdesc.getFeatureAttributeEmulator();
386
                    if (emulator != null) {
387
                        String ss[] = emulator.getRequiredFieldNames();
388
                        if (ss != null) {
389
                            attrnames.addAll(Arrays.asList(ss));
390
                            requiredAttrnames.addAll(Arrays.asList(ss));
391
                        }
392
                    }
393
                }
394
            }
395
            // Add missing pk fiels
396
            if (!parent.hasOID()) {
397
                for (FeatureAttributeDescriptor attrdesc : parent) {
398
                    if (attrdesc.isPrimaryKey()) {
399
                        attrnames.add(attrdesc.getName());
400
                        requiredAttrnames.add(attrdesc.getName());
401
                    }
402
                }
403
            }
404

    
405
            // Copy attributes
406
            int i = 0;
407
            for (String name : attrnames) {
408
                DefaultFeatureAttributeDescriptor attr = (DefaultFeatureAttributeDescriptor) parent.get(name);
409
                if (attr == null) {
410
                    throw new SubtypeFeatureTypeNameException(name, parent.getId());
411
                }
412
                attrcopy = new DefaultFeatureAttributeDescriptor(attr);
413
                this.add(attrcopy);
414
                attrcopy.index = i++;
415
            }
416

    
417
            // Set the consttants attributes.
418
            if (!ArrayUtils.isEmpty(constantsNames)) {
419
                for (String name : constantsNames) {
420
                    if (!requiredAttrnames.contains(name)) {
421
                        DefaultFeatureAttributeDescriptor attr = (DefaultFeatureAttributeDescriptor) this.get(name);
422
                        attr.setConstantValue(true);
423
                    }
424
                }
425
            }
426

    
427
            this.defaultGeometryAttributeIndex = this.getIndex(this.defaultGeometryAttributeName);
428
            if (this.defaultGeometryAttributeIndex < 0) {
429
                this.defaultGeometryAttributeName = null;
430
            }
431
            this.defaultTimeAttributeIndex = this.getIndex(this.defaultTimeAttributeName);
432
            if (this.defaultTimeAttributeIndex < 0) {
433
                this.defaultTimeAttributeName = null;
434
            }
435
            this.parent = new WeakReference(parent);
436
        }
437

    
438
        public FeatureType getSubtype(String[] names) throws DataException {
439
            return new SubtypeFeatureType((DefaultFeatureType) this.parent
440
                    .get(), names, null);
441
        }
442

    
443
        public boolean isSubtypeOf(FeatureType featureType) {
444
            if (featureType == null) {
445
                return false;
446
            }
447
            FeatureType parent = (FeatureType) this.parent.get();
448
            return featureType.equals(parent);
449
        }
450

    
451
        public EditableFeatureType getEditable() {
452
            throw new UnsupportedOperationException();
453
        }
454
    }
455

    
456
    public class SubtypeFeatureTypeNameException extends DataException {
457

    
458
        /**
459
         *
460
         */
461
        private static final long serialVersionUID = -4414242486723260101L;
462
        private final static String MESSAGE_FORMAT = "Attribute name '%(name)' not found in type (%(type)).";
463
        private final static String MESSAGE_KEY = "_SubtypeFeatureTypeNameException";
464

    
465
        public SubtypeFeatureTypeNameException(String name, String type) {
466
            super(MESSAGE_FORMAT, MESSAGE_KEY, serialVersionUID);
467
            setValue("name", name);
468
            setValue("type", type);
469
        }
470
    }
471

    
472
    public boolean hasOID() {
473
        return hasOID;
474
    }
475

    
476
    public String toString() {
477
        StringBuffer s = new StringBuffer();
478
        s.append(this.getId());
479
        s.append(":[");
480
        String attName;
481
        for (int i = 0; i < size(); i++) {
482
            attName = ((FeatureAttributeDescriptor) get(i)).getName().toString();
483
            s.append(attName);
484
            if (i < size() - 1) {
485
                s.append(',');
486
            }
487
        }
488
        s.append(']');
489
        return s.toString();
490
    }
491

    
492
    public Iterator<FeatureAttributeDescriptor> iterator() {
493
        return getIterator(super.iterator());
494
    }
495

    
496
    protected Iterator getIterator(Iterator iter) {
497
        return new DelegatedIterator(iter);
498
    }
499

    
500
    protected class DelegatedIterator implements Iterator {
501

    
502
        protected Iterator iterator;
503

    
504
        public DelegatedIterator(Iterator iter) {
505
            this.iterator = iter;
506
        }
507

    
508
        public boolean hasNext() {
509
            return iterator.hasNext();
510
        }
511

    
512
        public Object next() {
513
            return iterator.next();
514
        }
515

    
516
        public void remove() {
517
            throw new UnsupportedOperationException();
518
        }
519

    
520
    }
521

    
522
    public boolean allowAutomaticValues() {
523
        return this.allowAtomaticValues;
524
    }
525

    
526
    public FeatureAttributeDescriptor[] getAttributeDescriptors() {
527
        return (FeatureAttributeDescriptor[]) super
528
                .toArray(new FeatureAttributeDescriptor[super.size()]);
529
    }
530

    
531
    public FeatureAttributeDescriptor[] getPrimaryKey() {
532
        if (pk == null) {
533
            List pks = new ArrayList();
534
            Iterator iter = super.iterator();
535
            FeatureAttributeDescriptor attr;
536
            while (iter.hasNext()) {
537
                attr = (FeatureAttributeDescriptor) iter.next();
538
                if (attr.isPrimaryKey()) {
539
                    pks.add(attr);
540
                }
541
            }
542
            if (pks.isEmpty()) {
543
                pk = new FeatureAttributeDescriptor[0];
544
            } else {
545
                pk = (FeatureAttributeDescriptor[]) pks.toArray(new FeatureAttributeDescriptor[pks.size()]);
546
            }
547
        }
548
        return pk;
549
    }
550

    
551
    public FeatureAttributeDescriptor getDefaultGeometryAttribute() {
552
        if (this.defaultGeometryAttributeIndex < 0) {
553
            return null;
554
        }
555
        return (FeatureAttributeDescriptor) super
556
                .get(this.defaultGeometryAttributeIndex);
557
    }
558

    
559
    public boolean equals(Object o) {
560
        if (this == o) {
561
            return true;
562
        }
563
        if (!(o instanceof DefaultFeatureType)) {
564
            return false;
565
        }
566
        DefaultFeatureType other = (DefaultFeatureType) o;
567
        if (!this.id.equals(other.id)) {
568
            return false;
569
        }
570
        if (this.size() != other.size()) {
571
            return false;
572
        }
573
        FeatureAttributeDescriptor attr, attrOther;
574
        Iterator iter, iterOther;
575
        iter = this.iterator();
576
        iterOther = other.iterator();
577
        while (iter.hasNext()) {
578
            attr = (FeatureAttributeDescriptor) iter.next();
579
            attrOther = (FeatureAttributeDescriptor) iterOther.next();
580
            if (!attr.equals(attrOther)) {
581
                return false;
582
            }
583
        }
584

    
585
        if (!StringUtils.equals(defaultGeometryAttributeName, other.defaultGeometryAttributeName)) {
586
            return false;
587
        }
588
        if (!StringUtils.equals(defaultTimeAttributeName, other.defaultTimeAttributeName)) {
589
            return false;
590
        }
591
        return true;
592

    
593
    }
594

    
595
    /**
596
     * Start of DynClass interface implementation READONLY
597
     */
598
    public DynField addDynField(String name) {
599
        throw new UnsupportedOperationException();
600
    }
601

    
602
    public DynField getDeclaredDynField(String name) {
603
        return (DynField) getAttributeDescriptor(name);
604
    }
605

    
606
    public DynField[] getDeclaredDynFields() {
607
        return (DynField[]) getAttributeDescriptors();
608
    }
609

    
610
    public String getDescription() {
611
        return this.description;
612
    }
613

    
614
    public DynField getDynField(String name) {
615
        return (DynField) getAttributeDescriptor(name);
616
    }
617

    
618
    public DynField[] getDynFields() {
619
        return (DynField[]) getAttributeDescriptors();
620
    }
621

    
622
    public String getName() {
623
        return this.id + "_" + internalID;
624
    }
625

    
626
    public void removeDynField(String name) {
627
        throw new UnsupportedOperationException();
628

    
629
    }
630

    
631
    public void addDynMethod(DynMethod dynMethod) {
632
        throw new UnsupportedOperationException();
633

    
634
    }
635

    
636
    public void extend(DynClass dynClass) {
637
        throw new UnsupportedOperationException();
638

    
639
    }
640

    
641
    public void extend(String dynClassName) {
642
        throw new UnsupportedOperationException();
643

    
644
    }
645

    
646
    public void extend(String namespace, String dynClassName) {
647
        throw new UnsupportedOperationException();
648

    
649
    }
650

    
651
    public DynMethod getDeclaredDynMethod(String name)
652
            throws DynMethodException {
653
        return null;
654
    }
655

    
656
    public DynMethod[] getDeclaredDynMethods() throws DynMethodException {
657
        return null;
658
    }
659

    
660
    public DynMethod getDynMethod(String name) throws DynMethodException {
661
        return null;
662
    }
663

    
664
    public DynMethod getDynMethod(int code) throws DynMethodException {
665
        return null;
666
    }
667

    
668
    public DynMethod[] getDynMethods() throws DynMethodException {
669
        return null;
670
    }
671

    
672
    public DynClass[] getSuperDynClasses() {
673
        return null;
674
    }
675

    
676
    public boolean isInstance(DynObject dynObject) {
677
        if (dynObject.getDynClass().getName() == getName()) {
678
            return true;
679
        }
680
        return false;
681
    }
682

    
683
    public DynObject newInstance() {
684

    
685
        throw new UnsupportedOperationException();
686
    }
687

    
688
    public void removeDynMethod(String name) {
689
        throw new UnsupportedOperationException();
690

    
691
    }
692

    
693
    public DynField addDynFieldChoice(String name, int type,
694
            Object defaultValue, DynObjectValueItem[] values,
695
            boolean mandatory, boolean persistent) {
696
        throw new UnsupportedOperationException();
697
    }
698

    
699
    public DynField addDynFieldRange(String name, int type,
700
            Object defaultValue, Object min, Object max, boolean mandatory,
701
            boolean persistent) {
702
        throw new UnsupportedOperationException();
703
    }
704

    
705
    public DynField addDynFieldSingle(String name, int type,
706
            Object defaultValue, boolean mandatory, boolean persistent) {
707
        throw new UnsupportedOperationException();
708
    }
709

    
710
    public void validate(DynObject object) throws DynObjectValidateException {
711
        //FIXME: not sure it's the correct code
712
        if (object instanceof Feature) {
713
            Feature fea = (Feature) object;
714
            if (fea.getType().equals(this)) {
715
                return;
716
            }
717
        }
718
        throw new DynObjectValidateException(this.id);
719
    }
720

    
721
    public DynField addDynFieldLong(String name) {
722
        throw new UnsupportedOperationException();
723
    }
724

    
725
    public DynField addDynFieldChoice(String name, int type,
726
            Object defaultValue, DynObjectValueItem[] values) {
727
        throw new UnsupportedOperationException();
728
    }
729

    
730
    public DynField addDynFieldRange(String name, int type,
731
            Object defaultValue, Object min, Object max) {
732
        throw new UnsupportedOperationException();
733
    }
734

    
735
    public DynField addDynFieldSingle(String name, int type, Object defaultValue) {
736
        throw new UnsupportedOperationException();
737
    }
738

    
739
    public DynField addDynFieldString(String name) {
740
        throw new UnsupportedOperationException();
741
    }
742

    
743
    public DynField addDynFieldInt(String name) {
744
        throw new UnsupportedOperationException();
745
    }
746

    
747
    public DynField addDynFieldDouble(String name) {
748
        throw new UnsupportedOperationException();
749
    }
750

    
751
    public DynField addDynFieldFloat(String name) {
752
        throw new UnsupportedOperationException();
753
    }
754

    
755
    public DynField addDynFieldBoolean(String name) {
756
        throw new UnsupportedOperationException();
757
    }
758

    
759
    public DynField addDynFieldList(String name) {
760
        throw new UnsupportedOperationException();
761
    }
762

    
763
    public DynField addDynFieldMap(String name) {
764
        throw new UnsupportedOperationException();
765
    }
766

    
767
    public DynField addDynFieldObject(String name) {
768
        throw new UnsupportedOperationException();
769
    }
770

    
771
    public DynField addDynFieldSet(String name) {
772
        throw new UnsupportedOperationException();
773
    }
774

    
775
    public DynField addDynFieldArray(String name) {
776
        throw new UnsupportedOperationException();
777
    }
778

    
779
    public DynField addDynFieldDate(String name) {
780
        throw new UnsupportedOperationException();
781
    }
782

    
783
    public void extend(DynStruct struct) {
784
        throw new UnsupportedOperationException();
785
    }
786

    
787
    public String getFullName() {
788
        // TODO: usar el DynClassName
789
        return this.id;
790
    }
791

    
792
    public String getNamespace() {
793
        return "DALFeature";
794
    }
795

    
796
    public DynStruct[] getSuperDynStructs() {
797
        return null;
798
    }
799

    
800
    public void setDescription(String description) {
801
        this.description = description;
802
    }
803

    
804
    public void setNamespace(String namespace) {
805
        throw new UnsupportedOperationException();
806
    }
807

    
808
    public DynField addDynFieldFile(String name) {
809
        throw new UnsupportedOperationException();
810
    }
811

    
812
    public DynField addDynFieldFolder(String name) {
813
        throw new UnsupportedOperationException();
814
    }
815

    
816
    public DynField addDynFieldURL(String name) {
817
        throw new UnsupportedOperationException();
818
    }
819

    
820
    public DynField addDynFieldURI(String name) {
821
        throw new UnsupportedOperationException();
822
    }
823

    
824
    public boolean isExtendable(DynStruct dynStruct) {
825
        return false;
826
    }
827

    
828
    public void extend(DynStruct[] structs) {
829
        // TODO Auto-generated method stub
830

    
831
    }
832

    
833
    public void remove(DynStruct superDynStruct) {
834
        // TODO Auto-generated method stub
835

    
836
    }
837

    
838
    public void removeAll(DynStruct[] superDynStruct) {
839
        // TODO Auto-generated method stub
840

    
841
    }
842

    
843
    public FeatureAttributeDescriptor getDefaultTimeAttribute() {
844
        if (this.defaultTimeAttributeIndex < 0) {
845
            return null;
846
        }
847
        return (FeatureAttributeDescriptor) super
848
                .get(this.defaultTimeAttributeIndex);
849
    }
850

    
851
    public void setDefaultTimeAttributeName(String name) {
852
        if (name == null || name.length() == 0) {
853
            this.defaultTimeAttributeIndex = -1;
854
            return;
855
        }
856
        DefaultFeatureAttributeDescriptor attr = (DefaultFeatureAttributeDescriptor) this.get(name);
857
        if (attr == null) {
858
            throw new IllegalArgumentException("Attribute '" + name + "' not found.");
859
        }
860
        if (attr.getIndex() < 0) {
861
            fixAll();
862
        }
863
        this.defaultTimeAttributeIndex = attr.getIndex();
864
    }
865

    
866
    protected void fixAll() {
867
        int i = 0;
868
        Iterator iter = super.iterator();
869
        DefaultFeatureAttributeDescriptor attr;
870

    
871
        while (iter.hasNext()) {
872
            attr = (DefaultFeatureAttributeDescriptor) iter.next();
873
            if (attr.getOder() < 1) {
874
                attr.setOrder(i * 10);
875
            }
876
            attr.setIndex(i++);
877
            attr.fixAll();
878
            if (attr.getEvaluator() != null) {
879
                this.hasEvaluators = true;
880
            }
881
            if (attr.getFeatureAttributeEmulator() != null) {
882
                this.hasEmulators = true;
883
                String[] x = attr.getFeatureAttributeEmulator().getRequiredFieldNames();
884
                if (!ArrayUtils.isEmpty(x)) {
885
                    this.requiredFields = true;
886
                }
887
            }
888
            switch (attr.getType()) {
889
                case DataTypes.GEOMETRY:
890
                    if (this.defaultGeometryAttributeName == null) {
891
                        this.defaultGeometryAttributeName = attr.getName();
892
                    }
893
                    break;
894
                case DataTypes.INSTANT:
895
                case DataTypes.INTERVAL:
896
                case DataTypes.DATE:
897
                    if (this.defaultTimeAttributeName == null && attr.isTime()) {
898
                        this.defaultTimeAttributeName = attr.getName();
899
                    }
900
                    break;
901
            }
902
        }
903
        if (this.defaultGeometryAttributeName != null) {
904
            this.defaultGeometryAttributeIndex = this.getIndex(this.defaultGeometryAttributeName);
905
        }
906
        if (this.defaultTimeAttributeName != null) {
907
            this.defaultTimeAttributeIndex = this.getIndex(this.defaultTimeAttributeName);
908
        }
909
        this.internalID = Long.toHexString(this.getCRC());
910

    
911
    }
912

    
913
    protected long getCRC() {
914
        StringBuffer buffer = new StringBuffer();
915
        for (int i = 0; i < this.size(); i++) {
916
            FeatureAttributeDescriptor x = this.getAttributeDescriptor(i);
917
            buffer.append(x.getName());
918
            buffer.append(x.getDataTypeName());
919
            buffer.append(x.getSize());
920
        }
921
        CRC32 crc = new CRC32();
922
        byte[] data = buffer.toString().getBytes();
923
        crc.update(data);
924
        return crc.getValue();
925
    }
926

    
927
    @Override
928
    public FeatureStore getStore() {
929
        if (this.storeRef == null) {
930
            return null;
931
        }
932
        return (FeatureStore) this.storeRef.get();
933
    }
934

    
935
    public void setStore(FeatureStore store) {
936
        if (store == null) {
937
            this.storeRef = null;
938
        } else {
939
            this.storeRef = new WeakReference(store);
940
        }
941
    }
942

    
943
    @Override
944
    public List<FeatureAttributeDescriptor> getFilteredAttributes(
945
            Predicate<FeatureAttributeDescriptor> filter,
946
            int max
947
    ) {
948
        List<FeatureAttributeDescriptor> attrs = new ArrayList<>();
949
        for (FeatureAttributeDescriptor attribute : this) {
950
            if (filter.test(attribute)) {
951
                attrs.add(attribute);
952
            }
953
        }
954
        return attrs;
955
    }
956
    
957
    @Override
958
    public List<FeatureAttributeDescriptor> getRecentUseds() {
959
        return RECENTS_USEDS.getAttributes(this);
960
    }
961
    
962
    @Override
963
    public void loadFromState(PersistentState state)
964
            throws PersistenceException {
965

    
966
//        FIXME: rules
967
        hasEvaluators = state.getBoolean("hasEvaluators");
968
        hasEmulators = state.getBoolean("hasEmulators");
969
        defaultGeometryAttributeName = state.getString("defaultGeometryAttributeName");
970
        defaultTimeAttributeName = state.getString("defaultTimeAttributeName");
971
        defaultGeometryAttributeIndex = state.getInt("defaultGeometryAttributeIndex");
972
        defaultTimeAttributeIndex = state.getInt("defaultTimeAttributeIndex");
973
        id = state.getString("id");
974
        hasOID = state.getBoolean("hasOID");
975
        allowAtomaticValues = state.getBoolean("allowAtomaticValues");
976

    
977
        requiredFields = state.getBoolean("requiredFields");
978
        internalID = state.getString("internalID");
979
        tags = (Tags) state.get("tags");
980
        if( tags == null ) {
981
            this.tags = new DefaultTags();
982
        }
983

    
984
        List<FeatureAttributeDescriptor> elements = state.getList("elements");
985
        for (FeatureAttributeDescriptor element : elements) {
986
            ((DefaultFeatureAttributeDescriptor) element).setFeatureType(this);
987
            super.add(element);
988
        }
989
        this.pk = null;
990
        this.fixAll();
991
    }
992

    
993
    @Override
994
    public void saveToState(PersistentState state) throws PersistenceException {
995

    
996
//        FIXME: rules
997
        state.set("hasEvaluators", hasEvaluators);
998
        state.set("hasEmulators", hasEmulators);
999
        state.set("defaultGeometryAttributeName", defaultGeometryAttributeName);
1000
        state.set("defaultTimeAttributeName", defaultTimeAttributeName);
1001
        state.set("defaultGeometryAttributeIndex", defaultGeometryAttributeIndex);
1002
        state.set("defaultTimeAttributeIndex", defaultTimeAttributeIndex);
1003
        state.set("id", id);
1004
        state.set("hasOID", hasOID);
1005
        state.set("allowAtomaticValues", allowAtomaticValues);
1006

    
1007
        state.set("requiredFields", requiredFields);
1008
        state.set("internalID", internalID);
1009

    
1010
        List<FeatureAttributeDescriptor> elements = new ArrayList<>();
1011
        elements.addAll(this);
1012
        state.set("elements", elements);
1013
        state.set("tags", tags);
1014

    
1015
    }
1016

    
1017
    private static final String FEATTYPE_PERSISTENCE_DEFINITION_NAME = "FeatureType";
1018

    
1019
    public static void registerPersistenceDefinition() {
1020
        PersistenceManager manager = ToolsLocator.getPersistenceManager();
1021

    
1022
        if (manager.getDefinition(FEATTYPE_PERSISTENCE_DEFINITION_NAME)
1023
                == null) {
1024
            DynStruct definition = manager.addDefinition(DefaultFeatureType.class,
1025
                    FEATTYPE_PERSISTENCE_DEFINITION_NAME,
1026
                    FEATTYPE_PERSISTENCE_DEFINITION_NAME
1027
                    + " persistent definition",
1028
                    null,
1029
                    null
1030
            );
1031
//            definition.addDynFieldObject("rules");
1032
            definition.addDynFieldBoolean("hasEvaluators");
1033
            definition.addDynFieldBoolean("hasEmulators");
1034
            definition.addDynFieldString("defaultGeometryAttributeName");
1035
            definition.addDynFieldString("defaultTimeAttributeName");
1036
            definition.addDynFieldInt("defaultGeometryAttributeIndex");
1037
            definition.addDynFieldInt("defaultTimeAttributeIndex");
1038
            definition.addDynFieldString("id");
1039
            definition.addDynFieldBoolean("hasOID");
1040
            definition.addDynFieldBoolean("allowAtomaticValues");
1041

    
1042
            definition.addDynFieldBoolean("requiredFields");
1043
            definition.addDynFieldString("internalID");
1044

    
1045
            definition.addDynFieldList("elements")
1046
                    .setClassOfItems(FeatureAttributeDescriptor.class);
1047

    
1048
            definition.addDynFieldObject("tags")
1049
                    .setClassOfValue(Tags.class);
1050
            
1051
        }
1052
    }
1053

    
1054
}