Statistics
| Revision:

gvsig-tools / org.gvsig.tools / library / trunk / org.gvsig.tools / org.gvsig.tools.lib / src / main / java / org / gvsig / tools / persistence / impl / AbstractPersistenceManager.java @ 2145

History | View | Annotate | Download (19 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
package org.gvsig.tools.persistence.impl;
25

    
26
import java.io.IOException;
27
import java.io.InputStream;
28
import java.io.OutputStream;
29
import java.util.ArrayList;
30
import java.util.Collections;
31
import java.util.Iterator;
32
import java.util.List;
33
import java.util.Map;
34
import java.util.Set;
35
import org.apache.commons.lang3.mutable.MutableInt;
36

    
37
import org.gvsig.tools.ToolsLocator;
38
import org.gvsig.tools.dynobject.DynClass;
39
import org.gvsig.tools.dynobject.DynField;
40
import org.gvsig.tools.dynobject.DynObject;
41
import org.gvsig.tools.dynobject.DynObjectManager;
42
import org.gvsig.tools.dynobject.DynStruct;
43
import org.gvsig.tools.dynobject.exception.DynFieldNotFoundException;
44
import org.gvsig.tools.dynobject.exception.DynMethodException;
45
import org.gvsig.tools.dynobject.exception.DynObjectValidateException;
46
import org.gvsig.tools.dynobject.impl.DefaultDynClassName;
47
import org.gvsig.tools.persistence.PersistenceFactory;
48
import org.gvsig.tools.persistence.PersistenceManager;
49
import org.gvsig.tools.persistence.PersistentState;
50
import org.gvsig.tools.persistence.exception.AddDefinitionException;
51
import org.gvsig.tools.persistence.exception.DuplicatePersistentDefinitionException;
52
import org.gvsig.tools.persistence.exception.FieldNotDeclaredException;
53
import org.gvsig.tools.persistence.exception.PersistenceClassNotRegistered;
54
import org.gvsig.tools.persistence.exception.PersistenceCreateException;
55
import org.gvsig.tools.persistence.exception.PersistenceException;
56
import org.gvsig.tools.persistence.exception.PersistenceTypeNotSupportedException;
57
import org.gvsig.tools.persistence.exception.PersistenceValidateExceptions;
58
import org.gvsig.tools.persistence.exception.PersistenceWriteExeption;
59
import org.gvsig.tools.persistence.impl.exception.CantFindDefinitionInStreamException;
60
import org.gvsig.tools.persistence.impl.exception.PersistenceDomainNotRegisterdException;
61
import org.gvsig.tools.persistence.impl.exception.PersistenceIllegalStateTheClassNameNotSetException;
62
import org.gvsig.tools.persistence.impl.exception.PersistenceInvalidValidateModeException;
63
import org.gvsig.tools.persistence.impl.exception.PersistenceValidateMissingDefinitionException;
64
import org.gvsig.tools.persistence.spi.PersistenceManagerServices;
65
import org.gvsig.tools.persistence.spi.PersistentContextServices;
66
import org.gvsig.tools.persistence.spi.PersistentContextServices.ObjectReference;
67
import org.gvsig.tools.persistence.spi.PersistentStateServices;
68
import org.slf4j.Logger;
69
import org.slf4j.LoggerFactory;
70
import org.xmlpull.v1.XmlPullParserException;
71

    
72

    
73
public abstract  class AbstractPersistenceManager implements
74
                PersistenceManagerServices {
75

    
76
        private static final Logger LOG = LoggerFactory.getLogger(AbstractPersistenceManager.class);
77
        
78
        private DefaultFactories factories;
79
        private Domains domainsURL;
80
        private int autoValidationMode = PersistenceManager.DISABLED;
81
  private MutableInt globalReferenceCounter;
82
        
83

    
84
        protected AbstractPersistenceManager() {
85
                domainsURL = new Domains();
86
                factories = new DefaultFactories();
87
    globalReferenceCounter = new MutableInt(0);
88
        }
89

    
90
        public void addAlias(String name, Class aClass)
91
                        throws PersistenceClassNotRegistered {
92
                PersistenceFactory factory = this.factories.get(aClass.getName());
93
                this.factories.add(factory, aClass.getName());
94
        }
95

    
96
        public Factories getFactories() {
97
                return this.factories;
98
        }
99

    
100
  @Override
101
        public PersistentContextServices getNewContext() {
102
                return new DefaultPersistentContext(this, this.globalReferenceCounter);
103
        }        
104
  
105
  @Override
106
        public PersistentContextServices getNewContext(MutableInt referenceCounter) {
107
                return new DefaultPersistentContext(this, referenceCounter);
108
        }
109
        
110
        public Object create(PersistentState state) throws PersistenceException {
111
                String className = state.getTheClassName();
112
                if (className == null) {
113
                        throw new PersistenceIllegalStateTheClassNameNotSetException() ;
114
                }
115
                PersistentContextServices context = getContext(state);
116
                ObjectReference ref = context.get(state);
117
                return ref.getObject();
118
        }
119

    
120
        public Object getObject(InputStream is) {
121
                Object obj = null;
122
                PersistentState state = null;
123
                String theClassName = null;
124
                try {
125
                        state = this.loadState(is);
126
                        theClassName = state.getTheClassName();
127
                        obj = this.create(state);
128
                } catch (PersistenceException e) {
129
                        throw new PersistenceCreateException(theClassName,e);
130
                }
131
                return obj;
132
        }
133
        
134
        public void putObject(OutputStream os, Object obj) {
135
                PersistentState state;
136
                try {
137
                        state = this.getState(obj);
138
                        this.saveState(state, os);
139
                } catch (PersistenceException e) {
140
                        throw new PersistenceWriteExeption(e);
141
                }
142
        }
143
        
144
        public DynStruct getDefinition(Class persistentClass) {
145
                return getDefinition(persistentClass.getName());
146
        }
147

    
148
        public DynStruct getDefinition(String className) {
149
                PersistenceFactory factory = this.factories.get(className);
150
                if( factory== null ) {
151
                        return null;
152
                }
153
                return factory.getDefinition(className);
154
        }
155
        
156
        public DynStruct getDynObjectDefinition(String className) {
157
                DefaultDynClassName dynClassName = new DefaultDynClassName(PERSISTENCE_DYNOBJECT_NAMESPACE, className);
158
                PersistenceFactory factory = this.factories.get(dynClassName.getFullName());
159
                if( factory== null ) {
160
                        return null;
161
                }
162
                return factory.getDefinition(dynClassName.getFullName());
163
        }
164

    
165
        private PersistentContextServices getContext(PersistentState state) {
166
                return (PersistentContextServices) state.getContext();
167
        }
168

    
169
        public void validate(PersistentState state, int mode)
170
                        throws PersistenceValidateExceptions {
171

    
172
                if (mode == PersistenceManager.DISABLED){
173
                        return;
174
                }
175

    
176
                List exceptions = new ArrayList();
177
                DynStruct definition = state.getDefinition();
178
                if( definition == null ) {
179
                        if( mode == PersistenceManager.MANDATORY ) {
180
                                exceptions.add(new PersistenceValidateMissingDefinitionException(state.getTheClassName()));
181
                                throw  new PersistenceValidateExceptions(state.getTheClassName(), exceptions);
182
                        } else {
183
                                return;
184
                        }
185
                }
186

    
187
                PersistentStateServices state2 = (PersistentStateServices) state;
188
                Iterator it = state2.getNames();
189
                while( it.hasNext() ) {
190
                        String name = (String) it.next();
191
                        DynField field = definition.getDynField(name);
192
                        if(  field == null ) {
193
                                exceptions.add( new FieldNotDeclaredException(name,state.getTheClassName()));
194
                        } 
195
                }
196
                DynObjectToPersistentStateAdapter dynAdapter = new DynObjectToPersistentStateAdapter(state, definition);                        
197
                try {
198
                        definition.validate(dynAdapter);
199
                } catch (DynObjectValidateException e) {
200
                        exceptions.add(e);
201
                }
202
                if (exceptions.size() > 0) {
203
                        throw  new PersistenceValidateExceptions(state.getTheClassName(), exceptions);
204
                }
205
        }
206

    
207
        public void validateAll(PersistentState state, int mode)
208
                        throws PersistenceValidateExceptions {
209

    
210
                if (mode == PersistenceManager.DISABLED){
211
                        return;
212
                }
213
                PersistentContextServices context =  getContext(state);
214
                context.validate(this.autoValidationMode);
215
        }
216

    
217
        private class DynObjectToPersistentStateAdapter implements DynObject {
218
                private PersistentState state;
219
                private DynStruct struct;
220

    
221
//                DynObjectToPersistentStateAdapter() {
222
//                        this.state = null;
223
//                        this.struct = null;
224
//                }
225
                DynObjectToPersistentStateAdapter(PersistentState state, DynStruct struct) {
226
                        this.state = state;
227
                        this.struct = struct;
228
                }
229

    
230
//                public void setData(PersistentState state, DynStruct struct) {
231
//                        this.state = state;
232
//                        this.struct = struct;
233
//                }
234

    
235
                public void delegate(DynObject dynObject) {
236
                        // Nothing to do
237

    
238
                }
239

    
240
                public DynClass getDynClass() {
241
                        // Nothing to do
242
                        return null;
243
                }
244

    
245
                public Object getDynValue(String name) throws DynFieldNotFoundException {
246
                        try {
247
                                return state.get(name);
248
                        } catch (PersistenceException e) {
249
                                throw new DynFieldNotFoundException(name, struct.getName());
250
                        }
251
                }
252

    
253
                public boolean hasDynValue(String name) {
254
                        return state.hasValue(name);
255
                }
256

    
257
                public void implement(DynClass dynClass) {
258
                        // Nothing to do
259
                }
260

    
261
                public Object invokeDynMethod(String name, Object[] args)
262
                                throws DynMethodException {
263
                        // Nothing to do
264
                        return null;
265
                }
266

    
267
                public Object invokeDynMethod(int code, Object[] args)
268
                                throws DynMethodException {
269
                        // Nothing to do
270
                        return null;
271
                }
272

    
273
                public void setDynValue(String name, Object value)
274
                                throws DynFieldNotFoundException {
275
                        // Nothing to do
276
                }
277
                public void clear() {
278
                        // Nothing to do
279
                }
280

    
281
        }
282

    
283
        public int getAutoValidation() {
284
                return autoValidationMode;
285
        }
286

    
287
        public void setAutoValidation(int validationMode) throws PersistenceException {
288
                switch (validationMode) {
289
                case DISABLED:
290
                case MANDATORY:
291
                case MANDATORY_IF_DECLARED:
292
                        autoValidationMode = validationMode;
293
                        break;
294
                default:
295
                        throw new PersistenceInvalidValidateModeException(validationMode);
296
                }
297
        }
298

    
299
  @Override
300
        public PersistentState getState(Object obj)
301
                        throws PersistenceException, PersistenceValidateExceptions, PersistenceTypeNotSupportedException {
302
                return this.getState(obj, false, this.globalReferenceCounter);
303
        }
304

    
305
  @Override
306
        public PersistentState getState(Object obj, boolean collectAllErrors)
307
                        throws PersistenceException {
308
    return this.getState(obj, collectAllErrors, globalReferenceCounter);
309
  }
310
  
311
  @Override
312
        public PersistentState getState(Object obj, boolean collectAllErrors, MutableInt referenceCounter)
313
                        throws PersistenceException {
314
                PersistentStateServices state = null;
315
                if( collectAllErrors ) {
316
                        PersistentContextServices context = this.getNewContext(referenceCounter);
317
                        context.setCollectErrors(true);
318
                        try {
319
                                state = createState(obj, context);
320
                                context.setRootId(state.getId());
321
                                if (this.autoValidationMode != PersistenceManager.DISABLED){
322
                                        context.validate(this.autoValidationMode);
323
                                }
324
                        } catch(PersistenceException ex) {
325
                                context.addError(ex);
326
                        }
327
                } else {
328
                        PersistentContextServices context = this.getNewContext(referenceCounter);
329
                        state = createState(obj, context);
330
                        context.setRootId(state.getId());
331
                        this.validateAll(state, this.autoValidationMode);
332
                }
333
                return state;
334
        }
335
        
336
        public PersistentStateServices createState(Object object, PersistentContextServices context) throws PersistenceException {
337

    
338
                PersistentStateServices state = createPersistentState(context);
339
                state.setTheClassName(object.getClass().getName());
340
                
341
                context.add(state, object);
342
                
343
                PersistenceFactory factory = this.factories.get(object);
344
                if (factory == null) {
345
                        throw new PersistenceTypeNotSupportedException(object
346
                                        .getClass());
347
                }
348
                state.setFactory(factory);
349
                state.setTheClassName(factory.getManagedClassName(object));
350
                factory.saveToState(state, object);
351
                return state;
352
        }
353

    
354
        public List getWrappedList(List list, PersistentContextServices context) {
355
                return new DelegatedList(list, this, context);
356
        }
357

    
358
        public Map getWrappedMap(Map map, PersistentContextServices context) {
359
                return new DelegatedMap(map, this, context);
360
        }
361

    
362
        public Set getWrappedSet(Set set, PersistentContextServices context) {
363
                return new DelegatedSet(set, this, context);
364
        }
365

    
366

    
367
        public Map getDomains() {
368
                return Collections.unmodifiableMap(domainsURL);
369
        }
370

    
371
        public List getDomainDefinitions(String domainName) {
372
                if (!domainsURL.containsKey(domainName)) {
373
                        throw new PersistenceDomainNotRegisterdException(domainName);
374
                }
375
                List definitions = new ArrayList();
376
                Iterator it = this.factories.iterator();
377
                while( it.hasNext() ) {
378
                        PersistenceFactory factory = (PersistenceFactory) it.next();
379
                        if( factory.getDomainName().equals(domainName)) {
380
                                List factDefinitions = factory.getDefinitions();
381
                                if(factDefinitions != null){
382
                                        definitions.addAll(factDefinitions);
383
                                }
384
                        }
385
                }
386
                return definitions;
387
        }
388

    
389
                        
390
        public DynStruct addDefinition(Class theClass, String name, String description,
391
                        String domainName, String domainUrl) {
392
                DynObjectManager dynman = ToolsLocator.getDynObjectManager();
393

    
394
                DynClass definition = dynman.createDynClass(PERSISTENCE_NAMESPACE, name, description);
395
                return addDefinition(theClass, definition, domainName, domainUrl);
396
        }
397

    
398
        public DynStruct addDefinition(Class theClass, String name, InputStream definitions, ClassLoader loader,
399
                        String domainName, String domainUrl) {
400
                DynObjectManager dynman = ToolsLocator.getDynObjectManager();
401
                Map x;
402
                try {
403
                        x = dynman.importDynClassDefinitions(definitions, loader, PersistenceManager.PERSISTENCE_NAMESPACE);
404
                } catch (XmlPullParserException e) {
405
                        throw new AddDefinitionException(e);
406
                } catch (IOException e) {
407
                        throw new AddDefinitionException(e);
408
                }
409
                DynClass definition = (DynClass) x.get(name);
410
                if( definition == null ) {
411
                        throw new CantFindDefinitionInStreamException(name, getKeys(x));
412
                }
413
                return addDefinition(theClass, definition, domainName, domainUrl);
414
        }
415

    
416
        public DynStruct updateDefinition(Class theClass, String name, InputStream definitions, ClassLoader loader,
417
                        String domainName, String domainUrl) {
418
                DynObjectManager dynman = ToolsLocator.getDynObjectManager();
419
                Map x;
420
                try {
421
                        x = dynman.importDynClassDefinitions(definitions, loader, PersistenceManager.PERSISTENCE_NAMESPACE);
422
                } catch (XmlPullParserException e) {
423
                        throw new AddDefinitionException(e);
424
                } catch (IOException e) {
425
                        throw new AddDefinitionException(e);
426
                }
427
                DynClass definition = (DynClass) x.get(name);
428
                if( definition == null ) {
429
                        throw new CantFindDefinitionInStreamException(name, getKeys(x));
430
                }
431
                definition.setNamespace(PERSISTENCE_DYNOBJECT_NAMESPACE);
432
                dynman.remove(definition);
433
                return addDefinition(theClass, definition, domainName, domainUrl);
434
        }
435

    
436
        private String getKeys(Map theMap) {
437
                List l = new ArrayList(theMap.keySet());
438
                return l.toString();
439
        }
440
        
441

    
442
        public DynStruct addDefinition(Class theClass, String name, Map definitions,
443
                        String domainName, String domainUrl) {
444
                DynClass definition = (DynClass) definitions.get(name);
445
                return addDefinition(theClass, definition, domainName, domainUrl);
446
                
447
        }
448

    
449
        protected  DynStruct addDefinition(Class theClass, DynClass definition,
450
                String domainName, String domainUrl) {
451
                if(theClass == DynObject.class){
452
                        return this.addDefinition(definition, domainName, domainUrl);
453
                }
454
                DynObjectManager dynman = ToolsLocator.getDynObjectManager();
455
                
456
                if(theClass.equals(DynObject.class)){
457
                        definition.setNamespace(PERSISTENCE_DYNOBJECT_NAMESPACE);
458
                } else {
459
                        definition.setNamespace(PERSISTENCE_NAMESPACE);
460
                }
461
                if( dynman.get(definition.getNamespace(),definition.getName())!=null ) {
462
                        throw new DuplicatePersistentDefinitionException(definition.getName());
463
                }
464
                dynman.add(definition);
465
                
466
                PersistenceFactory factory = new SimplePersistenceFactory(
467
                                theClass, 
468
                                definition,
469
                                domainName, 
470
                                domainUrl
471
                        );
472
                this.factories.add(factory);
473
                this.domainsURL.add(factory.getDomainName(), factory.getDomainURL());
474
                LOG.trace("Add persistence definition {}.", new Object[] { definition.getFullName() });
475
                return definition;
476
        }
477
        
478
        public DynStruct addDefinition(DynStruct definition, String domainName,
479
                        String domainUrl) throws AddDefinitionException {
480
                DynObjectManager dynman = ToolsLocator.getDynObjectManager();
481
                
482
                definition.setNamespace(PERSISTENCE_DYNOBJECT_NAMESPACE);
483
                if( dynman.get(definition.getNamespace(),definition.getName())!=null ) {
484
                        throw new DuplicatePersistentDefinitionException(definition.getFullName());
485
                }
486
                dynman.add((DynClass) definition);
487
                
488
                PersistenceFactory factory = this.factories.get(definition.getFullName());
489
                this.domainsURL.add(factory.getDomainName(), factory.getDomainURL());
490
                LOG.trace("Add persistence definition {}.", new Object[] { definition.getFullName() });
491
                return definition;
492
        }
493
        
494
        public void registerFactory(PersistenceFactory factory) {
495
                this.factories.add(factory);
496
                this.domainsURL.add(factory.getDomainName(), factory.getDomainURL());
497
                LOG.trace("Add persistence factory {}.", new Object[] { factory.getClass().getName() });
498
        }
499

    
500
        public void unregisterClass(Class theClass) {
501
                PersistenceFactory factory = this.factories.get(theClass.getName());
502
                if( factory == null ) {
503
                        return ;
504
                }
505
                DynObjectManager dynman = ToolsLocator.getDynObjectManager();
506
                DynStruct definition = factory.getDefinition(theClass.getName());
507

    
508
                dynman.remove(definition);
509
                this.factories.remove( factory);
510
                this.domainsURL.remove(factory.getDomainName());
511
        }
512

    
513
        public void unregisterClass(String name) {
514
                PersistenceFactory factory = this.factories.get(name);
515
                if( factory == null ) {
516
                        return ;
517
                }
518
                DynObjectManager dynman = ToolsLocator.getDynObjectManager();
519

    
520
                this.factories.remove( factory);
521
                this.domainsURL.remove(factory.getDomainName());
522

    
523
                DynStruct definition = factory.getDefinition(name);
524
                dynman.remove(definition);
525
        }
526

    
527
        public void unregisterFactory(PersistenceFactory factory) {
528
                DynObjectManager dynman = ToolsLocator.getDynObjectManager();
529

    
530
                this.factories.remove(factory);
531
                this.domainsURL.remove(factory.getDomainName());
532

    
533
                List definitions = factory.getDefinitions();
534
                if (definitions != null){
535
                        Iterator it = definitions.iterator();
536
                        while( it.hasNext() ) {
537
                                DynStruct definition = (DynStruct) it.next();
538
                                dynman.remove(definition);
539
                        }
540
                }
541
        }
542
        
543
        public PersistentStateServices createPersistentState(        PersistentContextServices context) {
544
                return this.createPersistentState(context, context.getNewIdentifier());
545
        }
546

    
547
    @Override
548
    public PersistentState loadState(InputStream in) throws PersistenceException {
549
        return this.loadState(in, this.getNewContext());
550
    }
551

    
552
    public void addDefinition(Class theClass, String name, String resourceName) {
553
        if( this.getDefinition(name) == null ) {
554
            InputStream resource = theClass.getResourceAsStream(resourceName);
555
            if( resource == null ) {
556
                throw new IllegalArgumentException("Resource '" + resourceName + "' not found as a resource of '" + theClass.getName() + "'.");
557
            }
558
            this.addDefinition(
559
                theClass,
560
                name,
561
                resource,
562
                theClass.getClassLoader(),
563
                null,
564
                null
565
            );
566
        }
567
    }
568

    
569
    public void addDefinition(Class theClass, String name, InputStream resource) {
570
        if( this.getDefinition(name) == null ) {
571
            if( resource == null ) {
572
                throw new IllegalArgumentException("resource null not allowed.");
573
            }
574
            this.addDefinition(
575
                theClass,
576
                name,
577
                resource,
578
                theClass.getClassLoader(),
579
                null,
580
                null
581
            );
582
        }
583
    }
584
        
585

    
586
}