Statistics
| Revision:

svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.plugin / org.gvsig.app.document.table.app / org.gvsig.app.document.table.app.mainplugin / src / main / java / org / gvsig / app / project / documents / table / TableDocument.java @ 46338

History | View | Annotate | Download (21.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
/*
25
 * AUTHORS (In addition to CIT):
26
 * 2008 {DiSiD Technologies}  {TableDocument implementation based on the gvSIG DAL API}
27
 */
28
package org.gvsig.app.project.documents.table;
29

    
30
import java.text.MessageFormat;
31
import java.text.SimpleDateFormat;
32
import java.util.ArrayList;
33
import java.util.HashMap;
34
import java.util.Iterator;
35
import java.util.List;
36
import java.util.Map;
37
import org.apache.commons.lang.StringUtils;
38

    
39
import org.gvsig.andami.messages.NotificationManager;
40
import org.gvsig.app.project.ProjectManager;
41
import org.gvsig.app.project.documents.AbstractDocument;
42
import org.gvsig.app.project.documents.DocumentManager;
43
import org.gvsig.fmap.dal.DataStoreParameters;
44
import org.gvsig.fmap.dal.DataTypes;
45
import org.gvsig.fmap.dal.HasDataStore;
46
import org.gvsig.fmap.dal.exception.DataException;
47
import org.gvsig.fmap.dal.feature.Feature;
48
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
49
import org.gvsig.fmap.dal.feature.FeatureQuery;
50
import org.gvsig.fmap.dal.feature.FeatureQueryOrder;
51
import org.gvsig.fmap.dal.feature.FeatureSelection;
52
import org.gvsig.fmap.dal.feature.FeatureSet;
53
import org.gvsig.fmap.dal.feature.FeatureStore;
54
import org.gvsig.fmap.dal.feature.FeatureStoreNotification;
55
import org.gvsig.fmap.dal.feature.FeatureType;
56
import org.gvsig.fmap.mapcontext.layers.vectorial.FLyrVect;
57
import org.gvsig.fmap.mapcontext.layers.vectorial.VectorLayer;
58
import org.gvsig.fmap.mapcontrol.dal.feature.swing.table.FeatureStoreModel;
59
import org.gvsig.tools.dispose.DisposableIterator;
60
import org.gvsig.tools.dispose.DisposeUtils;
61
import org.gvsig.tools.evaluator.Evaluator;
62
import org.gvsig.tools.exception.BaseException;
63
import org.gvsig.tools.observer.Observable;
64
import org.gvsig.tools.observer.Observer;
65
import org.gvsig.tools.persistence.Persistent;
66
import org.gvsig.tools.persistence.PersistentState;
67
import org.gvsig.tools.persistence.exception.PersistenceException;
68

    
69
import org.slf4j.Logger;
70
import org.slf4j.LoggerFactory;
71

    
72
/**
73
 * @author <a href="mailto:cordin@disid.com">C?sar Ordi?ana</a>
74
 */
75
public class TableDocument extends AbstractDocument implements HasDataStore, Observer {
76

    
77
    public static final String TABLE_PROPERTIES_PAGE_GROUP = "TableDocument";
78

    
79
    private static final long serialVersionUID = -1842181135614158881L;
80

    
81
    final static private Logger logger = LoggerFactory
82
        .getLogger(TableDocument.class);
83

    
84
    private FeatureStore store;
85

    
86
    private String featureTypeId;
87

    
88
    private String[] attributeNames;
89

    
90
    private List<TableLink> linkTable;
91

    
92
    private VectorLayer associatedLayer;
93

    
94
    private FeatureQuery query;
95

    
96
    private Evaluator baseFilter;
97

    
98
    private FeatureQueryOrder baseOrder;
99

    
100
    private FeatureStoreModel featureStoreModel;
101

    
102
//    private final Object lock = new Object();
103
    
104
    private Map<String,String> patterns = null;
105

    
106
    public TableDocument(DocumentManager factory) {
107
        super(factory);
108
        this.store = null;
109
        this.query = null;
110
        this.featureTypeId = null;
111
        this.baseFilter = null;
112
        this.baseOrder = null;
113
        this.patterns = null;
114
    }
115

    
116
    public TableDocument() {
117
        this(null);
118
    }
119

    
120
    public TableDocument(DocumentManager factory, FeatureStore store) {
121
        this(factory);
122
        setStore(store);
123
    }
124

    
125
    public synchronized FeatureStoreModel getFeatureStoreModel() {
126
        if (this.featureStoreModel == null) {
127
            try {
128
                this.featureStoreModel =
129
                    new FeatureStoreModel(getStore(), getQuery());
130
            } catch (BaseException e) {
131
                NotificationManager.addError(e);
132
            }
133
        }
134
        return this.featureStoreModel;
135
    }
136

    
137
    public void setStore(FeatureStore store) {
138
        if (this.store != null) {
139
            throw new UnsupportedOperationException(
140
                "can't set store. store already set.");
141
        }
142
        this.store = store;
143
        DisposeUtils.bind(this.store);
144
        this.store.addObserver(this);
145
        this.query = null; // setQuery(store.createFeatureQuery());
146
        initializeFormattingPatterns();
147
    }
148

    
149
    private void initializeFormattingPatterns() {
150
        FeatureType featureType;
151
        try {
152
            featureType = this.store.getDefaultFeatureType();
153
        } catch (DataException ex) {
154
            logger.warn("Can't initialize formating patterns", ex);
155
            return;
156
        }
157
        this.patterns = new HashMap<>();
158
        for( FeatureAttributeDescriptor descriptor : featureType ) {
159
            String pattern = null;
160
            switch( descriptor.getDataType().getType() ) {
161
            case DataTypes.BYTE:
162
            case DataTypes.INT:
163
            case DataTypes.LONG:
164
                pattern = "#,##0";
165
                break;
166
            case DataTypes.DOUBLE:
167
                pattern = "#,##0.0000000000";
168
                break;
169
            case DataTypes.FLOAT:
170
                pattern = "#,##0.0000";
171
                break;
172
            case DataTypes.DECIMAL:
173
                pattern = "#,##0.0000";
174
                break;
175
            case DataTypes.DATE:
176
                pattern = new SimpleDateFormat().toPattern();
177
                break;
178
            }
179
            this.patterns.put(descriptor.getName(), pattern);
180
        }
181
    }
182

    
183
    public String getFormattingPattern(String columnName) {
184
        if( this.patterns==null ) {
185
            return null;
186
        }
187
        String pattern = this.patterns.get(columnName);
188
        return pattern;
189
    }
190
    
191
    public void setFormattingPattern(String columnName, String pattern) {
192
        if( this.patterns==null ) {
193
            return;
194
        }
195
        this.patterns.put(columnName,pattern);
196
    }
197
    
198
    @SuppressWarnings("unchecked")
199
    public FeatureQuery getQuery() {
200
        if (this.query == null) {
201
            try {
202
                FeatureType fType = null;
203
                this.query = this.store.createFeatureQuery();
204
                if (this.featureTypeId != null) {
205
                    Iterator<FeatureType> iter;
206
                    iter = this.store.getFeatureTypes().iterator();
207
                    while (iter.hasNext()) {
208
                        fType = iter.next();
209
                        if (this.featureTypeId.equals(fType.getId())) {
210
                            this.query.setFeatureType(fType);
211
                            break;
212
                        }
213
                    }
214
                    if (fType == null) {
215
                        throw new RuntimeException(MessageFormat.format(
216
                            "frature type {1} not found.", this.featureTypeId));
217
                    }
218

    
219
                } else {
220
                    fType = store.getDefaultFeatureType();
221
                }
222

    
223
                if (this.attributeNames != null) {
224
                    ArrayList<String> newNames = new ArrayList<>();
225
                    for (String name : this.attributeNames) {
226
                        if (fType.getIndex(name) > -1) {
227
                            newNames.add(name);
228
                        }
229
                    }
230
                    if (newNames.size() > 0) {
231
                        this.query.setAttributeNames(newNames
232
                            .toArray(this.attributeNames));
233
                    }
234
                }
235

    
236
                this.query.setFilter(this.baseFilter); // TODO check is valid
237
                this.query.setOrder(this.baseOrder);
238

    
239
            } catch (DataException e) {
240
                NotificationManager.addError(e);
241
                return null;
242
            }
243

    
244
        }
245
        return this.query;
246
    }
247

    
248
    /**
249
     * @return the store
250
     */
251
    public FeatureStore getStore() {
252
        return store;
253
    }
254

    
255
    @Override
256
    public FeatureStore getDataStore() {
257
        return store;
258
    }
259
    
260
    
261

    
262
    /**
263
     * @return the store
264
     */
265
    public FeatureStore getFeatureStore() {
266
        return store;
267
    }
268

    
269
    /**
270
     * Return information about the table links.
271
     *
272
     * @return List of TableLink information.
273
     */
274
    public List<TableLink> getLinks() {
275
        return this.linkTable;
276
    }
277

    
278
    /**
279
     * Returns if this table document has links with other tables.
280
     *
281
     * @return if this table document has links with other tables
282
     */
283
    public boolean hasLinks() {
284
        return this.linkTable != null && this.linkTable.size() > 0;
285
    }
286

    
287
    /**
288
     * Devuelve el identificador de la tabla que contiene el link.
289
     *
290
     * @return identificador ?nico de la tabla.
291
     * @deprecated see {{@link #getLinks()}
292
     */
293
    public String getLinkTable() {
294
        if (linkTable == null || linkTable.isEmpty()) {
295
            return null;
296
        }
297
        return linkTable.get(0).getTargetTable().getName();
298
    }
299

    
300
    /**
301
     * Devuelve el nombre del campo de la tabla a enlazar.
302
     *
303
     * @return Nombre del campo de la tabla a enlazar.
304
     * @deprecated see {{@link #getLink()}
305
     */
306
    public String getField1() {
307
        if (linkTable.isEmpty()) {
308
            return null;
309
        }
310
        return this.linkTable.get(0).getSourceFieldName();
311
    }
312

    
313
    /**
314
     * Devuelve el nombre del campo de la tabla enlazada.
315
     *
316
     * @return Nombre del campo de la tabla enlazada.
317
     * @deprecated see {{@link #getLink()}
318
     */
319
    public String getField2() {
320
        if (linkTable.isEmpty()) {
321
            return null;
322
        }
323
        return this.linkTable.get(0).getTargetFieldName();
324
    }
325

    
326
    /**
327
     * Enlaza la seleccion de esta tabla con la de la tabla indicada
328
     *
329
     * @param targetTable
330
     * @param fieldSource
331
     * @param fieldTarget
332
     * @deprecated see {@link #addLinkTable(String, String, String)}
333
     */
334
    public void setLinkTable(String targetTable, String fieldSource,
335
        String fieldTarget) {
336
        this.addLinkTable(targetTable, fieldSource, fieldTarget);
337
    }
338

    
339
    /**
340
     * Add a table link to this document.
341
     *
342
     * @param targetTable
343
     * @param fieldSource
344
     * @param fieldTarget
345
     */
346
    public void addLinkTable(String targetTable, String fieldSource,
347
        String fieldTarget) {
348
        TableDocument target =
349
            (TableDocument) ProjectManager.getInstance().getCurrentProject()
350
                .getDocument(targetTable, TableManager.TYPENAME);
351
        TableLink link = new TableLink(this, target, fieldSource, fieldTarget);
352
        link.setEnabled(true);
353
        if (this.linkTable == null) {
354
            this.linkTable = new ArrayList<>();
355
        }
356
        this.linkTable.add(link);
357
    }
358

    
359
    /**
360
     * remove the last link to table added.
361
     *
362
     */
363
    public void removeLinkTable() {
364
        if (linkTable.isEmpty()) {
365
            return;
366
        }
367
        TableLink link = this.linkTable.remove(this.linkTable.size() - 1);
368
        link.setEnabled(false);
369
        this.linkTable = null;
370
    }
371

    
372
    /**
373
     * Remove the link to the table document.
374
     *
375
     * @param name
376
     *            of table document to remove.
377
     */
378
    public void removeLinkTable(String name) {
379
        for (TableLink link : this.linkTable) {
380
            if (name.equals(link.target.getName())) {
381
                link.setEnabled(false);
382
                this.linkTable.remove(link);
383
            }
384
        }
385
    }
386

    
387
    public VectorLayer getAssociatedLayer() {
388
        return associatedLayer;
389
    }
390

    
391
    public void setAssociatedLayer(VectorLayer associatedLayer) {
392
        this.associatedLayer = associatedLayer;
393
    }
394

    
395
    @Override
396
    public void update(Observable arg0, Object arg1) {
397
        if (this.store.equals(arg0)) {
398
            if (arg1 instanceof FeatureStoreNotification) {
399
                FeatureStoreNotification event =
400
                    (FeatureStoreNotification) arg1;
401
                if ( FeatureStoreNotification.TRANSFORM_CHANGE.equals(event.getType()) 
402
                    || FeatureStoreNotification.RESOURCE_CHANGED.equals(event.getType()) ) {
403
                    this.query = null;
404
                }
405
            }
406

    
407
        }
408

    
409
    }
410

    
411
    @SuppressWarnings("unchecked")
412
    @Override
413
    public void loadFromState(PersistentState state)
414
        throws PersistenceException {
415
        try {
416
            super.loadFromState(state);
417

    
418
            this.store = (FeatureStore) state.get("store");
419
            this.featureTypeId = state.getString("featureTypeId");
420
            this.attributeNames =
421
                (String[]) state.getArray("attributeNames", String.class);
422
            this.linkTable = state.getList("linkTable");
423
            this.associatedLayer = (FLyrVect) state.get("associatedLayer");
424
            this.query = (FeatureQuery) state.get("query");
425
            this.baseFilter = (Evaluator) state.get("baseFilter");
426
            this.baseOrder = (FeatureQueryOrder) state.get("baseOrder");
427
            this.patterns = new HashMap<>(state.getMap("patterns"));
428
        } catch (Throwable e) {
429
            String storeName = (store == null) ? "unknow" : store.getFullName();
430
            logger.warn("can't load table '" + this.getName() + "' (store="
431
                + storeName + ") from persisted state.", e);
432
        }
433
    }
434

    
435
    @Override
436
    public void saveToState(PersistentState state) throws PersistenceException {
437
        super.saveToState(state);
438

    
439
        state.set("store", store);
440
        state.set("featureTypeId", featureTypeId);
441
        state.set("attributeNames", attributeNames);
442
        state.set("linkTable", linkTable);
443
        state.set("associatedLayer", associatedLayer);
444
        state.set("query", query);
445
        // state.set("baseFilter", baseFilter);
446
        state.set("baseOrder", baseOrder);
447
        state.set("patterns",patterns);
448
    }
449

    
450
    public static class TableLink implements Observer, Persistent {
451

    
452
        private TableDocument source;
453
        private FeatureStore storeSource;
454
        private int fieldSource;
455

    
456
        private TableDocument target;
457
        private FeatureStore storeTarget;
458
        private int fieldTarget;
459

    
460
        private boolean enabled;
461

    
462
        public TableLink() {
463
            this.source = null;
464
            this.target = null;
465
            this.fieldSource = -1;
466
            this.fieldTarget = -1;
467
            this.storeSource = null;
468
            this.storeTarget = null;
469
            this.enabled = false;
470
        }
471

    
472
        public TableLink(TableDocument source, TableDocument target,
473
            String fieldSource, String fieldTarget) {
474
            this();
475
            this.initialize(source, target, fieldSource, fieldTarget);
476
        }
477

    
478
        private void initialize(TableDocument source, TableDocument target,
479
            String fieldSource, String fieldTarget) {
480
            this.source = source;
481
            this.target = target;
482

    
483
            this.storeSource = this.source.getStore();
484
            this.storeTarget = this.target.getStore();
485
            try {
486
                this.fieldSource =
487
                    storeSource.getDefaultFeatureType().getIndex(fieldSource);
488
                this.fieldTarget =
489
                    storeTarget.getDefaultFeatureType().getIndex(fieldTarget);
490
            } catch (DataException ex) {
491
                logger.error("Can't initialize TableLink", ex);
492
                throw new RuntimeException("Can't initialize TableLink", ex);
493
            }
494
        }
495

    
496
        public void setEnabled(boolean enabled) {
497
            if (enabled) {
498
                this.storeSource.addObserver(this);
499
            } else {
500
                this.storeSource.deleteObserver(this);
501
            }
502
            this.enabled = enabled;
503
        }
504

    
505
        public boolean getEnabled() {
506
            return this.enabled;
507
        }
508

    
509
        public TableDocument getTargetTable() {
510
            return this.target;
511
        }
512

    
513
        public TableDocument getSourceTable() {
514
            return this.source;
515
        }
516

    
517
        public String getSourceFieldName() {
518
            try {
519
                return ((FeatureAttributeDescriptor) this.storeSource
520
                    .getDefaultFeatureType().get(this.fieldSource)).getName();
521
            } catch (DataException e) {
522
                logger.warn("Can't get source field name.", e);
523
                return null;
524
            }
525
        }
526

    
527
        public String getTargetFieldName() {
528
            try {
529
                return ((FeatureAttributeDescriptor) this.storeTarget
530
                    .getDefaultFeatureType().get(this.fieldTarget)).getName();
531
            } catch (DataException e) {
532
                logger.warn("Can't get target field name.", e);
533
                return null;
534
            }
535
        }
536

    
537
        @Override
538
        public void update(Observable arg0, Object arg1) {
539
            try {
540
                FeatureSet fCollection1 =
541
                    (FeatureSet) storeSource.getSelection();
542
                FeatureSelection fCollection2 =
543
                    (FeatureSelection) storeTarget.createSelection();
544
                List<Object> idx = new ArrayList<>();
545

    
546
                // Construimos el ?ndice
547
                DisposableIterator iterator1 = null;
548
                try {
549
                    iterator1 = fCollection1.fastIterator();
550
                    while (iterator1.hasNext()) {
551
                        Feature feature = (Feature) iterator1.next();
552
                        Object obj = feature.get(fieldSource);
553
                        if (!idx.contains(obj)) {
554
                            idx.add(obj);
555
                        }
556
                    }
557
                } finally {
558
                    if (iterator1 != null) {
559
                        iterator1.dispose();
560
                    }
561
                }
562
                FeatureSet set = null;
563
                DisposableIterator iterator2 = null;
564

    
565
                try {
566
                    set = storeTarget.getFeatureSet();
567
                    iterator2 = set.fastIterator();
568
                    while (iterator2.hasNext()) {
569
                        Feature feature = (Feature) iterator2.next();
570
                        Object obj = feature.get(fieldTarget);
571
                        if (idx.contains(obj)) {
572
                            fCollection2.select(feature);
573
                        }
574
                    }
575
                } catch (DataException e1) {
576
                    NotificationManager.addError(e1);
577
                    return;
578
                } finally {
579
                    if (iterator2 != null) {
580
                        iterator2.dispose();
581
                    }
582
                    if (set != null) {
583
                        set.dispose();
584
                    }
585
                }
586

    
587
                // this applies the selection to the linked table
588
                if (storeSource != storeTarget) {
589
                    storeTarget.setSelection(fCollection2);
590
                }
591
            } catch (DataException e2) {
592
                logger.warn(e2.getMessage(),e2);
593
            }
594
        }
595

    
596
        @Override
597
        public void loadFromState(PersistentState state)
598
            throws PersistenceException {
599
            this.initialize((TableDocument) state.get("source"),
600
                (TableDocument) state.get("target"),
601
                state.getString("fieldSource"), state.getString("fieldTarget"));
602
            this.setEnabled(state.getBoolean("enabled"));
603
        }
604

    
605
        @Override
606
        public void saveToState(PersistentState state)
607
            throws PersistenceException {
608
            state.set("source", this.source);
609
            state.set("target", this.target);
610
            state.set("fieldSource", this.getSourceFieldName());
611
            state.set("fieldTarget", this.getTargetFieldName());
612
            state.set("enabled", this.getEnabled());
613
        }
614

    
615
    }
616

    
617
    @Override
618
    public boolean isTemporary() {
619
        if(this.associatedLayer!=null && this.associatedLayer.isTemporary()){
620
            return true;
621
        }
622
        if( this.getFeatureStore().isTemporary() ) {
623
            return true;
624
        }
625
        return false;
626
    }
627

    
628
    @Override
629
    public boolean isAvailable() {
630
        if(this.store == null){
631
            return false;
632
        }
633
        return true;
634
    }
635

    
636

    
637
    @Override
638
    public boolean contains(Object value) {
639
        if( value == null ) {
640
            return false;
641
        }
642
        DataStoreParameters params;
643
        if( (value instanceof FeatureStore) ) {
644
            params = ((FeatureStore) value).getParameters();
645
        } else if(value instanceof DataStoreParameters){
646
            params = (DataStoreParameters) value;
647
        } else {
648
            return false;
649
        }
650
        FeatureStore featureStore = this.getStore();
651
                if(featureStore.getParameters().isTheSameStore(params)){
652
            return true;
653
        }
654
        return false;
655
    }
656

    
657
    @Override
658
    public void refresh() {
659
        try {
660
            this.getStore().refresh();
661
        } catch (DataException e) {
662
            logger.warn("Can't refresh table", e);
663
        }
664
    }
665
}