merge-update from trunk
[cdmlib.git] / cdmlib-persistence / src / main / java / eu / etaxonomy / cdm / database / update / UpdaterBase.java
1 // $Id$
2 /**
3 * Copyright (C) 2009 EDIT
4 * European Distributed Institute of Taxonomy
5 * http://www.e-taxonomy.eu
6 *
7 * The contents of this file are subject to the Mozilla Public License Version 1.1
8 * See LICENSE.TXT at the top of this package for the full license terms.
9 */
10 package eu.etaxonomy.cdm.database.update;
11
12 import java.sql.SQLException;
13 import java.util.List;
14
15 import org.apache.log4j.Logger;
16
17 import eu.etaxonomy.cdm.common.monitor.IProgressMonitor;
18 import eu.etaxonomy.cdm.database.ICdmDataSource;
19 import eu.etaxonomy.cdm.model.metadata.CdmMetaData;
20
21
22 /**
23 * Common updater base class for updating schema or terms.
24 *
25 * @see CdmUpdater
26 * @see ISchemaUpdater
27 * @see ITermUpdater
28 *
29 * @author a.mueller
30 * @date 16.11.2010
31 *
32 */
33 public abstract class UpdaterBase<T extends ISchemaUpdaterStep, U extends IUpdater<U>> implements IUpdater<U> {
34 private static final Logger logger = Logger.getLogger(TermUpdaterBase.class);
35
36 protected List<T> list;
37 protected String startVersion;
38 protected String targetVersion;
39
40
41 protected abstract boolean updateVersion(ICdmDataSource datasource, IProgressMonitor monitor, CaseType caseType) throws SQLException;
42
43 protected abstract String getCurrentVersion(ICdmDataSource datasource, IProgressMonitor monitor, CaseType caseType) throws SQLException;
44
45 @Override
46 public int countSteps(ICdmDataSource datasource, IProgressMonitor monitor, CaseType caseType){
47 int result = 0;
48 //TODO test if previous updater is needed
49 if (isToBeInvoked(datasource, monitor, caseType)){
50 for (T step: list){
51 result++; //+= list.size();
52 result += step.getInnerSteps().size();
53 }
54 if (getPreviousUpdater() != null){
55 result += getPreviousUpdater().countSteps(datasource, monitor, caseType);
56 }
57 }
58 return result;
59 }
60
61
62 private boolean isToBeInvoked(ICdmDataSource datasource, IProgressMonitor monitor, CaseType caseType) {
63 boolean result = true;
64 String datasourceVersion;
65 try {
66 datasourceVersion = getCurrentVersion(datasource, monitor, caseType);
67 } catch (SQLException e1) {
68 monitor.warning("SQLException", e1);
69 return false;
70 }
71
72 boolean isAfterMyStartVersion = isAfterMyStartVersion(datasourceVersion, monitor);
73 boolean isBeforeMyStartVersion = isBeforeMyStartVersion(datasourceVersion, monitor);
74 // boolean isBeforeMyTargetVersion = isBeforeMyTargetVersion(targetVersion, monitor);
75 boolean isBeforeMyTargetVersion = isBeforeMyTargetVersion(targetVersion, monitor);
76 boolean isDatasourceBeforeMyTargetVersion = isBeforeMyTargetVersion(datasourceVersion, monitor);
77
78 result &= isDatasourceBeforeMyTargetVersion;
79 result &= !(isAfterMyStartVersion && isBeforeMyTargetVersion);
80 result &= ! (isBeforeMyStartVersion && getPreviousUpdater() == null);
81 result &= !isBeforeMyTargetVersion;
82 return result;
83 }
84
85
86 @Override
87 public boolean invoke(ICdmDataSource datasource, IProgressMonitor monitor, CaseType caseType) throws Exception{
88 String currentLibrarySchemaVersion = CdmMetaData.getDbSchemaVersion();
89 return invoke(currentLibrarySchemaVersion, datasource, monitor, caseType);
90 }
91
92 @Override
93 public boolean invoke(String targetVersion, ICdmDataSource datasource, IProgressMonitor monitor, CaseType caseType) throws Exception{
94 boolean result = true;
95 String datasourceVersion;
96
97 try {
98 datasourceVersion = getCurrentVersion(datasource, monitor, caseType);
99 } catch (SQLException e1) {
100 monitor.warning("SQLException", e1);
101 return false;
102 }
103
104
105 boolean isAfterMyStartVersion = isAfterMyStartVersion(datasourceVersion, monitor);
106 boolean isBeforeMyStartVersion = isBeforeMyStartVersion(datasourceVersion, monitor);
107 // boolean isAfterMyTargetVersion = isAfterMyTargetVersion(targetVersion, monitor);
108 boolean isBeforeMyTargetVersion = isBeforeMyTargetVersion(targetVersion, monitor);
109 boolean isDatasourceBeforeMyTargetVersion = isBeforeMyTargetVersion(datasourceVersion, monitor);
110
111
112
113 if (! isDatasourceBeforeMyTargetVersion){
114 String warning = "Target version ("+targetVersion+") is not before updater target version ("+this.targetVersion+"). Nothing to update.";
115 monitor.warning(warning);
116 return true;
117 }
118
119 if (isAfterMyStartVersion && isBeforeMyTargetVersion){
120 String warning = "Database version is higher than updater start version but lower than updater target version";
121 RuntimeException exeption = new RuntimeException(warning);
122 monitor.warning(warning, exeption);
123 throw exeption;
124 }
125
126 if (isBeforeMyStartVersion){
127 if (getPreviousUpdater() == null){
128 String warning = "Database version is before updater version but no previous version updater exists";
129 RuntimeException exeption = new RuntimeException(warning);
130 monitor.warning(warning, exeption);
131 throw exeption;
132 }
133 result &= getPreviousUpdater().invoke(startVersion, datasource, monitor, caseType);
134 }
135
136
137
138 if (isBeforeMyTargetVersion){
139 String warning = "Target version ("+targetVersion+") is lower than updater target version ("+this.targetVersion+")";
140 RuntimeException exeption = new RuntimeException(warning);
141 monitor.warning(warning, exeption);
142 throw exeption;
143 }
144
145 if (result == false){
146 return result;
147 }
148 // datasource.startTransaction(); transaction already started by CdmUpdater
149 try {
150 for (T step : list){
151 result &= handleSingleStep(datasource, monitor, result, step, false, caseType);
152 if (result == false){
153 break;
154 }
155 }
156 if (result == true){
157 result &= updateVersion(datasource, monitor, caseType);
158 }else{
159 datasource.rollback();
160 }
161
162 } catch (Exception e) {
163 datasource.rollback();
164 logger.error("Error occurred while trying to run updater: " + this.getClass().getName());
165 result = false;
166 }
167 return result;
168
169 }
170
171 // protected abstract boolean handleSingleStep(ICdmDataSource datasource, IProgressMonitor monitor, boolean result, ISchemaUpdaterStep step, boolean isInnerStep) throws Exception;
172
173 protected boolean handleSingleStep(ICdmDataSource datasource, IProgressMonitor monitor, boolean result, ISchemaUpdaterStep step, boolean isInnerStep, CaseType caseType)
174 throws Exception {
175 try {
176 monitor.subTask(step.getStepName());
177 Integer invokeResult = step.invoke(datasource, monitor, caseType);
178 result &= (invokeResult != null);
179 for (ISchemaUpdaterStep innerStep : step.getInnerSteps()){
180 result &= handleSingleStep(datasource, monitor, result, innerStep, true, caseType);
181 }
182 // if (! isInnerStep){
183 monitor.worked(1);
184 // }
185 } catch (Exception e) {
186 monitor.warning("Monitor: Exception occurred while handling single schema updating step", e);
187 datasource.rollback();
188 result = false;
189 }
190 return result;
191 }
192
193 protected boolean isAfterMyStartVersion(String dataSourceSchemaVersion, IProgressMonitor monitor) {
194 int depth = 4;
195 int compareResult = CdmMetaData.compareVersion(dataSourceSchemaVersion, startVersion, depth, monitor);
196 return compareResult > 0;
197 }
198
199 protected boolean isBeforeMyStartVersion(String dataSourceSchemaVersion, IProgressMonitor monitor) {
200 int depth = 4;
201 int compareResult = CdmMetaData.compareVersion(dataSourceSchemaVersion, startVersion, depth, monitor);
202 return compareResult < 0;
203 }
204
205 protected boolean isAfterMyTargetVersion(String dataSourceSchemaVersion, IProgressMonitor monitor) {
206 int depth = 4;
207 int compareResult = CdmMetaData.compareVersion(dataSourceSchemaVersion, targetVersion, depth, monitor);
208 return compareResult > 0;
209 }
210
211 protected boolean isBeforeMyTargetVersion(String dataSourceSchemaVersion, IProgressMonitor monitor) {
212 int depth = 4;
213 int compareResult = CdmMetaData.compareVersion(dataSourceSchemaVersion, targetVersion, depth, monitor);
214 return compareResult < 0;
215 }
216
217 /* (non-Javadoc)
218 * @see eu.etaxonomy.cdm.database.update.IUpdater#getNextUpdater()
219 */
220 @Override
221 public abstract U getNextUpdater();
222
223 /* (non-Javadoc)
224 * @see eu.etaxonomy.cdm.database.update.IUpdater#getPreviousUpdater()
225 */
226 @Override
227 public abstract U getPreviousUpdater();
228
229
230 /**
231 * @return
232 */
233 public String getTargetVersion() {
234 return this.targetVersion;
235 }
236 }