org.eclipse.titan.designer.wizards.projectFormat.TpdImporter.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.titan.designer.wizards.projectFormat.TpdImporter.java

Source

/******************************************************************************
 * Copyright (c) 2000-2016 Ericsson Telecom AB
 * 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.titan.designer.wizards.projectFormat;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.xml.XMLConstants;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.Validator;

import org.eclipse.core.filesystem.URIUtil;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IPathVariableManager;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IProjectDescription;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.IWorkspaceDescription;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.resources.WorkspaceJob;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.QualifiedName;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubMonitor;
import org.eclipse.jface.dialogs.ProgressMonitorDialog;
import org.eclipse.jface.preference.PreferenceDialog;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.titan.common.logging.ErrorReporter;
import org.eclipse.titan.common.path.TITANPathUtilities;
import org.eclipse.titan.common.path.TitanURIUtil;
import org.eclipse.titan.common.utils.IOUtils;
import org.eclipse.titan.designer.Activator;
import org.eclipse.titan.designer.GeneralConstants;
import org.eclipse.titan.designer.consoles.TITANDebugConsole;
import org.eclipse.titan.designer.core.TITANNature;
import org.eclipse.titan.designer.graphics.ImageCache;
import org.eclipse.titan.designer.productUtilities.ProductConstants;
import org.eclipse.titan.designer.properties.data.DOMErrorHandlerImpl;
import org.eclipse.titan.designer.properties.data.ProjectBuildPropertyData;
import org.eclipse.titan.designer.properties.data.ProjectDocumentHandlingUtility;
import org.eclipse.titan.designer.properties.data.ProjectFileHandler;
import org.eclipse.ui.actions.WorkspaceModifyOperation;
import org.eclipse.ui.dialogs.PreferencesUtil;
import org.eclipse.ui.progress.IProgressConstants;
import org.osgi.framework.Bundle;
import org.w3c.dom.DOMConfiguration;
import org.w3c.dom.DOMImplementation;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.bootstrap.DOMImplementationRegistry;
import org.w3c.dom.ls.DOMImplementationLS;
import org.w3c.dom.ls.LSInput;
import org.w3c.dom.ls.LSParser;
import org.xml.sax.SAXException;

/**
 * This class should be the importation of modules described in a provided Tpd
 * file.
 * 
 * @author Kristof Szabados
 * */
public class TpdImporter {
    private static final String CREATING_PROJECT = "creating project";
    private static final String CREATION_FAILED = "Project creation failed";
    private static final String TPD_XSD = "schema/TPD.xsd";

    private DOMImplementationLS domImplLS;
    private LSParser parser;
    private DOMConfiguration config;

    private Map<String, String> finalProjectNames = new HashMap<String, String>();
    private Map<URI, Document> projectsToImport = new HashMap<URI, Document>();
    private List<URI> importChain = new ArrayList<URI>();
    private boolean wasAutoBuilding;
    private Shell shell;
    private final boolean headless;
    private List<String> searchPaths;
    private Map<String, String> tpdNameAttrMap = new HashMap<String, String>();
    private Map<String, String> tpdURIMap = new HashMap<String, String>();

    public TpdImporter(final Shell shell, final boolean headless) {
        this.shell = shell;
        this.headless = headless;
        IWorkspaceDescription description = ResourcesPlugin.getWorkspace().getDescription();
        wasAutoBuilding = description.isAutoBuilding();
        description.setAutoBuilding(false);
        try {
            ResourcesPlugin.getWorkspace().setDescription(description);
        } catch (CoreException e) {
            ErrorReporter.logExceptionStackTrace("while disabling autobuild on the workspace", e);
        }
        Activator.getDefault().pauseHandlingResourceChanges();
    }

