Changes:
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / core / Openable.java
1 /*******************************************************************************
2  * Copyright (c) 2000, 2003 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
7  * 
8  * Contributors:
9  *     IBM Corporation - initial API and implementation
10  *******************************************************************************/
11 package net.sourceforge.phpdt.internal.core;
12
13 import net.sourceforge.phpdt.core.BufferChangedEvent;
14 import net.sourceforge.phpdt.core.IBuffer;
15 import net.sourceforge.phpdt.core.IBufferChangedListener;
16 import net.sourceforge.phpdt.core.IJavaElement;
17 import net.sourceforge.phpdt.core.IOpenable;
18 import net.sourceforge.phpdt.core.JavaModelException;
19
20 import org.eclipse.core.resources.IContainer;
21 import org.eclipse.core.resources.IResource;
22 import org.eclipse.core.runtime.IProgressMonitor;
23
24 /**
25  * Abstract class for implementations of java elements which are IOpenable.
26  *
27  * @see IJavaElement
28  * @see IOpenable
29  */
30 public abstract class Openable extends JavaElement implements IOpenable, IBufferChangedListener {
31
32 protected Openable(int type, IJavaElement parent, String name) {
33         super(type, parent, name);
34 }
35         /**
36          * The buffer associated with this element has changed. Registers
37          * this element as being out of synch with its buffer's contents.
38          * If the buffer has been closed, this element is set as NOT out of
39          * synch with the contents.
40          *
41          * @see IBufferChangedListener
42          */
43         public void bufferChanged(BufferChangedEvent event) {
44                 if (event.getBuffer().isClosed()) {
45 //                      JavaModelManager.getJavaModelManager().getElementsOutOfSynchWithBuffers().remove(this);
46 //                      getBufferManager().removeBuffer(event.getBuffer());
47                 } else {
48 //                      JavaModelManager.getJavaModelManager().getElementsOutOfSynchWithBuffers().put(this, this);
49                 }
50         }       
51 ///**
52 // * Updates the info objects for this element and all of its children by
53 // * removing the current infos, generating new infos, and then placing
54 // * the new infos into the Java Model cache tables.
55 // */
56 //protected void buildStructure(OpenableElementInfo info, IProgressMonitor monitor) throws JavaModelException {
57 //
58 //      if (monitor != null && monitor.isCanceled()) return;
59 //      
60 //      // remove existing (old) infos
61 //      removeInfo();
62 //      HashMap newElements = new HashMap(11);
63 //      info.setIsStructureKnown(generateInfos(info, monitor, newElements, getResource()));
64 //      JavaModelManager.getJavaModelManager().getElementsOutOfSynchWithBuffers().remove(this);
65 //      for (Iterator iter = newElements.keySet().iterator(); iter.hasNext();) {
66 //              IJavaElement key = (IJavaElement) iter.next();
67 //              Object value = newElements.get(key);
68 //              JavaModelManager.getJavaModelManager().putInfo(key, value);
69 //      }
70 //              
71 //      // add the info for this at the end, to ensure that a getInfo cannot reply null in case the LRU cache needs
72 //      // to be flushed. Might lead to performance issues.
73 //      // see PR 1G2K5S7: ITPJCORE:ALL - NPE when accessing source for a binary type
74 //      JavaModelManager.getJavaModelManager().putInfo(this, info);     
75 //}
76 ///**
77 // * Close the buffer associated with this element, if any.
78 // */
79 //protected void closeBuffer(OpenableElementInfo info) {
80 //      if (!hasBuffer()) return; // nothing to do
81 //      IBuffer buffer = null;
82 //      buffer = getBufferManager().getBuffer(this);
83 //      if (buffer != null) {
84 //              buffer.close();
85 //              buffer.removeBufferChangedListener(this);
86 //      }
87 //}
88 ///**
89 // * This element is being closed.  Do any necessary cleanup.
90 // */
91 //protected void closing(Object info) throws JavaModelException {
92 //      OpenableElementInfo openableInfo = (OpenableElementInfo) info;
93 //      closeBuffer(openableInfo);
94 //      super.closing(info);
95 //}
96 ///**
97 // * @see ICodeAssist
98 // */
99 //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 {
100 //      if (requestor == null) {
101 //              throw new IllegalArgumentException(Util.bind("codeAssist.nullRequestor")); //$NON-NLS-1$
102 //      }
103 //      IBuffer buffer = getBuffer();
104 //      if (buffer == null) {
105 //              return;
106 //      }
107 //      if (position < -1 || position > buffer.getLength()) {
108 //              throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.INDEX_OUT_OF_BOUNDS));
109 //      }
110 //      JavaProject project = (JavaProject) getJavaProject();
111 //      SearchableEnvironment environment = (SearchableEnvironment) project.getSearchableNameEnvironment();
112 //      NameLookup nameLookup = project.getNameLookup();
113 //      environment.unitToSkip = unitToSkip;
114 //
115 //      CompletionEngine engine = new CompletionEngine(environment, new CompletionRequestorWrapper(requestor,nameLookup), project.getOptions(true), project);
116 //      engine.complete(cu, position, 0);
117 //      environment.unitToSkip = null;
118 //}
119 ///**
120 // * @see ICodeAssist
121 // */
122 //protected IJavaElement[] codeSelect(org.eclipse.jdt.internal.compiler.env.ICompilationUnit cu, int offset, int length) throws JavaModelException {
123 //      SelectionRequestor requestor= new SelectionRequestor(((JavaProject)getJavaProject()).getNameLookup(), this);
124 //      this.codeSelect(cu, offset, length, requestor);
125 //      return requestor.getElements();
126 //}
127 ///**
128 // * @see ICodeAssist
129 // */
130 //protected void codeSelect(org.eclipse.jdt.internal.compiler.env.ICompilationUnit cu, int offset, int length, ISelectionRequestor requestor) throws JavaModelException {
131 //      IBuffer buffer = getBuffer();
132 //      if (buffer == null) {
133 //              return;
134 //      }
135 //      int end= buffer.getLength();
136 //      if (offset < 0 || length < 0 || offset + length > end ) {
137 //              throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.INDEX_OUT_OF_BOUNDS));
138 //      }
139 //
140 //      // fix for 1FVGGKF
141 //      JavaProject project = (JavaProject)getJavaProject();
142 //      ISearchableNameEnvironment environment = project.getSearchableNameEnvironment();
143 //      
144 //      // fix for 1FVXGDK
145 //      SelectionEngine engine = new SelectionEngine(environment, requestor, project.getOptions(true));
146 //      engine.select(cu, offset, offset + length - 1);
147 //}
148 ///**
149 // * Returns a new element info for this element.
150 // */
151 //protected OpenableElementInfo createElementInfo() {
152 //      return new OpenableElementInfo();
153 //}
154 //
155 ///**
156 // * Builds this element's structure and properties in the given
157 // * info object, based on this element's current contents (reuse buffer
158 // * contents if this element has an open buffer, or resource contents
159 // * if this element does not have an open buffer). Children
160 // * are placed in the given newElements table (note, this element
161 // * has already been placed in the newElements table). Returns true
162 // * if successful, or false if an error is encountered while determining
163 // * the structure of this element.
164 // */
165 //protected abstract boolean generateInfos(OpenableElementInfo info, IProgressMonitor pm, Map newElements, IResource underlyingResource) throws JavaModelException;
166 /**
167  * Note: a buffer with no unsaved changes can be closed by the Java Model
168  * since it has a finite number of buffers allowed open at one time. If this
169  * is the first time a request is being made for the buffer, an attempt is
170  * made to create and fill this element's buffer. If the buffer has been
171  * closed since it was first opened, the buffer is re-created.
172  * 
173  * @see IOpenable
174  */
175 public IBuffer getBuffer() throws JavaModelException {
176         if (hasBuffer()) {
177                 // ensure element is open
178                 if (!isOpen()) {
179                         getElementInfo();
180                 }
181                 IBuffer buffer = getBufferManager().getBuffer(this);
182                 if (buffer == null) {
183                         // try to (re)open a buffer
184                         buffer = openBuffer(null);
185                 }
186                 return buffer;
187         } else {
188                 return null;
189         }
190 }
191 //
192 ///**
193 // * Answers the buffer factory to use for creating new buffers
194 // */
195 //public IBufferFactory getBufferFactory(){
196 //      return getBufferManager().getDefaultBufferFactory();
197 //}
198 //
199 /**
200  * Returns the buffer manager for this element.
201  */
202 protected BufferManager getBufferManager() {
203         return BufferManager.getDefaultBufferManager();
204 }
205 /**
206  * Return my underlying resource. Elements that may not have a
207  * corresponding resource must override this method.
208  *
209  * @see IJavaElement
210  */
211 public IResource getCorrespondingResource() throws JavaModelException {
212         return getUnderlyingResource();
213 }
214 ///*
215 // * @see IJavaElement
216 // */
217 //public IOpenable getOpenable() {
218 //      return this;    
219 //}
220 //
221 //
222 //
223 /**
224  * @see IJavaElement
225  */
226 public IResource getUnderlyingResource() throws JavaModelException {
227         IResource parentResource = fParent.getUnderlyingResource();
228         if (parentResource == null) {
229                 return null;
230         }
231         int type = parentResource.getType();
232         if (type == IResource.FOLDER || type == IResource.PROJECT) {
233                 IContainer folder = (IContainer) parentResource;
234                 IResource resource = folder.findMember(fName);
235                 if (resource == null) {
236                         throw newNotPresentException();
237                 } else {
238                         return resource;
239                 }
240         } else {
241                 return parentResource;
242         }
243 }
244
245 //public boolean exists() {
246 //      
247 //      IPackageFragmentRoot root = this.getPackageFragmentRoot();
248 //      if (root == null || root == this || !root.isArchive()) {
249 //              return parentExists() && resourceExists();
250 //      } else {
251 //              return super.exists();
252 //      }
253 //}     
254
255 /**
256  * Returns true if this element may have an associated source buffer,
257  * otherwise false. Subclasses must override as required.
258  */
259 protected boolean hasBuffer() {
260         return false;
261 }
262 ///**
263 // * @see IParent 
264 // */
265 //public boolean hasChildren() throws JavaModelException {
266 //      return getChildren().length > 0;
267 //}
268 ///**
269 // * @see IOpenable
270 // */
271 //public boolean hasUnsavedChanges() throws JavaModelException{
272 //      
273 //      if (isReadOnly() || !isOpen()) {
274 //              return false;
275 //      }
276 //      IBuffer buf = this.getBuffer();
277 //      if (buf != null && buf.hasUnsavedChanges()) {
278 //              return true;
279 //      }
280 //      // for package fragments, package fragment roots, and projects must check open buffers
281 //      // to see if they have an child with unsaved changes
282 //      if (fLEType == PACKAGE_FRAGMENT ||
283 //              fLEType == PACKAGE_FRAGMENT_ROOT ||
284 //              fLEType == JAVA_PROJECT ||
285 //              fLEType == JAVA_MODEL) { // fix for 1FWNMHH
286 //              Enumeration openBuffers= getBufferManager().getOpenBuffers();
287 //              while (openBuffers.hasMoreElements()) {
288 //                      IBuffer buffer= (IBuffer)openBuffers.nextElement();
289 //                      if (buffer.hasUnsavedChanges()) {
290 //                              IJavaElement owner= (IJavaElement)buffer.getOwner();
291 //                              if (isAncestorOf(owner)) {
292 //                                      return true;
293 //                              }
294 //                      }
295 //              }
296 //      }
297 //      
298 //      return false;
299 //}
300 /**
301  * Subclasses must override as required.
302  *
303  * @see IOpenable
304  */
305 public boolean isConsistent() throws JavaModelException {
306         return true;
307 }
308 /**
309  * 
310  * @see IOpenable
311  */
312 public boolean isOpen() {
313         // TODO isOpen - Openable needs JavaModelManager
314 //      synchronized(JavaModelManager.getJavaModelManager()){
315 //              return JavaModelManager.getJavaModelManager().getInfo(this) != null;
316 //      }
317   return false;
318 }
319 ///**
320 // * Returns true if this represents a source element.
321 // * Openable source elements have an associated buffer created
322 // * when they are opened.
323 // */
324 //protected boolean isSourceElement() {
325 //      return false;
326 //}
327 ///**
328 // * @see IOpenable
329 // */
330 //public void makeConsistent(IProgressMonitor pm) throws JavaModelException {
331 //      if (!isConsistent()) {
332 //              buildStructure((OpenableElementInfo)getElementInfo(), pm);
333 //      }
334 //}
335 ///**
336 // * @see IOpenable
337 // */
338 //public void open(IProgressMonitor pm) throws JavaModelException {
339 //      if (!isOpen()) {
340 //              // TODO: need to synchronize (IOpenable.open(IProgressMonitor) is API
341 //              // TODO: could use getElementInfo instead
342 //              this.openWhenClosed(pm);
343 //      }
344 //}
345 //
346 /**
347  * Opens a buffer on the contents of this element, and returns
348  * the buffer, or returns <code>null</code> if opening fails.
349  * By default, do nothing - subclasses that have buffers
350  * must override as required.
351  */
352 protected IBuffer openBuffer(IProgressMonitor pm) throws JavaModelException {
353         return null;
354 }
355 //
356 ///**
357 // *    Open the parent element if necessary
358 // * 
359 // */
360 //protected void openParent(IProgressMonitor pm) throws JavaModelException {
361 //
362 //      Openable openableParent = (Openable)getOpenableParent();
363 //      if (openableParent != null) {
364 //              if (!openableParent.isOpen()){
365 //                      openableParent.openWhenClosed(pm);
366 //              }
367 //      }
368 //}
369 //
370 ///**
371 // * Open an <code>Openable</code> that is known to be closed (no check for <code>isOpen()</code>).
372 // */
373 //protected void openWhenClosed(IProgressMonitor pm) throws JavaModelException {
374 //      try {
375 //              
376 //              if (JavaModelManager.VERBOSE){
377 //                      System.out.println("OPENING Element ("+ Thread.currentThread()+"): " + this.toStringWithAncestors()); //$NON-NLS-1$//$NON-NLS-2$
378 //              }
379 //              
380 //              // 1) Parent must be open - open the parent if necessary
381 //              openParent(pm);
382 //
383 //              // 2) create the new element info and open a buffer if needed
384 //              OpenableElementInfo info = createElementInfo();
385 //              if (isSourceElement()) {
386 //                      this.openBuffer(pm);
387 //              } 
388 //
389 //              // 3) build the structure of the openable
390 //              buildStructure(info, pm);
391 //
392 //              // 4) anything special
393 //              opening(info);
394 //              
395 //              if (JavaModelManager.VERBOSE) {
396 //                      System.out.println("-> Package cache size = " + JavaModelManager.getJavaModelManager().cache.pkgSize()); //$NON-NLS-1$
397 //                      System.out.println("-> Openable cache filling ratio = " + JavaModelManager.getJavaModelManager().cache.openableFillingRatio() + "%"); //$NON-NLS-1$//$NON-NLS-2$
398 //              }
399 //
400 //              // if any problems occuring openning the element, ensure that it's info
401 //              // does not remain in the cache (some elements, pre-cache their info
402 //              // as they are being opened).
403 //      } catch (JavaModelException e) {
404 //              JavaModelManager.getJavaModelManager().removeInfo(this);
405 //              throw e;
406 //      }
407 //}
408 //
409 ///**
410 // *  Answers true if the parent exists (null parent is answering true)
411 // * 
412 // */
413 //protected boolean parentExists(){
414 //      
415 //      IJavaElement parent = this.getParent();
416 //      if (parent == null) return true;
417 //      return parent.exists();
418 //}
419 //
420 ///**
421 // * Returns whether the corresponding resource or associated file exists
422 // */
423 //protected boolean resourceExists() {
424 //      IWorkspace workspace = ResourcesPlugin.getWorkspace();
425 //      if (workspace == null) return false; // workaround for http://bugs.eclipse.org/bugs/show_bug.cgi?id=34069
426 //      return 
427 //              JavaModel.getTarget(
428 //                      workspace.getRoot(), 
429 //                      this.getPath().makeRelative(), // ensure path is relative (see http://dev.eclipse.org/bugs/show_bug.cgi?id=22517)
430 //                      true) != null;
431 //}
432 //
433 ///**
434 // * @see IOpenable
435 // */
436 //public void save(IProgressMonitor pm, boolean force) throws JavaModelException {
437 //      if (isReadOnly() || this.getResource().isReadOnly()) {
438 //              throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.READ_ONLY, this));
439 //      }
440 //      IBuffer buf = getBuffer();
441 //      if (buf != null) { // some Openables (like a JavaProject) don't have a buffer
442 //              buf.save(pm, force);
443 //              this.makeConsistent(pm); // update the element info of this element
444 //      }
445 //}
446 //
447 /**
448  * Find enclosing package fragment root if any
449  */
450 public PackageFragmentRoot getPackageFragmentRoot() {
451         IJavaElement current = this;
452         do {
453                 if (current instanceof PackageFragmentRoot) return (PackageFragmentRoot)current;
454                 current = current.getParent();
455         } while(current != null);
456         return null;
457 }
458 ///**
459 // * @see ICodeAssist
460 // * @deprecated - use codeComplete(ICompilationUnit, ICompilationUnit, int, ICompletionRequestor) instead
461 // */
462 //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 {
463 //
464 //      if (requestor == null){
465 //              codeComplete(cu, unitToSkip, position, (ICompletionRequestor)null);
466 //              return;
467 //      }
468 //      codeComplete(
469 //              cu,
470 //              unitToSkip,
471 //              position,
472 //              new ICompletionRequestor(){
473 //                      public void acceptAnonymousType(char[] superTypePackageName,char[] superTypeName,char[][] parameterPackageNames,char[][] parameterTypeNames,char[][] parameterNames,char[] completionName,int modifiers,int completionStart,int completionEnd, int relevance) {
474 //                      }
475 //                      public void acceptClass(char[] packageName, char[] className, char[] completionName, int modifiers, int completionStart, int completionEnd, int relevance) {
476 //                              requestor.acceptClass(packageName, className, completionName, modifiers, completionStart, completionEnd);
477 //                      }
478 //                      public void acceptError(IProblem error) {
479 //                              if (true) return; // was disabled in 1.0
480 //
481 //                              try {
482 //                                      IMarker marker = ResourcesPlugin.getWorkspace().getRoot().createMarker(IJavaModelMarker.TRANSIENT_PROBLEM);
483 //                                      marker.setAttribute(IJavaModelMarker.ID, error.getID());
484 //                                      marker.setAttribute(IMarker.CHAR_START, error.getSourceStart());
485 //                                      marker.setAttribute(IMarker.CHAR_END, error.getSourceEnd() + 1);
486 //                                      marker.setAttribute(IMarker.LINE_NUMBER, error.getSourceLineNumber());
487 //                                      marker.setAttribute(IMarker.MESSAGE, error.getMessage());
488 //                                      marker.setAttribute(IMarker.SEVERITY, IMarker.SEVERITY_ERROR);
489 //                                      requestor.acceptError(marker);
490 //                              } catch(CoreException e){
491 //                              }
492 //                      }
493 //                      public void acceptField(char[] declaringTypePackageName, char[] declaringTypeName, char[] name, char[] typePackageName, char[] typeName, char[] completionName, int modifiers, int completionStart, int completionEnd, int relevance) {
494 //                              requestor.acceptField(declaringTypePackageName, declaringTypeName, name, typePackageName, typeName, completionName, modifiers, completionStart, completionEnd);
495 //                      }
496 //                      public void acceptInterface(char[] packageName,char[] interfaceName,char[] completionName,int modifiers,int completionStart,int completionEnd, int relevance) {
497 //                              requestor.acceptInterface(packageName, interfaceName, completionName, modifiers, completionStart, completionEnd);
498 //                      }
499 //                      public void acceptKeyword(char[] keywordName,int completionStart,int completionEnd, int relevance){
500 //                              requestor.acceptKeyword(keywordName, completionStart, completionEnd);
501 //                      }
502 //                      public void acceptLabel(char[] labelName,int completionStart,int completionEnd, int relevance){
503 //                              requestor.acceptLabel(labelName, completionStart, completionEnd);
504 //                      }
505 //                      public void acceptLocalVariable(char[] name,char[] typePackageName,char[] typeName,int modifiers,int completionStart,int completionEnd, int relevance){
506 //                              // ignore
507 //                      }
508 //                      public void acceptMethod(char[] declaringTypePackageName,char[] declaringTypeName,char[] selector,char[][] parameterPackageNames,char[][] parameterTypeNames,char[][] parameterNames,char[] returnTypePackageName,char[] returnTypeName,char[] completionName,int modifiers,int completionStart,int completionEnd, int relevance){
509 //                              // skip parameter names
510 //                              requestor.acceptMethod(declaringTypePackageName, declaringTypeName, selector, parameterPackageNames, parameterTypeNames, returnTypePackageName, returnTypeName, completionName, modifiers, completionStart, completionEnd);
511 //                      }
512 //                      public void acceptMethodDeclaration(char[] declaringTypePackageName,char[] declaringTypeName,char[] selector,char[][] parameterPackageNames,char[][] parameterTypeNames,char[][] parameterNames,char[] returnTypePackageName,char[] returnTypeName,char[] completionName,int modifiers,int completionStart,int completionEnd, int relevance){
513 //                              // ignore
514 //                      }
515 //                      public void acceptModifier(char[] modifierName,int completionStart,int completionEnd, int relevance){
516 //                              requestor.acceptModifier(modifierName, completionStart, completionEnd);
517 //                      }
518 //                      public void acceptPackage(char[] packageName,char[] completionName,int completionStart,int completionEnd, int relevance){
519 //                              requestor.acceptPackage(packageName, completionName, completionStart, completionEnd);
520 //                      }
521 //                      public void acceptType(char[] packageName,char[] typeName,char[] completionName,int completionStart,int completionEnd, int relevance){
522 //                              requestor.acceptType(packageName, typeName, completionName, completionStart, completionEnd);
523 //                      }
524 //                      public void acceptVariableName(char[] typePackageName,char[] typeName,char[] name,char[] completionName,int completionStart,int completionEnd, int relevance){
525 //                              // ignore
526 //                      }
527 //              });
528 //}
529 }