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

History | View | Annotate | Download (32.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.HashSet;
31
import java.util.Iterator;
32
import java.util.LinkedHashSet;
33
import java.util.List;
34
import java.util.Set;
35
import java.util.logging.Level;
36
import java.util.logging.Logger;
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

    
69
public class DefaultFeatureType
70
        extends ArrayList<FeatureAttributeDescriptor>
71
        implements
72
        FeatureType,
73
        Persistent,
74
        DynClass,
75
        DynStruct_v2,
76
        org.gvsig.tools.lang.Cloneable {
77

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

    
83
    private DefaultFeatureRules rules;
84
    protected boolean hasEvaluators;
85
    protected boolean hasEmulators;
86
    protected String defaultGeometryAttributeName;
87
    protected String defaultTimeAttributeName;
88
    protected int defaultGeometryAttributeIndex;
89
    protected int defaultTimeAttributeIndex;
90
    private String id;
91
    protected boolean hasOID;
92
    protected boolean allowAtomaticValues;
93
    protected FeatureAttributeDescriptor[] pk = null;
94
    protected String internalID = null;
95

    
96
    private List srsList = null;
97
    private WeakReference storeRef;
98
    private boolean requiredFields;
99

    
100
    private String description;
101
    private String label;
102
    private Tags tags;
103

    
104
    public DefaultFeatureType() {
105
        // Usado en la persistencia.
106
        this.internalID = Integer.toHexString((int) (Math.random() * 100000)).toUpperCase();
107
        this.id = id = "default";
108
        this.rules = new DefaultFeatureRules();
109
        this.hasEvaluators = false;
110
        this.hasEmulators = false;
111
        this.defaultGeometryAttributeName = null;
112
        this.defaultTimeAttributeName = null;
113
        this.defaultGeometryAttributeIndex = -1;
114
        this.defaultTimeAttributeIndex = -1;
115
        this.allowAtomaticValues = false;
116
        this.tags = new DefaultTags();
117
    }
118

    
119
    protected DefaultFeatureType(FeatureStore store, String id) {
120
        this();
121
        if (StringUtils.isEmpty(id)) {
122
            id = "default";
123
        }
124
        this.id = id;
125
        setStore(store);
126
    }
127

    
128
    protected DefaultFeatureType(FeatureStore store) {
129
        this(store, (String) null);
130
    }
131

    
132
    protected DefaultFeatureType(DefaultFeatureType other) {
133
        this(other.getStore(), (String) null);
134
        initialize(other, true);
135
    }
136

    
137
    protected DefaultFeatureType(DefaultFeatureType other,
138
            boolean copyAttributes) {
139
        this(other.getStore(), (String) null);
140
        initialize(other, copyAttributes);
141
    }
142

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

    
173
    protected void intitalizeAddAttibute(DefaultFeatureAttributeDescriptor attr) {
174
        super.add(attr.getCopy());
175
    }
176

    
177
    public String getId() {
178
        return this.id;
179
    }
180

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

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

    
205
    public FeatureAttributeDescriptor getAttributeDescriptor(int index) {
206
        return (FeatureAttributeDescriptor) super.get(index);
207
    }
208

    
209
    public FeatureType getCopy() {
210
        return new DefaultFeatureType(this);
211
    }
212

    
213
    public Object clone() {
214
        return this.getCopy();
215
    }
216

    
217
    public int getDefaultGeometryAttributeIndex() {
218
        return this.defaultGeometryAttributeIndex;
219
    }
220

    
221
    public String getDefaultGeometryAttributeName() {
222
        return this.defaultGeometryAttributeName;
223
    }
224

    
225
    public int getDefaultTimeAttributeIndex() {
226
        return this.defaultTimeAttributeIndex;
227
    }
228

    
229
    public String getDefaultTimeAttributeName() {
230
        return this.defaultTimeAttributeName;
231
    }
232

    
233
    public EditableFeatureType getEditable() {
234
        return new DefaultEditableFeatureType(this);
235
    }
236

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

    
249
    public FeatureRules getRules() {
250
        return this.rules;
251
    }
252

    
253
    public boolean hasEvaluators() {
254
        return this.hasEvaluators;
255
    }
256

    
257
    public boolean hasEmulators() {
258
        return this.hasEmulators;
259
    }
260

    
261
    public boolean hasRequiredFields() {
262
        return this.requiredFields;
263
    }
264

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

    
296
    public IProjection getDefaultSRS() {
297
        if (this.getDefaultGeometryAttributeIndex() < 0) {
298
            return null;
299
        }
300
        return this.getAttributeDescriptor(
301
                this.getDefaultGeometryAttributeIndex()).getSRS();
302
    }
303

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

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

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

    
323
    public FeatureType getSubtype() throws DataException {
324
        return new SubtypeFeatureType(this, null, null);
325
    }
326

    
327
    public boolean isSubtypeOf(FeatureType featureType) {
328
        return false;
329
    }
330

    
331
    @Override
332
    public List<FeatureAttributeDescriptor> toList() {
333
        return Collections.unmodifiableList(this);
334
    }
335

    
336
    @Override
337
    public Tags getTags() {
338
        return this.tags;
339
    }
340

    
341
    @Override
342
    public String getLabel() {
343
        return this.label;
344
    }
345

    
346
    @Override
347
    public void setLabel(String label) {
348
        this.label = label;
349
    }
350

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

    
356
    class SubtypeFeatureType extends DefaultFeatureType {
357

    
358
        /**
359
         *
360
         */
361
        private static final long serialVersionUID = 6913732960073922540L;
362
        WeakReference parent;
363

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

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

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

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

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

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

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

    
448
        public EditableFeatureType getEditable() {
449
            throw new UnsupportedOperationException();
450
        }
451
    }
452

    
453
    public class SubtypeFeatureTypeNameException extends DataException {
454

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

    
462
        public SubtypeFeatureTypeNameException(String name, String type) {
463
            super(MESSAGE_FORMAT, MESSAGE_KEY, serialVersionUID);
464
            setValue("name", name);
465
            setValue("type", type);
466
        }
467
    }
468

    
469
    public boolean hasOID() {
470
        return hasOID;
471
    }
472

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

    
489
    public Iterator<FeatureAttributeDescriptor> iterator() {
490
        return getIterator(super.iterator());
491
    }
492

    
493
    protected Iterator getIterator(Iterator iter) {
494
        return new DelegatedIterator(iter);
495
    }
496

    
497
    protected class DelegatedIterator implements Iterator {
498

    
499
        protected Iterator iterator;
500

    
501
        public DelegatedIterator(Iterator iter) {
502
            this.iterator = iter;
503
        }
504

    
505
        public boolean hasNext() {
506
            return iterator.hasNext();
507
        }
508

    
509
        public Object next() {
510
            return iterator.next();
511
        }
512

    
513
        public void remove() {
514
            throw new UnsupportedOperationException();
515
        }
516

    
517
    }
518

    
519
    public boolean allowAutomaticValues() {
520
        return this.allowAtomaticValues;
521
    }
522

    
523
    public FeatureAttributeDescriptor[] getAttributeDescriptors() {
524
        return (FeatureAttributeDescriptor[]) super
525
                .toArray(new FeatureAttributeDescriptor[super.size()]);
526
    }
527

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

    
548
    public FeatureAttributeDescriptor getDefaultGeometryAttribute() {
549
        if (this.defaultGeometryAttributeIndex < 0) {
550
            return null;
551
        }
552
        return (FeatureAttributeDescriptor) super
553
                .get(this.defaultGeometryAttributeIndex);
554
    }
555

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

    
582
        if (!StringUtils.equals(defaultGeometryAttributeName, other.defaultGeometryAttributeName)) {
583
            return false;
584
        }
585
        if (!StringUtils.equals(defaultTimeAttributeName, other.defaultTimeAttributeName)) {
586
            return false;
587
        }
588
        return true;
589

    
590
    }
591

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

    
599
    public DynField getDeclaredDynField(String name) {
600
        return (DynField) getAttributeDescriptor(name);
601
    }
602

    
603
    public DynField[] getDeclaredDynFields() {
604
        return (DynField[]) getAttributeDescriptors();
605
    }
606

    
607
    public String getDescription() {
608
        return this.description;
609
    }
610

    
611
    public DynField getDynField(String name) {
612
        return (DynField) getAttributeDescriptor(name);
613
    }
614

    
615
    public DynField[] getDynFields() {
616
        return (DynField[]) getAttributeDescriptors();
617
    }
618

    
619
    public String getName() {
620
        return this.id + "_" + internalID;
621
    }
622

    
623
    public void removeDynField(String name) {
624
        throw new UnsupportedOperationException();
625

    
626
    }
627

    
628
    public void addDynMethod(DynMethod dynMethod) {
629
        throw new UnsupportedOperationException();
630

    
631
    }
632

    
633
    public void extend(DynClass dynClass) {
634
        throw new UnsupportedOperationException();
635

    
636
    }
637

    
638
    public void extend(String dynClassName) {
639
        throw new UnsupportedOperationException();
640

    
641
    }
642

    
643
    public void extend(String namespace, String dynClassName) {
644
        throw new UnsupportedOperationException();
645

    
646
    }
647

    
648
    public DynMethod getDeclaredDynMethod(String name)
649
            throws DynMethodException {
650
        return null;
651
    }
652

    
653
    public DynMethod[] getDeclaredDynMethods() throws DynMethodException {
654
        return null;
655
    }
656

    
657
    public DynMethod getDynMethod(String name) throws DynMethodException {
658
        return null;
659
    }
660

    
661
    public DynMethod getDynMethod(int code) throws DynMethodException {
662
        return null;
663
    }
664

    
665
    public DynMethod[] getDynMethods() throws DynMethodException {
666
        return null;
667
    }
668

    
669
    public DynClass[] getSuperDynClasses() {
670
        return null;
671
    }
672

    
673
    public boolean isInstance(DynObject dynObject) {
674
        if (dynObject.getDynClass().getName() == getName()) {
675
            return true;
676
        }
677
        return false;
678
    }
679

    
680
    public DynObject newInstance() {
681

    
682
        throw new UnsupportedOperationException();
683
    }
684

    
685
    public void removeDynMethod(String name) {
686
        throw new UnsupportedOperationException();
687

    
688
    }
689

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

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

    
702
    public DynField addDynFieldSingle(String name, int type,
703
            Object defaultValue, boolean mandatory, boolean persistent) {
704
        throw new UnsupportedOperationException();
705
    }
706

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

    
718
    public DynField addDynFieldLong(String name) {
719
        throw new UnsupportedOperationException();
720
    }
721

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

    
727
    public DynField addDynFieldRange(String name, int type,
728
            Object defaultValue, Object min, Object max) {
729
        throw new UnsupportedOperationException();
730
    }
731

    
732
    public DynField addDynFieldSingle(String name, int type, Object defaultValue) {
733
        throw new UnsupportedOperationException();
734
    }
735

    
736
    public DynField addDynFieldString(String name) {
737
        throw new UnsupportedOperationException();
738
    }
739

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

    
744
    public DynField addDynFieldDouble(String name) {
745
        throw new UnsupportedOperationException();
746
    }
747

    
748
    public DynField addDynFieldFloat(String name) {
749
        throw new UnsupportedOperationException();
750
    }
751

    
752
    public DynField addDynFieldBoolean(String name) {
753
        throw new UnsupportedOperationException();
754
    }
755

    
756
    public DynField addDynFieldList(String name) {
757
        throw new UnsupportedOperationException();
758
    }
759

    
760
    public DynField addDynFieldMap(String name) {
761
        throw new UnsupportedOperationException();
762
    }
763

    
764
    public DynField addDynFieldObject(String name) {
765
        throw new UnsupportedOperationException();
766
    }
767

    
768
    public DynField addDynFieldSet(String name) {
769
        throw new UnsupportedOperationException();
770
    }
771

    
772
    public DynField addDynFieldArray(String name) {
773
        throw new UnsupportedOperationException();
774
    }
775

    
776
    public DynField addDynFieldDate(String name) {
777
        throw new UnsupportedOperationException();
778
    }
779

    
780
    public void extend(DynStruct struct) {
781
        throw new UnsupportedOperationException();
782
    }
783

    
784
    public String getFullName() {
785
        // TODO: usar el DynClassName
786
        return this.id;
787
    }
788

    
789
    public String getNamespace() {
790
        return "DALFeature";
791
    }
792

    
793
    public DynStruct[] getSuperDynStructs() {
794
        return null;
795
    }
796

    
797
    public void setDescription(String description) {
798
        this.description = description;
799
    }
800

    
801
    public void setNamespace(String namespace) {
802
        throw new UnsupportedOperationException();
803
    }
804

    
805
    public DynField addDynFieldFile(String name) {
806
        throw new UnsupportedOperationException();
807
    }
808

    
809
    public DynField addDynFieldFolder(String name) {
810
        throw new UnsupportedOperationException();
811
    }
812

    
813
    public DynField addDynFieldURL(String name) {
814
        throw new UnsupportedOperationException();
815
    }
816

    
817
    public DynField addDynFieldURI(String name) {
818
        throw new UnsupportedOperationException();
819
    }
820

    
821
    public boolean isExtendable(DynStruct dynStruct) {
822
        return false;
823
    }
824

    
825
    public void extend(DynStruct[] structs) {
826
        // TODO Auto-generated method stub
827

    
828
    }
829

    
830
    public void remove(DynStruct superDynStruct) {
831
        // TODO Auto-generated method stub
832

    
833
    }
834

    
835
    public void removeAll(DynStruct[] superDynStruct) {
836
        // TODO Auto-generated method stub
837

    
838
    }
839

    
840
    public FeatureAttributeDescriptor getDefaultTimeAttribute() {
841
        if (this.defaultTimeAttributeIndex < 0) {
842
            return null;
843
        }
844
        return (FeatureAttributeDescriptor) super
845
                .get(this.defaultTimeAttributeIndex);
846
    }
847

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

    
863
    protected void fixAll() {
864
        int i = 0;
865
        Iterator iter = super.iterator();
866
        DefaultFeatureAttributeDescriptor attr;
867

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

    
908
    }
909

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

    
924
    @Override
925
    public FeatureStore getStore() {
926
        if (this.storeRef == null) {
927
            return null;
928
        }
929
        return (FeatureStore) this.storeRef.get();
930
    }
931

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

    
940
    @Override
941
    public void loadFromState(PersistentState state)
942
            throws PersistenceException {
943

    
944
//        FIXME: rules
945
        hasEvaluators = state.getBoolean("hasEvaluators");
946
        hasEmulators = state.getBoolean("hasEmulators");
947
        defaultGeometryAttributeName = state.getString("defaultGeometryAttributeName");
948
        defaultTimeAttributeName = state.getString("defaultTimeAttributeName");
949
        defaultGeometryAttributeIndex = state.getInt("defaultGeometryAttributeIndex");
950
        defaultTimeAttributeIndex = state.getInt("defaultTimeAttributeIndex");
951
        id = state.getString("id");
952
        hasOID = state.getBoolean("hasOID");
953
        allowAtomaticValues = state.getBoolean("allowAtomaticValues");
954

    
955
        requiredFields = state.getBoolean("requiredFields");
956
        internalID = state.getString("internalID");
957

    
958
        List<FeatureAttributeDescriptor> elements = state.getList("elements");
959
        for (FeatureAttributeDescriptor element : elements) {
960
            ((DefaultFeatureAttributeDescriptor) element).setFeatureType(this);
961
            super.add(element);
962
        }
963
        this.pk = null;
964
        this.fixAll();
965
    }
966

    
967
    @Override
968
    public void saveToState(PersistentState state) throws PersistenceException {
969

    
970
//        FIXME: rules
971
        state.set("hasEvaluators", hasEvaluators);
972
        state.set("hasEmulators", hasEmulators);
973
        state.set("defaultGeometryAttributeName", defaultGeometryAttributeName);
974
        state.set("defaultTimeAttributeName", defaultTimeAttributeName);
975
        state.set("defaultGeometryAttributeIndex", defaultGeometryAttributeIndex);
976
        state.set("defaultTimeAttributeIndex", defaultTimeAttributeIndex);
977
        state.set("id", id);
978
        state.set("hasOID", hasOID);
979
        state.set("allowAtomaticValues", allowAtomaticValues);
980

    
981
        state.set("requiredFields", requiredFields);
982
        state.set("internalID", internalID);
983

    
984
        List<FeatureAttributeDescriptor> elements = new ArrayList<>();
985
        elements.addAll(this);
986
        state.set("elements", elements);
987

    
988
    }
989

    
990
    private static final String FEATTYPE_PERSISTENCE_DEFINITION_NAME = "FeatureType";
991

    
992
    public static void registerPersistenceDefinition() {
993
        PersistenceManager manager = ToolsLocator.getPersistenceManager();
994

    
995
        if (manager.getDefinition(FEATTYPE_PERSISTENCE_DEFINITION_NAME)
996
                == null) {
997
            DynStruct definition = manager.addDefinition(DefaultFeatureType.class,
998
                    FEATTYPE_PERSISTENCE_DEFINITION_NAME,
999
                    FEATTYPE_PERSISTENCE_DEFINITION_NAME
1000
                    + " persistent definition",
1001
                    null,
1002
                    null
1003
            );
1004
//            definition.addDynFieldObject("rules");
1005
            definition.addDynFieldBoolean("hasEvaluators");
1006
            definition.addDynFieldBoolean("hasEmulators");
1007
            definition.addDynFieldString("defaultGeometryAttributeName");
1008
            definition.addDynFieldString("defaultTimeAttributeName");
1009
            definition.addDynFieldInt("defaultGeometryAttributeIndex");
1010
            definition.addDynFieldInt("defaultTimeAttributeIndex");
1011
            definition.addDynFieldString("id");
1012
            definition.addDynFieldBoolean("hasOID");
1013
            definition.addDynFieldBoolean("allowAtomaticValues");
1014

    
1015
            definition.addDynFieldBoolean("requiredFields");
1016
            definition.addDynFieldString("internalID");
1017

    
1018
            definition.addDynFieldList("elements")
1019
                    .setClassOfItems(FeatureAttributeDescriptor.class);
1020
        }
1021
    }
1022

    
1023
}