// Copyright 2015 The Bazel Authors. 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.common.options;

import com.google.common.base.Joiner;
import com.google.common.base.Verify;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Multimap;
import com.google.devtools.build.lib.runtime.proto.InvocationPolicyOuterClass.AllowValues;
import com.google.devtools.build.lib.runtime.proto.InvocationPolicyOuterClass.DisallowValues;
import com.google.devtools.build.lib.runtime.proto.InvocationPolicyOuterClass.FlagPolicy;
import com.google.devtools.build.lib.runtime.proto.InvocationPolicyOuterClass.FlagPolicy.OperationCase;
import com.google.devtools.build.lib.runtime.proto.InvocationPolicyOuterClass.InvocationPolicy;
import com.google.devtools.build.lib.runtime.proto.InvocationPolicyOuterClass.SetValue;
import com.google.devtools.build.lib.runtime.proto.InvocationPolicyOuterClass.UseDefault;
import com.google.devtools.common.options.OptionPriority.PriorityCategory;
import com.google.devtools.common.options.OptionsParser.OptionDescription;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;
import javax.annotation.Nullable;

/**
 * Enforces the {@link FlagPolicy}s (from an {@link InvocationPolicy} proto) on an {@link
 * OptionsParser} by validating and changing the flag values in the given {@link OptionsParser}.
 *
 * <p>"Flag" and "Option" are used interchangeably in this file.
 */
public final class InvocationPolicyEnforcer {

  private static final Logger logger = Logger.getLogger(InvocationPolicyEnforcer.class.getName());

  private static final String INVOCATION_POLICY_SOURCE = "Invocation policy";
  @Nullable private final InvocationPolicy invocationPolicy;
  private final Level loglevel;

  /**
   * Creates an InvocationPolicyEnforcer that enforces the given policy.
   *
   * @param invocationPolicy the policy to enforce. A null policy means this enforcer will do
   *     nothing in calls to enforce().
   */
  public InvocationPolicyEnforcer(@Nullable InvocationPolicy invocationPolicy) {
    this(invocationPolicy, Level.FINE);
  }

  /**
   * Creates an InvocationPolicyEnforcer that enforces the given policy.
   *
   * @param invocationPolicy the policy to enforce. A null policy means this enforcer will do
   *     nothing in calls to enforce().
   * @param loglevel the level at which to log informational statements. Warnings and errors will
   *     still be logged at the appropriate level.
   */
  public InvocationPolicyEnforcer(@Nullable InvocationPolicy invocationPolicy, Level loglevel) {
    this.invocationPolicy = invocationPolicy;
    this.loglevel = loglevel;
  }

  private static final class FlagPolicyWithContext {
    private final FlagPolicy policy;
    private final OptionDescription description;
    private final OptionInstanceOrigin origin;

    public FlagPolicyWithContext(
        FlagPolicy policy, OptionDescription description, OptionInstanceOrigin origin) {
      this.policy = policy;
      this.description = description;
      this.origin = origin;
    }
  }

  public InvocationPolicy getInvocationPolicy() {
    return invocationPolicy;
  }

  /**
   * Applies this OptionsPolicyEnforcer's policy to the given OptionsParser for all blaze commands.
   *
   * @param parser The OptionsParser to enforce policy on.
   * @throws OptionsParsingException if any flag policy is invalid.
   */
  public void enforce(OptionsParser parser) throws OptionsParsingException {
    enforce(parser, null);
  }

