/** * 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.templates; import java.io.File; import java.util.Arrays; import java.util.Comparator; import java.util.Stack; import org.eclipse.core.resources.IContainer; 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.ResourceAttributes; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.jdt.core.IClasspathEntry; import org.eclipse.jdt.core.IJavaElement; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.core.IPackageFragment; import org.eclipse.jdt.core.IPackageFragmentRoot; import org.eclipse.jdt.core.JavaCore; import org.eclipse.jdt.core.JavaModelException; import org.whole.lang.util.CompositeUtils; /** * @author Enrico Persiani */ public class WorkspaceTemplate extends ResourceTemplate { public static class ResourceComparator implements Comparator<IResource> { public int compare(IResource first, IResource second) { boolean isFirstDirectory = first.getType() == IResource.FOLDER; boolean isSecondDirectory = second.getType() == IResource.FOLDER; if (isFirstDirectory && !isSecondDirectory) return 1; else if (!isFirstDirectory && isSecondDirectory) return -1; else return first.getName().compareTo(second.getName()); } } public static class JavaElementComparator implements Comparator<IJavaElement> { public int compare(IJavaElement first, IJavaElement second) { boolean isFirstDirectory = first.getElementType() == IJavaElement.PACKAGE_FRAGMENT; boolean isSecondDirectory = second.getElementType() == IJavaElement.PACKAGE_FRAGMENT; if (isFirstDirectory && !isSecondDirectory) return 1; else if (!isFirstDirectory && isSecondDirectory) return -1; else return first.getElementName().compareTo(second.getElementName()); } } protected IResource rootResource; protected boolean bindReversePath; public WorkspaceTemplate(IResource rootResource) { this(rootResource, true); } public WorkspaceTemplate(IResource rootResource, boolean bindReversePath) { this.rootResource = rootResource; this.bindReversePath = bindReversePath; } private void buildNatures(IProject project) { IJavaProject javaProject = JavaCore.create(project); if (javaProject != null) { getBindings().wDefValue("javaProject", javaProject); ab.Natures_(1); ab.Nature(JavaCore.NATURE_ID); ab._Natures(); } else ab.Natures(); } protected void buildMetadata(String... attributes) { File file = (File) getBindings().wGetValue("file"); if (file.isDirectory() && getBindings().wIsSet("javaProject")) { // check for source folders IJavaProject project = (IJavaProject) getBindings().wGetValue("javaProject"); boolean isSourceFolder = false; try { IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot(); IContainer[] containers = workspaceRoot.findContainersForLocationURI(file.toURI()); if (containers.length == 1) for (IClasspathEntry entry : project.getRawClasspath()) if (entry.getPath().equals(containers[0].getFullPath())) { isSourceFolder = true; break; } } catch (JavaModelException e) { // do nothing } if (isSourceFolder) attributes = CompositeUtils.grow(attributes, attributes.length+1, "source"); } super.buildMetadata(attributes); } protected void buildPackage(IPackageFragment packageFragment) { try { if (!packageFragment.hasChildren() && packageFragment.getNonJavaResources().length == 0) return; } catch (JavaModelException e1) { } getBindings().wEnterScope(); ab.PackageArtifact_(); String directoryName = packageFragment.getElementName(); ab.Name(directoryName); super.buildMetadata(); if (!testAndClearPurge()) { IResource[] artifacts = null; try { artifacts = ((IFolder) packageFragment.getCorrespondingResource()).members(); } catch (CoreException e) { } if (artifacts != null && artifacts.length > 0) { Arrays.sort(artifacts, new ResourceComparator()); ab.Artifacts_(artifacts.length); for (IResource artifact : artifacts) if (artifact.getType() == IResource.FILE) buildArtifact(artifact); ab._Artifacts(); } else ab.Artifacts(); } else ab.Artifacts(); ab._PackageArtifact(); getBindings().wExitScope(); } protected void buildDirectory(IFolder directory) { getBindings().wEnterScope(); ab.FolderArtifact_(); String directoryName = directory.getName(); ab.Name(directoryName); getBindings().wDefValue("file", directory.getLocation().toFile()); getBindings().wDefValue("fileName", directoryName); ResourceAttributes resourceAttributes = directory.getResourceAttributes(); if (resourceAttributes != null && resourceAttributes.isReadOnly()) buildMetadata("readonly"); else buildMetadata(); if (!testAndClearPurge()) { IJavaElement javaElement = JavaCore.create(directory); if (javaElement != null && javaElement.getElementType() == IJavaElement.PACKAGE_FRAGMENT_ROOT) { IJavaElement[] children = null; try { children = ((IPackageFragmentRoot) javaElement).getChildren(); } catch (JavaModelException e) { } if (children != null && children.length > 0) { Arrays.sort(children, new JavaElementComparator()); ab.Artifacts_(children.length); for (IJavaElement artifact : children) buildPackage((IPackageFragment) artifact); ab._Artifacts(); } else ab.Artifacts(); } else { IResource[] artifacts = null; try { artifacts = directory.members(); } catch (CoreException e) { } if (artifacts != null && artifacts.length > 0) { Arrays.sort(artifacts, new ResourceComparator()); ab.Artifacts_(artifacts.length); for (IResource artifact : artifacts) buildArtifact(artifact); ab._Artifacts(); } else ab.Artifacts(); } } else ab.Artifacts(); ab._FolderArtifact(); getBindings().wExitScope(); } protected void buildArtifact(IResource resource) { IJavaElement javaElement = JavaCore.create(resource); if (javaElement != null && javaElement.getElementType() == IJavaElement.PACKAGE_FRAGMENT) buildPackage((IPackageFragment) javaElement); else if (resource.getType() == IResource.FOLDER) { buildDirectory((IFolder) resource); } else buildFile(resource.getLocation().toFile()); } protected void buildProject(IProject project) { if (!project.isAccessible()) return; getBindings().wEnterScope(); ab.Project_(); String projectName = project.getName(); ab.Name(projectName); getBindings().wDefValue("file", project.getLocation().toFile()); getBindings().wDefValue("fileName", projectName); buildNatures(project); if (project.getResourceAttributes().isReadOnly()) buildMetadata("readonly"); else buildMetadata(); try { if(!testAndClearPurge()) { IResource[] members = project.members(); ab.Artifacts_(members.length); for (IResource member : members) buildArtifact(member); ab._Artifacts(); } } catch (CoreException e) { // do nothing } ab._Project(); getBindings().wExitScope(); } protected void buildWorkspace(IResource resource) { ab.Workspace_(); cb.Resolver(); if(!testAndClearPurge()) { IProject[] projects = ((IWorkspaceRoot) resource).getProjects(); ab.Projects_(projects.length); for (IProject project : projects) buildProject(project); ab._Projects(); } ab._Workspace(); } private void buildResourceStack(Stack<IResource> resourceStack) { if (!resourceStack.isEmpty()) { File resourceFile = resourceStack.pop().getLocation().toFile(); if (!resourceStack.isEmpty()) { getBindings().wEnterScope(); ab.FolderArtifact_(); String directoryName = resourceFile.getName(); ab.Name(directoryName); getBindings().wDefValue("file", resourceFile); getBindings().wDefValue("fileName", directoryName); if (!resourceFile.canWrite()) buildMetadata("readonly"); else buildMetadata(); ab.Artifacts_(1); buildResourceStack(resourceStack); ab._Artifacts(); ab._FolderArtifact(); getBindings().wExitScope(); } else buildArtifact(resourceFile); } } private void buildReversePathModel(IResource resource) { ab.Workspace_(); cb.Resolver(); ab.Projects_(1); if (resource.getType() == IResource.PROJECT) buildProject((IProject) resource); else { Stack<IResource> resourceStack = new Stack<IResource>(); while (resource.getType() != IResource.PROJECT) { resourceStack.push(resource); resource = resource.getParent(); } getBindings().wEnterScope(); IProject project = (IProject) resource; ab.Project_(); String projectName = project.getName(); ab.Name(projectName); getBindings().wDefValue("file", project.getLocation().toFile()); getBindings().wDefValue("fileName", projectName); buildNatures(project); if (project.getResourceAttributes().isReadOnly() || !project.isAccessible()) buildMetadata("readonly"); else buildMetadata(); ab.Artifacts_(1); buildResourceStack(resourceStack); ab._Artifacts(); ab._Project(); getBindings().wExitScope(); } ab._Projects(); ab._Workspace(); } protected void buildWorkspaceModel(IResource resource) { if (bindReversePath) buildReversePathModel(resource); else switch(resource.getType()) { case IResource.ROOT: buildWorkspace(resource); break; case IResource.PROJECT: buildProject((IProject) resource); break; case IResource.FOLDER: case IResource.FILE: default: buildArtifact(resource.getLocation().toFile()); break; } } protected void buildArtifactsModel() { testAndClearPurge(); buildWorkspaceModel(rootResource); } }