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

History | View | Annotate | Download (18.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.util.ArrayList;
32
import java.util.Iterator;
33
import java.util.List;
34

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

    
61
import org.slf4j.Logger;
62
import org.slf4j.LoggerFactory;
63

    
64
/**
65
 * @author <a href="mailto:cordin@disid.com">C?sar Ordi?ana</a>
66
 */
67
public class TableDocument extends AbstractDocument implements Observer {
68

    
69
    public static final String TABLE_PROPERTIES_PAGE_GROUP = "TableDocument";
70

    
71
    private static final long serialVersionUID = -1842181135614158881L;
72

    
73
    final static private Logger logger = LoggerFactory
74
        .getLogger(TableDocument.class);
75

    
76
    private FeatureStore store;
77

    
78
    private String featureTypeId;
79

    
80
    private String[] attributeNames;
81

    
82
    private List<TableLink> linkTable;
83

    
84
    private VectorLayer associatedLayer;
85

    
86
    private FeatureQuery query;
87

    
88
    private Evaluator baseFilter;
89

    
90
    private FeatureQueryOrder baseOrder;
91

    
92
    private FeatureStoreModel featureStoreModel;
93

    
94
    private Object lock = new Object();
95

    
96
    public TableDocument(DocumentManager factory) {
97
        super(factory);
98
        this.store = null;
99
        this.query = null;
100
        this.featureTypeId = null;
101
        this.baseFilter = null;
102
        this.baseOrder = null;
103
    }
104

    
105
    public TableDocument() {
106
        this(null);
107
    }
108

    
109
    public TableDocument(DocumentManager factory, FeatureStore store) {
110
        this(factory);
111
        setStore(store);
112
    }
113

    
114
    public FeatureStoreModel getFeatureStoreModel() {
115
        synchronized (lock) {
116
            if (this.featureStoreModel == null) {
117
                try {
118
                    this.featureStoreModel =
119
                        new FeatureStoreModel(getStore(), getQuery());
120
                } catch (BaseException e) {
121
                    NotificationManager.addError(e);
122
                }
123
            }
124
        }
125
        return this.featureStoreModel;
126
    }
127

    
128
    public void setStore(FeatureStore store) {
129
        if (this.store != null) {
130
            throw new UnsupportedOperationException(
131
                "can't set store. store already set.");
132
        }
133
        this.store = store;
134
        this.store.addObserver(this);
135
        this.query = null; // setQuery(store.createFeatureQuery());
136
    }
137

    
138
    @SuppressWarnings("unchecked")
139
    public FeatureQuery getQuery() {
140
        if (this.query == null) {
141
            try {
142
                FeatureType fType = null;
143
                this.query = this.store.createFeatureQuery();
144
                if (this.featureTypeId != null) {
145
                    Iterator<FeatureType> iter;
146
                    iter = this.store.getFeatureTypes().iterator();
147
                    while (iter.hasNext()) {
148
                        fType = iter.next();
149
                        if (this.featureTypeId.equals(fType.getId())) {
150
                            this.query.setFeatureType(fType);
151
                            break;
152
                        }
153
                    }
154
                    if (fType == null) {
155
                        throw new RuntimeException(MessageFormat.format(
156
                            "frature type {1} not found.", this.featureTypeId));
157
                    }
158

    
159
                } else {
160
                    fType = store.getDefaultFeatureType();
161
                }
162

    
163
                if (this.attributeNames != null) {
164
                    ArrayList<String> newNames = new ArrayList<String>();
165
                    for (String name : this.attributeNames) {
166
                        if (fType.getIndex(name) > -1) {
167
                            newNames.add(name);
168
                        }
169
                    }
170
                    if (newNames.size() > 0) {
171
                        this.query.setAttributeNames(newNames
172
                            .toArray(this.attributeNames));
173
                    }
174
                }
175

    
176
                this.query.setFilter(this.baseFilter); // TODO check is valid
177
                this.query.setOrder(this.baseOrder);
178

    
179
            } catch (DataException e) {
180
                NotificationManager.addError(e);
181
                return null;
182
            }
183

    
184
        }
185
        return this.query;
186
    }
187

    
188
    /**
189
     * @return the store
190
     */
191
    public FeatureStore getStore() {
192
        return store;
193
    }
194

    
195
    /**
196
     * @return the store
197
     */
198
    public FeatureStore getFeatureStore() {
199
        return store;
200
    }
201

    
202
    /**
203
     * Return information about the table links.
204
     *
205
     * @return List of TableLink information.
206
     */
207
    public List<TableLink> getLinks() {
208
        return this.linkTable;
209
    }
210

    
211
    /**
212
     * Returns if this table document has links with other tables.
213
     *
214
     * @return if this table document has links with other tables
215
     */
216
    public boolean hasLinks() {
217
        return this.linkTable != null && this.linkTable.size() > 0;
218
    }
219

    
220
    /**
221
     * Devuelve el identificador de la tabla que contiene el link.
222
     *
223
     * @return identificador ?nico de la tabla.
224
     * @deprecated see {{@link #getLinks()}
225
     */
226
    public String getLinkTable() {
227
        if (linkTable == null || linkTable.isEmpty()) {
228
            return null;
229
        }
230
        return linkTable.get(0).getTargetTable().getName();
231
    }
232

    
233
    /**
234
     * Devuelve el nombre del campo de la tabla a enlazar.
235
     *
236
     * @return Nombre del campo de la tabla a enlazar.
237
     * @deprecated see {{@link #getLink()}
238
     */
239
    public String getField1() {
240
        if (linkTable.isEmpty()) {
241
            return null;
242
        }
243
        return this.linkTable.get(0).getSourceFieldName();
244
    }
245

    
246
    /**
247
     * Devuelve el nombre del campo de la tabla enlazada.
248
     *
249
     * @return Nombre del campo de la tabla enlazada.
250
     * @deprecated see {{@link #getLink()}
251
     */
252
    public String getField2() {
253
        if (linkTable.isEmpty()) {
254
            return null;
255
        }
256
        return this.linkTable.get(0).getTargetFieldName();
257
    }
258

    
259
    /**
260
     * Enlaza la seleccion de esta tabla con la de la tabla indicada
261
     *
262
     * @deprecated see {@link #addLinkTable(String, String, String)}
263
     */
264
    public void setLinkTable(String targetTable, String fieldSource,
265
        String fieldTarget) {
266
        this.addLinkTable(targetTable, fieldSource, fieldTarget);
267
    }
268

    
269
    /**
270
     * Add a table link to this document.
271
     *
272
     * @param targetTable
273
     * @param fieldSource
274
     * @param fieldTarget
275
     */
276
    public void addLinkTable(String targetTable, String fieldSource,
277
        String fieldTarget) {
278
        TableDocument target =
279
            (TableDocument) ProjectManager.getInstance().getCurrentProject()
280
                .getDocument(targetTable, TableManager.TYPENAME);
281
        TableLink link = new TableLink(this, target, fieldSource, fieldTarget);
282
        link.setEnabled(true);
283
        if (this.linkTable == null) {
284
            this.linkTable = new ArrayList<TableLink>();
285
        }
286
        this.linkTable.add(link);
287
    }
288

    
289
    /**
290
     * remove the last link to table added.
291
     *
292
     */
293
    public void removeLinkTable() {
294
        if (linkTable.isEmpty()) {
295
            return;
296
        }
297
        TableLink link = this.linkTable.remove(this.linkTable.size() - 1);
298
        link.setEnabled(false);
299
        this.linkTable = null;
300
    }
301

    
302
    /**
303
     * Remove the link to the table document.
304
     *
305
     * @param name
306
     *            of table document to remove.
307
     */
308
    public void removeLinkTable(String name) {
309
        for (TableLink link : this.linkTable) {
310
            if (name.equals(link.target.getName())) {
311
                link.setEnabled(false);
312
                this.linkTable.remove(link);
313
            }
314
        }
315
    }
316

    
317
    public VectorLayer getAssociatedLayer() {
318
        return associatedLayer;
319
    }
320

    
321
    public void setAssociatedLayer(VectorLayer associatedLayer) {
322
        this.associatedLayer = associatedLayer;
323
    }
324

    
325
    public void update(Observable arg0, Object arg1) {
326
        if (this.store.equals(arg0)) {
327
            if (arg1 instanceof FeatureStoreNotification) {
328
                FeatureStoreNotification event =
329
                    (FeatureStoreNotification) arg1;
330
                if (event.getType() == FeatureStoreNotification.TRANSFORM_CHANGE
331
                    || event.getType() == FeatureStoreNotification.RESOURCE_CHANGED) {
332
                    this.query = null;
333
                }
334
            }
335

    
336
        }
337

    
338
    }
339

    
340
    @SuppressWarnings("unchecked")
341
    public void loadFromState(PersistentState state)
342
        throws PersistenceException {
343
        try {
344
            super.loadFromState(state);
345

    
346
            this.store = (FeatureStore) state.get("store");
347
            this.featureTypeId = state.getString("featureTypeId");
348
            this.attributeNames =
349
                (String[]) state.getArray("attributeNames", String.class);
350
            this.linkTable = state.getList("linkTable");
351
            this.associatedLayer = (FLyrVect) state.get("associatedLayer");
352
            this.query = (FeatureQuery) state.get("query");
353
            this.baseFilter = (Evaluator) state.get("baseFilter");
354
            this.baseOrder = (FeatureQueryOrder) state.get("baseOrder");
355
        } catch (Throwable e) {
356
            String storeName = (store == null) ? "unknow" : store.getFullName();
357
            logger.warn("can't load table '" + this.getName() + "' (store="
358
                + storeName + ") from persisted state.", e);
359
//            this.setAvailable(false);
360
            return;
361
        }
362
    }
363

    
364
    public void saveToState(PersistentState state) throws PersistenceException {
365
        super.saveToState(state);
366

    
367
        state.set("store", store);
368
        state.set("featureTypeId", featureTypeId);
369
        state.set("attributeNames", attributeNames);
370
        state.set("linkTable", linkTable);
371
        state.set("associatedLayer", associatedLayer);
372
        state.set("query", query);
373
        // state.set("baseFilter", baseFilter);
374
        state.set("baseOrder", baseOrder);
375
    }
376

    
377
    public static class TableLink implements Observer, Persistent {
378

    
379
        private TableDocument source;
380
        private FeatureStore storeSource;
381
        private int fieldSource;
382

    
383
        private TableDocument target;
384
        private FeatureStore storeTarget;
385
        private int fieldTarget;
386

    
387
        private boolean enabled;
388

    
389
        public TableLink() {
390
            this.source = null;
391
            this.target = null;
392
            this.fieldSource = -1;
393
            this.fieldTarget = -1;
394
            this.storeSource = null;
395
            this.storeTarget = null;
396
            this.enabled = false;
397
        }
398

    
399
        public TableLink(TableDocument source, TableDocument target,
400
            String fieldSource, String fieldTarget) {
401
            this();
402
            this.initialize(source, target, fieldSource, fieldTarget);
403
        }
404

    
405
        private void initialize(TableDocument source, TableDocument target,
406
            String fieldSource, String fieldTarget) {
407
            this.source = source;
408
            this.target = target;
409

    
410
            this.storeSource = this.source.getStore();
411
            this.storeTarget = this.target.getStore();
412
            try {
413
                this.fieldSource =
414
                    storeSource.getDefaultFeatureType().getIndex(fieldSource);
415
                this.fieldTarget =
416
                    storeTarget.getDefaultFeatureType().getIndex(fieldTarget);
417
            } catch (DataException ex) {
418
                logger.error("Can't initialize TableLink", ex);
419
                throw new RuntimeException("Can't initialize TableLink", ex);
420
            }
421
        }
422

    
423
        public void setEnabled(boolean enabled) {
424
            if (enabled) {
425
                this.storeSource.addObserver(this);
426
            } else {
427
                this.storeSource.deleteObserver(this);
428
            }
429
            this.enabled = enabled;
430
        }
431

    
432
        public boolean getEnabled() {
433
            return this.enabled;
434
        }
435

    
436
        public TableDocument getTargetTable() {
437
            return this.target;
438
        }
439

    
440
        public TableDocument getSourceTable() {
441
            return this.source;
442
        }
443

    
444
        public String getSourceFieldName() {
445
            try {
446
                return ((FeatureAttributeDescriptor) this.storeSource
447
                    .getDefaultFeatureType().get(this.fieldSource)).getName();
448
            } catch (DataException e) {
449
                logger.warn("Can't get source field name.", e);
450
                return null;
451
            }
452
        }
453

    
454
        public String getTargetFieldName() {
455
            try {
456
                return ((FeatureAttributeDescriptor) this.storeTarget
457
                    .getDefaultFeatureType().get(this.fieldTarget)).getName();
458
            } catch (DataException e) {
459
                logger.warn("Can't get target field name.", e);
460
                return null;
461
            }
462
        }
463

    
464
        public void update(Observable arg0, Object arg1) {
465
            try {
466
                FeatureSet fCollection1 =
467
                    (FeatureSet) storeSource.getSelection();
468
                FeatureSelection fCollection2 =
469
                    (FeatureSelection) storeTarget.createSelection();
470
                List<Object> idx = new ArrayList<Object>();
471

    
472
                // Construimos el ?ndice
473
                DisposableIterator iterator1 = null;
474
                try {
475
                    iterator1 = fCollection1.fastIterator();
476
                    while (iterator1.hasNext()) {
477
                        Feature feature = (Feature) iterator1.next();
478
                        Object obj = feature.get(fieldSource);
479
                        if (!idx.contains(obj)) {
480
                            idx.add(obj);
481
                        }
482
                    }
483
                } finally {
484
                    if (iterator1 != null) {
485
                        iterator1.dispose();
486
                    }
487
                }
488
                FeatureSet set = null;
489
                DisposableIterator iterator2 = null;
490

    
491
                try {
492
                    set = storeTarget.getFeatureSet();
493
                    iterator2 = set.fastIterator();
494
                    while (iterator2.hasNext()) {
495
                        Feature feature = (Feature) iterator2.next();
496
                        Object obj = feature.get(fieldTarget);
497
                        if (idx.contains(obj)) {
498
                            fCollection2.select(feature);
499
                        }
500
                    }
501
                } catch (DataException e1) {
502
                    NotificationManager.addError(e1);
503
                    return;
504
                } finally {
505
                    if (iterator2 != null) {
506
                        iterator2.dispose();
507
                    }
508
                    if (set != null) {
509
                        set.dispose();
510
                    }
511
                }
512

    
513
                // this applies the selection to the linked table
514
                if (storeSource != storeTarget) {
515
                    storeTarget.setSelection(fCollection2);
516
                }
517
            } catch (DataException e2) {
518
                NotificationManager.addError(e2);
519
                return;
520
            }
521
        }
522

    
523
        public void loadFromState(PersistentState state)
524
            throws PersistenceException {
525
            this.initialize((TableDocument) state.get("source"),
526
                (TableDocument) state.get("target"),
527
                state.getString("fieldSource"), state.getString("fieldTarget"));
528
            this.setEnabled(state.getBoolean("enabled"));
529
        }
530

    
531
        public void saveToState(PersistentState state)
532
            throws PersistenceException {
533
            state.set("source", this.source);
534
            state.set("target", this.target);
535
            state.set("fieldSource", this.getSourceFieldName());
536
            state.set("fieldTarget", this.getTargetFieldName());
537
            state.set("enabled", this.getEnabled());
538
        }
539

    
540
    }
541

    
542
    @Override
543
    public boolean isTemporary() {
544
        if(this.associatedLayer!=null && this.associatedLayer.isTemporary()){
545
            return true;
546
        }
547
        return false;
548
    }
549

    
550
    public boolean isAvailable() {
551
        if(this.store == null){
552
            return false;
553
        }
554
        return true;
555
    }
556

    
557
}