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

History | View | Annotate | Download (17.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.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
import org.slf4j.Logger;
61
import org.slf4j.LoggerFactory;
62

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

    
68
    private static final long serialVersionUID = -1842181135614158881L;
69

    
70
    final static private Logger logger = LoggerFactory
71
        .getLogger(TableDocument.class);
72

    
73
    private FeatureStore store;
74

    
75
    private String featureTypeId;
76

    
77
    private String[] attributeNames;
78

    
79
    private List<TableLink> linkTable;
80

    
81
    private VectorLayer associatedLayer;
82

    
83
    private FeatureQuery query;
84

    
85
    private Evaluator baseFilter;
86

    
87
    private FeatureQueryOrder baseOrder;
88

    
89
    private FeatureStoreModel featureStoreModel;
90

    
91
    private Object lock = new Object();
92

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

    
102
    public TableDocument() {
103
        this(null);
104
    }
105

    
106
    public TableDocument(DocumentManager factory, FeatureStore store) {
107
        this(factory);
108
        setStore(store);
109
    }
110

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

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

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

    
156
                } else {
157
                    fType = store.getDefaultFeatureType();
158
                }
159

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

    
173
                this.query.setFilter(this.baseFilter); // TODO check is valid
174
                this.query.setOrder(this.baseOrder);
175

    
176
            } catch (DataException e) {
177
                NotificationManager.addError(e);
178
                return null;
179
            }
180

    
181
        }
182
        return this.query;
183
    }
184

    
185
    /**
186
     * @return the store
187
     */
188
    public FeatureStore getStore() {
189
        return store;
190
    }
191

    
192
    /**
193
     * Return information about the table links.
194
     * 
195
     * @return List of TableLink information.
196
     */
197
    public List<TableLink> getLinks() {
198
        return this.linkTable;
199
    }
200

    
201
    /**
202
     * Returns if this table document has links with other tables.
203
     * 
204
     * @return if this table document has links with other tables
205
     */
206
    public boolean hasLinks() {
207
        return this.linkTable != null && this.linkTable.size() > 0;
208
    }
209

    
210
    /**
211
     * Devuelve el identificador de la tabla que contiene el link.
212
     * 
213
     * @return identificador ?nico de la tabla.
214
     * @deprecated see {{@link #getLinks()}
215
     */
216
    public String getLinkTable() {
217
        if (linkTable == null || linkTable.isEmpty()) {
218
            return null;
219
        }
220
        return linkTable.get(0).getTargetTable().getName();
221
    }
222

    
223
    /**
224
     * Devuelve el nombre del campo de la tabla a enlazar.
225
     * 
226
     * @return Nombre del campo de la tabla a enlazar.
227
     * @deprecated see {{@link #getLink()}
228
     */
229
    public String getField1() {
230
        if (linkTable.isEmpty()) {
231
            return null;
232
        }
233
        return this.linkTable.get(0).getSourceFieldName();
234
    }
235

    
236
    /**
237
     * Devuelve el nombre del campo de la tabla enlazada.
238
     * 
239
     * @return Nombre del campo de la tabla enlazada.
240
     * @deprecated see {{@link #getLink()}
241
     */
242
    public String getField2() {
243
        if (linkTable.isEmpty()) {
244
            return null;
245
        }
246
        return this.linkTable.get(0).getTargetFieldName();
247
    }
248

    
249
    /**
250
     * Enlaza la seleccion de esta tabla con la de la tabla indicada
251
     * 
252
     * @deprecated see {@link #addLinkTable(String, String, String)}
253
     */
254
    public void setLinkTable(String targetTable, String fieldSource,
255
        String fieldTarget) {
256
        this.addLinkTable(targetTable, fieldSource, fieldTarget);
257
    }
258

    
259
    /**
260
     * Add a table link to this document.
261
     * 
262
     * @param targetTable
263
     * @param fieldSource
264
     * @param fieldTarget
265
     */
266
    public void addLinkTable(String targetTable, String fieldSource,
267
        String fieldTarget) {
268
        TableDocument target =
269
            (TableDocument) ProjectManager.getInstance().getCurrentProject()
270
                .getDocument(targetTable, TableManager.TYPENAME);
271
        TableLink link = new TableLink(this, target, fieldSource, fieldTarget);
272
        link.setEnabled(true);
273
        if (this.linkTable == null) {
274
            this.linkTable = new ArrayList<TableLink>();
275
        }
276
        this.linkTable.add(link);
277
    }
