cogA set of diff/merge APIs
Developed by

XWiki Development Team

0 Votes
LicenseGNU Lesser General Public License 2.1

Since 4.1 Milestone 2


Since there is no real standard API for it and that most of the existing library are not very active enough or very tied to various EDIs we decided to write our own API for XWiki ecosystem which would be independent from the actual implementation.

Base API module

Expose generic diff and merge component implementing org.xwiki.commons.diff.DiffManager role.

The main idea of this API is that it's not tied to any type so you have to first transform the datas you want to diff into lists and the diff will be a diff between thoses two lists.

For example when you want to diff text you can choose if you want to to a line based diff, a word based diff, a character based diff, etc.

public interface DiffManager
     * Produce a diff between the two provided versions.
     * @param <E> the type of compared elements
     * @param previous the previous version of the content to compare
     * @param next the next version of the content to compare
     * @param configuration the configuration of the diff behavior
     * @return the result of the diff
     * @throws DiffException error when executing the diff
    <E> DiffResult<E> diff(List<E> previous, List<E> next, DiffConfiguration<E> configuration) throws DiffException;

     * Execute a 3-way merge on provided versions.
     * @param <E> the type of compared elements
     * @param commonAncestor the common ancestor of the two versions of the content to compare
     * @param next the next version of the content to compare
     * @param current the current version of the content to compare
     * @param configuration the configuration of the merge behavior
     * @return the result of the merge
     * @throws MergeException error when executing the merge
    <E> MergeResult<E> merge(List<E> commonAncestor, List<E> next, List<E> current, MergeConfiguration<E> configuration)
        throws MergeException;

Display API module

This module helps you display a DiffResult obtained with the base API in various formats. Currently there are two diff formats supported.

Inline diff

An inline diff is made of a list of chunks, each marked as added, removed or unmodified. For instance, if changes are computed at word level, you can have this inline diff:

The quicksick brown fox jumpsstumbles over the lazycrazy mad dog.

At character level the diff looks a bit different:

the qusick brown fox

In this case the first chunk is "the ", an unmodified chunk, made of 4 characters and the second chunk is "qu", a removed chunk, made of 2 characters. An inline diff can be displayed either as you've seen above, mixing added and removed chunks in one line, or it can be displayed on two lines, one showing the removed chunks and the other the added chunks:

The quick brown fox jumps over the lazy dog.
The sick brown fox stumbles over the crazy mad dog.

Unified diff

An unified diff consists in a list of blocks, each block grouping changes that are close to each other. The distance between two changes in a block is less than 2 * context size, where context size represents the number of unmodified elements to include before and after a change in order to place that change in context.

If the elements can be split in sub-elements, i.e. if a splitter is provided through the configuration, then the unified diff displays also the changes inside the modified elements using the inline format.

If changes are computed at the line level in a text, i.e. the elements that are compared to produce the diff are lines of text, and a word splitter is provided through configuration then the following is a block from a unified diff:

@@ -81,5 +85,5 @@
 first line of context
 another unmodified line
-this line <del>has been removed</del>
+this line <ins>replaced the previous line</ins>
 close the block with unmodified lines
 last line of context

Script service

Expose more script oriented APIs of the two previous modules. It also adds helpers like String based APIs etc.

## Compute the differences between two lists of elements (e.g. lines of text).
#set ($diffResult = $services.diff.diff($previous, $next, $configuration))

## Display the differences between two texts in the unified format.
#foreach ($block in $services.diff.display.unified($previous, $next))
Created by Thomas Mortagne on 2012/05/31 15:53

Get Connected