@Override
    public List<Change> computeDiff(List<T> source, List<T> target, DiffAlgorithmListener progress) {
        Objects.requireNonNull(source, "source list must not be null");
        Objects.requireNonNull(target, "target list must not be null");

        if (progress != null) {
            progress.diffStart();
        }

        DiffData data = new DiffData(source, target);

        int maxIdx = source.size() + target.size();

        buildScript(data, 0, source.size(), 0, target.size(), idx -> {
            if (progress != null) {
                progress.diffStep(idx, maxIdx);
            }
        });

        if (progress != null) {
            progress.diffEnd();
        }
        return data.script;
    }
@Test
    public void testDiffMyersExample1ForwardWithListener() {
        List<String> original = Arrays.asList("A", "B", "C", "A", "B", "B", "A");
        List<String> revised = Arrays.asList("C", "B", "A", "B", "A", "C");
        
        List<String> logdata = new ArrayList<>();
        final Patch<String> patch = Patch.generate(original, revised, 
                new MyersDiffWithLinearSpace<String>().computeDiff(original, revised, new DiffAlgorithmListener() {
            @Override
            public void diffStart() {
                logdata.add("start");
            }

            @Override
            public void diffStep(int value, int max) {
                logdata.add(value + " - " + max);
            }

            @Override
            public void diffEnd() {
                logdata.add("end");
            }
        }));
        assertNotNull(patch);
        System.out.println(patch);
        assertEquals(5, patch.getDeltas().size());
        assertEquals("Patch{deltas=[[InsertDelta, position: 0, lines: [C]], [DeleteDelta, position: 0, lines: [A]], [DeleteDelta, position: 2, lines: [C]], [DeleteDelta, position: 5, lines: [B]], [InsertDelta, position: 7, lines: [C]]]}", patch.toString());
        System.out.println(logdata);
        assertEquals(11, logdata.size());
    }