278

    
279
    /**
280
     * remove the last link to table added.
281
     * 
282
     */
283
    public void removeLinkTable() {
284
        if (linkTable.isEmpty()) {
285
            return;
286
        }
287
        TableLink link = this.linkTable.remove(this.linkTable.size() - 1);
288
        link.setEnabled(false);
289
        this.linkTable = null;
290
    }
291

    
292
    /**
293
     * Remove the link to the table document.
294
     * 
295
     * @param name
296
     *            of table document to remove.
297
     */
298
    public void removeLinkTable(String name) {
299
        for (TableLink link : this.linkTable) {
300
            if (name.equals(link.target.getName())) {
301
                link.setEnabled(false);
302
                this.linkTable.remove(link);
303
            }
304
        }
305
    }
306

    
307
    public VectorLayer getAssociatedLayer() {
308
        return associatedLayer;
309
    }
310

    
311
    public void setAssociatedLayer(VectorLayer associatedLayer) {
312
        this.associatedLayer = associatedLayer;
313
    }
314

    
315
    public void update(Observable arg0, Object arg1) {
316
        if (this.store.equals(arg0)) {
317
            if (arg1 instanceof FeatureStoreNotification) {
318
                FeatureStoreNotification event =
319
                    (FeatureStoreNotification) arg1;
320
                if (event.getType() == FeatureStoreNotification.TRANSFORM_CHANGE
321
                    || event.getType() == FeatureStoreNotification.RESOURCE_CHANGED) {
322
                    this.query = null;
323
                }
324
            }
325

    
326
        }
327

    
328
    }
329

    
330
    @SuppressWarnings("unchecked")
331
    public void loadFromState(PersistentState state)
332
        throws PersistenceException {
333
        super.loadFromState(state);
334

    
335
        this.store = (FeatureStore) state.get("store");
336
        this.featureTypeId = state.getString("featureTypeId");
337
        this.attributeNames =
338
            (String[]) state.getArray("attributeNames", String.class);
339
        this.linkTable = state.getList("linkTable");
340
        this.associatedLayer = (FLyrVect) state.get("associatedLayer");
341
        this.query = (FeatureQuery) state.get("query");
342
        this.baseFilter = (Evaluator) state.get("baseFilter");
343
        this.baseOrder = (FeatureQueryOrder) state.get("baseOrder");
344
    }
345

    
346
    public void saveToState(PersistentState state) throws PersistenceException {
347
        super.saveToState(state);
348

    
349
        state.set("store", store);
350
        state.set("featureTypeId", featureTypeId);
351
        state.set("attributeNames", attributeNames);
352
        state.set("linkTable", linkTable);
353
        state.set("associatedLayer", associatedLayer);
354
        state.set("query", query);
355
        // state.set("baseFilter", baseFilter);
356
        state.set("baseOrder", baseOrder);
357
    }
