source: josm/trunk/src/org/openstreetmap/josm/gui/history/TwoColumnDiff.java@ 8624

Last change on this file since 8624 was 8510, checked in by Don-vip, 9 years ago

checkstyle: enable relevant whitespace checks and fix them

  • Property svn:eol-style set to native
File size: 4.6 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.history;
3/// Feel free to move me somewhere else. Maybe a bit specific for josm.tools?
4
5import java.awt.Color;
6import java.util.ArrayList;
7import java.util.Arrays;
8import java.util.Collections;
9import java.util.List;
10
11import org.openstreetmap.josm.gui.history.TwoColumnDiff.Item.DiffItemType;
12import org.openstreetmap.josm.tools.Diff;
13import org.openstreetmap.josm.tools.Utils;
14
15/**
16 * Produces a "two column diff" of two lists. (same as diff -y)
17 *
18 * Each list is annotated with the changes relative to the other, and "empty" cells are inserted so the lists are comparable item by item.
19 *
20 * diff on [1 2 3 4] [1 a 4 5] yields:
21 *
22 * item(SAME, 1) item(SAME, 1)
23 * item(CHANGED, 2) item(CHANGED, 2)
24 * item(DELETED, 3) item(EMPTY)
25 * item(SAME, 4) item(SAME, 4)
26 * item(EMPTY) item(INSERTED, 5)
27 *
28 * @author olejorgenb
29 */
30class TwoColumnDiff {
31 public static class Item {
32
33 public enum DiffItemType {
34 INSERTED(new Color(0xDD, 0xFF, 0xDD)),
35 DELETED(new Color(255, 197, 197)),
36 CHANGED(new Color(255, 234, 213)),
37 SAME(new Color(234, 234, 234)),
38 EMPTY(new Color(234, 234, 234));
39
40 private final Color color;
41 private DiffItemType(Color color) {
42 this.color = color;
43 }
44
45 public Color getColor() {
46 return color;
47 }
48 }
49
50 public Item(DiffItemType state, Object value) {
51 this.state = state;
52 this.value = state == DiffItemType.EMPTY ? null : value;
53 }
54
55 public final Object value;
56 public final DiffItemType state;
57 }
58
59 public List<Item> referenceDiff;
60 public List<Item> currentDiff;
61 private Object[] reference;
62 private Object[] current;
63 boolean referenceReversed = false;
64
65 public TwoColumnDiff(Object[] reference, Object[] current) {
66 this.reference = Utils.copyArray(reference);
67 this.current = Utils.copyArray(current);
68 referenceDiff = new ArrayList<>();
69 currentDiff = new ArrayList<>();
70 diff();
71 }
72
73 private void diff() {
74 Diff.Change script = new Diff(reference, current).diff_2(false);
75 // attempt diff with reference reversed and test whether less deletions+inserts are required
76 Object[] referenceReversed = Utils.copyArray(reference);
77 Collections.reverse(Arrays.asList(referenceReversed));
78 Diff.Change scriptReversed = new Diff(referenceReversed, current).diff_2(false);
79 if (scriptReversed == null /* reference and current are identical */
80 || script != null && scriptReversed.deleted + scriptReversed.inserted < script.deleted + script.inserted) {
81 this.referenceReversed = true;
82 twoColumnDiffFromScript(scriptReversed, referenceReversed, current);
83 } else {
84 this.referenceReversed = false;
85 twoColumnDiffFromScript(script, reference, current);
86 }
87 }
88
89 /**
90 * The result from the diff algorithm is a "script" (a compressed description of the changes)
91 * This method expands this script into a full two column description.
92 */
93 private void twoColumnDiffFromScript(Diff.Change script, Object[] a, Object[] b) {
94 int ia = 0;
95 int ib = 0;
96
97 while (script != null) {
98 int deleted = script.deleted;
99 int inserted = script.inserted;
100 while (ia < script.line0 && ib < script.line1) {
101 Item cell = new Item(DiffItemType.SAME, a[ia]);
102 referenceDiff.add(cell);
103 currentDiff.add(cell);
104 ia++;
105 ib++;
106 }
107
108 while (inserted > 0 || deleted > 0) {
109 if (inserted > 0 && deleted > 0) {
110 referenceDiff.add(new Item(DiffItemType.CHANGED, a[ia++]));
111 currentDiff.add(new Item(DiffItemType.CHANGED, b[ib++]));
112 } else if (inserted > 0) {
113 referenceDiff.add(new Item(DiffItemType.EMPTY, null));
114 currentDiff.add(new Item(DiffItemType.INSERTED, b[ib++]));
115 } else {
116 referenceDiff.add(new Item(DiffItemType.DELETED, a[ia++]));
117 currentDiff.add(new Item(DiffItemType.EMPTY, null));
118 }
119 inserted--;
120 deleted--;
121 }
122 script = script.link;
123 }
124 while (ia < a.length && ib < b.length) {
125 referenceDiff.add(new Item(DiffItemType.SAME, a[ia++]));
126 currentDiff.add(new Item(DiffItemType.SAME, b[ib++]));
127 }
128 }
129}
Note: See TracBrowser for help on using the repository browser.