Fixed some issues with database handling and fixed a bug in LocationService.
[cdmlib.git] / cdmlib-persistence / src / main / java / eu / etaxonomy / cdm / database / PersistentTermInitializer.java
1 /**
2 * Copyright (C) 2007 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
5 *
6 * The contents of this file are subject to the Mozilla Public License Version 1.1
7 * See LICENSE.TXT at the top of this package for the full license terms.
8 */
9
10 package eu.etaxonomy.cdm.database;
11
12 import java.util.HashMap;
13 import java.util.Map;
14 import java.util.UUID;
15
16 import javax.annotation.PostConstruct;
17
18 import org.apache.log4j.Logger;
19 import org.hibernate.Hibernate;
20 import org.springframework.beans.factory.annotation.Autowired;
21 import org.springframework.stereotype.Component;
22 import org.springframework.transaction.PlatformTransactionManager;
23 import org.springframework.transaction.TransactionDefinition;
24 import org.springframework.transaction.TransactionStatus;
25 import org.springframework.transaction.support.DefaultTransactionDefinition;
26
27 import eu.etaxonomy.cdm.model.common.DefaultTermInitializer;
28 import eu.etaxonomy.cdm.model.common.DefinedTermBase;
29 import eu.etaxonomy.cdm.model.common.TermVocabulary;
30 import eu.etaxonomy.cdm.model.common.init.TermLoader;
31 import eu.etaxonomy.cdm.persistence.dao.common.IDefinedTermDao;
32 import eu.etaxonomy.cdm.persistence.dao.common.ITermVocabularyDao;
33
34 /**
35 * Spring bean class to initialize the {@link IVocabularyStore IVocabularyStore}.
36 * To initialize the store the {@link TermLoader TermLoader} and the {@link IVocabularyStore IVocabularyStore}
37 * are injected via spring and the initializeTerms method is called as an init-method (@PostConstruct).
38
39 * @author a.mueller
40 */
41
42 @Component
43 public class PersistentTermInitializer extends DefaultTermInitializer {
44 private static final Logger logger = Logger.getLogger(PersistentTermInitializer.class);
45
46 private boolean omit = false;
47 protected ITermVocabularyDao vocabularyDao;
48
49 protected PlatformTransactionManager transactionManager;
50 protected DefaultTransactionDefinition txDefinition = new DefaultTransactionDefinition();
51
52 public PersistentTermInitializer() {
53 txDefinition.setName("PersistentTermInitializer.initialize()");
54 txDefinition.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
55 }
56
57 public void setOmit(boolean omit) {
58 this.omit = omit;
59 }
60
61 @Autowired
62 public void setVocabularyDao(ITermVocabularyDao vocabularyDao) {
63 this.vocabularyDao = vocabularyDao;
64 }
65
66 @Autowired
67 public void setTransactionManager(PlatformTransactionManager transactionManager) {
68 this.transactionManager = transactionManager;
69 }
70
71 /*
72 * After a bit of head-scratching I found section 3.5.1.3. in the current spring
73 * reference manual - @PostConstruct / afterPropertiesSet() is called
74 * immediatly after the bean is constructed, prior to any AOP interceptors being
75 * wrapped round the bean. Thus, we have to use programmatic transactions, not
76 * annotations or pointcuts.
77 */
78 @PostConstruct
79 @Override
80 public void initialize(){
81 logger.debug("PersistentTermInitializer initialize start ...");
82 if (omit){
83 logger.info("PersistentTermInitializer.omit == true, returning without initializing terms");
84 return;
85 } else {
86 Map<UUID,DefinedTermBase> terms = new HashMap<UUID,DefinedTermBase>();
87 logger.info("PersistentTermInitializer.omit == false, initializing " + classesToInitialize.length + " term classes");
88 for(Class clazz : classesToInitialize) {
89 UUID vocabularyUuid = firstPass(clazz,terms);
90 secondPass(clazz,vocabularyUuid,terms);
91 }
92
93 }
94 logger.debug("PersistentTermInitializer initialize end ...");
95 }
96
97 protected void secondPass(Class clazz, UUID vocabularyUuid,Map<UUID,DefinedTermBase> terms) {
98 TransactionStatus txStatus = transactionManager.getTransaction(txDefinition);
99 logger.info("Loading vocabulary for class " + clazz.getSimpleName() + " with uuid " + vocabularyUuid );
100
101 TermVocabulary persistedVocabulary = vocabularyDao.findByUuid(vocabularyUuid);
102
103 for(Object obj : persistedVocabulary.getTerms()) {
104 DefinedTermBase d = (DefinedTermBase)obj;
105 Hibernate.initialize(d.getRepresentations());
106 terms.put(d.getUuid(), d);
107 }
108
109 logger.debug("Setting defined Terms for class " + clazz.getSimpleName());
110 super.setDefinedTerms(clazz, persistedVocabulary);
111
112 transactionManager.commit(txStatus);
113 }
114
115 /**
116 * T
117 * @param clazz
118 * @param persistedTerms
119 * @return
120 */
121 public UUID firstPass(Class clazz, Map<UUID, DefinedTermBase> persistedTerms) {
122 TransactionStatus txStatus = transactionManager.getTransaction(txDefinition);
123 logger.debug("loading terms for " + clazz.getSimpleName());
124 Map<UUID,DefinedTermBase> terms = new HashMap<UUID,DefinedTermBase>();
125
126 for(DefinedTermBase d : persistedTerms.values()) {
127 terms.put(d.getUuid(), d);
128 }
129
130 TermVocabulary loadedVocabulary = termLoader.loadTerms((Class<? extends DefinedTermBase>)clazz, terms);
131
132 UUID vocabularyUuid = loadedVocabulary.getUuid();
133
134 logger.debug("loading vocabulary " + vocabularyUuid);
135 TermVocabulary persistedVocabulary = vocabularyDao.findByUuid(vocabularyUuid);
136 if(persistedVocabulary == null) { // i.e. there is no persisted vocabulary
137 logger.debug("vocabulary " + vocabularyUuid + " does not exist - saving");
138 saveVocabulary(loadedVocabulary);
139 } else {
140 logger.debug("vocabulary " + vocabularyUuid + " does exist and already has " + persistedVocabulary.size() + " terms");
141 boolean persistedVocabularyHasMissingTerms = false;
142 for(Object t : loadedVocabulary.getTerms()) {
143 if(!persistedVocabulary.getTerms().contains(t)) {
144 persistedVocabularyHasMissingTerms = true;
145 persistedVocabulary.addTerm((DefinedTermBase)t);
146 }
147 }
148 if(persistedVocabularyHasMissingTerms) {
149 logger.debug("vocabulary " + vocabularyUuid + " exists but does not have all the required terms - updating");
150 updateVocabulary(persistedVocabulary);
151 }
152 }
153 transactionManager.commit(txStatus);
154 return vocabularyUuid;
155 }
156
157 private void updateVocabulary(TermVocabulary vocabulary) {
158 TransactionStatus txStatus = transactionManager.getTransaction(txDefinition);
159 vocabularyDao.update(vocabulary);
160 transactionManager.commit(txStatus);
161 }
162
163 private void saveVocabulary(TermVocabulary vocabulary) {
164 TransactionStatus txStatus = transactionManager.getTransaction(txDefinition);
165 vocabularyDao.save(vocabulary);
166 transactionManager.commit(txStatus);
167 }
168 }