(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 karl  1.16     /** optionValueEquals - Test the string value of an option.
255            	@param name provides the name of the option (ex. "port")
256            	@param value String value for comparison.
257            	@return true if the option exists and the value of the option 
258            	equals the input parameter value.
259                */
260                Boolean valueEquals(const String& name, const String& value) const;
261            
262            
263 mike  1.3      /** Print all the options. */
264                void print() const;
265 karl  1.16 
266 mike  1.2  
267 mike  1.1  private:
268            
269 mike  1.4      /** Lookup the option by its commandLineOptionName.
270            	@return 0 if no such option.
271                */
272                Option* _lookupOptionByCommandLineOptionName(const String& name);
273            
274 mike  1.1      Array<Option*> _options;
275            };
276            
277            /** The Option class is used to specify information about an Option.
278            
279                See the OptionManager class for more details.
280            */
281 mike  1.2  class PEGASUS_COMMON_LINKAGE Option
282 mike  1.1  {
283            public:
284            
285                /** Valid value types. */
286 karl  1.12     enum Type
287 mike  1.5      {
288            	// (..., -3, -2, -1, 0, 1, 2, 3, ...)
289 karl  1.12 	INTEGER,
290 mike  1.5  
291            	// (1, 2, 3, ...)
292 karl  1.12 	NATURAL_NUMBER,
293 mike  1.5  
294            	// (0, 1, 2, 3, ...)
295 karl  1.12 	WHOLE_NUMBER,
296 mike  1.5  
297            	// "true" or "false"
298 karl  1.12 	BOOLEAN,
299 mike  1.5  
300            	// Anything
301            	STRING
302                };
303 mike  1.1  
304                /** Constructor.
305            
306 mike  1.8  	@param optionName the name of this option.
307 mike  1.1  
308 mike  1.8  	@param defaultValue the default value of this option.
309 mike  1.1  
310 mike  1.8  	@param required whether the value of this option is required.
311 mike  1.1  
312 mike  1.8  	@param type type of the value. This is used to validate the value.
313 mike  1.1  
314 mike  1.8  	@param domain list of legal value for this option. If this list
315 mike  1.1  	    is empty, then no domain is enforced.
316            
317 mike  1.8  	@param commandLineOptionName name of the corresponding command line
318 mike  1.1  	    option (which may be different from the option name).
319                */
320                Option(
321                    const String& optionName,
322                    const String& defaultValue,
323                    Boolean required,
324                    Type type,
325 mike  1.13         const Array<String>& domain = EmptyStringArray(),
326 mike  1.2          const String& commandLineOptionName = String());
327            
328                Option(const Option& x);
329 mike  1.1  
330                virtual ~Option();
331            
332 mike  1.2      Option& operator=(const Option& x);
333 mike  1.1  
334                /** Accessor */
335                const String& getOptionName() const
336                {
337                    return _optionName;
338                }
339            
340                /** Modifier */
341                void setOptionName(const String& optionName)
342                {
343                    _optionName = optionName;
344                }
345            
346                /** Accessor */
347                const String& getDefaultValue() const
348                {
349                    return _defaultValue;
350                }
351            
352                /** Modifier. */
353                void setDefaultValue(const String& defaultValue)
354 mike  1.1      {
355                    _defaultValue = defaultValue;
356                }
357            
358 karl  1.12     /** Accessor
359 karl  1.11 	@return - Returns string representation of value
360                */
361 mike  1.1      const String& getValue() const
362                {
363                    return _value;
364                }
365            
366                /** Modifier */
367                void setValue(const String& value)
368                {
369                    _value = value;
370 mike  1.9  	_resolved = true;
371 mike  1.1      }
372            
373                /** Accessor */
374                Boolean getRequired() const
375                {
376                    return _required;
377                }
378            
379                /** Modifier */
380                void setRequired(Boolean required)
381                {
382                    _required = required;
383                }
384            
385                /** Accessor */
386                Type getType() const
387                {
388                    return _type;
389                }
390            
391                /** Modifier */
392 mike  1.1      void setType(Type type)
393                {
394                    _type = type;
395                }
396            
397                /** Accessor */
398 mike  1.13     const Array<String>& getDomain() const;
399 mike  1.1  
400                /** Modifier */
401 mike  1.13     void setDomain(const Array<String>& domain);
402 mike  1.1  
403                /** Accessor */
404                const String& getCommandLineOptionName() const
405                {
406                    return _commandLineOptionName;
407                }
408            
409                /** Modifier */
410                void setCommandLineOptionName(const String& commandLineOptionName)
411                {
412                    _commandLineOptionName = commandLineOptionName;
413                }
414            
415 karl  1.12     /** Accesor. Returns true if an option value was ever obtained for
416 mike  1.1  	this option.
417                */
418 karl  1.12     Boolean isResolved() const
419 mike  1.9      {
420 karl  1.12 	return _resolved;
421 mike  1.1      }
422            
423                /** Checks to see if the given value is valid or not. This method may be
424            	overriden by derived classes to do special purpose validation of the
425            	value. This implementation just checks the domain and type.
426                */
427                virtual Boolean isValid(const String& value) const;
428            
429            private:
430                String _optionName;
431                String _defaultValue;
432                String _value;
433                Boolean _required;
434                Type _type;
435 mike  1.13     Array<String> _domain;
436 mike  1.1      String _commandLineOptionName;
437 mike  1.9      Boolean _resolved;
438 mike  1.4  };
439            
440 mike  1.5  /** The OptionRow provides a declarative way of defining Option objects.
441                For the declarative programming enthusiast, we provide this structure.
442                It provides a declarative way of defining options for the OptionManager
443                class. Some developers prefer this since it makes all the options visible
444                in a kind of table like structure. Here is an example of how it can be
445                used to define a port number and hostname options. We also show how to
446                register one of these option lists with an OptionManager.
447            
448                <pre>
449            	static OptionRow options[] =
450            	{
451            	    { "port", "80", false, Option::NATURAL_NUMBER },
452            	    { "hostname", "", true, Option::STRING }
453            	};
454            
455            	...
456            
457            	OptionManager om;
458            	om.registerOptions(options, sizeof(options) / sizeof(options[0]));
459                </pre>
460            
461 mike  1.5      Recall that static memory areas are initialized with zeros so that the
462                members that are not initialized explicitly in the example above are
463                initialized implicitly with zeros (which the OptionManager used to
464                determine that they are not used).
465            
466                It is possible to specify domains as well. For example, suppose we
467                want to define a "color" option that can be in the following set:
468                {"red", "green", "blue"}. Here is how to express that:
469            
470                <pre>
471            	static const char* colors[] = { "red", "green", "blue" };
472 mike  1.9  	static const Uint32 NUM_COLORS = sizeof(colors) / sizeof(colors[0]);
473 mike  1.5  
474 karl  1.12 	static OptionRow options[] =
475 mike  1.5  	{
476 mike  1.9  	    { "color", "red", false, Option::STRING, colors, NUM_COLORS }
477 mike  1.5  	};
478                </pre>
479            */
480            struct OptionRow
481            {
482                const char* optionName;
483                const char* defaultValue;
484 mike  1.14     int required;
485 mike  1.5      Option::Type type;
486                char** domain;
487                Uint32 domainSize;
488                const char* commandLineOptionName;
489            };
490            
491            /** Exception class */
492 mike  1.4  class MissingCommandLineOptionArgument : public Exception
493            {
494            public:
495            
496                MissingCommandLineOptionArgument(const String& optionName)
497            	: Exception("Missing command line option argument: " + optionName) { }
498            };
499            
500 mike  1.5  /** Exception class */
501            class InvalidOptionValue : public Exception
502            {
503            public:
504            
505                InvalidOptionValue(const String& name, const String& value)
506            	: Exception("Invalid option value: " + name + "=\"" + value + "\"") { }
507            };
508            
509            /** Exception class */
510            class DuplicateOption : public Exception
511 mike  1.4  {
512            public:
513            
514 mike  1.5      DuplicateOption(const String& name)
515            	: Exception("Duplicate option: " + name) { }
516 mike  1.6  };
517            
518            /** Exception class */
519            class ConfigFileSyntaxError : public Exception
520            {
521            public:
522            
523                ConfigFileSyntaxError(const String& file, Uint32 line)
524            	: Exception(_formatMessage(file, line)) { }
525            
526                static String _formatMessage(const String& file, Uint32 line);
527            };
528            
529            /** Exception class */
530            class UnrecognizedConfigFileOption : public Exception
531            {
532            public:
533            
534                UnrecognizedConfigFileOption(const String& name)
535            	: Exception("Unrecognized config file option: " + name) { }
536 mike  1.9  };
537            
538            /** Exception class */
539            class MissingRequiredOptionValue : public Exception
540            {
541            public:
542            
543                MissingRequiredOptionValue(const String& name)
544            	: Exception("Missing required option value: " + name) { }
545 mike  1.1  };
546            
547            PEGASUS_NAMESPACE_END
548            
549            #endif /* Pegasus_OptionManager_h */

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2