Statistics
| Revision:

svn-gvsig-desktop / tags / v2_0_0_Build_2056 / extensions / org.gvsig.app.document.table.app / org.gvsig.app.document.table.app.mainplugin / src / main / java / org / gvsig / app / project / documents / table / TableDocument.java @ 39030

History | View | Annotate | Download (17.2 KB)

1
/* gvSIG. Geographic Information System of the Valencian Government
2
 *
3
 * Copyright (C) 2007-2008 Infrastructures and Transports Department
4
 * of the Valencian Government (CIT)
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 2
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
 */
22

    
23
/*
24
 * AUTHORS (In addition to CIT):
25
 * 2008 {DiSiD Technologies}  {TableDocument implementation based on the gvSIG DAL API}
26
 */
27
package org.gvsig.app.project.documents.table;
28

    
29
import java.text.MessageFormat;
30
import java.util.ArrayList;
31
import java.util.Iterator;
32
import java.util.List;
33

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

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

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

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

    
72
    private FeatureStore store;
73

    
74
    private String featureTypeId;
75

    
76
    private String[] attributeNames;
77

    
78
    private List<TableLink> linkTable;
79

    
80
    private VectorLayer associatedLayer;
81

    
82
    private FeatureQuery query;
83

    
84
    private Evaluator baseFilter;
85

    
86
    private FeatureQueryOrder baseOrder;
87

    
88
    private FeatureStoreModel featureStoreModel;
89

    
90
    private Object lock = new Object();
91

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

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

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

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

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

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

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

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

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

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

    
180
        }
181
        return this.query;
182
    }
183

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

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

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

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

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

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

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

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

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

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

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

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

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

    
325
        }
326

    
327
    }
328

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

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

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

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

    
358
    public static class TableLink implements Observer, Persistent {
359

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

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

    
368
        private boolean enabled;
369

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
521
    }
522

    
523
}