OptionBuilder.java

  1. /*
  2.   Licensed to the Apache Software Foundation (ASF) under one or more
  3.   contributor license agreements.  See the NOTICE file distributed with
  4.   this work for additional information regarding copyright ownership.
  5.   The ASF licenses this file to You under the Apache License, Version 2.0
  6.   (the "License"); you may not use this file except in compliance with
  7.   the License.  You may obtain a copy of the License at

  8.       http://www.apache.org/licenses/LICENSE-2.0

  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.  */

  15. package org.apache.commons.cli;

  16. /**
  17.  * OptionBuilder allows the user to create Options using descriptive methods.
  18.  * <p>
  19.  * Details on the Builder pattern can be found at
  20.  * <a href="https://c2.com/cgi-bin/wiki?BuilderPattern">https://c2.com/cgi-bin/wiki?BuilderPattern</a>.
  21.  * <p>
  22.  * This class is NOT thread safe. See <a href="https://issues.apache.org/jira/browse/CLI-209">CLI-209</a>
  23.  *
  24.  * @since 1.0
  25.  * @deprecated since 1.3, use {@link Option#builder(String)} instead
  26.  */
  27. @Deprecated
  28. public final class OptionBuilder {

  29.     /** Long option */
  30.     private static String longOption;

  31.     /** Option description */
  32.     private static String description;

  33.     /** Argument name */
  34.     private static String argName;

  35.     /** Is required? */
  36.     private static boolean required;

  37.     /** The number of arguments */
  38.     private static int argCount = Option.UNINITIALIZED;

  39.     /** Option type */
  40.     private static Class<?> type;

  41.     /** Option can have an optional argument value */
  42.     private static boolean optionalArg;

  43.     /** Value separator for argument value */
  44.     private static char valueSeparator;

  45.     /** Option builder instance */
  46.     private static final OptionBuilder INSTANCE = new OptionBuilder();

  47.     static {
  48.         // ensure the consistency of the initial values
  49.         reset();
  50.     }

  51.     /**
  52.      * Creates an Option using the current settings
  53.      *
  54.      * @return the Option instance
  55.      * @throws IllegalArgumentException if {@code longOpt} has not been set.
  56.      */
  57.     public static Option create() throws IllegalArgumentException {
  58.         if (longOption == null) {
  59.             reset();
  60.             throw new IllegalArgumentException("must specify longopt");
  61.         }

  62.         return create(null);
  63.     }

  64.     /**
  65.      * Creates an Option using the current settings and with the specified Option {@code char}.
  66.      *
  67.      * @param opt the character representation of the Option
  68.      * @return the Option instance
  69.      * @throws IllegalArgumentException if {@code opt} is not a valid character. See Option.
  70.      */
  71.     public static Option create(final char opt) throws IllegalArgumentException {
  72.         return create(String.valueOf(opt));
  73.     }

  74.     /**
  75.      * Creates an Option using the current settings and with the specified Option {@code char}.
  76.      *
  77.      * @param opt the {@code String} representation of the Option
  78.      * @return the Option instance
  79.      * @throws IllegalArgumentException if {@code opt} is not a valid character. See Option.
  80.      */
  81.     public static Option create(final String opt) throws IllegalArgumentException {
  82.         Option option;
  83.         try {
  84.             // create the option
  85.             option = new Option(opt, description);

  86.             // set the option properties
  87.             option.setLongOpt(longOption);
  88.             option.setRequired(required);
  89.             option.setOptionalArg(optionalArg);
  90.             option.setArgs(argCount);
  91.             option.setType(type);
  92.             option.setConverter(TypeHandler.getDefault().getConverter(type));
  93.             option.setValueSeparator(valueSeparator);
  94.             option.setArgName(argName);
  95.         } finally {
  96.             // reset the OptionBuilder properties
  97.             reset();
  98.         }

  99.         // return the Option instance
  100.         return option;
  101.     }

  102.     /**
  103.      * The next Option created will require an argument value.
  104.      *
  105.      * @return the OptionBuilder instance
  106.      */
  107.     public static OptionBuilder hasArg() {
  108.         argCount = 1;
  109.         return INSTANCE;
  110.     }

  111.     /**
  112.      * The next Option created will require an argument value if {@code hasArg} is true.
  113.      *
  114.      * @param hasArg if true then the Option has an argument value
  115.      * @return the OptionBuilder instance
  116.      */
  117.     public static OptionBuilder hasArg(final boolean hasArg) {
  118.         argCount = hasArg ? 1 : Option.UNINITIALIZED;
  119.         return INSTANCE;
  120.     }

  121.     /**
  122.      * The next Option created can have unlimited argument values.
  123.      *
  124.      * @return the OptionBuilder instance
  125.      */
  126.     public static OptionBuilder hasArgs() {
  127.         argCount = Option.UNLIMITED_VALUES;
  128.         return INSTANCE;
  129.     }

  130.     /**
  131.      * The next Option created can have {@code num} argument values.
  132.      *
  133.      * @param num the number of args that the option can have
  134.      * @return the OptionBuilder instance
  135.      */
  136.     public static OptionBuilder hasArgs(final int num) {
  137.         argCount = num;
  138.         return INSTANCE;
  139.     }

  140.     /**
  141.      * The next Option can have an optional argument.
  142.      *
  143.      * @return the OptionBuilder instance
  144.      */
  145.     public static OptionBuilder hasOptionalArg() {
  146.         argCount = 1;
  147.         optionalArg = true;
  148.         return INSTANCE;
  149.     }

  150.     /**
  151.      * The next Option can have an unlimited number of optional arguments.
  152.      *
  153.      * @return the OptionBuilder instance
  154.      */
  155.     public static OptionBuilder hasOptionalArgs() {
  156.         argCount = Option.UNLIMITED_VALUES;
  157.         optionalArg = true;
  158.         return INSTANCE;
  159.     }

  160.     /**
  161.      * The next Option can have the specified number of optional arguments.
  162.      *
  163.      * @param numArgs   the maximum number of optional arguments the next Option created can have.
  164.      * @return the OptionBuilder instance
  165.      */
  166.     public static OptionBuilder hasOptionalArgs(final int numArgs) {
  167.         argCount = numArgs;
  168.         optionalArg = true;
  169.         return INSTANCE;
  170.     }

  171.     /**
  172.      * The next Option created will be required.
  173.      *
  174.      * @return the OptionBuilder instance
  175.      */
  176.     public static OptionBuilder isRequired() {
  177.         required = true;
  178.         return INSTANCE;
  179.     }

  180.     /**
  181.      * The next Option created will be required if {@code required} is true.
  182.      *
  183.      * @param newRequired if true then the Option is required
  184.      * @return the OptionBuilder instance
  185.      */
  186.     public static OptionBuilder isRequired(final boolean newRequired) {
  187.         required = newRequired;
  188.         return INSTANCE;
  189.     }

  190.     /**
  191.      * Resets the member variables to their default values.
  192.      */
  193.     private static void reset() {
  194.         description = null;
  195.         argName = null;
  196.         longOption = null;
  197.         type = String.class;
  198.         required = false;
  199.         argCount = Option.UNINITIALIZED;
  200.         optionalArg = false;
  201.         valueSeparator = (char) 0;
  202.     }

  203.     /**
  204.      * The next Option created will have the specified argument value name.
  205.      *
  206.      * @param name the name for the argument value
  207.      * @return the OptionBuilder instance
  208.      */
  209.     public static OptionBuilder withArgName(final String name) {
  210.         argName = name;
  211.         return INSTANCE;
  212.     }

  213.     /**
  214.      * The next Option created will have the specified description
  215.      *
  216.      * @param newDescription a description of the Option's purpose
  217.      * @return the OptionBuilder instance
  218.      */
  219.     public static OptionBuilder withDescription(final String newDescription) {
  220.         description = newDescription;
  221.         return INSTANCE;
  222.     }

  223.     /**
  224.      * The next Option created will have the following long option value.
  225.      *
  226.      * @param newLongopt the long option value
  227.      * @return the OptionBuilder instance
  228.      */
  229.     public static OptionBuilder withLongOpt(final String newLongopt) {
  230.         longOption = newLongopt;
  231.         return INSTANCE;
  232.     }

  233.     /**
  234.      * The next Option created will have a value that will be an instance of {@code type}.
  235.      *
  236.      * @param newType the type of the Options argument value
  237.      * @return the OptionBuilder instance
  238.      * @since 1.3
  239.      */
  240.     public static OptionBuilder withType(final Class<?> newType) {
  241.         type = newType;
  242.         return INSTANCE;
  243.     }

  244.     /**
  245.      * The next Option created will have a value that will be an instance of {@code type}.
  246.      * <p>
  247.      * <b>Note:</b> this method is kept for binary compatibility and the input type is supposed to be a {@link Class}
  248.      * object.
  249.      *
  250.      * @param newType the type of the Options argument value
  251.      * @return the OptionBuilder instance
  252.      * @deprecated since 1.3, use {@link #withType(Class)} instead
  253.      */
  254.     @Deprecated
  255.     public static OptionBuilder withType(final Object newType) {
  256.         return withType((Class<?>) newType);
  257.     }

  258.     /**
  259.      * The next Option created uses '{@code =}' as a means to separate argument values.
  260.      *
  261.      * <b>Example:</b>
  262.      *
  263.      * <pre>
  264.      * Option opt = withValueSeparator().create('D');
  265.      *
  266.      * CommandLine line = parser.parse(args);
  267.      * String propertyName = opt.getValue(0);
  268.      * String propertyValue = opt.getValue(1);
  269.      * </pre>
  270.      *
  271.      * @return the OptionBuilder instance
  272.      */
  273.     public static OptionBuilder withValueSeparator() {
  274.         valueSeparator = Char.EQUAL;
  275.         return INSTANCE;
  276.     }

  277.     /**
  278.      * The next Option created uses {@code sep} as a means to separate argument values.
  279.      * <p>
  280.      * <b>Example:</b>
  281.      *
  282.      * <pre>
  283.      * Option opt = OptionBuilder.withValueSeparator('=').create('D');
  284.      *
  285.      * String args = "-Dkey=value";
  286.      * CommandLine line = parser.parse(args);
  287.      * String propertyName = opt.getValue(0); // will be "key"
  288.      * String propertyValue = opt.getValue(1); // will be "value"
  289.      * </pre>
  290.      *
  291.      * @param sep The value separator to be used for the argument values.
  292.      *
  293.      * @return the OptionBuilder instance
  294.      */
  295.     public static OptionBuilder withValueSeparator(final char sep) {
  296.         valueSeparator = sep;
  297.         return INSTANCE;
  298.     }

  299.     /**
  300.      * private constructor to prevent instances being created
  301.      */
  302.     private OptionBuilder() {
  303.         // hide the constructor
  304.     }
  305. }