@Override
    public Predicate accept(Visitor visitor, IndexRegistry indexes) {
        Predicate target = predicate;
        if (predicate instanceof VisitablePredicate visitablePredicate) {
            target = visitablePredicate.accept(visitor, indexes);
        }
        if (target == predicate) {
            // visitor didn't change the inner predicate
            return visitor.visit(this, indexes);
        }

        // visitor returned a different copy of the inner predicate.
        // We have to create our copy with the new inner predicate to maintained immutability
        NotPredicate copy = new NotPredicate(target);
        return visitor.visit(copy, indexes);
    }
@Test
    public void accept_whenPredicateChangedOnAccept_thenReturnAndNewNotPredicate() {
        Visitor mockVisitor = createPassthroughVisitor();
        IndexRegistry mockIndexes = mock(IndexRegistry.class);

        Predicate transformed = mock(Predicate.class);
        Predicate predicate = createMockVisitablePredicate(transformed);

        NotPredicate notPredicate = new NotPredicate(predicate);
        NotPredicate result = (NotPredicate) notPredicate.accept(mockVisitor, mockIndexes);

        assertThat(result).isNotSameAs(notPredicate);
        assertThat(result.predicate).isEqualTo(transformed);
    }