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
;
14 import java
.util
.UUID
;
16 import javax
.annotation
.PostConstruct
;
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
;
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
;
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).
44 public class PersistentTermInitializer
extends DefaultTermInitializer
{
45 private static final Logger logger
= Logger
.getLogger(PersistentTermInitializer
.class);
47 private boolean omit
= false;
48 protected ITermVocabularyDao vocabularyDao
;
50 protected PlatformTransactionManager transactionManager
;
51 protected DefaultTransactionDefinition txDefinition
= new DefaultTransactionDefinition();
53 public PersistentTermInitializer() {
54 txDefinition
.setName("PersistentTermInitializer.initialize()");
55 txDefinition
.setPropagationBehavior(TransactionDefinition
.PROPAGATION_REQUIRED
);
58 public void setOmit(boolean omit
) {
62 public boolean isOmit() {
68 public void setVocabularyDao(ITermVocabularyDao vocabularyDao
) {
69 this.vocabularyDao
= vocabularyDao
;
73 public void setTransactionManager(PlatformTransactionManager transactionManager
) {
74 this.transactionManager
= transactionManager
;
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.
86 public void initialize() {
92 public void doInitialize(){
93 logger
.info("PersistentTermInitializer initialize start ...");
95 logger
.info("PersistentTermInitializer.omit == true, returning without initializing terms");
98 Map
<UUID
,DefinedTermBase
> terms
= new HashMap
<UUID
,DefinedTermBase
>();
99 logger
.info("PersistentTermInitializer.omit == false, initializing " + VocabularyEnum
.values().length
+ " term classes");
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
);
107 transactionManager
.commit(txStatus
);
109 logger
.info("PersistentTermInitializer initialize end ...");
113 * Initializes the static fields of the <code>TermVocabulary</code> classes.
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
120 protected void secondPass(Class clazz
, UUID vocabularyUuid
, Map
<UUID
,DefinedTermBase
> terms
) {
121 logger
.debug("Initializing vocabulary for class " + clazz
.getSimpleName() + " with uuid " + vocabularyUuid
);
123 TermVocabulary persistedVocabulary
= vocabularyDao
.findByUuid(vocabularyUuid
);
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());
132 terms
.put(definedTermBase
.getUuid(), definedTermBase
);
135 logger
.error("Persisted Vocabulary does not exist in database: " + vocabularyUuid
);
136 throw new NullPointerException("Persisted Vocabulary does not exist in database: " + vocabularyUuid
);
138 logger
.debug("Setting defined Terms for class " + clazz
.getSimpleName());
139 super.setDefinedTerms(clazz
, persistedVocabulary
);
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.
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
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
>();
156 for(DefinedTermBase d
: persistedTerms
.values()) {
157 terms
.put(d
.getUuid(), d
);
160 TermVocabulary loadedVocabulary
= termLoader
.loadTerms(vocabularyType
, terms
);
162 UUID vocabularyUuid
= loadedVocabulary
.getUuid();
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
);
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
);
179 if(persistedVocabularyHasMissingTerms
) {
180 logger
.debug("vocabulary " + vocabularyUuid
+ " exists but does not have all the required terms - updating");
181 updateVocabulary(persistedVocabulary
);
184 return vocabularyUuid
;
187 private void updateVocabulary(TermVocabulary vocabulary
) {
188 TransactionStatus txStatus
= transactionManager
.getTransaction(txDefinition
);
189 vocabularyDao
.update(vocabulary
);
190 transactionManager
.commit(txStatus
);
193 private void saveVocabulary(TermVocabulary vocabulary
) {
194 TransactionStatus txStatus
= transactionManager
.getTransaction(txDefinition
);
195 vocabularyDao
.save(vocabulary
);
196 transactionManager
.commit(txStatus
);