1 /*******************************************************************************
2 * Copyright (c) 2000, 2004 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Common Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/cpl-v10.html
9 * IBM Corporation - initial API and implementation
10 *******************************************************************************/
12 package net.sourceforge.phpdt.internal.core;
14 import java.util.HashSet;
15 import java.util.Iterator;
17 import net.sourceforge.phpdt.core.IJavaElement;
18 import net.sourceforge.phpdt.core.IJavaElementDelta;
19 import net.sourceforge.phpdt.core.IJavaProject;
20 import net.sourceforge.phpdt.core.IPackageFragmentRoot;
21 import net.sourceforge.phpdt.core.JavaModelException;
24 * This class is used by <code>JavaModelManager</code> to update the JavaModel
25 * based on some <code>IJavaElementDelta</code>s.
27 public class ModelUpdater {
29 HashSet projectsToUpdate = new HashSet();
32 * Adds the given child handle to its parent's cache of children.
34 protected void addToParentInfo(Openable child) {
36 Openable parent = (Openable) child.getParent();
37 if (parent != null && parent.isOpen()) {
39 JavaElementInfo info = (JavaElementInfo)parent.getElementInfo();
41 } catch (JavaModelException e) {
42 // do nothing - we already checked if open
48 * Closes the given element, which removes it from the cache of open elements.
50 protected static void close(Openable element) {
54 } catch (JavaModelException e) {
60 * Processing for an element that has been added:<ul>
61 * <li>If the element is a project, do nothing, and do not process
62 * children, as when a project is created it does not yet have any
63 * natures - specifically a java nature.
64 * <li>If the elemet is not a project, process it as added (see
65 * <code>basicElementAdded</code>.
68 protected void elementAdded(Openable element) {
70 int elementType = element.getElementType();
71 if (elementType == IJavaElement.JAVA_PROJECT) {
72 // project add is handled by JavaProject.configure() because
73 // when a project is created, it does not yet have a java nature
74 addToParentInfo(element);
75 this.projectsToUpdate.add(element);
77 addToParentInfo(element);
79 // Force the element to be closed as it might have been opened
80 // before the resource modification came in and it might have a new child
81 // For example, in an IWorkspaceRunnable:
82 // 1. create a package fragment p using a java model operation
84 // 3. add file X.java in folder p
85 // When the resource delta comes in, only the addition of p is notified,
86 // but the package p is already opened, thus its children are not recomputed
87 // and it appears empty.
91 switch (elementType) {
92 case IJavaElement.PACKAGE_FRAGMENT_ROOT :
93 // when a root is added, and is on the classpath, the project must be updated
94 this.projectsToUpdate.add(element.getJavaProject());
96 case IJavaElement.PACKAGE_FRAGMENT :
97 // get rid of package fragment cache
98 JavaProject project = (JavaProject) element.getJavaProject();
99 // project.resetCaches();
105 * Generic processing for elements with changed contents:<ul>
106 * <li>The element is closed such that any subsequent accesses will re-open
107 * the element reflecting its new structure.
110 protected void elementChanged(Openable element) {
116 * Generic processing for a removed element:<ul>
117 * <li>Close the element, removing its structure from the cache
118 * <li>Remove the element from its parent's cache of children
119 * <li>Add a REMOVED entry in the delta
122 protected void elementRemoved(Openable element) {
124 if (element.isOpen()) {
127 removeFromParentInfo(element);
128 int elementType = element.getElementType();
130 switch (elementType) {
131 case IJavaElement.JAVA_MODEL :
132 // JavaModelManager.getJavaModelManager().getIndexManager().reset();
134 case IJavaElement.JAVA_PROJECT :
135 JavaModelManager.getJavaModelManager().removePerProjectInfo(
136 (JavaProject) element);
138 case IJavaElement.PACKAGE_FRAGMENT_ROOT :
139 this.projectsToUpdate.add(element.getJavaProject());
141 case IJavaElement.PACKAGE_FRAGMENT :
142 // get rid of package fragment cache
143 JavaProject project = (JavaProject) element.getJavaProject();
144 // project.resetCaches();
150 * Converts a <code>IResourceDelta</code> rooted in a <code>Workspace</code> into
151 * the corresponding set of <code>IJavaElementDelta</code>, rooted in the
152 * relevant <code>JavaModel</code>s.
154 public void processJavaDelta(IJavaElementDelta delta) {
156 // if (DeltaProcessor.VERBOSE){
157 // System.out.println("UPDATING Model with Delta: ["+Thread.currentThread()+":" + delta + "]:");//$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
161 this.traverseDelta(delta, null, null); // traverse delta
163 // update package fragment roots of projects that were affected
164 Iterator iterator = this.projectsToUpdate.iterator();
165 while (iterator.hasNext()) {
166 JavaProject project = (JavaProject) iterator.next();
167 project.updatePackageFragmentRoots();
170 this.projectsToUpdate = new HashSet();
175 * Removes the given element from its parents cache of children. If the
176 * element does not have a parent, or the parent is not currently open,
177 * this has no effect.
179 protected void removeFromParentInfo(Openable child) {
181 Openable parent = (Openable) child.getParent();
182 if (parent != null && parent.isOpen()) {
184 JavaElementInfo info = (JavaElementInfo)parent.getElementInfo();
185 info.removeChild(child);
186 } catch (JavaModelException e) {
187 // do nothing - we already checked if open
193 * Converts an <code>IResourceDelta</code> and its children into
194 * the corresponding <code>IJavaElementDelta</code>s.
195 * Return whether the delta corresponds to a resource on the classpath.
196 * If it is not a resource on the classpath, it will be added as a non-java
197 * resource by the sender of this method.
199 protected void traverseDelta(
200 IJavaElementDelta delta,
201 IPackageFragmentRoot root,
202 IJavaProject project) {
204 boolean processChildren = true;
206 Openable element = (Openable) delta.getElement();
207 switch (element.getElementType()) {
208 case IJavaElement.JAVA_PROJECT :
209 project = (IJavaProject) element;
211 case IJavaElement.PACKAGE_FRAGMENT_ROOT :
212 root = (IPackageFragmentRoot) element;
214 case IJavaElement.COMPILATION_UNIT :
215 // filter out working copies that are not primary (we don't want to add/remove them to/from the package fragment
216 CompilationUnit cu = (CompilationUnit)element;
217 if (cu.isWorkingCopy() && !cu.isPrimary()) {
220 case IJavaElement.CLASS_FILE :
221 processChildren = false;
225 switch (delta.getKind()) {
226 case IJavaElementDelta.ADDED :
227 elementAdded(element);
229 case IJavaElementDelta.REMOVED :
230 elementRemoved(element);
232 case IJavaElementDelta.CHANGED :
233 if ((delta.getFlags() & IJavaElementDelta.F_CONTENT) != 0){
234 elementChanged(element);
238 if (processChildren) {
239 IJavaElementDelta[] children = delta.getAffectedChildren();
240 for (int i = 0; i < children.length; i++) {
241 IJavaElementDelta childDelta = children[i];
242 this.traverseDelta(childDelta, root, project);