(file) Return to OptionManager.h CVS log (file) (dir) Up to [Pegasus] / pegasus / src / Pegasus / Common

  1 humberto 1.38 //%/////////////////////////////////////////////////////////////////////////////
  2               //
  3               // Copyright (c) 2000, 2001, 2002 BMC Software, Hewlett-Packard Company, IBM,
  4               // The Open Group, Tivoli Systems
  5               //
  6               // Permission is hereby granted, free of charge, to any person obtaining a copy
  7               // of this software and associated documentation files (the "Software"), to
  8               // deal in the Software without restriction, including without limitation the
  9               // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 10               // sell copies of the Software, and to permit persons to whom the Software is
 11               // furnished to do so, subject to the following conditions:
 12               // 
 13               // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
 14               // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
 15               // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
 16               // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
 17               // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 18               // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 19               // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 20               // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 21               //
 22 humberto 1.38 //==============================================================================
 23               //
 24               // Author: Mike Brasher (mbrasher@bmc.com)
 25               //
 26               // Modified By:	Karl Schopmyer(k.schopmeyer@opengroup.org)
 27               //
 28               //%/////////////////////////////////////////////////////////////////////////////
 29               
 30               //////////////////////////////////////////////////////////////////////////////
 31               // 
 32               // This file defines the classes necessary to manage commandline and 
 33               // configuration file options for Pegasus.  It defines 
 34               //   The OptionManager Class
 35               //   The Option Class - Used to define information about an option
 36               //   The Option Row structure - Used to define option declarations in a 
 37               //	program
 38               //   The optionexcptions Class
 39               //
 40               //////////////////////////////////////////////////////////////////////////////
 41               
 42               #ifndef Pegasus_OptionManager_h
 43 humberto 1.38 #define Pegasus_OptionManager_h
 44               
 45               #include <Pegasus/Common/Config.h>
 46               #include <Pegasus/Common/String.h>
 47               #include <Pegasus/Common/ArrayInternal.h>
 48               #include <Pegasus/Common/InternalException.h>
 49               #include <Pegasus/Common/Linkage.h>
 50               #include <Pegasus/Common/MessageLoader.h>
 51               
 52               PEGASUS_NAMESPACE_BEGIN
 53               
 54               class Option;
 55               struct OptionRow;
 56               
 57               typedef Option* OptionPtr;
 58               
 59               // REVIEW: I seem to remember seeing another class that does something like
 60               // REVIEW: this.
 61               
 62               /** The OptionManager class manages a collection of program options.
 63               
 64 humberto 1.38     <h4>Overview</h4>
 65               
 66                   A program option may be specified in two ways:
 67               
 68                   <ul>
 69               	<li>In a configuration file</li>
 70               	<li>On the command line</li>
 71                   </ul>
 72               
 73                   This class provides methods for merging options from both of these
 74                   sources into a single collection. The following example shows how to
 75                   merge options from a command line into the option manager.
 76               
 77                   <pre>
 78               	int main(int argc, char** argv)
 79               	{
 80               	    OptionManager om;
 81               
 82               	    ...
 83               
 84               	    // Merge options from the command line into the option manager's
 85 humberto 1.38 	    // option list. Remove arguments from command line.
 86               
 87               	    om.mergeCommandLine(argc, argv);
 88               
 89               	    ...
 90               	}
 91                   </pre>
 92               
 93                   Similarly, the OptionManager::mergeFile() method allows options to be
 94                   merged from a file.
 95               
 96                   Before options are merged into the option manager, information on each
 97                   option must be registered with the option manager so that the following
 98                   can be resolved:
 99               
100                   <ul>
101               	<li>The option's name</li>
102               	<li>The default value (to be used if not specified elsewhere)</li>
103               	<li>Whether the option is required</li>
104               	<li>The option's type (e.g., boolean, integer or string)</li>
105               	<li>The domain of the option if any (set of legal values)</li>
106 humberto 1.38 	<li>The name the option as it appears on the command line</li>
107                   </ul>
108               
109                   Here is how to regsiter an option:
110               
111                   <pre>
112               	OptionManager om;
113               
114               	Option* option = new Option("port", "80", false,
115               	    Option::NATURAL_NUMBER, Array<String>(), "p");
116               
117               	om.registerOption(option);
118                   </pre>
119               
120                   The arguments of the Option constructor are the same (and in the same
121                   order) as the list just above. Notice the last argument is "p". This
122                   is the name of the option argument on the command line (it would appear
123                   as "-p" on the command line).
124               
125                   Once options have been registered, the option values may be initialized
126                   using the merge methods described earlier. During merging, certain
127 humberto 1.38     validation is done using the corresponding Option instance described above.
128               
129                   Once options have been merged, they may obtained by calling the
130                   lookupOption() method like this:
131               
132                   <pre>
133               	Option* option = om.lookupOption("port");
134               	String port = option->getValue();
135                   </pre>
136               
137                   Or the lookupValue() convenience function may be used to lookup values:
138               
139                   <pre>
140               	String value;
141               	om.lookupValue("port", value);
142                   </pre>
143                   
144                   Boolean Options can easily be tested as follows:
145                   <pre>
146                   
147                   </pre>
148 humberto 1.38 
149                   <h4>Command Line Options</h4>
150               
151                   mergeCommandLine() like this:
152               
153                   <pre>
154               	om.mergeCommandLine(argc, argv);
155                   </pre>
156               
157                   This method searches the command line for options that match the registered
158                   ones. It will extract those options from the command line (argc and argv
159                   will be modified accordingly).
160               
161                   <h4>Configuration File Otpions</h4>
162               
163                   Options from a configuration file may be merged by calling the mergeFile()
164                   method like this:
165               
166                   <pre>
167               	om.mergeFile(fileName);
168                   </pre>
169 humberto 1.38 
170                   This searches the file for options matching registered ones. Exceptions
171                   are thrown for any unrecognized option names that are encountered.
172               
173                   <h4>Merge Validation</h4>
174               
175                   During merging, the option manager validates the following (using the
176                   information optatined during option registration).
177               
178                   <ul>
179               	<li>The type of the option - whether integer, positive integer,
180               	    or string or whatever.</li>
181               	<li>The domain of the option - whether the supplied option is a legal
182               	    value for that otpion</li>
183               	<li>User extended validation - whether the user overriden
184               	    Option::isValid() returns true when the value is passed to it</li>
185                   </ul>
186               
187                   <h4>Typcial Usage</h4>
188               
189                   The OptionManager is typically used in the following way. First, options
190 humberto 1.38     are registered to establish the valid set of options. Next, values are
191                   merged from the various sources by calling the merge functions. Finally,
192                   checkRequiredOptions() is called to see if any required option values were
193                   not provided.
194                   
195                   <h4>Option Types</h4>
196                   
197                   The option manager allows for several types of options including:
198                   <UL>
199               	<LI> (BOOLEAN)Simple keyword parameters (ex. -t or -h on the command 
200               	line). These are Boolean parameters and there are no additional parameters 
201               	after the keyword.
202               	
203               	<LI> (INTEGER) Numeric parameters - (ex -port 5988). These are 
204               	parameters where a numeric variable follows the parameter defintion.
205                
206               	<LI>(WHOLE_NUMBER) Numeric parameters  ATTN: Finish.
207               	
208               	<LI> (NATURAL_NUMBER Numieric parameters - (ex ). ATTN:	finish
209               	 
210               	<LI>(STRING) String Parameters - (ex. -file abd.log) These are 
211 humberto 1.38 	parameters that are represented by strings following the option 
212               	keyword. No limitations are placed on the string except that it must
213               	be resolvable to a single string.
214               
215               	<LI> (STRING) Domain Parameters - These are parameters where there is 
216               	a choice of keywords from a domain of keywords.	The input parameter may be any 
217               	one of these keywords. Thus, the domain (red blue green) for the 
218               	parameter "color" (-c) could be entered as -c red. The difference 
219               	between String interpretation and domain interpretation is the use of the 
220               	domain fields in the option definition.
221               	
222               	<LI> Mask parameters - These are parameters that define an internal 
223               	bit mask from a set of keywords input.
224               	ATTN: Finish this definition.
225                   </UL>
226               */
227               
228               class PEGASUS_COMMON_LINKAGE OptionManager
229               {
230               public:
231               
232 humberto 1.38     /** Constructor. */
233                   OptionManager();
234               
235                   /** Destructor. Deletes all contained Options. */
236                   ~OptionManager();
237               
238                   /** Registers an option. The OptionManager is responsible for disposing
239               	of the option; the caller must not delete this object.
240               
241               	@param option option to be registerd.
242               	@exception NullPointer exception if option argument is null.
243               	@exception OMDuplicateOption if option already defined.
244                   */
245                   void registerOption(Option* option); 
246                   //        throw(NullPointer, OMDuplicateOption);
247               
248                   /** Provides a simple way to register several options at once using
249               	a declartive style table. This may also be done programmitically
250               	by repeatedly calling registerOption above. See documentation for
251               	OptionRow for details on how to use them.
252                   */
253 humberto 1.38     void registerOptions(OptionRow* options, Uint32 numOptions)
254               	throw (NullPointer);
255               
256                   /** Merge option values from the command line. Searches the command
257               	line for registered options whose names are given by the
258               	Option::getCommandLineOptionName() method. Validation is performed
259               	on each option value obtained by calling Option::isValid(). Valid
260               	option values are set by calling Option::setValue(). The argc and
261               	argv arguments are modified: the option and its argument are
262               	stripped from the command line. The option and its argument have the
263               	following form: -option-name argument. A space must be supplied
264               	between the two. Boolean option arguments are an exception. They
265               	must have the form -option. If they are present, then they are
266               	taken to be true.
267               
268               	&param argc number of argument on the command line.
269               	&param argv list of command line arguments.
270                       &param abortOnErr - Optional Boolean that if true causes exception if there is
271                       a parameter found that is not in the table. Defaults to true
272               	&exception InvalidOptionValue if validation fails.
273               	&exception OMMissingCommandLineOptionArgument
274 humberto 1.38     */
275                   void mergeCommandLine(int& argc, char**& argv, Boolean abortOnErr=true);
276               
277                   /** Merge option values from a file. Searches file for registered options
278               	whose names are given by the options which have been registered.
279               	Validation is performed on each option value by calling
280               	Option::isValid(). Valid option values are set by calling
281               	Option::setValue().
282               
283               	&param fileName name of file to be merged.
284               	&exception NoSuchFile if file cannot be opened.
285               	&exception BadConfigFileOption
286                   */
287                   void mergeFile(const String& fileName);
288               
289                   /** After merging, this method is called to check for required options
290               	that were not merged (specified).
291               
292               	&exception OMMissingRequiredRequiredOption
293                   */
294                   void checkRequiredOptions() const;
295 humberto 1.38 
296                   /** Lookup the option with the given name.
297               	@param Name provides the name of the option.
298               	@return 0 if no such option.
299                   */
300                   const Option* lookupOption(const String& name) const;
301               
302                   /** Lookup value of an option.
303               	@param Name provides the name of the option (ex. "port")
304               	@param String parameter contains the String that contains the
305               	value for this parameter (in String format).
306               	@return Boolean return. True if the option found.
307                   */
308                   Boolean lookupValue(const String& name, String& value ) const;
309               
310                   /** LookupIntegerValue value of an option determines if the value exists
311               	and converts it to integer (Uint32).
312               	@param Name provides the name of the option (ex. "port")
313               	@param String parameter contains the String that contains the
314               	value for this parameter (in String format).
315               	@return Boolean return. True if the option found.
316 humberto 1.38     */
317                   Boolean lookupIntegerValue(const String& name, Uint32& value) const;
318               
319               
320                   /**	isStringInOptionMask - Looks for a String value in an option.
321               	This function is used to detect particular options listed in strings of
322               	entries forming a STRING option.  Thus, for example if the option string
323               	were "abc,def,ijk" in option toy isStringInOption ("toy", "def") returns 
324               	true.
325               	@param option  name of the option in the option table
326               	@param entry  Entry to compare
327               	@return True if the entry String is found in the option.
328                   */
329                   //Uint32 isStringInOptionMask (const String& option, String& entry) const;
330               
331                   /** optionValueEquals - Test the string value of an option.
332               	@param name provides the name of the option (ex. "port")
333               	@param value String value for comparison.
334               	@return true if the option exists and the value of the option 
335               	equals the input parameter value.
336                   */
337 humberto 1.38     Boolean valueEquals(const String& name, const String& value) const;
338               
339                   /** isTrue - determines if a Boolean Option is true or false. Note
340                       that this function simply tests the value for "true" string.
341                       @param name - the name of the opeiton
342                       @return - Returns true if the option value is true.
343                   */
344                   Boolean isTrue(const String& name) const;
345               
346                   /** Print all the options. */
347                   void print() const;
348               
349                   /** Print the help line for all options including cmdline name, name
350                       and the help string
351                   */
352                   void printOptionsHelp() const;
353               
354                   /** Print Complete Help Text message including header before the options help
355                       and trailer after the options help
356                   */
357                   void printOptionsHelpTxt(const String& header, const String& trailer) const;
358 humberto 1.38 
359               
360               private:
361               
362                   /** Lookup the option by its commandLineOptionName.
363               	@return 0 if no such option.
364                   */
365                   Option* _lookupOptionByCommandLineOptionName(const String& name);
366               
367                   Array<Option*> _options;
368               };
369               
370               //////////////////////////////////////////////////////////////////
371               //    OPTION CLASS
372               //////////////////////////////////////////////////////////////////
373               
374               /** The Option class is used to specify information about an Option.
375               
376                   See the OptionManager class for more details.
377               */
378               class PEGASUS_COMMON_LINKAGE Option
379 humberto 1.38 {
380               public:
381               
382                   /** Valid value types. */
383                   enum Type
384                   {
385               	// (..., -3, -2, -1, 0, 1, 2, 3, ...)
386               	INTEGER,
387               
388               	// (1, 2, 3, ...)
389               	NATURAL_NUMBER,
390               
391               	// (0, 1, 2, 3, ...)
392               	WHOLE_NUMBER,
393               
394               	// "true" or "false"
395               	BOOLEAN,
396               
397               	// Anything
398               	STRING
399                   };
400 humberto 1.38 
401                   /** Constructor.
402               
403               	@param optionName the name of this option.
404               
405               	@param defaultValue the default value of this option.
406               
407               	@param required whether the value of this option is required.
408               
409               	@param type type of the value. This is used to validate the value.
410               
411               	@param domain list of legal value for this option. If this list
412               	    is empty, then no domain is enforced.
413               
414               	@param commandLineOptionName name of the corresponding command line
415               	    option (which may be different from the option name).
416               	    
417               	@param optionHelpMessage Text message that defines option. To be used
418               	    in Usage messages.
419                   */
420                   Option(
421 humberto 1.38         const String& optionName,
422                       const String& defaultValue,
423                       Boolean required,
424                       Type type,
425                       const Array<String>& domain = Array<String>(),
426                       const String& commandLineOptionName = String(),
427                       const String& optionHelpMessage = String());
428               
429                   Option(const Option& x);
430               
431                   virtual ~Option();
432               
433                   Option& operator=(const Option& x);
434               
435                   /** Accessor */
436                   const String& getOptionName() const
437                   {
438                       return _optionName;
439                   }
440               
441                   /** Modifier */
442 humberto 1.38     void setOptionName(const String& optionName)
443                   {
444                       _optionName = optionName;
445                   }
446               
447                   /** Accessor */
448                   const String& getDefaultValue() const
449                   {
450                       return _defaultValue;
451                   }
452               
453                   /** Modifier. */
454                   void setDefaultValue(const String& defaultValue)
455                   {
456                       _defaultValue = defaultValue;
457                   }
458               
459                   /** Accessor
460               	@return - Returns string representation of value
461                   */
462                   const String& getValue() const
463 humberto 1.38     {
464                       return _value;
465                   }
466               
467                   /** Modifier */
468                   void setValue(const String& value)
469                   {
470                       _value = value;
471               	_resolved = true;
472                   }
473                   
474                   /** Accessor */
475                   Boolean getRequired() const
476                   {
477                       return _required;
478                   }
479               
480                   /** Modifier */
481                   void setRequired(Boolean required)
482                   {
483                       _required = required;
484 humberto 1.38     }
485               
486                   /** Accessor */
487                   Type getType() const
488                   {
489                       return _type;
490                   }
491               
492                   /** Modifier */
493                   void setType(Type type)
494                   {
495                       _type = type;
496                   }
497               
498                   /** Accessor */
499                   const Array<String>& getDomain() const;
500               
501                   /** Modifier */
502                   void setDomain(const Array<String>& domain);
503               
504                   /** Accessor */
505 humberto 1.38     const String& getCommandLineOptionName() const
506                   {
507                       return _commandLineOptionName;
508                   }
509               
510                   /** Accessor */
511                   const String& getOptionHelpMessage() const
512                   {
513               	return _optionHelpMessage;
514                   }
515               
516                   /** Modifier */
517                   void setCommandLineOptionName(const String& commandLineOptionName)
518                   {
519                       _commandLineOptionName = commandLineOptionName;
520                   }
521               
522                   /** Accesor. Returns true if an option value was ever obtained for
523               	this option.
524                   */
525                   Boolean isResolved() const
526 humberto 1.38     {
527               	return _resolved;
528                   }
529               
530                   /** Checks to see if the given value is valid or not. This method may be
531               	overriden by derived classes to do special purpose validation of the
532               	value. This implementation just checks the domain and type.
533                   */
534                   virtual Boolean isValid(const String& value) const;
535               
536               private:
537                   String _optionName;
538                   String _defaultValue;
539                   String _value;
540                   Boolean _required;
541                   Type _type;
542                   Array<String> _domain;
543                   String _commandLineOptionName;
544                   String _optionHelpMessage;
545                   Boolean _resolved;
546               };
547 humberto 1.38 
548               ///////////////////////////////////////////////////////////////////////
549               //  OptionRow
550               ///////////////////////////////////////////////////////////////////'//
551               
552               /** The OptionRow provides a declarative way of defining Option objects.
553                   For the declarative programming enthusiast, we provide this structure.
554                   It provides a declarative way of defining options for the OptionManager
555                   class. Some developers prefer this since it makes all the options visible
556                   in a kind of table like structure. Here is an example of how it can be
557                   used to define a port number and hostname options. We also show how to
558                   register one of these option lists with an OptionManager.
559               
560                   <pre>
561               	static OptionRow options[] =
562               	{
563               	    { "port", "80", false, Option::NATURAL_NUMBER },
564               	    { "hostname", "", true, Option::STRING }
565               	};
566               
567               	...
568 humberto 1.38 
569               	OptionManager om;
570               	om.registerOptions(options, sizeof(options) / sizeof(options[0]));
571                   </pre>
572               
573                   Recall that static memory areas are initialized with zeros so that the
574                   members that are not initialized explicitly in the example above are
575                   initialized implicitly with zeros (which the OptionManager used to
576                   determine that they are not used).
577               
578                   It is possible to specify domains as well. For example, suppose we
579                   want to define a "color" option that can be in the following set:
580                   {"red", "green", "blue"}. Here is how to express that:
581               
582                   <pre>
583               	static const char* colors[] = { "red", "green", "blue" };
584               	static const Uint32 NUM_COLORS = sizeof(colors) / sizeof(colors[0]);
585               
586               	static OptionRow options[] =
587               	{
588               	    { "color", "red", false, Option::STRING, colors, NUM_COLORS }
589 humberto 1.38 	};
590                   </pre>
591                   When a domain is defined, any of the keywords in that domain are legal 
592                   option keywords.  For example.  With the domain defined above,  a command 
593                   line or config file entry that includes -c blue sets the option "color" to 
594                   blue. Note that this requires a space between -c and blue. 
595                */
596               struct OptionRow
597               {
598                   const char* optionName;
599                   const char* defaultValue;
600                   int required;
601                   Option::Type type;
602                   char** domain;
603                   Uint32 domainSize;
604                   const char* commandLineOptionName;
605                   const char* optionHelpMessage;
606               };
607               /* NOTE: The "required" object must be an int rather than a Boolean because 
608                   bool on some platforms is not defined so that we cannot use a Boolean here 
609                   with a static object.  
610 humberto 1.38 */
611                
612               /** Exception class */
613               class OMMissingCommandLineOptionArgument : public Exception
614               {
615               public:
616               
617               	//l10n
618                   //OMMissingCommandLineOptionArgument(const String& optionName)
619               	//: Exception("Missing command line option argument: " + optionName) { }
620               	OMMissingCommandLineOptionArgument(const String& optionName)
621               	: Exception(MessageLoaderParms("Common.OptionManager.MISSING_CMD_LINE_OPTION",
622 humberto 1.39 											 "Missing command line option argument: $0",
623 humberto 1.38 											 optionName)) { }
624               };
625               
626               /** Exception class */
627               class OMInvalidOptionValue : public Exception
628               {
629               public:
630               
631               	//l10n
632                   //OMInvalidOptionValue(const String& name, const String& value)
633               	//: Exception("Invalid option value: " + name + "=\"" + value + "\"") { }
634               	OMInvalidOptionValue(const String& name, const String& value)
635               	: Exception(MessageLoaderParms("Common.OptionManager.INVALID_OPTION_VALUE",
636               											 "Invalid option value: $0=\"$1\"",
637               											 name,
638               											 value)) { }
639               };
640               
641               /** Exception class */
642               class OMDuplicateOption : public Exception
643               {
644 humberto 1.38 public:
645               //l10n
646                   //OMDuplicateOption(const String& name)
647               	//: Exception("Duplicate option: " + name) { }
648               	OMDuplicateOption(const String& name)
649               	: Exception(MessageLoaderParms("Common.OptionManager.DUPLICATE_OPTION",
650               											 "Duplicate option: $0",
651               											 name)) { }
652               };
653               
654               /** Exception class */
655               class OMConfigFileSyntaxError : public Exception
656               {
657               public:
658               
659                   OMConfigFileSyntaxError(const String& file, Uint32 line)
660               	: Exception(_formatMessage(file, line)) { }
661               
662                   static String _formatMessage(const String& file, Uint32 line);
663               };
664               
665 humberto 1.38 /** Exception class */
666               class OMUnrecognizedConfigFileOption : public Exception
667               {
668               public:
669               //l10n
670                   //OMUnrecognizedConfigFileOption(const String& name)
671               	//: Exception("Unrecognized config file option: " + name) { }
672               	OMUnrecognizedConfigFileOption(const String& name)
673               	: Exception(MessageLoaderParms("Common.OptionManager.UNRECOGNIZED_CONFIG_FILE_OPTION",
674               											 "Unrecognized config file option: $0",
675               											 name)) { }
676               };
677               
678               /** Exception class */
679               class OMMissingRequiredOptionValue : public Exception
680               {
681               public:
682               //l10n
683                   //OMMissingRequiredOptionValue(const String& name)
684               	//: Exception("Missing required option value: " + name) { }
685               	OMMissingRequiredOptionValue(const String& name)
686 humberto 1.38 	: Exception(MessageLoaderParms("Common.OptionManager.MISSING_REQUIRED_OPTION",
687               											 "Missing required option value: $0",
688               											 name)) { }
689               };
690               
691               /** Exception class */
692               class OMMBadCmdLineOption : public Exception
693               {
694               public:
695               //l10n
696                  // OMMBadCmdLineOption(const String& name)
697               	//: Exception("Parameter not Valid: " + name) { }
698               	OMMBadCmdLineOption(const String& name)
699               	: Exception(MessageLoaderParms("Common.OptionManager.PARAMETER_NOT_VALID",
700               											 "Parameter not Valid: $0",
701               											 name)) { }
702               };
703               
704               
705               PEGASUS_NAMESPACE_END
706               
707 humberto 1.38 #endif /* Pegasus_OM_h */

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2