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

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

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2