001: package liquibase.diff;
002:
003: import liquibase.database.Database;
004: import liquibase.database.structure.*;
005: import liquibase.exception.JDBCException;
006:
007: import java.util.HashSet;
008: import java.util.Set;
009:
010: public class Diff {
011:
012: private Database baseDatabase;
013: private Database targetDatabase;
014:
015: private DatabaseSnapshot baseSnapshot;
016: private DatabaseSnapshot targetSnapshot;
017:
018: private Set<DiffStatusListener> statusListeners = new HashSet<DiffStatusListener>();
019:
020: public Diff(Database baseDatabase, Database targetDatabase) {
021: this .baseDatabase = baseDatabase;
022:
023: this .targetDatabase = targetDatabase;
024: }
025:
026: public Diff(Database originalDatabase, String schema)
027: throws JDBCException {
028: targetDatabase = null;
029:
030: baseDatabase = originalDatabase;
031: baseDatabase.setDefaultSchemaName(schema);
032: }
033:
034: public Diff(DatabaseSnapshot baseDatabaseSnapshot,
035: DatabaseSnapshot targetDatabaseSnapshot) {
036: this .baseSnapshot = baseDatabaseSnapshot;
037:
038: this .targetSnapshot = targetDatabaseSnapshot;
039: }
040:
041: public void addStatusListener(DiffStatusListener listener) {
042: statusListeners.add(listener);
043: }
044:
045: public void removeStatusListener(DiffStatusListener listener) {
046: statusListeners.remove(listener);
047: }
048:
049: public DiffResult compare() throws JDBCException {
050: if (baseSnapshot == null) {
051: baseSnapshot = new DatabaseSnapshot(baseDatabase,
052: statusListeners);
053: }
054:
055: if (targetSnapshot == null) {
056: if (targetDatabase == null) {
057: targetSnapshot = new DatabaseSnapshot();
058: } else {
059: targetSnapshot = new DatabaseSnapshot(targetDatabase,
060: statusListeners);
061: }
062: }
063:
064: DiffResult diffResult = new DiffResult(baseSnapshot,
065: targetSnapshot);
066: checkVersionInfo(diffResult);
067: checkTables(diffResult);
068: checkViews(diffResult);
069: checkColumns(diffResult);
070: checkForeignKeys(diffResult);
071: checkPrimaryKeys(diffResult);
072: checkIndexes(diffResult);
073: checkSequences(diffResult);
074:
075: return diffResult;
076: }
077:
078: private void checkVersionInfo(DiffResult diffResult)
079: throws JDBCException {
080:
081: if (targetDatabase != null) {
082: diffResult.setProductName(new DiffComparison(baseDatabase
083: .getDatabaseProductName(), targetDatabase
084: .getDatabaseProductName()));
085: diffResult.setProductVersion(new DiffComparison(
086: baseDatabase.getDatabaseProductVersion(),
087: targetDatabase.getDatabaseProductVersion()));
088: }
089:
090: }
091:
092: private void checkTables(DiffResult diffResult) {
093: for (Table baseTable : baseSnapshot.getTables()) {
094: if (!targetSnapshot.getTables().contains(baseTable)) {
095: diffResult.addMissingTable(baseTable);
096: }
097: }
098:
099: for (Table targetTable : targetSnapshot.getTables()) {
100: if (!baseSnapshot.getTables().contains(targetTable)) {
101: diffResult.addUnexpectedTable(targetTable);
102: }
103: }
104: }
105:
106: private void checkViews(DiffResult diffResult) {
107: for (View baseView : baseSnapshot.getViews()) {
108: if (!targetSnapshot.getViews().contains(baseView)) {
109: diffResult.addMissingView(baseView);
110: }
111: }
112:
113: for (View targetView : targetSnapshot.getViews()) {
114: if (!baseSnapshot.getViews().contains(targetView)) {
115: diffResult.addUnexpectedView(targetView);
116: }
117: }
118: }
119:
120: private void checkColumns(DiffResult diffResult) {
121: for (Column baseColumn : baseSnapshot.getColumns()) {
122: if (!targetSnapshot.getColumns().contains(baseColumn)
123: && (baseColumn.getTable() == null || !diffResult
124: .getMissingTables().contains(
125: baseColumn.getTable()))
126: && (baseColumn.getView() == null || !diffResult
127: .getMissingViews().contains(
128: baseColumn.getView()))) {
129: diffResult.addMissingColumn(baseColumn);
130: }
131: }
132:
133: for (Column targetColumn : targetSnapshot.getColumns()) {
134: if (!baseSnapshot.getColumns().contains(targetColumn)
135: && (targetColumn.getTable() == null || !diffResult
136: .getUnexpectedTables().contains(
137: targetColumn.getTable()))
138: && (targetColumn.getView() == null || !diffResult
139: .getUnexpectedViews().contains(
140: targetColumn.getView()))) {
141: diffResult.addUnexpectedColumn(targetColumn);
142: } else if (targetColumn.getTable() != null
143: && !diffResult.getUnexpectedTables().contains(
144: targetColumn.getTable())) {
145: Column baseColumn = baseSnapshot.getColumn(targetColumn
146: .getTable().getName(), targetColumn.getName());
147:
148: if (targetColumn.isDifferent(baseColumn)) {
149: diffResult.addChangedColumn(targetColumn);
150: }
151: }
152: }
153: }
154:
155: private void checkForeignKeys(DiffResult diffResult) {
156: for (ForeignKey baseFK : baseSnapshot.getForeignKeys()) {
157: if (!targetSnapshot.getForeignKeys().contains(baseFK)) {
158: diffResult.addMissingForeignKey(baseFK);
159: }
160: }
161:
162: for (ForeignKey targetFK : targetSnapshot.getForeignKeys()) {
163: if (!baseSnapshot.getForeignKeys().contains(targetFK)) {
164: diffResult.addUnexpectedForeignKey(targetFK);
165: }
166: }
167: }
168:
169: private void checkIndexes(DiffResult diffResult) {
170: for (Index baseIndex : baseSnapshot.getIndexes()) {
171: if (!targetSnapshot.getIndexes().contains(baseIndex)) {
172: diffResult.addMissingIndex(baseIndex);
173: }
174: }
175:
176: for (Index targetIndex : targetSnapshot.getIndexes()) {
177: if (!baseSnapshot.getIndexes().contains(targetIndex)) {
178: diffResult.addUnexpectedIndex(targetIndex);
179: }
180: }
181: }
182:
183: private void checkPrimaryKeys(DiffResult diffResult) {
184: for (PrimaryKey basePrimaryKey : baseSnapshot.getPrimaryKeys()) {
185: if (!targetSnapshot.getPrimaryKeys().contains(
186: basePrimaryKey)) {
187: diffResult.addMissingPrimaryKey(basePrimaryKey);
188: }
189: }
190:
191: for (PrimaryKey targetPrimaryKey : targetSnapshot
192: .getPrimaryKeys()) {
193: if (!baseSnapshot.getPrimaryKeys().contains(
194: targetPrimaryKey)) {
195: diffResult.addUnexpectedPrimaryKey(targetPrimaryKey);
196: }
197: }
198: }
199:
200: private void checkSequences(DiffResult diffResult) {
201: for (Sequence baseSequence : baseSnapshot.getSequences()) {
202: if (!targetSnapshot.getSequences().contains(baseSequence)) {
203: diffResult.addMissingSequence(baseSequence);
204: }
205: }
206:
207: for (Sequence targetSequence : targetSnapshot.getSequences()) {
208: if (!baseSnapshot.getSequences().contains(targetSequence)) {
209: diffResult.addUnexpectedSequence(targetSequence);
210: }
211: }
212: }
213: }
|