/**
  * {@inheritDoc}
  *
  * @see
  *     org.eclipse.core.resources.IWorkspaceRunnable#run(org.eclipse.core.runtime.IProgressMonitor)
  */
 public void run(IProgressMonitor monitor) throws CoreException {
   monitor.beginTask(
       AcceleoUIMessages.getString("AcceleoCompileOperation.Task.Compile"),
       files.length); // $NON-NLS-1$
   for (int i = 0; i < files.length; i++) {
     checkCanceled(monitor);
     monitor.subTask(
         AcceleoUIMessages.getString(
             "AcceleoCompileOperation.Task.Clean",
             files[0].getFullPath().toString())); // $NON-NLS-1$
     if (files[i].isAccessible()) {
       files[i].deleteMarkers(IMarker.PROBLEM, true, IResource.DEPTH_INFINITE);
       files[i].deleteMarkers(IMarker.TASK, true, IResource.DEPTH_INFINITE);
       files[i].deleteMarkers(
           AcceleoMarkerUtils.OVERRIDE_MARKER_ID, true, IResource.DEPTH_INFINITE);
     }
   }
   if (!isClean) {
     doCompileResources(monitor);
   } else {
     for (IFile file : this.files) {
       AcceleoProject acceleoProject = new AcceleoProject(project);
       IPath outputPath = acceleoProject.getOutputFilePath(file);
       if (outputPath != null) {
         URI platformURI = URI.createPlatformResourceURI(outputPath.toString(), false);
         try {
           AcceleoUIResourceSet.removeResource(platformURI);
         } catch (IOException e) {
           AcceleoUIActivator.log(e, true);
         }
       }
     }
   }
   monitor.done();
 }
  /**
   * This method will ensure that the Acceleo project has a dependency with all the project
   * containing a dynamic metamodels used in the module.
   *
   * @param module The Acceleo module
   * @param inputFile The file in the Acceleo editor
   */
  private void checkDependenciesWithDynamicMetamodels(Module module, IFile inputFile) {
    List<TypedModel> input = module.getInput();
    for (TypedModel typedModel : input) {
      List<EPackage> takesTypesFrom = typedModel.getTakesTypesFrom();
      for (EPackage ePackage : takesTypesFrom) {
        Map<String, String> dynamicEcorePackagePaths =
            AcceleoPackageRegistry.INSTANCE.getDynamicEcorePackagePaths();
        String packagePath = dynamicEcorePackagePaths.get(ePackage.getNsURI());
        if (packagePath == null) {
          return;
        }
        IPath path = new Path(packagePath);
        IFile metamodelFile = ResourcesPlugin.getWorkspace().getRoot().getFile(path);
        if (metamodelFile != null && metamodelFile.isAccessible()) {
          // We have found the "ecore" file for the dynamic metamodel
          IProject metamodelProject = metamodelFile.getProject();
          IProject inputProject = inputFile.getProject();
          if (!inputProject.equals(metamodelProject)) {
            // The dynamic metamodel is not in the project of the generator, let's find if
            // this dynamic metamodel is in a dependency of the project of the generator.
            boolean foundProject = false;

            AcceleoProject acceleoProject = new AcceleoProject(inputProject);
            List<IProject> recursivelyAccessibleProjects =
                acceleoProject.getRecursivelyAccessibleProjects();
            for (IProject iProject : recursivelyAccessibleProjects) {
              if (iProject.equals(metamodelProject)) {
                foundProject = true;
              }
            }

            if (!foundProject) {
              // The dynamic metamodel is not in a dependency of the current project, log a
              // warning.
              try {
                AcceleoMarkerUtils.createMarkerOnFile(
                    AcceleoMarkerUtils.WARNING_MARKER_ID,
                    inputFile,
                    0,
                    typedModel.getStartPosition(),
                    typedModel.getEndPosition(),
                    AcceleoUIMessages.getString(
                        "AcceleoCompileOperation.NoDependencyWithDynamicMetamodelProject", //$NON-NLS-1$
                        metamodelProject.getName(),
                        inputProject.getName()));
              } catch (CoreException e) {
                AcceleoUIActivator.log(e, true);
              }
            }
          }
        }
      }
    }
  }
  /**
   * Compiles the templates. Creates an AST model from a list of Acceleo files, using a CST step.
   * The dependencies are loaded before link resolution.
   *
   * @param monitor is the monitor
   * @throws CoreException contains a status object describing the cause of the exception
   */
  private void doCompileResources(IProgressMonitor monitor) throws CoreException {
    AcceleoProject acceleoProject = new AcceleoProject(project);
    List<URI> dependenciesURIs = acceleoProject.getAccessibleOutputFiles();
    List<AcceleoFile> iFiles = new ArrayList<AcceleoFile>();
    List<URI> oURIs = new ArrayList<URI>();
    for (int i = 0; i < files.length; i++) {
      checkCanceled(monitor);
      if (acceleoProject.getOutputFilePath(files[i]) != null) {
        IPath outputPath = acceleoProject.getOutputFilePath(files[i]);
        if (outputPath != null) {
          String javaPackageName = acceleoProject.getPackageName(files[i]);
          AcceleoFile acceleoFile =
              new AcceleoFile(
                  files[i].getLocation().toFile(),
                  AcceleoFile.javaPackageToFullModuleName(
                      javaPackageName,
                      new Path(files[i].getName()).removeFileExtension().lastSegment()));
          iFiles.add(acceleoFile);
          URI platformURI = URI.createPlatformResourceURI(outputPath.toString(), false);
          oURIs.add(platformURI);
        }
      }
    }

    AcceleoParser parser = null;
    AcceleoBuilderSettings settings = new AcceleoBuilderSettings(project);
    String resourceKind = settings.getResourceKind();
    if (AcceleoBuilderSettings.BUILD_XMI_RESOURCE.equals(resourceKind)) {
      parser = new AcceleoParser(false, settings.isTrimmedPositions());
    } else {
      parser = new AcceleoParser(true, settings.isTrimmedPositions());
    }
    parser.parse(
        iFiles, oURIs, dependenciesURIs, null, new BasicMonitor.EclipseSubProgress(monitor, 1));
    for (URI uri : oURIs) {
      try {
        AcceleoUIResourceSet.removeResource(uri);
      } catch (IOException e) {
        AcceleoUIActivator.log(e, true);
      }
    }

    for (Iterator<AcceleoFile> iterator = iFiles.iterator(); iterator.hasNext(); ) {
      AcceleoFile iFile = iterator.next();

      AcceleoParserProblems problems = parser.getProblems(iFile);
      AcceleoParserWarnings warnings = parser.getWarnings(iFile);
      AcceleoParserInfos infos = parser.getInfos(iFile);

      IFile workspaceFile =
          ResourcesPlugin.getWorkspace()
              .getRoot()
              .getFileForLocation(new Path(iFile.getMtlFile().getAbsolutePath()));

      if (workspaceFile != null && workspaceFile.isAccessible()) {
        if (problems != null) {
          List<AcceleoParserProblem> list = problems.getList();
          for (Iterator<AcceleoParserProblem> itProblems = list.iterator();
              itProblems.hasNext(); ) {
            AcceleoParserProblem problem = itProblems.next();
            AcceleoMarkerUtils.createMarkerOnFile(
                AcceleoMarkerUtils.PROBLEM_MARKER_ID,
                workspaceFile,
                problem.getLine(),
                problem.getPosBegin(),
                problem.getPosEnd(),
                problem.getMessage());
          }
        }
        if (warnings != null) {
          List<AcceleoParserWarning> list = warnings.getList();
          for (Iterator<AcceleoParserWarning> itWarnings = list.iterator();
              itWarnings.hasNext(); ) {
            AcceleoParserWarning warning = itWarnings.next();
            AcceleoMarkerUtils.createMarkerOnFile(
                AcceleoMarkerUtils.WARNING_MARKER_ID,
                workspaceFile,
                warning.getLine(),
                warning.getPosBegin(),
                warning.getPosEnd(),
                warning.getMessage());
          }
        }
        if (infos != null) {
          List<AcceleoParserInfo> list = infos.getList();
          for (Iterator<AcceleoParserInfo> itInfos = list.iterator(); itInfos.hasNext(); ) {
            AcceleoParserInfo info = itInfos.next();
            AcceleoMarkerUtils.createMarkerOnFile(
                AcceleoMarkerUtils.INFO_MARKER_ID,
                workspaceFile,
                info.getLine(),
                info.getPosBegin(),
                info.getPosEnd(),
                info.getMessage());
          }
        }
      }
    }

    if (iFiles.size() > 0) {
      AcceleoFile acceleoFile = iFiles.get(0);
      IFile workspaceFile =
          ResourcesPlugin.getWorkspace()
              .getRoot()
              .getFileForLocation(new Path(acceleoFile.getMtlFile().getAbsolutePath()));

      // FIXME Performance problem? We will only check for the first file to compile.
      AcceleoSourceBuffer buffer = new AcceleoSourceBuffer(acceleoFile);
      buffer.createCST();
      Module module = buffer.getCST();
      this.checkDependenciesWithDynamicMetamodels(module, workspaceFile);
    }
    checkCanceled(monitor);
    List<IFile> filesWithMainTag = new ArrayList<IFile>();
    for (Iterator<AcceleoFile> iterator = iFiles.iterator(); iterator.hasNext(); ) {
      AcceleoFile iFile = iterator.next();
      IFile workspaceFile =
          ResourcesPlugin.getWorkspace()
              .getRoot()
              .getFileForLocation(new Path(iFile.getMtlFile().getAbsolutePath()));
      if (workspaceFile != null && workspaceFile.isAccessible() && hasMainTag(workspaceFile)) {
        filesWithMainTag.add(workspaceFile);
      }
    }
    CreateRunnableAcceleoOperation createRunnableAcceleoOperation =
        new CreateRunnableAcceleoOperation(acceleoProject, filesWithMainTag);
    createRunnableAcceleoOperation.run(monitor);

    settings = new AcceleoBuilderSettings(project);
    if (AcceleoBuilderSettings.BUILD_STRICT_MTL_COMPLIANCE == settings.getCompliance()) {
      Iterator<AcceleoFile> itFiles = iFiles.iterator();
      for (Iterator<URI> itURIs = oURIs.iterator();
          !monitor.isCanceled() && itURIs.hasNext() && itFiles.hasNext(); ) {
        AcceleoFile iFile = itFiles.next();
        URI oURI = itURIs.next();
        checkFullOMGCompliance(iFile.getMtlFile(), oURI);
      }
    }
  }