improved PHP parser
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / core / PackageFragmentRoot.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 java.util.ArrayList;
14 import java.util.Map;
15
16 import net.sourceforge.phpdt.core.IJavaElement;
17 import net.sourceforge.phpdt.core.IJavaModelStatusConstants;
18 import net.sourceforge.phpdt.core.IPackageFragment;
19 import net.sourceforge.phpdt.core.IPackageFragmentRoot;
20 import net.sourceforge.phpdt.core.JavaCore;
21 import net.sourceforge.phpdt.core.JavaModelException;
22 import net.sourceforge.phpdt.core.WorkingCopyOwner;
23 import net.sourceforge.phpdt.core.compiler.CharOperation;
24 import net.sourceforge.phpdt.internal.core.util.MementoTokenizer;
25 import net.sourceforge.phpdt.internal.core.util.Util;
26
27 import org.eclipse.core.resources.IContainer;
28 import org.eclipse.core.resources.IFolder;
29 import org.eclipse.core.resources.IResource;
30 import org.eclipse.core.resources.ResourcesPlugin;
31 import org.eclipse.core.runtime.CoreException;
32 import org.eclipse.core.runtime.IPath;
33 import org.eclipse.core.runtime.IProgressMonitor;
34 import org.eclipse.core.runtime.QualifiedName;
35
36 /**
37  * @see IPackageFragmentRoot
38  */
39 public class PackageFragmentRoot extends Openable implements IPackageFragmentRoot {
40
41   /**
42    * The delimiter between the source path and root path in the attachment server property.
43    */
44   protected final static char ATTACHMENT_PROPERTY_DELIMITER = '*';
45
46   /*
47    * No source attachment property
48    */
49   protected final static String NO_SOURCE_ATTACHMENT = ""; //$NON-NLS-1$
50
51   /*
52    * No source mapper singleton
53    */
54   //    protected final static SourceMapper NO_SOURCE_MAPPER = new SourceMapper();
55   /**
56    * The resource associated with this root. (an IResource or a java.io.File (for external jar only))
57    */
58   protected Object resource;
59
60   /**
61    * Constructs a package fragment root which is the root of the java package directory hierarchy.
62    */
63   protected PackageFragmentRoot(IResource resource, JavaProject project, String name) {
64     super(project, name);
65     this.resource = resource;
66   }
67
68   /**
69    * @see Openable
70    */
71   protected boolean buildStructure(OpenableElementInfo info, IProgressMonitor pm, Map newElements, IResource underlyingResource)
72       throws JavaModelException {
73
74     // check whether this pkg fragment root can be opened
75     if (!resourceExists()) { //|| !isOnClasspath()) {
76       throw newNotPresentException();
77     }
78
79     ((PackageFragmentRootInfo) info).setRootKind(determineKind(underlyingResource));
80     return computeChildren(info, newElements);
81   }
82
83   /**
84    * Returns the root's kind - K_SOURCE or K_BINARY, defaults to K_SOURCE if it is not on the classpath.
85    * 
86    * @exception NotPresentException
87    *              if the project and root do not exist.
88    */
89   protected int determineKind(IResource underlyingResource) throws JavaModelException {
90     //          IClasspathEntry[] entries= ((JavaProject)getJavaProject()).getExpandedClasspath(true);
91     //          for (int i= 0; i < entries.length; i++) {
92     //                  IClasspathEntry entry= entries[i];
93     //                  if (entry.getPath().equals(underlyingResource.getFullPath())) {
94     //                          return entry.getContentKind();
95     //                  }
96     //          }
97     return IPackageFragmentRoot.K_SOURCE;
98   }
99
100   /**
101    * Compute the package fragment children of this package fragment root.
102    * 
103    * @exception JavaModelException
104    *              The resource associated with this package fragment root does not exist
105    */
106   protected boolean computeChildren(OpenableElementInfo info, Map newElements) throws JavaModelException {
107     // Note the children are not opened (so not added to newElements) for a regular package fragment root
108     // Howver they are opened for a Jar package fragment root (see JarPackageFragmentRoot#computeChildren)
109     try {
110       // the underlying resource may be a folder or a project (in the case that the project folder
111       // is actually the package fragment root)
112       IResource underlyingResource = getResource();
113       if (underlyingResource.getType() == IResource.FOLDER || underlyingResource.getType() == IResource.PROJECT) {
114         ArrayList vChildren = new ArrayList(5);
115         IContainer rootFolder = (IContainer) underlyingResource;
116         //      char[][] inclusionPatterns = fullInclusionPatternChars();
117         char[][] exclusionPatterns = fullExclusionPatternChars();
118         computeFolderChildren(rootFolder, !Util.isExcluded(rootFolder, exclusionPatterns), "", vChildren, exclusionPatterns); //$NON-NLS-1$
119
120         IJavaElement[] children = new IJavaElement[vChildren.size()];
121         vChildren.toArray(children);
122         info.setChildren(children);
123       }
124     } catch (JavaModelException e) {
125       //problem resolving children; structure remains unknown
126       info.setChildren(new IJavaElement[] {});
127       throw e;
128     }
129     return true;
130   }
131
132   /**
133    * Starting at this folder, create package fragments and add the fragments that are not exclused to the collection of children.
134    * 
135    * @exception JavaModelException
136    *              The resource associated with this package fragment does not exist
137    */
138   protected void computeFolderChildren(IContainer folder, boolean isIncluded, String prefix, ArrayList vChildren,
139       char[][] exclusionPatterns) throws JavaModelException {
140     //, char[][] inclusionPatterns, char[][] exclusionPatterns) throws JavaModelException {
141
142     if (isIncluded) {
143       IPackageFragment pkg = getPackageFragment(prefix);
144       vChildren.add(pkg);
145     }
146     try {
147       JavaProject javaProject = (JavaProject) getJavaProject();
148       IResource[] members = folder.members();
149       boolean hasIncluded = isIncluded;
150       for (int i = 0, max = members.length; i < max; i++) {
151         IResource member = members[i];
152         String memberName = member.getName();
153
154         switch (member.getType()) {
155
156         case IResource.FOLDER:
157           if (Util.isValidFolderNameForPackage(memberName)) {
158             boolean isMemberIncluded = !Util.isExcluded(member, exclusionPatterns);
159             // keep looking inside as long as included already, or may have child included due to inclusion patterns
160             //                                              if (isMemberIncluded || inclusionPatterns != null) {
161             //                                                          // eliminate binary output only if nested inside direct subfolders
162             //                                                          if (javaProject.contains(member)) {
163             //                                                                  String newPrefix;
164             //                                                                  if (prefix.length() == 0) {
165             //                                                                          newPrefix = memberName;
166             //                                                                  } else {
167             //                                                                          newPrefix = prefix + "." + memberName; //$NON-NLS-1$
168             //                                                                  }
169             //                                                                  computeFolderChildren((IFolder) member, isMemberIncluded, newPrefix, vChildren, inclusionPatterns,
170             // exclusionPatterns);
171             //                                                          }
172             //                                                  }
173           }
174           break;
175         case IResource.FILE:
176           // inclusion filter may only include files, in which case we still want to include the immediate parent package (lazily)
177           if (!hasIncluded && Util.isValidCompilationUnitName(memberName) && !Util.isExcluded(member, exclusionPatterns)) {
178             hasIncluded = true;
179             IPackageFragment pkg = getPackageFragment(prefix);
180             vChildren.add(pkg);
181           }
182           break;
183         }
184       }
185     } catch (IllegalArgumentException e) {
186       throw new JavaModelException(e, IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST); // could be thrown by ElementTree when path
187                                                                                          // is not found
188     } catch (CoreException e) {
189       throw new JavaModelException(e);
190     }
191   }
192
193   /**
194    * @see IPackageFragmentRoot
195    */
196   //public void attachSource(IPath sourcePath, IPath rootPath, IProgressMonitor monitor) throws JavaModelException {
197   //    try {
198   //            verifyAttachSource(sourcePath);
199   //            if (monitor != null) {
200   //                    monitor.beginTask(ProjectPrefUtil.bind("element.attachingSource"), 2); //$NON-NLS-1$
201   //            }
202   //            SourceMapper oldMapper= getSourceMapper();
203   //            IWorkspace workspace = ResourcesPlugin.getWorkspace();
204   //            boolean rootNeedsToBeClosed= false;
205   //
206   //            if (sourcePath == null) {
207   //                    //source being detached
208   //                    rootNeedsToBeClosed= true;
209   //                    setSourceMapper(null);
210   //            /* Disable deltas (see 1GDTUSD)
211   //                    // fire a delta to notify the UI about the source detachement.
212   //                    JavaModelManager manager = (JavaModelManager) JavaModelManager.getJavaModelManager();
213   //                    JavaModel model = (JavaModel) getJavaModel();
214   //                    JavaElementDelta attachedSourceDelta = new JavaElementDelta(model);
215   //                    attachedSourceDelta .sourceDetached(this); // this would be a PackageFragmentRoot
216   //                    manager.registerResourceDelta(attachedSourceDelta );
217   //                    manager.fire(); // maybe you want to fire the change later. Let us know about it.
218   //            */
219   //            } else {
220   //            /*
221   //                    // fire a delta to notify the UI about the source attachement.
222   //                    JavaModelManager manager = (JavaModelManager) JavaModelManager.getJavaModelManager();
223   //                    JavaModel model = (JavaModel) getJavaModel();
224   //                    JavaElementDelta attachedSourceDelta = new JavaElementDelta(model);
225   //                    attachedSourceDelta .sourceAttached(this); // this would be a PackageFragmentRoot
226   //                    manager.registerResourceDelta(attachedSourceDelta );
227   //                    manager.fire(); // maybe you want to fire the change later. Let us know about it.
228   //             */
229   //
230   //                    //check if different from the current attachment
231   //                    IPath storedSourcePath= getSourceAttachmentPath();
232   //                    IPath storedRootPath= getSourceAttachmentRootPath();
233   //                    if (monitor != null) {
234   //                            monitor.worked(1);
235   //                    }
236   //                    if (storedSourcePath != null) {
237   //                            if (!(storedSourcePath.equals(sourcePath) && (rootPath != null && rootPath.equals(storedRootPath)) || storedRootPath == null))
238   // {
239   //                                    rootNeedsToBeClosed= true;
240   //                            }
241   //                    }
242   //                    // check if source path is valid
243   //                    Object target = JavaModel.getTarget(workspace.getRoot(), sourcePath, false);
244   //                    if (target == null) {
245   //                            if (monitor != null) {
246   //                                    monitor.done();
247   //                            }
248   //                            throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.INVALID_PATH, sourcePath));
249   //                    }
250   //                    SourceMapper mapper = createSourceMapper(sourcePath, rootPath);
251   //                    if (rootPath == null && mapper.rootPath != null) {
252   //                            // as a side effect of calling the SourceMapper constructor, the root path was computed
253   //                            rootPath = new Path(mapper.rootPath);
254   //                    }
255   //                    setSourceMapper(mapper);
256   //            }
257   //            if (sourcePath == null) {
258   //                    setSourceAttachmentProperty(null); //remove the property
259   //            } else {
260   //                    //set the property to the path of the mapped source
261   //                    setSourceAttachmentProperty(
262   //                            sourcePath.toString()
263   //                            + (rootPath == null ? "" : (ATTACHMENT_PROPERTY_DELIMITER + rootPath.toString()))); //$NON-NLS-1$
264   //            }
265   //            if (rootNeedsToBeClosed) {
266   //                    if (oldMapper != null) {
267   //                            oldMapper.close();
268   //                    }
269   //                    BufferManager manager= BufferManager.getDefaultBufferManager();
270   //                    Enumeration openBuffers= manager.getOpenBuffers();
271   //                    while (openBuffers.hasMoreElements()) {
272   //                            IBuffer buffer= (IBuffer) openBuffers.nextElement();
273   //                            IOpenable possibleMember= buffer.getOwner();
274   //                            if (isAncestorOf((IJavaElement) possibleMember)) {
275   //                                    buffer.close();
276   //                            }
277   //                    }
278   //                    if (monitor != null) {
279   //                            monitor.worked(1);
280   //                    }
281   //            }
282   //    } catch (JavaModelException e) {
283   //            setSourceAttachmentProperty(null); // loose info - will be recomputed
284   //            throw e;
285   //    } finally {
286   //            if (monitor != null) {
287   //                    monitor.done();
288   //            }
289   //    }
290   //}
291   //SourceMapper createSourceMapper(IPath sourcePath, IPath rootPath) {
292   //    SourceMapper mapper = new SourceMapper(
293   //            sourcePath,
294   //            rootPath == null ? null : rootPath.toOSString(),
295   //            this.isExternal() ? JavaCore.getOptions() : this.getJavaProject().getOptions(true)); // only project options if associated with
296   // resource
297   //    return mapper;
298   //}
299   /*
300    * @see net.sourceforge.phpdt.core.IPackageFragmentRoot#delete
301    */
302   //public void delete(
303   //    int updateResourceFlags,
304   //    int updateModelFlags,
305   //    IProgressMonitor monitor)
306   //    throws JavaModelException {
307   //
308   //    DeletePackageFragmentRootOperation op = new DeletePackageFragmentRootOperation(this, updateResourceFlags, updateModelFlags);
309   //    runOperation(op, monitor);
310   //}
311   /**
312    * This root is being closed. If this root has an associated source attachment, close it too.
313    * 
314    * @see JavaElement
315    */
316   //protected void closing(Object info) throws JavaModelException { TODO remove after 2.1
317   //    ((PackageFragmentRootInfo) info).sourceMapper = null;
318   //    super.closing(info);
319   //}
320   /**
321    * Compute the package fragment children of this package fragment root.
322    * 
323    * @exception JavaModelException
324    *              The resource associated with this package fragment root does not exist
325    */
326   //protected boolean computeChildren(OpenableElementInfo info) throws JavaModelException {
327   //    try {
328   //            // the underlying resource may be a folder or a project (in the case that the project folder
329   //            // is actually the package fragment root)
330   //            IResource resource = getResource();
331   //            if (resource.getType() == IResource.FOLDER || resource.getType() == IResource.PROJECT) {
332   //                    ArrayList vChildren = new ArrayList(5);
333   //                    char[][] exclusionPatterns = fullExclusionPatternChars();
334   //                    computeFolderChildren((IContainer) resource, "", vChildren, exclusionPatterns); //$NON-NLS-1$
335   //                    IJavaElement[] children = new IJavaElement[vChildren.size()];
336   //                    vChildren.toArray(children);
337   //                    info.setChildren(children);
338   //            }
339   //    } catch (JavaModelException e) {
340   //            //problem resolving children; structure remains unknown
341   //            info.setChildren(new IJavaElement[]{});
342   //            throw e;
343   //    }
344   //    return true;
345   //}
346   /**
347    * Starting at this folder, create package fragments and add the fragments that are not exclused to the collection of children.
348    * 
349    * @exception JavaModelException
350    *              The resource associated with this package fragment does not exist
351    */
352   //protected void computeFolderChildren(IContainer folder, String prefix, ArrayList vChildren, char[][] exclusionPatterns) throws
353   // JavaModelException {
354   //    IPackageFragment pkg = getPackageFragment(prefix);
355   //    vChildren.add(pkg);
356   //    try {
357   //            JavaProject javaProject = (JavaProject)getJavaProject();
358   //            IResource[] members = folder.members();
359   //            for (int i = 0, max = members.length; i < max; i++) {
360   //                    IResource member = members[i];
361   //                    String memberName = member.getName();
362   //                    if (member.getType() == IResource.FOLDER
363   //                            && ProjectPrefUtil.isValidFolderNameForPackage(memberName)
364   //                            && !ProjectPrefUtil.isExcluded(member, exclusionPatterns)) {
365   //                                    
366   //                            // eliminate binary output only if nested inside direct subfolders
367   //                            if (javaProject.contains(member)) {
368   //                                    String newPrefix;
369   //                                    if (prefix.length() == 0) {
370   //                                            newPrefix = memberName;
371   //                                    } else {
372   //                                            newPrefix = prefix + "." + memberName; //$NON-NLS-1$
373   //                                    }
374   //                                    computeFolderChildren((IFolder) member, newPrefix, vChildren, exclusionPatterns);
375   //                            }
376   //                    }
377   //            }
378   //    } catch(IllegalArgumentException e){
379   //            throw new JavaModelException(e, IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST); // could be thrown by ElementTree when path
380   // is not found
381   //    } catch (CoreException e) {
382   //            throw new JavaModelException(e);
383   //    }
384   //}
385   /*
386    * Computes and returns the source attachment root path for the given source attachment path. Returns <code> null </code> if none
387    * could be found.
388    * 
389    * @param sourceAttachmentPath the given absolute path to the source archive or folder @return the computed source attachment root
390    * path or <code> null </cde> if none could be found @throws JavaModelException
391    */
392   //public IPath computeSourceAttachmentRootPath(IPath sourceAttachmentPath) throws JavaModelException {
393   //    IPath sourcePath = this.getSourceAttachmentPath();
394   //    if (sourcePath == null) return null;
395   //    SourceMapper mapper =
396   //            new SourceMapper(
397   //            sourcePath,
398   //            null, // detect root path
399   //            this.isExternal() ? JavaCore.getOptions() : this.getJavaProject().getOptions(true) // only project options if associated with
400   // resource
401   //    );
402   //    if (mapper.rootPath == null) return null;
403   //    return new Path(mapper.rootPath);
404   //}
405   /*
406    * @see net.sourceforge.phpdt.core.IPackageFragmentRoot#copy
407    */
408   //public void copy(
409   //    IPath destination,
410   //    int updateResourceFlags,
411   //    int updateModelFlags,
412   //    IClasspathEntry sibling,
413   //    IProgressMonitor monitor)
414   //    throws JavaModelException {
415   //            
416   //    CopyPackageFragmentRootOperation op =
417   //            new CopyPackageFragmentRootOperation(this, destination, updateResourceFlags, updateModelFlags, sibling);
418   //    runOperation(op, monitor);
419   //}
420
421   /**
422    * Returns a new element info for this element.
423    */
424   protected Object createElementInfo() {
425     return new PackageFragmentRootInfo();
426   }
427
428   /**
429    * @see IPackageFragmentRoot
430    */
431   //public IPackageFragment createPackageFragment(String name, boolean force, IProgressMonitor monitor) throws JavaModelException {
432   //    CreatePackageFragmentOperation op = new CreatePackageFragmentOperation(this, name, force);
433   //    runOperation(op, monitor);
434   //    return getPackageFragment(name);
435   //}
436   /**
437    * Returns the root's kind - K_SOURCE or K_BINARY, defaults to K_SOURCE if it is not on the classpath.
438    * 
439    * @exception NotPresentException
440    *              if the project and root do not exist.
441    */
442   //protected int determineKind(IResource underlyingResource) throws JavaModelException {
443   //    IClasspathEntry[] entries= ((JavaProject)getJavaProject()).getExpandedClasspath(true);
444   //    for (int i= 0; i < entries.length; i++) {
445   //            IClasspathEntry entry= entries[i];
446   //            if (entry.getPath().equals(underlyingResource.getFullPath())) {
447   //                    return entry.getContentKind();
448   //            }
449   //    }
450   //    return IPackageFragmentRoot.K_SOURCE;
451   //}
452   /**
453    * Compares two objects for equality; for <code>PackageFragmentRoot</code>s, equality is having the same <code>JavaModel</code>,
454    * same resources, and occurrence count.
455    *  
456    */
457   public boolean equals(Object o) {
458     if (this == o)
459       return true;
460     if (!(o instanceof PackageFragmentRoot))
461       return false;
462     PackageFragmentRoot other = (PackageFragmentRoot) o;
463     return getJavaModel().equals(other.getJavaModel()) && this.resource.equals(other.resource)
464         && occurrenceCount == other.occurrenceCount;
465   }
466
467   /**
468    * @see IJavaElement
469    */
470   //public boolean exists() {
471   //    return super.exists()
472   //                            && isOnClasspath();
473   //}
474   //public IClasspathEntry findSourceAttachmentRecommendation() {
475   //    try {
476   //            IPath rootPath = this.getPath();
477   //            IClasspathEntry entry;
478   //            IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
479   //            
480   //            // try on enclosing project first
481   //            JavaProject parentProject = (JavaProject) getJavaProject();
482   //            try {
483   //                    entry = parentProject.getClasspathEntryFor(rootPath);
484   //                    if (entry != null){
485   //                            Object target = JavaModel.getTarget(workspaceRoot, entry.getSourceAttachmentPath(), true);
486   //                            if (target instanceof IFile){
487   //                                    IFile file = (IFile) target;
488   //                                    if (ProjectPrefUtil.isArchiveFileName(file.getName())){
489   //                                            return entry;
490   //                                    }
491   //                            } else if (target instanceof IFolder) {
492   //                                    return entry;
493   //                            }
494   //                            if (target instanceof java.io.File){
495   //                                    java.io.File file = (java.io.File) target;
496   //                                    if (file.isFile()) {
497   //                                            if (ProjectPrefUtil.isArchiveFileName(file.getName())){
498   //                                                    return entry;
499   //                                            }
500   //                                    } else {
501   //                                            // external directory
502   //                                            return entry;
503   //                                    }
504   //                            }
505   //                    }
506   //            } catch(JavaModelException e){
507   //            }
508   //            
509   //            // iterate over all projects
510   //            IJavaModel model = getJavaModel();
511   //            IJavaProject[] jProjects = model.getJavaProjects();
512   //            for (int i = 0, max = jProjects.length; i < max; i++){
513   //                    JavaProject jProject = (JavaProject) jProjects[i];
514   //                    if (jProject == parentProject) continue; // already done
515   //                    try {
516   //                            entry = jProject.getClasspathEntryFor(rootPath);
517   //                            if (entry != null){
518   //                                    Object target = JavaModel.getTarget(workspaceRoot, entry.getSourceAttachmentPath(), true);
519   //                                    if (target instanceof IFile){
520   //                                            IFile file = (IFile) target;
521   //                                            if (ProjectPrefUtil.isArchiveFileName(file.getName())){
522   //                                                    return entry;
523   //                                            }
524   //                                    } else if (target instanceof IFolder) {
525   //                                            return entry;
526   //                                    }
527   //                                    if (target instanceof java.io.File){
528   //                                            java.io.File file = (java.io.File) target;
529   //                                            if (file.isFile()) {
530   //                                                    if (ProjectPrefUtil.isArchiveFileName(file.getName())){
531   //                                                            return entry;
532   //                                                    }
533   //                                            } else {
534   //                                                    // external directory
535   //                                                    return entry;
536   //                                            }
537   //                                    }
538   //                            }
539   //                    } catch(JavaModelException e){
540   //                    }
541   //            }
542   //    } catch(JavaModelException e){
543   //    }
544   //
545   //    return null;
546   //}
547   /*
548    * Returns the exclusion patterns from the classpath entry associated with this root.
549    */
550   char[][] fullExclusionPatternChars() {
551     return null;
552     //  try {
553
554     //          if (this.isOpen() && this.getKind() != IPackageFragmentRoot.K_SOURCE) return null;
555     //          ClasspathEntry entry = (ClasspathEntry)getRawClasspathEntry();
556     //          if (entry == null) {
557     //                  return null;
558     //          } else {
559     //                  return entry.fullExclusionPatternChars();
560     //          }
561     //  } catch (JavaModelException e) {
562     //          return null;
563     //  }
564   }
565
566   /**
567    * @see Openable
568    */
569   protected boolean generateInfos(OpenableElementInfo info, IProgressMonitor pm, Map newElements, IResource underlyingResource)
570       throws JavaModelException {
571
572     //  ((PackageFragmentRootInfo) info).setRootKind(determineKind(underlyingResource));
573     //  return computeChildren(info);
574     return false;
575   }
576
577   /**
578    * @see JavaElement#getHandleMemento()
579    */
580   protected char getHandleMementoDelimiter() {
581     return JavaElement.JEM_PACKAGEFRAGMENTROOT;
582   }
583
584   /**
585    * @see IJavaElement
586    */
587   public int getElementType() {
588     return PACKAGE_FRAGMENT_ROOT;
589   }
590
591   /*
592    * @see JavaElement
593    */
594   public IJavaElement getHandleFromMemento(String token, MementoTokenizer memento, WorkingCopyOwner owner) {
595     switch (token.charAt(0)) {
596     case JEM_COUNT:
597       return getHandleUpdatingCountFromMemento(memento, owner);
598     case JEM_PACKAGEFRAGMENT:
599       String pkgName;
600       if (memento.hasMoreTokens()) {
601         pkgName = memento.nextToken();
602         char firstChar = pkgName.charAt(0);
603         //                              if (firstChar == JEM_CLASSFILE || firstChar == JEM_COMPILATIONUNIT || firstChar == JEM_COUNT) {
604         if (firstChar == JEM_COMPILATIONUNIT || firstChar == JEM_COUNT) {
605           token = pkgName;
606           pkgName = IPackageFragment.DEFAULT_PACKAGE_NAME;
607         } else {
608           token = null;
609         }
610       } else {
611         pkgName = IPackageFragment.DEFAULT_PACKAGE_NAME;
612         token = null;
613       }
614       JavaElement pkg = (JavaElement) getPackageFragment(pkgName);
615       if (token == null) {
616         return pkg.getHandleFromMemento(memento, owner);
617       } else {
618         return pkg.getHandleFromMemento(token, memento, owner);
619       }
620     }
621     return null;
622   }
623
624   /**
625    * @see JavaElement#getHandleMemento()
626    */
627   public String getHandleMemento() {
628     IPath path;
629     IResource underlyingResource = getResource();
630     if (underlyingResource != null) {
631       // internal jar or regular root
632       if (getResource().getProject().equals(getJavaProject().getProject())) {
633         path = underlyingResource.getProjectRelativePath();
634       } else {
635         path = underlyingResource.getFullPath();
636       }
637     } else {
638       // external jar
639       path = getPath();
640     }
641     StringBuffer buff = new StringBuffer(((JavaElement) getParent()).getHandleMemento());
642     buff.append(getHandleMementoDelimiter());
643     escapeMementoName(buff, path.toString());
644     if (this.occurrenceCount > 1) {
645       buff.append(JEM_COUNT);
646       buff.append(this.occurrenceCount);
647     }
648     return buff.toString();
649   }
650
651   /**
652    * @see IPackageFragmentRoot
653    */
654   public int getKind() throws JavaModelException {
655     return ((PackageFragmentRootInfo) getElementInfo()).getRootKind();
656   }
657
658   /**
659    * Returns an array of non-java resources contained in the receiver.
660    */
661   //public Object[] getNonJavaResources() throws JavaModelException {
662   //    return ((PackageFragmentRootInfo) getElementInfo()).getNonJavaResources(getJavaProject(), getResource(), this);
663   //}
664   /**
665    * @see IPackageFragmentRoot
666    */
667   public IPackageFragment getPackageFragment(String packageName) {
668     if (packageName.indexOf(' ') != -1) { // tolerate package names with spaces (e.g. 'x . y')
669                                           // (http://bugs.eclipse.org/bugs/show_bug.cgi?id=21957)
670       char[][] compoundName = Util.toCompoundChars(packageName);
671       StringBuffer buffer = new StringBuffer(packageName.length());
672       for (int i = 0, length = compoundName.length; i < length; i++) {
673         buffer.append(CharOperation.trim(compoundName[i]));
674         if (i != length - 1) {
675           buffer.append('.');
676         }
677       }
678       packageName = buffer.toString();
679     }
680     return new PackageFragment(this, packageName);
681   }
682
683   /**
684    * Returns the package name for the given folder (which is a decendent of this root).
685    */
686   protected String getPackageName(IFolder folder) throws JavaModelException {
687     IPath myPath = getPath();
688     IPath pkgPath = folder.getFullPath();
689     int mySegmentCount = myPath.segmentCount();
690     int pkgSegmentCount = pkgPath.segmentCount();
691     StringBuffer name = new StringBuffer(IPackageFragment.DEFAULT_PACKAGE_NAME);
692     for (int i = mySegmentCount; i < pkgSegmentCount; i++) {
693       if (i > mySegmentCount) {
694         name.append('.');
695       }
696       name.append(pkgPath.segment(i));
697     }
698     return name.toString();
699   }
700
701   /**
702    * @see IJavaElement
703    */
704   public IPath getPath() {
705     return getResource().getFullPath();
706   }
707
708   /*
709    * @see IPackageFragmentRoot
710    */
711   //public IClasspathEntry getRawClasspathEntry() throws JavaModelException {
712   //
713   //    IClasspathEntry rawEntry = null;
714   //    IJavaProject project = this.getJavaProject();
715   //    project.getResolvedClasspath(true); // force the reverse rawEntry cache to be populated
716   //    JavaModelManager.PerProjectInfo perProjectInfo =
717   //            JavaModelManager.getJavaModelManager().getPerProjectInfoCheckExistence(project.getProject());
718   //    if (perProjectInfo != null && perProjectInfo.resolvedPathToRawEntries != null) {
719   //            rawEntry = (IClasspathEntry) perProjectInfo.resolvedPathToRawEntries.get(this.getPath());
720   //    }
721   //    return rawEntry;
722   //}
723   /*
724    * @see IJavaElement
725    */
726   public IResource getResource() {
727     return (IResource) this.resource;
728   }
729
730   /**
731    * @see IPackageFragmentRoot
732    */
733   //public IPath getSourceAttachmentPath() throws JavaModelException {
734   //    if (getKind() != K_BINARY) return null;
735   //    
736   //    String serverPathString= getSourceAttachmentProperty();
737   //    if (serverPathString == null) {
738   //            return null;
739   //    }
740   //    int index= serverPathString.lastIndexOf(ATTACHMENT_PROPERTY_DELIMITER);
741   //    if (index < 0) {
742   //            // no root path specified
743   //            return new Path(serverPathString);
744   //    } else {
745   //            String serverSourcePathString= serverPathString.substring(0, index);
746   //            return new Path(serverSourcePathString);
747   //    }
748   //}
749   /**
750    * Returns the server property for this package fragment root's source attachement.
751    */
752   //protected String getSourceAttachmentProperty() throws JavaModelException {
753   //    String propertyString = null;
754   //    QualifiedName qName= getSourceAttachmentPropertyName();
755   //    try {
756   //            propertyString = ResourcesPlugin.getWorkspace().getRoot().getPersistentProperty(qName);
757   //            
758   //            // if no existing source attachment information, then lookup a recommendation from classpath entries
759   //            if (propertyString == null) {
760   //                    IClasspathEntry recommendation = findSourceAttachmentRecommendation();
761   //                    if (recommendation != null) {
762   //                            IPath rootPath = recommendation.getSourceAttachmentRootPath();
763   //                            propertyString =
764   //                                    recommendation.getSourceAttachmentPath().toString()
765   //                                            + ((rootPath == null)
766   //                                                    ? "" : //$NON-NLS-1$
767   //                                                    (ATTACHMENT_PROPERTY_DELIMITER + rootPath.toString()));
768   //                            setSourceAttachmentProperty(propertyString);
769   //                    } else {
770   //                            // mark as being already looked up
771   //                            setSourceAttachmentProperty(NO_SOURCE_ATTACHMENT);
772   //                    }
773   //            } else if (NO_SOURCE_ATTACHMENT.equals(propertyString)) {
774   //                    // already looked up and no source attachment found
775   //                    return null;
776   //            }
777   //            return propertyString;
778   //    } catch (CoreException ce) {
779   //            throw new JavaModelException(ce);
780   //    }
781   //}
782   /**
783    * Returns the qualified name for the source attachment property of this root.
784    */
785   protected QualifiedName getSourceAttachmentPropertyName() throws JavaModelException {
786     return new QualifiedName(JavaCore.PLUGIN_ID, "sourceattachment: " + this.getPath().toOSString()); //$NON-NLS-1$
787   }
788
789   public void setSourceAttachmentProperty(String property) {
790     try {
791       ResourcesPlugin.getWorkspace().getRoot().setPersistentProperty(this.getSourceAttachmentPropertyName(), property);
792     } catch (CoreException ce) {
793     }
794   }
795
796   /**
797    * For use by <code>AttachSourceOperation</code> only. Sets the source mapper associated with this root.
798    */
799   //public void setSourceMapper(SourceMapper mapper) throws JavaModelException {
800   //    ((PackageFragmentRootInfo) getElementInfo()).setSourceMapper(mapper);
801   //}
802
803   /**
804    * @see IPackageFragmentRoot
805    */
806   //public IPath getSourceAttachmentRootPath() throws JavaModelException {
807   //    if (getKind() != K_BINARY) return null;
808   //    
809   //    String serverPathString= getSourceAttachmentProperty();
810   //    if (serverPathString == null) {
811   //            return null;
812   //    }
813   //    int index = serverPathString.lastIndexOf(ATTACHMENT_PROPERTY_DELIMITER);
814   //    if (index == -1) return null;
815   //    String serverRootPathString= IPackageFragmentRoot.DEFAULT_PACKAGEROOT_PATH;
816   //    if (index != serverPathString.length() - 1) {
817   //            serverRootPathString= serverPathString.substring(index + 1);
818   //    }
819   //    return new Path(serverRootPathString);
820   //}
821   /**
822    * @see JavaElement
823    */
824   //public SourceMapper getSourceMapper() {
825   //    SourceMapper mapper;
826   //    try {
827   //            PackageFragmentRootInfo rootInfo = (PackageFragmentRootInfo) getElementInfo();
828   //            mapper = rootInfo.getSourceMapper();
829   //            if (mapper == null) {
830   //                    // first call to this method
831   //                    IPath sourcePath= getSourceAttachmentPath();
832   //                    if (sourcePath != null) {
833   //                            IPath rootPath= getSourceAttachmentRootPath();
834   //                            mapper = this.createSourceMapper(sourcePath, rootPath);
835   //                            if (rootPath == null && mapper.rootPath != null) {
836   //                                    // as a side effect of calling the SourceMapper constructor, the root path was computed
837   //                                    rootPath = new Path(mapper.rootPath);
838   //                                    
839   //                                    //set the property to the path of the mapped source
840   //                                    this.setSourceAttachmentProperty(
841   //                                            sourcePath.toString()
842   //                                            + ATTACHMENT_PROPERTY_DELIMITER
843   //                                            + rootPath.toString());
844   //                            }
845   //                            rootInfo.setSourceMapper(mapper);
846   //                    } else {
847   //                            // remember that no source is attached
848   //                            rootInfo.setSourceMapper(NO_SOURCE_MAPPER);
849   //                            mapper = null;
850   //                    }
851   //            } else if (mapper == NO_SOURCE_MAPPER) {
852   //                    // a previous call to this method found out that no source was attached
853   //                    mapper = null;
854   //            }
855   //    } catch (JavaModelException e) {
856   //            // no source can be attached
857   //            mapper = null;
858   //    }
859   //    return mapper;
860   //}
861   /**
862    * @see IJavaElement
863    */
864   public IResource getUnderlyingResource() throws JavaModelException {
865     if (!exists())
866       throw newNotPresentException();
867     return getResource();
868   }
869
870   public int hashCode() {
871     return this.resource.hashCode();
872   }
873
874   /**
875    * @see IPackageFragmentRoot
876    */
877   public boolean isArchive() {
878     return false;
879   }
880
881   /**
882    * @see IPackageFragmentRoot
883    */
884   public boolean isExternal() {
885     return false;
886   }
887
888   /*
889    * Returns whether this package fragment root is on the classpath of its project.
890    */
891   //protected boolean isOnClasspath() {
892   //    if (this.getElementType() == IJavaElement.JAVA_PROJECT){
893   //            return true;
894   //    }
895   //    
896   //    IPath path = this.getPath();
897   //    try {
898   //            // check package fragment root on classpath of its project
899   //            IJavaProject project = this.getJavaProject();
900   //            IClasspathEntry[] classpath = project.getResolvedClasspath(true);
901   //            for (int i = 0, length = classpath.length; i < length; i++) {
902   //                    IClasspathEntry entry = classpath[i];
903   //                    if (entry.getPath().equals(path)) {
904   //                            return true;
905   //                    }
906   //            }
907   //    } catch(JavaModelException e){
908   //            // could not read classpath, then assume it is outside
909   //    }
910   //    return false;
911   //}
912   /*
913    * @see net.sourceforge.phpdt.core.IPackageFragmentRoot#move
914    */
915   //public void move(
916   //    IPath destination,
917   //    int updateResourceFlags,
918   //    int updateModelFlags,
919   //    IClasspathEntry sibling,
920   //    IProgressMonitor monitor)
921   //    throws JavaModelException {
922   //
923   //    MovePackageFragmentRootOperation op =
924   //            new MovePackageFragmentRootOperation(this, destination, updateResourceFlags, updateModelFlags, sibling);
925   //    runOperation(op, monitor);
926   //}
927   //
928   //
929   //protected void openWhenClosed(IProgressMonitor pm) throws JavaModelException {
930   //    if (!this.resourceExists()
931   //                    || !this.isOnClasspath()) {
932   //            throw newNotPresentException();
933   //    }
934   //    super.openWhenClosed(pm);
935   //}
936   /**
937    * Recomputes the children of this element, based on the current state of the workbench.
938    */
939   //public void refreshChildren() {
940   //    try {
941   //            OpenableElementInfo info= (OpenableElementInfo)getElementInfo();
942   //            computeChildren(info);
943   //    } catch (JavaModelException e) {
944   //            // do nothing.
945   //    }
946   //}
947   ///*
948   // * @see JavaElement#rootedAt(IJavaProject)
949   // */
950   //public IJavaElement rootedAt(IJavaProject project) {
951   //    return
952   //            new PackageFragmentRoot(
953   //                    getResource(),
954   //                    project,
955   //                    name);
956   //}
957   /**
958    * @private Debugging purposes
959    */
960   protected void toStringInfo(int tab, StringBuffer buffer, Object info) {
961     buffer.append(this.tabString(tab));
962     if (getElementName().length() == 0) {
963       buffer.append("[project root]"); //$NON-NLS-1$
964     } else {
965       IPath path = getPath();
966       if (getJavaProject().getElementName().equals(path.segment(0))) {
967         buffer.append(path.removeFirstSegments(1).makeRelative());
968       } else {
969         buffer.append(path);
970       }
971     }
972     if (info == null) {
973       buffer.append(" (not open)"); //$NON-NLS-1$
974     }
975   }
976
977   /**
978    * Possible failures:
979    * <ul>
980    * <li>ELEMENT_NOT_PRESENT - the root supplied to the operation does not exist
981    * <li>INVALID_ELEMENT_TYPES - the root is not of kind K_BINARY
982    * <li>RELATIVE_PATH - the path supplied to this operation must be an absolute path
983    * </ul>
984    */
985   //protected void verifyAttachSource(IPath sourcePath) throws JavaModelException {
986   //    if (!exists()) {
987   //            throw newNotPresentException();
988   //    } else if (this.getKind() != K_BINARY) {
989   //            throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.INVALID_ELEMENT_TYPES, this));
990   //    } else if (sourcePath != null && !sourcePath.isAbsolute()) {
991   //            throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.RELATIVE_PATH, sourcePath));
992   //    }
993   //}
994 }