KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > core > Openable


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.jdt.internal.core;
12
13 import java.util.Enumeration JavaDoc;
14 import java.util.HashMap JavaDoc;
15 import java.util.Map JavaDoc;
16
17 import org.eclipse.core.resources.*;
18 import org.eclipse.core.runtime.IProgressMonitor;
19 import org.eclipse.core.runtime.OperationCanceledException;
20 import org.eclipse.core.runtime.PerformanceStats;
21 import org.eclipse.jdt.core.*;
22 import org.eclipse.jdt.internal.codeassist.CompletionEngine;
23 import org.eclipse.jdt.internal.codeassist.SelectionEngine;
24 import org.eclipse.jdt.internal.core.util.Util;
25
26
27 /**
28  * Abstract class for implementations of java elements which are IOpenable.
29  *
30  * @see IJavaElement
31  * @see IOpenable
32  */

33 public abstract class Openable extends JavaElement implements IOpenable, IBufferChangedListener {
34
35 protected Openable(JavaElement parent) {
36     super(parent);
37 }
38 /**
39  * The buffer associated with this element has changed. Registers
40  * this element as being out of synch with its buffer's contents.
41  * If the buffer has been closed, this element is set as NOT out of
42  * synch with the contents.
43  *
44  * @see IBufferChangedListener
45  */

46 public void bufferChanged(BufferChangedEvent event) {
47     if (event.getBuffer().isClosed()) {
48         JavaModelManager.getJavaModelManager().getElementsOutOfSynchWithBuffers().remove(this);
49         getBufferManager().removeBuffer(event.getBuffer());
50     } else {
51         JavaModelManager.getJavaModelManager().getElementsOutOfSynchWithBuffers().add(this);
52     }
53 }
54 /**
55  * Builds this element's structure and properties in the given
56  * info object, based on this element's current contents (reuse buffer
57  * contents if this element has an open buffer, or resource contents
58  * if this element does not have an open buffer). Children
59  * are placed in the given newElements table (note, this element
60  * has already been placed in the newElements table). Returns true
61  * if successful, or false if an error is encountered while determining
62  * the structure of this element.
63  */

64 protected abstract boolean buildStructure(OpenableElementInfo info, IProgressMonitor pm, Map JavaDoc newElements, IResource underlyingResource) throws JavaModelException;
65 /*
66  * Returns whether this element can be removed from the Java model cache to make space.
67  */

68 public boolean canBeRemovedFromCache() {
69     try {
70         return !hasUnsavedChanges();
71     } catch (JavaModelException e) {
72         return false;
73     }
74 }
75 /*
76  * Returns whether the buffer of this element can be removed from the Java model cache to make space.
77  */

78 public boolean canBufferBeRemovedFromCache(IBuffer buffer) {
79     return !buffer.hasUnsavedChanges();
80 }
81 /**
82  * Close the buffer associated with this element, if any.
83  */

84 protected void closeBuffer() {
85     if (!hasBuffer()) return; // nothing to do
86
IBuffer buffer = getBufferManager().getBuffer(this);
87     if (buffer != null) {
88         buffer.close();
89         buffer.removeBufferChangedListener(this);
90     }
91 }
92 /**
93  * This element is being closed. Do any necessary cleanup.
94  */

95 protected void closing(Object JavaDoc info) {
96     closeBuffer();
97 }
98 protected void codeComplete(org.eclipse.jdt.internal.compiler.env.ICompilationUnit cu, org.eclipse.jdt.internal.compiler.env.ICompilationUnit unitToSkip, int position, CompletionRequestor requestor, WorkingCopyOwner owner) throws JavaModelException {
99     if (requestor == null) {
100         throw new IllegalArgumentException JavaDoc("Completion requestor cannot be null"); //$NON-NLS-1$
101
}
102     PerformanceStats performanceStats = CompletionEngine.PERF
103         ? PerformanceStats.getStats(JavaModelManager.COMPLETION_PERF, this)
104         : null;
105     if(performanceStats != null) {
106         performanceStats.startRun(new String JavaDoc(cu.getFileName()) + " at " + position); //$NON-NLS-1$
107
}
108     IBuffer buffer = getBuffer();
109     if (buffer == null) {
110         return;
111     }
112     if (position < -1 || position > buffer.getLength()) {
113         throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.INDEX_OUT_OF_BOUNDS));
114     }
115     JavaProject project = (JavaProject) getJavaProject();
116     SearchableEnvironment environment = project.newSearchableNameEnvironment(owner);
117
118     // set unit to skip
119
environment.unitToSkip = unitToSkip;
120
121     // code complete
122
CompletionEngine engine = new CompletionEngine(environment, requestor, project.getOptions(true), project);
123     engine.complete(cu, position, 0);
124     if(performanceStats != null) {
125         performanceStats.endRun();
126     }
127     if (NameLookup.VERBOSE) {
128         System.out.println(Thread.currentThread() + " TIME SPENT in NameLoopkup#seekTypesInSourcePackage: " + environment.nameLookup.timeSpentInSeekTypesInSourcePackage + "ms"); //$NON-NLS-1$ //$NON-NLS-2$
129
System.out.println(Thread.currentThread() + " TIME SPENT in NameLoopkup#seekTypesInBinaryPackage: " + environment.nameLookup.timeSpentInSeekTypesInBinaryPackage + "ms"); //$NON-NLS-1$ //$NON-NLS-2$
130
}
131 }
132 protected IJavaElement[] codeSelect(org.eclipse.jdt.internal.compiler.env.ICompilationUnit cu, int offset, int length, WorkingCopyOwner owner) throws JavaModelException {
133     PerformanceStats performanceStats = SelectionEngine.PERF
134         ? PerformanceStats.getStats(JavaModelManager.SELECTION_PERF, this)
135         : null;
136     if(performanceStats != null) {
137         performanceStats.startRun(new String JavaDoc(cu.getFileName()) + " at [" + offset + "," + length + "]"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
138
}
139     
140     JavaProject project = (JavaProject)getJavaProject();
141     SearchableEnvironment environment = project.newSearchableNameEnvironment(owner);
142     
143     SelectionRequestor requestor= new SelectionRequestor(environment.nameLookup, this);
144     IBuffer buffer = getBuffer();
145     if (buffer == null) {
146         return requestor.getElements();
147     }
148     int end= buffer.getLength();
149     if (offset < 0 || length < 0 || offset + length > end ) {
150         throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.INDEX_OUT_OF_BOUNDS));
151     }
152
153     // fix for 1FVXGDK
154
SelectionEngine engine = new SelectionEngine(environment, requestor, project.getOptions(true));
155     engine.select(cu, offset, offset + length - 1);
156     
157     if(performanceStats != null) {
158         performanceStats.endRun();
159     }
160     if (NameLookup.VERBOSE) {
161         System.out.println(Thread.currentThread() + " TIME SPENT in NameLoopkup#seekTypesInSourcePackage: " + environment.nameLookup.timeSpentInSeekTypesInSourcePackage + "ms"); //$NON-NLS-1$ //$NON-NLS-2$
162
System.out.println(Thread.currentThread() + " TIME SPENT in NameLoopkup#seekTypesInBinaryPackage: " + environment.nameLookup.timeSpentInSeekTypesInBinaryPackage + "ms"); //$NON-NLS-1$ //$NON-NLS-2$
163
}
164     return requestor.getElements();
165 }
166 /*
167  * Returns a new element info for this element.
168  */

