/*******************************************************************************
* Copyright (c) 2000, 2003 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
+ * All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
- *
+ *
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package net.sourceforge.phpdt.internal.core;
+import java.text.NumberFormat;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
import net.sourceforge.phpdt.core.BufferChangedEvent;
import net.sourceforge.phpdt.core.IBuffer;
import net.sourceforge.phpdt.core.IBufferChangedListener;
+import net.sourceforge.phpdt.core.IBufferFactory;
+import net.sourceforge.phpdt.core.ICodeAssist;
import net.sourceforge.phpdt.core.IJavaElement;
+import net.sourceforge.phpdt.core.IJavaModelStatusConstants;
import net.sourceforge.phpdt.core.IOpenable;
+import net.sourceforge.phpdt.core.IPackageFragmentRoot;
+import net.sourceforge.phpdt.core.IParent;
import net.sourceforge.phpdt.core.JavaModelException;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspace;
+import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IProgressMonitor;
/**
*/
public abstract class Openable extends JavaElement implements IOpenable, IBufferChangedListener {
-protected Openable(int type, IJavaElement parent, String name) {
- super(type, parent, name);
+protected Openable(JavaElement parent, String name) {
+ super(parent, name);
}
/**
* The buffer associated with this element has changed. Registers
*/
public void bufferChanged(BufferChangedEvent event) {
if (event.getBuffer().isClosed()) {
-// JavaModelManager.getJavaModelManager().getElementsOutOfSynchWithBuffers().remove(this);
-// getBufferManager().removeBuffer(event.getBuffer());
+ JavaModelManager.getJavaModelManager().getElementsOutOfSynchWithBuffers().remove(this);
+ getBufferManager().removeBuffer(event.getBuffer());
} else {
-// JavaModelManager.getJavaModelManager().getElementsOutOfSynchWithBuffers().put(this, this);
+ JavaModelManager.getJavaModelManager().getElementsOutOfSynchWithBuffers().put(this, this);
}
- }
+ }
+
+ /**
+ * Builds this element's structure and properties in the given
+ * info object, based on this element's current contents (reuse buffer
+ * contents if this element has an open buffer, or resource contents
+ * if this element does not have an open buffer). Children
+ * are placed in the given newElements table (note, this element
+ * has already been placed in the newElements table). Returns true
+ * if successful, or false if an error is encountered while determining
+ * the structure of this element.
+ */
+ protected abstract boolean buildStructure(OpenableElementInfo info, IProgressMonitor pm, Map newElements, IResource underlyingResource) throws JavaModelException;
+
///**
// * Updates the info objects for this element and all of its children by
// * removing the current infos, generating new infos, and then placing
//protected void buildStructure(OpenableElementInfo info, IProgressMonitor monitor) throws JavaModelException {
//
// if (monitor != null && monitor.isCanceled()) return;
-//
+//
// // remove existing (old) infos
// removeInfo();
// HashMap newElements = new HashMap(11);
// Object value = newElements.get(key);
// JavaModelManager.getJavaModelManager().putInfo(key, value);
// }
-//
+//
// // add the info for this at the end, to ensure that a getInfo cannot reply null in case the LRU cache needs
// // to be flushed. Might lead to performance issues.
// // see PR 1G2K5S7: ITPJCORE:ALL - NPE when accessing source for a binary type
-// JavaModelManager.getJavaModelManager().putInfo(this, info);
-//}
-///**
-// * Close the buffer associated with this element, if any.
-// */
-//protected void closeBuffer(OpenableElementInfo info) {
-// if (!hasBuffer()) return; // nothing to do
-// IBuffer buffer = null;
-// buffer = getBufferManager().getBuffer(this);
-// if (buffer != null) {
-// buffer.close();
-// buffer.removeBufferChangedListener(this);
-// }
-//}
-///**
-// * This element is being closed. Do any necessary cleanup.
-// */
-//protected void closing(Object info) throws JavaModelException {
-// OpenableElementInfo openableInfo = (OpenableElementInfo) info;
-// closeBuffer(openableInfo);
-// super.closing(info);
+// JavaModelManager.getJavaModelManager().putInfo(this, info);
//}
+/*
+ * Returns whether this element can be removed from the Java model cache to make space.
+ */
+public boolean canBeRemovedFromCache() {
+ try {
+ return !hasUnsavedChanges();
+ } catch (JavaModelException e) {
+ return false;
+ }
+}
+/*
+ * Returns whether the buffer of this element can be removed from the Java model cache to make space.
+ */
+public boolean canBufferBeRemovedFromCache(IBuffer buffer) {
+ return !buffer.hasUnsavedChanges();
+}
+/**
+ * Close the buffer associated with this element, if any.
+ */
+protected void closeBuffer() {
+ if (!hasBuffer()) return; // nothing to do
+ IBuffer buffer = getBufferManager().getBuffer(this);
+ if (buffer != null) {
+ buffer.close();
+ buffer.removeBufferChangedListener(this);
+ }
+}
+/**
+ * Close the buffer associated with this element, if any.
+ */
+protected void closeBuffer(OpenableElementInfo info) {
+ if (!hasBuffer()) return; // nothing to do
+ IBuffer buffer = null;
+ buffer = getBufferManager().getBuffer(this);
+ if (buffer != null) {
+ buffer.close();
+ buffer.removeBufferChangedListener(this);
+ }
+}
+/**
+ * This element is being closed. Do any necessary cleanup.
+ */
+protected void closing(Object info) {
+ closeBuffer();
+}
+
///**
// * @see ICodeAssist
// */
-//protected void codeComplete(org.eclipse.jdt.internal.compiler.env.ICompilationUnit cu, org.eclipse.jdt.internal.compiler.env.ICompilationUnit unitToSkip, int position, ICompletionRequestor requestor) throws JavaModelException {
+//protected void codeComplete(net.sourceforge.phpdt.internal.compiler.env.ICompilationUnit cu, net.sourceforge.phpdt.internal.compiler.env.ICompilationUnit unitToSkip, int position, ICompletionRequestor requestor) throws JavaModelException {
// if (requestor == null) {
-// throw new IllegalArgumentException(Util.bind("codeAssist.nullRequestor")); //$NON-NLS-1$
+// throw new IllegalArgumentException(ProjectPrefUtil.bind("codeAssist.nullRequestor")); //$NON-NLS-1$
// }
// IBuffer buffer = getBuffer();
// if (buffer == null) {
// engine.complete(cu, position, 0);
// environment.unitToSkip = null;
//}
-///**
-// * @see ICodeAssist
-// */
-//protected IJavaElement[] codeSelect(org.eclipse.jdt.internal.compiler.env.ICompilationUnit cu, int offset, int length) throws JavaModelException {
+/**
+ * @see ICodeAssist
+ */
+//protected IJavaElement[] codeSelect(net.sourceforge.phpdt.internal.compiler.env.ICompilationUnit cu, int offset, int length) throws JavaModelException {
// SelectionRequestor requestor= new SelectionRequestor(((JavaProject)getJavaProject()).getNameLookup(), this);
// this.codeSelect(cu, offset, length, requestor);
// return requestor.getElements();
//}
-///**
-// * @see ICodeAssist
-// */
-//protected void codeSelect(org.eclipse.jdt.internal.compiler.env.ICompilationUnit cu, int offset, int length, ISelectionRequestor requestor) throws JavaModelException {
+/**
+ * @see ICodeAssist
+ */
+//protected void codeSelect(net.sourceforge.phpdt.internal.compiler.env.ICompilationUnit cu, int offset, int length, ISelectionRequestor requestor) throws JavaModelException {
// IBuffer buffer = getBuffer();
// if (buffer == null) {
// return;
// // fix for 1FVGGKF
// JavaProject project = (JavaProject)getJavaProject();
// ISearchableNameEnvironment environment = project.getSearchableNameEnvironment();
-//
+//
// // fix for 1FVXGDK
// SelectionEngine engine = new SelectionEngine(environment, requestor, project.getOptions(true));
// engine.select(cu, offset, offset + length - 1);
//}
-///**
-// * Returns a new element info for this element.
-// */
-//protected OpenableElementInfo createElementInfo() {
-// return new OpenableElementInfo();
-//}
-//
+/*
+ * Returns a new element info for this element.
+ */
+protected Object createElementInfo() {
+ return new OpenableElementInfo();
+}
///**
// * Builds this element's structure and properties in the given
// * info object, based on this element's current contents (reuse buffer
// * the structure of this element.
// */
//protected abstract boolean generateInfos(OpenableElementInfo info, IProgressMonitor pm, Map newElements, IResource underlyingResource) throws JavaModelException;
+
+protected void generateInfos(Object info, HashMap newElements, IProgressMonitor monitor) throws JavaModelException {
+
+ if (JavaModelManager.VERBOSE){
+ System.out.println("OPENING Element ("+ Thread.currentThread()+"): " + this.toStringWithAncestors()); //$NON-NLS-1$//$NON-NLS-2$
+ }
+
+ // open the parent if necessary
+ openParent(info, newElements, monitor);
+ if (monitor != null && monitor.isCanceled()) return;
+
+ // puts the info before building the structure so that questions to the handle behave as if the element existed
+ // (case of compilation units becoming working copies)
+ newElements.put(this, info);
+
+ // build the structure of the openable (this will open the buffer if needed)
+ try {
+ OpenableElementInfo openableElementInfo = (OpenableElementInfo)info;
+ boolean isStructureKnown = buildStructure(openableElementInfo, monitor, newElements, getResource());
+ openableElementInfo.setIsStructureKnown(isStructureKnown);
+ } catch (JavaModelException e) {
+ newElements.remove(this);
+ throw e;
+ }
+
+ // remove out of sync buffer for this element
+ JavaModelManager.getJavaModelManager().getElementsOutOfSynchWithBuffers().remove(this);
+
+ if (JavaModelManager.VERBOSE) {
+ System.out.println("-> Package cache size = " + JavaModelManager.getJavaModelManager().cache.pkgSize()); //$NON-NLS-1$
+ System.out.println("-> Openable cache filling ratio = " + NumberFormat.getInstance().format(JavaModelManager.getJavaModelManager().cache.openableFillingRatio()) + "%"); //$NON-NLS-1$//$NON-NLS-2$
+ }
+}
/**
* Note: a buffer with no unsaved changes can be closed by the Java Model
* since it has a finite number of buffers allowed open at one time. If this
* is the first time a request is being made for the buffer, an attempt is
* made to create and fill this element's buffer. If the buffer has been
* closed since it was first opened, the buffer is re-created.
- *
+ *
* @see IOpenable
*/
public IBuffer getBuffer() throws JavaModelException {
return null;
}
}
-//
-///**
-// * Answers the buffer factory to use for creating new buffers
-// */
-//public IBufferFactory getBufferFactory(){
-// return getBufferManager().getDefaultBufferFactory();
-//}
-//
+
+/**
+ * Answers the buffer factory to use for creating new buffers
+ */
+public IBufferFactory getBufferFactory(){
+ return getBufferManager().getDefaultBufferFactory();
+}
+
/**
* Returns the buffer manager for this element.
*/
public IResource getCorrespondingResource() throws JavaModelException {
return getUnderlyingResource();
}
-///*
-// * @see IJavaElement
-// */
-//public IOpenable getOpenable() {
-// return this;
-//}
-//
-//
-//
+/*
+ * @see IJavaElement
+ */
+public IOpenable getOpenable() {
+ return this;
+}
+
+
+
/**
* @see IJavaElement
*/
public IResource getUnderlyingResource() throws JavaModelException {
- IResource parentResource = fParent.getUnderlyingResource();
+ IResource parentResource = parent.getUnderlyingResource();
if (parentResource == null) {
return null;
}
int type = parentResource.getType();
if (type == IResource.FOLDER || type == IResource.PROJECT) {
IContainer folder = (IContainer) parentResource;
- IResource resource = folder.findMember(fName);
+ IResource resource = folder.findMember(name);
if (resource == null) {
throw newNotPresentException();
} else {
}
}
-//public boolean exists() {
-//
-// IPackageFragmentRoot root = this.getPackageFragmentRoot();
-// if (root == null || root == this || !root.isArchive()) {
-// return parentExists() && resourceExists();
-// } else {
-// return super.exists();
-// }
-//}
+public boolean exists() {
+
+ IPackageFragmentRoot root = this.getPackageFragmentRoot();
+ if (root == null || root == this || !root.isArchive()) {
+ return parentExists() && resourceExists();
+ } else {
+ return super.exists();
+ }
+}
/**
* Returns true if this element may have an associated source buffer,
protected boolean hasBuffer() {
return false;
}
-///**
-// * @see IParent
-// */
-//public boolean hasChildren() throws JavaModelException {
-// return getChildren().length > 0;
-//}
-///**
-// * @see IOpenable
-// */
-//public boolean hasUnsavedChanges() throws JavaModelException{
-//
-// if (isReadOnly() || !isOpen()) {
-// return false;
-// }
-// IBuffer buf = this.getBuffer();
-// if (buf != null && buf.hasUnsavedChanges()) {
-// return true;
-// }
-// // for package fragments, package fragment roots, and projects must check open buffers
-// // to see if they have an child with unsaved changes
-// if (fLEType == PACKAGE_FRAGMENT ||
-// fLEType == PACKAGE_FRAGMENT_ROOT ||
-// fLEType == JAVA_PROJECT ||
-// fLEType == JAVA_MODEL) { // fix for 1FWNMHH
-// Enumeration openBuffers= getBufferManager().getOpenBuffers();
-// while (openBuffers.hasMoreElements()) {
-// IBuffer buffer= (IBuffer)openBuffers.nextElement();
-// if (buffer.hasUnsavedChanges()) {
-// IJavaElement owner= (IJavaElement)buffer.getOwner();
-// if (isAncestorOf(owner)) {
-// return true;
-// }
-// }
-// }
-// }
-//
-// return false;
-//}
+/**
+ * @see IParent
+ */
+public boolean hasChildren() throws JavaModelException {
+ return getChildren().length > 0;
+}
+/**
+ * @see IOpenable
+ */
+public boolean hasUnsavedChanges() throws JavaModelException{
+
+ if (isReadOnly() || !isOpen()) {
+ return false;
+ }
+ IBuffer buf = this.getBuffer();
+ if (buf != null && buf.hasUnsavedChanges()) {
+ return true;
+ }
+// for package fragments, package fragment roots, and projects must check open buffers
+ // to see if they have an child with unsaved changes
+ int elementType = getElementType();
+ if (elementType == PACKAGE_FRAGMENT ||
+ elementType == PACKAGE_FRAGMENT_ROOT ||
+ elementType == JAVA_PROJECT ||
+ elementType == JAVA_MODEL) { // fix for 1FWNMHH
+ Enumeration openBuffers= getBufferManager().getOpenBuffers();
+ while (openBuffers.hasMoreElements()) {
+ IBuffer buffer= (IBuffer)openBuffers.nextElement();
+ if (buffer.hasUnsavedChanges()) {
+ IJavaElement owner= (IJavaElement)buffer.getOwner();
+ if (isAncestorOf(owner)) {
+ return true;
+ }
+ }
+ }
+ }
+
+ return false;
+}
/**
* Subclasses must override as required.
*
return true;
}
/**
- *
+ *
* @see IOpenable
*/
public boolean isOpen() {
- // TODO isOpen - Openable needs JavaModelManager
-// synchronized(JavaModelManager.getJavaModelManager()){
-// return JavaModelManager.getJavaModelManager().getInfo(this) != null;
-// }
- return false;
+ synchronized(JavaModelManager.getJavaModelManager()){
+ return JavaModelManager.getJavaModelManager().getInfo(this) != null;
+ }
+}
+/**
+ * Returns true if this represents a source element.
+ * Openable source elements have an associated buffer created
+ * when they are opened.
+ */
+protected boolean isSourceElement() {
+ return false;
}
-///**
-// * Returns true if this represents a source element.
-// * Openable source elements have an associated buffer created
-// * when they are opened.
-// */
-//protected boolean isSourceElement() {
-// return false;
-//}
///**
// * @see IOpenable
// */
// buildStructure((OpenableElementInfo)getElementInfo(), pm);
// }
//}
-///**
-// * @see IOpenable
-// */
-//public void open(IProgressMonitor pm) throws JavaModelException {
-// if (!isOpen()) {
-// // TODO: need to synchronize (IOpenable.open(IProgressMonitor) is API
-// // TODO: could use getElementInfo instead
-// this.openWhenClosed(pm);
-// }
-//}
-//
+/**
+ * @see IOpenable
+ */
+public void makeConsistent(IProgressMonitor monitor) throws JavaModelException {
+ if (isConsistent()) return;
+
+ // create a new info and make it the current info
+ // (this will remove the info and its children just before storing the new infos)
+ JavaModelManager manager = JavaModelManager.getJavaModelManager();
+ boolean hadTemporaryCache = manager.hasTemporaryCache();
+ try {
+ HashMap newElements = manager.getTemporaryCache();
+ openWhenClosed(newElements, monitor);
+ if (newElements.get(this) == null) {
+ // close any buffer that was opened for the new elements
+ Iterator iterator = newElements.keySet().iterator();
+ while (iterator.hasNext()) {
+ IJavaElement element = (IJavaElement)iterator.next();
+ if (element instanceof Openable) {
+ ((Openable)element).closeBuffer();
+ }
+ }
+ throw newNotPresentException();
+ }
+ if (!hadTemporaryCache) {
+ manager.putInfos(this, newElements);
+ }
+ } finally {
+ if (!hadTemporaryCache) {
+ manager.resetTemporaryCache();
+ }
+ }
+}
+
+/**
+ * @see IOpenable
+ */
+public void open(IProgressMonitor pm) throws JavaModelException {
+ getElementInfo(pm);
+}
/**
* Opens a buffer on the contents of this element, and returns
* the buffer, or returns <code>null</code> if opening fails.
protected IBuffer openBuffer(IProgressMonitor pm) throws JavaModelException {
return null;
}
-//
-///**
-// * Open the parent element if necessary
-// *
-// */
-//protected void openParent(IProgressMonitor pm) throws JavaModelException {
-//
-// Openable openableParent = (Openable)getOpenableParent();
-// if (openableParent != null) {
-// if (!openableParent.isOpen()){
-// openableParent.openWhenClosed(pm);
-// }
-// }
-//}
-//
+
+/**
+ * Open the parent element if necessary.
+ */
+protected void openParent(Object childInfo, HashMap newElements, IProgressMonitor pm) throws JavaModelException {
+
+ Openable openableParent = (Openable)getOpenableParent();
+ if (openableParent != null && !openableParent.isOpen()){
+ openableParent.generateInfos(openableParent.createElementInfo(), newElements, pm);
+ }
+}
+
///**
// * Open an <code>Openable</code> that is known to be closed (no check for <code>isOpen()</code>).
// */
//protected void openWhenClosed(IProgressMonitor pm) throws JavaModelException {
// try {
-//
+//
// if (JavaModelManager.VERBOSE){
// System.out.println("OPENING Element ("+ Thread.currentThread()+"): " + this.toStringWithAncestors()); //$NON-NLS-1$//$NON-NLS-2$
// }
-//
+//
// // 1) Parent must be open - open the parent if necessary
// openParent(pm);
//
// OpenableElementInfo info = createElementInfo();
// if (isSourceElement()) {
// this.openBuffer(pm);
-// }
+// }
//
// // 3) build the structure of the openable
// buildStructure(info, pm);
//
// // 4) anything special
// opening(info);
-//
-// if (JavaModelManager.VERBOSE) {
-// System.out.println("-> Package cache size = " + JavaModelManager.getJavaModelManager().cache.pkgSize()); //$NON-NLS-1$
-// System.out.println("-> Openable cache filling ratio = " + JavaModelManager.getJavaModelManager().cache.openableFillingRatio() + "%"); //$NON-NLS-1$//$NON-NLS-2$
-// }
+//
+//// if (JavaModelManager.VERBOSE) {
+//// System.out.println("-> Package cache size = " + JavaModelManager.getJavaModelManager().cache.pkgSize()); //$NON-NLS-1$
+//// System.out.println("-> Openable cache filling ratio = " + JavaModelManager.getJavaModelManager().cache.openableFillingRatio() + "%"); //$NON-NLS-1$//$NON-NLS-2$
+//// }
//
// // if any problems occuring openning the element, ensure that it's info
// // does not remain in the cache (some elements, pre-cache their info
// throw e;
// }
//}
-//
-///**
-// * Answers true if the parent exists (null parent is answering true)
-// *
-// */
-//protected boolean parentExists(){
-//
-// IJavaElement parent = this.getParent();
-// if (parent == null) return true;
-// return parent.exists();
-//}
-//
-///**
-// * Returns whether the corresponding resource or associated file exists
-// */
-//protected boolean resourceExists() {
-// IWorkspace workspace = ResourcesPlugin.getWorkspace();
-// if (workspace == null) return false; // workaround for http://bugs.eclipse.org/bugs/show_bug.cgi?id=34069
-// return
-// JavaModel.getTarget(
-// workspace.getRoot(),
-// this.getPath().makeRelative(), // ensure path is relative (see http://dev.eclipse.org/bugs/show_bug.cgi?id=22517)
-// true) != null;
-//}
-//
-///**
-// * @see IOpenable
-// */
-//public void save(IProgressMonitor pm, boolean force) throws JavaModelException {
-// if (isReadOnly() || this.getResource().isReadOnly()) {
-// throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.READ_ONLY, this));
-// }
-// IBuffer buf = getBuffer();
-// if (buf != null) { // some Openables (like a JavaProject) don't have a buffer
-// buf.save(pm, force);
-// this.makeConsistent(pm); // update the element info of this element
-// }
-//}
-//
+
+/**
+ * Answers true if the parent exists (null parent is answering true)
+ *
+ */
+protected boolean parentExists(){
+
+ IJavaElement parent = this.getParent();
+ if (parent == null) return true;
+ return parent.exists();
+}
+
+/**
+ * Returns whether the corresponding resource or associated file exists
+ */
+protected boolean resourceExists() {
+ IWorkspace workspace = ResourcesPlugin.getWorkspace();
+ if (workspace == null) return false; // workaround for http://bugs.eclipse.org/bugs/show_bug.cgi?id=34069
+ return
+ JavaModel.getTarget(
+ workspace.getRoot(),
+ this.getPath().makeRelative(), // ensure path is relative (see http://dev.eclipse.org/bugs/show_bug.cgi?id=22517)
+ true) != null;
+}
+
+/**
+ * @see IOpenable
+ */
+public void save(IProgressMonitor pm, boolean force) throws JavaModelException {
+ if (isReadOnly() || this.getResource().getResourceAttributes().isReadOnly()) {
+ throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.READ_ONLY, this));
+ }
+ IBuffer buf = getBuffer();
+ if (buf != null) { // some Openables (like a JavaProject) don't have a buffer
+ buf.save(pm, force);
+ this.makeConsistent(pm); // update the element info of this element
+ }
+}
+
/**
* Find enclosing package fragment root if any
*/
// * @see ICodeAssist
// * @deprecated - use codeComplete(ICompilationUnit, ICompilationUnit, int, ICompletionRequestor) instead
// */
-//protected void codeComplete(org.eclipse.jdt.internal.compiler.env.ICompilationUnit cu, org.eclipse.jdt.internal.compiler.env.ICompilationUnit unitToSkip, int position, final ICodeCompletionRequestor requestor) throws JavaModelException {
+//protected void codeComplete(net.sourceforge.phpdt.internal.compiler.env.ICompilationUnit cu, net.sourceforge.phpdt.internal.compiler.env.ICompilationUnit unitToSkip, int position, final ICodeCompletionRequestor requestor) throws JavaModelException {
//
// if (requestor == null){
// codeComplete(cu, unitToSkip, position, (ICompletionRequestor)null);