src/jdk.internal.vm.compiler/share/classes/org.graalvm.options/src/org/graalvm/options/OptionType.java
changeset 48861 47f19ff9903c
parent 48860 5bce1b7e7800
child 48862 e13c8c5d9eb3
equal deleted inserted replaced
48860:5bce1b7e7800 48861:47f19ff9903c
     1 /*
       
     2  * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.  Oracle designates this
       
     8  * particular file as subject to the "Classpath" exception as provided
       
     9  * by Oracle in the LICENSE file that accompanied this code.
       
    10  *
       
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    14  * version 2 for more details (a copy is included in the LICENSE file that
       
    15  * accompanied this code).
       
    16  *
       
    17  * You should have received a copy of the GNU General Public License version
       
    18  * 2 along with this work; if not, write to the Free Software Foundation,
       
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    20  *
       
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    22  * or visit www.oracle.com if you need additional information or have any
       
    23  * questions.
       
    24  */
       
    25 package org.graalvm.options;
       
    26 
       
    27 import java.util.HashMap;
       
    28 import java.util.Map;
       
    29 import java.util.Objects;
       
    30 import java.util.function.Consumer;
       
    31 import java.util.function.Function;
       
    32 
       
    33 /**
       
    34  * Represents a type of an option that allows to convert string values to Java values.
       
    35  *
       
    36  * @since 1.0
       
    37  */
       
    38 public final class OptionType<T> {
       
    39 
       
    40     private final String name;
       
    41     private final Function<String, T> stringConverter;
       
    42     private final Consumer<T> validator;
       
    43     private final T defaultValue;
       
    44 
       
    45     /**
       
    46      * Constructs a new option type with name, defaultValue, and function that allows to convert a
       
    47      * string to the option type.
       
    48      *
       
    49      * @param name the name of the type.
       
    50      * @param defaultValue the default value to use if no value is given.
       
    51      * @param stringConverter a function that converts a string value to the option value. Can throw
       
    52      *            {@link IllegalArgumentException} to indicate an invalid string.
       
    53      * @param validator used for validating the option value. Throws
       
    54      *            {@link IllegalArgumentException} if the value is invalid.
       
    55      *
       
    56      * @since 1.0
       
    57      */
       
    58     public OptionType(String name, T defaultValue, Function<String, T> stringConverter, Consumer<T> validator) {
       
    59         Objects.requireNonNull(name);
       
    60         Objects.requireNonNull(stringConverter);
       
    61         Objects.requireNonNull(validator);
       
    62         this.name = name;
       
    63         this.stringConverter = stringConverter;
       
    64         this.defaultValue = defaultValue;
       
    65         this.validator = validator;
       
    66     }
       
    67 
       
    68     /**
       
    69      * Constructs a new option type with name, defaultValue, and function that allows to convert a
       
    70      * string to the option type.
       
    71      *
       
    72      * @param name the name of the type.
       
    73      * @param defaultValue the default value to use if no value is given.
       
    74      * @param stringConverter a function that converts a string value to the option value. Can throw
       
    75      *            {@link IllegalArgumentException} to indicate an invalid string.
       
    76      *
       
    77      * @since 1.0
       
    78      */
       
    79     public OptionType(String name, T defaultValue, Function<String, T> stringConverter) {
       
    80         this(name, defaultValue, stringConverter, new Consumer<T>() {
       
    81             public void accept(T t) {
       
    82             }
       
    83         });
       
    84     }
       
    85 
       
    86     /**
       
    87      * Returns the default value of this type. Used if no value is available.
       
    88      *
       
    89      * @since 1.0
       
    90      */
       
    91     public T getDefaultValue() {
       
    92         return defaultValue;
       
    93     }
       
    94 
       
    95     /**
       
    96      * Returns the name of this type.
       
    97      *
       
    98      * @since 1.0
       
    99      */
       
   100     public String getName() {
       
   101         return name;
       
   102     }
       
   103 
       
   104     /**
       
   105      * Converts a string value, validates it, and converts it to an object of this type.
       
   106      *
       
   107      * @throws IllegalArgumentException if the value is invalid or cannot be converted.
       
   108      * @since 1.0
       
   109      */
       
   110     public T convert(String value) {
       
   111         T v = stringConverter.apply(value);
       
   112         validate(v);
       
   113         return v;
       
   114     }
       
   115 
       
   116     /**
       
   117      * Validates an option value and throws an {@link IllegalArgumentException} if the value is
       
   118      * invalid.
       
   119      *
       
   120      * @throws IllegalArgumentException if the value is invalid or cannot be converted.
       
   121      * @since 1.0
       
   122      */
       
   123     public void validate(T value) {
       
   124         validator.accept(value);
       
   125     }
       
   126 
       
   127     /**
       
   128      * @since 1.0
       
   129      */
       
   130     @Override
       
   131     public String toString() {
       
   132         return "OptionType[name=" + name + ", defaultValue=" + defaultValue + "]";
       
   133     }
       
   134 
       
   135     private static final Map<Class<?>, OptionType<?>> DEFAULTTYPES = new HashMap<>();
       
   136     static {
       
   137         DEFAULTTYPES.put(Boolean.class, new OptionType<>("Boolean", false, new Function<String, Boolean>() {
       
   138             public Boolean apply(String t) {
       
   139                 if ("true".equals(t)) {
       
   140                     return Boolean.TRUE;
       
   141                 } else if ("false".equals(t)) {
       
   142                     return Boolean.FALSE;
       
   143                 } else {
       
   144                     throw new IllegalArgumentException(String.format("Invalid boolean option value '%s'. The value of the option must be '%s' or '%s'.", t, "true", "false"));
       
   145                 }
       
   146             }
       
   147         }));
       
   148         DEFAULTTYPES.put(Byte.class, new OptionType<>("Byte", (byte) 0, new Function<String, Byte>() {
       
   149             public Byte apply(String t) {
       
   150                 try {
       
   151                     return Byte.parseByte(t);
       
   152                 } catch (NumberFormatException e) {
       
   153                     throw new IllegalArgumentException(e.getMessage(), e);
       
   154                 }
       
   155             }
       
   156         }));
       
   157         DEFAULTTYPES.put(Integer.class, new OptionType<>("Integer", 0, new Function<String, Integer>() {
       
   158             public Integer apply(String t) {
       
   159                 try {
       
   160                     return Integer.parseInt(t);
       
   161                 } catch (NumberFormatException e) {
       
   162                     throw new IllegalArgumentException(e.getMessage(), e);
       
   163                 }
       
   164             }
       
   165         }));
       
   166         DEFAULTTYPES.put(Long.class, new OptionType<>("Long", 0L, new Function<String, Long>() {
       
   167             public Long apply(String t) {
       
   168                 try {
       
   169                     return Long.parseLong(t);
       
   170                 } catch (NumberFormatException e) {
       
   171                     throw new IllegalArgumentException(e.getMessage(), e);
       
   172                 }
       
   173             }
       
   174         }));
       
   175         DEFAULTTYPES.put(Float.class, new OptionType<>("Float", 0.0f, new Function<String, Float>() {
       
   176             public Float apply(String t) {
       
   177                 try {
       
   178                     return Float.parseFloat(t);
       
   179                 } catch (NumberFormatException e) {
       
   180                     throw new IllegalArgumentException(e.getMessage(), e);
       
   181                 }
       
   182             }
       
   183         }));
       
   184         DEFAULTTYPES.put(Double.class, new OptionType<>("Double", 0.0d, new Function<String, Double>() {
       
   185             public Double apply(String t) {
       
   186                 try {
       
   187                     return Double.parseDouble(t);
       
   188                 } catch (NumberFormatException e) {
       
   189                     throw new IllegalArgumentException(e.getMessage(), e);
       
   190                 }
       
   191             }
       
   192         }));
       
   193         DEFAULTTYPES.put(String.class, new OptionType<>("String", "0", new Function<String, String>() {
       
   194             public String apply(String t) {
       
   195                 return t;
       
   196             }
       
   197         }));
       
   198     }
       
   199 
       
   200     /**
       
   201      * Returns the default option type for a given value. Returns <code>null</code> if no default
       
   202      * option type is available for the Java type of this value.
       
   203      *
       
   204      * @since 1.0
       
   205      */
       
   206     @SuppressWarnings("unchecked")
       
   207     public static <T> OptionType<T> defaultType(T value) {
       
   208         return defaultType((Class<T>) value.getClass());
       
   209     }
       
   210 
       
   211     /**
       
   212      * Returns the default option type for a class. Returns <code>null</code> if no default option
       
   213      * type is available for this Java type.
       
   214      *
       
   215      * @since 1.0
       
   216      */
       
   217     @SuppressWarnings("unchecked")
       
   218     public static <T> OptionType<T> defaultType(Class<T> clazz) {
       
   219         return (OptionType<T>) DEFAULTTYPES.get(clazz);
       
   220     }
       
   221 
       
   222 }