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