    001/*
    002  Licensed to the Apache Software Foundation (ASF) under one or more
    003  contributor license agreements.  See the NOTICE file distributed with
    004  this work for additional information regarding copyright ownership.
    005  The ASF licenses this file to You under the Apache License, Version 2.0
    006  (the "License"); you may not use this file except in compliance with
    007  the License.  You may obtain a copy of the License at
    008
    009      https://www.apache.org/licenses/LICENSE-2.0
    010
    011  Unless required by applicable law or agreed to in writing, software
    012  distributed under the License is distributed on an "AS IS" BASIS,
    013  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    014  See the License for the specific language governing permissions and
    015  limitations under the License.
    016 */
    017
    018package org.apache.commons.cli;
    019
    020import java.io.Serializable;
    021import java.util.Collection;
    022import java.util.Iterator;
    023import java.util.LinkedHashMap;
    024import java.util.Map;
    025
    026/**
    027 * A group of mutually exclusive options.
    028 */
    029public class OptionGroup implements Serializable {
    030
    031    /** The serial version UID. */
    032    private static final long serialVersionUID = 1L;
    033
    034    /**
    035     * Maps options where keys are option name and values are the options.
    036     */
    037    private final Map<String, Option> optionMap = new LinkedHashMap<>();
    038
    039    /** The name of the selected option. */
    040    private String selected;
    041
    042    /** Specified whether this group is required. */
    043    private boolean required;
    044
    045    /**
    046     * Constructs a new instance.
    047     */
    048    public OptionGroup() {
    049        // empty
    050    }
    051
    052    /**
    053     * Adds the given {@code Option} to this group.
    054     *
    055     * @param option the option to add to this group.
    056     * @return this option group with the option added.
    057     */
    058    public OptionGroup addOption(final Option option) {
    059        optionMap.put(option.getKey(), option);
    060        return this;
    061    }
    062
    063    /**
    064     * Gets the names of the options in this group as a {@code Collection}.
    065     *
    066     * @return the names of the options in this group as a {@code Collection}.
    067     */
    068    public Collection<String> getNames() {
    069        // the key set is the collection of names
    070        return optionMap.keySet();
    071    }
    072
    073    /**
    074     * Gets the options in this group as a {@code Collection}.
    075     *
    076     * @return the options in this group as a {@code Collection}.
    077     */
    078    public Collection<Option> getOptions() {
    079        // the values are the collection of options
    080        return optionMap.values();
    081    }
    082
    083    /**
    084     * Gets the selected option name.
    085     *
    086     * If the selected option is deprecated <em>no warning is logged</em>.
    087     * @return the selected option name.
    088     */
    089    public String getSelected() {
    090        return selected;
    091    }
    092
    093    /**
    094     * Tests whether this option group is required.
    095     *
    096     * @return whether this option group is required.
    097     */
    098    public boolean isRequired() {
    099        return required;
    100    }
    101
    102    /**
    103     * Tests whether an option is selected.
    104     *
    105     *  If an option is selected and is deprecated <em>no warning is logged</em>.
    106     * @return whether whether an option is selected.
    107     * @since 1.9.0
    108     */
    109    public boolean isSelected() {
    110        return selected != null;
    111    }
    112
    113    /**
    114     * Sets whether this group is required.
    115     *
    116     * @param required whether this group is required.
    117     */
    118    public void setRequired(final boolean required) {
    119        this.required = required;
    120    }
    121
    122    /**
    123     * Sets the selected option of this group to {@code name}.
    124     *
    125     * If the selected option is deprecated <em>no warning is logged</em>.
    126     * @param option the option that is selected.
    127     * @throws AlreadySelectedException if an option from this group has already been selected.
    128     */
    129    public void setSelected(final Option option) throws AlreadySelectedException {
    130        if (option == null) {
    131            // reset the option previously selected
    132            selected = null;
    133            return;
    134        }
    135        // if no option has already been selected or the
    136        // same option is being reselected then set the
    137        // selected member variable
    138        if (selected != null && !selected.equals(option.getKey())) {
    139            throw new AlreadySelectedException(this, option);
    140        }
    141        selected = option.getKey();
    142    }
    143
    144    /**
    145     * Returns the stringified version of this OptionGroup.
    146     *
    147     * @return the stringified representation of this group.
    148     */
    149    @Override
    150    public String toString() {
    151        final StringBuilder buff = new StringBuilder();
    152        final Iterator<Option> iter = getOptions().iterator();
    153        buff.append("[");
    154        while (iter.hasNext()) {
    155            final Option option = iter.next();
    156            if (option.getOpt() != null) {
    157                buff.append("-");
    158                buff.append(option.getOpt());
    159            } else {
    160                buff.append("--");
    161                buff.append(option.getLongOpt());
    162            }
    163
    164            if (option.getDescription() != null) {
    165                buff.append(Char.SP);
    166                buff.append(option.getDescription());
    167            }
    168
    169            if (iter.hasNext()) {
    170                buff.append(", ");
    171            }
    172        }
    173        buff.append("]");
    174        return buff.toString();
    175    }
    176}