001    /*
002     * CDDL HEADER START
003     *
004     * The contents of this file are subject to the terms of the
005     * Common Development and Distribution License, Version 1.0 only
006     * (the "License").  You may not use this file except in compliance
007     * with the License.
008     *
009     * You can obtain a copy of the license at
010     * trunk/opends/resource/legal-notices/OpenDS.LICENSE
011     * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
012     * See the License for the specific language governing permissions
013     * and limitations under the License.
014     *
015     * When distributing Covered Code, include this CDDL HEADER in each
016     * file and include the License file at
017     * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
018     * add the following below this CDDL HEADER, with the fields enclosed
019     * by brackets "[]" replaced with your own identifying information:
020     *      Portions Copyright [yyyy] [name of copyright owner]
021     *
022     * CDDL HEADER END
023     *
024     *
025     *      Copyright 2006-2008 Sun Microsystems, Inc.
026     */
027    package org.opends.server.util.args;
028    import org.opends.messages.Message;
029    
030    
031    
032    import static org.opends.messages.UtilityMessages.*;
033    import org.opends.messages.MessageBuilder;
034    
035    
036    /**
037     * This class defines an argument type that will only accept integer values,
038     * and potentially only those in a given range.
039     */
040    public class IntegerArgument
041           extends Argument
042    {
043      // Indicates whether a lower bound will be enforced for this argument.
044      private boolean hasLowerBound;
045    
046      // Indicates whether an upper bound will be enforced for this argument.
047      private boolean hasUpperBound;
048    
049      // The lower bound that will be enforced for this argument.
050      private int lowerBound;
051    
052      // The upper bound that will be enforced for this argument.
053      private int upperBound;
054    
055    
056    
057      /**
058       * Creates a new integer argument with the provided information.
059       *
060       * @param  name              The generic name that should be used to refer to
061       *                           this argument.
062       * @param  shortIdentifier   The single-character identifier for this
063       *                           argument, or <CODE>null</CODE> if there is none.
064       * @param  longIdentifier    The long identifier for this argument, or
065       *                           <CODE>null</CODE> if there is none.
066       * @param  isRequired        Indicates whether this argument must be specified
067       *                           on the command line.
068       * @param  needsValue        Indicates whether this argument requires a value.
069       * @param  valuePlaceholder  The placeholder for the argument value that will
070       *                           be displayed in usage information, or
071       *                           <CODE>null</CODE> if this argument does not
072       *                           require a value.
073       * @param  description       Message for the description of this
074       *                           argument.
075       *
076       * @throws  ArgumentException  If there is a problem with any of the
077       *                             parameters used to create this argument.
078       */
079      public IntegerArgument(String name, Character shortIdentifier,
080                             String longIdentifier, boolean isRequired,
081                             boolean needsValue, Message valuePlaceholder,
082                             Message description)
083             throws ArgumentException
084      {
085        super(name, shortIdentifier, longIdentifier, isRequired, false, needsValue,
086              valuePlaceholder, null, null, description);
087    
088        hasLowerBound = false;
089        hasUpperBound = false;
090        lowerBound    = Integer.MIN_VALUE;
091        upperBound    = Integer.MAX_VALUE;
092      }
093    
094    
095    
096      /**
097       * Creates a new integer argument with the provided information.
098       *
099       * @param  name              The generic name that should be used to refer to
100       *                           this argument.
101       * @param  shortIdentifier   The single-character identifier for this
102       *                           argument, or <CODE>null</CODE> if there is none.
103       * @param  longIdentifier    The long identifier for this argument, or
104       *                           <CODE>null</CODE> if there is none.
105       * @param  isRequired        Indicates whether this argument must be specified
106       *                           on the command line.
107       * @param  needsValue        Indicates whether this argument requires a value.
108       * @param  valuePlaceholder  The placeholder for the argument value that will
109       *                           be displayed in usage information, or
110       *                           <CODE>null</CODE> if this argument does not
111       *                           require a value.
112       * @param  hasLowerBound     Indicates whether a lower bound should be
113       *                           enforced for values of this argument.
114       * @param  lowerBound        The lower bound that should be enforced for
115       *                           values of this argument.
116       * @param  hasUpperBound     Indicates whether an upperbound should be
117       *                           enforced for values of this argument.
118       * @param  upperBound        The upper bound that should be enforced for
119       *                           values of this argument.
120       * @param  description       Message for the description of this
121       *                           argument.
122       *
123       * @throws  ArgumentException  If there is a problem with any of the
124       *                             parameters used to create this argument.
125       */
126      public IntegerArgument(String name, Character shortIdentifier,
127                             String longIdentifier, boolean isRequired,
128                             boolean needsValue, Message valuePlaceholder,
129                             boolean hasLowerBound, int lowerBound,
130                             boolean hasUpperBound, int upperBound,
131                             Message description)
132             throws ArgumentException
133      {
134        super(name, shortIdentifier, longIdentifier, isRequired, false, needsValue,
135              valuePlaceholder, null, null, description);
136    
137        this.hasLowerBound = hasLowerBound;
138        this.hasUpperBound = hasUpperBound;
139        this.lowerBound    = lowerBound;
140        this.upperBound    = upperBound;
141    
142        if (hasLowerBound && hasUpperBound && (lowerBound > upperBound))
143        {
144          Message message = ERR_INTARG_LOWER_BOUND_ABOVE_UPPER_BOUND.get(
145              name, lowerBound, upperBound);
146          throw new ArgumentException(message);
147        }
148      }
149    
150    
151    
152      /**
153       * Creates a new integer argument with the provided information.
154       *
155       * @param  name              The generic name that should be used to refer to
156       *                           this argument.
157       * @param  shortIdentifier   The single-character identifier for this
158       *                           argument, or <CODE>null</CODE> if there is none.
159       * @param  longIdentifier    The long identifier for this argument, or
160       *                           <CODE>null</CODE> if there is none.
161       * @param  isRequired        Indicates whether this argument must be specified
162       *                           on the command line.
163       * @param  isMultiValued     Indicates whether this argument may be specified
164       *                           more than once to provide multiple values.
165       * @param  needsValue        Indicates whether this argument requires a value.
166       * @param  valuePlaceholder  The placeholder for the argument value that will
167       *                           be displayed in usage information, or
168       *                           <CODE>null</CODE> if this argument does not
169       *                           require a value.
170       * @param  defaultValue      The default value that should be used for this
171       *                           argument if none is provided in a properties file
172       *                           or on the command line.  This may be
173       *                           <CODE>null</CODE> if there is no generic default.
174       * @param  propertyName      The name of the property in a property file that
175       *                           may be used to override the default value but
176       *                           will be overridden by a command-line argument.
177       * @param  description       Message for the description of this
178       *                           argument.
179       *
180       * @throws  ArgumentException  If there is a problem with any of the
181       *                             parameters used to create this argument.
182       */
183      public IntegerArgument(String name, Character shortIdentifier,
184                             String longIdentifier, boolean isRequired,
185                             boolean isMultiValued, boolean needsValue,
186                             Message valuePlaceholder, int defaultValue,
187                             String propertyName,
188                             Message description)
189             throws ArgumentException
190      {
191        super(name, shortIdentifier, longIdentifier, isRequired, isMultiValued,
192              needsValue, valuePlaceholder, String.valueOf(defaultValue),
193              propertyName, description);
194    
195        hasLowerBound = false;
196        hasUpperBound = false;
197        lowerBound    = Integer.MIN_VALUE;
198        upperBound    = Integer.MAX_VALUE;
199      }
200    
201    
202    
203      /**
204       * Creates a new integer argument with the provided information.
205       *
206       * @param  name              The generic name that should be used to refer to
207       *                           this argument.
208       * @param  shortIdentifier   The single-character identifier for this
209       *                           argument, or <CODE>null</CODE> if there is none.
210       * @param  longIdentifier    The long identifier for this argument, or
211       *                           <CODE>null</CODE> if there is none.
212       * @param  isRequired        Indicates whether this argument must be specified
213       *                           on the command line.
214       * @param  isMultiValued     Indicates whether this argument may be specified
215       *                           more than once to provide multiple values.
216       * @param  needsValue        Indicates whether this argument requires a value.
217       * @param  valuePlaceholder  The placeholder for the argument value that will
218       *                           be displayed in usage information, or
219       *                           <CODE>null</CODE> if this argument does not
220       *                           require a value.
221       * @param  defaultValue      The default value that should be used for this
222       *                           argument if none is provided in a properties file
223       *                           or on the command line.  This may be
224       *                           <CODE>null</CODE> if there is no generic default.
225       * @param  propertyName      The name of the property in a property file that
226       *                           may be used to override the default value but
227       *                           will be overridden by a command-line argument.
228       * @param  hasLowerBound     Indicates whether a lower bound should be
229       *                           enforced for values of this argument.
230       * @param  lowerBound        The lower bound that should be enforced for
231       *                           values of this argument.
232       * @param  hasUpperBound     Indicates whether an upperbound should be
233       *                           enforced for values of this argument.
234       * @param  upperBound        The upper bound that should be enforced for
235       *                           values of this argument.
236       * @param  description       Message for the description of this
237       *                           argument.
238       *
239       * @throws  ArgumentException  If there is a problem with any of the
240       *                             parameters used to create this argument.
241       */
242      public IntegerArgument(String name, Character shortIdentifier,
243                             String longIdentifier, boolean isRequired,
244                             boolean isMultiValued, boolean needsValue,
245                             Message valuePlaceholder, int defaultValue,
246                             String propertyName, boolean hasLowerBound,
247                             int lowerBound, boolean hasUpperBound, int upperBound,
248                             Message description)
249             throws ArgumentException
250      {
251        super(name, shortIdentifier, longIdentifier, isRequired, isMultiValued,
252              needsValue, valuePlaceholder, String.valueOf(defaultValue),
253              propertyName, description);
254    
255        this.hasLowerBound = hasLowerBound;
256        this.hasUpperBound = hasUpperBound;
257        this.lowerBound    = lowerBound;
258        this.upperBound    = upperBound;
259    
260        if (hasLowerBound && hasUpperBound && (lowerBound > upperBound))
261        {
262          Message message = ERR_INTARG_LOWER_BOUND_ABOVE_UPPER_BOUND.get(
263              name, lowerBound, upperBound);
264          throw new ArgumentException(message);
265        }
266      }
267    
268    
269    
270      /**
271       * Indicates whether a lower bound should be enforced for values of this
272       * argument.
273       *
274       * @return  <CODE>true</CODE> if a lower bound should be enforced for values
275       *          of this argument, or <CODE>false</CODE> if not.
276       */
277      public boolean hasLowerBound()
278      {
279        return hasLowerBound;
280      }
281    
282    
283    
284      /**
285       * Retrieves the lower bound that may be enforced for values of this argument.
286       *
287       * @return  The lower bound that may be enforced for values of this argument.
288       */
289      public int getLowerBound()
290      {
291        return lowerBound;
292      }
293    
294    
295    
296      /**
297       * Indicates whether a upper bound should be enforced for values of this
298       * argument.
299       *
300       * @return  <CODE>true</CODE> if a upper bound should be enforced for values
301       *          of this argument, or <CODE>false</CODE> if not.
302       */
303      public boolean hasUpperBound()
304      {
305        return hasUpperBound;
306      }
307    
308    
309    
310      /**
311       * Retrieves the upper bound that may be enforced for values of this argument.
312       *
313       * @return  The upper bound that may be enforced for values of this argument.
314       */
315      public int getUpperBound()
316      {
317        return upperBound;
318      }
319    
320    
321    
322      /**
323       * Indicates whether the provided value is acceptable for use in this
324       * argument.
325       *
326       * @param  valueString    The value for which to make the determination.
327       * @param  invalidReason  A buffer into which the invalid reason may be
328       *                        written if the value is not acceptable.
329       *
330       * @return  <CODE>true</CODE> if the value is acceptable, or
331       *          <CODE>false</CODE> if it is not.
332       */
333      public boolean valueIsAcceptable(String valueString,
334                                       MessageBuilder invalidReason)
335      {
336        // First, the value must be decodable as an integer.
337        int intValue;
338        try
339        {
340          intValue = Integer.parseInt(valueString);
341        }
342        catch (Exception e)
343        {
344          invalidReason.append(ERR_ARG_CANNOT_DECODE_AS_INT.get(
345                  valueString, getName()));
346          return false;
347        }
348    
349    
350        // If there is a lower bound, then the value must be greater than or equal
351        // to it.
352        if (hasLowerBound && (intValue < lowerBound))
353        {
354          invalidReason.append(ERR_INTARG_VALUE_BELOW_LOWER_BOUND.get(
355                  getName(), intValue, lowerBound));
356          return false;
357        }
358    
359    
360        // If there  is an upper bound, then the value must be less than or equal to
361        // it.
362        if (hasUpperBound && (intValue > upperBound))
363        {
364    
365          invalidReason.append(ERR_INTARG_VALUE_ABOVE_UPPER_BOUND.get(
366                  getName(), intValue, upperBound));
367          return false;
368        }
369    
370    
371        // At this point, the value should be acceptable.
372        return true;
373      }
374    }
375