  /**
   * Applies this OptionsPolicyEnforcer's policy to the given OptionsParser.
   *
   * @param parser The OptionsParser to enforce policy on.
   * @param command The current blaze command, for flag policies that apply to only specific
   *     commands. Such policies will be enforced only if they contain this command or a command
   *     they inherit from
   * @throws OptionsParsingException if any flag policy is invalid.
   */
  public void enforce(OptionsParser parser, @Nullable String command)
      throws OptionsParsingException {
    if (invocationPolicy == null || invocationPolicy.getFlagPoliciesCount() == 0) {
      return;
    }

    // The effective policy returned is expanded, filtered for applicable commands, and cleaned of
    // redundancies and conflicts.
    List<FlagPolicyWithContext> effectivePolicies =
        getEffectivePolicies(invocationPolicy, parser, command, loglevel);

    for (FlagPolicyWithContext flagPolicy : effectivePolicies) {
      String flagName = flagPolicy.policy.getFlagName();

      OptionValueDescription valueDescription;
      try {
        valueDescription = parser.getOptionValueDescription(flagName);
      } catch (IllegalArgumentException e) {
        // This flag doesn't exist. We are deliberately lenient if the flag policy has a flag
        // we don't know about. This is for better future proofing so that as new flags are added,
        // new policies can use the new flags without worrying about older versions of Bazel.
        logger.log(
            loglevel,
            String.format("Flag '%s' specified by invocation policy does not exist", flagName));
        continue;
      }

      // getOptionDescription() will return null if the option does not exist, however
      // getOptionValueDescription() above would have thrown an IllegalArgumentException if that
      // were the case.
      Verify.verifyNotNull(flagPolicy.description);

      switch (flagPolicy.policy.getOperationCase()) {
        case SET_VALUE:
          applySetValueOperation(parser, flagPolicy, valueDescription, loglevel);
          break;

        case USE_DEFAULT:
          applyUseDefaultOperation(
              parser, "UseDefault", flagPolicy.description.getOptionDefinition(), loglevel);
          break;

        case ALLOW_VALUES:
          AllowValues allowValues = flagPolicy.policy.getAllowValues();
          FilterValueOperation.AllowValueOperation allowValueOperation =
              new FilterValueOperation.AllowValueOperation(loglevel);
          allowValueOperation.apply(
              parser,
              flagPolicy.origin,
              allowValues.getAllowedValuesList(),
              allowValues.hasNewValue() ? allowValues.getNewValue() : null,
              allowValues.hasUseDefault(),
              valueDescription,
              flagPolicy.description);
          break;

        case DISALLOW_VALUES:
          DisallowValues disallowValues = flagPolicy.policy.getDisallowValues();
          FilterValueOperation.DisallowValueOperation disallowValueOperation =
              new FilterValueOperation.DisallowValueOperation(loglevel);
          disallowValueOperation.apply(
              parser,
              flagPolicy.origin,
              disallowValues.getDisallowedValuesList(),
              disallowValues.hasNewValue() ? disallowValues.getNewValue() : null,
              disallowValues.hasUseDefault(),
              valueDescription,
              flagPolicy.description);
          break;

        case OPERATION_NOT_SET:
          throw new PolicyOperationNotSetException(flagName);

        default:
          logger.warning(
              String.format(
                  "Unknown operation '%s' from invocation policy for flag '%s'",
                  flagPolicy.policy.getOperationCase(), flagName));
          break;
      }
    }
  }

  private static class PolicyOperationNotSetException extends OptionsParsingException {
    PolicyOperationNotSetException(String flagName) {
      super(String.format("Flag policy for flag '%s' does not " + "have an operation", flagName));
    }
  }

  private static boolean policyApplies(FlagPolicy policy, ImmutableSet<String> applicableCommands) {
    // Skip the flag policy if it doesn't apply to this command. If the commands list is empty,
    // then the policy applies to all commands.
    if (policy.getCommandsList().isEmpty() || applicableCommands.isEmpty()) {
      return true;
    }

    return !Collections.disjoint(policy.getCommandsList(), applicableCommands);
  }

  /** Returns the expanded and filtered policy that would be enforced for the given command. */
  public static InvocationPolicy getEffectiveInvocationPolicy(
      InvocationPolicy invocationPolicy, OptionsParser parser, String command, Level loglevel)
      throws OptionsParsingException {
    ImmutableList<FlagPolicyWithContext> effectivePolicies =
        getEffectivePolicies(invocationPolicy, parser, command, loglevel);

    InvocationPolicy.Builder builder = InvocationPolicy.newBuilder();
    for (FlagPolicyWithContext policyWithContext : effectivePolicies) {
      builder.addFlagPolicies(policyWithContext.policy);
    }
    return builder.build();
  }

