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     */
017    package org.apache.commons.cli2.builder;
018    
019    import java.util.ArrayList;
020    import java.util.List;
021    
022    import org.apache.commons.cli2.Argument;
023    import org.apache.commons.cli2.option.ArgumentImpl;
024    import org.apache.commons.cli2.resource.ResourceConstants;
025    import org.apache.commons.cli2.resource.ResourceHelper;
026    import org.apache.commons.cli2.validation.Validator;
027    
028    /**
029     * Builds Argument instances.
030     */
031    public 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    }