    /**
     * Internal function used to do the import job. It is needed to extract this
     * functionality in order to be able to handle erroneous situations.
     *
     * @param projectFile
     *            the file path string of the project descriptor file (tpd)
     * @param projectsCreated
     *            the list of projects created so far. In case of problems we
     *            will try to delete them.
     * @param monitor
     *            the monitor used to report progress.
     *
     * @return true if the import was successful, false otherwise.
     * */
    public boolean internalFinish(final String projectFile, final boolean isSkipExistingProjects,
            final boolean isOpenPropertiesForAllImports, final List<IProject> projectsCreated,
            final IProgressMonitor monitor, final List<String> searchPaths) {
        if (projectFile == null || "".equals(projectFile.trim())) {
            return false;
        }
        if (searchPaths != null) {
            this.searchPaths = new ArrayList<String>(searchPaths);
        }
        System.setProperty(DOMImplementationRegistry.PROPERTY, ProjectFormatConstants.DOM_IMPLEMENTATION_SOURCE);
        DOMImplementationRegistry registry = null;
        try {
            registry = DOMImplementationRegistry.newInstance();
        } catch (Exception e) {
            ErrorReporter.logExceptionStackTrace("While importing from `" + projectFile + "'", e);
            activatePreviousSettings();
            return false;
        }

        // Specifying "LS 3.0" in the features list ensures that the
        // DOMImplementation
        // object implements the load and save features of the DOM 3.0
        // specification.
        final DOMImplementation domImpl = registry.getDOMImplementation(ProjectFormatConstants.LOAD_SAVE_VERSION);
        domImplLS = (DOMImplementationLS) domImpl;
        // If the mode is MODE_SYNCHRONOUS, the parse and parseURI
        // methods of the LSParser
        // object return the org.w3c.dom.Document object. If the mode is
        // MODE_ASYNCHRONOUS, the parse and parseURI methods return null.
        parser = domImplLS.createLSParser(DOMImplementationLS.MODE_SYNCHRONOUS, ProjectFormatConstants.XML_SCHEMA);

        config = parser.getDomConfig();
        DOMErrorHandlerImpl errorHandler = new DOMErrorHandlerImpl();
        config.setParameter("error-handler", errorHandler);
        config.setParameter("validate", Boolean.TRUE);
        config.setParameter("schema-type", ProjectFormatConstants.XML_SCHEMA);
        config.setParameter("well-formed", Boolean.TRUE);
        config.setParameter("validate-if-schema", Boolean.TRUE);

        Validator tpdValidator = null;
        try {
            final Schema tpdXsd = getTPDSchema();
            tpdValidator = tpdXsd.newValidator();
        } catch (Exception e) {
            ErrorReporter.INTERNAL_ERROR(e.getMessage());
            // Hint: cp $TTCN3_DIR/etc/xsd/TPD.xsd designer/schema/
        }

        URI resolvedProjectFileURI = TITANPathUtilities.resolvePath(projectFile, (URI) null);
        //====================================
        // Loading all URI Documents (tpds) 
        // and collect projects to be imported
        //====================================
        if (!loadURIDocuments(resolvedProjectFileURI, tpdValidator)) {
            return false;
        }

        final SubMonitor progress = SubMonitor.convert(monitor, 3);
        progress.setTaskName("Loading data");

        IProgressMonitor projectCreationMonitor = progress.newChild(1);
        projectCreationMonitor.beginTask("Creating required projects", projectsToImport.size());
        //========================
        // Create projects and 
        // store load location 
        // (where they are loaded from)
        //========================
        Map<URI, IProject> projectMap = new HashMap<URI, IProject>();
        for (URI file : projectsToImport.keySet()) {
            Document actualDocument = projectsToImport.get(file);

            IProject project = createProject(actualDocument.getDocumentElement(),
                    file.equals(resolvedProjectFileURI) || !isSkipExistingProjects);
            if (project == null) {
                projectCreationMonitor.worked(1);
                continue;
            }
            projectsCreated.add(project);
            projectMap.put(file, project);
            try {
                project.setPersistentProperty(new QualifiedName(ProjectBuildPropertyData.QUALIFIER,
                        ProjectBuildPropertyData.LOAD_LOCATION), file.getPath().toString());
            } catch (CoreException e) {
                ErrorReporter.logExceptionStackTrace(
                        "While loading referenced project from `" + file.getPath() + "'", e);
            }
            projectCreationMonitor.worked(1);
        }
        projectCreationMonitor.done();

        IProgressMonitor normalInformationLoadingMonitor = progress.newChild(1);
        normalInformationLoadingMonitor.beginTask("Loading directly stored project information",
                projectsToImport.size());

        //====================================
        //Load Project Data from all projects:
        //====================================
        for (URI file : projectsToImport.keySet()) {
            if (!projectMap.containsKey(file)) {
                normalInformationLoadingMonitor.worked(1);
                continue;
            }

            IProject project = projectMap.get(file);
            IPath projectFileFolderPath = new Path(file.getPath()).removeLastSegments(1);
            URI projectFileFolderURI = URIUtil.toURI(projectFileFolderPath);
            Document actualDocument = projectsToImport.get(file);

            if (this.searchPaths != null && !this.searchPaths.isEmpty()) {
                String tpdNameAttrVal = tpdNameAttrMap.get(project.getName());
                String tpdURIVal = tpdURIMap.get(project.getName());
                if (tpdNameAttrVal != null) {
                    try {
                        project.setPersistentProperty(new QualifiedName(ProjectBuildPropertyData.QUALIFIER,
                                ProjectBuildPropertyData.USE_TPD_NAME), tpdNameAttrVal);
                    } catch (CoreException e) {
                        ErrorReporter.logExceptionStackTrace(
                                "While setting `useTpdName' for project `" + project.getName() + "'", e);
                    }
                }
                if (tpdURIVal != null) {
                    try {
                        project.setPersistentProperty(new QualifiedName(ProjectBuildPropertyData.QUALIFIER,
                                ProjectBuildPropertyData.ORIG_TPD_URI), tpdURIVal);
                    } catch (CoreException e) {
                        ErrorReporter.logExceptionStackTrace(
                                "While setting `origTpdURI' for project `" + project.getName() + "'", e);
                    }
                }
            }

            Element mainElement = actualDocument.getDocumentElement();
            if (!loadProjectDataFromNode(mainElement, project, projectFileFolderURI)) {
                return false;
            }

            normalInformationLoadingMonitor.worked(1);
        }
        normalInformationLoadingMonitor.done();
        //=====================================
        //Load information from packed projects
        //=====================================
        IPath mainProjectFileFolderPath = new Path(resolvedProjectFileURI.getPath()).removeLastSegments(1);
        URI mainProjectFileFolderURI = URIUtil.toURI(mainProjectFileFolderPath);

        List<Node> packedProjects = loadPackedProjects(projectsToImport.get(resolvedProjectFileURI));
        IProgressMonitor packedInformationLoadingMonitor = progress.newChild(1);
        packedInformationLoadingMonitor.beginTask("Loading packed project information", packedProjects.size());
        for (Node node : packedProjects) {
            IProject project = createProject(node, false);
            if (project == null) {
                packedInformationLoadingMonitor.worked(1);
                continue;
            }
            projectsCreated.add(project);

            try {
                project.setPersistentProperty(new QualifiedName(ProjectBuildPropertyData.QUALIFIER,
                        ProjectBuildPropertyData.LOAD_LOCATION), resolvedProjectFileURI.toString());
            } catch (CoreException e) {
                ErrorReporter.logExceptionStackTrace("While loading packed project `" + project.getName() + "'", e);
            }

            if (!loadProjectDataFromNode(node, project, mainProjectFileFolderURI)) {
                return false;
            }

            packedInformationLoadingMonitor.worked(1);
        }
        packedInformationLoadingMonitor.done();

        IProject mainProject = projectMap.get(resolvedProjectFileURI);
        if (mainProject == null) {
            progress.done();
            return false;
        }
        try {
            mainProject.setPersistentProperty(
                    new QualifiedName(ProjectBuildPropertyData.QUALIFIER, ProjectBuildPropertyData.USE_TPD_NAME),
                    mainProject.getName() + ".tpd");
        } catch (CoreException e) {
            ErrorReporter.logExceptionStackTrace(
                    "While setting `useTpdName' for project `" + mainProject.getName() + "'", e);
        }
        List<WorkspaceJob> jobs = new ArrayList<WorkspaceJob>();
        List<IProject> projectsToBeConfigured;
        if (isOpenPropertiesForAllImports) {
            projectsToBeConfigured = projectsCreated;
        } else {
            projectsToBeConfigured = new ArrayList<IProject>();
            projectsToBeConfigured.add(mainProject);
        }

        if (!headless) {
            for (final IProject project : projectsToBeConfigured) {
                WorkspaceJob loadJob = new WorkspaceJob("Property initilizer for " + project.getName()) {
                    @Override
                    public IStatus runInWorkspace(final IProgressMonitor monitor) {
                        Display.getDefault().asyncExec(new Runnable() {
                            @Override
                            public void run() {
                                PreferenceDialog dialog = PreferencesUtil.createPropertyDialogOn(null, project,
                                        GeneralConstants.PROJECT_PROPERTY_PAGE, null, null);
                                if (dialog != null) {
                                    dialog.open();
                                }
                            }
                        });
                        return Status.OK_STATUS;
                    }
                };
                loadJob.setUser(false);
                loadJob.setSystem(true);
                loadJob.setRule(project.getWorkspace().getRuleFactory().refreshRule(project));
                loadJob.setProperty(IProgressConstants.ICON_PROPERTY, ImageCache.getImageDescriptor("titan.gif"));
                loadJob.schedule();
                jobs.add(loadJob);
            }

            for (WorkspaceJob job : jobs) {
                try {
                    job.join();
                } catch (InterruptedException e) {
                    ErrorReporter.logExceptionStackTrace("Interrupted while performing: " + job.getName(), e);
                }
            }
        }

        activatePreviousSettings();

        progress.done();
        return true;
    }

