package liquibase.diff.compare;
import liquibase.CatalogAndSchema;
import liquibase.database.Database;
import liquibase.exception.UnexpectedLiquibaseException;
import liquibase.structure.DatabaseObject;
import liquibase.structure.core.DatabaseObjectFactory;
import liquibase.util.StringUtils;
import java.util.*;
public class CompareControl {
private CompareControl.SchemaComparison[] schemaComparisons;
private Set<Class<? extends DatabaseObject>> compareTypes = new HashSet<Class<? extends DatabaseObject>>();
private Map<Class<? extends DatabaseObject>, Set<String>> suppressedFields = new HashMap<Class<? extends DatabaseObject>, Set<String>>();
public static CompareControl STANDARD = new CompareControl();
public CompareControl() {
this(null);
}
public CompareControl(Set<Class<? extends DatabaseObject>> compareTypes) {
schemaComparisons = new SchemaComparison[]{new SchemaComparison(new CatalogAndSchema(null, null), new CatalogAndSchema(null, null))};
setTypes(compareTypes);
}
public CompareControl(SchemaComparison[] schemaComparison, Set<Class<? extends DatabaseObject>> compareTypes) {
this.schemaComparisons = schemaComparison;
setTypes(compareTypes);
}
public CompareControl(SchemaComparison[] schemaComparison, String compareTypes) {
if (schemaComparison != null && schemaComparison.length > 0) {
this.schemaComparisons = schemaComparison;
} else {
this.schemaComparisons = new SchemaComparison[]{new SchemaComparison(new CatalogAndSchema(null, null), new CatalogAndSchema(null, null))};
}
setTypes(DatabaseObjectFactory.getInstance().parseTypes(compareTypes));
}
public CompareControl(String[] referenceVsComparisonSchemas, Set<Class<? extends DatabaseObject>> compareTypes) {
String[] splitReferenceSchemas = referenceVsComparisonSchemas[0].split(",");
String[] splitComparisonSchemas = referenceVsComparisonSchemas[1].split(",");
this.schemaComparisons = new SchemaComparison[splitReferenceSchemas.length];
for (int i = 0; i < splitReferenceSchemas.length; i++) {
String referenceCatalogName = null;
String referenceSchemaName = splitReferenceSchemas[i];
if (referenceSchemaName.contains(".")) {
referenceCatalogName = referenceSchemaName.split(".", 2)[0];
referenceSchemaName = referenceSchemaName.split(".", 2)[1];
}
String comparisonCatalogName = null;
String comparisonSchemaName = splitComparisonSchemas[i];
if (comparisonSchemaName.contains(".")) {
comparisonCatalogName = comparisonSchemaName.split(".", 2)[0];
comparisonSchemaName = comparisonSchemaName.split(".", 2)[1];
}
CatalogAndSchema referenceSchema = new CatalogAndSchema(referenceCatalogName, referenceSchemaName);
CatalogAndSchema comparisonSchema = new CatalogAndSchema(comparisonCatalogName, comparisonSchemaName);
this.schemaComparisons[i] = new SchemaComparison(referenceSchema, comparisonSchema);
setTypes(compareTypes);
}
}
protected void setTypes(Set<Class<? extends DatabaseObject>> types) {
if (types == null || types.size() == 0) {
types = DatabaseObjectFactory.getInstance().getStandardTypes();
}
this.compareTypes = types;
}
public Set<Class<? extends DatabaseObject>> getComparedTypes() {
return compareTypes;
}
public CompareControl addSuppressedField(Class<? extends DatabaseObject> type, String field) {
if (!suppressedFields.containsKey(type)) {
suppressedFields.put(type, new HashSet<String>());
}
suppressedFields.get(type).add(field);
return this;
}
public boolean isSuppressedField(Class<? extends DatabaseObject> type, String field) {
if (!suppressedFields.containsKey(type)) {
return false;
}
return suppressedFields.get(type).contains(field);
}
public SchemaComparison[] getSchemaComparisons() {
return schemaComparisons;
}
public CatalogAndSchema[] getSchemas(DatabaseRole databaseRole) {
CatalogAndSchema[] schemas = new CatalogAndSchema[schemaComparisons.length];
for (int i=0; i<schemaComparisons.length; i++) {
if (databaseRole.equals(DatabaseRole.COMPARISON)) {
schemas[i] = schemaComparisons[i].getComparisonSchema();
} else if (databaseRole.equals(DatabaseRole.REFERENCE)) {
schemas[i] = schemaComparisons[i].getReferenceSchema();
} else {
throw new UnexpectedLiquibaseException("Unknkown diff type: " + databaseRole);
}
}
return schemas;
}
public static enum DatabaseRole {
REFERENCE,
COMPARISON
}
public static class SchemaComparison {
private CatalogAndSchema comparisonSchema;
private CatalogAndSchema referenceSchema;
private String outputSchemaAs;
public SchemaComparison(CatalogAndSchema reference, CatalogAndSchema comparison) {
this.referenceSchema = reference;
this.comparisonSchema = comparison;
}
public CatalogAndSchema getComparisonSchema() {
return comparisonSchema;
}
public CatalogAndSchema getReferenceSchema() {
return referenceSchema;
}
public String getOutputSchemaAs() {
return outputSchemaAs;
}
public void setOutputSchemaAs(String outputSchemaAs) {
this.outputSchemaAs = outputSchemaAs;
}
public static String convertSchema(String schemaName, SchemaComparison[] schemaComparisons) {
if (schemaComparisons == null || schemaComparisons.length == 0 || schemaName == null) {
return schemaName;
}
String convertedSchemaName = null;
for (CompareControl.SchemaComparison comparison : schemaComparisons) {
if (schemaName.equals(comparison.getComparisonSchema().getSchemaName())) {
convertedSchemaName = comparison.getReferenceSchema().getSchemaName();
} else if (schemaName.equals(comparison.getComparisonSchema().getCatalogName())) {
convertedSchemaName = comparison.getReferenceSchema().getCatalogName();
} else if (schemaName.equals(comparison.getReferenceSchema().getSchemaName())) {
convertedSchemaName = comparison.getComparisonSchema().getSchemaName();
} else if (schemaName.equals(comparison.getReferenceSchema().getCatalogName())) {
convertedSchemaName = comparison.getComparisonSchema().getCatalogName();
}
}
if (convertedSchemaName == null) {
return schemaName;
} else {
return convertedSchemaName;
}
}
}
public static ComputedSchemas computeSchemas(String schemaNames, String referenceSchemaNames, String outputSchemaNames, String defaultCatalogName, String defaultSchemaName, String referenceDefaultCatalogName, String referenceDefaultSchemaName, Database database) {
//Make sure either both schemaNames and referenceSchemaNames are set or both are null. If only one is set, make them equal
if (schemaNames == null && referenceSchemaNames == null) {
;//they will be set to the defaults
} else if (schemaNames == null && referenceSchemaNames != null) {
schemaNames = referenceSchemaNames;
} else if (schemaNames != null && referenceSchemaNames == null) {
referenceSchemaNames = schemaNames;
}
if (schemaNames == null && outputSchemaNames != null) {
if (defaultSchemaName == null) {
schemaNames = database.getDefaultSchemaName();
} else {
schemaNames = defaultSchemaName;
}
referenceSchemaNames = schemaNames;
}
ComputedSchemas returnObj = new ComputedSchemas();
if (referenceSchemaNames == null) {
returnObj.finalSchemaComparisons = new CompareControl.SchemaComparison[]{new CompareControl.SchemaComparison(
new CatalogAndSchema(referenceDefaultCatalogName, referenceDefaultSchemaName),
new CatalogAndSchema(defaultCatalogName, defaultSchemaName)
)};
returnObj.finalTargetSchemas = new CatalogAndSchema[]{new CatalogAndSchema(defaultCatalogName, defaultSchemaName)};
} else {
List<SchemaComparison> schemaComparisons = new ArrayList<CompareControl.SchemaComparison>();
List<CatalogAndSchema> referenceSchemas = new ArrayList<CatalogAndSchema>();
List<CatalogAndSchema> targetSchemas = new ArrayList<CatalogAndSchema>();
List<String> splitReferenceSchemaNames = StringUtils.splitAndTrim(referenceSchemaNames, ",");
List<String> splitSchemaNames = StringUtils.splitAndTrim(schemaNames, ",");
List<String> splitOutputSchemaNames = StringUtils.splitAndTrim(StringUtils.trimToNull(outputSchemaNames), ",");
if (splitReferenceSchemaNames.size() != splitSchemaNames.size()) {
throw new UnexpectedLiquibaseException("You must specify the same number of schemas in --schemas and --referenceSchemas");
}
if (splitOutputSchemaNames != null && splitOutputSchemaNames.size() != splitSchemaNames.size()) {
throw new UnexpectedLiquibaseException("You must specify the same number of schemas in --schemas and --outputSchemasAs");
}
for (int i=0; i<splitReferenceSchemaNames.size(); i++) {
String referenceSchema = splitReferenceSchemaNames.get(i);
String targetSchema = splitSchemaNames.get(i);
String outputSchema = null;
if (splitOutputSchemaNames != null) {
outputSchema = splitOutputSchemaNames.get(i);
}
CatalogAndSchema correctedTargetSchema = new CatalogAndSchema(null, targetSchema).customize(database);
CatalogAndSchema correctedReferenceSchema = new CatalogAndSchema(null, referenceSchema).customize(database);
SchemaComparison comparison = new SchemaComparison(correctedReferenceSchema, correctedTargetSchema);
comparison.setOutputSchemaAs(outputSchema);
schemaComparisons.add(comparison);
referenceSchemas.add(correctedReferenceSchema);
targetSchemas.add(correctedTargetSchema);
}
returnObj.finalSchemaComparisons = schemaComparisons.toArray(new CompareControl.SchemaComparison[schemaComparisons.size()]);
returnObj.finalTargetSchemas = targetSchemas.toArray(new CatalogAndSchema[targetSchemas.size()]);
}
return returnObj;
}
public static class ComputedSchemas {
public CompareControl.SchemaComparison[] finalSchemaComparisons;
public CatalogAndSchema[] finalTargetSchemas;
}
}