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

History | View | Annotate | Download (20.1 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

    
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
import org.gvsig.fmap.dal.DataStore;
43
import org.gvsig.fmap.dal.DataTypes;
44
import org.gvsig.fmap.dal.HasDataStore;
45
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

    
67
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
public class TableDocument extends AbstractDocument implements HasDataStore, Observer {
74

    
75
    public static final String TABLE_PROPERTIES_PAGE_GROUP = "TableDocument";
76

    
77
    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
//    private final Object lock = new Object();
101
    
102
    private Map<String,String> patterns = null;
103

    
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
        this.patterns = null;
112
    }
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
    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
            }
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
        initializeFormattingPatterns();
144
    }
145

    
146
    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
    @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
                    ArrayList<String> newNames = new ArrayList<>();
219
                    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
    @Override
250
    public FeatureStore getDataStore() {
251
        return store;
252
    }
253
    
254
    
255

    
256
    /**
257
     * @return the store
258
     */
259
    public FeatureStore getFeatureStore() {
260
        return store;
261
    }
262

    
263
    /**
264
     * Return information about the table links.
265
     *
266
     * @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
     *
275
     * @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
     *
284
     * @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
     *
297
     * @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
     *
310
     * @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
     *
323
     * @param targetTable
324
     * @param fieldSource
325
     * @param fieldTarget
326
     * @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
     *
336
     * @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
            this.linkTable = new ArrayList<>();
349
        }
350
        this.linkTable.add(link);
351
    }
352

    
353
    /**
354
     * remove the last link to table added.
355
     *
356
     */
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
     *
369
     * @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
    @Override
390
    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
                if ( FeatureStoreNotification.TRANSFORM_CHANGE.equals(event.getType()) 
396
                    || FeatureStoreNotification.RESOURCE_CHANGED.equals(event.getType()) ) {
397
                    this.query = null;
398
                }
399
            }
400

    
401
        }
402

    
403
    }
404

    
405
    @SuppressWarnings("unchecked")
406
    @Override
407
    public void loadFromState(PersistentState state)
408
        throws PersistenceException {
409
        try {
410
            super.loadFromState(state);
411

    
412
            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
            this.patterns = new HashMap<>(state.getMap("patterns"));
422
        } 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
    }
428

    
429
    @Override
430
    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
        state.set("patterns",patterns);
442
    }
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
        @Override
532
        public void update(Observable arg0, Object arg1) {
533
            try {
534
                FeatureSet fCollection1 =
535
                    (FeatureSet) storeSource.getSelection();
536
                FeatureSelection fCollection2 =
537
                    (FeatureSelection) storeTarget.createSelection();
538
                List<Object> idx = new ArrayList<>();
539

    
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
                logger.warn(e2.getMessage(),e2);
587
            }
588
        }
589

    
590
        @Override
591
        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
        @Override
600
        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
    @Override
612
    public boolean isTemporary() {
613
        if(this.associatedLayer!=null && this.associatedLayer.isTemporary()){
614
            return true;
615
        }
616
        return false;
617
    }
618

    
619
    @Override
620
    public boolean isAvailable() {
621
        if(this.store == null){
622
            return false;
623
        }
624
        return true;
625
    }
626

    
627
}