ProgrammableChangeSet.java

/*
 * Copyright 2024 Global Crop Diversity Trust
 *
 * 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
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * 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 org.genesys.custom.liquibase;

import liquibase.change.CheckSum;
import liquibase.changelog.ChangeSet;
import liquibase.changelog.DatabaseChangeLog;
import liquibase.changelog.visitor.ChangeExecListener;
import liquibase.database.Database;
import liquibase.exception.MigrationFailedException;
import liquibase.precondition.Precondition;
import liquibase.precondition.core.PreconditionContainer;
import liquibase.util.StringUtil;

public class ProgrammableChangeSet extends ChangeSet {

	private final Executable instructions;
	private String description;

	public ProgrammableChangeSet(String id, String filePath, Executable instructions, String description, String comments,
		String dbmsList, String contextList, boolean alwaysRun, String author, DatabaseChangeLog databaseChangeLog) {
		super(id, author, alwaysRun, false, filePath, contextList, dbmsList, databaseChangeLog);
		this.instructions = instructions;
		this.description = description;
		this.setComments(comments);
	}

	@Override
	public CheckSum generateCheckSum() {
		if (checkSum == null) {
			StringBuilder stringToMD5 = new StringBuilder();
			stringToMD5.append(getId()).append(":");
			stringToMD5.append(isAlwaysRun()).append(":");
			stringToMD5.append(isRunOnChange()).append(":");

			checkSum = CheckSum.compute(stringToMD5.toString());
		}

		return checkSum;
	}

	@Override
	public String getDescription() {
		return StringUtil.limitSize(this.description, 255);
	}

	@Override
	public ExecType execute(DatabaseChangeLog databaseChangeLog, ChangeExecListener listener, Database database) throws MigrationFailedException {
		try {
			if (instructions == null) {
				throw new MigrationFailedException(this, "Instructions for execution must not be null!");
			}
			instructions.execute();
			return ExecType.EXECUTED;
		} catch (Exception e) {
			throw new MigrationFailedException(this, e);
		}
	}

	public ProgrammableChangeSet preConditions(PreconditionContainer.FailOption onFail, Precondition precondition) {
		var pre = new PreconditionContainer();
		pre.setOnFail(onFail);
		pre.addNestedPrecondition(precondition);
		this.setPreconditions(pre);
		return this;
	}

	public interface Executable {
		void execute() throws Exception;
	}
}