  /**
   * Takes the provided policy and processes it to the form that can be used on the user options.
   *
   * <p>Expands any policies on expansion flags.
   */
  private static ImmutableList<FlagPolicyWithContext> getEffectivePolicies(
      InvocationPolicy invocationPolicy, OptionsParser parser, String command, Level loglevel)
      throws OptionsParsingException {
    if (invocationPolicy == null) {
      return ImmutableList.of();
    }

    ImmutableSet<String> commandAndParentCommands =
        command == null
            ? ImmutableSet.of()
            : CommandNameCache.CommandNameCacheInstance.INSTANCE.get(command);

    // Expand all policies to transfer policies on expansion flags to policies on the child flags.
    List<FlagPolicyWithContext> expandedPolicies = new ArrayList<>();
    OptionPriority nextPriority =
        OptionPriority.lowestOptionPriorityAtCategory(PriorityCategory.INVOCATION_POLICY);
    for (FlagPolicy policy : invocationPolicy.getFlagPoliciesList()) {
      // These policies are high-level, before expansion, and so are not the implicitDependents or
      // expansions of any other flag, other than in an obtuse sense from --invocation_policy.
      OptionPriority currentPriority = nextPriority;
      OptionInstanceOrigin origin =
          new OptionInstanceOrigin(currentPriority, INVOCATION_POLICY_SOURCE, null, null);
      nextPriority = OptionPriority.nextOptionPriority(currentPriority);
      if (!policyApplies(policy, commandAndParentCommands)) {
        // Only keep and expand policies that are applicable to the current command.
        continue;
      }

      OptionDescription optionDescription = parser.getOptionDescription(policy.getFlagName());
      if (optionDescription == null) {
        // InvocationPolicy ignores policy on non-existing flags by design, for version
        // compatibility.
        logger.log(
            loglevel,
            String.format(
                "Flag '%s' specified by invocation policy does not exist, and will be ignored",
                policy.getFlagName()));
        continue;
      }
      FlagPolicyWithContext policyWithContext =
          new FlagPolicyWithContext(policy, optionDescription, origin);
      List<FlagPolicyWithContext> policies = expandPolicy(policyWithContext, parser, loglevel);
      expandedPolicies.addAll(policies);
    }

    // Only keep that last policy for each flag.
    Map<String, FlagPolicyWithContext> effectivePolicy = new HashMap<>();
    for (FlagPolicyWithContext expandedPolicy : expandedPolicies) {
      String flagName = expandedPolicy.policy.getFlagName();
      effectivePolicy.put(flagName, expandedPolicy);
    }

    return ImmutableList.copyOf(effectivePolicy.values());
  }

  private static void throwAllowValuesOnExpansionFlagException(String flagName)
      throws OptionsParsingException {
    throw new OptionsParsingException(
        String.format("Allow_Values on expansion flags like %s is not allowed.", flagName));
  }

  private static void throwDisallowValuesOnExpansionFlagException(String flagName)
      throws OptionsParsingException {
    throw new OptionsParsingException(
        String.format("Disallow_Values on expansion flags like %s is not allowed.", flagName));
  }

