/** * Copyright 2010-2015 Axel Fontaine * <p/> * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * <p/> * http://www.apache.org/licenses/LICENSE-2.0 * <p/> * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.contrastsecurity.cassandra.migration.info; import com.contrastsecurity.cassandra.migration.config.MigrationType; import com.contrastsecurity.cassandra.migration.utils.ObjectUtils; import java.util.Date; public class MigrationInfo implements Comparable<MigrationInfo> { /** * The resolved migration to aggregate the info from. */ private final ResolvedMigration resolvedMigration; /** * The applied migration to aggregate the info from. */ private final AppliedMigration appliedMigration; /** * The current context. */ private final MigrationInfoContext context; /** * Creates a new MigrationInfoImpl. * * @param resolvedMigration The resolved migration to aggregate the info from. * @param appliedMigration The applied migration to aggregate the info from. * @param context The current context. */ public MigrationInfo(ResolvedMigration resolvedMigration, AppliedMigration appliedMigration, MigrationInfoContext context) { this.resolvedMigration = resolvedMigration; this.appliedMigration = appliedMigration; this.context = context; } /** * @return The resolved migration to aggregate the info from. */ public ResolvedMigration getResolvedMigration() { return resolvedMigration; } /** * @return The applied migration to aggregate the info from. */ public AppliedMigration getAppliedMigration() { return appliedMigration; } public MigrationType getType() { if (appliedMigration != null) { return appliedMigration.getType(); } return resolvedMigration.getType(); } public Integer getChecksum() { if (appliedMigration != null) { return appliedMigration.getChecksum(); } return resolvedMigration.getChecksum(); } public MigrationVersion getVersion() { if (appliedMigration != null) { return appliedMigration.getVersion(); } return resolvedMigration.getVersion(); } public String getDescription() { if (appliedMigration != null) { return appliedMigration.getDescription(); } return resolvedMigration.getDescription(); } public String getScript() { if (appliedMigration != null) { return appliedMigration.getScript(); } return resolvedMigration.getScript(); } public MigrationState getState() { if (appliedMigration == null) { if (resolvedMigration.getVersion().compareTo(context.baseline) < 0) { return MigrationState.BELOW_BASELINE; } if (resolvedMigration.getVersion().compareTo(context.target) > 0) { return MigrationState.ABOVE_TARGET; } if ((resolvedMigration.getVersion().compareTo(context.lastApplied) < 0) && !context.outOfOrder) { return MigrationState.IGNORED; } return MigrationState.PENDING; } if (resolvedMigration == null) { if (MigrationType.SCHEMA == appliedMigration.getType()) { return MigrationState.SUCCESS; } if (MigrationType.BASELINE == appliedMigration.getType()) { return MigrationState.BASELINE; } if (getVersion().compareTo(context.lastResolved) < 0) { if (appliedMigration.isSuccess()) { return MigrationState.MISSING_SUCCESS; } return MigrationState.MISSING_FAILED; } if (getVersion().compareTo(context.lastResolved) > 0) { if (appliedMigration.isSuccess()) { return MigrationState.FUTURE_SUCCESS; } return MigrationState.FUTURE_FAILED; } } if (appliedMigration.isSuccess()) { if (appliedMigration.getVersionRank() == appliedMigration.getInstalledRank()) { return MigrationState.SUCCESS; } return MigrationState.OUT_OF_ORDER; } return MigrationState.FAILED; } public Date getInstalledOn() { if (appliedMigration != null) { return appliedMigration.getInstalledOn(); } return null; } public Integer getExecutionTime() { if (appliedMigration != null) { return appliedMigration.getExecutionTime(); } return null; } /** * Validates this migrationInfo for consistency. * * @return The error message, or {@code null} if everything is fine. */ public String validate() { if (!context.pendingOrFuture && (resolvedMigration == null) && (appliedMigration.getType() != MigrationType.SCHEMA) && (appliedMigration.getType() != MigrationType.BASELINE)) { return "Detected applied migration not resolved locally: " + getVersion(); } if ((!context.pendingOrFuture && (MigrationState.PENDING == getState())) || (MigrationState.IGNORED == getState())) { return "Detected resolved migration not applied to database: " + getVersion(); } if (resolvedMigration != null && appliedMigration != null) { if (getVersion().compareTo(context.baseline) > 0) { if (resolvedMigration.getType() != appliedMigration.getType()) { return createMismatchMessage("Type", appliedMigration.getVersion(), appliedMigration.getType(), resolvedMigration.getType()); } if (!ObjectUtils.nullSafeEquals(resolvedMigration.getChecksum(), appliedMigration.getChecksum())) { return createMismatchMessage("Checksum", appliedMigration.getVersion(), appliedMigration.getChecksum(), resolvedMigration.getChecksum()); } if (!resolvedMigration.getDescription().equals(appliedMigration.getDescription())) { return createMismatchMessage("Description", appliedMigration.getVersion(), appliedMigration.getDescription(), resolvedMigration.getDescription()); } } } return null; } /** * Creates a message for a mismatch. * * @param mismatch The type of mismatch. * @param version The offending version. * @param applied The applied value. * @param resolved The resolved value. * @return The message. */ private String createMismatchMessage(String mismatch, MigrationVersion version, Object applied, Object resolved) { return String.format("Migration " + mismatch + " mismatch for migration %s\n" + "-> Applied to database : %s\n" + "-> Resolved locally : %s", version, applied, resolved); } @SuppressWarnings("NullableProblems") public int compareTo(MigrationInfo o) { return getVersion().compareTo(o.getVersion()); } @SuppressWarnings("SimplifiableIfStatement") @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; MigrationInfo that = (MigrationInfo) o; if (appliedMigration != null ? !appliedMigration.equals(that.appliedMigration) : that.appliedMigration != null) return false; if (!context.equals(that.context)) return false; return !(resolvedMigration != null ? !resolvedMigration.equals(that.resolvedMigration) : that.resolvedMigration != null); } @Override public int hashCode() { int result = resolvedMigration != null ? resolvedMigration.hashCode() : 0; result = 31 * result + (appliedMigration != null ? appliedMigration.hashCode() : 0); result = 31 * result + context.hashCode(); return result; } }