// Copyright 2014 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.devtools.build.lib.runtime.commands;

import com.google.devtools.build.lib.events.Event;
import com.google.devtools.build.lib.runtime.BlazeCommand;
import com.google.devtools.build.lib.runtime.BlazeCommandUtils;
import com.google.devtools.build.lib.runtime.BlazeRuntime;
import com.google.devtools.build.lib.runtime.Command;
import com.google.devtools.build.lib.util.ExitCode;
import com.google.devtools.common.options.Converter;
import com.google.devtools.common.options.Option;
import com.google.devtools.common.options.OptionsBase;
import com.google.devtools.common.options.OptionsParser;
import com.google.devtools.common.options.OptionsParsingException;
import com.google.devtools.common.options.OptionsProvider;

import java.util.Collection;
import java.util.List;

/**
 * The 'blaze canonicalize-flags' command.
 */
@Command(name = "canonicalize-flags",
         options = { CanonicalizeCommand.Options.class },
         allowResidue = true,
         mustRunInWorkspace = false,
         shortDescription = "Canonicalizes a list of %{product} options.",
         help = "This command canonicalizes a list of %{product} options. Don't forget to prepend "
             + " '--' to end option parsing before the flags to canonicalize.\n"
             + "%{options}")
public final class CanonicalizeCommand implements BlazeCommand {

  public static class CommandConverter implements Converter<String> {

    @Override
    public String convert(String input) throws OptionsParsingException {
      if (input.equals("build")) {
        return input;
      } else if (input.equals("test")) {
        return input;
      }
      throw new OptionsParsingException("Not a valid command: '" + input + "' (should be "
          + getTypeDescription() + ")");
    }

    @Override
    public String getTypeDescription() {
      return "build or test";
    }
  }

  public static class Options extends OptionsBase {

    @Option(name = "for_command",
            defaultValue = "build",
            category = "misc",
            converter = CommandConverter.class,
            help = "The command for which the options should be canonicalized.")
    public String forCommand;
  }

  @Override
  public ExitCode exec(BlazeRuntime runtime, OptionsProvider options) {
    BlazeCommand command = runtime.getCommandMap().get(
        options.getOptions(Options.class).forCommand);
    Collection<Class<? extends OptionsBase>> optionsClasses =
        BlazeCommandUtils.getOptions(
            command.getClass(), runtime.getBlazeModules(), runtime.getRuleClassProvider());
    try {
      List<String> result = OptionsParser.canonicalize(optionsClasses, options.getResidue());
      for (String piece : result) {
        runtime.getReporter().getOutErr().printOutLn(piece);
      }
    } catch (OptionsParsingException e) {
      runtime.getReporter().handle(Event.error(e.getMessage()));
      return ExitCode.COMMAND_LINE_ERROR;
    }
    return ExitCode.SUCCESS;
  }

  @Override
  public void editOptions(BlazeRuntime runtime, OptionsParser optionsParser) {}
}

@@ -658,16 +658,54 @@
 mands;%0A%0A
+import com.google.common.base.Joiner;%0A
 import c
@@ -747,16 +747,16 @@
 .Event;%0A
-
 import c
@@ -1039,61 +1039,8 @@
 de;%0A
-import com.google.devtools.common.options.Converter;%0A
 impo
@@ -1946,529 +1946,8 @@
  %7B%0A%0A
-  public static class CommandConverter implements Converter%3CString%3E %7B%0A%0A    @Override%0A    public String convert(String input) throws OptionsParsingException %7B%0A      if (input.equals(%22build%22)) %7B%0A        return input;%0A      %7D else if (input.equals(%22test%22)) %7B%0A        return input;%0A      %7D%0A      throw new OptionsParsingException(%22Not a valid command: '%22 + input + %22' (should be %22%0A          + getTypeDescription() + %22)%22);%0A    %7D%0A%0A    @Override%0A    public String getTypeDescription() %7B%0A      return %22build or test%22;%0A    %7D%0A  %7D%0A%0A
   pu
@@ -1994,17 +1994,16 @@
 sBase %7B%0A
-%0A
     @Opt
@@ -2099,56 +2099,8 @@
 c%22,%0A
-            converter = CommandConverter.class,%0A
     
@@ -2303,114 +2303,405 @@
     
-BlazeCommand command = runtime.getCommandMap().get(%0A        options.getOptions(Options.class).forCommand);
+String commandName = options.getOptions(Options.class).forCommand;%0A    BlazeCommand command = runtime.getCommandMap().get(commandName);%0A    if (command == null) %7B%0A      runtime.getReporter().handle(Event.error(%22Not a valid command: '%22 + commandName%0A          + %22' (should be one of %22 + Joiner.on(%22, %22).join(runtime.getCommandMap().keySet()) + %22)%22));%0A      return ExitCode.COMMAND_LINE_ERROR;%0A    %7D
 %0A   

Allow canonicalize-flags to run for any command.