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

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

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2