    public static void validateTpd(final File tpdFile) throws IOException, SAXException {
        final Schema tpdXsd = getTPDSchema();
        Validator validator = tpdXsd.newValidator();
        validator.validate(new StreamSource(tpdFile));
    }

    public static Schema getTPDSchema() throws IOException, SAXException {
        Bundle bundle = Platform.getBundle(ProductConstants.PRODUCT_ID_DESIGNER);
        InputStream xsdInputStream = null;
        try {
            xsdInputStream = FileLocator.openStream(bundle, new Path(TPD_XSD), false);
            SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
            Schema result = factory.newSchema(new StreamSource(xsdInputStream));
            xsdInputStream.close();
            return result;
        } finally {
            IOUtils.closeQuietly(xsdInputStream);
        }
    }

    private void activatePreviousSettings() {
        IWorkspaceDescription description = ResourcesPlugin.getWorkspace().getDescription();
        if (description.isAutoBuilding() != wasAutoBuilding) {
            description.setAutoBuilding(wasAutoBuilding);
            try {
                ResourcesPlugin.getWorkspace().setDescription(description);
            } catch (CoreException e) {
                ErrorReporter.logExceptionStackTrace("Resetting autobuild settings to" + wasAutoBuilding, e);
            }
        }
        Activator.getDefault().resumeHandlingResourceChanges();
    }

    /**
     * Collects the list of packed projects from the provided document.
     *
     * @param document
     *            the document to check.
     *
     * @return the list of found packed projects, an empty list if none.
     * */
    private List<Node> loadPackedProjects(final Document document) {
        NodeList referencedProjectsList = document.getDocumentElement().getChildNodes();
        Node packed = ProjectFileHandler.getNodebyName(referencedProjectsList,
                ProjectFormatConstants.PACKED_REFERENCED_PROJECTS_NODE);
        if (packed == null) {
            return new ArrayList<Node>();
        }

        List<Node> result = new ArrayList<Node>();
        NodeList projects = packed.getChildNodes();
        for (int i = 0, size = projects.getLength(); i < size; i++) {
            Node referencedProjectNode = projects.item(i);
            if (ProjectFormatConstants.PACKED_REFERENCED_PROJECT_NODE.equals(referencedProjectNode.getNodeName())) {
                result.add(referencedProjectNode);
            }
        }

        return result;
    }

    /**
     * Loads the project data from the provided node onto the provided project.
     *
     * @param mainElement
     *            the node to load the data from.
     * @param project
     *            the project to set the loaded data on.
     * @param projectFileFolderURI
     *            the URI of the folder to calculate all paths relative to.
     *
     * @return true if the import was successful, false otherwise.
     * */
    private boolean loadProjectDataFromNode(final Node mainElement, final IProject project,
            final URI projectFileFolderURI) {
        NodeList mainNodes = mainElement.getChildNodes();

        Node referencedProjectsNode = ProjectFileHandler.getNodebyName(mainNodes,
                ProjectFormatConstants.REFERENCED_PROJECTS_NODE);
        if (referencedProjectsNode != null) {
            if (!loadReferencedProjectsData(referencedProjectsNode, project)) {
                return false;
            }
        }

        Node pathVariablesNode = ProjectFileHandler.getNodebyName(mainNodes, ProjectFormatConstants.PATH_VARIABLES);
        if (pathVariablesNode != null) {
            if (!loadPathVariables(pathVariablesNode, project.getName())) {
                return false;
            }
        }

        Node foldersNode = ProjectFileHandler.getNodebyName(mainNodes, ProjectFormatConstants.FOLDERS_NODE);
        if (foldersNode != null) {
            if (!loadFoldersData(foldersNode, project, projectFileFolderURI)) {
                return false;
            }
        }

        Node filesNode = ProjectFileHandler.getNodebyName(mainNodes, ProjectFormatConstants.FILES_NODE);
        if (filesNode != null) {
            if (!loadFilesData(filesNode, project, projectFileFolderURI)) {
                return false;
            }
        }

        ProjectDocumentHandlingUtility.createDocument(project);

        if (!loadConfigurationData(project, mainNodes)) {
            return false;
        }

        return true;
    }

