Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 3608546
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 18, 20262026-05-18T21:30:54+00:00 2026-05-18T21:30:54+00:00

I’m digging through Google’s results for free (open source) Java diff libaries, and there

  • 0

I’m digging through Google’s results for free (open source) Java diff libaries, and there seem quite a bunch of those (some of them even working with generic Objects and not only with Strings).

Before I’m digging through tons of search results and not finding what I’m searching, I’ll ask here first:

Does any of those diff libraries support a feature like cvs annotate or svn blame. I want to

  • pass the current String[] to a function
  • continue passing older versions of the String[] to a function, until either I have used up all of them, or the library tells me that no original line was left unannotated (the last thing is not really a must but very useful since retrieving older versions of the String[] is expensive so I’d like to stop as early as possible)
  • call a function which gives me an ìnt[] that tells me for every line of the current version, in which version it was last changed or whether it was not changed at all (i. e. last changed in the very first version).

Having support for objects that are not Strings is nice, but no must. And if the API is not exactly that way, I guess I could live with it.

If there is none, can anybody suggest an extensible diff library where that feature can be added easily, preferrably one that would like to receive that feature as a contribution (and does not require tons of paperwork to be filled before they accept contributions, like the GNU project)? I’d volunteer to (at least try to) add it there, then.

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-18T21:30:54+00:00Added an answer on May 18, 2026 at 9:30 pm

    I decided to implement it myself for Dmitry Naumenko’s java-diff-utils library:

    /*
       Copyright 2010 Michael Schierl (schierlm@gmx.de)
    
       Licensed under the Apache License, Version 2.0 (the "License");
       you may not use this file except in compliance with the License.
       You may obtain a copy of the License at
    
           http://www.apache.org/licenses/LICENSE-2.0
    
       Unless required by applicable law or agreed to in writing, software
       distributed under the License is distributed on an "AS IS" BASIS,
       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
       See the License for the specific language governing permissions and
       limitations under the License.
     */
    package difflib.annotate;
    
    import java.util.*;
    
    import difflib.*;
    
    /**
     * Generates an annotated version of a revision based on a list of older
     * revisions, like <tt>cvs annotate</tt> or <tt>svn blame</tt>.
     * 
     * @author <a href="schierlm@gmx.de">Michael Schierl</a>
     * 
     * @param <R>
     *            Type of the revision metadata
     */
    public class Annotate<R> {
    
        private final List<R> revisions;
        private final int[] lineNumbers;
        private R currentRevision;
        private final List<Object> currentLines;
        private final List<Integer> currentLineMap;
    
        /**
         * Creates a new annotation generator.
         * 
         * @param revision
         *            Revision metadata for the revision to be annotated
         * @param targetLines
         *            Lines of the revision to be annotated
         */
        public Annotate(R revision, List<?> targetLines) {
            revisions = new ArrayList<R>();
            lineNumbers = new int[targetLines.size()];
            currentRevision = revision;
            currentLines = new ArrayList<Object>(targetLines);
            currentLineMap = new ArrayList<Integer>();
            for (int i = 0; i < lineNumbers.length; i++) {
                lineNumbers[i] = -1;
                revisions.add(null);
                currentLineMap.add(i);
            }
        }
    
        /**
         * Check whether there are still lines that are unannotated. In that case,
         * more older revisions should be retrieved and passed to the function. Note
         * that as soon as you pass an empty revision, all lines will be annotated
         * (with a later revision), therefore if you do not have any more revisions,
         * pass an empty revision to annotate the rest of the lines.
         */
        public boolean areLinesUnannotated() {
            for (int i = 0; i < lineNumbers.length; i++) {
                if (lineNumbers[i] == -1 || revisions.get(i) == null)
                    return true;
            }
            return false;
        }
    
        /**
         * Add the previous revision and update annotation info.
         * 
         * @param revision
         *            Revision metadata for this revision
         * @param lines
         *            Lines of this revision
         */
        public void addRevision(R revision, List<?> lines) {
            Patch patch = DiffUtils.diff(currentLines, lines);
            int lineOffset = 0; // remember number of already deleted/added lines
            for (Delta d : patch.getDeltas()) {
                Chunk original = d.getOriginal();
                Chunk revised = d.getRevised();
                int pos = original.getPosition() + lineOffset;
                // delete lines
                for (int i = 0; i < original.getSize(); i++) {
                    int origLine = currentLineMap.remove(pos);
                    currentLines.remove(pos);
                    if (origLine != -1) {
                        lineNumbers[origLine] = original.getPosition() + i;
                        revisions.set(origLine, currentRevision);
                    }
                }
                for (int i = 0; i < revised.getSize(); i++) {
                    currentLines.add(pos + i, revised.getLines().get(i));
                    currentLineMap.add(pos + i, -1);
                }
                lineOffset += revised.getSize() - original.getSize();
            }
    
            currentRevision = revision;
            if (!currentLines.equals(lines))
                throw new RuntimeException("Patch application failed");
        }
    
        /**
         * Return the result of the annotation. It will be a List of the same length
         * as the target revision, for which every entry states the revision where
         * the line appeared last.
         */
        public List<R> getAnnotatedRevisions() {
            return Collections.unmodifiableList(revisions);
        }
    
        /**
         * Return the result of the annotation. It will be a List of the same length
         * as the target revision, for which every entry states the line number in
         * the revision where the line appeared last.
         */
        public int[] getAnnotatedLineNumbers() {
            return (int[]) lineNumbers.clone();
        }
    }
    

    I also sent it to Dmitry Naumenko (with a few test cases) in case he wants to include it.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

link Im having trouble converting the html entites into html characters, (&# 8217;) i
Seemingly simple, but I cannot find anything relevant on the web. What is the
Does anyone know how can I replace this 2 symbol below from the string
this is what i have right now Drawing an RSS feed into the php,
I'm trying to decode HTML entries from here NYTimes.com and I cannot figure out
That's pretty much it. I'm using Nokogiri to scrape a web page what has
I have just tried to save a simple *.rtf file with some websites and
I want to count how many characters a certain string has in PHP, but
I ran into a problem. Wrote the following code snippet: teksti = teksti.Trim() teksti
I have a French site that I want to parse, but am running into

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.