package com.sap.cloud.lm.sl.cf.core.liquibase;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import com.sap.cloud.lm.sl.persistence.util.JdbcUtil;

import liquibase.database.jvm.JdbcConnection;
import liquibase.exception.DatabaseException;

public abstract class AbstractDataTransformationChange<OriginalDataType, TransformedDataType> extends AbstractChange {

    @Override
    protected void executeInTransaction(JdbcConnection jdbcConnection) throws Exception {
        OriginalDataType retrievedData = retrieveData(jdbcConnection);
        TransformedDataType transformedData = transformData(retrievedData);
        updateTable(jdbcConnection, transformedData);
    }

    public OriginalDataType retrieveData(JdbcConnection jdbcConnection) throws DatabaseException, SQLException {
        PreparedStatement preparedStatement = null;
        OriginalDataType result = null;

        try {
            preparedStatement = jdbcConnection.prepareStatement(getSelectStatement());
            ResultSet resultSet = preparedStatement.executeQuery();
            result = extractData(resultSet);
            resultSet.close();
        } finally {
            JdbcUtil.closeQuietly(preparedStatement);
        }
        return result;
    }

    public void updateTable(JdbcConnection jdbcConnection, TransformedDataType transformedData) throws DatabaseException, SQLException {
        PreparedStatement preparedStatement = null;

        try {
            preparedStatement = jdbcConnection.prepareStatement(getUpdateStatement());
            setUpdateStatementParameters(preparedStatement, transformedData);
            preparedStatement.executeBatch();
        } finally {
            JdbcUtil.closeQuietly(preparedStatement);
        }
    }

    public abstract TransformedDataType transformData(OriginalDataType retrievedData);

    public abstract OriginalDataType extractData(ResultSet resultSet) throws SQLException;

    public abstract String getSelectStatement();

    public abstract String getUpdateStatement();

    public abstract void setUpdateStatementParameters(PreparedStatement preparedStatement, TransformedDataType transformedData)
        throws SQLException;

}

@@ -645,32 +645,68 @@
 retrievedData);%0A
+        alterTable(jdbcConnection);%0A
         updateTa
@@ -1813,32 +1813,669 @@
        %7D%0A    %7D%0A%0A
+    public void alterTable(JdbcConnection jdbcConnection) throws DatabaseException, SQLException %7B%0A        for (String alterStatement : getAlterStatements()) %7B%0A            executeStatement(jdbcConnection, alterStatement);%0A        %7D%0A    %7D%0A%0A    private void executeStatement(JdbcConnection jdbcConnection, String statement) throws DatabaseException, SQLException %7B%0A        PreparedStatement preparedStatement = null;%0A        try %7B%0A            preparedStatement = jdbcConnection.prepareStatement(statement);%0A            preparedStatement.execute();%0A        %7D finally %7B%0A            JdbcUtil.closeQuietly(preparedStatement);%0A        %7D%0A    %7D%0A%0A
     public abstr
@@ -2730,32 +2730,112 @@
 teStatement();%0A%0A
+    public String%5B%5D getAlterStatements() %7B%0A        return new String%5B0%5D;%0A    %7D%0A%0A
     public abstr

Allow AbstractDataTransformationChanges to alter tables