// Path: src/main/java/org/madlonkay/supertmxmerge/data/DiffAnalysis.java
// public class DiffAnalysis<T> {
//     public final Set<T> deleted;
//     public final Set<T> added;
//     public final Set<T> modified;
//     
//     public DiffAnalysis(Set<T> deleted, Set<T> added, Set<T> modified) {
//         this.deleted = Collections.unmodifiableSet(deleted);
//         this.added = Collections.unmodifiableSet(added);
//         this.modified = Collections.unmodifiableSet(modified);
//     }
// }
// 
// Path: src/main/java/org/madlonkay/supertmxmerge/data/MergeAnalysis.java
// public class MergeAnalysis<K,V> {
//     public final Set<K> deleted;
//     public final Set<K> added;
//     public final Map<K, V> modified;
//     public final Set<K> conflicts;
//     
//     public static MergeAnalysis unmodifiableAnalysis(MergeAnalysis analysis) {
//         return new MergeAnalysis(Collections.unmodifiableSet(analysis.deleted),
//                 Collections.unmodifiableSet(analysis.added),
//                 Collections.unmodifiableMap(analysis.modified),
//                 Collections.unmodifiableSet(analysis.conflicts));
//     }
//     
//     public MergeAnalysis(Set<K> deleted, Set<K> added, Map<K,V> modified, Set<K> conflicts) {
//         this.deleted = deleted;
//         this.added = added;
//         this.modified = modified;
//         this.conflicts = conflicts;
//     }
//     
//     public boolean hasConflicts() {
//         return !conflicts.isEmpty();
//     }
// }


import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.madlonkay.supertmxmerge.data.DiffAnalysis;
import org.madlonkay.supertmxmerge.data.MergeAnalysis;
            if (leftItem == null) {
                // We don't delete in this case because it would duplicate when we deleted
                // in the similar case above.
            } else if (baseItem.equals(leftItem)) {
                toDelete.add(key);
            } else {
                conflicts.add(key);
            }
        }
        // Modified on left
        for (K key : baseToLeft.modified) {
            if (conflicts.contains(key)) {
                continue;
            }
            V baseItem = base.get(key);
            V leftItem = left.get(key);
            V rightItem = right.get(key);
            if (leftItem.equals(rightItem) || baseItem.equals(rightItem)) {
                toReplace.put(key, leftItem);
            } else {
                conflicts.add(key);
            }
        }
        // Modified on right
        for (K key : baseToRight.modified) {
            if (conflicts.contains(key)) {
                continue;
            }
            V leftItem = left.get(key);
            V rightItem = right.get(key);
// Path: src/main/java/org/madlonkay/supertmxmerge/data/DiffAnalysis.java
// public class DiffAnalysis<T> {
//     public final Set<T> deleted;
//     public final Set<T> added;
//     public final Set<T> modified;
//     
//     public DiffAnalysis(Set<T> deleted, Set<T> added, Set<T> modified) {
//         this.deleted = Collections.unmodifiableSet(deleted);
//         this.added = Collections.unmodifiableSet(added);
//         this.modified = Collections.unmodifiableSet(modified);
//     }
// }
// 
// Path: src/main/java/org/madlonkay/supertmxmerge/data/MergeAnalysis.java
// public class MergeAnalysis<K,V> {
//     public final Set<K> deleted;
//     public final Set<K> added;
//     public final Map<K, V> modified;
//     public final Set<K> conflicts;
//     
//     public static MergeAnalysis unmodifiableAnalysis(MergeAnalysis analysis) {
//         return new MergeAnalysis(Collections.unmodifiableSet(analysis.deleted),
//                 Collections.unmodifiableSet(analysis.added),
//                 Collections.unmodifiableMap(analysis.modified),
//                 Collections.unmodifiableSet(analysis.conflicts));
//     }
//     
//     public MergeAnalysis(Set<K> deleted, Set<K> added, Map<K,V> modified, Set<K> conflicts) {
//         this.deleted = deleted;
//         this.added = added;
//         this.modified = modified;
//         this.conflicts = conflicts;
//     }
//     
//     public boolean hasConflicts() {
//         return !conflicts.isEmpty();
//     }
// }


// Path: src/main/java/org/madlonkay/supertmxmerge/util/DiffUtil.java
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.madlonkay.supertmxmerge.data.DiffAnalysis;
import org.madlonkay.supertmxmerge.data.MergeAnalysis;

            if (leftItem == null) {
                // We don't delete in this case because it would duplicate when we deleted
                // in the similar case above.
            } else if (baseItem.equals(leftItem)) {
                toDelete.add(key);
            } else {
                conflicts.add(key);
            }
        }
        // Modified on left
        for (K key : baseToLeft.modified) {
            if (conflicts.contains(key)) {
                continue;
            }
            V baseItem = base.get(key);
            V leftItem = left.get(key);
            V rightItem = right.get(key);
            if (leftItem.equals(rightItem) || baseItem.equals(rightItem)) {
                toReplace.put(key, leftItem);
            } else {
                conflicts.add(key);
            }
        }
        // Modified on right
        for (K key : baseToRight.modified) {
            if (conflicts.contains(key)) {
                continue;
            }
            V leftItem = left.get(key);
            V rightItem = right.get(key);
            V baseItem = base.get(key);