1 11 package org.eclipse.jdt.internal.debug.core.hcr; 12 13 14 import java.util.ArrayList ; 15 import java.util.HashMap ; 16 import java.util.HashSet ; 17 import java.util.Iterator ; 18 import java.util.List ; 19 import java.util.Map ; 20 import java.util.Set ; 21 22 import org.eclipse.core.runtime.IProgressMonitor; 23 import org.eclipse.core.runtime.OperationCanceledException; 24 25 51 abstract class Differencer { 52 53 57 public static final int NO_CHANGE= 0; 58 61 public static final int ADDITION= 1; 62 65 public static final int DELETION= 2; 66 69 public static final int CHANGE= 3; 70 71 74 public static final int CHANGE_TYPE_MASK= 3; 75 76 80 public static final int LEFT= 4; 81 82 85 public static final int RIGHT= 8; 86 87 91 public static final int CONFLICTING= 12; 92 93 96 public static final int DIRECTION_MASK= 12; 97 98 102 public static final int PSEUDO_CONFLICT= 16; 103 104 105 static class Node { 106 List fChildren; 107 int fCode; 108 Object fAncestor; 109 Object fLeft; 110 Object fRight; 111 112 Node() { 113 } 114 Node(Node parent, Object ancestor, Object left, Object right) { 115 parent.add(this); 116 fAncestor= ancestor; 117 fLeft= left; 118 fRight= right; 119 } 120 void add(Node child) { 121 if (fChildren == null) 122 fChildren= new ArrayList (); 123 fChildren.add(child); 124 } 125 Object visit(Differencer d, Object parent, int level) { 126 if (fCode == NO_CHANGE) 127 return null; 128 Object data= d.visit(parent, fCode, fAncestor, fLeft, fRight); 130 if (fChildren != null) { 131 Iterator i= fChildren.iterator(); 132 while (i.hasNext()) { 133 Node n= (Node) i.next(); 134 n.visit(d, data, level+1); 135 } 136 } 137 return data; 138 } 139 } 140 141 144 public Differencer() { 145 } 146 147 163 public Object findDifferences(boolean threeWay, IProgressMonitor pm, Object data, Object ancestor, Object left, Object right) { 164 165 Node root= new Node(); 166 167 int code= traverse(threeWay, root, pm, threeWay ? ancestor : null, left, right); 168 169 if (code != NO_CHANGE) { 170 List l= root.fChildren; 171 if (l.size() > 0) { 172 Node first= (Node)l.get(0); 173 return first.visit(this, data, 0); 174 } 175 } 176 return null; 177 } 178 179 182 private int traverse(boolean threeWay, Node parent, IProgressMonitor pm, Object ancestor, Object left, Object right) { 183 184 Object [] ancestorChildren= getChildren(ancestor); 185 Object [] rightChildren= getChildren(right); 186 Object [] leftChildren= getChildren(left); 187 188 int code= NO_CHANGE; 189 190 Node node= new Node(parent, ancestor, left, right); 191 192 boolean content= true; 194 if (((threeWay && ancestorChildren != null) || !threeWay) 195 && rightChildren != null && leftChildren != null) { 196 199 Set allSet= new HashSet (20); 200 Map ancestorSet= null; 201 Map rightSet= null; 202 Map leftSet= null; 203 204 if (ancestorChildren != null) { 205 ancestorSet= new HashMap (10); 206 for (int i= 0; i < ancestorChildren.length; i++) { 207 Object ancestorChild= ancestorChildren[i]; 208 ancestorSet.put(ancestorChild, ancestorChild); 209 allSet.add(ancestorChild); 210 } 211 } 212 213 if (rightChildren != null) { 214 rightSet= new HashMap (10); 215 for (int i= 0; i < rightChildren.length; i++) { 216 Object rightChild= rightChildren[i]; 217 rightSet.put(rightChild, rightChild); 218 allSet.add(rightChild); 219 } 220 } 221 222 if (leftChildren != null) { 223 leftSet= new HashMap (10); 224 for (int i= 0; i < leftChildren.length; i++) { 225 Object leftChild= leftChildren[i]; 226 leftSet.put(leftChild, leftChild); 227 allSet.add(leftChild); 228 } 229 } 230 231 Iterator e= allSet.iterator(); 232 while (e.hasNext()) { 233 Object keyChild= e.next(); 234 235 content= false; 236 237 if (pm != null) { 238 239 if (pm.isCanceled()) 240 throw new OperationCanceledException(); 241 } 242 243 Object ancestorChild= ancestorSet != null ? ancestorSet.get(keyChild) : null; 244 Object leftChild= leftSet != null ? leftSet.get(keyChild) : null; 245 Object rightChild= rightSet != null ? rightSet.get(keyChild) : null; 246 247 int c= traverse(threeWay, node, pm, ancestorChild, leftChild, rightChild); 248 249 if ((c & CHANGE_TYPE_MASK) != NO_CHANGE) { 250 code|= CHANGE; code|= (c & DIRECTION_MASK); } 253 } 254 } 255 256 if (content) code= compare(threeWay, ancestor, left, right); 258 259 node.fCode= code; 260 261 return code; 262 } 263 264 282 abstract protected Object visit(Object data, int result, Object ancestor, Object left, Object right); 283 284 288 private int compare(boolean threeway, Object ancestor, Object left, Object right) { 289 290 int description= NO_CHANGE; 291 292 if (threeway) { 293 if (ancestor == null) { 294 if (left == null) { 295 if (right == null) { 296 } else { 299 description= RIGHT | ADDITION; 300 } 301 } else { 302 if (right == null) { 303 description= LEFT | ADDITION; 304 } else { 305 description= CONFLICTING | ADDITION; 306 if (contentsEqual(left, right)) 307 description|= PSEUDO_CONFLICT; 308 } 309 } 310 } else { 311 if (left == null) { 312 if (right == null) { 313 description= CONFLICTING | DELETION | PSEUDO_CONFLICT; 314 } else { 315 if (contentsEqual(ancestor, right)) 316 description= LEFT | DELETION; 317 else 318 description= CONFLICTING | CHANGE; 319 } 320 } else { 321 if (right == null) { 322 if (contentsEqual(ancestor, left)) 323 description= RIGHT | DELETION; 324 else 325 description= CONFLICTING | CHANGE; 326 } else { 327 boolean ay= contentsEqual(ancestor, left); 328 boolean am= contentsEqual(ancestor, right); 329 330 if (ay && am) 331 ; 332 else if (ay && !am) { 333 description= RIGHT | CHANGE; 334 } else if (!ay && am) { 335 description= LEFT | CHANGE; 336 } else { 337 description= CONFLICTING | CHANGE; 338 if (contentsEqual(left, right)) 339 description|= PSEUDO_CONFLICT; 340 } 341 } 342 } 343 } 344 } else { if (left == null) { 346 if (right == null) { 347 } else { 350 description= ADDITION; 351 } 352 } else { 353 if (right == null) { 354 description= DELETION; 355 } else { 356 if (! contentsEqual(left, right)) 357 description= CHANGE; 358 } 359 } 360 } 361 362 return description; 363 } 364 365 378 abstract protected boolean contentsEqual(Object input1, Object input2); 379 380 391 abstract protected Object [] getChildren(Object input); 392 } 393 394 | Popular Tags |