001package org.kualigan.tools.liquibase;
002
003import liquibase.database.Database;
004import liquibase.diff.ObjectDifferences;
005import liquibase.diff.StringDiff;
006import liquibase.diff.compare.CompareControl;
007import liquibase.diff.compare.DatabaseObjectComparatorFactory;
008import liquibase.exception.DatabaseException;
009import liquibase.snapshot.DatabaseSnapshot;
010import liquibase.structure.DatabaseObject;
011
012import java.io.*;
013import java.util.*;
014
015public class DiffResult {
016
017    private DatabaseSnapshot referenceSnapshot;
018    private DatabaseSnapshot comparisonSnapshot;
019
020    private CompareControl compareControl;
021
022    private StringDiff productNameDiff;
023    private StringDiff productVersionDiff;
024
025    private Set<DatabaseObject> missingObjects = new HashSet<DatabaseObject>();
026    private Set<DatabaseObject> unexpectedObjects = new HashSet<DatabaseObject>();
027    private Map<DatabaseObject, ObjectDifferences> changedObjects = new HashMap<DatabaseObject, ObjectDifferences>();
028
029
030    public DiffResult(DatabaseSnapshot referenceDatabaseSnapshot, DatabaseSnapshot comparisonDatabaseSnapshot, CompareControl compareControl) {
031        this.referenceSnapshot = referenceDatabaseSnapshot;
032        this.comparisonSnapshot = comparisonDatabaseSnapshot;
033        this.compareControl = compareControl;
034    }
035
036    public DatabaseSnapshot getReferenceSnapshot() {
037        return referenceSnapshot;
038    }
039
040    public DatabaseSnapshot getComparisonSnapshot() {
041        return comparisonSnapshot;
042    }
043
044    public StringDiff getProductNameDiff() {
045        return productNameDiff;
046    }
047
048    public void setProductNameDiff(StringDiff productNameDiff) {
049        this.productNameDiff = productNameDiff;
050    }
051
052    public StringDiff getProductVersionDiff() {
053        return productVersionDiff;
054    }
055
056
057    public void setProductVersionDiff(StringDiff productVersionDiff) {
058        this.productVersionDiff = productVersionDiff;
059    }
060
061    public CompareControl getCompareControl() {
062        return compareControl;
063    }
064
065    public Set<? extends DatabaseObject> getMissingObjects() {
066        return missingObjects;
067    }
068
069    public <T extends DatabaseObject> Set<T> getMissingObjects(Class<T> type) {
070        Set returnSet = new HashSet();
071        for (DatabaseObject obj : missingObjects) {
072            if (type.isAssignableFrom(obj.getClass())) {
073                returnSet.add(obj);
074            }
075        }
076        return returnSet;
077    }
078
079    public <T extends DatabaseObject> SortedSet<T> getMissingObjects(Class<T> type, Comparator<DatabaseObject> comparator) {
080        TreeSet<T> set = new TreeSet<T>(comparator);
081        set.addAll(getMissingObjects(type));
082        return set;
083    }
084
085    public <T extends DatabaseObject> T getMissingObject(T example) {
086        Database accordingTo = getComparisonSnapshot().getDatabase();
087        DatabaseObjectComparatorFactory comparator = DatabaseObjectComparatorFactory.getInstance();
088        for (T obj : (Set<T>) getMissingObjects(example.getClass())) {
089            if (comparator.isSameObject(obj, example, accordingTo)) {
090                return obj;
091            }
092        }
093        return null;
094    }
095
096    public void addMissingObject(DatabaseObject obj) {
097        missingObjects.add(obj);
098    }
099
100    public Set<? extends DatabaseObject> getUnexpectedObjects() {
101        return unexpectedObjects;
102    }
103
104    public <T extends DatabaseObject> Set<T> getUnexpectedObjects(Class<T> type) {
105        Set returnSet = new HashSet();
106        for (DatabaseObject obj : unexpectedObjects) {
107            if (type.isAssignableFrom(obj.getClass())) {
108                returnSet.add(obj);
109            }
110        }
111        return returnSet;
112    }
113
114    public <T extends DatabaseObject> SortedSet<T> getUnexpectedObjects(Class<T> type, Comparator<DatabaseObject> comparator) {
115        TreeSet<T> set = new TreeSet<T>(comparator);
116        set.addAll(getUnexpectedObjects(type));
117        return set;
118    }
119
120    public <T extends DatabaseObject> T getUnexpectedObject(T example) {
121        Database accordingTo = this.getComparisonSnapshot().getDatabase();
122        DatabaseObjectComparatorFactory comparator = DatabaseObjectComparatorFactory.getInstance();
123        for (T obj : (Set<T>) getUnexpectedObjects(example.getClass())) {
124            if (comparator.isSameObject(obj, example, accordingTo)) {
125                return obj;
126            }
127        }
128        return null;
129    }
130
131    public void addUnexpectedObject(DatabaseObject obj) {
132        unexpectedObjects.add(obj);
133    }
134
135    public Map<DatabaseObject, ObjectDifferences> getChangedObjects() {
136        return changedObjects;
137    }
138
139    public  <T extends DatabaseObject> Map<T, ObjectDifferences> getChangedObjects(Class<T> type) {
140        Map returnSet = new HashMap();
141        for (Map.Entry<DatabaseObject, ObjectDifferences> obj : changedObjects.entrySet()) {
142            if (type.isAssignableFrom(obj.getKey().getClass())) {
143                returnSet.put(obj.getKey(), obj.getValue());
144            }
145        }
146        return returnSet;
147    }
148
149    public <T extends DatabaseObject> SortedMap<T, ObjectDifferences> getChangedObjects(Class<T> type, Comparator<DatabaseObject> comparator) {
150        SortedMap<T, ObjectDifferences> map = new TreeMap<T, ObjectDifferences>(comparator);
151        map.putAll(getChangedObjects(type));
152        return map;
153    }
154
155    public ObjectDifferences getChangedObject(DatabaseObject example) {
156        Database accordingTo = this.getComparisonSnapshot().getDatabase();
157        DatabaseObjectComparatorFactory comparator = DatabaseObjectComparatorFactory.getInstance();
158        for (Map.Entry<? extends DatabaseObject, ObjectDifferences> entry : getChangedObjects(example.getClass()).entrySet()) {
159            if (comparator.isSameObject(entry.getKey(), example, accordingTo)) {
160                return entry.getValue();
161            }
162        }
163        return null;
164    }
165
166
167    public void addChangedObject(DatabaseObject obj, ObjectDifferences differences) {
168        changedObjects.put(obj, differences);
169    }
170
171    public boolean areEqual() throws DatabaseException, IOException {
172//        boolean differencesInData = false;
173//        if (compareControl.shouldDiffData()) {
174//            List<ChangeSet> changeSets = new ArrayList<ChangeSet>();
175//            addInsertDataChanges(changeSets, dataDir);
176//            differencesInData = !changeSets.isEmpty();
177//        }
178
179        return missingObjects.size() == 0 && unexpectedObjects.size() == 0 && changedObjects.size() == 0;
180    }
181
182    public Set<Class<? extends DatabaseObject>> getComparedTypes() {
183        return compareControl.getComparedTypes();
184    }
185}