package org.rubypeople.rdt.internal.core; import java.io.File; import java.util.ArrayList; import java.util.HashSet; import java.util.Map; import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.Path; import org.rubypeople.rdt.core.IParent; import org.rubypeople.rdt.core.IRubyElement; import org.rubypeople.rdt.core.IRubyScript; import org.rubypeople.rdt.core.ISourceFolder; import org.rubypeople.rdt.core.ISourceFolderRoot; import org.rubypeople.rdt.core.RubyModelException; import org.rubypeople.rdt.core.WorkingCopyOwner; import org.rubypeople.rdt.internal.core.util.MementoTokenizer; import org.rubypeople.rdt.internal.core.util.Messages; import org.rubypeople.rdt.internal.core.util.Util; public class SourceFolder extends Openable implements ISourceFolder { public String[] names; public SourceFolder(SourceFolderRoot parent, String[] names) { super(parent); this.names = names; } /** * @see IParent */ public boolean hasChildren() throws RubyModelException { return getChildren().length > 0; } @Override protected boolean buildStructure(OpenableElementInfo info, IProgressMonitor pm, Map newElements, IResource underlyingResource) throws RubyModelException { // check whether this folder can be opened if (!underlyingResource.isAccessible()) throw newNotPresentException(); // check that it is not excluded (https://bugs.eclipse.org/bugs/show_bug.cgi?id=138577) if (Util.isExcluded(this)) throw newNotPresentException(); // add ruby scripts from resources HashSet vChildren = new HashSet(); try { SourceFolderRoot root = getSourceFolderRoot(); char[][] inclusionPatterns = root.fullInclusionPatternChars(); char[][] exclusionPatterns = root.fullExclusionPatternChars(); IResource[] members = ((IContainer) underlyingResource).members(); for (int i = 0, max = members.length; i < max; i++) { IResource child = members[i]; if (child.getType() != IResource.FOLDER && !Util.isExcluded(child, inclusionPatterns, exclusionPatterns)) { IRubyElement childElement; if (Util.isValidRubyScriptName(child.getName())) { childElement = new RubyScript(this, child.getName(), DefaultWorkingCopyOwner.PRIMARY); vChildren.add(childElement); } else if (Util.isERBLikeFileName(child.getName())) { childElement = new ERBScript(this, child.getName(), DefaultWorkingCopyOwner.PRIMARY); vChildren.add(childElement); } } } } catch (CoreException e) { throw new RubyModelException(e); } // add primary compilation units IRubyScript[] primaryCompilationUnits = getRubyScripts(DefaultWorkingCopyOwner.PRIMARY); for (int i = 0, length = primaryCompilationUnits.length; i < length; i++) { IRubyScript primary = primaryCompilationUnits[i]; vChildren.add(primary); } IRubyElement[] children = new IRubyElement[vChildren.size()]; vChildren.toArray(children); info.setChildren(children); return true; } @Override protected Object createElementInfo() { return new SourceFolderInfo(); } @Override public int getElementType() { return IRubyElement.SOURCE_FOLDER; } @Override public String getElementName() { if (names.length == 0) return ""; return Util.concatWith(this.names, File.separatorChar); } public boolean containsRubyResources() throws RubyModelException { return ((SourceFolderInfo) getElementInfo()).containsRubyResources(); } public IRubyScript createRubyScript(String name, String contents, boolean force, IProgressMonitor monitor) throws RubyModelException { CreateRubyScriptOperation op= new CreateRubyScriptOperation(this, name, contents, force); op.runOperation(monitor); return new RubyScript(this, name, DefaultWorkingCopyOwner.PRIMARY); } public Object[] getNonRubyResources() throws RubyModelException { if (this.isDefaultPackage()) { // We don't want to show non ruby resources of the default package (see PR #1G58NB8) return RubyElementInfo.NO_NON_RUBY_RESOURCES; } else { return ((SourceFolderInfo) getElementInfo()).getNonRubyResources(getResource(), getSourceFolderRoot()); } } public boolean isDefaultPackage() { return this.names.length == 0; } public IRubyScript[] getRubyScripts() throws RubyModelException { ArrayList<IRubyElement> list = getChildrenOfType(SCRIPT); IRubyScript[] array= new IRubyScript[list.size()]; list.toArray(array); return array; } public IRubyScript[] getRubyScripts(WorkingCopyOwner owner) throws RubyModelException { IRubyScript[] workingCopies = RubyModelManager.getRubyModelManager().getWorkingCopies(owner, false/*don't add primary*/); if (workingCopies == null) return RubyModelManager.NO_WORKING_COPY; int length = workingCopies.length; IRubyScript[] result = new IRubyScript[length]; int index = 0; for (int i = 0; i < length; i++) { IRubyScript wc = workingCopies[i]; if (equals(wc.getParent()) && !Util.isExcluded(wc)) { // 59933 - excluded wc shouldn't be answered back result[index++] = wc; } } if (index != length) { System.arraycopy(result, 0, result = new IRubyScript[index], 0, index); } return result; } public IPath getPath() { SourceFolderRoot root = this.getSourceFolderRoot(); IPath path = root.getPath(); for (int i = 0, length = this.names.length; i < length; i++) { String name = this.names[i]; path = path.append(name); } return path; } public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof SourceFolder)) return false; SourceFolder other = (SourceFolder) o; return Util.equalArraysOrNull(this.names, other.names) && this.parent.equals(other.parent); } public boolean exists() { // super.exist() only checks for the parent and the resource existence // so also ensure that the package is not exceluded (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=138577) return super.exists() && !Util.isExcluded(this); } public IResource getResource() { SourceFolderRoot root = this.getSourceFolderRoot(); if (root.isExternal()) { return root.getResource(); } int length = this.names.length; if (length == 0) { return root.getResource(); } IPath path = new Path(this.names[0]); for (int i = 1; i < length; i++) path = path.append(this.names[i]); return ((IContainer) root.getResource()).getFolder(path); } public IResource getUnderlyingResource() throws RubyModelException { IResource rootResource = this.parent.getUnderlyingResource(); if (rootResource == null) { //jar package fragment root that has no associated resource return null; } // the underlying resource may be a folder or a project (in the case that the project folder // is atually the package fragment root) if (rootResource.getType() == IResource.FOLDER || rootResource.getType() == IResource.PROJECT) { IContainer folder = (IContainer) rootResource; String[] segs = this.names; for (int i = 0; i < segs.length; ++i) { IResource child = folder.findMember(segs[i]); if (child == null || child.getType() != IResource.FOLDER) { throw newNotPresentException(); } folder = (IFolder) child; } return folder; } else { return rootResource; } } public IRubyScript getRubyScript(String name) { if (org.rubypeople.rdt.internal.core.util.Util.isERBLikeFileName(name)) { return new ERBScript(this, name, DefaultWorkingCopyOwner.PRIMARY); } if (!org.rubypeople.rdt.internal.core.util.Util.isRubyLikeFileName(name)) { throw new IllegalArgumentException(Messages.convention_unit_notRubyName); } return new RubyScript(this, name, DefaultWorkingCopyOwner.PRIMARY); } /* * @see RubyElement */ public IRubyElement getHandleFromMemento(String token, MementoTokenizer memento, WorkingCopyOwner owner) { switch (token.charAt(0)) { case JEM_RUBYSCRIPT: if (!memento.hasMoreTokens()) return this; String cuName = memento.nextToken(); RubyElement cu = new RubyScript(this, cuName, owner); return cu.getHandleFromMemento(memento, owner); } return null; } /** * @see RubyElement#getHandleMementoDelimiter() */ protected char getHandleMementoDelimiter() { return RubyElement.JEM_SOURCE_FOLDER; } /** * @see ISourceFolder#hasSubfolders() */ public boolean hasSubfolders() throws RubyModelException { IRubyElement[] packages= ((ISourceFolderRoot)getParent()).getChildren(); int namesLength = this.names.length; nextPackage: for (int i= 0, length = packages.length; i < length; i++) { String[] otherNames = ((SourceFolder) packages[i]).names; if (otherNames.length <= namesLength) continue nextPackage; for (int j = 0; j < namesLength; j++) if (!this.names[j].equals(otherNames[j])) continue nextPackage; return true; } return false; } }