class BranchAwareSmellTypeAnalysis implements Query {

    @Override
    public void query() throws QueryException {
        Smell smell;
        Commit previousCommit;
        Commit commit = Commit.empty();
        Integer previousBranch;
        Integer currentBranch = -1;

        Map<String, Object> instance;
        while (smells.hasNext()) {
            instance = smells.next();
            previousCommit = commit;
            previousBranch = currentBranch;
            commit = Commit.fromInstance(instance);
            smell = Smell.fromPaprikaInstance(instance, smellType);
            try {
                currentBranch = fetchCommitBranch(commit);
            } catch (BranchNotFoundException e) {
                logger.warn("[" + projectId + "] ==> Unable to guess branch for commit (" + commit.sha + "), skipping", e.getMessage());
                continue;
            }

            // We create the new BranchAnalyzer if needed.
            if (!branchAnalyzers.containsKey(currentBranch)) {
                logger.debug("[" + projectId + "] => Initializing new branch: " + currentBranch);
                initializeBranch(currentBranch);
            }

            // We set the commit ordinal, branch-wise to enable our BranchAnalyzer
            // to correctly handle gaps.
            commit.setBranchOrdinal(fetchCommitOrdinal(currentBranch, commit));
            branchAnalyzers.get(currentBranch).notifyCommit(commit);

            // On commit change, we ensure to merge SmellPresence from the merged commit if necessary.
            if (!previousCommit.equals(commit)) {
                synchronizeMergeSmells(commit, currentBranch);
            }

            // Once the previous Smells are all set, notify our newly found smell.
            branchAnalyzers.get(currentBranch).notifySmell(smell);

            // When we are sure that we passed the last branch commit, we will finalize the branch analysis,
            // i.e. setting introductions and refactoring for the last branch commit.
            if (!previousCommit.equals(commit) && isLastBranchCommit(previousCommit, previousBranch)) {
                finalizeBranch(previousBranch);
                branchAnalyzers.remove(previousBranch);
            }
        }

        // We should only perform operations for branch 0 since all other commits are looped around.
        // On top of that, we may have missed some branch finalization because of lost commits.
        for (int branchId : branchAnalyzers.keySet()) {
            finalizeBranch(branchId);
        }
    }

      BranchAwareSmellTypeAnalysis(int projectId, Persistence persistence, Iterator<Map<String, Object>> smells,
                                 String smellType, SmellDuplicationChecker duplicationChecker,
                                 CommitQueries commitQueries, SmellQueries smellQueries, BranchQueries branchQueries);

}