msi.gama.gui.swt.WorkspaceModelsManager.java Source code

Java tutorial

Introduction

Here is the source code for msi.gama.gui.swt.WorkspaceModelsManager.java

Source

/*********************************************************************************************
 * 
 * 
 * 'WorkspaceModelsManager.java', in plugin 'msi.gama.application', is part of the source code of the
 * GAMA modeling and simulation platform.
 * (c) 2007-2014 UMI 209 UMMISCO IRD/UPMC & Partners
 * 
 * Visit https://code.google.com/p/gama-platform/ for license information and developers contact.
 * 
 * 
 **********************************************************************************************/
package msi.gama.gui.swt;

import java.io.*;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.util.*;
import java.util.regex.*;
import msi.gama.common.util.GuiUtils;
import org.apache.commons.lang.StringUtils;
import org.eclipse.core.resources.*;
import org.eclipse.core.runtime.*;
import org.eclipse.equinox.internal.app.CommandLineArgs;
import org.eclipse.swt.widgets.*;
import org.eclipse.ui.actions.WorkspaceModifyOperation;
import org.eclipse.ui.internal.ide.application.DelayedEventsProcessor;

/**
 * Class InitialModelOpener.
 * 
 * @author drogoul
 * @since 16 nov. 2013
 * 
 */
public class WorkspaceModelsManager {

    private final static FileFilter noHiddenFiles = new FileFilter() {

        @Override
        public boolean accept(final File arg0) {
            File f = arg0;
            String s = f.getName();
            return !s.startsWith(".");
        }
    };

    public final static WorkspaceModelsManager instance = new WorkspaceModelsManager();
    public static OpenDocumentEventProcessor processor;

    public static void createProcessor(final Display display) {
        processor = new OpenDocumentEventProcessor(display);
    }

    public static class OpenDocumentEventProcessor extends DelayedEventsProcessor {

        private OpenDocumentEventProcessor(final Display display) {
            super(display);
        }

        private final ArrayList<String> filesToOpen = new ArrayList<String>(1);

        @Override
        public void handleEvent(final Event event) {
            if (event.text != null) {
                filesToOpen.add(event.text);
                System.out.println("RECEIVED FILE TO OPEN: " + event.text);
            }
        }

        @Override
        public void catchUp(final Display display) {
            if (filesToOpen.isEmpty()) {
                return;
            }

            String[] filePaths = filesToOpen.toArray(new String[filesToOpen.size()]);
            filesToOpen.clear();

            for (String path : filePaths) {
                instance.openModelPassedAsArgument(path);
            }
        }
    }

    public static QualifiedName BUILTIN_PROPERTY = new QualifiedName("gama.builtin", "models");
    public static String BUILTIN_VERSION = Platform.getProduct().getDefiningBundle().getVersion().toString();
    public final static String builtInNature = "msi.gama.builtin.model";

    public void openModelPassedAsArgument(final String modelPath) {

        // printAllGuaranteedProperties();

        String filePath = modelPath;
        String expName = null;
        if (filePath.contains("#")) {
            String[] segments = filePath.split("#");
            if (segments.length != 2) {
                System.out.println("Wrong definition of model and experiment in argument '" + filePath + "'");
                return;
            }
            filePath = segments[0];
            expName = segments[1];
        }
        IFile file = findAndLoadIFile(filePath);
        if (file != null) {
            try {
                // Force the project to rebuild itself in order to load the various XText plugins.
                file.touch(null);
                file.getProject().build(IncrementalProjectBuilder.FULL_BUILD, null);
            } catch (CoreException e) {
                System.out.println("File " + file.getFullPath() + " cannot be built");
                return;
            }
            if (expName == null) {
                GuiUtils.editModel(file);
            } else {
                GuiUtils.runModel(file, expName);
            }
        }
    }

    /**
     * @param filePath
     * @return
     */
    private IFile findAndLoadIFile(final String filePath) {
        GuiUtils.debug("WorkspaceModelsManager.findAndLoadIFile " + filePath);
        // No error in case of an empty argument
        if (filePath == null || filePath.isEmpty() || StringUtils.isWhitespace(filePath)) {
            return null;
        }
        IPath path = new Path(filePath);
        // 1st case: the path can be identified as a file residing in the workspace
        IFile result = findInWorkspace(path);
        if (result != null) {
            return result;
        }
        // 2nd case: the path is outside the workspace
        result = findOutsideWorkspace(path);
        if (result != null) {
            return result;
        }
        System.out.println("File " + filePath
                + " cannot be located. Please check its name and location. Arguments provided were : "
                + Arrays.toString(CommandLineArgs.getApplicationArgs()));
        return null;
    }

