Package com.google.devtools.moe.client.editors

Source Code of com.google.devtools.moe.client.editors.RenamingEditor

// Copyright 2011 The MOE Authors All Rights Reserved.

package com.google.devtools.moe.client.editors;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.CharMatcher;
import com.google.common.collect.ImmutableMap;
import com.google.devtools.moe.client.AppContext;
import com.google.devtools.moe.client.MoeProblem;
import com.google.devtools.moe.client.codebase.Codebase;
import com.google.devtools.moe.client.project.EditorConfig;
import com.google.devtools.moe.client.project.ProjectContext;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.google.gson.reflect.TypeToken;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.Type;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
* The renaming editor reorganizes the project's hierarchy.
*
*/
public class RenamingEditor implements Editor {

  /** CharMatcher for trimming leading and trailing file path separators. */
  private static final CharMatcher SEP_CHAR_MATCHER = CharMatcher.is(File.separatorChar);

  private final String editorName;
  private final Map<Pattern, String> regexMappings;

  RenamingEditor(String editorName, Map<String, String> mappings, boolean useRegex) {
    this.editorName = editorName;

    ImmutableMap.Builder<Pattern, String> regexMappingsBuilder = ImmutableMap.builder();
    for (String mapping : mappings.keySet()) {
      regexMappingsBuilder.put(Pattern.compile(useRegex ? mapping : Pattern.quote(mapping)),
                               mappings.get(mapping));
    }
    this.regexMappings = regexMappingsBuilder.build();
  }

  /**
   * Returns a description of what this editor will do.
   */
  @Override
  public String getDescription() {
    return String.format("rename step %s", editorName);
  }

  /**
   * Recursively copies files from src to dest, changing the filenames as specified
   * in mappings.
   *
   * @param srcFile  the absolute path of a file to rename and copy or a dir to crawl
   * @param srcFolder  the absolute root of the from folder being crawled
   * @param destFolder  the absolute root of the to folder receiving renamed files
   */
  @VisibleForTesting
  void copyDirectoryAndRename(File srcFile, File srcFolder, File destFolder)
      throws IOException {
    if (AppContext.RUN.fileSystem.isDirectory(srcFile)) {
      File[] files = AppContext.RUN.fileSystem.listFiles(srcFile);
      for (File subFile : files) {
        copyDirectoryAndRename(subFile, srcFolder, destFolder);
      }
    } else {
      // "/srcFolder/path/to/file" -> "path/to/file"
      String relativePath = srcFolder.toURI().relativize(srcFile.toURI()).getPath();
      File renamedFile = new File(destFolder, renameFile(relativePath));
      AppContext.RUN.fileSystem.makeDirsForFile(renamedFile);
      AppContext.RUN.fileSystem.copyFile(srcFile, renamedFile);
    }
  }

  /**
   * Returns the filename according to the rules in mappings.
   *
   * @param inputFilename  the filename to be renamed, relative to the root of the codebase
   *
   * @return the new relative filename
   * @throws MoeProblem  if a mapping for inputFilename could not be found
   */
  String renameFile(String inputFilename) {
    for (Pattern searchExp : regexMappings.keySet()) {
      Matcher matcher = searchExp.matcher(inputFilename);
      if (matcher.find()) {
        String renamed = matcher.replaceFirst(regexMappings.get(searchExp));
        // Erase leading path separators, e.g. when the rule "dir" -> "" maps
        // "dir/filename.txt" to "/filename.txt".
        return SEP_CHAR_MATCHER.trimLeadingFrom(renamed);
      }
    }
    throw new MoeProblem(String.format(
        "Cannot find a rename mapping that covers file %s. "
        + "Every file needs an applicable renaming rule.", inputFilename));
  }

  /**
   * Copies the input Codebase's contents, renaming the files according to this.mappings and
   * returns a new Codebase with the results.
   *
   * @param input the Codebase to edit
   * @param context the ProjectContext for this project
   * @param options a map containing any command line options such as a specific revision
   */
  @Override
  public Codebase edit(Codebase input, ProjectContext context, Map<String, String> options) {
    File tempDir = AppContext.RUN.fileSystem.getTemporaryDirectory("rename_run_");
    try {
      copyDirectoryAndRename(input.getPath().getAbsoluteFile(),
                             input.getPath().getAbsoluteFile(),
                             tempDir.getAbsoluteFile());
    } catch (IOException e) {
      throw new MoeProblem(e.getMessage());
    }
    return new Codebase(tempDir, input.getProjectSpace(), input.getExpression());
  }

  public static RenamingEditor makeRenamingEditor(String editorName, EditorConfig config) {
    if (config.getMappings() == null) {
      throw new MoeProblem(String.format("No mappings object found in the config for editor %s",
          editorName));
    }
    return new RenamingEditor(editorName,
                              RenamingEditor.parseJsonMap(config.getMappings()),
                              config.getUseRegex());
  }

  /**
   * Converts Json representing a map to a Java Map.
   *
   * @param jsonMappings  the JsonObject representing the renaming rules
   */
  static Map<String, String> parseJsonMap(JsonObject jsonMappings) {
    Type type = new TypeToken<Map<String, String>>(){}.getType();
    return new Gson().fromJson(jsonMappings, type);
  }
}
TOP

Related Classes of com.google.devtools.moe.client.editors.RenamingEditor

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.