class UpToTagChangeSetFilter implements ChangeSetFilter {
    private final String tag;
    private boolean seenTag;
    private String ranChangesetTagId = null;


    public UpToTagChangeSetFilter(String tag, List<RanChangeSet> ranChangeSets) {
        this.tag = tag;
        for (RanChangeSet ranChangeSet : ranChangeSets) {
            if (tag.equalsIgnoreCase(ranChangeSet.getTag())) {
                ranChangesetTagId = ranChangeSet.toString();
                break;
            }
        }

    }

    public boolean isSeenTag() {
        return seenTag;
    }

    @Override
    public ChangeSetFilterResult accepts(ChangeSet changeSet) {<FILL_FUNCTION_BODY>}

    @Override
    public String getMdcName() {
        return "afterTag";
    }

    @Override
    public String getDisplayName() {
        return "After tag";
    }
}

        if (seenTag) {
            return new ChangeSetFilterResult(false, "Changeset is after tag '" + this.tag + "'", this.getClass(), getMdcName(), getDisplayName());
        }

        // if the tag is already in the database, accept the changesets until we find it
        if (changeSet.toString().equals(this.ranChangesetTagId)) {
            seenTag = true;
        // otherwise validate each new changeset until we find the tag
        } else {
            String changesetTag = null;
            for (Change change : changeSet.getChanges()) {
                if (change instanceof TagDatabaseChange) {
                    changesetTag = ((TagDatabaseChange) change).getTag();
                }
            }

            if (this.tag.equals(changesetTag)) {
                seenTag = true;
            }
        }

        return new ChangeSetFilterResult(true, "Changeset is at or before tag '" + this.tag + "'", this.getClass(), getMdcName(), getDisplayName());
    
<no_super_class>