    /**
     * Load the data related to project references.
     *
     * @param referencedProjectsNode
     *            the node containing information on referenced projects.
     * @param project
     *            the project to set the data on.
     *
     * @return true if the import was successful, false otherwise.
     * */
    private boolean loadReferencedProjectsData(final Node referencedProjectsNode, final IProject project) {
        NodeList referencedProjectsList = referencedProjectsNode.getChildNodes();
        List<IProject> referencedProjects = new ArrayList<IProject>();
        for (int i = 0, size = referencedProjectsList.getLength(); i < size; i++) {
            Node referencedProjectNode = referencedProjectsList.item(i);
            if (referencedProjectNode.getNodeType() != Node.ELEMENT_NODE) {
                continue;
            }
            NamedNodeMap attributeMap = referencedProjectNode.getAttributes();
            if (attributeMap == null) {
                continue;
            }
            Node nameNode = attributeMap.getNamedItem(ProjectFormatConstants.REFERENCED_PROJECT_NAME_ATTRIBUTE);
            if (nameNode == null) {
                displayError("Import failed", "Error while importing project " + project.getName()
                        + " the name attribute of the " + i + " th referenced project is missing");
                return false;
            }

            String projectName = nameNode.getTextContent();

            String realProjectName = finalProjectNames.get(projectName);
            if (realProjectName != null && realProjectName.length() > 0) {
                IProject tempProject = ResourcesPlugin.getWorkspace().getRoot().getProject(realProjectName);
                referencedProjects.add(tempProject);
            } else {
                //already existing projects:
                IProject tempProject = ResourcesPlugin.getWorkspace().getRoot().getProject(projectName);
                referencedProjects.add(tempProject);
            }
        }
        try {
            IProjectDescription description = project.getDescription();
            description.setReferencedProjects(referencedProjects.toArray(new IProject[referencedProjects.size()]));
            project.setDescription(description, null);
        } catch (CoreException e) {
            ErrorReporter.logExceptionStackTrace("While setting project references for `" + project.getName() + "'",
                    e);
            return false;
        }

        return true;
    }

    /**
     * Load the information describing folders.
     *
     * @param foldersNode
     *            the node to load from.
     * @param project
     *            the project to set this information on.
     * @param projectFileFolderURI
     *            the location of the project file's folder.
     *
     * @return true if the import was successful, false otherwise.
     * */
    private boolean loadFoldersData(final Node foldersNode, final IProject project,
            final URI projectFileFolderURI) {
        final URI projectLocationURI = project.getLocationURI();
        NodeList folderNodeList = foldersNode.getChildNodes();

        for (int i = 0, size = folderNodeList.getLength(); i < size; i++) {
            Node folderItem = folderNodeList.item(i);
            if (folderItem.getNodeType() != Node.ELEMENT_NODE) {
                continue;
            }
            NamedNodeMap attributeMap = folderItem.getAttributes();
            if (attributeMap == null) {
                continue;
            }
            Node projectRelativePathNode = attributeMap
                    .getNamedItem(ProjectFormatConstants.FOLDER_ECLIPSE_LOCATION_NODE);
            if (projectRelativePathNode == null) {
                displayError("Import failed", "Error while importing project " + project.getName()
                        + " the project relative path attribute of the " + i + " th folder is missing");
                return false;
            }

            String projectRelativePath = projectRelativePathNode.getTextContent();

            Node relativeURINode = attributeMap.getNamedItem(ProjectFormatConstants.FOLDER_RELATIVE_LOCATION);
            Node rawURINode = attributeMap.getNamedItem(ProjectFormatConstants.FOLDER_RAW_LOCATION);

            IFolder folder = project.getFolder(projectRelativePath);
            if (!folder.exists()) {
                try {
                    if (relativeURINode != null) {
                        String relativeLocation = relativeURINode.getTextContent();
                        URI absoluteURI = TITANPathUtilities.resolvePathURI(relativeLocation,
                                URIUtil.toPath(projectFileFolderURI).toOSString());
                        if (absoluteURI == null) {
                            // The URI cannot be resolved - for example it
                            // contains not existing environment variables
                            continue;
                        }
                        if (TitanURIUtil.isPrefix(projectLocationURI, absoluteURI)) {
                            folder.create(false, true, null);
                        } else {
                            File tmpFolder = new File(absoluteURI);
                            if (tmpFolder.exists()) {
                                folder.createLink(absoluteURI, IResource.ALLOW_MISSING_LOCAL, null);
                            } else {
                                ErrorReporter.logError("Error while importing folders into project `"
                                        + project.getName() + "'. Folder `" + absoluteURI + "' does not exist");
                                continue;
                            }
                        }
                    } else if (rawURINode != null) {
                        String rawLocation = rawURINode.getTextContent();
                        folder.createLink(URI.create(rawLocation), IResource.ALLOW_MISSING_LOCAL, null);
                    } else {
                        TITANDebugConsole.getConsole().newMessageStream()
                                .println("Cannot create the resource " + folder.getFullPath().toString()
                                        + " the location information is missing or corrupted");
                    }
                } catch (CoreException e) {
                    //be silent, it can happen normally
                }
            } else {
                ErrorReporter.logWarning("Folder to be imported `" + folder.getName()
                        + "' already exists in project `" + project.getName() + "'");
            }
        }
        return true;
    }

