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 *     http://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 */
017package org.apache.commons.cli2.builder;
018
019import java.util.ArrayList;
020import java.util.List;
021
022import org.apache.commons.cli2.Argument;
023import org.apache.commons.cli2.option.ArgumentImpl;
024import org.apache.commons.cli2.resource.ResourceConstants;
025import org.apache.commons.cli2.resource.ResourceHelper;
026import org.apache.commons.cli2.validation.Validator;
027
028/**
029 * Builds Argument instances.
030 */
031public class ArgumentBuilder {
032
033    /** i18n */
034    private final static ResourceHelper resources = ResourceHelper.getResourceHelper();
035
036    /** name of the argument. Used for display and lookups in CommandLine */
037    private String name;
038
039    /** description of the argument. Used in the automated online help */
040    private String description;
041
042    /** minimum number of values required */
043    private int minimum;
044
045    /** maximum number of values permitted */
046    private int maximum;
047
048    /** character used to separate the values from the option */
049    private char initialSeparator;
050
051    /** character used to separate the values from each other */
052    private char subsequentSeparator;
053
054    /** object that should be used to ensure the values are valid */
055    private Validator validator;
056
057    /** used to identify the consume remaining option, typically "--" */
058    private String consumeRemaining;
059
060    /** default values for argument */
061    private List defaultValues;
062
063    /** id of the argument */
064    private int id;
065
066    /**
067     * Creates a new ArgumentBuilder instance
068     */
069    public ArgumentBuilder() {
070        reset();
071    }
072
073    /**
074     * Creates a new Argument instance using the options specified in this
075     * ArgumentBuilder.
076     *
077     * @return A new Argument instance using the options specified in this
078     * ArgumentBuilder.
079     */
080    public final Argument create() {
081        final Argument argument =
082            new ArgumentImpl(
083                name,
084                description,
085                minimum,
086                maximum,
087                initialSeparator,
088                subsequentSeparator,
089                validator,
090                consumeRemaining,
091                defaultValues,
092                id);
093
094        reset();
095
096        return argument;
097    }
098
099    /**
100     * Resets the ArgumentBuilder to the defaults for a new Argument. The
101     * method is called automatically at the end of a create() call.
102     * @return this ArgumentBuilder
103     */
104    public final ArgumentBuilder reset() {
105        name = "arg";
106        description = null;
107        minimum = 0;
108        maximum = Integer.MAX_VALUE;
109        initialSeparator = ArgumentImpl.DEFAULT_INITIAL_SEPARATOR;
110        subsequentSeparator = ArgumentImpl.DEFAULT_SUBSEQUENT_SEPARATOR;
111        validator = null;
112        consumeRemaining = "--";
113        defaultValues = null;
114        id = 0;
115        return this;
116    }
117
118    /**
119     * Sets the name of the argument. The name is used when displaying usage
120     * information and to allow lookups in the CommandLine object.
121     *
122     * @see org.apache.commons.cli2.CommandLine#getValue(String)
123     *
124     * @param newName the name of the argument
125     * @return this ArgumentBuilder
126     */
127    public final ArgumentBuilder withName(final String newName) {
128        if (newName == null) {
129            throw new IllegalArgumentException(resources.getMessage(ResourceConstants.ARGUMENT_BUILDER_NULL_NAME));
130        }
131        if ("".equals(newName)) {
132            throw new IllegalArgumentException(resources.getMessage(ResourceConstants.ARGUMENT_BUILDER_EMPTY_NAME));
133        }
134        this.name = newName;
135        return this;
136    }
137
138    /**
139     * Sets the description of the argument.
140     *
141     * The description is used when displaying online help.
142     *
143     * @param newDescription a description of the argument
144     * @return this ArgumentBuilder
145     */
146    public final ArgumentBuilder withDescription(final String newDescription) {
147        this.description = newDescription;
148        return this;
149    }
150
151    /**
152     * Sets the minimum number of values needed for the argument to be valid.
153     *
154     * @param newMinimum the number of values needed
155     * @return this ArgumentBuilder
156     */
157    public final ArgumentBuilder withMinimum(final int newMinimum) {
158        if (newMinimum < 0) {
159            throw new IllegalArgumentException(resources.getMessage(ResourceConstants.ARGUMENT_BUILDER_NEGATIVE_MINIMUM));
160        }
161        this.minimum = newMinimum;
162        return this;
163    }
164
165    /**
166     * Sets the maximum number of values allowed for the argument to be valid.
167     *
168     * @param newMaximum the number of values allowed
169     * @return this ArgumentBuilder
170     */
171    public final ArgumentBuilder withMaximum(final int newMaximum) {
172        if (newMaximum < 0) {
173            throw new IllegalArgumentException(resources.getMessage(ResourceConstants.ARGUMENT_BUILDER_NEGATIVE_MAXIMUM));
174        }
175        this.maximum = newMaximum;
176        return this;
177    }
178
179    /**
180     * Sets the character used to separate the values from the option. When an
181     * argument is of the form -libs:dir1,dir2,dir3 the initialSeparator would
182     * be ':'.
183     *
184     * @param newInitialSeparator the character used to separate the values
185     * from the option
186     * @return this ArgumentBuilder
187     */
188    public final ArgumentBuilder withInitialSeparator(
189        final char newInitialSeparator) {
190
191        this.initialSeparator = newInitialSeparator;
192        return this;
193    }
194
195    /**
196     * Sets the character used to separate the values from each other. When an
197     * argument is of the form -libs:dir1,dir2,dir3 the subsequentSeparator
198     * would be ','.
199     *
200     * @param newSubsequentSeparator the character used to separate the values
201     * from each other
202     * @return this ArgumentBuilder
203     */
204    public final ArgumentBuilder withSubsequentSeparator(
205        final char newSubsequentSeparator) {
206
207        this.subsequentSeparator = newSubsequentSeparator;
208        return this;
209    }
210
211    /**
212     * Sets the validator instance used to perform validation on the Argument
213     * values.
214     *
215     * @param newValidator a Validator instance
216     * @return this ArgumentBuilder
217     */
218    public final ArgumentBuilder withValidator(final Validator newValidator) {
219        if (newValidator == null) {
220            throw new IllegalArgumentException(resources.getMessage(ResourceConstants.ARGUMENT_BUILDER_NULL_VALIDATOR));
221        }
222        this.validator = newValidator;
223        return this;
224    }
225
226    /**
227     * Sets the "consume remaining" option, defaults to "--". Use this if you
228     * want to allow values that might be confused with option strings.
229     *
230     * @param newConsumeRemaining the string to use for the consume
231     * remaining option
232     * @return this ArgumentBuilder
233     */
234    public final ArgumentBuilder withConsumeRemaining(final String newConsumeRemaining) {
235        if (newConsumeRemaining == null) {
236            throw new IllegalArgumentException(resources.getMessage(ResourceConstants.ARGUMENT_BUILDER_NULL_CONSUME_REMAINING));
237        }
238        if ( "".equals(newConsumeRemaining)) {
239            throw new IllegalArgumentException(resources.getMessage(ResourceConstants.ARGUMENT_BUILDER_EMPTY_CONSUME_REMAINING));
240        }
241        this.consumeRemaining = newConsumeRemaining;
242        return this;
243    }
244
245    /**
246     * Sets the default value.
247     *
248     * @param defaultValue the default value for the Argument
249     * @return this ArgumentBuilder
250     */
251    public final ArgumentBuilder withDefault(final Object defaultValue) {
252        if (defaultValue == null) {
253            throw new IllegalArgumentException(resources.getMessage(ResourceConstants.ARGUMENT_BUILDER_NULL_DEFAULT));
254        }
255
256        if (this.defaultValues == null) {
257            this.defaultValues = new ArrayList(1);
258        }
259        this.defaultValues.add(defaultValue);
260        return this;
261    }
262
263    /**
264     * Sets the default values.
265     *
266     * @param newDefaultValues the default values for the Argument
267     * @return this ArgumentBuilder
268     */
269    public final ArgumentBuilder withDefaults(final List newDefaultValues) {
270        if (newDefaultValues == null) {
271            throw new IllegalArgumentException(resources.getMessage(ResourceConstants.ARGUMENT_BUILDER_NULL_DEFAULTS));
272        }
273        this.defaultValues = newDefaultValues;
274        return this;
275    }
276
277    /**
278     * Sets the id
279     *
280     * @param newId the id of the Argument
281     * @return this ArgumentBuilder
282     */
283    public final ArgumentBuilder withId(final int newId) {
284        this.id = newId;
285        return this;
286    }
287}