package liquibase.changelog.visitor;

import liquibase.changelog.ChangeSet;
import liquibase.changelog.DatabaseChangeLog;
import liquibase.changelog.filter.ChangeSetFilterResult;
import liquibase.database.Database;
import liquibase.exception.LiquibaseException;
import liquibase.logging.LogService;
import liquibase.logging.LogType;

import java.util.Set;

public class RollbackVisitor implements ChangeSetVisitor {

    private Database database;

    private ChangeExecListener execListener;

    /**
     * @deprecated - please use the constructor with ChangeExecListener, which can be null.
     */
    @Deprecated
    public RollbackVisitor(Database database) {
        this.database = database;
    }

    public RollbackVisitor(Database database, ChangeExecListener listener) {
        this(database);
        this.execListener = listener;
    }

    @Override
    public Direction getDirection() {
        return ChangeSetVisitor.Direction.REVERSE;
    }

    @Override
    public void visit(ChangeSet changeSet, DatabaseChangeLog databaseChangeLog, Database database, Set<ChangeSetFilterResult> filterResults) throws LiquibaseException {
        LogService.getLog(getClass()).info(LogType.USER_MESSAGE, "Rolling Back Changeset:" + changeSet);
        changeSet.rollback(this.database, this.execListener);
        this.database.removeRanStatus(changeSet);
        sendRollbackEvent(changeSet, databaseChangeLog, database);
        this.database.commit();

    }

    private void sendRollbackEvent(ChangeSet changeSet, DatabaseChangeLog databaseChangeLog, Database database2) {
        if (execListener != null) {
            execListener.rolledBack(changeSet, databaseChangeLog, database);
        }
    }
}

@@ -31,16 +31,92 @@
 sitor;%0A%0A
+import liquibase.change.Change;%0Aimport liquibase.change.core.SQLFileChange;%0A
 import l
@@ -191,16 +191,62 @@
 ngeLog;%0A
+import liquibase.changelog.RollbackContainer;%0A
 import l
@@ -449,16 +449,39 @@
 gType;%0A%0A
+import java.util.List;%0A
 import j
@@ -1601,16 +1601,840 @@
 mmit();%0A
+        checkForEmptyRollbackFile(changeSet);%0A    %7D%0A%0A    private void checkForEmptyRollbackFile(ChangeSet changeSet) %7B%0A        RollbackContainer container = changeSet.getRollback();%0A        List%3CChange%3E changes = container.getChanges();%0A        if (changes.isEmpty()) %7B%0A            return;%0A        %7D%0A        for (Change change : changes) %7B%0A            if (! (change instanceof SQLFileChange)) %7B%0A                continue;%0A            %7D%0A            String sql = ((SQLFileChange)change).getSql();%0A            if (sql.length() == 0) %7B%0A                LogService.getLog(getClass())%0A                          .info(%22%5CnNo rollback logic defined in empty rollback script. Changesets have been removed from%5Cn%22 +%0A                                %22the DATABASECHANGELOG table but no other logic was performed.%22);%0A            %7D%0A        %7D
 %0A    %7D%0A%0A

Handle empty rollback file which occurs in a <rollback> tag DAT-4080