  /**
   * Expand a single policy. If the policy is not about an expansion flag, this will simply return a
   * list with a single element, oneself. If the policy is for an expansion flag, the policy will
   * get split into multiple policies applying to each flag the original flag expands to.
   *
   * <p>None of the flagPolicies returned should be on expansion flags.
   */
  private static List<FlagPolicyWithContext> expandPolicy(
      FlagPolicyWithContext originalPolicy,
      OptionsParser parser,
      Level loglevel)
      throws OptionsParsingException {
    List<FlagPolicyWithContext> expandedPolicies = new ArrayList<>();

    boolean isExpansion = originalPolicy.description.isExpansion();
    ImmutableList<ParsedOptionDescription> subflags =
        parser.getExpansionValueDescriptions(
            originalPolicy.description.getOptionDefinition(), originalPolicy.origin);

    // If we have nothing to expand to, no need to do any further work.
    if (subflags.isEmpty()) {
      return ImmutableList.of(originalPolicy);
    }

    if (logger.isLoggable(loglevel)) {
      // Log the expansion. This is only really useful for understanding the invocation policy
      // itself.
      List<String> subflagNames = new ArrayList<>(subflags.size());
      for (ParsedOptionDescription subflag : subflags) {
        subflagNames.add("--" + subflag.getOptionDefinition().getOptionName());
      }

      logger.logp(
          loglevel,
          "InvocationPolicyEnforcer",
          "expandPolicy",
          String.format(
              "Expanding %s on option %s to its %s: %s.",
              originalPolicy.policy.getOperationCase(),
              originalPolicy.policy.getFlagName(),
              isExpansion ? "expansions" : "implied flags",
              Joiner.on("; ").join(subflagNames)));
    }

    // Repeated flags are special, and could set multiple times in an expansion, with the user
    // expecting both values to be valid. Collect these separately.
    Multimap<OptionDescription, ParsedOptionDescription> repeatableSubflagsInSetValues =
        ArrayListMultimap.create();

    // Create a flag policy for the child that looks like the parent's policy "transferred" to its
    // child. Note that this only makes sense for SetValue, when setting an expansion flag, or
    // UseDefault, when preventing it from being set.
    for (ParsedOptionDescription currentSubflag : subflags) {
      OptionDescription subflagOptionDescription =
          parser.getOptionDescription(currentSubflag.getOptionDefinition().getOptionName());

      if (currentSubflag.getOptionDefinition().allowsMultiple()
          && originalPolicy.policy.getOperationCase().equals(OperationCase.SET_VALUE)) {
        repeatableSubflagsInSetValues.put(subflagOptionDescription, currentSubflag);
      } else {
        FlagPolicyWithContext subflagAsPolicy =
            getSingleValueSubflagAsPolicy(
                subflagOptionDescription, currentSubflag, originalPolicy, isExpansion);
        // In case any of the expanded flags are themselves expansions, recurse.
        expandedPolicies.addAll(expandPolicy(subflagAsPolicy, parser, loglevel));
      }
    }

    // If there are any repeatable flag SetValues, deal with them together now.
    // Note that expansion flags have no value, and so cannot have multiple values either.
    // Skipping the recursion above is fine.
    for (OptionDescription repeatableFlag : repeatableSubflagsInSetValues.keySet()) {
      int numValues = repeatableSubflagsInSetValues.get(repeatableFlag).size();
      ArrayList<String> newValues = new ArrayList<>(numValues);
      ArrayList<OptionInstanceOrigin> origins = new ArrayList<>(numValues);
      for (ParsedOptionDescription setValue : repeatableSubflagsInSetValues.get(repeatableFlag)) {
        newValues.add(setValue.getUnconvertedValue());
        origins.add(setValue.getOrigin());
      }
      // These options come from expanding a single policy, so they have effectively the same
      // priority. They could have come from different expansions or implicit requirements in the
      // recursive resolving of the option list, so just pick the first one. Do collapse the source
      // strings though, in case there are different sources.
      OptionInstanceOrigin arbitraryFirstOptionOrigin = origins.get(0);
      OptionInstanceOrigin originOfSubflags =
          new OptionInstanceOrigin(
              arbitraryFirstOptionOrigin.getPriority(),
              origins
                  .stream()
                  .map(OptionInstanceOrigin::getSource)
                  .distinct()
                  .collect(Collectors.joining(", ")),
              arbitraryFirstOptionOrigin.getImplicitDependent(),
              arbitraryFirstOptionOrigin.getExpandedFrom());
      expandedPolicies.add(
          getSetValueSubflagAsPolicy(repeatableFlag, newValues, originOfSubflags, originalPolicy));
    }

    // Don't add the original policy if it was an expansion flag, which have no value, but do add
    // it if there was either no expansion or if it was a valued flag with implicit requirements.
    if (!isExpansion) {
      expandedPolicies.add(originalPolicy);
    }

    return expandedPolicies;
  }

