1 11 package org.eclipse.team.internal.core.mapping; 12 13 import java.util.*; 14 15 import org.eclipse.core.runtime.IPath; 16 17 20 public class PathTree { 21 22 class Node { 23 Object payload; 24 Set descendantsWithPayload; 25 int flags; 26 public boolean isEmpty() { 27 return payload == null && (descendantsWithPayload == null || descendantsWithPayload.isEmpty()); 28 } 29 public Object getPayload() { 30 return payload; 31 } 32 public void setPayload(Object payload) { 33 this.payload = payload; 34 } 35 public boolean hasDescendants() { 36 return descendantsWithPayload != null && !descendantsWithPayload.isEmpty(); 37 } 38 public boolean hasFlag(int propertyBit) { 39 return (flags & propertyBit) != 0; 40 } 41 public void setProperty(int propertyBit, boolean value) { 42 if (value) 43 flags |= propertyBit; 44 else 45 flags ^= propertyBit; 46 } 47 public boolean descendantHasFlag(int property) { 48 if (hasDescendants()) { 49 for (Iterator iter = descendantsWithPayload.iterator(); iter.hasNext();) { 50 IPath path = (IPath) iter.next(); 51 Node child = getNode(path); 52 if (child.hasFlag(property)) { 53 return true; 54 } 55 } 56 } 57 return false; 58 } 59 } 60 61 private Map objects = new HashMap(); 62 63 69 public synchronized Object get(IPath path) { 70 Node node = getNode(path); 71 if (node == null) 72 return null; 73 return node.getPayload(); 74 } 75 76 84 public synchronized Object put(IPath path, Object object) { 85 Node node = getNode(path); 86 if (node == null) { 87 node = addNode(path); 88 } 89 Object previous = node.getPayload(); 90 node.setPayload(object); 91 if(previous == null) { 92 addToParents(path, path); 93 } 94 return previous; 95 } 96 97 105 public synchronized Object remove(IPath path) { 106 Node node = getNode(path); 107 if (node == null) 108 return null; 109 Object previous = node.getPayload(); 110 node.setPayload(null); 111 if(previous != null) { 112 removeFromParents(path, path); 113 if (node.isEmpty()) { 114 removeNode(path); 115 } 116 } 117 return previous; 118 119 } 120 121 126 public synchronized boolean hasChildren(IPath path) { 127 if (path.isEmpty()) return !objects.isEmpty(); 128 Node node = getNode(path); 129 if (node == null) 130 return false; 131 return node.hasDescendants(); 132 } 133 134 139 public synchronized IPath[] getChildren(IPath path) { 140 Set children = new HashSet(); 143 Node node = getNode(path); 144 if (node != null) { 145 Set possibleChildren = node.descendantsWithPayload; 146 if(possibleChildren != null) { 147 for (Iterator it = possibleChildren.iterator(); it.hasNext();) { 148 Object next = it.next(); 149 IPath descendantPath = (IPath)next; 150 IPath childPath = null; 151 if(descendantPath.segmentCount() == (path.segmentCount() + 1)) { 152 childPath = descendantPath; 153 } else if (descendantPath.segmentCount() > path.segmentCount()) { 154 childPath = descendantPath.removeLastSegments(descendantPath.segmentCount() - path.segmentCount() - 1); 155 } 156 if (childPath != null) { 157 children.add(childPath); 158 } 159 } 160 } 161 } 162 return (IPath[]) children.toArray(new IPath[children.size()]); 163 } 164 165 private boolean addToParents(IPath path, IPath parent) { 166 boolean addedParent = false; 168 if (path == parent) { 169 addedParent = true; 171 } else { 172 Node node = getNode(parent); 173 if (node == null) 174 node = addNode(parent); 175 Set children = node.descendantsWithPayload; 176 if (children == null) { 177 children = new HashSet(); 178 node.descendantsWithPayload = children; 179 addedParent = true; 181 } 182 children.add(path); 183 } 184 if ((parent.segmentCount() == 0 || !addToParents(path, parent.removeLastSegments(1))) && addedParent) { 186 } 189 return addedParent; 190 } 191 192 private boolean removeFromParents(IPath path, IPath parent) { 193 boolean removedParent = false; 195 Node node = getNode(parent); 196 if (node == null) { 197 removedParent = true; 199 } else { 200 Set children = node.descendantsWithPayload; 201 if (children == null) { 202 removedParent = true; 204 } else { 205 children.remove(path); 206 if (children.isEmpty()) { 207 node.descendantsWithPayload = null; 208 if (node.isEmpty()) 209 removeNode(parent); 210 removedParent = true; 211 } 212 } 213 } 214 if ((parent.segmentCount() == 0 || !removeFromParents(path, parent.removeLastSegments(1))) && removedParent) { 216 } 219 return removedParent; 220 } 221 222 225 public synchronized void clear() { 226 objects.clear(); 227 } 228 229 233 public synchronized boolean isEmpty() { 234 return objects.isEmpty(); 235 } 236 237 241 public synchronized IPath[] getPaths() { 242 List result = new ArrayList(); 243 for (Iterator iter = objects.keySet().iterator(); iter.hasNext();) { 244 IPath path = (IPath) iter.next(); 245 Node node = getNode(path); 246 if (node.getPayload() != null) 247 result.add(path); 248 } 249 return (IPath[]) result.toArray(new IPath[result.size()]); 250 } 251 252 256 public synchronized Collection values() { 257 List result = new ArrayList(); 258 for (Iterator iter = objects.keySet().iterator(); iter.hasNext();) { 259 IPath path = (IPath) iter.next(); 260 Node node = getNode(path); 261 if (node.getPayload() != null) 262 result.add(node.getPayload()); 263 } 264 return result; 265 } 266 267 271 public int size() { 272 return values().size(); 273 } 274 275 private Node getNode(IPath path) { 276 return (Node)objects.get(path); 277 } 278 279 private Node addNode(IPath path) { 280 Node node; 281 node = new Node(); 282 objects.put(path, node); 283 return node; 284 } 285 286 private Object removeNode(IPath path) { 287 return objects.remove(path); 288 } 289 290 299 public synchronized IPath[] setPropogatedProperty(IPath path, int property, boolean value) { 300 Set changed = new HashSet(); 301 internalSetPropertyBit(path, property, value, changed); 302 return (IPath[]) changed.toArray(new IPath[changed.size()]); 303 } 304 305 private void internalSetPropertyBit(IPath path, int property, boolean value, Set changed) { 306 if (path.segmentCount() == 0) 307 return; 308 Node node = getNode(path); 309 if (node == null) 310 return; 311 if (value == node.hasFlag(property)) 313 return; 314 if (!value && node.descendantHasFlag(property)) 316 return; 317 node.setProperty(property, value); 318 changed.add(path); 319 internalSetPropertyBit(path.removeLastSegments(1), property, value, changed); 320 } 321 322 public synchronized boolean getProperty(IPath path, int property) { 323 if (path.segmentCount() == 0) 324 return false; 325 Node node = getNode(path); 326 if (node == null) 327 return false; 328 return (node.hasFlag(property)); 329 } 330 331 } 332 | Popular Tags |