class AbstractChangeLogHistoryService implements ChangeLogHistoryService {

    @Getter
    private Database database;
    private String deploymentId;

    @Override
    public void setDatabase(Database database) {
        this.database = database;
    }

    @Override
    public void reset() {
    }

    @Override
    public ChangeSet.RunStatus getRunStatus(final ChangeSet changeSet)
            throws DatabaseException, DatabaseHistoryException {
        RanChangeSet foundRan = getRanChangeSet(changeSet);

        if (foundRan == null) {
            return ChangeSet.RunStatus.NOT_RAN;
        } else {
            if (foundRan.getLastCheckSum() == null) {
                try {
                    Scope.getCurrentScope().getLog(getClass()).info("Updating NULL md5sum for " + changeSet.toString());
                    replaceChecksum(changeSet);
                } catch (DatabaseException e) {
                    throw new DatabaseException(e);
                }

                return ChangeSet.RunStatus.ALREADY_RAN;
            } else {
                if (foundRan.getLastCheckSum().equals(changeSet.generateCheckSum(
                        ChecksumVersion.enumFromChecksumVersion(foundRan.getLastCheckSum().getVersion())))) {
                    return ChangeSet.RunStatus.ALREADY_RAN;
                } else {
                    if (changeSet.shouldRunOnChange()) {
                        return ChangeSet.RunStatus.RUN_AGAIN;
                    } else {
                        return ChangeSet.RunStatus.INVALID_MD5SUM;
                    }
                }
            }
        }
    }

    @Override
    public void upgradeChecksums(final DatabaseChangeLog databaseChangeLog, final Contexts contexts,
                                 LabelExpression labels) throws DatabaseException {
        for (RanChangeSet ranChangeSet : this.getRanChangeSets()) {
            if (ranChangeSet.getLastCheckSum() == null) {
                List<ChangeSet> changeSets = databaseChangeLog.getChangeSets(ranChangeSet);
                for (ChangeSet changeSet : changeSets) {
                    if ((changeSet != null) && new ContextChangeSetFilter(contexts).accepts(changeSet).isAccepted() &&
                            new DbmsChangeSetFilter(getDatabase()).accepts(changeSet).isAccepted()) {
                        Scope.getCurrentScope().getLog(getClass()).fine(
                                "Updating null or out of date checksum on changeSet " + changeSet + " to correct value"
                        );
                        replaceChecksum(changeSet);
                    }
                }
            }
        }
    }

    @Override
    public RanChangeSet getRanChangeSet(final ChangeSet changeSet) throws DatabaseException, DatabaseHistoryException {
        for (RanChangeSet ranChange : getRanChangeSets()) {
            if (ranChange.isSameAs(changeSet)) {
                return ranChange;
            }
        }
        return null;
    }

    @Override
    public Date getRanDate(ChangeSet changeSet) throws DatabaseException, DatabaseHistoryException {<FILL_FUNCTION_BODY>}

    /**
     * Returns the deployment ID of the last changeset that has been run, or {@code null} if no changesets have been run yet.
     *
     * @return the deployment ID of the last changeset that has been run, or null if no changesets have been run yet.
     * @throws DatabaseException if there is an error accessing the database
     */
     public String getLastDeploymentId() throws DatabaseException {
         List<RanChangeSet> ranChangeSetsList = getRanChangeSets();
         if (ranChangeSetsList == null || ranChangeSetsList.isEmpty()) {
             return null;
         }
         RanChangeSet lastRanChangeSet = ranChangeSetsList.get(ranChangeSetsList.size() - 1);
         return lastRanChangeSet.getDeploymentId();
    }

    @Override
    public void replaceChecksum(ChangeSet changeSet) throws DatabaseException {
        Scope.getCurrentScope().getSingleton(ExecutorService.class).getExecutor("jdbc", getDatabase()).execute(new UpdateChangeSetChecksumStatement
                (changeSet));
        getDatabase().commit();
        reset();
    }

    @Override
    public String getDeploymentId() {
        return this.deploymentId;
    }

    @Override
    public void resetDeploymentId() {
        this.deploymentId = null;
    }

    @Override
    public void generateDeploymentId() {
        if (this.deploymentId == null) {
            long time = (new Date()).getTime();
            String dateString = String.valueOf(time);
            DecimalFormat decimalFormat = new DecimalFormat("0000000000");
            this.deploymentId = dateString.length() > 9 ? dateString.substring(dateString.length() - 10) :
                    decimalFormat.format(time);
        }
    }


}

        RanChangeSet ranChange = getRanChangeSet(changeSet);
        if (ranChange == null) {
            return null;
        } else {
            return ranChange.getDateExecuted();
        }
    
<no_super_class>