  /**
   * Expand a SetValue flag policy on a repeatable flag. SetValue operations are the only flag
   * policies that set the flag, and so interact with repeatable flags, flags that can be set
   * multiple times, in subtle ways.
   *
   * @param subflagDesc, the description of the flag the SetValue'd expansion flag expands to.
   * @param subflagValue, the values that the SetValue'd expansion flag expands to for this flag.
   * @param originalPolicy, the original policy on the expansion flag.
   * @return the flag policy for the subflag given, this will be part of the expanded form of the
   *     SetValue policy on the original flag.
   */
  private static FlagPolicyWithContext getSetValueSubflagAsPolicy(
      OptionDescription subflagDesc,
      List<String> subflagValue,
      OptionInstanceOrigin subflagOrigin,
      FlagPolicyWithContext originalPolicy) {
    // Some sanity checks.
    OptionDefinition subflag = subflagDesc.getOptionDefinition();
    Verify.verify(originalPolicy.policy.getOperationCase().equals(OperationCase.SET_VALUE));
    if (!subflag.allowsMultiple()) {
      Verify.verify(subflagValue.size() <= 1);
    }

    // Flag value from the expansion, overridability from the original policy, unless the flag is
    // repeatable, in which case we care about appendability, not overridability.
    SetValue.Builder setValueExpansion = SetValue.newBuilder();
    for (String value : subflagValue) {
      setValueExpansion.addFlagValue(value);
    }
    if (subflag.allowsMultiple()) {
      setValueExpansion.setAppend(originalPolicy.policy.getSetValue().getOverridable());
    } else {
      setValueExpansion.setOverridable(originalPolicy.policy.getSetValue().getOverridable());
    }

    // Commands from the original policy, flag name of the expansion
    return new FlagPolicyWithContext(
        FlagPolicy.newBuilder()
            .addAllCommands(originalPolicy.policy.getCommandsList())
            .setFlagName(subflag.getOptionName())
            .setSetValue(setValueExpansion)
            .build(),
        subflagDesc,
        subflagOrigin);
  }

  /**
   * For an expansion flag in an invocation policy, each flag it expands to must be given a
   * corresponding policy.
   */
  private static FlagPolicyWithContext getSingleValueSubflagAsPolicy(
      OptionDescription subflagContext,
      ParsedOptionDescription currentSubflag,
      FlagPolicyWithContext originalPolicy,
      boolean isExpansion)
      throws OptionsParsingException {
    FlagPolicyWithContext subflagAsPolicy = null;
    switch (originalPolicy.policy.getOperationCase()) {
      case SET_VALUE:
        if (currentSubflag.getOptionDefinition().allowsMultiple()) {
          throw new AssertionError(
              "SetValue subflags with allowMultiple should have been dealt with separately and "
                  + "accumulated into a single FlagPolicy.");
        }
        // Accept null originalValueStrings, they are expected when the subflag is also an expansion
        // flag.
        List<String> subflagValue;
        if (currentSubflag.getUnconvertedValue() == null) {
          subflagValue = ImmutableList.of();
        } else {
          subflagValue = ImmutableList.of(currentSubflag.getUnconvertedValue());
        }
        subflagAsPolicy =
            getSetValueSubflagAsPolicy(
                subflagContext, subflagValue, currentSubflag.getOrigin(), originalPolicy);
        break;

      case USE_DEFAULT:
        // Commands from the original policy, flag name of the expansion
        subflagAsPolicy =
            new FlagPolicyWithContext(
                FlagPolicy.newBuilder()
                    .addAllCommands(originalPolicy.policy.getCommandsList())
                    .setFlagName(currentSubflag.getOptionDefinition().getOptionName())
                    .setUseDefault(UseDefault.getDefaultInstance())
                    .build(),
                subflagContext,
                currentSubflag.getOrigin());
        break;

      case ALLOW_VALUES:
        if (isExpansion) {
          throwAllowValuesOnExpansionFlagException(originalPolicy.policy.getFlagName());
        }
        // If this flag is an implicitRequirement, and some values for the parent flag are
        // allowed, nothing needs to happen on the implicitRequirement that is set for all
        // values of the flag.
        break;

      case DISALLOW_VALUES:
        if (isExpansion) {
          throwDisallowValuesOnExpansionFlagException(originalPolicy.policy.getFlagName());
        }
        // If this flag is an implicitRequirement, and some values for the parent flag are
        // disallowed, that implies that all others are allowed, so nothing needs to happen
        // on the implicitRequirement that is set for all values of the parent flag.
        break;

      case OPERATION_NOT_SET:
        throw new PolicyOperationNotSetException(originalPolicy.policy.getFlagName());

      default:
        return null;
    }
    return subflagAsPolicy;
  }

