1 11 package org.eclipse.jdt.internal.core; 12 13 import java.util.ArrayList ; 14 import java.util.HashMap ; 15 import java.util.HashSet ; 16 import java.util.Iterator ; 17 import java.util.Map ; 18 import java.util.Set ; 19 20 import org.eclipse.jdt.core.IJavaElement; 21 import org.eclipse.jdt.core.IJavaElementDelta; 22 import org.eclipse.jdt.core.IParent; 23 import org.eclipse.jdt.core.JavaModelException; 24 import org.eclipse.jdt.core.compiler.CharOperation; 25 import org.eclipse.jdt.internal.core.util.Util; 26 27 38 public class JavaElementDeltaBuilder { 39 42 IJavaElement javaElement; 43 44 47 int maxDepth = Integer.MAX_VALUE; 48 49 52 Map infos; 53 54 57 Map oldPositions; 58 59 62 Map newPositions; 63 64 67 public JavaElementDelta delta = null; 68 69 72 ArrayList added; 73 74 77 ArrayList removed; 78 79 82 static class ListItem { 83 public IJavaElement previous; 84 public IJavaElement next; 85 86 public ListItem(IJavaElement previous, IJavaElement next) { 87 this.previous = previous; 88 this.next = next; 89 } 90 } 91 95 public JavaElementDeltaBuilder(IJavaElement javaElement) { 96 this.javaElement = javaElement; 97 this.initialize(); 98 this.recordElementInfo( 99 javaElement, 100 (JavaModel)this.javaElement.getJavaModel(), 101 0); 102 } 103 107 public JavaElementDeltaBuilder(IJavaElement javaElement, int maxDepth) { 108 this.javaElement = javaElement; 109 this.maxDepth = maxDepth; 110 this.initialize(); 111 this.recordElementInfo( 112 javaElement, 113 (JavaModel)this.javaElement.getJavaModel(), 114 0); 115 } 116 120 private void added(IJavaElement element) { 121 this.added.add(element); 122 ListItem current = this.getNewPosition(element); 123 ListItem previous = null, next = null; 124 if (current.previous != null) 125 previous = this.getNewPosition(current.previous); 126 if (current.next != null) 127 next = this.getNewPosition(current.next); 128 if (previous != null) 129 previous.next = current.next; 130 if (next != null) 131 next.previous = current.previous; 132 } 133 137 public void buildDeltas() { 138 this.delta = new JavaElementDelta(this.javaElement); 139 if (this.javaElement.getElementType() >= IJavaElement.COMPILATION_UNIT) { 142 this.delta.fineGrained(); 143 } 144 this.recordNewPositions(this.javaElement, 0); 145 this.findAdditions(this.javaElement, 0); 146 this.findDeletions(); 147 this.findChangesInPositioning(this.javaElement, 0); 148 this.trimDelta(this.delta); 149 if (this.delta.getAffectedChildren().length == 0) { 150 this.delta.contentChanged(); 152 } 153 } 154 private boolean equals(char[][][] first, char[][][] second) { 155 if (first == second) 156 return true; 157 if (first == null || second == null) 158 return false; 159 if (first.length != second.length) 160 return false; 161 162 for (int i = first.length; --i >= 0;) 163 if (!CharOperation.equals(first[i], second[i])) 164 return false; 165 return true; 166 } 167 170 private void findAdditions(IJavaElement newElement, int depth) { 171 JavaElementInfo oldInfo = this.getElementInfo(newElement); 172 if (oldInfo == null && depth < this.maxDepth) { 173 this.delta.added(newElement); 174 added(newElement); 175 } else { 176 this.removeElementInfo(newElement); 177 } 178 179 if (depth >= this.maxDepth) { 180 this.delta.changed(newElement, IJavaElementDelta.F_CONTENT); 182 return; 183 } 184 185 JavaElementInfo newInfo = null; 186 try { 187 newInfo = (JavaElementInfo)((JavaElement)newElement).getElementInfo(); 188 } catch (JavaModelException npe) { 189 return; 190 } 191 192 this.findContentChange(oldInfo, newInfo, newElement); 193 194 if (oldInfo != null && newElement instanceof IParent) { 195 196 IJavaElement[] children = newInfo.getChildren(); 197 if (children != null) { 198 int length = children.length; 199 for(int i = 0; i < length; i++) { 200 this.findAdditions(children[i], depth + 1); 201 } 202 } 203 } 204 } 205 208 private void findChangesInPositioning(IJavaElement element, int depth) { 209 if (depth >= this.maxDepth || this.added.contains(element) || this.removed.contains(element)) 210 return; 211 212 if (!isPositionedCorrectly(element)) { 213 this.delta.changed(element, IJavaElementDelta.F_REORDER); 214 } 215 216 if (element instanceof IParent) { 217 JavaElementInfo info = null; 218 try { 219 info = (JavaElementInfo)((JavaElement)element).getElementInfo(); 220 } catch (JavaModelException npe) { 221 return; 222 } 223 224 IJavaElement[] children = info.getChildren(); 225 if (children != null) { 226 int length = children.length; 227 for(int i = 0; i < length; i++) { 228 this.findChangesInPositioning(children[i], depth + 1); 229 } 230 } 231 } 232 } 233 236 private void findContentChange(JavaElementInfo oldInfo, JavaElementInfo newInfo, IJavaElement newElement) { 237 if (oldInfo instanceof MemberElementInfo && newInfo instanceof MemberElementInfo) { 238 if (((MemberElementInfo)oldInfo).getModifiers() != ((MemberElementInfo)newInfo).getModifiers()) { 239 this.delta.changed(newElement, IJavaElementDelta.F_MODIFIERS); 240 } else if (oldInfo instanceof SourceMethodElementInfo && newInfo instanceof SourceMethodElementInfo) { 241 SourceMethodElementInfo oldSourceMethodInfo = (SourceMethodElementInfo)oldInfo; 242 SourceMethodElementInfo newSourceMethodInfo = (SourceMethodElementInfo)newInfo; 243 if (!CharOperation.equals(oldSourceMethodInfo.getReturnTypeName(), newSourceMethodInfo.getReturnTypeName()) 244 || !CharOperation.equals(oldSourceMethodInfo.getTypeParameterNames(), newSourceMethodInfo.getTypeParameterNames()) 245 || !equals(oldSourceMethodInfo.getTypeParameterBounds(), newSourceMethodInfo.getTypeParameterBounds())) { 246 this.delta.changed(newElement, IJavaElementDelta.F_CONTENT); 247 } 248 } else if (oldInfo instanceof SourceFieldElementInfo && newInfo instanceof SourceFieldElementInfo) { 249 if (!CharOperation.equals( 250 ((SourceFieldElementInfo)oldInfo).getTypeName(), 251 ((SourceFieldElementInfo)newInfo).getTypeName())) { 252 this.delta.changed(newElement, IJavaElementDelta.F_CONTENT); 253 } 254 } 255 } 256 if (oldInfo instanceof SourceTypeElementInfo && newInfo instanceof SourceTypeElementInfo) { 257 SourceTypeElementInfo oldSourceTypeInfo = (SourceTypeElementInfo)oldInfo; 258 SourceTypeElementInfo newSourceTypeInfo = (SourceTypeElementInfo)newInfo; 259 if (!CharOperation.equals(oldSourceTypeInfo.getSuperclassName(), newSourceTypeInfo.getSuperclassName()) 260 || !CharOperation.equals(oldSourceTypeInfo.getInterfaceNames(), newSourceTypeInfo.getInterfaceNames())) { 261 this.delta.changed(newElement, IJavaElementDelta.F_SUPER_TYPES); 262 } 263 if (!CharOperation.equals(oldSourceTypeInfo.getTypeParameterNames(), newSourceTypeInfo.getTypeParameterNames()) 264 || !equals(oldSourceTypeInfo.getTypeParameterBounds(), newSourceTypeInfo.getTypeParameterBounds())) { 265 this.delta.changed(newElement, IJavaElementDelta.F_CONTENT); 266 } 267 HashMap oldTypeCategories = oldSourceTypeInfo.categories; 268 HashMap newTypeCategories = newSourceTypeInfo.categories; 269 if (oldTypeCategories != null) { 270 Set elements; 272 if (newTypeCategories != null) { 273 elements = new HashSet (oldTypeCategories.keySet()); 274 elements.addAll(newTypeCategories.keySet()); 275 } else 276 elements = oldTypeCategories.keySet(); 277 Iterator iterator = elements.iterator(); 278 while (iterator.hasNext()) { 279 IJavaElement element = (IJavaElement) iterator.next(); 280 String [] oldCategories = (String []) oldTypeCategories.get(element); 281 String [] newCategories = newTypeCategories == null ? null : (String []) newTypeCategories.get(element); 282 if (!Util.equalArraysOrNull(oldCategories, newCategories)) { 283 this.delta.changed(element, IJavaElementDelta.F_CATEGORIES); 284 } 285 } 286 } else if (newTypeCategories != null) { 287 Iterator elements = newTypeCategories.keySet().iterator(); 288 while (elements.hasNext()) { 289 IJavaElement element = (IJavaElement) elements.next(); 290 this.delta.changed(element, IJavaElementDelta.F_CATEGORIES); } 292 } 293 } 294 } 295 298 private void findDeletions() { 299 Iterator iter = this.infos.keySet().iterator(); 300 while(iter.hasNext()) { 301 IJavaElement element = (IJavaElement)iter.next(); 302 this.delta.removed(element); 303 this.removed(element); 304 } 305 } 306 private JavaElementInfo getElementInfo(IJavaElement element) { 307 return (JavaElementInfo)this.infos.get(element); 308 } 309 private ListItem getNewPosition(IJavaElement element) { 310 return (ListItem)this.newPositions.get(element); 311 } 312 private ListItem getOldPosition(IJavaElement element) { 313 return (ListItem)this.oldPositions.get(element); 314 } 315 private void initialize() { 316 this.infos = new HashMap (20); 317 this.oldPositions = new HashMap (20); 318 this.newPositions = new HashMap (20); 319 this.putOldPosition(this.javaElement, new ListItem(null, null)); 320 this.putNewPosition(this.javaElement, new ListItem(null, null)); 321 this.added = new ArrayList (5); 322 this.removed = new ArrayList (5); 323 } 324 327 private void insertPositions(IJavaElement[] elements, boolean isNew) { 328 int length = elements.length; 329 IJavaElement previous = null, current = null, next = (length > 0) ? elements[0] : null; 330 for(int i = 0; i < length; i++) { 331 previous = current; 332 current = next; 333 next = (i + 1 < length) ? elements[i + 1] : null; 334 if (isNew) { 335 this.putNewPosition(current, new ListItem(previous, next)); 336 } else { 337 this.putOldPosition(current, new ListItem(previous, next)); 338 } 339 } 340 } 341 344 private boolean isPositionedCorrectly(IJavaElement element) { 345 ListItem oldListItem = this.getOldPosition(element); 346 if (oldListItem == null) return false; 347 348 ListItem newListItem = this.getNewPosition(element); 349 if (newListItem == null) return false; 350 351 IJavaElement oldPrevious = oldListItem.previous; 352 IJavaElement newPrevious = newListItem.previous; 353 if (oldPrevious == null) { 354 return newPrevious == null; 355 } else { 356 return oldPrevious.equals(newPrevious); 357 } 358 } 359 private void putElementInfo(IJavaElement element, JavaElementInfo info) { 360 this.infos.put(element, info); 361 } 362 private void putNewPosition(IJavaElement element, ListItem position) { 363 this.newPositions.put(element, position); 364 } 365 private void putOldPosition(IJavaElement element, ListItem position) { 366 this.oldPositions.put(element, position); 367 } 368 372 private void recordElementInfo(IJavaElement element, JavaModel model, int depth) { 373 if (depth >= this.maxDepth) { 374 return; 375 } 376 JavaElementInfo info = (JavaElementInfo)JavaModelManager.getJavaModelManager().getInfo(element); 377 if (info == null) return; 379 this.putElementInfo(element, info); 380 381 if (element instanceof IParent) { 382 IJavaElement[] children = info.getChildren(); 383 if (children != null) { 384 insertPositions(children, false); 385 for(int i = 0, length = children.length; i < length; i++) 386 recordElementInfo(children[i], model, depth + 1); 387 } 388 } 389 } 390 393 private void recordNewPositions(IJavaElement newElement, int depth) { 394 if (depth < this.maxDepth && newElement instanceof IParent) { 395 JavaElementInfo info = null; 396 try { 397 info = (JavaElementInfo)((JavaElement)newElement).getElementInfo(); 398 } catch (JavaModelException npe) { 399 return; 400 } 401 402 IJavaElement[] children = info.getChildren(); 403 if (children != null) { 404 insertPositions(children, true); 405 for(int i = 0, length = children.length; i < length; i++) { 406 recordNewPositions(children[i], depth + 1); 407 } 408 } 409 } 410 } 411 415 private void removed(IJavaElement element) { 416 this.removed.add(element); 417 ListItem current = this.getOldPosition(element); 418 ListItem previous = null, next = null; 419 if (current.previous != null) 420 previous = this.getOldPosition(current.previous); 421 if (current.next != null) 422 next = this.getOldPosition(current.next); 423 if (previous != null) 424 previous.next = current.next; 425 if (next != null) 426 next.previous = current.previous; 427 428 } 429 private void removeElementInfo(IJavaElement element) { 430 this.infos.remove(element); 431 } 432 public String toString() { 433 StringBuffer buffer = new StringBuffer (); 434 buffer.append("Built delta:\n"); buffer.append(this.delta == null ? "<null>" : this.delta.toString()); return buffer.toString(); 437 } 438 441 private void trimDelta(JavaElementDelta elementDelta) { 442 if (elementDelta.getKind() == IJavaElementDelta.REMOVED) { 443 IJavaElementDelta[] children = elementDelta.getAffectedChildren(); 444 for(int i = 0, length = children.length; i < length; i++) { 445 elementDelta.removeAffectedChild((JavaElementDelta)children[i]); 446 } 447 } else { 448 IJavaElementDelta[] children = elementDelta.getAffectedChildren(); 449 for(int i = 0, length = children.length; i < length; i++) { 450 trimDelta((JavaElementDelta)children[i]); 451 } 452 } 453 } 454 } 455 | Popular Tags |