    /**
     * Load the information describing files.
     *
     * @param filesNode
     *            the node to load from.
     * @param project
     *            the project to set this information on.
     * @param projectFileFolderURI
     *            the location of the project file's folder.
     *
     * @return true if the import was successful, false otherwise.
     * */
    private boolean loadFilesData(final Node filesNode, final IProject project, final URI projectFileFolderURI) {
        NodeList fileNodeList = filesNode.getChildNodes();
        for (int i = 0, size = fileNodeList.getLength(); i < size; i++) {
            Node fileItem = fileNodeList.item(i);
            if (fileItem.getNodeType() != Node.ELEMENT_NODE) {
                continue;
            }
            NamedNodeMap attributeMap = fileItem.getAttributes();
            if (attributeMap == null) {
                // there is no attribute, check next node
                continue;
            }
            Node projectRelativePathNode = attributeMap
                    .getNamedItem(ProjectFormatConstants.FILE_ECLIPSE_LOCATION_NODE);
            if (projectRelativePathNode == null) {
                displayError("Import failed", "Error while importing project " + project.getName()
                        + " some attributes of the " + i + " th file are missing");
                continue;
            }

            String projectRelativePath = projectRelativePathNode.getTextContent();

            Node relativeURINode = attributeMap.getNamedItem(ProjectFormatConstants.FILE_RELATIVE_LOCATION);
            Node rawURINode = attributeMap.getNamedItem(ProjectFormatConstants.FILE_RAW_LOCATION);

            IFile targetFile = project.getFile(projectRelativePath);
            if (!targetFile.exists()) {
                try {
                    if (relativeURINode != null) {
                        String relativeLocation = relativeURINode.getTextContent();
                        //perhaps the next few lines should be implemented as in the function loadFoldersData()
                        URI absoluteURI = TITANPathUtilities.resolvePathURI(relativeLocation,
                                URIUtil.toPath(projectFileFolderURI).toOSString());
                        if (absoluteURI == null) {
                            continue;
                        }
                        File file = new File(absoluteURI);
                        if (file.exists()) {
                            targetFile.createLink(absoluteURI, IResource.ALLOW_MISSING_LOCAL, null);
                        } else {
                            ErrorReporter.logError("Error while importing files into project `" + project.getName()
                                    + "'. File `" + absoluteURI + "' does not exist");
                            continue;
                        }
                    } else if (rawURINode != null) {
                        String rawURI = rawURINode.getTextContent();
                        targetFile.createLink(URI.create(rawURI), IResource.ALLOW_MISSING_LOCAL, null);
                    } else {
                        TITANDebugConsole.getConsole().newMessageStream()
                                .println("Can not create the resource " + targetFile.getFullPath().toString()
                                        + " the location information is missing or corrupted");
                        continue;
                    }
                } catch (CoreException e) {
                    ErrorReporter.logExceptionStackTrace("While creating link for `" + targetFile + "'", e);
                    return false;
                }
            }
        }

        return true;
    }