    /**
     * @param filePath
     * @return
     */
    private IFile findInWorkspace(final IPath originalPath) {
        GuiUtils.debug("WorkspaceModelsManager.findInWorkspace  " + originalPath);
        IWorkspace workspace = ResourcesPlugin.getWorkspace();
        IPath workspacePath = new Path(Platform.getInstanceLocation().getURL().getPath());
        IPath filePath = originalPath.makeRelativeTo(workspacePath);
        IFile file = null;
        try {
            file = workspace.getRoot().getFile(filePath);
        } catch (Exception e) {
            return null;
        }
        if (!file.exists()) {
            return null;
        }
        return file;
    }

    private IFile findOutsideWorkspace(final IPath originalPath) {
        GuiUtils.debug("WorkspaceModelsManager.findOutsideWorkspace " + originalPath);
        final File modelFile = new File(originalPath.toOSString());
        // TODO If the file does not exist we return null (might be a good idea to check other locations)
        if (!modelFile.exists()) {
            return null;
        }

        // We try to find a folder containing the model file which can be considered as a project
        File projectFileBean = new File(modelFile.getPath());
        File dotFile = null;
        while (projectFileBean != null && dotFile == null) {
            projectFileBean = projectFileBean.getParentFile();
            if (projectFileBean != null) {
                /* parcours des fils pour trouver le dot file et creer le lien vers le projet */
                File[] children = projectFileBean.listFiles();
                for (int i = 0; i < children.length; i++) {
                    if (children[i].getName().equals(".project")) {
                        dotFile = children[i];
                        break;
                    }
                }
            }
        }

        if (dotFile == null || projectFileBean == null) {
            GuiUtils.tell("The model '" + modelFile.getAbsolutePath()
                    + "' does not seem to belong to an existing GAML project. It will be imported as part of the 'Unclassified models' project.");
            return createUnclassifiedModelsProjectAndAdd(originalPath);
        }

        final IWorkspace workspace = ResourcesPlugin.getWorkspace();
        final IPath location = new Path(dotFile.getAbsolutePath());
        final String pathToProject = projectFileBean.getName();

        try {
            // We load the project description.
            final IProjectDescription description = workspace.loadProjectDescription(location);
            if (description != null) {
                WorkspaceModifyOperation operation = new WorkspaceModifyOperation() {

                    @Override
                    protected void execute(final IProgressMonitor monitor)
                            throws CoreException, InvocationTargetException, InterruptedException {
                        // We try to get the project in the workspace
                        IProject proj = workspace.getRoot().getProject(pathToProject);
                        // If it does not exist, we create it
                        if (!proj.exists()) {
                            // If a project with the same name exists
                            IProject[] projects = workspace.getRoot().getProjects();
                            String name = description.getName();
                            for (IProject p : projects) {
                                if (p.getName().equals(name)) {
                                    GuiUtils.tell(
                                            "A project with the same name already exists in the workspace. The model '"
                                                    + modelFile.getAbsolutePath()
                                                    + " will be imported as part of the 'Unclassified models' project.");
                                    createUnclassifiedModelsProjectAndAdd(originalPath);
                                    return;
                                }
                            }

                            proj.create(description, monitor);
                        } else {
                            // project exists but is not accessible, so we delete it and recreate it
                            if (!proj.isAccessible()) {
                                proj.delete(true, null);
                                proj = workspace.getRoot().getProject(pathToProject);
                                proj.create(description, monitor);
                            }
                        }
                        // We open the project
                        proj.open(IResource.NONE, monitor);
                        // And we set some properties to it
                        setValuesProjectDescription(proj, false);
                    }
                };
                operation.run(new NullProgressMonitor() {

                    // @Override
                    // public void done() {
                    // RefreshHandler.run();
                    // // GuiUtils.tell("Project " + workspace.getRoot().getProject(pathToProject).getName() +
                    // // " has been imported");
                    // }

                });
            }
        } catch (InterruptedException e) {
            return null;
        } catch (InvocationTargetException e) {
            return null;
        } catch (CoreException e) {
            GuiUtils.error("Error wien importing project: " + e.getMessage());
        }
        IProject project = workspace.getRoot().getProject(pathToProject);
        String relativePathToModel = project.getName()
                + modelFile.getAbsolutePath().replace(projectFileBean.getPath(), "");
        return findInWorkspace(new Path(relativePathToModel));
    }

    /**
     *
     */

    public static String UNCLASSIFIED_MODELS = "Unclassified Models";

