public static PredicateTreeAnnotations createPredicateTreeAnnotations(Predicate predicate) {
        PredicateTreeAnalyzerResult analyzerResult = PredicateTreeAnalyzer.analyzePredicateTree(predicate);
        // The tree size is used as the interval range.
        int intervalEnd = analyzerResult.treeSize;
        AnnotatorContext context = new AnnotatorContext(intervalEnd, analyzerResult.sizeMap);
        assignIntervalLabels(predicate, Interval.INTERVAL_BEGIN, intervalEnd, false, context);
        return new PredicateTreeAnnotations(
                analyzerResult.minFeature, intervalEnd, context.intervals, context.intervalsWithBounds,
                context.featureConjunctions);
    }
@Test
    void show_different_types_of_not_intervals() {
        {
            Predicate p =
                    and(
                            or(
                                    and(
                                            feature("key").inSet("A"),
                                            not(feature("key").inSet("B"))),
                                    and(
                                            not(feature("key").inSet("C")),
                                            feature("key").inSet("D"))),
                            feature("foo").inSet("bar"));
            PredicateTreeAnnotations r = PredicateTreeAnnotator.createPredicateTreeAnnotations(p);
            assertEquals(3, r.minFeature);
            assertEquals(7, r.intervalEnd);
            assertEquals(6, r.intervalMap.size());

            assertIntervalContains(r, "foo=bar", 0x00070007);
            assertIntervalContains(r, "key=A", 0x00010001);
            assertIntervalContains(r, "key=B", 0x00020002);
            assertIntervalContains(r, "key=C", 0x00010004);
            assertIntervalContains(r, "key=D", 0x00060006);
            assertIntervalContains(r, Feature.Z_STAR_COMPRESSED_ATTRIBUTE_NAME, 0x00020001, 0x00000006, 0x00040000);
        }
        {
            Predicate p =
                    or(
                            not(feature("key").inSet("A")),
                            not(feature("key").inSet("B")));

            PredicateTreeAnnotations r = PredicateTreeAnnotator.createPredicateTreeAnnotations(p);
            assertEquals(1, r.minFeature);
            assertEquals(4, r.intervalEnd);
            assertEquals(3, r.intervalMap.size());
            assertIntervalContains(r, "key=A", 0x00010003);
            assertIntervalContains(r, "key=B", 0x00010003);
            assertIntervalContains(r, Feature.Z_STAR_COMPRESSED_ATTRIBUTE_NAME, 0x00030000, 0x00030000);
        }
        {
            Predicate p =
                    or(
                            and(
                                    not(feature("key").inSet("A")),
                                    not(feature("key").inSet("B"))),
                            and(
                                    not(feature("key").inSet("C")),
                                    not(feature("key").inSet("D"))));

            PredicateTreeAnnotations r = PredicateTreeAnnotator.createPredicateTreeAnnotations(p);
            assertEquals(1, r.minFeature);
            assertEquals(8, r.intervalEnd);
            assertEquals(5, r.intervalMap.size());
            assertIntervalContains(r, "key=A", 0x00010001);
            assertIntervalContains(r, "key=B", 0x00030007);
            assertIntervalContains(r, "key=C", 0x00010005);
            assertIntervalContains(r, "key=D", 0x00070007);
            assertIntervalContains(r, Feature.Z_STAR_COMPRESSED_ATTRIBUTE_NAME,
                    0x00010000, 0x00070002, 0x00050000, 0x00070006);
        }
    }