@Override
    public Predicate visit(OrPredicate orPredicate, IndexRegistry indexes) {
        Predicate[] originalInnerPredicates = orPredicate.predicates;
        if (originalInnerPredicates == null || originalInnerPredicates.length < MINIMUM_NUMBER_OF_OR_TO_REPLACE) {
            return orPredicate;
        }

        InternalListMultiMap<String, Integer> candidates = findAndGroupCandidates(originalInnerPredicates);
        if (candidates == null) {
            return orPredicate;
        }
        int toBeRemoved = 0;
        boolean modified = false;
        Predicate[] target = originalInnerPredicates;
        for (Map.Entry<String, List<Integer>> candidate : candidates.entrySet()) {
            String attribute = candidate.getKey();
            List<Integer> positions = candidate.getValue();
            if (positions.size() < MINIMUM_NUMBER_OF_OR_TO_REPLACE) {
                continue;
            }
            if (!modified) {
                modified = true;
                target = createCopy(target);
            }
            toBeRemoved = replaceForAttribute(attribute, target, positions, toBeRemoved);
        }
        Predicate[] newInnerPredicates = replaceInnerPredicates(target, toBeRemoved);
        return getOrCreateFinalPredicate(orPredicate, originalInnerPredicates, newInnerPredicates);
    }
@Test
    public void whenThresholdExceeded_noEnoughCandidatesFound_thenReturnItself() {
        // (age != 1 or age != 2 or age != 3 or age != 4 or age != 5)
        Predicate p1 = equal("age", 1);
        Predicate p2 = equal("age", 2);
        Predicate p3 = equal("age", 3);
        Predicate p4 = equal("age", 4);
        Predicate p5 = notEqual("age", 5);
        OrPredicate or = (OrPredicate) or(p1, p2, p3, p4, p5);
        OrPredicate result = (OrPredicate) visitor.visit(or, indexes);
        assertThat(or).isEqualTo(result);
    }