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

History | View | Annotate | Download (31.2 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.zip.CRC32;
36
import org.apache.commons.lang3.ArrayUtils;
37
import org.apache.commons.lang3.StringUtils;
38

    
39
import org.cresques.cts.IProjection;
40

    
41
import org.gvsig.fmap.dal.DataTypes;
42
import org.gvsig.fmap.dal.exception.DataException;
43
import org.gvsig.fmap.dal.feature.EditableFeatureType;
44
import org.gvsig.fmap.dal.feature.Feature;
45
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
46
import org.gvsig.fmap.dal.feature.FeatureAttributeEmulator;
47
import org.gvsig.fmap.dal.feature.FeatureRules;
48
import org.gvsig.fmap.dal.feature.FeatureStore;
49
import org.gvsig.fmap.dal.feature.FeatureType;
50
import org.gvsig.tools.ToolsLocator;
51
import org.gvsig.tools.dynobject.DynClass;
52
import org.gvsig.tools.dynobject.DynField;
53
import org.gvsig.tools.dynobject.DynMethod;
54
import org.gvsig.tools.dynobject.DynObject;
55
import org.gvsig.tools.dynobject.DynObjectValueItem;
56
import org.gvsig.tools.dynobject.DynStruct;
57
import org.gvsig.tools.dynobject.exception.DynMethodException;
58
import org.gvsig.tools.dynobject.exception.DynObjectValidateException;
59
import org.gvsig.tools.persistence.PersistenceManager;
60
import org.gvsig.tools.persistence.Persistent;
61
import org.gvsig.tools.persistence.PersistentState;
62
import org.gvsig.tools.persistence.exception.PersistenceException;
63

    
64
public class DefaultFeatureType 
65
        extends ArrayList<FeatureAttributeDescriptor> 
66
        implements 
67
            FeatureType,
68
            Persistent,
69
            DynClass, 
70
            org.gvsig.tools.lang.Cloneable 
71
    {
72

    
73
        /**
74
         *
75
         */
76
        private static final long serialVersionUID = -7988721447349282215L;
77

    
78
        private DefaultFeatureRules rules;
79
        protected boolean hasEvaluators;
80
        protected boolean hasEmulators;
81
        protected String defaultGeometryAttributeName;
82
        protected String defaultTimeAttributeName;
83
        protected int defaultGeometryAttributeIndex;
84
        protected int defaultTimeAttributeIndex;
85
        private String id;
86
        protected boolean hasOID;
87
        protected boolean allowAtomaticValues;
88
        protected FeatureAttributeDescriptor[] pk = null;
89
        protected String internalID = null;
90

    
91
        private List srsList = null;
92
        private WeakReference storeRef;
93
        private boolean requiredFields;
94

    
95
        public DefaultFeatureType() {
96
            // Usado en la persistencia.
97
            this.internalID = Integer.toHexString((int) (Math.random() * 100000)).toUpperCase();
98
            this.id = id = "default";
99
            this.rules = new DefaultFeatureRules();
100
            this.hasEvaluators = false;
101
            this.hasEmulators = false;
102
            this.defaultGeometryAttributeName = null;
103
            this.defaultTimeAttributeName = null;
104
            this.defaultGeometryAttributeIndex = -1;
105
            this.defaultTimeAttributeIndex = -1;
106
            this.allowAtomaticValues = false;
107
        }
108
        
109
        protected DefaultFeatureType(FeatureStore store, String id) {
110
            this();
111
            if (StringUtils.isEmpty(id)) {
112
                id = "default";
113
            }
114
            this.id = id;
115
            setStore(store);
116
        }
117

    
118
        protected DefaultFeatureType(FeatureStore store) {
119
            this(store, (String)null);
120
        }
121

    
122
        protected DefaultFeatureType(DefaultFeatureType other) {
123
            this(other.getStore(), (String)null);
124
            initialize(other, true);
125
        }
126

    
127
        protected DefaultFeatureType(DefaultFeatureType other,
128
                        boolean copyAttributes) {
129
            this(other.getStore(), (String)null);
130
            initialize(other, copyAttributes);
131
        }
132

    
133
        protected void initialize(DefaultFeatureType other, boolean copyAttributes) {
134
                this.id = other.getId();
135
                if (copyAttributes) {
136
                    Iterator iter = other.iterator();
137
                    DefaultFeatureAttributeDescriptor attr;
138
                    while (iter.hasNext()) {
139
                            attr = (DefaultFeatureAttributeDescriptor) iter.next();
140
                            this.intitalizeAddAttibute(attr);
141
                    }
142
                    if( other.pk!=null ) {
143
                        this.pk = new FeatureAttributeDescriptor[other.pk.length];
144
                        for( int i=0; i<other.pk.length; i++ ) {
145
                            this.pk[i] = other.pk[i].getCopy();
146
                        }
147
                    }
148
                }
149
                this.defaultGeometryAttributeName = other.defaultGeometryAttributeName;
150
                this.defaultTimeAttributeName = other.defaultTimeAttributeName;
151
                this.hasEvaluators = other.hasEvaluators;
152
                this.hasEmulators = other.hasEmulators;
153
                this.rules = (DefaultFeatureRules) other.rules.getCopy();
154
                this.defaultGeometryAttributeIndex = other.defaultGeometryAttributeIndex;
155
                this.defaultTimeAttributeIndex = other.defaultTimeAttributeIndex;
156
                this.hasOID = other.hasOID;
157
                this.id = other.id; // XXX ???? copiar o no esto????
158
                this.internalID = other.internalID;
159
        }
160

    
161
        protected void intitalizeAddAttibute(DefaultFeatureAttributeDescriptor attr) {
162
                super.add(attr.getCopy());
163
        }
164

    
165
        public String getId() {
166
                return this.id;
167
        }
168

    
169
        public Object get(String name) {
170
                FeatureAttributeDescriptor attr;
171
                Iterator iter = this.iterator();
172
                while (iter.hasNext()) {
173
                        attr = (FeatureAttributeDescriptor) iter.next();
174
                        if (attr.getName().equalsIgnoreCase(name)) {
175
                                return attr;
176
                        }
177
                }
178
                return null;
179
        }
180

    
181
        public FeatureAttributeDescriptor getAttributeDescriptor(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(int index) {
194
                return (FeatureAttributeDescriptor) super.get(index);
195
        }
196

    
197
        public FeatureType getCopy() {
198
                return new DefaultFeatureType(this);
199
        }
200

    
201
        public Object clone() {
202
            return this.getCopy();
203
        }
204

    
205
        public int getDefaultGeometryAttributeIndex() {
206
                return this.defaultGeometryAttributeIndex;
207
        }
208

    
209
        public String getDefaultGeometryAttributeName() {
210
                return this.defaultGeometryAttributeName;
211
        }
212

    
213
        public int getDefaultTimeAttributeIndex() {
214
                return this.defaultTimeAttributeIndex;
215
        }
216

    
217
        public String getDefaultTimeAttributeName() {
218
                return this.defaultTimeAttributeName;
219
        }
220

    
221
        public EditableFeatureType getEditable() {
222
                return new DefaultEditableFeatureType(this);
223
        }
224

    
225
        public int getIndex(String name) {
226
                FeatureAttributeDescriptor attr;
227
                Iterator iter = this.iterator();
228
                while (iter.hasNext()) {
229
                        attr = (FeatureAttributeDescriptor) iter.next();
230
                        if (attr.getName().equalsIgnoreCase(name)) {
231
                                return attr.getIndex();
232
                        }
233
                }
234
                return -1;
235
        }
236

    
237
        public FeatureRules getRules() {
238
                return this.rules;
239
        }
240

    
241
        public boolean hasEvaluators() {
242
                return this.hasEvaluators;
243
        }
244

    
245
        public boolean hasEmulators() {
246
                return this.hasEmulators;
247
        }
248
        
249
        public boolean hasRequiredFields() {
250
            return this.requiredFields;
251
        }
252

    
253
        public List getSRSs() {
254
                if (this.srsList == null) {
255
                        ArrayList tmp = new ArrayList();
256
                        Iterator iter = iterator();
257
                        Iterator tmpIter;
258
                        boolean allreadyHave;
259
                        IProjection tmpSRS;
260
                        FeatureAttributeDescriptor attr;
261
                        while (iter.hasNext()){
262
                                attr = (FeatureAttributeDescriptor) iter.next();
263
                                if (attr.getDataType().getType() == DataTypes.GEOMETRY
264
                                                && attr.getSRS() != null) {
265
                                        allreadyHave = false;
266
                                        tmpIter = tmp.iterator();
267
                                        while (tmpIter.hasNext()) {
268
                                                tmpSRS = (IProjection) tmpIter.next();
269
                                                if (tmpSRS.getAbrev().equals(attr.getSRS().getAbrev())) {
270
                                                        allreadyHave = true;
271
                                                        break;
272
                                                }
273
                                        }
274
                                        if (!allreadyHave) {
275
                                                tmp.add(attr.getSRS());
276
                                        }
277
                                }
278
                        }
279
                        this.srsList = Collections.unmodifiableList(tmp);
280
                }
281
                return this.srsList;
282
        }
283

    
284
        public IProjection getDefaultSRS() {
285
                if (this.getDefaultGeometryAttributeIndex() < 0) {
286
                        return null;
287
                }
288
                return this.getAttributeDescriptor(
289
                                this.getDefaultGeometryAttributeIndex()).getSRS();
290
        }
291

    
292
        public void validateFeature(Feature feature, int mode) throws DataException {
293
            DefaultFeatureRules rules = (DefaultFeatureRules) this.getRules();
294
            rules.validate(feature,mode);
295
        }
296

    
297
        public FeatureType getSubtype(String[] names) throws DataException {
298
                if( names==null || names.length <1) {
299
                    return (FeatureType) this.clone();
300
                }
301
                return new SubtypeFeatureType(this, names, null);
302
        }
303

    
304
        public FeatureType getSubtype(String[] names, String[] constantsNames) throws DataException {
305
        if( ArrayUtils.isEmpty(names) && ArrayUtils.isEmpty(constantsNames) ) {
306
            return (FeatureType) this.clone();
307
        }
308
                return new SubtypeFeatureType(this, names,constantsNames);
309
        }
310

    
311
        public FeatureType getSubtype() throws DataException {
312
                return new SubtypeFeatureType(this, null,null);
313
        }
314

    
315
        public boolean isSubtypeOf(FeatureType featureType) {
316
                return false;
317
        }
318

    
319
    @Override
320
    public List<FeatureAttributeDescriptor> toList() {
321
        return Collections.unmodifiableList(this);
322
    }
323

    
324
        class SubtypeFeatureType extends DefaultFeatureType {
325
                /**
326
                 *
327
                 */
328
                private static final long serialVersionUID = 6913732960073922540L;
329
                WeakReference parent;
330

    
331
                SubtypeFeatureType(DefaultFeatureType parent, String[] names, String[] constantsNames)
332
                        throws DataException {
333
                    super(parent, false);
334
                    DefaultFeatureAttributeDescriptor attrcopy;
335
                    Set<String> attrnames = new LinkedHashSet<>();
336
                    Set<String> requiredAttrnames = new HashSet<>();
337
                    
338
                    if ( ArrayUtils.isEmpty(names) ) {
339
                        for (FeatureAttributeDescriptor attrdesc : parent) {
340
                            attrnames.add(attrdesc.getName());
341
                        }
342
                    } else {
343
                        attrnames.addAll(Arrays.asList(names));
344
                        requiredAttrnames.addAll(Arrays.asList(names));
345
                    }
346
                    // Add required fields for emulated fields
347
                    if ( parent.hasEmulators ) {
348
                        for (FeatureAttributeDescriptor attrdesc : parent) {
349
                            FeatureAttributeEmulator emulator = attrdesc.getFeatureAttributeEmulator();
350
                            if ( emulator != null ) {
351
                                String ss[] = emulator.getRequiredFieldNames();
352
                                if ( ss != null ) {
353
                                    attrnames.addAll(Arrays.asList(ss));
354
                                    requiredAttrnames.addAll(Arrays.asList(ss));
355
                                }
356
                            }
357
                        }
358
                    }
359
                    // Add missing pk fiels
360
                    if ( !parent.hasOID() ) {
361
                        for (FeatureAttributeDescriptor attrdesc : parent) {
362
                            if ( attrdesc.isPrimaryKey() ) {
363
                                attrnames.add(attrdesc.getName());
364
                                requiredAttrnames.add(attrdesc.getName());
365
                            }
366
                        }
367
                    }
368
                        
369
                    // Copy attributes
370
                    int i = 0;
371
                    for (String name : attrnames) {
372
                        DefaultFeatureAttributeDescriptor attr = (DefaultFeatureAttributeDescriptor) parent.get(name);
373
                        if ( attr == null ) {
374
                            throw new SubtypeFeatureTypeNameException(name, parent.getId());
375
                        }
376
                        attrcopy = new DefaultFeatureAttributeDescriptor(attr);
377
                        this.add(attrcopy);
378
                        attrcopy.index = i++;
379
                    }
380
                    
381
                    // Set the consttants attributes.
382
                    if ( !ArrayUtils.isEmpty(constantsNames) ) {
383
                        for (String name : constantsNames) {
384
                            if ( !requiredAttrnames.contains(name) ) { 
385
                                DefaultFeatureAttributeDescriptor attr = (DefaultFeatureAttributeDescriptor) this.get(name);
386
                                attr.setConstantValue(true);
387
                            }
388
                        }
389
                    }
390

    
391
                    this.defaultGeometryAttributeIndex = this.getIndex(this.defaultGeometryAttributeName);
392
                    if ( this.defaultGeometryAttributeIndex < 0 ) {
393
                        this.defaultGeometryAttributeName = null;
394
                    }
395
                    this.defaultTimeAttributeIndex = this.getIndex(this.defaultTimeAttributeName);
396
                    if ( this.defaultTimeAttributeIndex < 0 ) {
397
                        this.defaultTimeAttributeName = null;
398
                    }
399
                    this.parent = new WeakReference(parent);
400
                }
401

    
402
                public FeatureType getSubtype(String[] names) throws DataException {
403
                        return new SubtypeFeatureType((DefaultFeatureType) this.parent
404
                                        .get(), names, null);
405
                }
406

    
407
                public boolean isSubtypeOf(FeatureType featureType) {
408
                        if (featureType == null) {
409
                                return false;
410
                        }
411
                        FeatureType parent = (FeatureType) this.parent.get();
412
                        return featureType.equals(parent);
413
                }
414

    
415
                public EditableFeatureType getEditable() {
416
                        throw new UnsupportedOperationException();
417
                }
418
        }
419

    
420
        public class SubtypeFeatureTypeNameException extends DataException {
421

    
422
                /**
423
                 *
424
                 */
425
                private static final long serialVersionUID = -4414242486723260101L;
426
                private final static String MESSAGE_FORMAT = "Attribute name '%(name)' not found in type (%(type)).";
427
                private final static String MESSAGE_KEY = "_SubtypeFeatureTypeNameException";
428

    
429
                public SubtypeFeatureTypeNameException(String name, String type) {
430
                        super(MESSAGE_FORMAT, MESSAGE_KEY, serialVersionUID);
431
                        setValue("name", name);
432
                        setValue("type", type);
433
                }
434
        }
435

    
436
        public boolean hasOID() {
437
                return hasOID;
438
        }
439
        public String toString(){
440
                StringBuffer s = new StringBuffer();
441
                s.append(this.getId());
442
                s.append(":[");
443
                String attName;
444
                for (int i = 0; i < size(); i++) {
445
                        attName =((FeatureAttributeDescriptor)get(i)).getName().toString();
446
                        s.append(attName);
447
                        if (i < size() - 1) {
448
                                s.append(',');
449
                        }
450
                }
451
                s.append(']');
452
                return s.toString();
453
        }
454

    
455
        public Iterator<FeatureAttributeDescriptor> iterator() {
456
                return getIterator(super.iterator());
457
        }
458

    
459
        protected Iterator getIterator(Iterator iter) {
460
                return new DelegatedIterator(iter);
461
        }
462

    
463
        protected class DelegatedIterator implements Iterator {
464

    
465
                protected Iterator iterator;
466

    
467
                public DelegatedIterator(Iterator iter) {
468
                        this.iterator = iter;
469
                }
470

    
471
                public boolean hasNext() {
472
                        return iterator.hasNext();
473
                }
474

    
475
                public Object next() {
476
                        return iterator.next();
477
                }
478

    
479
                public void remove() {
480
                        throw new UnsupportedOperationException();
481
                }
482

    
483
        }
484

    
485
        public boolean allowAutomaticValues() {
486
                return this.allowAtomaticValues;
487
        }
488

    
489
        public FeatureAttributeDescriptor[] getAttributeDescriptors() {
490
                return (FeatureAttributeDescriptor[]) super
491
                                .toArray(new FeatureAttributeDescriptor[super.size()]);
492
        }
493

    
494
        public FeatureAttributeDescriptor[] getPrimaryKey() {
495
                if (pk == null) {
496
                        List pks = new ArrayList();
497
                        Iterator iter = super.iterator();
498
                        FeatureAttributeDescriptor attr;
499
                        while (iter.hasNext()){
500
                                attr = (FeatureAttributeDescriptor) iter.next();
501
                                if (attr.isPrimaryKey()){
502
                                        pks.add(attr);
503
                                }
504
                        }
505
            if( pks.isEmpty() ) {
506
                pk = new FeatureAttributeDescriptor[0];
507
            } else {
508
                pk = (FeatureAttributeDescriptor[])pks.toArray(new FeatureAttributeDescriptor[pks.size()]);
509
            }
510
                }
511
                return pk;
512
        }
513

    
514
        public FeatureAttributeDescriptor getDefaultGeometryAttribute() {
515
                if (this.defaultGeometryAttributeIndex < 0) {
516
                        return null;
517
                }
518
                return (FeatureAttributeDescriptor) super
519
                                .get(this.defaultGeometryAttributeIndex);
520
        }
521

    
522

    
523

    
524
        public boolean equals(Object o) {
525
            if (this == o) {
526
                    return true;
527
            }
528
            if (!(o instanceof DefaultFeatureType)) {
529
                    return false;
530
            }
531
            DefaultFeatureType other = (DefaultFeatureType) o;
532
            if (!this.id.equals(other.id)) {
533
                    return false;
534
            }
535
            if (this.size() != other.size()) {
536
                    return false;
537
            }
538
            FeatureAttributeDescriptor attr,attrOther;
539
            Iterator iter,iterOther;
540
            iter = this.iterator();
541
            iterOther = other.iterator();
542
            while (iter.hasNext()) {
543
                    attr = (FeatureAttributeDescriptor) iter.next();
544
                    attrOther = (FeatureAttributeDescriptor) iterOther.next();
545
                    if (!attr.equals(attrOther)) {
546
                            return false;
547
                    }
548
            }
549

    
550
            if( !StringUtils.equals(defaultGeometryAttributeName, other.defaultGeometryAttributeName)) {
551
                return false;
552
            }
553
            if( !StringUtils.equals(defaultTimeAttributeName, other.defaultTimeAttributeName)) {
554
                return false;
555
            }
556
            return true;
557

    
558
        }
559

    
560
        /**
561
         * Start of DynClass interface implementation
562
         * READONLY
563
         */
564

    
565
        public DynField addDynField(String name) {
566
                throw new UnsupportedOperationException();
567
        }
568

    
569
        public DynField getDeclaredDynField(String name) {
570
                return (DynField) getAttributeDescriptor(name);
571
        }
572

    
573
        public DynField[] getDeclaredDynFields() {
574
                return (DynField[]) getAttributeDescriptors();
575
        }
576

    
577
        public String getDescription() {
578
            return null;
579
        }
580

    
581
        public DynField getDynField(String name) {
582
                return (DynField) getAttributeDescriptor(name);
583
        }
584

    
585
        public DynField[] getDynFields() {
586
                return (DynField[]) getAttributeDescriptors();
587
        }
588

    
589
        public String getName() {
590
                return this.id + "_" + internalID;
591
        }
592

    
593
        public void removeDynField(String name) {
594
                throw new UnsupportedOperationException();
595

    
596
        }
597

    
598
        public void addDynMethod(DynMethod dynMethod) {
599
                throw new UnsupportedOperationException();
600

    
601
        }
602

    
603
        public void extend(DynClass dynClass) {
604
                throw new UnsupportedOperationException();
605

    
606
        }
607

    
608
        public void extend(String dynClassName) {
609
                throw new UnsupportedOperationException();
610

    
611
        }
612

    
613
        public void extend(String namespace, String dynClassName) {
614
                throw new UnsupportedOperationException();
615

    
616
        }
617

    
618
        public DynMethod getDeclaredDynMethod(String name)
619
                        throws DynMethodException {
620
                return null;
621
        }
622

    
623
        public DynMethod[] getDeclaredDynMethods() throws DynMethodException {
624
                return null;
625
        }
626

    
627
        public DynMethod getDynMethod(String name) throws DynMethodException {
628
                return null;
629
        }
630

    
631
        public DynMethod getDynMethod(int code) throws DynMethodException {
632
                return null;
633
        }
634

    
635
        public DynMethod[] getDynMethods() throws DynMethodException {
636
                return null;
637
        }
638

    
639
        public DynClass[] getSuperDynClasses() {
640
                return null;
641
        }
642

    
643
        public boolean isInstance(DynObject dynObject) {
644
                if (dynObject.getDynClass().getName() == getName()) {
645
                        return true;
646
                }
647
                return false;
648
        }
649

    
650
        public DynObject newInstance() {
651

    
652
                throw new UnsupportedOperationException();
653
        }
654

    
655
        public void removeDynMethod(String name) {
656
                throw new UnsupportedOperationException();
657

    
658
        }
659

    
660
        public DynField addDynFieldChoice(String name, int type,
661
                        Object defaultValue, DynObjectValueItem[] values,
662
                        boolean mandatory, boolean persistent) {
663
                throw new UnsupportedOperationException();
664
        }
665

    
666
        public DynField addDynFieldRange(String name, int type,
667
                        Object defaultValue, Object min, Object max, boolean mandatory,
668
                        boolean persistent) {
669
                throw new UnsupportedOperationException();
670
        }
671

    
672
        public DynField addDynFieldSingle(String name, int type,
673
                        Object defaultValue, boolean mandatory, boolean persistent) {
674
                throw new UnsupportedOperationException();
675
        }
676

    
677
        public void validate(DynObject object) throws DynObjectValidateException {
678
                //FIXME: not sure it's the correct code
679
                if (object instanceof Feature) {
680
                        Feature fea = (Feature) object;
681
                        if (fea.getType().equals(this)) {
682
                                return;
683
                        }
684
                }
685
                throw new DynObjectValidateException(this.id);
686
        }
687

    
688
        public DynField addDynFieldLong(String name) {
689
                throw new UnsupportedOperationException();
690
        }
691

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

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

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

    
706
        public DynField addDynFieldString(String name) {
707
                throw new UnsupportedOperationException();
708
        }
709

    
710
        public DynField addDynFieldInt(String name) {
711
                throw new UnsupportedOperationException();
712
        }
713

    
714
        public DynField addDynFieldDouble(String name) {
715
                throw new UnsupportedOperationException();
716
        }
717

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

    
722
        public DynField addDynFieldBoolean(String name) {
723
                throw new UnsupportedOperationException();
724
        }
725

    
726
        public DynField addDynFieldList(String name) {
727
                throw new UnsupportedOperationException();
728
        }
729

    
730
        public DynField addDynFieldMap(String name) {
731
                throw new UnsupportedOperationException();
732
        }
733

    
734
        public DynField addDynFieldObject(String name) {
735
                throw new UnsupportedOperationException();
736
        }
737

    
738
        public DynField addDynFieldSet(String name) {
739
                throw new UnsupportedOperationException();
740
        }
741

    
742
        public DynField addDynFieldArray(String name) {
743
                throw new UnsupportedOperationException();
744
        }
745

    
746
        public DynField addDynFieldDate(String name) {
747
                throw new UnsupportedOperationException();
748
        }
749

    
750
        public void extend(DynStruct struct) {
751
                throw new UnsupportedOperationException();
752
        }
753

    
754
        public String getFullName() {
755
        // TODO: usar el DynClassName
756
                return this.id;
757
        }
758

    
759
        public String getNamespace() {
760
                return "DALFeature";
761
        }
762

    
763
        public DynStruct[] getSuperDynStructs() {
764
                return null;
765
        }
766

    
767
        public void setDescription(String description) {
768
                throw new UnsupportedOperationException();
769
        }
770

    
771
        public void setNamespace(String namespace) {
772
                throw new UnsupportedOperationException();
773
        }
774

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

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

    
783
        public DynField addDynFieldURL(String name) {
784
                throw new UnsupportedOperationException();
785
        }
786

    
787
        public DynField addDynFieldURI(String name) {
788
                throw new UnsupportedOperationException();
789
        }
790

    
791
    public boolean isExtendable(DynStruct dynStruct) {
792
        return false;
793
    }
794

    
795
        public void extend(DynStruct[] structs) {
796
                // TODO Auto-generated method stub
797

    
798
        }
799

    
800
        public void remove(DynStruct superDynStruct) {
801
                // TODO Auto-generated method stub
802

    
803
        }
804

    
805
        public void removeAll(DynStruct[] superDynStruct) {
806
                // TODO Auto-generated method stub
807

    
808
        }
809

    
810
        public FeatureAttributeDescriptor getDefaultTimeAttribute() {
811
                if (this.defaultTimeAttributeIndex < 0) {
812
                        return null;
813
                }
814
                return (FeatureAttributeDescriptor) super
815
                                .get(this.defaultTimeAttributeIndex);
816
        }
817

    
818
    public void setDefaultTimeAttributeName(String name) {
819
        if (name == null || name.length() == 0) {
820
            this.defaultTimeAttributeIndex = -1;
821
            return;
822
        }
823
        DefaultFeatureAttributeDescriptor attr = (DefaultFeatureAttributeDescriptor) this.get(name);
824
        if (attr == null) {
825
            throw new IllegalArgumentException("Attribute '" + name + "' not found.");
826
        }
827
        if( attr.getIndex()<0 ) {
828
            fixAll();
829
        }
830
        this.defaultTimeAttributeIndex = attr.getIndex();
831
    }
832
    
833
    protected void fixAll() {
834
        int i = 0;
835
        Iterator iter = super.iterator();
836
        DefaultFeatureAttributeDescriptor attr;
837

    
838
        while (iter.hasNext()) {
839
            attr = (DefaultFeatureAttributeDescriptor) iter.next();
840
            attr.setIndex(i++);
841
            attr.fixAll();
842
            if (attr.getEvaluator() != null) {
843
                this.hasEvaluators = true;
844
            }
845
            if (attr.getFeatureAttributeEmulator() != null) {
846
                this.hasEmulators = true;
847
                String[] x = attr.getFeatureAttributeEmulator().getRequiredFieldNames();
848
                if( !ArrayUtils.isEmpty(x) ) {
849
                    this.requiredFields = true;
850
                }
851
            }
852
            switch(attr.getType()) {
853
                case DataTypes.GEOMETRY:
854
                    if (this.defaultGeometryAttributeName == null ) {
855
                        this.defaultGeometryAttributeName = attr.getName();
856
                    }
857
                    break;
858
                case DataTypes.INSTANT:
859
                case DataTypes.INTERVAL:
860
                case DataTypes.DATE:
861
                    if (this.defaultTimeAttributeName == null && attr.isTime() ) {
862
                        this.defaultTimeAttributeName = attr.getName();
863
                    }
864
                    break;
865
            }
866
        }
867
        if (this.defaultGeometryAttributeName != null) {
868
            this.defaultGeometryAttributeIndex = this.getIndex(this.defaultGeometryAttributeName);
869
        }
870
        if (this.defaultTimeAttributeName != null) {
871
            this.defaultTimeAttributeIndex = this.getIndex(this.defaultTimeAttributeName);
872
        }
873
        this.internalID = Long.toHexString(this.getCRC());
874
        
875
    }
876
    
877
    protected long getCRC() {
878
        StringBuffer buffer = new StringBuffer();
879
        for (int i = 0; i < this.size(); i++) {
880
            FeatureAttributeDescriptor x = this.getAttributeDescriptor(i);
881
            buffer.append(x.getName());
882
            buffer.append(x.getDataTypeName());
883
            buffer.append(x.getSize());
884
        }
885
        CRC32 crc = new CRC32();
886
        byte[] data = buffer.toString().getBytes();
887
        crc.update(data);
888
        return crc.getValue();
889
    }
890

    
891
    @Override
892
    public FeatureStore getStore() {
893
        if( this.storeRef == null ) {
894
            return null;
895
        }
896
        return (FeatureStore) this.storeRef.get();
897
    }
898
    
899
    public void setStore(FeatureStore store) {
900
        if( store == null ) {
901
            this.storeRef = null; 
902
        } else {
903
            this.storeRef = new WeakReference(store);
904
        }
905
    }
906

    
907
    @Override
908
    public void loadFromState(PersistentState state)
909
            throws PersistenceException {
910

    
911
//        FIXME: rules
912

    
913
        hasEvaluators = state.getBoolean("hasEvaluators");
914
        hasEmulators = state.getBoolean("hasEmulators");
915
        defaultGeometryAttributeName = state.getString("defaultGeometryAttributeName");
916
        defaultTimeAttributeName = state.getString("defaultTimeAttributeName");
917
        defaultGeometryAttributeIndex = state.getInt("defaultGeometryAttributeIndex");
918
        defaultTimeAttributeIndex = state.getInt("defaultTimeAttributeIndex");
919
        id = state.getString("id");
920
        hasOID = state.getBoolean("hasOID");
921
        allowAtomaticValues = state.getBoolean("allowAtomaticValues");
922

    
923
        requiredFields = state.getBoolean("requiredFields");
924
        internalID = state.getString("internalID");
925
        
926
        List<FeatureAttributeDescriptor> elements = state.getList("elements");
927
        for (FeatureAttributeDescriptor element : elements) {
928
            ((DefaultFeatureAttributeDescriptor)element).setFeatureType(this);
929
            super.add(element);
930
        }
931
        
932
        List<String> thePk = state.getList("pk");
933
        if( thePk==null ) {
934
            this.pk = null;
935
        } else {
936
            this.pk = new FeatureAttributeDescriptor[thePk.size()];
937
            for (int i = 0; i < pk.length; i++) {
938
                pk[i] = this.getAttributeDescriptor(thePk.get(i));
939
            }
940
        }
941
        this.fixAll();
942
    }
943

    
944
    @Override
945
    public void saveToState(PersistentState state) throws PersistenceException {
946

    
947
//        FIXME: rules
948

    
949
        state.set("hasEvaluators", hasEvaluators);
950
        state.set("hasEmulators", hasEmulators);
951
        state.set("defaultGeometryAttributeName", defaultGeometryAttributeName);
952
        state.set("defaultTimeAttributeName", defaultTimeAttributeName);
953
        state.set("defaultGeometryAttributeIndex", defaultGeometryAttributeIndex);
954
        state.set("defaultTimeAttributeIndex", defaultTimeAttributeIndex);
955
        state.set("id", id);
956
        state.set("hasOID", hasOID);
957
        state.set("allowAtomaticValues", allowAtomaticValues);
958

    
959
        List<String> thePk = null;
960
        if( this.pk!=null ) {
961
            thePk = new ArrayList<>();
962
            for (FeatureAttributeDescriptor attrdesc : this.pk) {
963
                thePk.add(attrdesc.getName());
964
            }
965
        }
966
        state.set("pk",thePk);
967

    
968
        state.set("requiredFields", requiredFields);
969
        state.set("internalID", internalID);
970
        
971
        List<FeatureAttributeDescriptor> elements = new ArrayList<>();
972
        elements.addAll(this);
973
        state.set("elements", elements);
974
        
975
        
976
    }
977
    
978
    private static final String FEATTYPE_PERSISTENCE_DEFINITION_NAME = "FeatureType";
979

    
980
    public static void registerPersistenceDefinition() {
981
        PersistenceManager manager = ToolsLocator.getPersistenceManager();
982
        
983
        if (manager.getDefinition(FEATTYPE_PERSISTENCE_DEFINITION_NAME)
984
                == null) {
985
            DynStruct definition = manager.addDefinition(DefaultFeatureType.class,
986
                    FEATTYPE_PERSISTENCE_DEFINITION_NAME,
987
                    FEATTYPE_PERSISTENCE_DEFINITION_NAME
988
                        + " persistent definition",
989
                    null,
990
                    null
991
            );
992
//            definition.addDynFieldObject("rules");
993
            definition.addDynFieldBoolean("hasEvaluators");
994
            definition.addDynFieldBoolean("hasEmulators");
995
            definition.addDynFieldString("defaultGeometryAttributeName");
996
            definition.addDynFieldString("defaultTimeAttributeName");
997
            definition.addDynFieldInt("defaultGeometryAttributeIndex");
998
            definition.addDynFieldInt("defaultTimeAttributeIndex");
999
            definition.addDynFieldString("id");
1000
            definition.addDynFieldBoolean("hasOID");
1001
            definition.addDynFieldBoolean("allowAtomaticValues");
1002
            
1003
            definition.addDynFieldArray("pk")
1004
                    .setClassOfItems(String.class);
1005
            
1006
            definition.addDynFieldBoolean("requiredFields");
1007
            definition.addDynFieldString("internalID"); 
1008

    
1009
            definition.addDynFieldList("elements")
1010
                    .setClassOfItems(FeatureAttributeDescriptor.class); 
1011
        }
1012
    }
1013

    
1014

    
1015
}