358

    
359
    public static class TableLink implements Observer, Persistent {
360

    
361
        private TableDocument source;
362
        private FeatureStore storeSource;
363
        private int fieldSource;
364

    
365
        private TableDocument target;
366
        private FeatureStore storeTarget;
367
        private int fieldTarget;
368

    
369
        private boolean enabled;
370

    
371
        public TableLink() {
372
            this.source = null;
373
            this.target = null;
374
            this.fieldSource = -1;
375
            this.fieldTarget = -1;
376
            this.storeSource = null;
377
            this.storeTarget = null;
378
            this.enabled = false;
379
        }
380

    
381
        public TableLink(TableDocument source, TableDocument target,
382
            String fieldSource, String fieldTarget) {
383
            this();
384
            this.initialize(source, target, fieldSource, fieldTarget);
385
        }
386

    
387
        private void initialize(TableDocument source, TableDocument target,
388
            String fieldSource, String fieldTarget) {
389
            this.source = source;
390
            this.target = target;
391

    
392
            this.storeSource = this.source.getStore();
393
            this.storeTarget = this.target.getStore();
394
            try {
395
                this.fieldSource =
396
                    storeSource.getDefaultFeatureType().getIndex(fieldSource);
397
                this.fieldTarget =
398
                    storeTarget.getDefaultFeatureType().getIndex(fieldTarget);
399
            } catch (DataException ex) {
400
                logger.error("Can't initialize TableLink", ex);
401
                throw new RuntimeException("Can't initialize TableLink", ex);
402
            }
403
        }
404

    
405
        public void setEnabled(boolean enabled) {
406
            if (enabled) {
407
                this.storeSource.addObserver(this);
408
            } else {
409
                this.storeSource.deleteObserver(this);
410
            }
411
            this.enabled = enabled;
412
        }
413

    
414
        public boolean getEnabled() {
415
            return this.enabled;
416
        }
417

    
418
        public TableDocument getTargetTable() {
419
            return this.target;
420
        }
421

    
422
        public TableDocument getSourceTable() {
423
            return this.source;
424
        }
425

    
426
        public String getSourceFieldName() {
427
            try {
428
                return ((FeatureAttributeDescriptor) this.storeSource
429
                    .getDefaultFeatureType().get(this.fieldSource)).getName();
430
            } catch (DataException e) {
431
                logger.warn("Can't get source field name.", e);
432
                return null;
433
            }
434
        }
435

    
436
        public String getTargetFieldName() {
437
            try {
438
                return ((FeatureAttributeDescriptor) this.storeTarget
439
                    .getDefaultFeatureType().get(this.fieldTarget)).getName();
440
            } catch (DataException e) {
441
                logger.warn("Can't get target field name.", e);
442
                return null;
443
            }
444
        }
445

    
446
        public void update(Observable arg0, Object arg1) {
447
            try {
448
                FeatureSet fCollection1 =
449
                    (FeatureSet) storeSource.getSelection();
450
                FeatureSelection fCollection2 =
451
                    (FeatureSelection) storeTarget.createSelection();
452
                List<Object> idx = new ArrayList<Object>();
453

    
454
                // Construimos el ?ndice
455
                DisposableIterator iterator1 = null;
456
                try {
457
                    iterator1 = fCollection1.fastIterator();
458
                    while (iterator1.hasNext()) {
459
                        Feature feature = (Feature) iterator1.next();
460
                        Object obj = feature.get(fieldSource);
461
                        if (!idx.contains(obj)) {
462
                            idx.add(obj);
463
                        }
464
                    }
465
                } finally {
466
                    if (iterator1 != null) {
467
                        iterator1.dispose();
468
                    }
469
                }
470
                FeatureSet set = null;
471
                DisposableIterator iterator2 = null;
472

    
473
                try {
474
                    set = storeTarget.getFeatureSet();
475
                    iterator2 = set.fastIterator();
476
                    while (iterator2.hasNext()) {
477
                        Feature feature = (Feature) iterator2.next();
478
                        Object obj = feature.get(fieldTarget);
479
                        if (idx.contains(obj)) {
480
                            fCollection2.select(feature);
481
                        }
482
                    }
483
                } catch (DataException e1) {
484
                    NotificationManager.addError(e1);
485
                    return;
486
                } finally {
487
                    if (iterator2 != null) {
488
                        iterator2.dispose();
489
                    }
490
                    if (set != null) {
491
                        set.dispose();
492
                    }
493
                }
494

    
495
                // this applies the selection to the linked table
496
                if (storeSource != storeTarget) {
497
                    storeTarget.setSelection(fCollection2);
498
                }
499
            } catch (DataException e2) {
500
                NotificationManager.addError(e2);
501
                return;
502
            }
503
        }
504

    
505
        public void loadFromState(PersistentState state)
506
            throws PersistenceException {
507
            this.initialize((TableDocument) state.get("source"),
508
                (TableDocument) state.get("target"),
509
                state.getString("fieldSource"), state.getString("fieldTarget"));
510
            this.setEnabled(state.getBoolean("enabled"));
511
        }
512

    
513
        public void saveToState(PersistentState state)
514
            throws PersistenceException {
515
            state.set("source", this.source);
516
            state.set("target", this.target);
517
            state.set("fieldSource", this.getSourceFieldName());
518
            state.set("fieldTarget", this.getTargetFieldName());
519
            state.set("enabled", this.getEnabled());
520
        }
521

    
522
    }
523

    
524
}