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

History | View | Annotate | Download (10.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.gvsig.fmap.dal.DataServerExplorer;
32
import org.gvsig.fmap.dal.DataStore;
33
import org.gvsig.fmap.dal.SupportTransactions;
34
import org.gvsig.fmap.dal.exception.DataException;
35
import org.gvsig.fmap.dal.feature.FeatureStore;
36
import static org.gvsig.fmap.dal.feature.FeatureStore.MODE_QUERY;
37
import org.gvsig.fmap.dal.spi.DataTransactionServices;
38
import org.gvsig.tools.dispose.Disposable;
39
import org.gvsig.tools.dispose.DisposeUtils;
40
import org.gvsig.tools.observer.BaseNotification;
41
import org.gvsig.tools.observer.ObservableHelper;
42
import org.gvsig.tools.observer.Observer;
43
import org.slf4j.Logger;
44
import org.slf4j.LoggerFactory;
45

    
46
/**
47
 *
48
 * @author gvSIG Team
49
 */
50
@SuppressWarnings("UseSpecificCatch")
51
public class DefaultTransaction implements DataTransactionServices {
52

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

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

    
73
    @Override
74
    public String getCode() {
75
        return this.code;
76
    }
77

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

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

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

    
129
    @Override
130
    public void rollbackQuietly() {
131
        try {
132
            this.rollback();
133
        } catch(Exception ex) {
134
            // Do nothing
135
        }
136
    }
137

    
138
    @Override
139
    public void add(DataStore store) {
140
        add(store, null, true);
141
    }
142

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

    
176
    @Override
177
    public FeatureStore getFeatureStore(String id) {
178
        return (FeatureStore) this.stores.get(id);
179
    }
180
    
181
    @Override
182
    public void add(DataServerExplorer explorer) {
183
        this.add(explorer, null, true);
184
    }
185

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

    
225
    @Override
226
    public void add(Disposable resource) throws DataException {
227
        this.disposables.add(resource);
228
    }
229

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

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

    
274
    @Override
275
    public boolean isInProgress() {
276
        return inProgress;
277
    }
278

    
279
    @Override
280
    public void dispose() {
281
        if( this.inProgress ) {
282
            this.rollbackQuietly();
283
        }
284
        for (DataStore store : stores.values()) {
285
            if( store instanceof SupportTransactions ) {
286
                ((SupportTransactions) store).setTransaction(null);
287
            }
288
            DisposeUtils.disposeQuietly(store);
289
            
290
        }
291
        for (DataServerExplorer explorer : explorers.values()) {
292
            if( explorer instanceof SupportTransactions ) {
293
                ((SupportTransactions) explorer).setTransaction(null);
294
            }
295
            DisposeUtils.disposeQuietly(explorer);
296
            
297
        }
298
        for (Disposable resource : disposables) {
299
            if( resource instanceof SupportTransactions ) {
300
                ((SupportTransactions) resource).setTransaction(null);
301
            }
302
            DisposeUtils.disposeQuietly(resource);            
303
        }
304
        for (ConnectionService connection : this.connections.values()) {
305
            connection.dispose();
306
        }
307
        this.disposables = null;
308
        this.stores = null;
309
    }
310

    
311
    @Override
312
    public void close() throws Exception {
313
        this.dispose();
314
    }
315

    
316
    @Override
317
    public void addConnection(ConnectionService connection) {
318
        if( this.connections.containsKey(connection.getId()) ) {
319
            return;
320
        }
321
        this.connections.put(connection.getId(), connection);
322
    }
323

    
324
    @Override
325
    public ConnectionService getConnection(String id) {
326
        return this.connections.get(id);
327
    }
328

    
329
    @Override
330
    public void removeConnection(String id) {
331
        this.connections.remove(id);
332
    }
333

    
334
    @Override
335
    public boolean existsConnection(String id) {
336
        return this.connections.containsKey(id);
337
    }
338

    
339
    @Override
340
    public void addObserver(Observer obsrvr) {
341
        this.observableHelper.addObserver(obsrvr);
342
    }
343

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

    
349
    @Override
350
    public void deleteObservers() {
351
        this.observableHelper.deleteObservers();
352
    }
353
}