/**
* Copyright 2004-2016 Riccardo Solmi. All rights reserved.
* This file is part of the Whole Platform.
*
* The Whole Platform is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* The Whole Platform is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with the Whole Platform. If not, see <http://www.gnu.org/licenses/>.
*/
package org.whole.lang.artifacts.util;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.JavaCore;
import org.whole.lang.artifacts.factories.ArtifactsEntityFactory;
import org.whole.lang.artifacts.model.Artifact;
import org.whole.lang.artifacts.model.AttributeEnum;
import org.whole.lang.artifacts.model.Content;
import org.whole.lang.artifacts.model.FileArtifact;
import org.whole.lang.artifacts.model.FileName;
import org.whole.lang.artifacts.model.FolderArtifact;
import org.whole.lang.artifacts.model.Metadata;
import org.whole.lang.artifacts.model.NameWithExtension;
import org.whole.lang.artifacts.model.PackageArtifact;
import org.whole.lang.artifacts.model.PersistenceKitId;
import org.whole.lang.artifacts.model.Project;
import org.whole.lang.artifacts.model.Workspace;
import org.whole.lang.artifacts.reflect.ArtifactsEntityDescriptorEnum;
import org.whole.lang.artifacts.reflect.ArtifactsFeatureDescriptorEnum;
import org.whole.lang.artifacts.visitors.LoadContentsVisitor;
import org.whole.lang.bindings.BindingManagerFactory;
import org.whole.lang.bindings.IBindingManager;
import org.whole.lang.codebase.IFilePersistenceProvider;
import org.whole.lang.codebase.IPersistenceKit;
import org.whole.lang.codebase.IPersistenceProvider;
import org.whole.lang.commons.factories.CommonsEntityAdapterFactory;
import org.whole.lang.commons.factories.CommonsEntityFactory;
import org.whole.lang.commons.model.Resolver;
import org.whole.lang.commons.reflect.CommonsEntityDescriptorEnum;
import org.whole.lang.factories.RegistryConfigurations;
import org.whole.lang.iterators.CollectionIterator;
import org.whole.lang.iterators.IEntityIterator;
import org.whole.lang.iterators.IteratorFactory;
import org.whole.lang.matchers.Matcher;
import org.whole.lang.model.IEntity;
import org.whole.lang.model.NullEntity;
import org.whole.lang.reflect.ILanguageKit;
import org.whole.lang.reflect.ReflectionFactory;
import org.whole.lang.util.EntityUtils;
import org.whole.lang.util.StringUtils;
/**
* @author Riccardo Solmi, Enrico Persiani
*/
public class ArtifactsWorkspaceUtils {
public static boolean existsPath(IEntity artifact) {
return existsPath(artifact, null);
}
public static boolean existsPath(IEntity artifact, IEntity childArtifact) {
try {
IBindingManager bindings = BindingManagerFactory.instance.createBindingManager();
bindPath(artifact, bindings, false);
if (childArtifact != null) {
IFolder parentFolder = (IFolder) bindings.wGetValue("folder");
return parentFolder.exists(parentFolder.getFullPath().append(ArtifactsUtils.getName(childArtifact)));
} else
return true;
} catch (IllegalArgumentException e) {
return false;
}
}
public static void bindPath(IEntity artifact, IBindingManager bindings, boolean force) {
if (!ArtifactsEntityDescriptorEnum.Artifact.isLanguageSupertypeOf(artifact.wGetEntityDescriptor()) &&
!Matcher.match(ArtifactsEntityDescriptorEnum.Workspace, artifact) &&
!Matcher.match(ArtifactsEntityDescriptorEnum.Project, artifact))
throw new IllegalArgumentException("Wrong path ending with: "+artifact.toString());
IEntityIterator<IEntity> pathIterator = new AncestorOrSelfInSameLanguageReverseIterator();
pathIterator.reset(artifact);
if (!pathIterator.hasNext())
throw new IllegalArgumentException("Empty model");
if (CommonsEntityDescriptorEnum.RootFragment.equals(pathIterator.lookahead().wGetEntityDescriptor()))
pathIterator.next();
IEntity rootEntity = pathIterator.next();
if (!Matcher.matchImpl(ArtifactsEntityDescriptorEnum.Workspace, rootEntity))
throw new IllegalArgumentException("Missing Workspace root entity");
bindMetadata(((Workspace) rootEntity).getMetadata(), bindings);
while (pathIterator.hasNext()) {
IEntity pathFragment = pathIterator.next();
if (EntityUtils.isNotResolver(pathFragment) && !EntityUtils.isComposite(pathFragment)) {
switch (pathFragment.wGetEntityOrd()) {
case ArtifactsEntityDescriptorEnum.Project_ord:
bindProject((Project) pathFragment, bindings, force);
break;
case ArtifactsEntityDescriptorEnum.FolderArtifact_ord:
bindFolder((FolderArtifact) pathFragment, bindings, force);
break;
case ArtifactsEntityDescriptorEnum.PackageArtifact_ord:
bindPackage((PackageArtifact) pathFragment, bindings, force);
break;
case ArtifactsEntityDescriptorEnum.FileArtifact_ord:
bindFile((FileArtifact) pathFragment, bindings, force);
break;
default:
throw new IllegalArgumentException("Unsupported entity in path: "+pathFragment.toString());
}
}
}
}
private static void bindProject(Project projectEntity, IBindingManager bindings, boolean force) {
bindings.wEnterScope();
IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
if (!Matcher.matchImplAndBind(ArtifactsEntityDescriptorEnum.Name, projectEntity.getName(), bindings, "projectName"))
throw new IllegalArgumentException("No Project name");
bindMetadata(projectEntity.getMetadata(), bindings);
IProject project = workspaceRoot.getProject(bindings.wStringValue("projectName"));
bindings.wDefValue("project", project);
if (!project.exists()) {
if (!force)
throw new IllegalArgumentException("Missing Project: "+bindings.wStringValue("projectName"));
else {
try {
project.create((IProgressMonitor) bindings.wGetValue("progressMonitor"));
if (project.hasNature(JavaCore.NATURE_ID))
bindings.wDefValue("javaProject", JavaCore.create(project));
} catch (CoreException e) {
throw new IllegalArgumentException("Cannot create Project: "+bindings.wStringValue("projectName"));
}
}
}
bindings.wExitScope(true);
}
private static void bindFolder(FolderArtifact folderEntity, IBindingManager bindings, boolean force) {
bindings.wEnterScope();
if (!Matcher.matchImplAndBind(ArtifactsEntityDescriptorEnum.Name, folderEntity.getName(), bindings, "folderName"))
throw new IllegalArgumentException("No Folder name");
bindMetadata(folderEntity.getMetadata(), bindings);
IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
IFolder folder = workspaceRoot.getFolder(getParentPath(bindings).append(bindings.wStringValue("folderName")));
bindings.wDefValue("folder", folder);
if (!folder.exists()) {
if(!force)
throw new IllegalArgumentException("Missing Folder: "+bindings.wStringValue("folderName"));
else {
try {
folder.create(true, true, (IProgressMonitor) bindings.wGetValue("progressMonitor"));
} catch (Exception e) {
throw new IllegalArgumentException("Cannot create Folder: "+bindings.wStringValue("folderName"));
}
}
}
bindings.wExitScope(true);
}
private static void bindPackage(PackageArtifact packageEntity, IBindingManager bindings, boolean force) {
bindings.wEnterScope();
if (!Matcher.matchImplAndBind(ArtifactsEntityDescriptorEnum.Name, packageEntity.getName(), bindings, "packageName"))
throw new IllegalArgumentException("No Folder name");
bindMetadata(packageEntity.getMetadata(), bindings);
IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
IFolder folder = workspaceRoot.getFolder(getParentPath(bindings).append(StringUtils.packagePath(bindings.wStringValue("packageName"))));
bindings.wDefValue("folder", folder);
if (!folder.exists()) {
if(!force)
throw new IllegalArgumentException("Missing Package: "+bindings.wStringValue("packageName"));
else {
try {
folder.create(true, true, (IProgressMonitor) bindings.wGetValue("progressMonitor"));
} catch (Exception e) {
throw new IllegalArgumentException("Cannot create Package: "+bindings.wStringValue("packageName"));
}
}
}
bindings.wExitScope(true);
}
private static void bindFile(FileArtifact fileEntity, IBindingManager bindings, boolean force) {
bindings.wEnterScope();
if (!Matcher.matchImplAndBind(ArtifactsEntityDescriptorEnum.Name, fileEntity.getName(), bindings, "fileName")) {
NameWithExtension name = (NameWithExtension) fileEntity.getName();
if (!Matcher.matchImplAndBind(ArtifactsEntityDescriptorEnum.Name, name.getName(), bindings, "fileName"))
throw new IllegalArgumentException("No File name");
if (!Matcher.matchImplAndBind(ArtifactsEntityDescriptorEnum.Extension, name.getExtension(), bindings, "extension"))
throw new IllegalArgumentException("No File name");
}
bindMetadata(fileEntity.getMetadata(), bindings);
IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
IFile file = workspaceRoot.getFile(getParentPath(bindings).append(bindings.wIsSet("extension") ?
bindings.wStringValue("fileName")+'.'+bindings.wStringValue("extension") : bindings.wStringValue("fileName")));
bindings.wDefValue("file", file);
if (!file.exists() && !force)
throw new IllegalArgumentException("Missing File: "+bindings.wStringValue("fileName"));
bindings.wExitScope(true);
}
private static void bindMetadata(Metadata metadata, IBindingManager bindings) {
if (!EntityUtils.isImpl(metadata))
return;
PersistenceKitId persistenceKitId = metadata.getPersistenceKitId();
if (EntityUtils.isImpl(persistenceKitId))
bindings.wDef("persistenceKitId", persistenceKitId);
}
public static IPath getParentPath(IBindingManager bindings) {
IPath parentPath;
if (bindings.wIsSet("folder")) {
IFolder parentFolder = (IFolder) bindings.wGetValue("folder");
parentPath = parentFolder.getFullPath();
} else {
IProject project = (IProject) bindings.wGetValue("project");
parentPath = project.getFullPath();
}
return parentPath;
}
public static IEntity toArtifactsPath(IResource fromResource, IResource toResource) {
return toArtifactsPath(fromResource, toResource, NullEntity.instance);
}
public static IEntity toArtifactsPath(IResource fromResource, IResource toResource, IEntity child) {
ArtifactsEntityFactory aef = ArtifactsEntityFactory.instance(RegistryConfigurations.RESOLVER);
IEntity entity;
String name = toResource.getName();
switch (toResource.getType()) {
case IResource.FILE:
FileArtifact fileArtifact = aef.createFileArtifact();
fileArtifact.setName(createFileName(name));
entity = fileArtifact;
break;
case IResource.FOLDER:
FolderArtifact folderArtifact = aef.createFolderArtifact();
folderArtifact.setName(aef.createName(name));
folderArtifact.setArtifacts(aef.createArtifacts(0));
entity = folderArtifact;
break;
case IResource.PROJECT:
Project project = aef.createProject();
project.setName(aef.createName(name));
project.setArtifacts(aef.createArtifacts(0));
entity = project;
break;
default:
case IResource.ROOT:
Workspace workspace = aef.createWorkspace();
workspace.setProjects(aef.createProjects(0));
entity = workspace;
break;
}
boolean isWorkspace = Matcher.match(ArtifactsEntityDescriptorEnum.Workspace, entity);
if (!EntityUtils.isNull(child))
entity.wGet(isWorkspace ? ArtifactsFeatureDescriptorEnum.projects :
ArtifactsFeatureDescriptorEnum.artifacts).wAdd(child);
return fromResource.equals(toResource) ? entity : toArtifactsPath(fromResource, toResource.getParent(), entity);
}
public static IEntity toArtifactsPath(IJavaElement fromJavaElement, IJavaElement toJavaElement) {
return toArtifactsPath(fromJavaElement, toJavaElement, NullEntity.instance);
}
public static IEntity toArtifactsPath(IJavaElement fromJavaElement, IJavaElement toJavaElement, IEntity child) {
ArtifactsEntityFactory aef = ArtifactsEntityFactory.instance(RegistryConfigurations.RESOLVER);
IEntity entity;
String name = toJavaElement.getElementName();
switch (toJavaElement.getElementType()) {
case IJavaElement.COMPILATION_UNIT:
FileArtifact fileArtifact = aef.createFileArtifact();
fileArtifact.setName(createFileName(name));
entity = fileArtifact;
break;
case IJavaElement.PACKAGE_FRAGMENT:
if (name == IPackageFragment.DEFAULT_PACKAGE_NAME)
return fromJavaElement.equals(toJavaElement) ?
child : toArtifactsPath(fromJavaElement, toJavaElement.getParent(), child);
PackageArtifact packageArtifact = aef.createPackageArtifact();
packageArtifact.setName(aef.createName(name));
entity = packageArtifact;
break;
case IJavaElement.PACKAGE_FRAGMENT_ROOT:
FolderArtifact folderArtifact = aef.createFolderArtifact();
Metadata metadata = aef.createMetadata();
metadata.setAttributes(aef.createAttributes(aef.createAttribute(AttributeEnum.source)));
folderArtifact.setMetadata(metadata);
folderArtifact.setName(aef.createName(name));
entity = folderArtifact;
break;
case IJavaElement.JAVA_PROJECT:
Project project = aef.createProject();
project.setName(aef.createName(name));
project.setNatures(aef.createNatures(aef.createNature("org.eclipse.jdt.core.javanature")));
project.setArtifacts(aef.createArtifacts(0));
entity = project;
break;
default:
case IJavaElement.JAVA_MODEL:
Workspace workspace = aef.createWorkspace();
workspace.setProjects(aef.createProjects(0));
entity = workspace;
break;
}
boolean isWorkspace = Matcher.match(ArtifactsEntityDescriptorEnum.Workspace, entity);
if (!EntityUtils.isNull(child))
entity.wGet(isWorkspace ? ArtifactsFeatureDescriptorEnum.projects :
ArtifactsFeatureDescriptorEnum.artifacts).wAdd(child);
return fromJavaElement.equals(toJavaElement) ? entity : toArtifactsPath(fromJavaElement, toJavaElement.getParent(), entity);
}
public static IEntity toArtifactsPath(IJavaElement fromJavaElement, IResource toResource) {
ArtifactsEntityFactory aef = ArtifactsEntityFactory.instance(RegistryConfigurations.RESOLVER);
Artifact child;
if (toResource.getType() == IResource.FILE) {
FileArtifact fileArtifact = aef.createFileArtifact();
fileArtifact.setName(createFileName(toResource.getName()));
child = fileArtifact;
} else {
FolderArtifact folderArtifact = aef.createFolderArtifact();
folderArtifact.setName(aef.createName(toResource.getName()));
child = folderArtifact;
}
return toArtifactsPath(fromJavaElement, JavaCore.create(toResource.getParent()), child);
}
public static IEntity getArtifacts(IEntity artifact) {
ArtifactsEntityFactory aef = ArtifactsEntityFactory.instance(RegistryConfigurations.RESOLVER);
IEntity children = BindingManagerFactory.instance.createTuple();
if (Matcher.match(ArtifactsEntityDescriptorEnum.Workspace, artifact)) {
IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
for (IProject project : workspaceRoot.getProjects()) {
Project projectArtifact = aef.createProject();
projectArtifact.setName(aef.createName(project.getName()));
projectArtifact.setArtifacts(aef.createArtifacts(0));
children.wAdd(projectArtifact);
}
} else {
try {
IBindingManager bindings = BindingManagerFactory.instance.createBindingManager();
bindPath(artifact, bindings, false);
IContainer container = (IContainer) (bindings.wIsSet("folder") ?
bindings.wGetValue("folder") : bindings.wGetValue("project"));
IJavaElement javaContainer = JavaCore.create(container);
if (javaContainer == null || javaContainer.getElementType() == IJavaElement.JAVA_PROJECT) {
for (IResource resource : container.members()) {
if (resource.getType() == IResource.FILE) {
appendFileArtifact(((IFile) resource).getName(), children);
} else {
FolderArtifact folderArtifact = aef.createFolderArtifact();
Metadata metadata = aef.createMetadata();
metadata.setAttributes(aef.createAttributes(aef.createAttribute(AttributeEnum.source)));
folderArtifact.setMetadata(metadata);
folderArtifact.setName(aef.createName(StringUtils.getFileName(resource.getName())));
folderArtifact.setArtifacts(aef.createArtifacts(0));
children.wAdd(folderArtifact);
}
}
} else {
if (javaContainer.getElementType() == IJavaElement.PACKAGE_FRAGMENT_ROOT) {
IPackageFragmentRoot fragmentRoot = (IPackageFragmentRoot) javaContainer;
if (fragmentRoot.getKind() == IPackageFragmentRoot.K_SOURCE) {
for (IJavaElement element : fragmentRoot.getChildren()) {
if (element.getElementType() == IJavaElement.PACKAGE_FRAGMENT) {
if (element.getElementName() == IPackageFragment.DEFAULT_PACKAGE_NAME) {
appendPackageFragmentChildren((IPackageFragment) element, children);
} else {
PackageArtifact packageArtifact = aef.createPackageArtifact();
packageArtifact.setName(aef.createName(StringUtils.getFileName(element.getElementName())));
packageArtifact.setArtifacts(aef.createArtifacts(0));
children.wAdd(packageArtifact);
}
}
}
}
} else // IJavaElement.PACKAGE_FRAGMENT
appendPackageFragmentChildren((IPackageFragment) javaContainer, children);
}
} catch (Exception e) {
}
}
return children;
}
protected static void appendPackageFragmentChildren(IPackageFragment packageFragment, IEntity children) throws Exception {
for (ICompilationUnit cu : packageFragment.getCompilationUnits())
appendFileArtifact(cu.getElementName(), children);
for (Object resource : packageFragment.getNonJavaResources())
if (resource instanceof IFile)
appendFileArtifact(((IFile) resource).getName(), children);
}
protected static void appendFileArtifact(String nameWithExtension, IEntity children) {
ArtifactsEntityFactory aef = ArtifactsEntityFactory.instance(RegistryConfigurations.RESOLVER);
FileArtifact fileArtifact = aef.createFileArtifact();
fileArtifact.setName(createFileName(nameWithExtension));
children.wAdd(fileArtifact);
}
protected static FileName createFileName(String nameWithExtension) {
ArtifactsEntityFactory aef = ArtifactsEntityFactory.instance(RegistryConfigurations.RESOLVER);
String fileName = StringUtils.stripFileExtension(nameWithExtension);
String extension = StringUtils.getFileExtension(nameWithExtension);
if (fileName.length() > 0)
return aef.createNameWithExtension(
aef.createName(fileName),
aef.createExtension(extension));
else
return aef.createName('.'+extension);
}
public static IEntity getPersistenceKits() {
IEntity persistenceKitIds = BindingManagerFactory.instance.createTuple();
for (IPersistenceKit persistenceKit : ReflectionFactory.getPersistenceKits())
persistenceKitIds.wAdd(BindingManagerFactory.instance.createSpecificValue(
ReflectionFactory.getPersistenceKit(persistenceKit.getId())));
return persistenceKitIds;
}
public static IEntity getPersistenceKits(FileArtifact fileArtifact) {
IEntity persistenceKitIds = BindingManagerFactory.instance.createTuple();
IBindingManager bindings = BindingManagerFactory.instance.createBindingManager();
bindPath(fileArtifact, bindings, false);
if (bindings.wIsSet("persistenceKitId")) {
persistenceKitIds.wAdd(
BindingManagerFactory.instance.createSpecificValue(
ReflectionFactory.getPersistenceKit(bindings.wStringValue("persistenceKitId"))));
return persistenceKitIds;
} else
return getPersistenceKits();
}
public static IEntity getContents(FileArtifact fileArtifact, String persistenceKitId) {
IBindingManager bindings = BindingManagerFactory.instance.createBindingManager();
bindPath(fileArtifact, bindings, false);
IFile file = (IFile) bindings.wGetValue("file");
final IPersistenceProvider pp = new IFilePersistenceProvider(file);
final Resolver resolver = CommonsEntityFactory.instance.createResolver();
final Content fragment = CommonsEntityAdapterFactory.createStageUpFragment(
ArtifactsEntityDescriptorEnum.Content, resolver);
try {
fragment.wSet(0, ReflectionFactory.getPersistenceKit(persistenceKitId).readModel(pp));
} catch (Exception e) {
}
return fragment;
}
public static void loadContents(IEntity rootArtifact, IBindingManager bindings) {
try {
if (!Matcher.match(ArtifactsEntityDescriptorEnum.Project, rootArtifact) &&
!Matcher.match(ArtifactsEntityDescriptorEnum.Workspace, rootArtifact))
rootArtifact = (IEntity) rootArtifact.wGetParent().wGetParent();
bindPath(rootArtifact, bindings, false);
} catch(ClassCastException e) {
}
LoadContentsVisitor visitor = new LoadContentsVisitor(bindings);
visitor.visit(rootArtifact);
}
public static class AncestorOrSelfInSameLanguageReverseIterator extends CollectionIterator<IEntity> {
@Override
protected Iterable<?> getCollectionIterable(IEntity entity) {
List<IEntity> ancestors = new ArrayList<IEntity>();
ILanguageKit languageKit = entity.wGetLanguageKit();
IEntityIterator<IEntity> iterator = IteratorFactory.ancestorOrSelfIterator();
iterator.reset(entity);
for (IEntity parent : iterator) {
if (languageKit.equals(parent.wGetLanguageKit()))
ancestors.add(parent);
else
break;
}
Collections.reverse(ancestors);
return ancestors;
}
}
}