package liquibase.diff.output.report;
import liquibase.database.Database;
import liquibase.diff.Difference;
import liquibase.diff.ObjectDifferences;
import liquibase.diff.compare.CompareControl;
import liquibase.structure.DatabaseObject;
import liquibase.diff.DiffResult;
import liquibase.diff.StringDiff;
import liquibase.exception.DatabaseException;
import liquibase.structure.DatabaseObjectComparator;
import liquibase.structure.core.Schema;
import liquibase.util.StringUtils;
import java.io.PrintStream;
import java.util.*;
public class DiffToReport {
private DiffResult diffResult;
private PrintStream out;
public DiffToReport(DiffResult diffResult, PrintStream out) {
this.diffResult = diffResult;
this.out = out;
}
public void print() throws DatabaseException {
final DatabaseObjectComparator comparator = new DatabaseObjectComparator();
out.println("Reference Database: " + diffResult.getReferenceSnapshot().getDatabase());
out.println("Comparison Database: " + diffResult.getComparisonSnapshot().getDatabase());
CompareControl.SchemaComparison[] schemas = diffResult.getCompareControl().getSchemaComparisons();
if (schemas != null && schemas.length > 0) {
out.println("Compared Schemas: " + StringUtils.join(Arrays.asList(schemas), ", ", new StringUtils.StringUtilsFormatter<CompareControl.SchemaComparison>() {
@Override
public String toString(CompareControl.SchemaComparison obj) {
String referenceName;
String comparisonName;
Database referenceDatabase = diffResult.getReferenceSnapshot().getDatabase();
Database comparisonDatabase = diffResult.getComparisonSnapshot().getDatabase();
if (referenceDatabase.supportsSchemas()) {
referenceName = obj.getReferenceSchema().getSchemaName();
if (referenceName == null) {
referenceName = referenceDatabase.getDefaultSchemaName();
}
} else if (referenceDatabase.supportsCatalogs()) {
referenceName = obj.getReferenceSchema().getCatalogName();
if (referenceName == null) {
referenceName = referenceDatabase.getDefaultCatalogName();
}
} else {
return "";
}
if (comparisonDatabase.supportsSchemas()) {
comparisonName = obj.getComparisonSchema().getSchemaName();
if (comparisonName == null) {
comparisonName = comparisonDatabase.getDefaultSchemaName();
}
} else if (comparisonDatabase.supportsCatalogs()) {
comparisonName = obj.getComparisonSchema().getCatalogName();
if (comparisonName == null) {
comparisonName = comparisonDatabase.getDefaultCatalogName();
}
} else {
return "";
}
if (referenceName == null) {
referenceName = StringUtils.trimToEmpty(referenceDatabase.getDefaultSchemaName());
}
if (comparisonName == null) {
comparisonName = StringUtils.trimToEmpty(comparisonDatabase.getDefaultSchemaName());
}
if (referenceName.equalsIgnoreCase(comparisonName)) {
return referenceName;
} else {
return referenceName + " -> " + comparisonName;
}
}
}, true));
}
printComparison("Product Name", diffResult.getProductNameDiff(), out);
printComparison("Product Version", diffResult.getProductVersionDiff(), out);
TreeSet<Class<? extends DatabaseObject>> types = new TreeSet<Class<? extends DatabaseObject>>(new Comparator<Class<? extends DatabaseObject>>() {
@Override
public int compare(Class<? extends DatabaseObject> o1, Class<? extends DatabaseObject> o2) {
return o1.getSimpleName().compareTo(o2.getSimpleName());
}
});
types.addAll(diffResult.getCompareControl().getComparedTypes());
for (Class<? extends DatabaseObject> type : types) {
if (type.equals(Schema.class) && !diffResult.getComparisonSnapshot().getDatabase().supportsSchemas()) {
continue;
}
printSetComparison("Missing " + getTypeName(type), diffResult.getMissingObjects(type, comparator), out);
printSetComparison("Unexpected " + getTypeName(type), diffResult.getUnexpectedObjects(type, comparator), out);
printChangedComparison("Changed " + getTypeName(type), diffResult.getChangedObjects(type, comparator), out);
}
// printColumnComparison(diffResult.getColumns().getChanged(), out);
}
protected String getTypeName(Class<? extends DatabaseObject> type) {
return type.getSimpleName().replaceAll("([A-Z])", " $1").trim() + "(s)";
}
protected boolean getIncludeSchema() {
return diffResult.getCompareControl().getSchemaComparisons().length > 1;
}
protected void printChangedComparison(String title, Map<? extends DatabaseObject, ObjectDifferences> objects, PrintStream out) {
out.print(title + ": ");
if (objects.size() == 0) {
out.println("NONE");
} else {
out.println();
for (Map.Entry<? extends DatabaseObject, ObjectDifferences> object : objects.entrySet()) {
if (object.getValue().hasDifferences()) {
out.println(" " + object.getKey());
for (Difference difference : object.getValue().getDifferences()) {
out.println(" " + difference.toString());
}
}
}
}
}
protected void printSetComparison(String title, Set<? extends DatabaseObject> objects, PrintStream out) {
out.print(title + ": ");
Schema lastSchema = null;
if (objects.size() == 0) {
out.println("NONE");
} else {
out.println();
for (DatabaseObject object : objects) {
if (getIncludeSchema() && object.getSchema() != null && (lastSchema == null || !lastSchema.equals(object.getSchema()))) {
lastSchema = object.getSchema();
String schemaName = object.getSchema().getName();
if (schemaName == null) {
schemaName = object.getSchema().getCatalogName();
}
schemaName = includeSchemaComparison(schemaName);
out.println(" SCHEMA: " + schemaName);
}
out.println(" " + object);
}
}
}
protected String includeSchemaComparison(String schemaName) {
String convertedSchemaName = CompareControl.SchemaComparison.convertSchema(schemaName, diffResult.getCompareControl().getSchemaComparisons());
if (convertedSchemaName != null && !convertedSchemaName.equals(schemaName)) {
schemaName = schemaName + " -> " + convertedSchemaName;
}
return schemaName;
}
// private void printColumnComparison(SortedSet<Column> changedColumns,
// PrintStream out) {
// out.print("Changed Columns: ");
// if (changedColumns.size() == 0) {
// out.println("NONE");
// } else {
// out.println();
// for (Column column : changedColumns) {
// out.println(" " + column);
// Column baseColumn = diffResult.getReferenceSnapshot().getColumn(column.getRelation().getSchema(),
// column.getRelation().getName(), column.getName());
// if (baseColumn != null) {
// if (baseColumn.isDataTypeDifferent(column)) {
// out.println(" from "
// + baseColumn.getType()
// + " to "
// + diffResult.getComparisonSnapshot().getColumn(column.getRelation().getSchema(), column.getRelation().getName(), column.getName()).getType());
// }
// if (baseColumn.isNullabilityDifferent(column)) {
// Boolean nowNullable = diffResult.getComparisonSnapshot().getColumn(column.getRelation().getSchema(),
// column.getRelation().getName(), column.getName())
// .isNullable();
// if (nowNullable == null) {
// nowNullable = Boolean.TRUE;
// }
// if (nowNullable) {
// out.println(" now nullable");
// } else {
// out.println(" now not null");
// }
// }
// }
// }
// }
// }
protected void printComparison(String title, StringDiff string, PrintStream out) {
out.print(title + ":");
if (string == null) {
out.print("NULL");
return;
}
if (string.areEqual()) {
out.println(" EQUAL");
} else {
String referenceVersion = string.getReferenceVersion();
if (referenceVersion == null) {
referenceVersion = "NULL";
} else {
referenceVersion = "'" + referenceVersion + "'";
}
String targetVersion = string.getTargetVersion();
if (targetVersion == null) {
targetVersion = "NULL";
} else {
targetVersion = "'" + targetVersion + "'";
}
out.println();
out.println(" Reference: "
+ referenceVersion);
out.println(" Target: " + targetVersion);
}
}
}