blob: ddc14c2b79c898864b2901d68fe4e2a3f8a14159 [file] [log] [blame]
/*******************************************************************************
* 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;
}
}