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

History | View | Annotate | Download (12.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 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
                    String classname = "";
283
                    if (state == null) {
284
                        classname = "[State is null]";
285
                    } else {
286
                        classname = state.getTheClassName();
287
                        if (classname == null) {
288
                            classname = "[Null]";
289
                        }
290
                    }
291
                        throw new PersistenceClassNotRegistered(classname);
292
                }
293
                
294

    
295
                // This can be done in two step to avoid cyclic references
296
                state.setFactory(factory);
297
                ref.update( factory.createFromState(state) );
298
                factory.loadFromState(state, ref.getObject());
299
                
300
                objToReference.put(ref.getObject(), ref);
301
        }
302
        
303
        public void update(ObjectReference ref) throws PersistenceException {
304
                this.validated = false;
305
                this.updateObjectInReference((ContextValue) ref);
306
        }
307

    
308
        private void updateAll() throws PersistenceException {
309
                Iterator it = idToReference.entrySet().iterator();
310
                while ( it.hasNext() ) {
311
                        ContextValue ref = (ContextValue) ((Entry) it.next()).getValue();
312
                        this.update(ref);
313
                }
314
        }
315

    
316
        public void clear() {
317
                this.validated = false;
318
                Iterator it = idToReference.entrySet().iterator();
319
                while ( it.hasNext() ) {
320
                        ContextValue ref = (ContextValue) ((Entry) it.next()).getValue();
321
                        ref.update(null);
322
                }
323
        }
324

    
325
        public Iterator iterator() {
326
                final class StatesIterator implements Iterator {
327
                        private Iterator referenceIterator;
328

    
329
                        StatesIterator(Map idToReference) {
330
                                this.referenceIterator = idToReference.entrySet().iterator();
331
                        }
332
                        
333
//                        StatesIterator(Map idToReference) {
334
//                                List values = new ArrayList(); 
335
//                                values.addAll(idToReference.values());
336
//                                Collections.sort(values);
337
//                                this.referenceIterator = values.iterator();
338
//                        }
339
                        
340
                        public boolean hasNext() {
341
                                return referenceIterator.hasNext();
342
                        }
343
                        public Object next() {
344
                                ContextValue ref = (ContextValue) ((Entry) referenceIterator.next()).getValue();
345
//                                ContextValue ref = (ContextValue) referenceIterator.next();
346
                                return ref.getState();
347
                        }
348
                        public void remove() {
349
                                throw new UnsupportedOperationException();
350
                        }
351
                }
352
                
353
                return new StatesIterator(idToReference);
354
        }
355

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

    
365
        public PersistentState getState(Object obj)
366
                        throws PersistenceException {
367
                ContextValue ref = (ContextValue) this.get(obj);
368
                if (ref == null) {
369
                        return null;
370
                }
371
                return ref.getState();
372
        }
373

    
374
        public Object getObject(Integer id) throws PersistenceException {
375
                ContextValue ref = (ContextValue) this.get(id);
376
                if (ref == null) {
377
                        throw new PersistenceIDNotLoadedException(id);
378
                }
379
                return ref.getObject();
380
        }
381

    
382
        public PersistentIdentifier getId(Object obj) throws PersistenceException {
383
                ContextValue ref = (ContextValue) this.get(obj);
384
                if( ref != null ) {
385
                        return ref.getId();
386
                }
387
                this.updateAll();
388
                ref = (ContextValue) this.get(obj);
389
                if (ref == null) {
390
                        throw new ObjectNotFoundException();
391
                }
392
                return ref.getId();                
393
        }
394

    
395

    
396
        public void setRootId(PersistentIdentifier id) {
397
                this.rootId = id;
398
        }
399

    
400
        public ObjectReference getRoot() throws PersistenceException {
401
                ObjectReference root = this.get(this.rootId); 
402
                return  root;
403
        }
404

    
405
        public void setCollectErrors(boolean collectErrors) {
406
                this.collectErrors = collectErrors;
407
        }
408

    
409
        public boolean getCollectErrors() {
410
                return this.collectErrors;
411
        }
412

    
413
        public void addError(Throwable cause) {
414
                if( this.errors == null ) {
415
                        this.errors = new PersistenceException();
416
                }
417
                this.errors.add(cause);
418
        }
419

    
420
        public PersistenceException getErrors() {
421
                return this.errors;
422
        }
423

    
424
        public void validate(int mode) throws PersistenceValidateExceptions {
425
                if( this.validated ) {
426
                        return;
427
                }
428
                List exceptions = new ArrayList();
429

    
430
                Iterator it = this.iterator();
431
                while( it.hasNext() ) {
432
                        PersistentState astate = (PersistentState) it.next();
433
                        try {
434
                                this.manager.validate(astate,mode);
435
                        } catch(Exception e) {
436
                                exceptions.add(e);
437
                        }
438
                }
439

    
440
                this.validated=true;
441
                if (exceptions.size() > 0) {
442
                        throw  new PersistenceValidateExceptions(exceptions);
443
                }                
444
        }
445
}