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

History | View | Annotate | Download (20.2 KB)

1 40558 jjdelcerro
/**
2
 * gvSIG. Desktop Geographic Information System.
3 40435 jjdelcerro
 *
4 40558 jjdelcerro
 * Copyright (C) 2007-2013 gvSIG Association.
5
 *
6 40435 jjdelcerro
 * This program is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU General Public License
8 40558 jjdelcerro
 * as published by the Free Software Foundation; either version 3
9 40435 jjdelcerro
 * of the License, or (at your option) any later version.
10 40558 jjdelcerro
 *
11 40435 jjdelcerro
 * 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 40558 jjdelcerro
 *
16 40435 jjdelcerro
 * 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 40558 jjdelcerro
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19 40435 jjdelcerro
 * MA  02110-1301, USA.
20 40558 jjdelcerro
 *
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 40435 jjdelcerro
 */
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 43354 jjdelcerro
import java.text.SimpleDateFormat;
32 40435 jjdelcerro
import java.util.ArrayList;
33 43354 jjdelcerro
import java.util.HashMap;
34 40435 jjdelcerro
import java.util.Iterator;
35
import java.util.List;
36 43354 jjdelcerro
import java.util.Map;
37 40435 jjdelcerro
38
import org.gvsig.andami.messages.NotificationManager;
39
import org.gvsig.app.project.ProjectManager;
40
import org.gvsig.app.project.documents.AbstractDocument;
41
import org.gvsig.app.project.documents.DocumentManager;
42 44189 jjdelcerro
import org.gvsig.fmap.dal.DataStore;
43 43354 jjdelcerro
import org.gvsig.fmap.dal.DataTypes;
44 44189 jjdelcerro
import org.gvsig.fmap.dal.HasDataStore;
45 40435 jjdelcerro
import org.gvsig.fmap.dal.exception.DataException;
46
import org.gvsig.fmap.dal.feature.Feature;
47
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
48
import org.gvsig.fmap.dal.feature.FeatureQuery;
49
import org.gvsig.fmap.dal.feature.FeatureQueryOrder;
50
import org.gvsig.fmap.dal.feature.FeatureSelection;
51
import org.gvsig.fmap.dal.feature.FeatureSet;
52
import org.gvsig.fmap.dal.feature.FeatureStore;
53
import org.gvsig.fmap.dal.feature.FeatureStoreNotification;
54
import org.gvsig.fmap.dal.feature.FeatureType;
55
import org.gvsig.fmap.mapcontext.layers.vectorial.FLyrVect;
56
import org.gvsig.fmap.mapcontext.layers.vectorial.VectorLayer;
57
import org.gvsig.fmap.mapcontrol.dal.feature.swing.table.FeatureStoreModel;
58
import org.gvsig.tools.dispose.DisposableIterator;
59
import org.gvsig.tools.evaluator.Evaluator;
60
import org.gvsig.tools.exception.BaseException;
61
import org.gvsig.tools.observer.Observable;
62
import org.gvsig.tools.observer.Observer;
63
import org.gvsig.tools.persistence.Persistent;
64
import org.gvsig.tools.persistence.PersistentState;
65
import org.gvsig.tools.persistence.exception.PersistenceException;
66 42088 fdiaz
67 40435 jjdelcerro
import org.slf4j.Logger;
68
import org.slf4j.LoggerFactory;
69
70
/**
71
 * @author <a href="mailto:cordin@disid.com">C?sar Ordi?ana</a>
72
 */
