SecurityInterceptor added
[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.Representation;
30 import eu.etaxonomy.cdm.model.common.TermVocabulary;
31 import eu.etaxonomy.cdm.model.common.VocabularyEnum;
32 import eu.etaxonomy.cdm.model.common.init.TermLoader;
33 import eu.etaxonomy.cdm.persistence.dao.common.ITermVocabularyDao;
34
35 /**
36 * Spring bean class to initialize the {@link IVocabularyStore IVocabularyStore}.
37 * To initialize the store the {@link TermLoader TermLoader} and the {@link IVocabularyStore IVocabularyStore}
38 * are injected via spring and the initializeTerms method is called as an init-method (@PostConstruct).
39
40 * @author a.mueller
41 */
42
43 @Component
44 public class PersistentTermInitializer extends DefaultTermInitializer {
45 private static final Logger logger = Logger.getLogger(PersistentTermInitializer.class);
46
47 private boolean omit = false;
48 protected ITermVocabularyDao vocabularyDao;
49
50 protected PlatformTransactionManager transactionManager;
51 protected DefaultTransactionDefinition txDefinition = new DefaultTransactionDefinition();
52
53 public PersistentTermInitializer() {
54 txDefinition.setName("PersistentTermInitializer.initialize()");
55 txDefinition.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
56 }
57
58 public void setOmit(boolean omit) {
59 this.omit = omit;
60 }
61
62 public boolean isOmit() {
63 return omit;
64 }
65
66
67 @Autowired
68 public void setVocabularyDao(ITermVocabularyDao vocabularyDao) {
69 this.vocabularyDao = vocabularyDao;
70 }
71
72 @Autowired
73 public void setTransactionManager(PlatformTransactionManager transactionManager) {
74 this.transactionManager = transactionManager;
75 }
76
77 /*
78 * After a bit of head-scratching I found section 3.5.1.3. in the current spring
79 * reference manual - @PostConstruct / afterPropertiesSet() is called
80 * immediatly after the bean is constructed, prior to any AOP interceptors being
81 * wrapped round the bean. Thus, we have to use programmatic transactions, not
82 * annotations or pointcuts.
83 */
84 @PostConstruct
85 @Override
86 public void initialize() {
87 super.initialize();
88 }
89
90
91 @Override
92 public void doInitialize(){
93 logger.info("PersistentTermInitializer initialize start ...");
94 if (omit){
95 logger.info("PersistentTermInitializer.omit == true, returning without initializing terms");
96 return;
97 } else {
98 Map<UUID,DefinedTermBase> terms = new HashMap<UUID,DefinedTermBase>();
99 logger.info("PersistentTermInitializer.omit == false, initializing " + VocabularyEnum.values().length + " term classes");
100
101 TransactionStatus txStatus = transactionManager.getTransaction(txDefinition);
102 for(VocabularyEnum vocabularyType : VocabularyEnum.values()) {
103 //Class<? extends DefinedTermBase<?>> clazz = vocabularyType.getClazz();
104 UUID vocabularyUuid = firstPass(vocabularyType,terms);
105 secondPass(vocabularyType.getClazz(),vocabularyUuid,terms);
106 }
107 transactionManager.commit(txStatus);
108 }
109 logger.info("PersistentTermInitializer initialize end ...");
110 }
111
112 /**
113 * Initializes the static fields of the <code>TermVocabulary</code> classes.
114 *
115 * @param clazz the <code>Class</code> of the vocabulary
116 * @param vocabularyUuid the <code>UUID</code> of the vocabulary
117 * @param terms a <code>Map</code> containing all already
118 * loaded terms with their <code>UUID</code> as key
119 */
120 protected void secondPass(Class clazz, UUID vocabularyUuid, Map<UUID,DefinedTermBase> terms) {
121 logger.debug("Initializing vocabulary for class " + clazz.getSimpleName() + " with uuid " + vocabularyUuid );
122
123 TermVocabulary persistedVocabulary = vocabularyDao.findByUuid(vocabularyUuid);
124
125 if (persistedVocabulary != null){
126 for(Object object : persistedVocabulary.getTerms()) {
127 DefinedTermBase definedTermBase = (DefinedTermBase) object;
128 Hibernate.initialize(definedTermBase.getRepresentations());
129 for(Representation r : definedTermBase.getRepresentations()) {
130 Hibernate.initialize(r.getLanguage());
131 }
132 terms.put(definedTermBase.getUuid(), definedTermBase);
133 }
134 }else{
135 logger.error("Persisted Vocabulary does not exist in database: " + vocabularyUuid);
136 throw new NullPointerException("Persisted Vocabulary does not exist in database: " + vocabularyUuid);
137 }
138 logger.debug("Setting defined Terms for class " + clazz.getSimpleName());
139 super.setDefinedTerms(clazz, persistedVocabulary);
140 }
141
142 /**
143 * This method loads the vocabularies from CSV files and compares them to the vocabularies
144 * already in database. Non-existing vocabularies will be created and vocabularies with missing
145 * terms will be updated.
146 *
147 * @param clazz the <code>Class</code> of the vocabulary
148 * @param persistedTerms a <code>Map</code> containing all already
149 * loaded terms with their <code>UUID</code> as key
150 * @return the <code>UUID</code> of the loaded vocabulary as found in CSV file
151 */
152 public UUID firstPass(VocabularyEnum vocabularyType, Map<UUID, DefinedTermBase> persistedTerms) {
153 logger.info("Loading terms for '" + vocabularyType.name() + "': " + vocabularyType.getClazz().getName());
154 Map<UUID,DefinedTermBase> terms = new HashMap<UUID,DefinedTermBase>();
155
156 for(DefinedTermBase d : persistedTerms.values()) {
157 terms.put(d.getUuid(), d);
158 }
159
160 TermVocabulary loadedVocabulary = termLoader.loadTerms(vocabularyType, terms);
161
162 UUID vocabularyUuid = loadedVocabulary.getUuid();
163
164
165 logger.debug("loading vocabulary " + vocabularyUuid);
166 TermVocabulary persistedVocabulary = vocabularyDao.findByUuid(vocabularyUuid);
167 if(persistedVocabulary == null) { // i.e. there is no persisted vocabulary
168 logger.debug("vocabulary " + vocabularyUuid + " does not exist - saving");
169 saveVocabulary(loadedVocabulary);
170 }else {
171 logger.debug("vocabulary " + vocabularyUuid + " does exist and already has " + persistedVocabulary.size() + " terms");
172 boolean persistedVocabularyHasMissingTerms = false;
173 for(Object t : loadedVocabulary.getTerms()) {
174 if(!persistedVocabulary.getTerms().contains(t)) {
175 persistedVocabularyHasMissingTerms = true;
176 persistedVocabulary.addTerm((DefinedTermBase)t);
177 }
178 }
179 if(persistedVocabularyHasMissingTerms) {
180 logger.debug("vocabulary " + vocabularyUuid + " exists but does not have all the required terms - updating");
181 updateVocabulary(persistedVocabulary);
182 }
183 }
184 return vocabularyUuid;
185 }
186
187 private void updateVocabulary(TermVocabulary vocabulary) {
188 TransactionStatus txStatus = transactionManager.getTransaction(txDefinition);
189 vocabularyDao.update(vocabulary);
190 transactionManager.commit(txStatus);
191 }
192
193 private void saveVocabulary(TermVocabulary vocabulary) {
194 TransactionStatus txStatus = transactionManager.getTransaction(txDefinition);
195 vocabularyDao.save(vocabulary);
196 transactionManager.commit(txStatus);
197 }
198 }