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

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2