| /******************************************************************************* |
| * Copyright (c) 2005, 2017 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| *******************************************************************************/ |
| package org.eclipse.dltk.internal.core; |
| |
| import java.util.ArrayList; |
| import java.util.HashSet; |
| import java.util.List; |
| import java.util.Map; |
| |
| import org.eclipse.core.resources.IContainer; |
| 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.dltk.core.DLTKCore; |
| import org.eclipse.dltk.core.DLTKLanguageManager; |
| import org.eclipse.dltk.core.IDLTKLanguageToolkit; |
| import org.eclipse.dltk.core.IModelElement; |
| import org.eclipse.dltk.core.IModelProvider; |
| import org.eclipse.dltk.core.IProjectFragment; |
| import org.eclipse.dltk.core.IScriptFolder; |
| import org.eclipse.dltk.core.ISourceModule; |
| import org.eclipse.dltk.core.ModelException; |
| import org.eclipse.dltk.core.WorkingCopyOwner; |
| import org.eclipse.dltk.internal.core.util.MementoTokenizer; |
| import org.eclipse.dltk.internal.core.util.Messages; |
| import org.eclipse.dltk.internal.core.util.Util; |
| import org.eclipse.dltk.utils.CorePrinter; |
| |
| public class ScriptFolder extends Openable implements IScriptFolder { |
| |
| protected final IPath path; |
| private final String elementName; |
| |
| protected ScriptFolder(ModelElement parent, IPath path) { |
| super(parent); |
| this.path = path; |
| |
| elementName = pathToString(path); |
| } |
| |
| public static String pathToString(IPath path) { |
| final int segmentCount = path.segmentCount(); |
| if (segmentCount == 0) { |
| return org.eclipse.dltk.compiler.util.Util.EMPTY_STRING; |
| } else if (segmentCount == 1) { |
| return path.segment(0); |
| } else { |
| int resultSize = (segmentCount - 1) |
| /* x PACKAGE_DELIMETER_STR.length() */; |
| for (int i = 0; i < segmentCount; ++i) { |
| resultSize += path.segment(i).length(); |
| } |
| char[] result = new char[resultSize]; |
| int index = 0; |
| for (int i = 0; i < segmentCount; ++i) { |
| if (i != 0) { |
| result[index++] = PACKAGE_DELIMITER; |
| } |
| final String segment = path.segment(i); |
| segment.getChars(0, segment.length(), result, index); |
| index += segment.length(); |
| } |
| return new String(result); |
| } |
| } |
| |
| public static String pathToString(String[] path) { |
| final int segmentCount = path.length; |
| if (segmentCount == 0) { |
| return org.eclipse.dltk.compiler.util.Util.EMPTY_STRING; |
| } else if (segmentCount == 1) { |
| return path[0]; |
| } else { |
| int resultSize = (segmentCount - 1) |
| /* x PACKAGE_DELIMETER_STR.length() */; |
| for (int i = 0; i < segmentCount; ++i) { |
| resultSize += path[i].length(); |
| } |
| char[] result = new char[resultSize]; |
| int index = 0; |
| for (int i = 0; i < segmentCount; ++i) { |
| if (i != 0) { |
| result[index++] = PACKAGE_DELIMITER; |
| } |
| final String segment = path[i]; |
| segment.getChars(0, segment.length(), result, index); |
| index += segment.length(); |
| } |
| return new String(result); |
| } |
| } |
| |
| /** |
| * @see ModelElement |
| */ |
| @Override |
| protected Object createElementInfo() { |
| return new ScriptFolderInfo(); |
| } |
| |
| @Override |
| public int getElementType() { |
| return SCRIPT_FOLDER; |
| } |
| |
| /** |
| * @see IModelElement#getPath() |
| */ |
| @Override |
| public IPath getPath() { |
| IProjectFragment root = this.getProjectFragment(); |
| if (root.isArchive()) { |
| return root.getPath(); |
| } else { |
| return root.getPath().append(path); |
| } |
| } |
| |
| /** |
| * @see IModelElement#getResource() |
| */ |
| @Override |
| public IResource getResource() { |
| IProjectFragment root = this.getProjectFragment(); |
| if (root.isArchive()) { |
| return root.getResource(); |
| } else { |
| if (path.segmentCount() == 0) |
| return root.getResource(); |
| IContainer container = (IContainer) root.getResource(); |
| if (container != null) { |
| return container.getFolder(path); |
| } |
| return null; |
| } |
| } |
| |
| @Override |
| public boolean equals(Object o) { |
| if (this == o) |
| return true; |
| if (!(o instanceof ScriptFolder)) |
| return false; |
| |
| ScriptFolder other = (ScriptFolder) o; |
| return this.path.equals(other.path) && this.parent.equals(other.parent); |
| } |
| |
| @Override |
| public int hashCode() { |
| return Util.combineHashCodes(parent.hashCode(), path.hashCode()); |
| } |
| |
| @Override |
| public boolean exists() { |
| /* |
| * super.exist() only checks for the parent and the resource existence |
| * so also ensure that the package is not excluded (see |
| * https://bugs.eclipse.org/bugs/show_bug.cgi?id=138577) |
| */ |
| return super.exists() && !Util.isExcluded(this); |
| } |
| |
| public int getKind() throws ModelException { |
| return getProjectFragment().getKind(); |
| } |
| |
| @Override |
| protected boolean buildStructure(OpenableElementInfo info, |
| IProgressMonitor pm, Map newElements, IResource underlyingResource) |
| throws ModelException { |
| // check whether this folder can be opened |
| if (!underlyingResource.isAccessible()) |
| throw newNotPresentException(); |
| |
| int kind = getKind(); |
| |
| if (kind == IProjectFragment.K_SOURCE && Util.isExcluded(this)) |
| throw newNotPresentException(); |
| |
| // add modules from resources |
| HashSet<IModelElement> vChildren = new HashSet<>(); |
| try { |
| IProjectFragment root = getProjectFragment(); |
| 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, root)) { |
| IModelElement childElement; |
| if (kind == IProjectFragment.K_SOURCE |
| && Util.isValidSourceModule(this, child)) { |
| childElement = getSourceModule(child.getName()); |
| vChildren.add(childElement); |
| } |
| } |
| } |
| } catch (CoreException e) { |
| throw new ModelException(e); |
| } |
| |
| if (kind == IProjectFragment.K_SOURCE) { |
| // add primary source modules |
| ISourceModule[] primarySourceModules = getSourceModules( |
| DefaultWorkingCopyOwner.PRIMARY); |
| for (int i = 0, length = primarySourceModules.length; i < length; i++) { |
| ISourceModule primary = primarySourceModules[i]; |
| vChildren.add(primary); |
| } |
| } |
| |
| // IModelElement[] children = new IModelElement[vChildren.size()]; |
| // vChildren.toArray(children); |
| List<IModelElement> childrenSet = new ArrayList<>( |
| vChildren); |
| // Call for extra model providers |
| IDLTKLanguageToolkit toolkit = DLTKLanguageManager |
| .getLanguageToolkit(this); |
| if (toolkit != null) { |
| IModelProvider[] providers = ModelProviderManager |
| .getProviders(toolkit.getNatureId()); |
| if (providers != null) { |
| for (int i = 0; i < providers.length; i++) { |
| providers[i].provideModelChanges(this, childrenSet); |
| } |
| } |
| } |
| info.setChildren( |
| childrenSet.toArray(new IModelElement[childrenSet.size()])); |
| return true; |
| } |
| |
| public ISourceModule[] getSourceModules(WorkingCopyOwner owner) { |
| ISourceModule[] workingCopies = ModelManager.getModelManager() |
| .getWorkingCopies(owner, false/* don't add primary */); |
| if (workingCopies == null) |
| return ModelManager.NO_WORKING_COPY; |
| int length = workingCopies.length; |
| ISourceModule[] result = new ISourceModule[length]; |
| int index = 0; |
| for (int i = 0; i < length; i++) { |
| ISourceModule wc = workingCopies[i]; |
| IResource res = wc.getResource(); |
| boolean valid; |
| if (res != null) |
| valid = Util.isValidSourceModule(this, res); |
| else |
| valid = Util.isValidSourceModule(this, wc.getPath()); |
| if (equals(wc.getParent()) && !Util.isExcluded(wc) && valid) { |
| result[index++] = wc; |
| } |
| } |
| if (index != length) { |
| System.arraycopy(result, 0, result = new ISourceModule[index], 0, |
| index); |
| } |
| return result; |
| } |
| |
| @Override |
| public ISourceModule getSourceModule(String name) { |
| // We need to check for element providers and if provider are declared |
| // we need to build structure to return correct handle here. |
| IDLTKLanguageToolkit toolkit = DLTKLanguageManager |
| .getLanguageToolkit(this); |
| if (toolkit != null) { |
| IModelProvider[] providers = ModelProviderManager |
| .getProviders(toolkit.getNatureId()); |
| if (providers != null) { |
| boolean provides = false; |
| for (int i = 0; i < providers.length; i++) { |
| if (providers[i].isModelChangesProvidedFor(this, name)) { |
| provides = true; |
| break; |
| } |
| } |
| if (provides) { |
| try { |
| IModelElement[] children = getChildren(); |
| IPath fullPath = getPath().append(name); |
| for (int i = 0; i < children.length; i++) { |
| IModelElement child = children[i]; |
| if (child instanceof IScriptFolder) { |
| IPath childPath = child.getPath(); |
| if (fullPath.equals(childPath)) { |
| return (ISourceModule) child; |
| } |
| } |
| } |
| } catch (ModelException e) { |
| DLTKCore.error( |
| "Could not obtain model element childrens.", e); |
| } |
| } |
| } |
| } |
| return new SourceModule(this, name, DefaultWorkingCopyOwner.PRIMARY); |
| } |
| |
| /** |
| * @see IScriptFolder |
| */ |
| @Override |
| public ISourceModule createSourceModule(String cuName, String contents, |
| boolean force, IProgressMonitor monitor) throws ModelException { |
| CreateSourceModuleOperation op = new CreateSourceModuleOperation(this, |
| cuName, contents, force); |
| op.runOperation(monitor); |
| return new SourceModule(this, cuName, DefaultWorkingCopyOwner.PRIMARY); |
| } |
| |
| @Override |
| public final IProjectFragment getProjectFragment() { |
| return (IProjectFragment) getParent(); |
| } |
| |
| /** |
| * Debugging purposes |
| */ |
| @Override |
| protected void toStringName(StringBuffer buffer) { |
| String elementName = getElementName(); |
| if (elementName.length() == 0) { |
| buffer.append("<default>"); //$NON-NLS-1$ |
| } else { |
| buffer.append(elementName); |
| } |
| } |
| |
| @Override |
| public String getElementName() { |
| return elementName; |
| } |
| |
| @Override |
| public boolean isRootFolder() { |
| return path.segmentCount() == 0; |
| } |
| |
| @Override |
| public void printNode(CorePrinter output) { |
| output.formatPrint("DLTK Script folder:" + getElementName()); //$NON-NLS-1$ |
| output.indent(); |
| try { |
| IModelElement modelElements[] = this.getChildren(); |
| for (int i = 0; i < modelElements.length; ++i) { |
| IModelElement element = modelElements[i]; |
| if (element instanceof ModelElement) { |
| ((ModelElement) element).printNode(output); |
| } else { |
| output.print("Unknown element:" + element); //$NON-NLS-1$ |
| } |
| } |
| } catch (ModelException ex) { |
| output.formatPrint(ex.getLocalizedMessage()); |
| } |
| output.dedent(); |
| } |
| |
| @Override |
| public ISourceModule[] getSourceModules() throws ModelException { |
| List<IModelElement> list = getChildrenOfType(SOURCE_MODULE); |
| return list.toArray(new ISourceModule[list.size()]); |
| } |
| |
| @Override |
| public Object[] getForeignResources() throws ModelException { |
| if (this.isRootFolder()) { |
| return ModelElementInfo.NO_NON_SCRIPT_RESOURCES; |
| } else { |
| return ((ScriptFolderInfo) getElementInfo()) |
| .getForeignResources(getResource(), getProjectFragment()); |
| } |
| } |
| |
| @Override |
| public boolean hasSubfolders() throws ModelException { |
| IModelElement[] packages = ((IProjectFragment) getParent()) |
| .getChildren(); |
| int namesLength = this.path.segmentCount(); |
| nextPackage: for (int i = 0, length = packages.length; i < length; i++) { |
| IPath otherNames = null; |
| if (packages[i] instanceof ScriptFolder) { |
| otherNames = ((ScriptFolder) packages[i]).path; |
| if (otherNames.segmentCount() <= namesLength) |
| continue nextPackage; |
| for (int j = 0; j < namesLength; j++) |
| if (!this.path.segment(j).equals(otherNames.segment(j))) |
| continue nextPackage; |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| @Override |
| public IModelElement getHandleFromMemento(String token, |
| MementoTokenizer memento, WorkingCopyOwner owner) { |
| switch (token.charAt(0)) { |
| case JEM_SOURCEMODULE: |
| if (!memento.hasMoreTokens()) |
| return this; |
| String classFileName = memento.nextToken(); |
| ModelElement classFile = (ModelElement) getSourceModule( |
| classFileName); |
| return classFile.getHandleFromMemento(memento, owner); |
| case JEM_USER_ELEMENT: |
| return MementoModelElementUtil.getHandleFromMemento(memento, this, |
| owner); |
| } |
| return null; |
| } |
| |
| @Override |
| protected char getHandleMementoDelimiter() { |
| return JEM_SCRIPTFOLDER; |
| } |
| |
| @Override |
| public boolean containsScriptResources() throws ModelException { |
| Object elementInfo = getElementInfo(); |
| if (!(elementInfo instanceof ScriptFolderInfo)) |
| return false; |
| ScriptFolderInfo scriptElementInfo = (ScriptFolderInfo) elementInfo; |
| return scriptElementInfo.containsScriptResources(); |
| } |
| |
| @Override |
| public boolean hasChildren() throws ModelException { |
| return getChildren().length > 0; |
| } |
| |
| @Override |
| public void copy(IModelElement container, IModelElement sibling, |
| String rename, boolean replace, IProgressMonitor monitor) |
| throws ModelException { |
| if (container == null) { |
| throw new IllegalArgumentException( |
| Messages.operation_nullContainer); |
| } |
| IModelElement[] elements = new IModelElement[] { this }; |
| IModelElement[] containers = new IModelElement[] { container }; |
| IModelElement[] siblings = null; |
| if (sibling != null) { |
| siblings = new IModelElement[] { sibling }; |
| } |
| String[] renamings = null; |
| if (rename != null) { |
| renamings = new String[] { rename }; |
| } |
| getModel().copy(elements, containers, siblings, renamings, replace, |
| monitor); |
| } |
| |
| @Override |
| public void delete(boolean force, IProgressMonitor monitor) |
| throws ModelException { |
| IModelElement[] elements = new IModelElement[] { this }; |
| getModel().delete(elements, force, monitor); |
| } |
| |
| @Override |
| public void move(IModelElement container, IModelElement sibling, |
| String rename, boolean replace, IProgressMonitor monitor) |
| throws ModelException { |
| if (container == null) { |
| throw new IllegalArgumentException( |
| Messages.operation_nullContainer); |
| } |
| IModelElement[] elements = new IModelElement[] { this }; |
| IModelElement[] containers = new IModelElement[] { container }; |
| IModelElement[] siblings = null; |
| if (sibling != null) { |
| siblings = new IModelElement[] { sibling }; |
| } |
| String[] renamings = null; |
| if (rename != null) { |
| renamings = new String[] { rename }; |
| } |
| getModel().move(elements, containers, siblings, renamings, replace, |
| monitor); |
| } |
| |
| @Override |
| public void rename(String newName, boolean force, IProgressMonitor monitor) |
| throws ModelException { |
| if (newName == null) { |
| throw new IllegalArgumentException(Messages.element_nullName); |
| } |
| IModelElement[] elements = new IModelElement[] { this }; |
| IModelElement[] dests = new IModelElement[] { this.getParent() }; |
| String[] renamings = new String[] { newName }; |
| getModel().rename(elements, dests, renamings, force, monitor); |
| } |
| |
| public IPath getRelativePath() { |
| return this.path; |
| } |
| } |