  private static void logInApplySetValueOperation(
      Level loglevel, String formattingString, Object... objects) {
    // Finding the caller here is relatively expensive and shows up in profiling, so provide it
    // manually.
    logger.logp(
        loglevel,
        "InvocationPolicyEnforcer",
        "applySetValueOperation",
        String.format(formattingString, objects));
  }

  private static void applySetValueOperation(
      OptionsParser parser,
      FlagPolicyWithContext flagPolicy,
      OptionValueDescription valueDescription,
      Level loglevel)
      throws OptionsParsingException {
    SetValue setValue = flagPolicy.policy.getSetValue();
    OptionDefinition optionDefinition = flagPolicy.description.getOptionDefinition();

    // SetValue.flag_value must have at least 1 value.
    if (setValue.getFlagValueCount() == 0) {
      throw new OptionsParsingException(
          String.format(
              "SetValue operation from invocation policy for %s does not have a value",
              optionDefinition));
    }

    // Flag must allow multiple values if multiple values are specified by the policy.
    if (setValue.getFlagValueCount() > 1
        && !flagPolicy.description.getOptionDefinition().allowsMultiple()) {
      throw new OptionsParsingException(
          String.format(
              "SetValue operation from invocation policy sets multiple values for %s which "
                  + "does not allow multiple values",
              optionDefinition));
    }

    if (setValue.getOverridable() && valueDescription != null) {
      // The user set the value for the flag but the flag policy is overridable, so keep the user's
      // value.
      logInApplySetValueOperation(
          loglevel,
          "Keeping value '%s' from source '%s' for %s because the invocation policy specifying "
              + "the value(s) '%s' is overridable",
          valueDescription.getValue(),
          valueDescription.getSourceString(),
          optionDefinition,
          setValue.getFlagValueList());
    } else {

      if (!setValue.getAppend()) {
        // Clear the value in case the flag is a repeated flag so that values don't accumulate.
        parser.clearValue(flagPolicy.description.getOptionDefinition());
      }

      // Set all the flag values from the policy.
      for (String flagValue : setValue.getFlagValueList()) {
        if (valueDescription == null) {
          logInApplySetValueOperation(
              loglevel,
              "Setting value for %s from invocation policy to '%s', overriding the default value "
                  + "'%s'",
              optionDefinition,
              flagValue,
              optionDefinition.getDefaultValue());
        } else {
          logInApplySetValueOperation(
              loglevel,
              "Setting value for %s from invocation policy to '%s', overriding value '%s' from "
                  + "'%s'",
              optionDefinition,
              flagValue,
              valueDescription.getValue(),
              valueDescription.getSourceString());
        }

        parser.addOptionValueAtSpecificPriority(flagPolicy.origin, optionDefinition, flagValue);
      }
    }
  }