73 44189 jjdelcerro
public class TableDocument extends AbstractDocument implements HasDataStore, Observer {
74 40435 jjdelcerro
75 41707 jjdelcerro
    public static final String TABLE_PROPERTIES_PAGE_GROUP = "TableDocument";
76 42088 fdiaz
77 40435 jjdelcerro
    private static final long serialVersionUID = -1842181135614158881L;
78
79
    final static private Logger logger = LoggerFactory
80
        .getLogger(TableDocument.class);
81
82
    private FeatureStore store;
83
84
    private String featureTypeId;
85
86
    private String[] attributeNames;
87
88
    private List<TableLink> linkTable;
89
90
    private VectorLayer associatedLayer;
91
92
    private FeatureQuery query;
93
94
    private Evaluator baseFilter;
95
96
    private FeatureQueryOrder baseOrder;
97
98
    private FeatureStoreModel featureStoreModel;
99
100 43354 jjdelcerro
//    private final Object lock = new Object();
101
102
    private Map<String,String> patterns = null;
103 40435 jjdelcerro
104
    public TableDocument(DocumentManager factory) {
105
        super(factory);
106
        this.store = null;
107
        this.query = null;
108
        this.featureTypeId = null;
109
        this.baseFilter = null;
110
        this.baseOrder = null;
111 43354 jjdelcerro
        this.patterns = null;
112 40435 jjdelcerro
    }
113
114
    public TableDocument() {
115
        this(null);
116
    }
117
118
    public TableDocument(DocumentManager factory, FeatureStore store) {
119
        this(factory);
120
        setStore(store);
121
    }
122
123 43354 jjdelcerro
    public synchronized FeatureStoreModel getFeatureStoreModel() {
124
        if (this.featureStoreModel == null) {
125
            try {
126
                this.featureStoreModel =
127
                    new FeatureStoreModel(getStore(), getQuery());
128
            } catch (BaseException e) {
129
                NotificationManager.addError(e);
130 40435 jjdelcerro
            }
131
        }
132
        return this.featureStoreModel;
133
    }
134
135
    public void setStore(FeatureStore store) {
136
        if (this.store != null) {
137
            throw new UnsupportedOperationException(
138
                "can't set store. store already set.");
139
        }
140
        this.store = store;
141
        this.store.addObserver(this);
142
        this.query = null; // setQuery(store.createFeatureQuery());
143 43354 jjdelcerro
        initializeFormattingPatterns();
144 40435 jjdelcerro
    }
145
146 43354 jjdelcerro
    private void initializeFormattingPatterns() {
147
        FeatureType featureType;
148
        try {
149
            featureType = this.store.getDefaultFeatureType();
150
        } catch (DataException ex) {
151
            logger.warn("Can't initialize formating patterns", ex);
152
            return;
153
        }
154
        this.patterns = new HashMap<>();
155
        for( FeatureAttributeDescriptor descriptor : featureType ) {
156
            String pattern = null;
157
            switch( descriptor.getDataType().getType() ) {
158
            case DataTypes.BYTE:
159
            case DataTypes.INT:
160
            case DataTypes.LONG:
161
                pattern = "#,##0";
162
                break;
163
            case DataTypes.DOUBLE:
164
                pattern = "#,##0.0000000000";
165
                break;
166
            case DataTypes.FLOAT:
167
                pattern = "#,##0.0000";
168
                break;
169
            case DataTypes.DATE:
170
                pattern = new SimpleDateFormat().toPattern();
171
                break;
172
            }
173
            this.patterns.put(descriptor.getName(), pattern);
174
        }
175
    }
176
177
    public String getFormattingPattern(String columnName) {
178
        if( this.patterns==null ) {
179
            return null;
180
        }
181
        String pattern = this.patterns.get(columnName);
182
        return pattern;
183
    }
184
185
    public void setFormattingPattern(String columnName, String pattern) {
186
        if( this.patterns==null ) {
187
            return;
188
        }
189
        this.patterns.put(columnName,pattern);
190
    }
191
192 40435 jjdelcerro
    @SuppressWarnings("unchecked")
193
    public FeatureQuery getQuery() {
194
        if (this.query == null) {
195
            try {
196
                FeatureType fType = null;
197
                this.query = this.store.createFeatureQuery();
198
                if (this.featureTypeId != null) {
199
                    Iterator<FeatureType> iter;
200
                    iter = this.store.getFeatureTypes().iterator();
201
                    while (iter.hasNext()) {
202
                        fType = iter.next();
203
                        if (this.featureTypeId.equals(fType.getId())) {
204
                            this.query.setFeatureType(fType);
205
                            break;
206
                        }
207
                    }
208
                    if (fType == null) {
209
                        throw new RuntimeException(MessageFormat.format(
210
                            "frature type {1} not found.", this.featureTypeId));
211
                    }
212
213
                } else {
214
                    fType = store.getDefaultFeatureType();
215
                }
216
217
                if (this.attributeNames != null) {
218 43354 jjdelcerro
                    ArrayList<String> newNames = new ArrayList<>();
219 40435 jjdelcerro
                    for (String name : this.attributeNames) {
220
                        if (fType.getIndex(name) > -1) {
221
                            newNames.add(name);
222
                        }
223
                    }
224
                    if (newNames.size() > 0) {
225
                        this.query.setAttributeNames(newNames
226
                            .toArray(this.attributeNames));
227
                    }
228
                }
229
230
                this.query.setFilter(this.baseFilter); // TODO check is valid
231
                this.query.setOrder(this.baseOrder);
232
233
            } catch (DataException e) {
234
                NotificationManager.addError(e);
235
                return null;
236
            }
237
238
        }
239
        return this.query;
240
    }
241
242
    /**
243
     * @return the store
244
     */
245
    public FeatureStore getStore() {
246
        return store;
247
    }
248
249 44189 jjdelcerro
    @Override
250
    public FeatureStore getDataStore() {
251
        return store;
252
    }
253
254
255
256 40435 jjdelcerro
    /**
257 42775 jjdelcerro
     * @return the store
258
     */
259
    public FeatureStore getFeatureStore() {
260
        return store;
261
    }
262
263
    /**
264 40435 jjdelcerro
     * Return information about the table links.
265 42088 fdiaz
     *
266 40435 jjdelcerro
     * @return List of TableLink information.
267
     */
268
    public List<TableLink> getLinks() {
269
        return this.linkTable;
270
    }
271
272
    /**
273
     * Returns if this table document has links with other tables.
274 42088 fdiaz
     *
275 40435 jjdelcerro
     * @return if this table document has links with other tables
276
     */
277
    public boolean hasLinks() {
278
        return this.linkTable != null && this.linkTable.size() > 0;
279
    }
280
281
    /**
282
     * Devuelve el identificador de la tabla que contiene el link.
283 42088 fdiaz
     *
284 40435 jjdelcerro
     * @return identificador ?nico de la tabla.
285
     * @deprecated see {{@link #getLinks()}
286
     */
287
    public String getLinkTable() {
288
        if (linkTable == null || linkTable.isEmpty()) {
289
            return null;
290
        }
291
        return linkTable.get(0).getTargetTable().getName();
292
    }
293
294
    /**
295
     * Devuelve el nombre del campo de la tabla a enlazar.
296 42088 fdiaz
     *
297 40435 jjdelcerro
     * @return Nombre del campo de la tabla a enlazar.
298
     * @deprecated see {{@link #getLink()}
299
     */
300
    public String getField1() {
301
        if (linkTable.isEmpty()) {
302
            return null;
303
        }
304
        return this.linkTable.get(0).getSourceFieldName();
305
    }
306
307
    /**
308
     * Devuelve el nombre del campo de la tabla enlazada.
309 42088 fdiaz
     *
310 40435 jjdelcerro
     * @return Nombre del campo de la tabla enlazada.
311
     * @deprecated see {{@link #getLink()}
312
     */
313
    public String getField2() {
314
        if (linkTable.isEmpty()) {
315
            return null;
316
        }
317
        return this.linkTable.get(0).getTargetFieldName();
318
    }
319
320
    /**
321
     * Enlaza la seleccion de esta tabla con la de la tabla indicada
322 42088 fdiaz
     *
323 43354 jjdelcerro
     * @param targetTable
324
     * @param fieldSource
325
     * @param fieldTarget
326 40435 jjdelcerro
     * @deprecated see {@link #addLinkTable(String, String, String)}
327
     */
328
    public void setLinkTable(String targetTable, String fieldSource,
329
        String fieldTarget) {
330
        this.addLinkTable(targetTable, fieldSource, fieldTarget);
331
    }
332
333
    /**
334
     * Add a table link to this document.
335 42088 fdiaz
     *
336 40435 jjdelcerro
     * @param targetTable
337
     * @param fieldSource
338
     * @param fieldTarget
339
     */
340
    public void addLinkTable(String targetTable, String fieldSource,
341
        String fieldTarget) {
342
        TableDocument target =
343
            (TableDocument) ProjectManager.getInstance().getCurrentProject()
344
                .getDocument(targetTable, TableManager.TYPENAME);
345
        TableLink link = new TableLink(this, target, fieldSource, fieldTarget);
346
        link.setEnabled(true);
347
        if (this.linkTable == null) {
348 43354 jjdelcerro
            this.linkTable = new ArrayList<>();
349 40435 jjdelcerro
        }
350
        this.linkTable.add(link);
351
    }
352
353
    /**
354
     * remove the last link to table added.
355 42088 fdiaz
     *
356 40435 jjdelcerro
     */
357
    public void removeLinkTable() {
358
        if (linkTable.isEmpty()) {
359
            return;
360
        }
361
        TableLink link = this.linkTable.remove(this.linkTable.size() - 1);
362
        link.setEnabled(false);
363
        this.linkTable = null;
364
    }
365
366
    /**
367
     * Remove the link to the table document.
368 42088 fdiaz
     *
369 40435 jjdelcerro
     * @param name
370
     *            of table document to remove.
371
     */
372
    public void removeLinkTable(String name) {
373
        for (TableLink link : this.linkTable) {
374
            if (name.equals(link.target.getName())) {
375
                link.setEnabled(false);
376
                this.linkTable.remove(link);
377
            }
378
        }
379
    }
380
381
    public VectorLayer getAssociatedLayer() {
382
        return associatedLayer;
383
    }
384
385
    public void setAssociatedLayer(VectorLayer associatedLayer) {
386
        this.associatedLayer = associatedLayer;
387
    }
388
389 43354 jjdelcerro
    @Override
390 40435 jjdelcerro
    public void update(Observable arg0, Object arg1) {
391
        if (this.store.equals(arg0)) {
392
            if (arg1 instanceof FeatureStoreNotification) {
393
                FeatureStoreNotification event =
394
                    (FeatureStoreNotification) arg1;
395 43354 jjdelcerro
                if ( FeatureStoreNotification.TRANSFORM_CHANGE.equals(event.getType())
396
                    || FeatureStoreNotification.RESOURCE_CHANGED.equals(event.getType()) ) {
397 40435 jjdelcerro
                    this.query = null;
398
                }
399
            }
400
401
        }
402
403
    }
404
405
    @SuppressWarnings("unchecked")
406 43354 jjdelcerro
    @Override
407 40435 jjdelcerro
    public void loadFromState(PersistentState state)
408
        throws PersistenceException {
409 42088 fdiaz
        try {
410
            super.loadFromState(state);
411 40435 jjdelcerro
412 42088 fdiaz
            this.store = (FeatureStore) state.get("store");
413
            this.featureTypeId = state.getString("featureTypeId");
414
            this.attributeNames =
415
                (String[]) state.getArray("attributeNames", String.class);
416
            this.linkTable = state.getList("linkTable");
417
            this.associatedLayer = (FLyrVect) state.get("associatedLayer");
418
            this.query = (FeatureQuery) state.get("query");
419
            this.baseFilter = (Evaluator) state.get("baseFilter");
420
            this.baseOrder = (FeatureQueryOrder) state.get("baseOrder");
421 43354 jjdelcerro
            this.patterns = new HashMap<>(state.getMap("patterns"));
422 42088 fdiaz
        } catch (Throwable e) {
423
            String storeName = (store == null) ? "unknow" : store.getFullName();
424
            logger.warn("can't load table '" + this.getName() + "' (store="
425
                + storeName + ") from persisted state.", e);
426
        }
427 40435 jjdelcerro
    }
428
429 43354 jjdelcerro
    @Override
430 40435 jjdelcerro
    public void saveToState(PersistentState state) throws PersistenceException {
431
        super.saveToState(state);
432
433
        state.set("store", store);
434
        state.set("featureTypeId", featureTypeId);
435
        state.set("attributeNames", attributeNames);
436
        state.set("linkTable", linkTable);
437
        state.set("associatedLayer", associatedLayer);
438
        state.set("query", query);
439
        // state.set("baseFilter", baseFilter);
440
        state.set("baseOrder", baseOrder);
441 43354 jjdelcerro
        state.set("patterns",patterns);
442 40435 jjdelcerro
    }
443
444
    public static class TableLink implements Observer, Persistent {
445
446
        private TableDocument source;
447
        private FeatureStore storeSource;
448
        private int fieldSource;
449
450
        private TableDocument target;
451
        private FeatureStore storeTarget;
452
        private int fieldTarget;
453
454
        private boolean enabled;
455
456
        public TableLink() {
457
            this.source = null;
458
            this.target = null;
459
            this.fieldSource = -1;
460
            this.fieldTarget = -1;
461
            this.storeSource = null;
462
            this.storeTarget = null;
463
            this.enabled = false;
464
        }
465
466
        public TableLink(TableDocument source, TableDocument target,
467
            String fieldSource, String fieldTarget) {
468
            this();
469
            this.initialize(source, target, fieldSource, fieldTarget);
470
        }
471
472
        private void initialize(TableDocument source, TableDocument target,
473
            String fieldSource, String fieldTarget) {
474
            this.source = source;
475
            this.target = target;
476
477
            this.storeSource = this.source.getStore();
478
            this.storeTarget = this.target.getStore();
479
            try {
480
                this.fieldSource =
481
                    storeSource.getDefaultFeatureType().getIndex(fieldSource);
482
                this.fieldTarget =
483
                    storeTarget.getDefaultFeatureType().getIndex(fieldTarget);
484
            } catch (DataException ex) {
485
                logger.error("Can't initialize TableLink", ex);
486
                throw new RuntimeException("Can't initialize TableLink", ex);
487
            }
488
        }
489
490
        public void setEnabled(boolean enabled) {
491
            if (enabled) {
492
                this.storeSource.addObserver(this);
493
            } else {
494
                this.storeSource.deleteObserver(this);
495
            }
496
            this.enabled = enabled;
497
        }
498
499
        public boolean getEnabled() {
500
            return this.enabled;
501
        }
502
503
        public TableDocument getTargetTable() {
504
            return this.target;
505
        }
506
507
        public TableDocument getSourceTable() {
508
            return this.source;
509
        }
510
511
        public String getSourceFieldName() {
512
            try {
513
                return ((FeatureAttributeDescriptor) this.storeSource
514
                    .getDefaultFeatureType().get(this.fieldSource)).getName();
515
            } catch (DataException e) {
516
                logger.warn("Can't get source field name.", e);
517
                return null;
518
            }
519
        }
520
521
        public String getTargetFieldName() {
522
            try {
523
                return ((FeatureAttributeDescriptor) this.storeTarget
524
                    .getDefaultFeatureType().get(this.fieldTarget)).getName();
525
            } catch (DataException e) {
526
                logger.warn("Can't get target field name.", e);
527
                return null;
528
            }
529
        }
530
531 43354 jjdelcerro
        @Override
532 40435 jjdelcerro
        public void update(Observable arg0, Object arg1) {
533
            try {
534
                FeatureSet fCollection1 =
535
                    (FeatureSet) storeSource.getSelection();
536
                FeatureSelection fCollection2 =
537
                    (FeatureSelection) storeTarget.createSelection();
538 43354 jjdelcerro
                List<Object> idx = new ArrayList<>();
539 40435 jjdelcerro
540
                // Construimos el ?ndice
541
                DisposableIterator iterator1 = null;
542
                try {
543
                    iterator1 = fCollection1.fastIterator();
544
                    while (iterator1.hasNext()) {
545
                        Feature feature = (Feature) iterator1.next();
546
                        Object obj = feature.get(fieldSource);
547
                        if (!idx.contains(obj)) {
548
                            idx.add(obj);
549
                        }
550
                    }
551
                } finally {
552
                    if (iterator1 != null) {
553
                        iterator1.dispose();
554
                    }
555
                }
556
                FeatureSet set = null;
557
                DisposableIterator iterator2 = null;
558
559
                try {
560
                    set = storeTarget.getFeatureSet();
561
                    iterator2 = set.fastIterator();
562
                    while (iterator2.hasNext()) {
563
                        Feature feature = (Feature) iterator2.next();
564
                        Object obj = feature.get(fieldTarget);
565
                        if (idx.contains(obj)) {
566
                            fCollection2.select(feature);
567
                        }
568
                    }
569
                } catch (DataException e1) {
570
                    NotificationManager.addError(e1);
571
                    return;
572
                } finally {
573
                    if (iterator2 != null) {
574
                        iterator2.dispose();
575
                    }
576
                    if (set != null) {
577
                        set.dispose();
578
                    }
579
                }
580
581
                // this applies the selection to the linked table
582
                if (storeSource != storeTarget) {
583
                    storeTarget.setSelection(fCollection2);
584
                }
585
            } catch (DataException e2) {
586 43354 jjdelcerro
                logger.warn(e2.getMessage(),e2);
587 40435 jjdelcerro
            }
588
        }
589
590 43354 jjdelcerro
        @Override
591 40435 jjdelcerro
        public void loadFromState(PersistentState state)
592
            throws PersistenceException {
593
            this.initialize((TableDocument) state.get("source"),
594
                (TableDocument) state.get("target"),
595
                state.getString("fieldSource"), state.getString("fieldTarget"));
596
            this.setEnabled(state.getBoolean("enabled"));
597
        }
598
599 43354 jjdelcerro
        @Override
600 40435 jjdelcerro
        public void saveToState(PersistentState state)
601
            throws PersistenceException {
602
            state.set("source", this.source);
603
            state.set("target", this.target);
604
            state.set("fieldSource", this.getSourceFieldName());
605
            state.set("fieldTarget", this.getTargetFieldName());
606
            state.set("enabled", this.getEnabled());
607
        }
608
609
    }
610
611 42088 fdiaz
    @Override
612
    public boolean isTemporary() {
613
        if(this.associatedLayer!=null && this.associatedLayer.isTemporary()){
614
            return true;
615
        }
616 44443 jjdelcerro
        if( this.getFeatureStore().isTemporary() ) {
617
            return true;
618
        }
619 42088 fdiaz
        return false;
620
    }
621
622 43354 jjdelcerro
    @Override
623 42088 fdiaz
    public boolean isAvailable() {
624
        if(this.store == null){
625
            return false;
626
        }
627
        return true;
628
    }
629
630 40435 jjdelcerro
}