Statistics
| Revision:

gvsig-tools / org.gvsig.tools / library / trunk / org.gvsig.tools / org.gvsig.tools.lib / src / main / java / org / gvsig / tools / persistence / impl / DefaultPersistentContext.java @ 836

History | View | Annotate | Download (12 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 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
 * 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
/* gvSIG. Geographic Information System of the Valencian Government
25
*
26
* Copyright (C) 2007-2008 Infrastructures and Transports Department
27
* of the Valencian Government (CIT)
28
*
29
* This program is free software; you can redistribute it and/or
30
* modify it under the terms of the GNU General Public License
31
* as published by the Free Software Foundation; either version 2
32
* of the License, or (at your option) any later version.
33
*
34
* This program is distributed in the hope that it will be useful,
35
* but WITHOUT ANY WARRANTY; without even the implied warranty of
36
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
37
* GNU General Public License for more details.
38
*
39
* You should have received a copy of the GNU General Public License
40
* along with this program; if not, write to the Free Software
41
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
42
* MA  02110-1301, USA.
43
*
44
*/
45

    
46
/*
47
* AUTHORS (In addition to CIT):
48
* 2009 IVER T.I   {{Task}}
49
*/
50

    
51
package org.gvsig.tools.persistence.impl;
52

    
53
import java.util.ArrayList;
54
import java.util.Iterator;
55
import java.util.LinkedHashMap;
56
import java.util.List;
57
import java.util.Map;
58
import java.util.Map.Entry;
59

    
60
import org.gvsig.tools.persistence.PersistenceFactory;
61
import org.gvsig.tools.persistence.PersistenceManager;
62
import org.gvsig.tools.persistence.PersistentState;
63
import org.gvsig.tools.persistence.exception.PersistenceClassNotRegistered;
64
import org.gvsig.tools.persistence.exception.PersistenceException;
65
import org.gvsig.tools.persistence.exception.PersistenceRuntimeException;
66
import org.gvsig.tools.persistence.exception.PersistenceValidateExceptions;
67
import org.gvsig.tools.persistence.impl.exception.ObjectNotFoundException;
68
import org.gvsig.tools.persistence.impl.exception.PersistenceIDNotLoadedException;
69
import org.gvsig.tools.persistence.spi.PersistentContextServices;
70
import org.gvsig.tools.persistence.spi.PersistentIdentifier;
71
import org.gvsig.tools.persistence.spi.PersistentStateServices;
72

    
73
public class DefaultPersistentContext implements PersistentContextServices {
74
        private static int IdentifiersCounter = 1; 
75

    
76
        private Map idToReference;
77
        private Map objToReference;
78
        private PersistentIdentifier rootId;
79
        private PersistenceManager manager;
80
        private boolean collectErrors;
81
        private PersistenceException errors;
82
        private boolean validated;
83

    
84
        public DefaultPersistentContext(PersistenceManager manager) {
85
                this.manager = manager;
86
                this.collectErrors = false;
87
                this.errors = null;
88
                this.validated = false;
89

    
90
                // Use LinkedHashMap for predictable order when save to a file
91
                this.idToReference = new LinkedHashMap(); 
92
                this.objToReference = new LinkedHashMap();
93
        }
94

    
95
        private class DefaultPersistentIdentifier implements PersistentIdentifier, Comparable {
96
                private String value;
97
                
98
                DefaultPersistentIdentifier(String value) {
99
                        this.value = value;
100
                }
101
                
102
//                String getValue() {
103
//                        return value;
104
//                }
105

    
106
                public boolean equals(Object obj) {
107
                        if (!(obj instanceof DefaultPersistentIdentifier)) {
108
                                return false;
109
                        }
110
                        return value == ((DefaultPersistentIdentifier) obj).value;
111
                }
112

    
113
                public boolean hasValue(Object value) {
114
                        return this.value.equals(value);
115
                }
116
                
117
                public int hashCode() {
118
                        return value.hashCode();
119
                }
120
                
121
                public String toString() {
122
                        return value;
123
                }
124

    
125
                public int compareTo(Object obj) {
126
                        if (!(obj instanceof DefaultPersistentIdentifier)) {
127
                                return -1;
128
                        }
129
                        return value.compareTo( ((DefaultPersistentIdentifier) obj).value) ;
130
                }
131
        }
132
        
133
        private class ContextValue implements ObjectReference, Comparable {
134
                private Object obj;
135
                private PersistentState state;
136
                private PersistentIdentifier id;
137

    
138
                ContextValue(PersistentIdentifier id, PersistentState state) {
139
                        this.id = id;
140
                        this.state = state;
141
                        this.obj = null;
142
                }
143
                
144
//                public void update() throws PersistenceException {
145
//                        if( this.obj == null ) {
146
//                                updateObjectInReference(this);
147
//                        }
148
//                }
149

    
150
                public boolean hasObject() {
151
                        return this.obj != null;
152
                }
153
                
154
//                public boolean hasState() {
155
//                        return this.state != null;
156
//                }
157
                
158
                public Object getObject() {
159
                        if( this.obj == null ) {
160
                                try {
161
                                        updateObjectInReference(this);
162
                                } catch (PersistenceException e) {
163
                                        throw new PersistenceRuntimeException(e);
164
                                }
165
                        }
166
                        return this.obj;
167
                }
168
                
169
                public PersistentState getState() {
170
                        return this.state;
171
                }
172
                
173
                public PersistentIdentifier getId() {
174
                        return this.id;
175
                }
176

    
177
                protected void update(Object object) {
178
                        this.obj = object;
179
                }
180
                
181
                public boolean equals(Object obj) {
182
                        if (!(obj instanceof ContextValue)) {
183
                                return false;
184
                        }
185
                        return id.equals(((ContextValue) obj).id);
186
                }
187

    
188
                public int hashCode() {
189
                        return id.hashCode();
190
                }
191
                
192
                public String toString() {
193
                        String idStr = id == null ? "null" : id.toString();
194
                        return getClass().getName().concat(": id = ").concat(idStr);
195
                }
196

    
197
                public int compareTo(Object arg0) {
198
                        if (!(obj instanceof ContextValue)) {
199
                                return -1;
200
                        }
201
                        return ((DefaultPersistentIdentifier)id).compareTo(((ContextValue) obj).id);
202
                }
203

    
204
        }
205

    
206
        public PersistentIdentifier getNewIdentifier() {
207
                return new DefaultPersistentIdentifier(String.valueOf( IdentifiersCounter++));
208
        }
209
        
210
        public PersistentIdentifier getIdentifier(String id) throws PersistenceException {
211
                Iterator it = this.idToReference.values().iterator();
212
                while( it.hasNext() ) {
213
                        ContextValue value = (ContextValue) it.next();
214
                        if( ((DefaultPersistentIdentifier)(value.getId())).hasValue(id) ) {
215
                                return value.getId();
216
                        }
217
                }
218
                return new DefaultPersistentIdentifier(id);
219
        }
220
        
221
        public ObjectReference add(PersistentIdentifier id) throws PersistenceException  {
222
                this.validated = false;
223
                ContextValue value = (ContextValue) idToReference.get(id);
224
                if (value == null ) {
225
                        value = new ContextValue(id, null);
226
                        idToReference.put(value.getId(), value);
227
                }
228
                return value;
229
        }
230
        
231
        public ObjectReference add(PersistentState state, Object obj) throws PersistenceException  {
232
                this.validated = false;
233
                PersistentIdentifier id = ((PersistentStateServices)state).getId();
234
                ContextValue value = (ContextValue) idToReference.get(id);
235
                if (value == null ) {
236
                        value = new ContextValue( id, state);
237
                        idToReference.put(value.getId(), value);
238
                }
239
                if( value.getState() == null ) {
240
                        value.state = state;
241
                }
242
                if( obj != null ) {
243
                        value.update(obj);
244
                        objToReference.put(obj,value);
245
                }
246
                return value;
247
        }
248
        
249
        public ObjectReference get(PersistentState state) throws PersistenceException {
250
                PersistentIdentifier id = ((PersistentStateServices)state).getId();
251
                ContextValue ref = (ContextValue) idToReference.get(id);
252
                if (ref == null ) {
253
                        ref = new ContextValue(id, state);
254
                        idToReference.put(id, ref);
255
                }
256
                return ref;
257
        }
258

    
259
        public ObjectReference get(PersistentIdentifier id) {
260
                ContextValue value = (ContextValue) idToReference.get(id);
261
                return value;
262
        }
263
        
264
        public ObjectReference get(Object obj) {
265
                return (ContextValue) objToReference.get(obj);
266
        }
267
        
268
        private void updateObjectInReference(ContextValue ref) throws PersistenceException {
269
                /*
270
                 * Note: this method is used by the inner class Reference.
271
                 */
272
                PersistentStateServices state = (PersistentStateServices) ref.getState();
273
                PersistenceFactory factory = manager.getFactories().get(state);
274
                
275
                if (factory == null) {
276
                        /*
277
                         * This happens if persistence refers to objects
278
                         * of a missing plugin (example: persistence
279
                         * has data about oracle connections but we dont have
280
                         * the oracle plugin in the current execution)
281
                         */
282
                        throw new PersistenceClassNotRegistered(ref.getClass());
283
                }
284
                
285

    
286
                // This can be done in two step to avoid cyclic references
287
                state.setFactory(factory);
288
                ref.update( factory.createFromState(state) );
289
                factory.loadFromState(state, ref.getObject());
290
                
291
                objToReference.put(ref.getObject(), ref);
292
        }
293
        
294
        public void update(ObjectReference ref) throws PersistenceException {
295
                this.validated = false;
296
                this.updateObjectInReference((ContextValue) ref);
297
        }
298

    
299
        private void updateAll() throws PersistenceException {
300
                Iterator it = idToReference.entrySet().iterator();
301
                while ( it.hasNext() ) {
302
                        ContextValue ref = (ContextValue) ((Entry) it.next()).getValue();
303
                        this.update(ref);
304
                }
305
        }
306

    
307
        public void clear() {
308
                this.validated = false;
309
                Iterator it = idToReference.entrySet().iterator();
310
                while ( it.hasNext() ) {
311
                        ContextValue ref = (ContextValue) ((Entry) it.next()).getValue();
312
                        ref.update(null);
313
                }
314
        }
315

    
316
        public Iterator iterator() {
317
                final class StatesIterator implements Iterator {
318
                        private Iterator referenceIterator;
319

    
320
                        StatesIterator(Map idToReference) {
321
                                this.referenceIterator = idToReference.entrySet().iterator();
322
                        }
323
                        
324
//                        StatesIterator(Map idToReference) {
325
//                                List values = new ArrayList(); 
326
//                                values.addAll(idToReference.values());
327
//                                Collections.sort(values);
328
//                                this.referenceIterator = values.iterator();
329
//                        }
330
                        
331
                        public boolean hasNext() {
332
                                return referenceIterator.hasNext();
333
                        }
334
                        public Object next() {
335
                                ContextValue ref = (ContextValue) ((Entry) referenceIterator.next()).getValue();
336
//                                ContextValue ref = (ContextValue) referenceIterator.next();
337
                                return ref.getState();
338
                        }
339
                        public void remove() {
340
                                throw new UnsupportedOperationException();
341
                        }
342
                }
343
                
344
                return new StatesIterator(idToReference);
345
        }
346

    
347
        public PersistentState getState(Integer id)
348
                        throws PersistenceException {
349
                ContextValue ref = (ContextValue) this.get(id);
350
                if (ref == null) {
351
                        throw new PersistenceIDNotLoadedException(id);
352
                }
353
                return ref.getState();
354
        }
355

    
356
        public PersistentState getState(Object obj)
357
                        throws PersistenceException {
358
                ContextValue ref = (ContextValue) this.get(obj);
359
                if (ref == null) {
360
                        return null;
361
                }
362
                return ref.getState();
363
        }
364

    
365
        public Object getObject(Integer id) throws PersistenceException {
366
                ContextValue ref = (ContextValue) this.get(id);
367
                if (ref == null) {
368
                        throw new PersistenceIDNotLoadedException(id);
369
                }
370
                return ref.getObject();
371
        }
372

    
373
        public PersistentIdentifier getId(Object obj) throws PersistenceException {
374
                ContextValue ref = (ContextValue) this.get(obj);
375
                if( ref != null ) {
376
                        return ref.getId();
377
                }
378
                this.updateAll();
379
                ref = (ContextValue) this.get(obj);
380
                if (ref == null) {
381
                        throw new ObjectNotFoundException();
382
                }
383
                return ref.getId();                
384
        }
385

    
386

    
387
        public void setRootId(PersistentIdentifier id) {
388
                this.rootId = id;
389
        }
390

    
391
        public ObjectReference getRoot() throws PersistenceException {
392
                ObjectReference root = this.get(this.rootId); 
393
                return  root;
394
        }
395

    
396
        public void setCollectErrors(boolean collectErrors) {
397
                this.collectErrors = collectErrors;
398
        }
399

    
400
        public boolean getCollectErrors() {
401
                return this.collectErrors;
402
        }
403

    
404
        public void addError(Throwable cause) {
405
                if( this.errors == null ) {
406
                        this.errors = new PersistenceException();
407
                }
408
                this.errors.add(cause);
409
        }
410

    
411
        public PersistenceException getErrors() {
412
                return this.errors;
413
        }
414

    
415
        public void validate(int mode) throws PersistenceValidateExceptions {
416
                if( this.validated ) {
417
                        return;
418
                }
419
                List exceptions = new ArrayList();
420

    
421
                Iterator it = this.iterator();
422
                while( it.hasNext() ) {
423
                        PersistentState astate = (PersistentState) it.next();
424
                        try {
425
                                this.manager.validate(astate,mode);
426
                        } catch(Exception e) {
427
                                exceptions.add(e);
428
                        }
429
                }
430

    
431
                this.validated=true;
432
                if (exceptions.size() > 0) {
433
                        throw  new PersistenceValidateExceptions(exceptions);
434
                }                
435
        }
436
}