  private static void applyUseDefaultOperation(
      OptionsParser parser, String policyType, OptionDefinition option, Level loglevel)
      throws OptionsParsingException {
    OptionValueDescription clearedValueDescription = parser.clearValue(option);
    if (clearedValueDescription != null) {
      // Log the removed value.
      String clearedFlagName = clearedValueDescription.getOptionDefinition().getOptionName();
      Object clearedFlagDefaultValue =
          clearedValueDescription.getOptionDefinition().getDefaultValue();
      logger.log(
          loglevel,
          String.format(
              "Using default value '%s' for flag '%s' as specified by %s invocation policy, "
                  + "overriding original value '%s' from '%s'",
              clearedFlagDefaultValue,
              clearedFlagName,
              policyType,
              clearedValueDescription.getValue(),
              clearedValueDescription.getSourceString()));
    }
  }

  /** Checks the user's flag values against a filtering function. */
  private abstract static class FilterValueOperation {

    private static final class AllowValueOperation extends FilterValueOperation {
      AllowValueOperation(Level loglevel) {
        super("Allow", loglevel);
      }

      @Override
      boolean isFlagValueAllowed(Set<Object> convertedPolicyValues, Object value) {
        return convertedPolicyValues.contains(value);
      }
    }

    private static final class DisallowValueOperation extends FilterValueOperation {
      DisallowValueOperation(Level loglevel) {
        super("Disalllow", loglevel);
      }

      @Override
      boolean isFlagValueAllowed(Set<Object> convertedPolicyValues, Object value) {
        // In a disallow operation, the values that the flag policy specifies are not allowed,
        // so the value is allowed if the set of policy values does not contain the current
        // flag value.
        return !convertedPolicyValues.contains(value);
      }
    }

    private final String policyType;
    private final Level loglevel;

    FilterValueOperation(String policyType, Level loglevel) {
      this.policyType = policyType;
      this.loglevel = loglevel;
    }

    /**
     * Determines if the given value is allowed.
     *
     * @param convertedPolicyValues The values given from the FlagPolicy, converted to real objects.
     * @param value The user value of the flag.
     * @return True if the value should be allowed, false if it should not.
     */
    abstract boolean isFlagValueAllowed(Set<Object> convertedPolicyValues, Object value);

    void apply(
        OptionsParser parser,
        OptionInstanceOrigin origin,
        List<String> policyValues,
        String newValue,
        boolean useDefault,
        OptionValueDescription valueDescription,
        OptionDescription optionDescription)
        throws OptionsParsingException {
      OptionDefinition optionDefinition = optionDescription.getOptionDefinition();
      // Convert all the allowed values from strings to real objects using the options'
      // converters so that they can be checked for equality using real .equals() instead
      // of string comparison. For example, "--foo=0", "--foo=false", "--nofoo", and "-f-"
      // (if the option has an abbreviation) are all equal for boolean flags. Plus converters
      // can be arbitrarily complex.
      Set<Object> convertedPolicyValues = new HashSet<>();
      for (String value : policyValues) {
        Object convertedValue = optionDefinition.getConverter().convert(value);
        // Some converters return lists, and if the flag is a repeatable flag, the items in the
        // list from the converter should be added, and not the list itself. Otherwise the items
        // from invocation policy will be compared to lists, which will never work.
        // See OptionsParserImpl.ParsedOptionEntry.addValue.
        if (optionDefinition.allowsMultiple() && convertedValue instanceof List<?>) {
          convertedPolicyValues.addAll((List<?>) convertedValue);
        } else {
          convertedPolicyValues.add(optionDefinition.getConverter().convert(value));
        }
      }

      // Check that if the default value of the flag is disallowed by the policy, that the policy
      // does not also set use_default. Otherwise the default value would will still be set if the
      // user uses a disallowed value. This doesn't apply to repeatable flags since the default
      // value for repeatable flags is always the empty list.
      if (!optionDescription.getOptionDefinition().allowsMultiple()) {

        boolean defaultValueAllowed =
            isFlagValueAllowed(
                convertedPolicyValues, optionDescription.getOptionDefinition().getDefaultValue());
        if (!defaultValueAllowed && useDefault) {
          throw new OptionsParsingException(
              String.format(
                  "%sValues policy disallows the default value '%s' for %s but also specifies to "
                      + "use the default value",
                  policyType, optionDefinition.getDefaultValue(), optionDefinition));
        }
      }

      if (valueDescription == null) {
        // Nothing has set the value yet, so check that the default value from the flag's
        // definition is allowed. The else case below (i.e. valueDescription is not null) checks for
        // the flag allowing multiple values, however, flags that allow multiple values cannot have
        // default values, and their value is always the empty list if they haven't been specified,
        // which is why new_default_value is not a repeated field.
        checkDefaultValue(
            parser, origin, optionDescription, policyValues, newValue, convertedPolicyValues);
      } else {
        checkUserValue(
            parser,
            origin,
            optionDescription,
            valueDescription,
            policyValues,
            newValue,
            useDefault,
            convertedPolicyValues);
      }
    }