169 protected Object JavaDoc createElementInfo() {
170     return new OpenableElementInfo();
171 }
172 /**
173  * @see IJavaElement
174  */

175 public boolean exists() {
176     JavaModelManager manager = JavaModelManager.getJavaModelManager();
177     if (manager.getInfo(this) != null) return true;
178     if (!parentExists()) return false;
179     PackageFragmentRoot root = getPackageFragmentRoot();
180     if (root != null
181             && (root == this || !root.isArchive())) {
182         return resourceExists();
183     }
184     return super.exists();
185 }
186 public String JavaDoc findRecommendedLineSeparator() throws JavaModelException {
187     IBuffer buffer = getBuffer();
188     String JavaDoc source = buffer == null ? null : buffer.getContents();
189     return Util.getLineSeparator(source, getJavaProject());
190 }
191 protected void generateInfos(Object JavaDoc info, HashMap JavaDoc newElements, IProgressMonitor monitor) throws JavaModelException {
192
193     if (JavaModelCache.VERBOSE){
194         String JavaDoc element;
195         switch (getElementType()) {
196             case JAVA_PROJECT:
197                 element = "project"; //$NON-NLS-1$
198
break;
199             case PACKAGE_FRAGMENT_ROOT:
200                 element = "root"; //$NON-NLS-1$
201
break;
202             case PACKAGE_FRAGMENT:
203                 element = "package"; //$NON-NLS-1$
204
break;
205             case CLASS_FILE:
206                 element = "class file"; //$NON-NLS-1$
207
break;
208             case COMPILATION_UNIT:
209                 element = "compilation unit"; //$NON-NLS-1$
210
break;
211             default:
212                 element = "element"; //$NON-NLS-1$
213
}
214         System.out.println(Thread.currentThread() +" OPENING " + element + " " + this.toStringWithAncestors()); //$NON-NLS-1$//$NON-NLS-2$
215
}
216     
217     // open the parent if necessary
218
openParent(info, newElements, monitor);
219     if (monitor != null && monitor.isCanceled())
220         throw new OperationCanceledException();
221
222      // puts the info before building the structure so that questions to the handle behave as if the element existed
223
// (case of compilation units becoming working copies)
224
newElements.put(this, info);
225
226     // build the structure of the openable (this will open the buffer if needed)
227
try {
228         OpenableElementInfo openableElementInfo = (OpenableElementInfo)info;
229         boolean isStructureKnown = buildStructure(openableElementInfo, monitor, newElements, getResource());
230         openableElementInfo.setIsStructureKnown(isStructureKnown);
231     } catch (JavaModelException e) {
232         newElements.remove(this);
233         throw e;
234     }
235     
236     // remove out of sync buffer for this element
237
JavaModelManager.getJavaModelManager().getElementsOutOfSynchWithBuffers().remove(this);
238
239     if (JavaModelCache.VERBOSE) {
240         System.out.println(JavaModelManager.getJavaModelManager().cacheToString("-> ")); //$NON-NLS-1$
241
}
242 }
243 /**
244  * Note: a buffer with no unsaved changes can be closed by the Java Model
245  * since it has a finite number of buffers allowed open at one time. If this
246  * is the first time a request is being made for the buffer, an attempt is
247  * made to create and fill this element's buffer. If the buffer has been
248  * closed since it was first opened, the buffer is re-created.
249  *
250  * @see IOpenable
251  */

