1 package org.vaadin.aceeditor;
2
3 import java.util.Collections;
4 import java.util.LinkedList;
5 import java.util.List;
6 import java.util.Map;
7 import java.util.Set;
8
9 import name.fraser.neil.plaintext.diff_match_patch;
10 import name.fraser.neil.plaintext.diff_match_patch.Patch;
11
12 import org.vaadin.aceeditor.client.AceAnnotation.MarkerAnnotation;
13 import org.vaadin.aceeditor.client.AceAnnotation.RowAnnotation;
14 import org.vaadin.aceeditor.client.AceDoc;
15 import org.vaadin.aceeditor.client.AceMarker;
16 import org.vaadin.aceeditor.client.MarkerSetDiff;
17 import org.vaadin.aceeditor.client.SetDiff;
18 import org.vaadin.aceeditor.client.TransportDiff;
19 import org.vaadin.aceeditor.client.TransportDiff.TransportSetDiffForMarkerAnnotations;
20 import org.vaadin.aceeditor.client.TransportDiff.TransportSetDiffForRowAnnotations;
21 import org.vaadin.aceeditor.client.TransportDoc.TransportMarkerAnnotation;
22 import org.vaadin.aceeditor.client.TransportDoc.TransportRowAnnotation;
23
24
25
26
27 public class ServerSideDocDiff {
28
29
30
31
32
33
34
35
36
37
38
39
40
41 private static diff_match_patch getDmp() {
42 return new diff_match_patch();
43 }
44
45 private final LinkedList<Patch> patches;
46 private final MarkerSetDiff markerSetDiff;
47 private final SetDiff<RowAnnotation,TransportRowAnnotation> rowAnnDiff;
48 private final SetDiff<MarkerAnnotation,TransportMarkerAnnotation> markerAnnDiff;
49
50 public static ServerSideDocDiff diff(AceDoc doc1, AceDoc doc2) {
51 LinkedList<Patch> patches = getDmp().patch_make(doc1.getText(), doc2.getText());
52 MarkerSetDiff msd = MarkerSetDiff.diff(doc1.getMarkers(), doc2.getMarkers(), doc2.getText());
53 SetDiff<RowAnnotation,TransportRowAnnotation> rowAnnDiff =
54 diffRA(doc1.getRowAnnotations(), doc2.getRowAnnotations());
55 SetDiff<MarkerAnnotation,TransportMarkerAnnotation> markerAnnDiff =
56 diffMA(doc1.getMarkerAnnotations(), doc2.getMarkerAnnotations());
57 return new ServerSideDocDiff(patches, msd, rowAnnDiff, markerAnnDiff);
58 }
59
60 public static ServerSideDocDiff diff(String text1, String text2) {
61 LinkedList<Patch> patches = getDmp().patch_make(text1, text2);
62 return new ServerSideDocDiff(patches);
63 }
64
65
66
67 private static SetDiff<MarkerAnnotation, TransportMarkerAnnotation> diffMA(
68 Set<MarkerAnnotation> anns1,
69 Set<MarkerAnnotation> anns2) {
70 if (anns2 == null && anns1 != null) {
71 return null;
72 }
73 if (anns1==null) {
74 anns1 = Collections.emptySet();
75 }
76 if (anns2==null) {
77 anns2 = Collections.emptySet();
78 }
79 return new SetDiff.Differ<MarkerAnnotation,TransportMarkerAnnotation>().diff(anns1, anns2);
80 }
81
82
83 private static SetDiff<RowAnnotation, TransportRowAnnotation> diffRA(
84 Set<RowAnnotation> anns1,
85 Set<RowAnnotation> anns2) {
86 if (anns2 == null && anns1 != null) {
87 return null;
88 }
89 if (anns1==null) {
90 anns1 = Collections.emptySet();
91 }
92 if (anns2==null) {
93 anns2 = Collections.emptySet();
94 }
95 return new SetDiff.Differ<RowAnnotation,TransportRowAnnotation>().diff(anns1, anns2);
96 }
97
98
99 public static ServerSideDocDiff fromTransportDiff(TransportDiff diff) {
100 return new ServerSideDocDiff(
101 (LinkedList<Patch>) getDmp().patch_fromText(diff.patchesAsString),
102 MarkerSetDiff.fromTransportDiff(diff.markerSetDiff),
103 rowAnnsFromTransport(diff.rowAnnDiff),
104 markerAnnsFromTransport(diff.markerAnnDiff));
105 }
106
107
108 private static SetDiff<RowAnnotation,TransportRowAnnotation> rowAnnsFromTransport(
109 TransportSetDiffForRowAnnotations rowAnnDiff) {
110 return rowAnnDiff==null ? null : SetDiff.fromTransport(rowAnnDiff);
111 }
112
113
114 private static SetDiff<MarkerAnnotation,TransportMarkerAnnotation> markerAnnsFromTransport(
115 TransportSetDiffForMarkerAnnotations markerAnnDiff) {
116 return markerAnnDiff==null ? null : SetDiff.fromTransport(markerAnnDiff);
117 }
118
119 private ServerSideDocDiff(LinkedList<Patch> patches, MarkerSetDiff markerSetDiff,
120 SetDiff<RowAnnotation,TransportRowAnnotation> rowAnnDiff,
121 SetDiff<MarkerAnnotation,TransportMarkerAnnotation> markerAnnDiff) {
122 this.patches = patches;
123 this.markerSetDiff = markerSetDiff;
124 this.rowAnnDiff = rowAnnDiff;
125 this.markerAnnDiff = markerAnnDiff;
126 }
127
128 public ServerSideDocDiff(LinkedList<Patch> patches) {
129 this(patches, null, null, null);
130 }
131
132 public String getPatchesString() {
133 return getDmp().patch_toText(patches);
134 }
135
136 public List<Patch> getPatches() {
137 return Collections.unmodifiableList(patches);
138 }
139
140
141 public AceDoc applyTo(AceDoc doc) {
142 String text = (String)getDmp().patch_apply(patches, doc.getText())[0];
143 Map<String, AceMarker> markers = markerSetDiff==null ? doc.getMarkers() : markerSetDiff.applyTo(doc.getMarkers(), text);
144 Set<RowAnnotation> rowAnns = rowAnnDiff==null ? null : rowAnnDiff.applyTo(doc.getRowAnnotations());
145 Set<MarkerAnnotation> markerAnns = markerAnnDiff==null ? null : markerAnnDiff.applyTo(doc.getMarkerAnnotations());
146 return new AceDoc(text, markers, rowAnns, markerAnns);
147 }
148
149 public String applyTo(String text) {
150 return (String)getDmp().patch_apply(patches, text)[0];
151 }
152
153 public TransportDiff asTransport() {
154 TransportDiff d = new TransportDiff();
155 d.patchesAsString = getPatchesString();
156 d.markerSetDiff = markerSetDiff==null ? null : markerSetDiff.asTransportDiff();
157 d.rowAnnDiff = rowAnnDiff==null ? null : rowAnnDiff.asTransportRowAnnotations();
158 d.markerAnnDiff = markerAnnDiff==null ? null : markerAnnDiff.asTransportMarkerAnnotations();
159 return d;
160 }
161
162 public boolean isIdentity() {
163 return patches.isEmpty() && (markerSetDiff==null || markerSetDiff.isIdentity());
164 }
165
166 @Override
167 public String toString() {
168 return "---ServerSideDocDiff---\n" + getPatchesString()+"\n"+markerSetDiff+"\nrad:"+rowAnnDiff+", mad:"+markerAnnDiff;
169 }
170
171
172 public static ServerSideDocDiff newMarkersAndAnnotations(
173 MarkerSetDiff msd, SetDiff<MarkerAnnotation,TransportMarkerAnnotation> mad) {
174 LinkedList<Patch> patches = new LinkedList<Patch>();
175 SetDiff<RowAnnotation,TransportRowAnnotation> rowAnnDiff =
176 new SetDiff<RowAnnotation, TransportRowAnnotation>();
177 return new ServerSideDocDiff(patches, msd, rowAnnDiff, mad);
178 }
179
180 }