    /**
     * Load the information on path variables.
     *
     * @param rootNode
     *            the node to load from.
     * @param projectName
     *            the name of the project to be used on the user interface.
     *
     * @return true if the import was successful, false otherwise.
     * */
    private boolean loadPathVariables(final Node rootNode, final String projectName) {
        final IPathVariableManager pathVariableManager = ResourcesPlugin.getWorkspace().getPathVariableManager();

        NodeList variableNodes = rootNode.getChildNodes();
        for (int i = 0, size = variableNodes.getLength(); i < size; i++) {
            Node variable = variableNodes.item(i);
            if (variable.getNodeType() != Node.ELEMENT_NODE) {
                continue;
            }
            NamedNodeMap attributeMap = variable.getAttributes();
            if (attributeMap == null) {
                continue;
            }

            Node nameNode = attributeMap.getNamedItem("name");
            Node valueNode = attributeMap.getNamedItem("value");

            if (nameNode == null || valueNode == null) {
                displayError("Import failed", "Error while importing project " + projectName
                        + " some attributes of a path variable are missing");
                return false;
            }

            final String variableName = nameNode.getTextContent();
            final String variableValue = valueNode.getTextContent();

            if (headless || shell == null) {
                try {
                    pathVariableManager.setURIValue(variableName, URIUtil.toURI(variableValue));
                } catch (CoreException e) {
                    ErrorReporter.logExceptionStackTrace(
                            "While setting path variable `" + variableName + "' in headless mode", e);
                }
            } else {
                Display.getDefault().syncExec(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            if (pathVariableManager.isDefined(variableName)) {
                                URI uri = pathVariableManager.getURIValue(variableName);
                                if (!variableValue.equals(URIUtil.toPath(uri).toString())) {
                                    EditPathVariableDialog dialog = new EditPathVariableDialog(shell, variableName,
                                            uri, URIUtil.toURI(variableValue));
                                    if (Window.OK == dialog.open()) {
                                        URI actualValue = dialog.getActualValue();
                                        pathVariableManager.setURIValue(variableName, actualValue);
                                    }
                                }
                            } else {
                                NewPathVariableDialog dialog = new NewPathVariableDialog(shell, variableName,
                                        URIUtil.toURI(variableValue));
                                if (Window.OK == dialog.open()) {
                                    URI actualValue = dialog.getActualValue();
                                    pathVariableManager.setURIValue(variableName, actualValue);
                                }
                            }
                        } catch (CoreException e) {
                            ErrorReporter.logExceptionStackTrace(
                                    "While setting path variable `" + variableName + "' in GUI mode", e);
                        }
                    }
                });
            }
        }

        return true;
    }

    /**
     * Loads the configuration related options onto the project from the
     * document being loaded.
     *
     * @param project
     *            the project to load onto.
     * @param mainNodes
     *            the mainNodes to check for the configuration related options.
     *
     * @return true if the import was successful, false otherwise.
     * */
    private boolean loadConfigurationData(final IProject project, final NodeList mainNodes) {
        final Document targetDocument = ProjectDocumentHandlingUtility.getDocument(project);
        Node activeConfigurationNode = ProjectFileHandler.getNodebyName(mainNodes,
                ProjectFormatConstants.ACTIVE_CONFIGURATION_NODE);
        String activeConfiguration = ProjectFormatConstants.DEFAULT_CONFIGURATION_NAME;
        if (activeConfigurationNode != null) {
            activeConfiguration = activeConfigurationNode.getTextContent();
        } else {
            activeConfiguration = "Default";
        }
        try {
            project.setPersistentProperty(new QualifiedName(ProjectBuildPropertyData.QUALIFIER,
                    ProjectBuildPropertyData.ACTIVECONFIGURATION), activeConfiguration);
        } catch (CoreException e) {
            ErrorReporter.logExceptionStackTrace("While setting `" + activeConfiguration
                    + "' as configuration for project `" + project.getName() + "'", e);
        }

        // Remove possible target configuration nodes in existence
        removeConfigurationNodes(targetDocument.getDocumentElement());

        Node targetActiveConfiguration = targetDocument
                .createElement(ProjectFormatConstants.ACTIVE_CONFIGURATION_NODE);
        targetActiveConfiguration.appendChild(targetDocument.createTextNode(activeConfiguration));
        targetDocument.getDocumentElement().appendChild(targetActiveConfiguration);

        Node targetConfigurationsRoot = targetDocument.createElement(ProjectFormatConstants.CONFIGURATIONS_NODE);
        targetDocument.getDocumentElement().appendChild(targetConfigurationsRoot);

        Node configurationsNode = ProjectFileHandler.getNodebyName(mainNodes,
                ProjectFormatConstants.CONFIGURATIONS_NODE);
        if (configurationsNode == null) {
            ProjectDocumentHandlingUtility.saveDocument(project);
            ProjectBuildPropertyData.setProjectAlreadyExported(project, false);
            ProjectFileHandler handler = new ProjectFileHandler(project);
            handler.loadProjectSettingsFromDocument(targetDocument);

            return true;
        }

        NodeList configurationsNodeList = configurationsNode.getChildNodes();
        for (int i = 0, size = configurationsNodeList.getLength(); i < size; i++) {
            Node configurationNode = configurationsNodeList.item(i);
            if (configurationNode.getNodeType() != Node.ELEMENT_NODE) {
                continue;
            }
            NamedNodeMap attributeMap = configurationNode.getAttributes();
            if (attributeMap == null) {
                continue;
            }
            Node nameNode = attributeMap.getNamedItem(ProjectFormatConstants.CONFIGURATION_NAME_ATTRIBUTE);
            if (nameNode == null) {
                displayError("Import failed", "Error while importing project " + project.getName()
                        + " the name attribute of a referenced project is missing");
                return false;
            }

            String configurationName = nameNode.getTextContent();

            if (ProjectFormatConstants.DEFAULT_CONFIGURATION_NAME.equals(configurationName)) {
                copyConfigurationData(targetDocument.getDocumentElement(), configurationNode);
            } else {
                Element targetConfiguration = targetDocument
                        .createElement(ProjectFormatConstants.CONFIGURATION_NODE);
                targetConfiguration.setAttribute(ProjectFormatConstants.CONFIGURATION_NAME_ATTRIBUTE,
                        configurationName);
                targetConfigurationsRoot.appendChild(targetConfiguration);

                copyConfigurationData(targetConfiguration, configurationNode);
            }
        }

        ProjectDocumentHandlingUtility.saveDocument(project);
        ProjectBuildPropertyData.setProjectAlreadyExported(project, false);
        ProjectFileHandler handler = new ProjectFileHandler(project);
        handler.loadProjectSettingsFromDocument(targetDocument);

        return true;
    }

    /**
     * Remove those child nodes of the provided node, which are related to
     * handling configuration data.
     *
     * @param rootNode
     *            the node to use.
     * */
    private void removeConfigurationNodes(final Node rootNode) {
        NodeList rootNodeList = rootNode.getChildNodes();

        Node tempNode = ProjectFileHandler.getNodebyName(rootNodeList, ProjectFormatConstants.CONFIGURATIONS_NODE);
        if (tempNode != null) {
            rootNode.removeChild(tempNode);
        }
        tempNode = ProjectFileHandler.getNodebyName(rootNodeList, ProjectFileHandler.PROJECTPROPERTIESXMLNODE);
        if (tempNode != null) {
            rootNode.removeChild(tempNode);
        }
        tempNode = ProjectFileHandler.getNodebyName(rootNodeList, ProjectFileHandler.FOLDERPROPERTIESXMLNODE);
        if (tempNode != null) {
            rootNode.removeChild(tempNode);
        }
        tempNode = ProjectFileHandler.getNodebyName(rootNodeList, ProjectFileHandler.FILEPROPERTIESXMLNODE);
        if (tempNode != null) {
            rootNode.removeChild(tempNode);
        }
        tempNode = ProjectFileHandler.getNodebyName(rootNodeList, ProjectFormatConstants.ACTIVE_CONFIGURATION_NODE);
        if (tempNode != null) {
            rootNode.removeChild(tempNode);
        }
    }

    /**
     * Copies the configuration related data from the source node, to the target
     * node.
     *
     * @param targetRoot
     *            the node where the configuration data should be moved to.
     * @param sourceRoot
     *            the node from where the configuration data is moved.
     * */
    private void copyConfigurationData(final Element targetRoot, final Node sourceRoot) {
        final Document document = targetRoot.getOwnerDocument();
        final NodeList rootList = sourceRoot.getChildNodes();
        Node targetNode = null;
        for (int i = 0, size = rootList.getLength(); i < size; i++) {
            Node tempNode = rootList.item(i);
            String nodeName = tempNode.getNodeName();
            if (ProjectFileHandler.PROJECTPROPERTIESXMLNODE.equals(nodeName)
                    || ProjectFileHandler.FOLDERPROPERTIESXMLNODE.equals(nodeName)
                    || ProjectFileHandler.FILEPROPERTIESXMLNODE.equals(nodeName)) {
                targetNode = document.importNode(tempNode, true);
                ProjectFileHandler.clearNode(targetNode);
                targetRoot.appendChild(targetNode);
            }
        }
    }

    class ProjectSelector implements Runnable {
        private String projectName;
        private IProject project = null;
        private boolean cancelled = false;

        public ProjectSelector(final String projectName) {
            this.projectName = projectName;
        }

        public String getProjectName() {
            return projectName;
        }

        public IProject getProject() {
            return project;
        }

        public boolean isCancelled() {
            return cancelled;
        }

        @Override
        public void run() {
            NewProjectNameDialog dialog = new NewProjectNameDialog(shell, projectName);
            if (dialog.open() == Window.OK) {
                projectName = dialog.getName();
                project = ResourcesPlugin.getWorkspace().getRoot().getProject(projectName);
                if (project.exists()) {
                    cancelled = true;
                }
            } else {
                cancelled = true;
            }
        }

    }

    /**
     * Create a new project based on the information found in the provided
     * document.
     * */
    private IProject createProject(final Node mainElement, final boolean treatExistingProjectAsError) {
        NodeList mainNodes = mainElement.getChildNodes();
        Node projectNameNode = ProjectFileHandler.getNodebyName(mainNodes, ProjectFormatConstants.PROJECTNAME_NODE);
        if (null == projectNameNode) {
            TITANDebugConsole.getConsole().newMessageStream().println(
                    "The name of the project could not be found in the project descriptor, it will not be created.");
            return null;
        }
        String originalProjectName = projectNameNode.getFirstChild().getTextContent();
        String projectName = originalProjectName;

        IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(projectName);
        if (project.exists()) {

            if (!treatExistingProjectAsError || headless) {

                if (!project.isOpen()) {
                    try {
                        project.open(null);
                    } catch (CoreException e) {
                        ErrorReporter.logError(
                                "An existing project with the name " + projectName + " cannot be opened!");
                    }
                }
                ErrorReporter
                        .logWarning("A project with the name " + projectName + " already exists, skipping it!");
                //It will be skipped => 
                return null;
            }
            //Error dialog:
            //gets a new project name instead of the existing one:
            ProjectSelector temp = new ProjectSelector(projectName);
            Display.getDefault().syncExec(temp);
            if (temp.cancelled) {
                return null;
            }

            projectName = temp.getProjectName();
            project = temp.getProject();
        }

        finalProjectNames.put(originalProjectName, projectName);

        project = createNewProject(project, projectName);
        if (project == null) {
            TITANDebugConsole.getConsole().newMessageStream()
                    .println("There was an error while creating the project " + projectName);
            return null;
        }

        try {
            TITANNature.addTITANBuilderToProject(project);
        } catch (CoreException e) {
            ErrorReporter.logExceptionStackTrace("While adding builder to `" + project.getName() + "'", e);
        }

        return project;
    }

    /**
     * Load the project information document from the provided file and
     * recursively for all project files mentioned in the referenced projects
     * section.
     *
     * @param file
     *            the file to load the data from.
     * @param validator
     *            the xml validator. can be <code>null</code>
     *
     * @return true if there were no errors, false otherwise.
     * */
    private boolean loadURIDocuments(final URI file, final Validator validator) {
        if (projectsToImport.containsKey(file)) {
            return true;
        }

        if (!"file".equals(file.getScheme()) && !"".equals(file.getScheme())) {
            ErrorReporter.logError("Loading of project information is only supported for local files right now. "
                    + file.toString() + " could not be loaded");
            return false;
        }

        Document document = getDocumentFromFile(file.getPath());

        if (document == null) {
            final StringBuilder builder = new StringBuilder(
                    "It was not possible to load the imported project file: '" + file.toString() + "'\n");
            for (int i = importChain.size() - 1; i >= 0; --i) {
                builder.append("imported by: '");
                builder.append(importChain.get(i).toString());
                builder.append("'\n");
            }
            ErrorReporter.logError(builder.toString());
            return false;
        }
        if (validator != null) {
            try {
                validator.validate(new StreamSource(new File(file)));
            } catch (final Exception e) {
                ErrorReporter.logExceptionStackTrace(
                        "Error while importing from file " + file + ": " + System.getProperty("line.separator"), e);
                return false;
            }
        }

        ProjectFileHandler.clearNode(document);

        projectsToImport.put(file, document);

        Element mainElement = document.getDocumentElement();
        NodeList mainNodes = mainElement.getChildNodes();
        Node referencedProjectsNode = ProjectFileHandler.getNodebyName(mainNodes,
                ProjectFormatConstants.REFERENCED_PROJECTS_NODE);
        if (referencedProjectsNode == null) {
            return true;
        }

        // === Get referenced projects ===
        final IPath projectFileFolderPath = new Path(file.getPath()).removeLastSegments(1);
        NodeList referencedProjectsList = referencedProjectsNode.getChildNodes();
        boolean result = true;
        for (int i = 0, size = referencedProjectsList.getLength(); i < size; i++) {
            Node referencedProjectNode = referencedProjectsList.item(i);
            if (referencedProjectNode.getNodeType() != Node.ELEMENT_NODE) {
                continue;
            }
            NamedNodeMap attributeMap = referencedProjectNode.getAttributes();
            if (attributeMap == null) {
                continue;
            }
            Node nameNode = attributeMap.getNamedItem(ProjectFormatConstants.REFERENCED_PROJECT_NAME_ATTRIBUTE);
            if (nameNode == null) {
                displayError("Import failed", "Error while importing from file " + file
                        + " the name attribute of a referenced project is missing");
                return false;
            }

            final String projectName = nameNode.getTextContent();
            Node locationNode = attributeMap
                    .getNamedItem(ProjectFormatConstants.REFERENCED_PROJECT_LOCATION_ATTRIBUTE);
            if (locationNode == null) {
                displayError("Import failed", "Error while importing from file " + file
                        + " the location attribute of the referenced project " + projectName + " is not given.");
                return false;
            }

            String unresolvedProjectLocationURI = locationNode.getTextContent();

            URI absoluteURI = TITANPathUtilities.resolvePath(unresolvedProjectLocationURI,
                    URIUtil.toURI(projectFileFolderPath));

            String fileName;
            // Determine tpdname
            Node tpdNameNode = attributeMap
                    .getNamedItem(ProjectFormatConstants.REFERENCED_PROJECT_TPD_NAME_ATTRIBUTE);
            if (tpdNameNode != null) {
                fileName = tpdNameNode.getTextContent();
            } else {
                fileName = projectName + ".tpd";
            }
            tpdNameAttrMap.put(projectName, fileName);
            if (searchPaths != null && !searchPaths.isEmpty()) {
                File f = new File(absoluteURI);
                IPath unresolvedProjectLocationURIPath = new Path(unresolvedProjectLocationURI);
                if (!unresolvedProjectLocationURIPath.isAbsolute() && (!f.exists() || f.isDirectory())) {
                    ;
                    // Try search paths
                    for (String path : searchPaths) {
                        String filePath = path;
                        if (path.charAt(path.length() - 1) != '/') {
                            filePath += "/";
                        }
                        filePath += fileName;
                        String systemPath = new Path(filePath).toOSString();
                        f = new File(systemPath);
                        // tpd found
                        if (f.exists() && !f.isDirectory()) {
                            absoluteURI = URIUtil.toURI(systemPath);
                            tpdURIMap.put(projectName, unresolvedProjectLocationURI);
                            break;
                        }
                    }
                }
            }

            if (absoluteURI != null && !"file".equals(absoluteURI.getScheme())) {
                final StringBuilder builder = new StringBuilder(
                        "Loading of project information is only supported for local files right now. "
                                + absoluteURI.toString() + " could not be loaded\n");
                for (int j = importChain.size() - 1; j >= 0; --j) {
                    builder.append("imported by: '");
                    builder.append(importChain.get(j).toString());
                    builder.append("'\n");
                }
                ErrorReporter.logError(builder.toString());
                continue;
            }

            importChain.add(file);
            //         if( !projectsWithUnresolvedName.containsKey(absoluteURI) ) {
            //            projectsWithUnresolvedName.put(absoluteURI, unresolvedProjectLocationURI);
            //         }
            result &= loadURIDocuments(absoluteURI, validator);
            importChain.remove(importChain.size() - 1);
        }

        return result;
    }

    private void displayError(final String title, final String message) {
        if (!headless) {
            ErrorReporter.parallelErrorDisplayInMessageDialog(title, message);
        }
        ErrorReporter.logError(message);
    }

    /**
     * Extracts an XML document from the provided file.
     *
     * @param file
     *            the file to read from.
     * @return the extracted XML document, or null if there were some error.
     * */
    public Document getDocumentFromFile(final String file) {
        final LSInput lsInput = domImplLS.createLSInput();
        Document document = null;
        try {
            FileInputStream istream = new FileInputStream(file);
            lsInput.setByteStream(istream);
            document = parser.parse(lsInput);
            istream.close();
        } catch (Exception e) {
            ErrorReporter.logExceptionStackTrace("While getting the document from `" + file + "'", e);
        }

        return document;
    }

    /**
     * Creating a new project.
     *
     * @return the new project created.
     */
    IProject createNewProject(final IProject newProjectHandle, final String name) {
        IProject newProject;

        final IWorkspace workspace = ResourcesPlugin.getWorkspace();
        final IProjectDescription description = workspace.newProjectDescription(name);

        TITANNature.addTITANNatureToProject(description);

        if (headless) {
            try {
                createProject(description, newProjectHandle, new NullProgressMonitor());
            } catch (CoreException e) {
                ErrorReporter.logExceptionStackTrace("While creating project `" + newProjectHandle.getName() + "'",
                        e);
            }
        } else {
            Display.getDefault().syncExec(new Runnable() {
                @Override
                public void run() {
                    try {
                        final WorkspaceModifyOperation op = new WorkspaceModifyOperation() {
                            @Override
                            protected void execute(final IProgressMonitor monitor) throws CoreException {
                                createProject(description, newProjectHandle, monitor);
                            }
                        };
                        new ProgressMonitorDialog(null).run(true, true, op);
                    } catch (InterruptedException e) {
                        return;
                    } catch (final InvocationTargetException e) {
                        displayError(CREATION_FAILED, e.getMessage());
                        ErrorReporter.logExceptionStackTrace(
                                "While creating project `" + newProjectHandle.getName() + "'", e);
                        return;
                    }
                }
            });
        }

        newProject = newProjectHandle;

        return newProject;
    }

    /**
     * Creating a new project.
     *
     * @param description
     *            - IProjectDescription that belongs to the newly created
     *            project.
     * @param projectHandle
     *            - a project handle that is used to create the new project.
     * @param monitor
     *            - reference to the monitor object
     * @exception CoreException
     *                thrown if access to the resources throws a CoreException.
     * @exception OperationCanceledException
     *                if the operation was canceled by the user.
     */
    protected void createProject(final IProjectDescription description, final IProject projectHandle,
            final IProgressMonitor monitor) throws CoreException {
        final SubMonitor progress = SubMonitor.convert(monitor, 3);

        try {
            progress.setTaskName(CREATING_PROJECT);

            projectHandle.create(description, progress.newChild(1));

            if (progress.isCanceled()) {
                throw new OperationCanceledException();
            }

            projectHandle.open(IResource.BACKGROUND_REFRESH, progress.newChild(1));

            projectHandle.refreshLocal(IResource.DEPTH_ONE, progress.newChild(1));
        } finally {
            progress.done();
        }
    }
}