252 public IBuffer getBuffer() throws JavaModelException {
253     if (hasBuffer()) {
254         // ensure element is open
255
Object JavaDoc info = getElementInfo();
256         IBuffer buffer = getBufferManager().getBuffer(this);
257         if (buffer == null) {
258             // try to (re)open a buffer
259
buffer = openBuffer(null, info);
260         }
261         if (buffer instanceof NullBuffer) {
262             return null;
263         }
264         return buffer;
265     } else {
266         return null;
267     }
268 }
269 /**
270  * Answers the buffer factory to use for creating new buffers
271  * @deprecated
272  */

273 public IBufferFactory getBufferFactory(){
274     return getBufferManager().getDefaultBufferFactory();
275 }
276
277 /**
278  * Returns the buffer manager for this element.
279  */

280 protected BufferManager getBufferManager() {
281     return BufferManager.getDefaultBufferManager();
282 }
283 /**
284  * Return my underlying resource. Elements that may not have a
285  * corresponding resource must override this method.
286  *
287  * @see IJavaElement
288  */

289 public IResource getCorrespondingResource() throws JavaModelException {
290     return getUnderlyingResource();
291 }
292 /*
293  * @see IJavaElement
294  */

295 public IOpenable getOpenable() {
296     return this;
297 }
298
299
300
301 /**
302  * @see IJavaElement
303  */

304 public IResource getUnderlyingResource() throws JavaModelException {
305     IResource parentResource = this.parent.getUnderlyingResource();
306     if (parentResource == null) {
307         return null;
308     }
309     int type = parentResource.getType();
310     if (type == IResource.FOLDER || type == IResource.PROJECT) {
311         IContainer folder = (IContainer) parentResource;
312         IResource resource = folder.findMember(getElementName());
313         if (resource == null) {
314             throw newNotPresentException();
315         } else {
316             return resource;
317         }
318     } else {
319         return parentResource;
320     }
321 }
322
323 /**
324  * Returns true if this element may have an associated source buffer,
325  * otherwise false. Subclasses must override as required.
326  */

327 protected boolean hasBuffer() {
328     return false;
329 }
330 /**
331  * @see IOpenable
332  */

