Statistics
| Revision:

svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.compat.cdc / org.gvsig.fmap.dal / org.gvsig.fmap.dal.impl / src / main / java / org / gvsig / fmap / dal / impl / DefaultTransaction.java @ 47217

History | View | Annotate | Download (11.9 KB)

1
/*
2
 * gvSIG. Desktop Geographic Information System.
3
 * 
4
 * Copyright (C) 2007-2020 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, see <https://www.gnu.org/licenses/>. 
18
 * 
19
 * For any additional information, do not hesitate to contact us
20
 * at info AT gvsig.com, or visit our website www.gvsig.com.
21
 */
22

    
23
package org.gvsig.fmap.dal.impl;
24

    
25
import java.util.ArrayList;
26
import java.util.HashMap;
27
import java.util.List;
28
import java.util.Map;
29
import java.util.UUID;
30
import org.apache.commons.lang3.StringUtils;
31
import org.apache.commons.lang3.tuple.MutablePair;
32
import org.apache.commons.lang3.tuple.Pair;
33
import org.gvsig.fmap.dal.DataServerExplorer;
34
import org.gvsig.fmap.dal.DataStore;
35
import org.gvsig.fmap.dal.SupportTransactions;
36
import org.gvsig.fmap.dal.exception.DataException;
37
import org.gvsig.fmap.dal.feature.FeatureStore;
38
import static org.gvsig.fmap.dal.feature.FeatureStore.MODE_QUERY;
39
import org.gvsig.fmap.dal.spi.DataTransactionServices;
40
import org.gvsig.tools.dispose.Disposable;
41
import org.gvsig.tools.dispose.DisposeUtils;
42
import org.gvsig.tools.dispose.impl.AbstractDisposable;
43
import org.gvsig.tools.observer.BaseNotification;
44
import org.gvsig.tools.observer.ObservableHelper;
45
import org.gvsig.tools.observer.Observer;
46
import org.slf4j.Logger;
47
import org.slf4j.LoggerFactory;
48

    
49
/**
50
 *
51
 * @author gvSIG Team
52
 */