    private IFile createUnclassifiedModelsProjectAndAdd(final IPath location) {
        IProject project = createOrUpdateProject(UNCLASSIFIED_MODELS);
        IFile iFile = null;
        try {
            IFolder modelFolder = project.getFolder(new Path("models"));
            if (!modelFolder.exists()) {
                modelFolder.create(true, true, null);
            }
            iFile = modelFolder.getFile(location.lastSegment());
            if (iFile.exists()) {
                if (iFile.isLinked()) {
                    IPath path = iFile.getLocation();
                    if (path.equals(location)) {
                        // First case, this is a linked resource to the same location. In that case, we simply return
                        // its name.
                        return iFile;
                    } else {
                        // Second case, this resource is a link to another location. We create a filename that is
                        // guaranteed not to exist and change iFile accordingly.
                        iFile = createUniqueFileFrom(iFile, modelFolder);
                    }
                } else {
                    // Third case, this resource is local and we do not want to overwrite it. We create a filename that
                    // is guaranteed not to exist and change iFile accordingly.
                    iFile = createUniqueFileFrom(iFile, modelFolder);
                }
            }
            iFile.createLink(location, IResource.NONE, null);
            // RefreshHandler.run();
            return iFile;
        } catch (CoreException e) {
            e.printStackTrace();
            GuiUtils.tell("The file " + (iFile == null ? location.lastSegment() : iFile.getFullPath().lastSegment())
                    + " cannot be created because of the following exception " + e.getMessage());
            return null;
        }
    }

    /**
     * @param lastSegment
     * @param modelFolder
     * @return
     */
    private IFile createUniqueFileFrom(final IFile originalFile, final IFolder modelFolder) {
        GuiUtils.debug("WorkspaceModelsManager.createUniqueFileFrom " + originalFile.getLocation() + " in "
                + modelFolder.getFullPath());
        IFile file = originalFile;
        while (file.exists()) {
            IPath path = file.getLocation();
            String fName = path.lastSegment();
            Pattern p = Pattern.compile("(.*?)(\\d+)?(\\..*)?");
            Matcher m = p.matcher(fName);
            if (m.matches()) {// group 1 is the prefix, group 2 is the number, group 3 is the suffix
                fName = m.group(1) + (m.group(2) == null ? 1 : Integer.parseInt(m.group(2)) + 1)
                        + (m.group(3) == null ? "" : m.group(3));
            }
            file = modelFolder.getFile(fName);
        }
        return file;

    }

    public static void linkSampleModelsToWorkspace() {
        final IWorkspace workspace = ResourcesPlugin.getWorkspace();
        URL urlRep = null;
        try {
            urlRep = FileLocator.toFileURL(new URL("platform:/plugin/msi.gama.models/models/"));
        } catch (IOException e) {
            e.printStackTrace();
            return;
        }
        File modelsRep = new File(urlRep.getPath());
        // FileBean gFile = new FileBean(modelsRep);
        File[] projects = modelsRep.listFiles(noHiddenFiles);
        for (final File project : projects) {
            File dotFile = null;
            /* parcours des fils pour trouver le dot file et creer le lien vers le projet */
            File[] children = project.listFiles();
            for (int i = 0; i < children.length; i++) {
                if (children[i].getName().equals(".project")) {
                    dotFile = new File(children[i].getPath());
                    break;
                }
            }
            IProjectDescription tempDescription = null;
            /* If the '.project' doesn't exists we create one */
            if (dotFile == null) {
                /* Initialize file content */
                tempDescription = setProjectDescription(project);
            } else {
                final IPath location = new Path(dotFile.getAbsolutePath());
                try {
                    tempDescription = workspace.loadProjectDescription(location);
                } catch (CoreException e) {
                    e.printStackTrace();
                }
            }
            final IProjectDescription description = tempDescription;

            WorkspaceModifyOperation operation = new WorkspaceModifyOperation() {

                @Override
                protected void execute(final IProgressMonitor monitor)
                        throws CoreException, InvocationTargetException, InterruptedException {
                    IProject proj = workspace.getRoot().getProject(project.getName());
                    if (!proj.exists()) {
                        proj.create(description, monitor);
                    } else {
                        // project exists but is not accessible
                        if (!proj.isAccessible()) {
                            proj.delete(true, null);
                            proj = workspace.getRoot().getProject(project.getName());
                            proj.create(description, monitor);
                        }
                    }
                    proj.open(IResource.NONE, monitor);
                    setValuesProjectDescription(proj, true);
                }
            };
            try {
                operation.run(null);
                stampWorkspaceFromModels();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }

        }
    }

