2 * Copyright (C) 2007 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
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.
10 package eu
.etaxonomy
.cdm
.database
;
12 import java
.util
.HashMap
;
13 import java
.util
.List
;
15 import java
.util
.UUID
;
17 import javax
.annotation
.PostConstruct
;
19 import org
.apache
.log4j
.Logger
;
20 import org
.hibernate
.Hibernate
;
21 import org
.springframework
.beans
.factory
.annotation
.Autowired
;
22 import org
.springframework
.stereotype
.Component
;
23 import org
.springframework
.transaction
.PlatformTransactionManager
;
24 import org
.springframework
.transaction
.TransactionDefinition
;
25 import org
.springframework
.transaction
.TransactionStatus
;
26 import org
.springframework
.transaction
.support
.DefaultTransactionDefinition
;
28 import eu
.etaxonomy
.cdm
.model
.common
.DefaultTermInitializer
;
29 import eu
.etaxonomy
.cdm
.model
.common
.DefinedTermBase
;
30 import eu
.etaxonomy
.cdm
.model
.common
.Representation
;
31 import eu
.etaxonomy
.cdm
.model
.common
.TermVocabulary
;
32 import eu
.etaxonomy
.cdm
.model
.common
.VocabularyEnum
;
33 import eu
.etaxonomy
.cdm
.model
.common
.init
.TermLoader
;
34 import eu
.etaxonomy
.cdm
.persistence
.dao
.common
.ITermVocabularyDao
;
37 * Spring bean class to initialize the {@link IVocabularyStore IVocabularyStore}.
38 * To initialize the store the {@link TermLoader TermLoader} and the {@link IVocabularyStore IVocabularyStore}
39 * are injected via spring and the initializeTerms method is called as an init-method (@PostConstruct).
45 public class PersistentTermInitializer
extends DefaultTermInitializer
{
46 private static final Logger logger
= Logger
.getLogger(PersistentTermInitializer
.class);
48 private boolean omit
= false;
49 protected ITermVocabularyDao vocabularyDao
;
51 protected PlatformTransactionManager transactionManager
;
52 protected DefaultTransactionDefinition txDefinition
= new DefaultTransactionDefinition();
54 public PersistentTermInitializer() {
55 txDefinition
.setName("PersistentTermInitializer.initialize()");
56 txDefinition
.setPropagationBehavior(TransactionDefinition
.PROPAGATION_REQUIRED
);
59 public void setOmit(boolean omit
) {
63 public boolean isOmit() {
69 public void setVocabularyDao(ITermVocabularyDao vocabularyDao
) {
70 this.vocabularyDao
= vocabularyDao
;
74 public void setTransactionManager(PlatformTransactionManager transactionManager
) {
75 this.transactionManager
= transactionManager
;
79 * After a bit of head-scratching I found section 3.5.1.3. in the current spring
80 * reference manual - @PostConstruct / afterPropertiesSet() is called
81 * immediatly after the bean is constructed, prior to any AOP interceptors being
82 * wrapped round the bean. Thus, we have to use programmatic transactions, not
83 * annotations or pointcuts.
87 public void initialize() {
93 public void doInitialize(){
94 logger
.info("PersistentTermInitializer initialize start ...");
96 // //only for testing - remove
97 // TransactionStatus txStatus2 = transactionManager.getTransaction(txDefinition);
98 // int i = vocabularyDao.count();
99 // List<TermVocabulary> list = vocabularyDao.list(null, null);
100 // for (TermVocabulary voc : list){
101 // System.out.println(voc.getUuid());
103 // transactionManager.commit(txStatus2);
107 logger
.info("PersistentTermInitializer.omit == true, returning without initializing terms");
110 Map
<UUID
,DefinedTermBase
> terms
= new HashMap
<UUID
,DefinedTermBase
>();
111 logger
.info("PersistentTermInitializer.omit == false, initializing " + VocabularyEnum
.values().length
+ " term classes");
113 TransactionStatus txStatus
= transactionManager
.getTransaction(txDefinition
);
114 for(VocabularyEnum vocabularyType
: VocabularyEnum
.values()) {
115 //Class<? extends DefinedTermBase<?>> clazz = vocabularyType.getClazz();
116 UUID vocabularyUuid
= firstPass(vocabularyType
,terms
);
117 secondPass(vocabularyType
.getClazz(),vocabularyUuid
,terms
);
119 transactionManager
.commit(txStatus
);
121 logger
.info("PersistentTermInitializer initialize end ...");
125 * Initializes the static fields of the <code>TermVocabulary</code> classes.
127 * @param clazz the <code>Class</code> of the vocabulary
128 * @param vocabularyUuid the <code>UUID</code> of the vocabulary
129 * @param terms a <code>Map</code> containing all already
130 * loaded terms with their <code>UUID</code> as key
132 protected void secondPass(Class clazz
, UUID vocabularyUuid
, Map
<UUID
,DefinedTermBase
> terms
) {
133 logger
.debug("Initializing vocabulary for class " + clazz
.getSimpleName() + " with uuid " + vocabularyUuid
);
135 TermVocabulary
<?
> persistedVocabulary
= vocabularyDao
.findByUuid(vocabularyUuid
);
137 if (persistedVocabulary
!= null){
138 for(Object object
: persistedVocabulary
.getTerms()) {
139 DefinedTermBase
<?
> definedTermBase
= (DefinedTermBase
) object
;
140 Hibernate
.initialize(definedTermBase
.getRepresentations());
141 for(Representation r
: definedTermBase
.getRepresentations()) {
142 Hibernate
.initialize(r
.getLanguage());
144 terms
.put(definedTermBase
.getUuid(), definedTermBase
);
147 logger
.error("Persisted Vocabulary does not exist in database: " + vocabularyUuid
);
148 throw new NullPointerException("Persisted Vocabulary does not exist in database: " + vocabularyUuid
);
150 logger
.debug("Setting defined Terms for class " + clazz
.getSimpleName() + ", " + persistedVocabulary
.getTerms().size() + " in vocabulary");
151 super.setDefinedTerms(clazz
, persistedVocabulary
);
155 * This method loads the vocabularies from CSV files and compares them to the vocabularies
156 * already in database. Non-existing vocabularies will be created and vocabularies with missing
157 * terms will be updated.
159 * @param clazz the <code>Class</code> of the vocabulary
160 * @param persistedTerms a <code>Map</code> containing all already
161 * loaded terms with their <code>UUID</code> as key
162 * @return the <code>UUID</code> of the loaded vocabulary as found in CSV file
164 public UUID
firstPass(VocabularyEnum vocabularyType
, Map
<UUID
, DefinedTermBase
> persistedTerms
) {
165 logger
.info("Loading terms for '" + vocabularyType
.name() + "': " + vocabularyType
.getClazz().getName());
166 Map
<UUID
,DefinedTermBase
> terms
= new HashMap
<UUID
,DefinedTermBase
>();
168 for(DefinedTermBase d
: persistedTerms
.values()) {
169 terms
.put(d
.getUuid(), d
);
172 TermVocabulary
<?
> loadedVocabulary
= termLoader
.loadTerms(vocabularyType
, terms
);
174 UUID vocabularyUuid
= loadedVocabulary
.getUuid();
177 logger
.debug("loading vocabulary " + vocabularyUuid
);
178 TermVocabulary
<DefinedTermBase
> persistedVocabulary
= vocabularyDao
.findByUuid(vocabularyUuid
);
179 if(persistedVocabulary
== null) { // i.e. there is no persisted vocabulary
180 logger
.debug("vocabulary " + vocabularyUuid
+ " does not exist - saving");
181 saveVocabulary(loadedVocabulary
);
183 logger
.debug("vocabulary " + vocabularyUuid
+ " does exist and already has " + persistedVocabulary
.size() + " terms");
184 boolean persistedVocabularyHasMissingTerms
= false;
185 for(Object t
: loadedVocabulary
.getTerms()) {
186 if(!persistedVocabulary
.getTerms().contains(t
)) {
187 persistedVocabularyHasMissingTerms
= true;
188 persistedVocabulary
.addTerm((DefinedTermBase
)t
);
191 if(persistedVocabularyHasMissingTerms
) {
192 logger
.debug("vocabulary " + vocabularyUuid
+ " exists but does not have all the required terms - updating");
193 updateVocabulary(persistedVocabulary
);
196 return vocabularyUuid
;
199 private void updateVocabulary(TermVocabulary vocabulary
) {
200 TransactionStatus txStatus
= transactionManager
.getTransaction(txDefinition
);
201 vocabularyDao
.update(vocabulary
);
202 transactionManager
.commit(txStatus
);
205 private void saveVocabulary(TermVocabulary vocabulary
) {
206 TransactionStatus txStatus
= transactionManager
.getTransaction(txDefinition
);
207 vocabularyDao
.save(vocabulary
);
208 transactionManager
.commit(txStatus
);