(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 mike  1.10 // Modified By:
 25 mike  1.9  //
 26 mike  1.10 //%/////////////////////////////////////////////////////////////////////////////
 27 mike  1.1  
 28            #ifndef Pegasus_OptionManager_h
 29            #define Pegasus_OptionManager_h
 30            
 31            #include <Pegasus/Common/Config.h>
 32            #include <Pegasus/Common/String.h>
 33            #include <Pegasus/Common/Array.h>
 34 mike  1.4  #include <Pegasus/Common/Exception.h>
 35 mike  1.1  
 36            PEGASUS_NAMESPACE_BEGIN
 37            
 38            class Option;
 39 mike  1.5  struct OptionRow;
 40 mike  1.1  
 41            /** The OptionManager class manages a collection of program options. 
 42            
 43                <h4>Overview</h4>
 44            
 45 mike  1.9      A program option may be specified in two ways:
 46 mike  1.1  
 47                <ul>
 48            	<li>In a configuration file</li>
 49            	<li>On the command line</li>
 50                </ul>
 51            
 52 mike  1.9      This class provides methods for merging options from both of these 
 53                sources into a single collection. The following example shows how to 
 54                merge options from a command line into the option manager.
 55 mike  1.1  
 56                <pre>
 57            	int main(int argc, char** argv)
 58            	{
 59            	    OptionManager om;
 60            
 61            	    ...
 62            
 63            	    // Merge options from the command line into the option manager's
 64            	    // option list. Remove arguments from command line.
 65            
 66            	    om.mergeCommandLine(argc, argv);
 67            
 68            	    ...
 69            	}
 70                </pre>
 71            
 72 mike  1.9      Similarly, the OptionManager::mergeFile() method allows options to be
 73                merged from a file.
 74 mike  1.1  
 75                Before options are merged into the option manager, information on each
 76                option must be registered with the option manager so that the following
 77                can be resolved:
 78            
 79                <ul>
 80            	<li>The option's name</li>
 81            	<li>The default value (to be used if not specified elsewhere)</li>
 82            	<li>Whether the option is required</li>
 83 mike  1.2  	<li>The option's type (e.g., boolean, integer or string)</li>
 84 mike  1.1  	<li>The domain of the option if any (set of legal values)</li>
 85            	<li>The name the option as it appears on the command line</li>
 86                </ul>
 87            
 88                Here is how to regsiter an option:
 89            
 90                <pre>
 91            	OptionManager om;
 92            
 93 mike  1.9  	Option* option = new Option("port", "80", false, 
 94            	    Option::NATURAL_NUMBER, Array<String>(), "p");
 95 mike  1.1  
 96            	om.registerOption(option);
 97                </pre>
 98            
 99                The arguments of the Option constructor are the same (and in the same
100 mike  1.9      order) as the list just above. Notice the last argument is "p". This
101                is the name of the option argument on the command line (it would appear
102                as "-p" on the command line).
103            
104                Once options have been registered, the option values may be initialized 
105                using the merge methods described earlier. During merging, certain 
106                validation is done using the corresponding Option instance described above.
107 mike  1.1  
108                Once options have been merged, they may obtained by calling the 
109                lookupOption() method like this:
110                
111                <pre>
112            	Option* option = om.lookupOption("port");
113 mike  1.9  	String port = option->getValue();
114                </pre>
115 mike  1.1  
116 mike  1.9      Or the lookupValue() convenience function may be used to lookup values:
117            
118                <pre>
119            	String value;
120            	om.lookupValue("port", value);
121 mike  1.1      </pre>
122            
123                <h4>Command Line Options</h4>
124            
125                mergeCommandLine() like this:
126            
127                <pre>
128            	om.mergeCommandLine(argc, argv);
129                </pre>
130                
131                This method searches the command line for options that match the registered 
132                ones. It will extract those options from the command line (argc and argv 
133                will be modified accordingly).
134            
135                <h4>Configuration File Otpions</h4>
136            
137                Options from a configuration file may be merged by calling the mergeFile() 
138                method like this:
139            
140                <pre>
141            	om.mergeFile(fileName);
142 mike  1.1      </pre>
143            
144                This searches the file for options matching registered ones. Exceptions
145                are thrown for any unrecognized option names that are encountered.
146            
147                <h4>Merge Validation</h4>
148            
149                During merging, the option manager validates the following (using the 
150                information optatined during option registration).
151            
152                <ul>
153            	<li>The type of the option - whether integer, positive integer,
154 mike  1.9  	    or string or whatever.</li>
155 mike  1.1  	<li>The domain of the option - whether the supplied option is a legal
156            	    value for that otpion</li>
157            	<li>User extended validation - whether the user overriden 
158            	    Option::isValid() returns true when the value is passed to it</li>
159                </ul>
160 mike  1.2  
161                <h4>Typcial Usage</h4>
162            
163                The OptionManager is typically used in the following way. First, options
164                are registered to establish the valid set of options. Next, values are
165                merged from the various sources by calling the merge functions. Finally,
166                checkRequiredOptions() is called to see if any required option values were
167                not provided.
168 mike  1.1  */
169 mike  1.2  class PEGASUS_COMMON_LINKAGE OptionManager
170 mike  1.1  {
171            public:
172            
173                /** Constructor. */
174                OptionManager();
175            
176                /** Destructor. Deletes all contained Options. */
177                ~OptionManager();
178            
179                /** Registers an option. The OptionManager is responsible for disposing
180            	of the option; the caller must not delete this object.
181            
182 mike  1.8  	@param option option to be registerd.
183 mike  1.7  	@exception NullPointer exception if option argument is null.
184            	@exception DuplicateOption if option already defined.
185 mike  1.5      */
186                void registerOption(Option* option);
187            
188                /** Provides a simple way to register several options at once using
189            	a declartive style table. This may also be done programmitically
190            	by repeatedly calling registerOption above. See documentation for
191            	OptionRow for details on how to use them.
192 mike  1.1      */
193 mike  1.5      void registerOptions(OptionRow* options, Uint32 numOptions);
194 mike  1.1  
195                /** Merge option values from the command line. Searches the command 
196            	line for registered options whose names are given by the
197            	Option::getCommandLineOptionName() method. Validation is performed
198            	on each option value obtained by calling Option::isValid(). Valid
199            	option values are set by calling Option::setValue(). The argc and
200            	argv arguments are modified: the option and its argument are 
201            	stripped from the command line. The option and its argument have the
202            	following form: -option-name argument. A space must be supplied
203            	between the two. Boolean option arguments are an exception. They
204            	must have the form -option. If they are present, then they are
205            	taken to be true.
206            
207 mike  1.8  	&param argc number of argument on the command line.
208            	&param argv list of command line arguments.
209 mike  1.7  	&exception InvalidOptionValue if validation fails.
210            	&exception MissingCommandLineOptionArgument
211 mike  1.1      */
212                void mergeCommandLine(int& argc, char**& argv);
213            
214                /** Merge option values from a file. Searches file for registered options
215 mike  1.9  	whose names are given by the options which have been registered.
216            	Validation is performed on each option value by calling 
217 mike  1.1  	Option::isValid(). Valid option values are set by calling 
218            	Option::setValue().
219            
220 mike  1.8  	&param fileName name of file to be merged.
221 mike  1.7  	&exception NoSuchFile if file cannot be opened.
222            	&exception BadConfigFileOption
223 mike  1.1      */
224                void mergeFile(const String& fileName);
225            
226                /** After merging, this method is called to check for required options
227            	that were not merged (specified).
228            
229 mike  1.9  	&exception MissingRequiredRequiredOption
230 mike  1.1      */
231                void checkRequiredOptions() const;
232            
233 mike  1.2      /** Lookup the option with the given name.
234 mike  1.4  	@return 0 if no such option.
235 mike  1.2      */
236 mike  1.4      const Option* lookupOption(const String& name) const;
237 mike  1.3  
238 mike  1.6      /** Lookup value of an option.
239                */
240                Boolean lookupValue(const String& name, String& value) const;
241            
242 mike  1.3      /** Print all the options. */
243                void print() const;
244 mike  1.2  
245 mike  1.1  private:
246            
247 mike  1.4      /** Lookup the option by its commandLineOptionName.
248            	@return 0 if no such option.
249                */
250                Option* _lookupOptionByCommandLineOptionName(const String& name);
251            
252 mike  1.1      Array<Option*> _options;
253            };
254            
255            /** The Option class is used to specify information about an Option.
256            
257                See the OptionManager class for more details.
258            */
259 mike  1.2  class PEGASUS_COMMON_LINKAGE Option
260 mike  1.1  {
261            public:
262            
263                /** Valid value types. */
264 mike  1.5      enum Type 
265                {
266            	// (..., -3, -2, -1, 0, 1, 2, 3, ...)
267            	INTEGER, 
268            
269            	// (1, 2, 3, ...)
270            	NATURAL_NUMBER, 
271            
272            	// (0, 1, 2, 3, ...)
273            	WHOLE_NUMBER, 
274            
275            	// "true" or "false"
276            	BOOLEAN, 
277            
278            	// Anything
279            	STRING
280                };
281 mike  1.1  
282                // Hack to fix bug in MSVC.
283                typedef Array<String> StringArray;
284            
285                /** Constructor.
286            
287 mike  1.8  	@param optionName the name of this option.
288 mike  1.1  
289 mike  1.8  	@param defaultValue the default value of this option.
290 mike  1.1  
291 mike  1.8  	@param required whether the value of this option is required.
292 mike  1.1  
293 mike  1.8  	@param type type of the value. This is used to validate the value.
294 mike  1.1  
295 mike  1.8  	@param domain list of legal value for this option. If this list
296 mike  1.1  	    is empty, then no domain is enforced.
297            
298 mike  1.8  	@param commandLineOptionName name of the corresponding command line
299 mike  1.1  	    option (which may be different from the option name).
300                */
301                Option(
302                    const String& optionName,
303                    const String& defaultValue,
304                    Boolean required,
305                    Type type,
306                    const StringArray& domain = StringArray(),
307 mike  1.2          const String& commandLineOptionName = String());
308            
309                Option(const Option& x);
310 mike  1.1  
311                virtual ~Option();
312            
313 mike  1.2      Option& operator=(const Option& x);
314 mike  1.1  
315                /** Accessor */
316                const String& getOptionName() const
317                {
318                    return _optionName;
319                }
320            
321                /** Modifier */
322                void setOptionName(const String& optionName)
323                {
324                    _optionName = optionName;
325                }
326            
327                /** Accessor */
328                const String& getDefaultValue() const
329                {
330                    return _defaultValue;
331                }
332            
333                /** Modifier. */
334                void setDefaultValue(const String& defaultValue)
335 mike  1.1      {
336                    _defaultValue = defaultValue;
337                }
338            
339                /** Accessor */
340                const String& getValue() const
341                {
342                    return _value;
343                }
344            
345                /** Modifier */
346                void setValue(const String& value)
347                {
348                    _value = value;
349 mike  1.9  	_resolved = true;
350 mike  1.1      }
351            
352                /** Accessor */
353                Boolean getRequired() const
354                {
355                    return _required;
356                }
357            
358                /** Modifier */
359                void setRequired(Boolean required)
360                {
361                    _required = required;
362                }
363            
364                /** Accessor */
365                Type getType() const
366                {
367                    return _type;
368                }
369            
370                /** Modifier */
371 mike  1.1      void setType(Type type)
372                {
373                    _type = type;
374                }
375            
376                /** Accessor */
377                const StringArray& getDomain() const
378                {
379                    return _domain;
380                }
381            
382                /** Modifier */
383                void setDomain(const StringArray& domain)
384                {
385                    _domain = domain;
386                }
387            
388                /** Accessor */
389                const String& getCommandLineOptionName() const
390                {
391                    return _commandLineOptionName;
392 mike  1.1      }
393            
394                /** Modifier */
395                void setCommandLineOptionName(const String& commandLineOptionName)
396                {
397                    _commandLineOptionName = commandLineOptionName;
398                }
399            
400                /** Accesor. Returns true if an option value was ever obtained for 
401            	this option.
402                */
403 mike  1.9      Boolean isResolved() const 
404                {
405            	return _resolved; 
406 mike  1.1      }
407            
408                /** Checks to see if the given value is valid or not. This method may be
409            	overriden by derived classes to do special purpose validation of the
410            	value. This implementation just checks the domain and type.
411                */
412                virtual Boolean isValid(const String& value) const;
413            
414            private:
415                String _optionName;
416                String _defaultValue;
417                String _value;
418                Boolean _required;
419                Type _type;
420                StringArray _domain;
421                String _commandLineOptionName;
422 mike  1.9      Boolean _resolved;
423 mike  1.4  };
424            
425 mike  1.5  /** The OptionRow provides a declarative way of defining Option objects.
426                For the declarative programming enthusiast, we provide this structure.
427                It provides a declarative way of defining options for the OptionManager
428                class. Some developers prefer this since it makes all the options visible
429                in a kind of table like structure. Here is an example of how it can be
430                used to define a port number and hostname options. We also show how to
431                register one of these option lists with an OptionManager.
432            
433                <pre>
434            	static OptionRow options[] =
435            	{
436            	    { "port", "80", false, Option::NATURAL_NUMBER },
437            	    { "hostname", "", true, Option::STRING }
438            	};
439            
440            	...
441            
442            	OptionManager om;
443            	om.registerOptions(options, sizeof(options) / sizeof(options[0]));
444                </pre>
445            
446 mike  1.5      Recall that static memory areas are initialized with zeros so that the
447                members that are not initialized explicitly in the example above are
448                initialized implicitly with zeros (which the OptionManager used to
449                determine that they are not used).
450            
451                It is possible to specify domains as well. For example, suppose we
452                want to define a "color" option that can be in the following set:
453                {"red", "green", "blue"}. Here is how to express that:
454            
455                <pre>
456            	static const char* colors[] = { "red", "green", "blue" };
457 mike  1.9  	static const Uint32 NUM_COLORS = sizeof(colors) / sizeof(colors[0]);
458 mike  1.5  
459            	static OptionRow options[] = 
460            	{
461 mike  1.9  	    { "color", "red", false, Option::STRING, colors, NUM_COLORS }
462 mike  1.5  	};
463                </pre>
464            */
465            struct OptionRow
466            {
467                const char* optionName;
468                const char* defaultValue;
469                Boolean required;
470                Option::Type type;
471                char** domain;
472                Uint32 domainSize;
473                const char* commandLineOptionName;
474            };
475            
476            /** Exception class */
477 mike  1.4  class MissingCommandLineOptionArgument : public Exception
478            {
479            public:
480            
481                MissingCommandLineOptionArgument(const String& optionName)
482            	: Exception("Missing command line option argument: " + optionName) { }
483            };
484            
485 mike  1.5  /** Exception class */
486            class InvalidOptionValue : public Exception
487            {
488            public:
489            
490                InvalidOptionValue(const String& name, const String& value)
491            	: Exception("Invalid option value: " + name + "=\"" + value + "\"") { }
492            };
493            
494            /** Exception class */
495            class DuplicateOption : public Exception
496 mike  1.4  {
497            public:
498            
499 mike  1.5      DuplicateOption(const String& name)
500            	: Exception("Duplicate option: " + name) { }
501 mike  1.6  };
502            
503            /** Exception class */
504            class ConfigFileSyntaxError : public Exception
505            {
506            public:
507            
508                ConfigFileSyntaxError(const String& file, Uint32 line)
509            	: Exception(_formatMessage(file, line)) { }
510            
511                static String _formatMessage(const String& file, Uint32 line);
512            };
513            
514            /** Exception class */
515            class UnrecognizedConfigFileOption : public Exception
516            {
517            public:
518            
519                UnrecognizedConfigFileOption(const String& name)
520            	: Exception("Unrecognized config file option: " + name) { }
521 mike  1.9  };
522            
523            /** Exception class */
524            class MissingRequiredOptionValue : public Exception
525            {
526            public:
527            
528                MissingRequiredOptionValue(const String& name)
529            	: Exception("Missing required option value: " + name) { }
530 mike  1.1  };
531            
532            PEGASUS_NAMESPACE_END
533            
534            #endif /* Pegasus_OptionManager_h */

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2