/*
 * FindBugs - Find bugs in Java programs
 * Copyright (C) 2004, University of Maryland
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 * 
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

package edu.umd.cs.findbugs;

import java.io.IOException;
import java.util.*;

import org.dom4j.DocumentException;

/**
 * Compute the union of two sets of bug results,
 * preserving annotations.
 */
public class UnionResults {
	private SortedBugCollection origCollection;
	private SortedBugCollection newCollection;
	private Project project;

	public UnionResults(String origFilename, String newFilename) throws IOException, DocumentException {
		this(new SortedBugCollection(), new SortedBugCollection(), new Project());
		origCollection.readXML(origFilename, new Project());
		newCollection.readXML(newFilename, this.project);
	}

	public UnionResults(SortedBugCollection origCollection, SortedBugCollection newCollection, Project project) {
		this.origCollection = origCollection;
		this.newCollection = newCollection;
		this.project = project;
	}

	public Project getProject() {
		return project;
	}

	public SortedBugCollection execute() {
		DetectorFactoryCollection.instance(); // as a side effect, loads detector plugins

		SortedBugCollection result = new SortedBugCollection();

		for (Iterator<BugInstance> i = origCollection.iterator(); i.hasNext();) {
			result.add(i.next());
		}

		for (Iterator<BugInstance> i = newCollection.iterator(); i.hasNext();) {
			BugInstance bugInstance = i.next();
			BugInstance matching = origCollection.getMatching(bugInstance);
			if (matching == null)
				result.add(bugInstance);
			else {
				// If all of the words in the new annotation are already
				// in the old annotation, don't combine the annotations.
				Set<String> oldWords = matching.getTextAnnotationWords();
				Set<String> newWords = bugInstance.getTextAnnotationWords();
				newWords.removeAll(oldWords);
				if (newWords.isEmpty())
					continue;

				// Combine the annotations
				StringBuffer buf = new StringBuffer();
				buf.append(matching.getAnnotationText());
				buf.append('\n');
				buf.append(bugInstance.getAnnotationText());
				bugInstance.setAnnotationText(buf.toString());

				result.remove(matching);
				result.add(bugInstance);
			}
		}

		return result;
	}

	public static void main(String[] argv) throws Exception {
		if (argv.length != 3) {
			System.err.println("Usage: " + UnionResults.class.getName() + " <orig results> <new results> <output file>");
			System.exit(1);
		}

		String origFilename = argv[0];
		String newFilename = argv[1];
		String outputFilename = argv[2];

		UnionResults unionResults = new UnionResults(origFilename, newFilename);
		SortedBugCollection result = unionResults.execute();
		result.writeXML(outputFilename, unionResults.getProject());
	}

	private static SortedSet<BugInstance> createSet(SortedBugCollection bugCollection) {
		SortedSet<BugInstance> set = new TreeSet<BugInstance>();
		set.addAll(bugCollection.getCollection());
		return set;
	}
}

// vim:ts=3

@@ -1062,435 +1062,121 @@
 s %7B%0A
-%09private SortedBugCollection origCollection;%0A%09private SortedBugCollection newCollection;%0A%09private Project project;%0A%0A%09public UnionResults(String origFilename, String newFilename) throws IOException, DocumentException %7B%0A%09%09this(new SortedBugCollection(), new SortedBugCollection(), new Project());%0A%09%09origCollection.readXML(origFilename, new Project());%0A%09%09newCollection.readXML(newFilename, this.project);%0A%09%7D%0A%0A%09public UnionResults(
+%0A%09static %7B%0A%09%09DetectorFactoryCollection.instance(); // as a side effect, loads detector plugins%0A%09%7D%0A%09static public 
 Sort
@@ -1195,24 +1195,15 @@
 ion 
-origCollect
+un
 ion
-,
  
+(
 Sort
@@ -1222,326 +1222,60 @@
 ion 
-newCollection, Project project) %7B%0A%09%09this.origCollection = origCollection;%0A%09%09this.newCollection = newCollection;%0A%09%09this.project = project;%0A%09%7D%0A%0A%09public Project getProject() %7B%0A%09%09return project;%0A%09%7D%0A%0A%09public SortedBugCollection execute() %7B%0A%09%09DetectorFactoryCollection.instance(); // as a side effect, loads detector plugins
+origCollection, SortedBugCollection newCollection) %7B
 %0A%0A%09%09
@@ -2400,16 +2400,18 @@
 ption %7B%0A
+%0A%0A
 %09%09if (ar
@@ -2424,12 +2424,12 @@
 gth 
-!= 3
+== 0
 ) %7B%0A
@@ -2572,127 +2572,28 @@
 %0A%09%09S
-tring origFilename = argv%5B0%5D;%0A%09%09String newFilename = argv%5B1%5D;%0A%09%09String outputFilename = argv%5B2%5D;%0A%0A%09%09UnionResults unionR
+ortedBugCollection r
 esul
@@ -2605,377 +2605,306 @@
 new 
-UnionResults(origFilename, newFilename);%0A%09%09SortedBugCollection result = unionResults.execute();%0A%09%09result.writeXML(outputFilename, unionResults.getProject());%0A%09%7D%0A%0A%09private static SortedSet%3CBugInstance%3E createSet(SortedBugCollection bugCollection) %7B%0A%09%09SortedSet%3CBugInstance%3E set = new TreeSet%3CBugInstance%3E(
+SortedBugCollection();%0A%09%09results.readXML(argv%5B0%5D, new Project());%0A%09%09for(int i = 1; i %3C argv.length; i++) %7B%0A%09%09%09SortedBugCollection more = new SortedBugCollection();%0A%09%09%09more.readXML(argv%5Bi%5D, new Project()
 );%0A%09%09
-set.addAll(bugCollection.getCollection());%0A%09%09return set
+%09results = union(results, more);%0A%09%09%7D%0A%09%0A%09%09results.writeXML(System.out, new Project())
 ;%0A%09%7D%0A
+%0A%0A
 %7D%0A%0A/

Make UnionResults take any number of xml files and sent the unioned result to standard output