333 public boolean hasUnsavedChanges() throws JavaModelException{
334     
335     if (isReadOnly() || !isOpen()) {
336         return false;
337     }
338     IBuffer buf = this.getBuffer();
339     if (buf != null && buf.hasUnsavedChanges()) {
340         return true;
341     }
342     // for package fragments, package fragment roots, and projects must check open buffers
343
// to see if they have an child with unsaved changes
344
int elementType = getElementType();
345     if (elementType == PACKAGE_FRAGMENT ||
346         elementType == PACKAGE_FRAGMENT_ROOT ||
347         elementType == JAVA_PROJECT ||
348         elementType == JAVA_MODEL) { // fix for 1FWNMHH
349
Enumeration JavaDoc openBuffers= getBufferManager().getOpenBuffers();
350         while (openBuffers.hasMoreElements()) {
351             IBuffer buffer= (IBuffer)openBuffers.nextElement();
352             if (buffer.hasUnsavedChanges()) {
353                 IJavaElement owner= (IJavaElement)buffer.getOwner();
354                 if (isAncestorOf(owner)) {
355                     return true;
356                 }
357             }
358         }
359     }
360     
361     return false;
362 }
363 /**
364  * Subclasses must override as required.
365  *
366  * @see IOpenable
367  */

368 public boolean isConsistent() {
369     return true;
370 }
371 /**
372  *
373  * @see IOpenable
374  */

375 public boolean isOpen() {
376     return JavaModelManager.getJavaModelManager().getInfo(this) != null;
377 }
378 /**
379  * Returns true if this represents a source element.
380  * Openable source elements have an associated buffer created
381  * when they are opened.
382  */

383 protected boolean isSourceElement() {
384     return false;
385 }
386 /**
387  * @see IJavaElement
388  */

389 public boolean isStructureKnown() throws JavaModelException {
390     return ((OpenableElementInfo)getElementInfo()).isStructureKnown();
391 }
392 /**
393  * @see IOpenable
394  */

395 public void makeConsistent(IProgressMonitor monitor) throws JavaModelException {
396     // only compilation units can be inconsistent
397
// other openables cannot be inconsistent so default is to do nothing
398
}
399 /**
400  * @see IOpenable
401  */

402 public void open(IProgressMonitor pm) throws JavaModelException {
403     getElementInfo(pm);
404 }
405
406 /**
407  * Opens a buffer on the contents of this element, and returns
408  * the buffer, or returns <code>null</code> if opening fails.
409  * By default, do nothing - subclasses that have buffers
410  * must override as required.
411  */

412 protected IBuffer openBuffer(IProgressMonitor pm, Object JavaDoc info) throws JavaModelException {
413     return null;
414 }
415
416 /**
417  * Open the parent element if necessary.
418  */

419 protected void openParent(Object JavaDoc childInfo, HashMap JavaDoc newElements, IProgressMonitor pm) throws JavaModelException {
420
421     Openable openableParent = (Openable)getOpenableParent();
422     if (openableParent != null && !openableParent.isOpen()){
423         openableParent.generateInfos(openableParent.createElementInfo(), newElements, pm);
424     }
425 }
426
427 /**
428  * Answers true if the parent exists (null parent is answering true)
429  *
430  */

431 protected boolean parentExists(){
432     
433     IJavaElement parentElement = getParent();
434     if (parentElement == null) return true;
435     return parentElement.exists();
436 }
437
438 /**
439  * Returns whether the corresponding resource or associated file exists
440  */

441 protected boolean resourceExists() {
442     IWorkspace workspace = ResourcesPlugin.getWorkspace();
443     if (workspace == null) return false; // workaround for http://bugs.eclipse.org/bugs/show_bug.cgi?id=34069
444
return
445         JavaModel.getTarget(
446             workspace.getRoot(),
447             this.getPath().makeRelative(), // ensure path is relative (see http://dev.eclipse.org/bugs/show_bug.cgi?id=22517)
448
true) != null;
449 }
450
451 /**
452  * @see IOpenable
453  */

454 public void save(IProgressMonitor pm, boolean force) throws JavaModelException {
455     if (isReadOnly()) {
456         throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.READ_ONLY, this));
457     }
458     IBuffer buf = getBuffer();
459     if (buf != null) { // some Openables (like a JavaProject) don't have a buffer
460
buf.save(pm, force);
461         this.makeConsistent(pm); // update the element info of this element
462
}
463 }
464
465 /**
466  * Find enclosing package fragment root if any
467  */

468 public PackageFragmentRoot getPackageFragmentRoot() {
469     return (PackageFragmentRoot) getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT);
470 }
471
472 }
473
Popular Tags