1 24 package org.riotfamily.revolt; 25 26 import java.util.ArrayList ; 27 import java.util.Iterator ; 28 import java.util.List ; 29 30 import javax.sql.DataSource ; 31 32 import org.apache.commons.logging.Log; 33 import org.apache.commons.logging.LogFactory; 34 import org.riotfamily.revolt.definition.Database; 35 import org.riotfamily.revolt.support.DatabaseUtils; 36 import org.riotfamily.revolt.support.DialectResolver; 37 import org.riotfamily.revolt.support.LogTable; 38 import org.riotfamily.revolt.support.ScriptBuilder; 39 import org.springframework.beans.factory.BeanNameAware; 40 41 45 public class EvolutionHistory implements BeanNameAware { 46 47 private static final Log log = LogFactory.getLog(EvolutionHistory.class); 48 49 private String moduleName; 50 51 private List changeSets; 52 53 private DataSource dataSource; 54 55 private Dialect dialect; 56 57 private LogTable logTable; 58 59 private ArrayList appliedIds; 60 61 private boolean newModule; 62 63 public EvolutionHistory(DataSource dataSource) { 64 this.dataSource = dataSource; 65 this.dialect = new DialectResolver().getDialect(dataSource); 66 } 67 68 public DataSource getDataSource() { 69 return this.dataSource; 70 } 71 72 public Dialect getDialect() { 73 return this.dialect; 74 } 75 76 public void setBeanName(String name) { 77 this.moduleName = name; 78 } 79 80 public String getModuleName() { 81 return this.moduleName; 82 } 83 84 public void setChangeSets(ChangeSet[] changeSets) { 85 this.changeSets = new ArrayList (); 86 for (int i = 0; i < changeSets.length; i++) { 87 ChangeSet changeSet = changeSets[i]; 88 changeSet.setHistory(this); 89 changeSet.setSequenceNumber(i); 90 this.changeSets.add(changeSet); 91 } 92 } 93 94 public void validate() { 95 DatabaseUtils.validate(dataSource, evolveModel()); 96 } 97 98 private Database evolveModel() { 99 Database model = new Database(); 100 Iterator it = changeSets.iterator(); 101 while (it.hasNext()) { 102 ChangeSet changeSet = (ChangeSet) it.next(); 103 changeSet.alterModel(model); 104 } 105 return model; 106 } 107 108 111 public void init(LogTable logTable) { 112 this.logTable = logTable; 113 appliedIds = new ArrayList (); 114 appliedIds.addAll(logTable.getAppliedChangeSetIds(moduleName)); 115 } 116 117 120 public Script getScript() { 121 if (appliedIds.isEmpty()) { 122 log.info("The log-table contains no entries for module '" 123 + moduleName + "'. Checking if schema is up-to-date ..."); 124 125 newModule = true; 126 return getEvolvedSetupScript(); 127 } 128 else { 129 return getMigrationScript(); 130 } 131 } 132 133 private Script getEvolvedSetupScript() { 134 Script script = new Script(); 135 Database model = evolveModel(); 136 try { 137 DatabaseUtils.validate(dataSource, model); 138 log.info("Schema looks okay. Marking all changes as applied."); 139 } 140 catch (DatabaseOutOfSyncException e) { 141 log.info(e.getMessage()); 142 log.info("Generating setup script ..."); 143 ScriptBuilder builder = new ScriptBuilder(model, dialect); 144 script.append(builder.buildScript()); 145 } 146 Iterator it = changeSets.iterator(); 147 while (it.hasNext()) { 148 ChangeSet changeSet = (ChangeSet) it.next(); 149 script.append(markAsApplied(changeSet)); 150 } 151 return script; 152 } 153 154 private Script getMigrationScript() { 155 Script script = new Script(); 156 Iterator it = changeSets.iterator(); 157 while (it.hasNext()) { 158 ChangeSet changeSet = (ChangeSet) it.next(); 159 if (!isApplied(changeSet)) { 160 script.append(changeSet.getScript(dialect)); 161 script.append(markAsApplied(changeSet)); 162 } 163 } 164 return script; 165 } 166 167 171 public boolean isNewModule() { 172 return newModule; 173 } 174 175 180 private boolean isApplied(ChangeSet changeSet) { 181 if (appliedIds.size() > changeSet.getSequenceNumber()) { 182 String appliedId = (String ) appliedIds.get( 183 changeSet.getSequenceNumber()); 184 185 if (appliedId.equals(changeSet.getId())) { 186 return true; 187 } 188 throw new DatabaseOutOfSyncException("ChangeSet number " 189 + changeSet.getSequenceNumber() + " should be [" 190 + changeSet.getId() + "] but is [" + appliedId + "]"); 191 } 192 return false; 193 } 194 195 201 private Script markAsApplied(ChangeSet changeSet) { 202 if (changeSet.getSequenceNumber() != appliedIds.size()) { 203 throw new DatabaseOutOfSyncException("ChangeSet [" 204 + changeSet.getId() + "] is number " 205 + changeSet.getSequenceNumber() + " but there are already " 206 + appliedIds.size() + " ChangeSets applied!"); 207 } 208 appliedIds.add(changeSet.getId()); 209 return logTable.getInsertScript(changeSet); 210 } 211 212 } 213
| Popular Tags
|