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
42 } catch (JavaModelException e) {
43 // do nothing - we already checked if open
49 * Closes the given element, which removes it from the cache of open
52 protected static void close(Openable element) {
56 } catch (JavaModelException e) {
62 * Processing for an element that has been added:
64 * <li>If the element is a project, do nothing, and do not process
65 * children, as when a project is created it does not yet have any natures -
66 * specifically a java nature.
67 * <li>If the elemet is not a project, process it as added (see
68 * <code>basicElementAdded</code>.
71 protected void elementAdded(Openable element) {
73 int elementType = element.getElementType();
74 if (elementType == IJavaElement.JAVA_PROJECT) {
75 // project add is handled by JavaProject.configure() because
76 // when a project is created, it does not yet have a java nature
77 addToParentInfo(element);
78 this.projectsToUpdate.add(element);
80 addToParentInfo(element);
82 // Force the element to be closed as it might have been opened
83 // before the resource modification came in and it might have a new
85 // For example, in an IWorkspaceRunnable:
86 // 1. create a package fragment p using a java model operation
88 // 3. add file X.java in folder p
89 // When the resource delta comes in, only the addition of p is
91 // but the package p is already opened, thus its children are not
93 // and it appears empty.
97 switch (elementType) {
98 case IJavaElement.PACKAGE_FRAGMENT_ROOT:
99 // when a root is added, and is on the classpath, the project must
101 this.projectsToUpdate.add(element.getJavaProject());
103 case IJavaElement.PACKAGE_FRAGMENT:
104 // get rid of package fragment cache
105 JavaProject project = (JavaProject) element.getJavaProject();
106 // project.resetCaches();
112 * Generic processing for elements with changed contents:
114 * <li>The element is closed such that any subsequent accesses will re-open
115 * the element reflecting its new structure.
118 protected void elementChanged(Openable element) {
124 * Generic processing for a removed element:
126 * <li>Close the element, removing its structure from the cache
127 * <li>Remove the element from its parent's cache of children
128 * <li>Add a REMOVED entry in the delta
131 protected void elementRemoved(Openable element) {
133 if (element.isOpen()) {
136 removeFromParentInfo(element);
137 int elementType = element.getElementType();
139 switch (elementType) {
140 case IJavaElement.JAVA_MODEL:
141 // JavaModelManager.getJavaModelManager().getIndexManager().reset();
143 case IJavaElement.JAVA_PROJECT:
144 JavaModelManager.getJavaModelManager().removePerProjectInfo(
145 (JavaProject) element);
147 case IJavaElement.PACKAGE_FRAGMENT_ROOT:
148 this.projectsToUpdate.add(element.getJavaProject());
150 case IJavaElement.PACKAGE_FRAGMENT:
151 // get rid of package fragment cache
152 JavaProject project = (JavaProject) element.getJavaProject();
153 // project.resetCaches();
159 * Converts a <code>IResourceDelta</code> rooted in a
160 * <code>Workspace</code> into the corresponding set of
161 * <code>IJavaElementDelta</code>, rooted in the relevant
162 * <code>JavaModel</code>s.
164 public void processJavaDelta(IJavaElementDelta delta) {
166 // if (DeltaProcessor.VERBOSE){
167 // System.out.println("UPDATING Model with Delta:
168 // ["+Thread.currentThread()+":" + delta +
169 // "]:");//$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
173 this.traverseDelta(delta, null, null); // traverse delta
175 // update package fragment roots of projects that were affected
176 Iterator iterator = this.projectsToUpdate.iterator();
177 while (iterator.hasNext()) {
178 JavaProject project = (JavaProject) iterator.next();
179 project.updatePackageFragmentRoots();
182 this.projectsToUpdate = new HashSet();
187 * Removes the given element from its parents cache of children. If the
188 * element does not have a parent, or the parent is not currently open, this
191 protected void removeFromParentInfo(Openable child) {
193 Openable parent = (Openable) child.getParent();
194 if (parent != null && parent.isOpen()) {
196 JavaElementInfo info = (JavaElementInfo) parent
198 info.removeChild(child);
199 } catch (JavaModelException e) {
200 // do nothing - we already checked if open
206 * Converts an <code>IResourceDelta</code> and its children into the
207 * corresponding <code>IJavaElementDelta</code>s. Return whether the
208 * delta corresponds to a resource on the classpath. If it is not a resource
209 * on the classpath, it will be added as a non-java resource by the sender
212 protected void traverseDelta(IJavaElementDelta delta,
213 IPackageFragmentRoot root, IJavaProject project) {
215 boolean processChildren = true;
217 Openable element = (Openable) delta.getElement();
218 switch (element.getElementType()) {
219 case IJavaElement.JAVA_PROJECT:
220 project = (IJavaProject) element;
222 case IJavaElement.PACKAGE_FRAGMENT_ROOT:
223 root = (IPackageFragmentRoot) element;
225 case IJavaElement.COMPILATION_UNIT:
226 // filter out working copies that are not primary (we don't want to
227 // add/remove them to/from the package fragment
228 CompilationUnit cu = (CompilationUnit) element;
229 if (cu.isWorkingCopy() && !cu.isPrimary()) {
232 case IJavaElement.CLASS_FILE:
233 processChildren = false;
237 switch (delta.getKind()) {
238 case IJavaElementDelta.ADDED:
239 elementAdded(element);
241 case IJavaElementDelta.REMOVED:
242 elementRemoved(element);
244 case IJavaElementDelta.CHANGED:
245 if ((delta.getFlags() & IJavaElementDelta.F_CONTENT) != 0) {
246 elementChanged(element);
250 if (processChildren) {
251 IJavaElementDelta[] children = delta.getAffectedChildren();
252 for (int i = 0; i < children.length; i++) {
253 IJavaElementDelta childDelta = children[i];
254 this.traverseDelta(childDelta, root, project);