1// Copyright 2014 The Bazel Authors. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//    http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package com.google.devtools.common.options;
16
17import java.util.Arrays;
18
19/**
20 * A converter superclass for converters that parse enums.
21 *
22 * <p>Just subclass this class, creating a zero argument constructor that
23 * calls {@link #EnumConverter(Class, String)}.
24 *
25 * <p>This class compares the input string to the string returned by the toString()
26 * method of each enum member in a case-insensitive way. Usually, this is the
27 * name of the symbol, but beware if you override toString()!
28 */
29public abstract class EnumConverter<T extends Enum<T>>
30    implements Converter<T> {
31
32  private final Class<T> enumType;
33  private final String typeName;
34
35  /**
36   * Creates a new enum converter. You *must* implement a zero-argument
37   * constructor that delegates to this constructor, passing in the appropriate
38   * parameters.
39   *
40   * @param enumType The type of your enumeration; usually a class literal
41   *                 like MyEnum.class
42   * @param typeName The intuitive name of your enumeration, for example, the
43   *                 type name for CompilationMode might be "compilation mode".
44   */
45  protected EnumConverter(Class<T> enumType, String typeName) {
46    this.enumType = enumType;
47    this.typeName = typeName;
48  }
49
50  /**
51   * Implements {@link #convert(String)}.
52   */
53  @Override
54  public T convert(String input) throws OptionsParsingException {
55    for (T value : enumType.getEnumConstants()) {
56      if (value.toString().equalsIgnoreCase(input)) {
57        return value;
58      }
59    }
60    throw new OptionsParsingException("Not a valid " + typeName + ": '"
61                                      + input + "' (should be "
62                                      + getTypeDescription() + ")");
63  }
64
65  /**
66   * Implements {@link #getTypeDescription()}.
67   */
68  @Override
69  public final String getTypeDescription() {
70    return Converters.joinEnglishList(
71        Arrays.asList(enumType.getEnumConstants())).toLowerCase();
72  }
73
74}
75