    void checkDefaultValue(
        OptionsParser parser,
        OptionInstanceOrigin origin,
        OptionDescription optionDescription,
        List<String> policyValues,
        String newValue,
        Set<Object> convertedPolicyValues)
        throws OptionsParsingException {

      OptionDefinition optionDefinition = optionDescription.getOptionDefinition();
      if (!isFlagValueAllowed(
          convertedPolicyValues, optionDescription.getOptionDefinition().getDefaultValue())) {
        if (newValue != null) {
          // Use the default value from the policy, since the original default is not allowed
          logger.log(
              loglevel,
              String.format(
                  "Overriding default value '%s' for %s with value '%s' specified by invocation "
                      + "policy. %sed values are: %s",
                  optionDefinition.getDefaultValue(),
                  optionDefinition,
                  newValue,
                  policyType,
                  policyValues));
          parser.clearValue(optionDefinition);
          parser.addOptionValueAtSpecificPriority(origin, optionDefinition, newValue);
        } else {
          // The operation disallows the default value, but doesn't supply a new value.
          throw new OptionsParsingException(
              String.format(
                  "Default flag value '%s' for %s is not allowed by invocation policy, but "
                      + "the policy does not provide a new value. %sed values are: %s",
                  optionDescription.getOptionDefinition().getDefaultValue(),
                  optionDefinition,
                  policyType,
                  policyValues));
        }
      }
    }

    void checkUserValue(
        OptionsParser parser,
        OptionInstanceOrigin origin,
        OptionDescription optionDescription,
        OptionValueDescription valueDescription,
        List<String> policyValues,
        String newValue,
        boolean useDefault,
        Set<Object> convertedPolicyValues)
        throws OptionsParsingException {
      OptionDefinition option = optionDescription.getOptionDefinition();
      if (optionDescription.getOptionDefinition().allowsMultiple()) {
        // allowMultiple requires that the type of the option be List<T>, so cast from Object
        // to List<?>.
        List<?> optionValues = (List<?>) valueDescription.getValue();
        for (Object value : optionValues) {
          if (!isFlagValueAllowed(convertedPolicyValues, value)) {
            if (useDefault) {
              applyUseDefaultOperation(parser, policyType + "Values", option, loglevel);
            } else {
              throw new OptionsParsingException(
                  String.format(
                      "Flag value '%s' for %s is not allowed by invocation policy. %sed values "
                          + "are: %s",
                      value, option, policyType, policyValues));
            }
          }
        }

      } else {

        if (!isFlagValueAllowed(convertedPolicyValues, valueDescription.getValue())) {
          if (newValue != null) {
            logger.log(
                loglevel,
                String.format(
                    "Overriding disallowed value '%s' for %s with value '%s' "
                        + "specified by invocation policy. %sed values are: %s",
                    valueDescription.getValue(), option, newValue, policyType, policyValues));
            parser.clearValue(option);
            parser.addOptionValueAtSpecificPriority(origin, option, newValue);
          } else if (useDefault) {
            applyUseDefaultOperation(parser, policyType + "Values", option, loglevel);
          } else {
            throw new OptionsParsingException(
                String.format(
                    "Flag value '%s' for %s is not allowed by invocation policy and the "
                        + "policy does not specify a new value. %sed values are: %s",
                    valueDescription.getValue(), option, policyType, policyValues));
          }
        }
      }
    }
  }
}
