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.*;
20 * This class is used by <code>JavaModelManager</code> to update the JavaModel
21 * based on some <code>IJavaElementDelta</code>s.
23 public class ModelUpdater {
25 HashSet projectsToUpdate = new HashSet();
28 * Adds the given child handle to its parent's cache of children.
30 protected void addToParentInfo(Openable child) {
32 Openable parent = (Openable) child.getParent();
33 if (parent != null && parent.isOpen()) {
35 JavaElementInfo info = (JavaElementInfo)parent.getElementInfo();
37 } catch (JavaModelException e) {
38 // do nothing - we already checked if open
44 * Closes the given element, which removes it from the cache of open elements.
46 protected static void close(Openable element) {
50 } catch (JavaModelException e) {
56 * Processing for an element that has been added:<ul>
57 * <li>If the element is a project, do nothing, and do not process
58 * children, as when a project is created it does not yet have any
59 * natures - specifically a java nature.
60 * <li>If the elemet is not a project, process it as added (see
61 * <code>basicElementAdded</code>.
64 protected void elementAdded(Openable element) {
66 int elementType = element.getElementType();
67 if (elementType == IJavaElement.JAVA_PROJECT) {
68 // project add is handled by JavaProject.configure() because
69 // when a project is created, it does not yet have a java nature
70 addToParentInfo(element);
71 this.projectsToUpdate.add(element);
73 addToParentInfo(element);
75 // Force the element to be closed as it might have been opened
76 // before the resource modification came in and it might have a new child
77 // For example, in an IWorkspaceRunnable:
78 // 1. create a package fragment p using a java model operation
80 // 3. add file X.java in folder p
81 // When the resource delta comes in, only the addition of p is notified,
82 // but the package p is already opened, thus its children are not recomputed
83 // and it appears empty.
87 switch (elementType) {
88 case IJavaElement.PACKAGE_FRAGMENT_ROOT :
89 // when a root is added, and is on the classpath, the project must be updated
90 this.projectsToUpdate.add(element.getJavaProject());
92 case IJavaElement.PACKAGE_FRAGMENT :
93 // get rid of package fragment cache
94 JavaProject project = (JavaProject) element.getJavaProject();
95 // project.resetCaches();
101 * Generic processing for elements with changed contents:<ul>
102 * <li>The element is closed such that any subsequent accesses will re-open
103 * the element reflecting its new structure.
106 protected void elementChanged(Openable element) {
112 * Generic processing for a removed element:<ul>
113 * <li>Close the element, removing its structure from the cache
114 * <li>Remove the element from its parent's cache of children
115 * <li>Add a REMOVED entry in the delta
118 protected void elementRemoved(Openable element) {
120 if (element.isOpen()) {
123 removeFromParentInfo(element);
124 int elementType = element.getElementType();
126 switch (elementType) {
127 case IJavaElement.JAVA_MODEL :
128 // JavaModelManager.getJavaModelManager().getIndexManager().reset();
130 case IJavaElement.JAVA_PROJECT :
131 JavaModelManager.getJavaModelManager().removePerProjectInfo(
132 (JavaProject) element);
134 case IJavaElement.PACKAGE_FRAGMENT_ROOT :
135 this.projectsToUpdate.add(element.getJavaProject());
137 case IJavaElement.PACKAGE_FRAGMENT :
138 // get rid of package fragment cache
139 JavaProject project = (JavaProject) element.getJavaProject();
140 // project.resetCaches();
146 * Converts a <code>IResourceDelta</code> rooted in a <code>Workspace</code> into
147 * the corresponding set of <code>IJavaElementDelta</code>, rooted in the
148 * relevant <code>JavaModel</code>s.
150 public void processJavaDelta(IJavaElementDelta delta) {
152 // if (DeltaProcessor.VERBOSE){
153 // System.out.println("UPDATING Model with Delta: ["+Thread.currentThread()+":" + delta + "]:");//$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
157 this.traverseDelta(delta, null, null); // traverse delta
159 // update package fragment roots of projects that were affected
160 Iterator iterator = this.projectsToUpdate.iterator();
161 while (iterator.hasNext()) {
162 JavaProject project = (JavaProject) iterator.next();
163 project.updatePackageFragmentRoots();
166 this.projectsToUpdate = new HashSet();
171 * Removes the given element from its parents cache of children. If the
172 * element does not have a parent, or the parent is not currently open,
173 * this has no effect.
175 protected void removeFromParentInfo(Openable child) {
177 Openable parent = (Openable) child.getParent();
178 if (parent != null && parent.isOpen()) {
180 JavaElementInfo info = (JavaElementInfo)parent.getElementInfo();
181 info.removeChild(child);
182 } catch (JavaModelException e) {
183 // do nothing - we already checked if open
189 * Converts an <code>IResourceDelta</code> and its children into
190 * the corresponding <code>IJavaElementDelta</code>s.
191 * Return whether the delta corresponds to a resource on the classpath.
192 * If it is not a resource on the classpath, it will be added as a non-java
193 * resource by the sender of this method.
195 protected void traverseDelta(
196 IJavaElementDelta delta,
197 IPackageFragmentRoot root,
198 IJavaProject project) {
200 boolean processChildren = true;
202 Openable element = (Openable) delta.getElement();
203 switch (element.getElementType()) {
204 case IJavaElement.JAVA_PROJECT :
205 project = (IJavaProject) element;
207 case IJavaElement.PACKAGE_FRAGMENT_ROOT :
208 root = (IPackageFragmentRoot) element;
210 case IJavaElement.COMPILATION_UNIT :
211 // filter out working copies that are not primary (we don't want to add/remove them to/from the package fragment
212 CompilationUnit cu = (CompilationUnit)element;
213 if (cu.isWorkingCopy() && !cu.isPrimary()) {
216 case IJavaElement.CLASS_FILE :
217 processChildren = false;
221 switch (delta.getKind()) {
222 case IJavaElementDelta.ADDED :
223 elementAdded(element);
225 case IJavaElementDelta.REMOVED :
226 elementRemoved(element);
228 case IJavaElementDelta.CHANGED :
229 if ((delta.getFlags() & IJavaElementDelta.F_CONTENT) != 0){
230 elementChanged(element);
234 if (processChildren) {
235 IJavaElementDelta[] children = delta.getAffectedChildren();
236 for (int i = 0; i < children.length; i++) {
237 IJavaElementDelta childDelta = children[i];
238 this.traverseDelta(childDelta, root, project);