53
@SuppressWarnings("UseSpecificCatch")
54
public class DefaultTransaction extends AbstractDisposable implements DataTransactionServices {
55

    
56
    private static final Logger LOGGER = LoggerFactory.getLogger(DefaultTransaction.class);
57
    
58
    private final String code;
59
    private final Map<String,DataServerExplorer> explorers;
60
    private final Map<String,ConnectionService> connections;
61
    private Map<String,Pair<DataStore,Boolean>> stores;
62
    private boolean inProgress;
63
    private List<Disposable> disposables;
64
    private ObservableHelper observableHelper;
65

    
66
    public DefaultTransaction() {
67
        this.code = UUID.randomUUID().toString().replace("-", "");
68
        this.stores = new HashMap<>();
69
        this.explorers = new HashMap<>();
70
        this.disposables = new ArrayList<>();
71
        this.inProgress = false;
72
        this.connections = new HashMap<>();
73
        this.observableHelper = new ObservableHelper();
74
    }
75

    
76
    @Override
77
    public String getCode() {
78
        return this.code;
79
    }
80

    
81
    @Override
82
    public void begin() throws DataException {
83
        if( this.inProgress ) {
84
            throw new IllegalStateException("Transaction already started.");
85
        }
86
        this.observableHelper.notifyObservers(this, new BaseNotification("BEGIN", null));
87
        this.inProgress = true;
88
    }
89

    
90
    @Override
91
    public void commit() throws DataException {
92
        if( !this.isInProgress() ) {
93
            throw new IllegalStateException("Can't commit transaction without begin.");
94
        }
95
        for (Pair<DataStore, Boolean> item : stores.values()) {
96
            DataStore store = item.getLeft();
97
            if( store instanceof FeatureStore ) {
98
                FeatureStore fstore = (FeatureStore) store;
99
                if( fstore!=null && fstore.getMode() != MODE_QUERY) {
100
//                    LOGGER.info("Transaction commit: finishEditing "+store.getFullName());
101
                    fstore.finishEditing();
102
                }
103
            }
104
        }
105
        for (ConnectionService connection : this.connections.values()) {
106
            connection.finish();
107
        }
108
        this.observableHelper.notifyObservers(this, new BaseNotification("COMMIT", null));
109
        this.inProgress = false;
110
    }
111

    
112
    @Override
113
    public void rollback() throws DataException {
114
        if( !this.isInProgress() ) {
115
            throw new IllegalStateException("Can't rollback transaction without begin.");
116
        }
117
        
118
        for (Pair<DataStore, Boolean> item : stores.values()) {
119
            DataStore store = item.getLeft();
120
            if( store instanceof FeatureStore ) {
121
                FeatureStore fstore = (FeatureStore) store;
122
                if( fstore.getMode() != MODE_QUERY) {
123
                    fstore.cancelEditing();
124
                }
125
            }
126
        }
127
        for (ConnectionService connection : this.connections.values()) {
128
            connection.abort();
129
        }
130
        this.observableHelper.notifyObservers(this, new BaseNotification("ROLLBACK", null));
131
        this.inProgress = false;
132
    }
133

    
134
    @Override
135
    public void rollbackQuietly() {
136
        try {
137
            this.rollback();
138
        } catch(Exception ex) {
139
            // Do nothing
140
        }
141
    }
142

    
143
    @Override
144
    public void add(DataStore store) {
145
        add(store, null, true);
146
    }
147

    
148
    @Override
149
    public void add(DataStore store, String id) { 
150
        this.add(store, id, true);
151
    }
152
    
153
    @Override
154
    public void add(DataStore store, boolean local) {
155
        this.add(store, null, local);
156
    }
157
    
158
    @Override
159
    public void add(DataStore store, String id, boolean local) {
160
        String theId = id;
161
        if( StringUtils.isBlank(id) ) {
162
            theId = store.hashCode() + "@"+ store.getFullName();
163
        } else {
164
            DataStore theStore = this.stores.get(theId).getLeft();
165
            if(theStore!=null ){
166
                if( theStore==store ) {
167
                    return;
168
                }
169
                throw new IllegalArgumentException("The id '"+id+"' is already used.");
170
            }
171
        }
172
        if( store instanceof SupportTransactions ) {
173
            ((SupportTransactions) store).setTransaction(this);
174
        }
175
        if(!local){
176
            DisposeUtils.bind(store);
177
        }
178
        this.stores.put(theId,new MutablePair<>(store,local));
179
    }
180

    
181
    @Override
182
    public FeatureStore getFeatureStore(String id) {
183
        return (FeatureStore) this.stores.get(id);
184
    }
185
    
186
    @Override
187
    public void add(DataServerExplorer explorer) {
188
        this.add(explorer, null, true);
189
    }
190

    
191
    @Override
192
    public void add(DataServerExplorer explorer, String id) {
193
        this.add(explorer, id, true);
194
    }
195
    
196
    @Override
197
    public void add(DataServerExplorer explorer, boolean local) {
198
        this.add(explorer, null, local);
199
    }
200
    
201
    @Override
202
    public void add(DataServerExplorer explorer, String id, boolean local) {
203
        String theId = id;
204
        if( StringUtils.isBlank(id) ) {
205
            theId = String.valueOf(explorer.hashCode());
206
        } else {
207
            DataServerExplorer theExplorer = this.explorers.get(theId);
208
            if(theExplorer!=null ){
209
                if( theExplorer==explorer ) {
210
                    return;
211
                }
212
                throw new IllegalArgumentException("The id '"+id+"' is already used.");
213
            }
214
        }
215
        
216
        if( explorer instanceof SupportTransactions ) {
217
            ((SupportTransactions) explorer).setTransaction(this);
218
        }
219
        if(!local){
220
            DisposeUtils.bind(explorer);
221
        }
222
        this.explorers.put(theId,explorer);
223
    }
224
    
225
    @Override
226
    public DataServerExplorer getServerExplorer(String id) {
227
        return this.explorers.get(id);
228
    }
229

    
230
    @Override
231
    public void add(Disposable resource) throws DataException {
232
        this.disposables.add(resource);
233
    }
234

    
235
    @Override
236
    public void remove(DataStore store) {
237
        if( this.inProgress && !DisposeUtils.isNullOrDisposed(store)){
238
            throw new IllegalStateException("Can't remove store from a in progress transaction.");
239
        }
240
        String id = null;
241
        for (Map.Entry<String, Pair<DataStore,Boolean>> entry : this.stores.entrySet()) {
242
            if( store == entry.getValue().getLeft() ) {
243
                id = entry.getKey();
244
                break;
245
            }
246
        }
247
        if( id==null ) {
248
            return;
249
        }
250
        if( store instanceof SupportTransactions ) {
251
            ((SupportTransactions) store).setTransaction(null);
252
        }
253
        this.stores.remove(id);
254
        DisposeUtils.dispose(store);
255
    }
256

    
257
    @Override
258
    public void remove(DataServerExplorer serverExplorer) {
259
        if( this.inProgress ) {
260
            throw new IllegalStateException("Can't remove server explorer from a in progress transaction.");
261
        }
262
        String id = null;
263
        for (Map.Entry<String, DataServerExplorer> entry : this.explorers.entrySet()) {
264
            if( serverExplorer == entry.getValue() ) {
265
                id = entry.getKey();
266
                break;
267
            }
268
        }
269
        if( id==null ) {
270
            return;
271
        }
272
        if( serverExplorer instanceof SupportTransactions ) {
273
            ((SupportTransactions) serverExplorer).setTransaction(null);
274
        }
275
        this.explorers.remove(id);
276
        DisposeUtils.dispose(serverExplorer);
277
    }
278

    
279
    @Override
280
    public boolean isInProgress() {
281
        return inProgress;
282
    }
283

    
284
    @Override
285
    public void doDispose() {
286
        if( this.inProgress ) {
287
            this.rollbackQuietly();
288
        }
289
        for (Pair<DataStore, Boolean> item : stores.values()) {
290
            DataStore store = item.getLeft();
291
            if( store instanceof SupportTransactions ) {
292
                ((SupportTransactions) store).setTransaction(null);
293
            }
294
            DisposeUtils.disposeQuietly(store);
295
            
296
        }
297
        for (DataServerExplorer explorer : explorers.values()) {
298
            if( explorer instanceof SupportTransactions ) {
299
                ((SupportTransactions) explorer).setTransaction(null);
300
            }
301
            DisposeUtils.disposeQuietly(explorer);
302
            
303
        }
304
        for (Disposable resource : disposables) {
305
            if( resource instanceof SupportTransactions ) {
306
                ((SupportTransactions) resource).setTransaction(null);
307
            }
308
            DisposeUtils.disposeQuietly(resource);            
309
        }
310
        for (ConnectionService connection : this.connections.values()) {
311
            connection.dispose();
312
        }
313
        this.disposables = null;
314
        this.stores = null;
315
    }
316

    
317
    @Override
318
    public void close() throws Exception {
319
        this.dispose();
320
    }
321

    
322
    @Override
323
    public void addConnection(ConnectionService connection) {
324
        if( this.connections.containsKey(connection.getId()) ) {
325
            return;
326
        }
327
        this.connections.put(connection.getId(), connection);
328
    }
329

    
330
    @Override
331
    public ConnectionService getConnection(String id) {
332
        return this.connections.get(id);
333
    }
334

    
335
    @Override
336
    public void removeConnection(String id) {
337
        this.connections.remove(id);
338
    }
339

    
340
    @Override
341
    public boolean existsConnection(String id) {
342
        return this.connections.containsKey(id);
343
    }
344

    
345
    @Override
346
    public void addObserver(Observer obsrvr) {
347
        this.observableHelper.addObserver(obsrvr);
348
    }
349

    
350
    @Override
351
    public void deleteObserver(Observer obsrvr) {
352
        this.observableHelper.deleteObserver(obsrvr);
353
    }
354

    
355
    @Override
356
    public void deleteObservers() {
357
        this.observableHelper.deleteObservers();
358
    }
359

    
360
    @Override
361
    public boolean contains(DataServerExplorer explorer) {
362
        for (DataServerExplorer value : this.explorers.values()) {
363
            if(explorer == value){
364
                return true;
365
            }
366
        }
367
        return false;
368
    }
369

    
370
    @Override
371
    public boolean contains(DataStore store) {
372
        for (Pair<DataStore, Boolean> item : stores.values()) {
373
            DataStore value = item.getLeft();
374
            if(store == value){
375
                return true;
376
            }
377
        }
378
        return false;
379
    }
380
}