/**
  * Initializes variables, which are often reused. This should be called every time there is a
  * chance that project settings have been changed.
  */
 public void init() {
   sourceDir = TexlipseProperties.getProjectSourceDir(project);
   outputDir = TexlipseProperties.getProjectOutputDir(project);
   tempDir = TexlipseProperties.getProjectTempDir(project);
   format = TexlipseProperties.getProjectProperty(project, TexlipseProperties.OUTPUT_FORMAT);
   sourceFile = TexlipseProperties.getProjectSourceFile(project);
 }
  /**
   * Moves temporary files out of the build directory, if applicable. A file is considered a
   * temporary file, if
   *
   * <ul>
   *   <li>it had been in the temporary files folder before the build process
   *       <p><b>or</b>
   *   <li>it was created or modified during the build process, and has a temporary file extension
   *       as specified in the preferences
   * </ul>
   *
   * @param excludes set of paths to exclude from moving, e.g. because they are the main output
   *     files
   * @param monitor progress monitor
   * @throws CoreException if an error occurs
   */
  private void moveTempFiles(final Set<IPath> excludes, IProgressMonitor monitor)
      throws CoreException {
    final IContainer aSourceContainer = getActualSourceContainer();
    if (tracking.isInitial() || aSourceContainer == null || !aSourceContainer.exists()) {
      return;
    }

    final boolean markAsDerived =
        "true"
            .equals(
                TexlipseProperties.getProjectProperty(
                    project, TexlipseProperties.MARK_TEMP_DERIVED_PROPERTY));
    final String[] tempExts = TexlipsePlugin.getPreferenceArray(TexlipseProperties.TEMP_FILE_EXTS);

    // Check if there is anything to do
    if (markAsDerived || tempDir != null) {
      // First move temporary files, which had been placed into the source folder
      // just prior to the build;
      // then check for new temporary files, which need to be moved
      project
          .getWorkspace()
          .run(
              new IWorkspaceRunnable() {
                public void run(IProgressMonitor monitor) throws CoreException {
                  if (movedFiles != null) {
                    if (excludes != null) {
                      movedFiles.removeAll(excludes);
                    }
                    moveFiles(sourceDir, tempDir, movedFiles, markAsDerived, true, monitor);
                  }
                  final Set<IPath> newTempNames =
                      tracking.getNewTempNames(aSourceContainer, tempExts, format, monitor);
                  if (excludes != null) {
                    newTempNames.removeAll(excludes);
                  }
                  moveFiles(sourceDir, tempDir, newTempNames, markAsDerived, true, monitor);
                }
              },
              monitor);
    }
  }
  /**
   * Renames output files and/or moves them if necessary. A file is considered an output file, if
   *
   * <ul>
   *   <li>it is the current output file (which can also be from a temporary build)
   *       <p><b>or</b>
   *   <li>it has the same file name as the current input file, apart from its file extension, and
   *       one of the derived file extensions as specified in the preferences
   * </ul>
   *
   * @param monitor progress monitor
   * @return set of paths to the (possibly moved) files
   * @throws CoreException if an error occurs
   */
  private Set<IPath> moveOutputFiles(IProgressMonitor monitor) throws CoreException {
    final boolean markAsDerived =
        "true"
            .equals(
                TexlipseProperties.getProjectProperty(
                    project, TexlipseProperties.MARK_OUTPUT_DERIVED_PROPERTY));
    final String[] derivedExts =
        TexlipsePlugin.getPreferenceArray(TexlipseProperties.DERIVED_FILES);

    final IFile aSourceFile = getActualSourceFile();
    final IContainer aSourceContainer = getActualSourceContainer();
    final IFile sOutputFile = getSelectedOutputFile();
    final IContainer sOutputContainer = getSelectedOutputContainer(markAsDerived, monitor);
    if (aSourceFile == null
        || aSourceContainer == null
        || sOutputFile == null
        || sOutputContainer == null) {
      // Something is wrong with the settings
      return null;
    }

    // Get name without extension from main files for renaming
    final String dotFormat = '.' + format;
    final String sourceBaseName = stripFileExt(aSourceFile.getName(), null);
    final String outputBaseName = stripFileExt(sOutputFile.getName(), dotFormat);

    // Check if files are to be moved or renamed
    final boolean moveFiles =
        !sourceBaseName.equals(outputBaseName) || !sOutputContainer.equals(aSourceContainer);
    // Retrieve output and other derived files along with their extensions
    final Map<IPath, String> outputFiles =
        ProjectFileTracking.getOutputNames(
            aSourceContainer, sourceBaseName, derivedExts, format, monitor);

    // Check if there is anything to do
    if ((moveFiles || markAsDerived) && !outputFiles.isEmpty()) {
      final Set<IPath> movedFiles = new HashSet<IPath>(outputFiles.size());

      project
          .getWorkspace()
          .run(
              new IWorkspaceRunnable() {
                public void run(IProgressMonitor monitor) throws CoreException {
                  // Move files to destination folder and rename
                  for (Entry<IPath, String> entry : outputFiles.entrySet()) {
                    IFile currentFile = project.getFile(entry.getKey());
                    if (moveFiles) {
                      // Determine new file name
                      String destName = outputBaseName + entry.getValue();
                      // Move file
                      IFile dest =
                          moveFile(project, currentFile, sOutputContainer, destName, monitor);
                      if (dest != null && markAsDerived) {
                        dest.setDerived(true);
                      }
                      movedFiles.add(dest.getProjectRelativePath());
                    } else {
                      // Possibly mark as derived
                      if (markAsDerived) {
                        currentFile.setDerived(true);
                      }
                      movedFiles.add(entry.getKey());
                    }
                  }
                }
              },
              monitor);

      return movedFiles;
    } else {
      return outputFiles.keySet();
    }
  }
  /**
   * Does the same as super.createDocument(Object), except this also adds latex nature to the
   * project containing the given document.
   */
  public IDocument getDocument(Object element) {
    IDocument doc = super.getDocument(element);

    // add latex nature to project holding this latex file
    // this way we also get latex builder to any project that has latex files
    if (element instanceof FileEditorInput) {
      IFile file = (IFile) ((FileEditorInput) element).getAdapter(IFile.class);
      if (file != null) {

        IProject project = file.getProject();
        try {
          if (!project.hasNature(TexlipseNature.NATURE_ID)) {
            return doc;
            //                        TexlipseProjectCreationOperation.addProjectNature(project, new
            // NullProgressMonitor());
          } else if (TexlipseProperties.getProjectProperty(
                  project, TexlipseProperties.OUTPUT_FORMAT)
              == null) {
            // this is needed for imported projects
            TexlipseNature n = new TexlipseNature();
            // the nature is not added, just configured
            n.setProject(project);
            // this will cause the builder to be added, if not already there
            n.configure();
          }
        } catch (CoreException e) {
          return doc;
        }

        // output format might not yet be set
        String format =
            TexlipseProperties.getProjectProperty(project, TexlipseProperties.OUTPUT_FORMAT);
        if (format == null || format.length() == 0) {
          TexlipseProperties.setProjectProperty(
              project,
              TexlipseProperties.OUTPUT_FORMAT,
              TexlipsePlugin.getPreference(TexlipseProperties.OUTPUT_FORMAT));
          TexlipseProperties.setProjectProperty(
              project,
              TexlipseProperties.BUILDER_NUMBER,
              TexlipsePlugin.getPreference(TexlipseProperties.BUILDER_NUMBER));
          TexlipseProperties.setProjectProperty(
              project, TexlipseProperties.MARK_TEMP_DERIVED_PROPERTY, "true");
          TexlipseProperties.setProjectProperty(
              project, TexlipseProperties.MARK_OUTPUT_DERIVED_PROPERTY, "true");

          String name = file.getName();
          TexlipseProperties.setProjectProperty(
              project, TexlipseProperties.MAINFILE_PROPERTY, name);
          String output =
              name.substring(0, name.lastIndexOf('.') + 1)
                  + TexlipsePlugin.getPreference(TexlipseProperties.OUTPUT_FORMAT);
          TexlipseProperties.setProjectProperty(
              project, TexlipseProperties.OUTPUTFILE_PROPERTY, output);

          IPath path = file.getFullPath();
          String dir = path.removeFirstSegments(1).removeLastSegments(1).toString();
          if (dir.length() > 0) {
            TexlipseProperties.setProjectProperty(
                project, TexlipseProperties.SOURCE_DIR_PROPERTY, dir);
            TexlipseProperties.setProjectProperty(
                project, TexlipseProperties.OUTPUT_DIR_PROPERTY, dir);
            TexlipseProperties.setProjectProperty(
                project, TexlipseProperties.TEMP_DIR_PROPERTY, dir);
          }
        }
      }
    }

    return doc;
  }