/**
   * {@inheritDoc}
   *
   * @see java.util.concurrent.Callable#call()
   */
  public CompilationResult call() throws Exception {
    checkCancelled();

    String fullExpression = acceleoSource.rebuildFullExpression(context);

    ResourceSet resourceSet = new ResourceSetImpl();
    Resource resource =
        ModelUtils.createResource(
            URI.createURI("http://acceleo.eclipse.org/default.emtl"), resourceSet); // $NON-NLS-1$

    AcceleoSourceBuffer source = new AcceleoSourceBuffer(new StringBuffer(fullExpression));

    List<URI> dependencies = new ArrayList<URI>();
    if (acceleoSource.getModuleImport() != null) {
      dependencies.addAll(computeImportList(acceleoSource.getModuleImport(), resourceSet));
    }

    AcceleoParser parser = new AcceleoParser();
    parser.parse(source, resource, dependencies);

    checkCancelled();

    ASTNode selectedNode = null;
    if (!resource.getContents().isEmpty()) {
      Module module = (Module) resource.getContents().get(0);

      ISelection selection = context.getSelection();
      if (selection instanceof ITextSelection && ((ITextSelection) selection).getLength() > 0) {
        ITextSelection textSelection = (ITextSelection) selection;
        int startOffset = textSelection.getOffset() + acceleoSource.getGap();
        int endOffset = startOffset + textSelection.getLength();

        if (textSelection.getText().startsWith("[")) { // $NON-NLS-1$
          startOffset++;
        }
        if (textSelection.getText().endsWith("/]")) { // $NON-NLS-1$
          endOffset -= 2;
        }

        selectedNode = getChildrenCandidate(module, startOffset, endOffset);

        if (textSelection.getLength() == 0) {
          while (selectedNode != null && !(selectedNode instanceof ModuleElement)) {
            selectedNode = (ASTNode) selectedNode.eContainer();
          }
        }
      }

      if (selectedNode == null && module != null && !module.getOwnedModuleElement().isEmpty()) {
        selectedNode = module.getOwnedModuleElement().get(0);
      }
    }

    checkCancelled();

    IStatus problems = parseProblems(source.getProblems(), source.getWarnings(), source.getInfos());
    return new CompilationResult(selectedNode, problems);
  }
 /**
  * Check the '.emtl' file and report in the '.mtl' file some syntax errors when we use the
  * non-standard library.
  *
  * @param iFile is the '.mtl' file
  * @param oURI is the URI of the '.emtl' file
  */
 private void checkFullOMGCompliance(File iFile, URI oURI) {
   try {
     AcceleoSourceBuffer buffer = new AcceleoSourceBuffer(iFile);
     ResourceSet oResourceSet = new ResourceSetImpl();
     EObject oRoot = ModelUtils.load(oURI, oResourceSet);
     TreeIterator<EObject> oAllContents = oRoot.eAllContents();
     while (oAllContents.hasNext()) {
       EObject oNext = oAllContents.next();
       if (oNext instanceof OperationCallExp) {
         OperationCallExp oOperationCallExp = (OperationCallExp) oNext;
         if (oOperationCallExp.getReferredOperation() != null
             && oOperationCallExp.getReferredOperation().getEAnnotation("MTL non-standard")
                 != null) { //$NON-NLS-1$
           IFile workspaceFile =
               ResourcesPlugin.getWorkspace()
                   .getRoot()
                   .getFileForLocation(new Path(iFile.getAbsolutePath()));
           if (workspaceFile != null
               && workspaceFile.isAccessible()
               && oOperationCallExp.getStartPosition() > -1) {
             int line = buffer.getLineOfOffset(oOperationCallExp.getStartPosition());
             AcceleoMarkerUtils.createMarkerOnFile(
                 AcceleoMarkerUtils.PROBLEM_MARKER_ID,
                 workspaceFile,
                 line,
                 oOperationCallExp.getStartPosition(),
                 oOperationCallExp.getEndPosition(),
                 AcceleoUIMessages.getString(
                     "AcceleoCompileOperation.NotFullyCompliant",
                     oOperationCallExp //$NON-NLS-1$
                         .getReferredOperation()
                         .getName()));
           }
         }
       }
     }
   } catch (IOException e) {
     Status status = new Status(IStatus.WARNING, AcceleoUIActivator.PLUGIN_ID, e.getMessage(), e);
     AcceleoUIActivator.getDefault().getLog().log(status);
   } catch (CoreException e) {
     AcceleoUIActivator.getDefault().getLog().log(e.getStatus());
   }
 }
  /**
   * 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);
      }
    }
  }