    static private IProject createOrUpdateProject(final String name) {
        final IWorkspace ws = ResourcesPlugin.getWorkspace();
        final IProject[] projectHandle = new IProject[] { null };
        WorkspaceModifyOperation op = new WorkspaceModifyOperation() {

            @Override
            protected void execute(final IProgressMonitor monitor) throws CoreException {
                monitor.beginTask("Creating or updating " + name, 2000);
                IProject project = ws.getRoot().getProject(name);
                // IProjectDescription desc = null;
                if (!project.exists()) {
                    // desc = project.getDescription();
                    // } else {
                    IProjectDescription desc = ws.newProjectDescription(name);
                    project.create(desc, new SubProgressMonitor(monitor, 1000));
                }
                if (monitor.isCanceled()) {
                    throw new OperationCanceledException();
                }
                project.open(IResource.BACKGROUND_REFRESH, new SubProgressMonitor(monitor, 1000));
                projectHandle[0] = project;
                setValuesProjectDescription(project, false);
            }
        };
        try {
            op.run(null);
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return projectHandle[0];
    }

    static public void setValuesProjectDescription(final IProject proj, final boolean builtin) {
        /* Modify the project description */
        IProjectDescription desc = null;
        try {
            desc = proj.getDescription();
            /* Automatically associate GamaNature and Xtext nature to the project */
            // String[] ids = desc.getNatureIds();
            String[] newIds = new String[builtin ? 3 : 2];
            // System.arraycopy(ids, 0, newIds, 0, ids.length);
            newIds[1] = "msi.gama.application.gamaNature";
            newIds[0] = "org.eclipse.xtext.ui.shared.xtextNature";
            // Addition of a special nature to the project.
            if (builtin) {
                newIds[2] = "msi.gama.builtin.model";
            }
            desc.setNatureIds(newIds);
            proj.setDescription(desc, IResource.FORCE, null);
            // Addition of a special persistent property to indicate that the project is built-in
            if (builtin) {
                proj.setPersistentProperty(BUILTIN_PROPERTY, BUILTIN_VERSION);
            }
        } catch (CoreException e) {
            e.printStackTrace();
        }
    }

    static private IProjectDescription setProjectDescription(final File project) {
        final IProjectDescription description = ResourcesPlugin.getWorkspace()
                .newProjectDescription(project.getName());
        final IPath location = new Path(project.getAbsolutePath());
        description.setLocation(location);
        return description;
    }

    public static void stampWorkspaceFromModels() {
        final IWorkspace workspace = ResourcesPlugin.getWorkspace();
        try {
            String stamp = getCurrentGamaStampString();
            IWorkspaceRoot root = workspace.getRoot();
            String oldStamp = root.getPersistentProperty(BUILTIN_PROPERTY);
            if (oldStamp != null) {
                File stampFile = new File(
                        new Path(root.getLocation().toOSString() + File.separator + oldStamp).toOSString());
                if (stampFile.exists()) {
                    stampFile.delete();
                }
            }
            root.setPersistentProperty(BUILTIN_PROPERTY, stamp);
            File stampFile = new File(
                    new Path(root.getLocation().toOSString() + File.separator + stamp).toOSString());
            if (!stampFile.exists()) {
                stampFile.createNewFile();
            }
        } catch (CoreException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static String getCurrentGamaStampString() {
        String gamaStamp = null;
        try {
            URL urlRep = FileLocator.toFileURL(new URL("platform:/plugin/msi.gama.models/models/"));
            File modelsRep = new File(urlRep.getPath());
            long time = modelsRep.lastModified();
            gamaStamp = ".built_in_models_" + time;
            System.out.println("Version of the models in GAMA = " + gamaStamp);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return gamaStamp;
    }

    public static void printAllGuaranteedProperties() {
        System.out.println("Arguments received by GAMA: " + Arrays.toString(Platform.getApplicationArgs()));
        System.out.println("Platform.instanceLocation: " + Platform.getInstanceLocation().getURL());
        System.out.println("Platform.configurationLocation: " + Platform.getConfigurationLocation().getURL());

        System.out.println("Platform.installLocation: " + Platform.getInstallLocation().getURL());

        System.out.println("Platform.location: " + Platform.getLocation());
        System.out.println("Location of '.'" + new File(".").getAbsolutePath());
        printAProperty("java.version", "Java version number");
        printAProperty("java.vendor", "Java vendor specific string");
        printAProperty("java.vendor.url", "Java vendor URL");
        printAProperty("java.home", "Java installation directory");
        printAProperty("java.class.version", "Java class version number");
        printAProperty("java.class.path", "Java classpath");
        printAProperty("os.name", "Operating System Name");
        printAProperty("os.arch", "Operating System Architecture");
        printAProperty("os.version", "Operating System Version");
        printAProperty("file.separator", "File separator");
        printAProperty("path.separator", "Path separator");
        printAProperty("line.separator", "Line separator");
        printAProperty("user.name", "User account name");
        printAProperty("user.home", "User home directory");
        printAProperty("user.dir", "User's current working directory");
    }

    public static void printAProperty(final String propName, final String desc) {
        System.out.println(desc + " = " + System.getProperty(propName) + ".");
    }

}