1 //============================================================================== 2 // 3 // This file is part of GPSTk, the GPS Toolkit. 4 // 5 // The GPSTk is free software; you can redistribute it and/or modify 6 // it under the terms of the GNU Lesser General Public License as published 7 // by the Free Software Foundation; either version 3.0 of the License, or 8 // any later version. 9 // 10 // The GPSTk is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU Lesser General Public License for more details. 14 // 15 // You should have received a copy of the GNU Lesser General Public 16 // License along with GPSTk; if not, write to the Free Software Foundation, 17 // Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA 18 // 19 // This software was developed by Applied Research Laboratories at the 20 // University of Texas at Austin. 21 // Copyright 2004-2020, The Board of Regents of The University of Texas System 22 // 23 //============================================================================== 24 25 //============================================================================== 26 // 27 // This software was developed by Applied Research Laboratories at the 28 // University of Texas at Austin, under contract to an agency or agencies 29 // within the U.S. Department of Defense. The U.S. Government retains all 30 // rights to use, duplicate, distribute, disclose, or release this software. 31 // 32 // Pursuant to DoD Directive 523024 33 // 34 // DISTRIBUTION STATEMENT A: This software has been approved for public 35 // release, distribution is unlimited. 36 // 37 //============================================================================== 38 39 /** 40 * @file BasicFramework.hpp 41 * Basic framework for programs in the GPS toolkit 42 */ 43 44 #ifndef GPSTK_BASICFRAMEWORK_HPP 45 #define GPSTK_BASICFRAMEWORK_HPP 46 47 #include "CommandOptionParser.hpp" 48 #include "MainAdapter.hpp" 49 50 namespace gpstk 51 { 52 53 /** @defgroup AppFrame Frameworks for Applications 54 * 55 * The application frameworks provide a set of classes that 56 * perform the basic functions of applications within the GPS 57 * toolkit. That is, they provide a framework for applications 58 * so that the applications only have to implement those 59 * features which are unique to that application. 60 * 61 * The classes are defined in a tree of increasing capability, 62 * that is, the BasicFramework class at the root of the tree 63 * does very little and implements only those functions which 64 * are common to all programs within the toolkit. Each 65 * subsequent subclass adds additional layers to these basic 66 * capabilities. 67 * 68 * The end user is expected to create a class, which inherits 69 * from one of these frameworks, and override the appropriate 70 * methods in order to perform the necessary function of that 71 * program. The methods to be overridden depend on the 72 * framework being used and what the program is intended to 73 * do. 74 * 75 * For information on how to use the frameworks, see \ref appbuilding. 76 */ 77 78 /** @page appbuilding Building Up Applications Using Frameworks 79 * 80 * \tableofcontents 81 * 82 * While not GNSS-related, the gpstk provides a set of 83 * frameworks to reduce the amount of effort required when 84 * writing applications. 85 * 86 * The classes used for quickly implementing applications are: 87 * - BasicFramework for simple applications with no 88 * repetitive processing. 89 * - LoopedFramework for applications with repetetive processing. 90 * - CommandOption which is the parent class for a myriad of 91 * specialized command-line option processing classes. 92 * 93 * @section overview Overview 94 * 95 * Using the application frameworks is pretty consistent across 96 * all applications (which of course is the intent). An 97 * application will define a class that derives from one of the 98 * frameworks, and overrides the methods of the framework class 99 * that are appropriate for the application. The implementation 100 * of the main function is very similar from application to 101 * application, with only the application class name changing, 102 * in general. 103 * 104 * The structure of applications using these frameworks follows 105 * the following formula: 106 * 107 * @code{.cpp} 108 * class MyApp : public gpstk::BasicFramework 109 * { 110 * public: 111 * MyApp(const std::string& appName); 112 * virtual ~MyApp(); 113 * void process() override; 114 * }; 115 * 116 * int main(int argc, char *argv[]) 117 * { 118 * try 119 * { 120 * MyApp app(argv[0]); 121 * if (app.initialize(argc, argv)) 122 * { 123 * app.run(); 124 * } 125 * return app.exitCode; 126 * } 127 * catch (gpstk::Exception& e) 128 * { 129 * cerr << e << endl; 130 * } 131 * catch (std::exception& e) 132 * { 133 * cerr << e.what() << endl; 134 * } 135 * catch (...) 136 * { 137 * cerr << "Caught unknown exception" << endl; 138 * } 139 * return gpstk::BasicFramework::EXCEPTION_ERROR; 140 * } 141 * @endcode 142 * 143 * @section basic BasicFramework Usage 144 * 145 * When you need to implement an application that performs a 146 * single task before exiting (timeconvert is a good example of 147 * this), BasicFramework is probably the ideal framework class 148 * for you to use. 149 * 150 * The flow of execution for applications derived from the 151 * BasicFramework class is as follows (indentation levels 152 * indicate the call stack): 153 * -# main() 154 * -# Constructor 155 * -# initialize() (often overridden) 156 * -# run() (never overridden) 157 * -# completeProcessing() (rarely overridden) 158 * -# additionalSetup() (often overridden, empty by default) 159 * -# spinUp() (often overridden, empty by default) 160 * -# process() (often overridden, empty by default) 161 * -# shutDown() (sometimes overridden) 162 * 163 * The functions/methods of an application class perform 164 * functions as follows: 165 * - main() instantiates the application class and executes the code. 166 * - Constructor does all the usual things C++ constructors do, 167 * including calling the parent's class' constructor and 168 * initializing the command-line option objects. 169 * - initialize() processes the command-line options. 170 * - run() calls the completeProcessing() method in a try/catch 171 * block, and calls shutDown(). 172 * - completeProcessing() calls additionalSetup(), spinUp() and 173 * process() in that order. Sometimes it may be overridden 174 * for additional processing (see @ref looped), but this is 175 * fairly rare and typically is only done in specialized 176 * frameworks. 177 * - additionalSetup() is a method intended to be used when 178 * additional tasks are needed to be done prior to the main 179 * execution that depend on the completion of tasks in the 180 * initialize() method. 181 * - spinUp() is a method intended to be used when additional 182 * tasks are needed to be done prior to the main execution 183 * that depend on the completion of tasks in both the 184 * initialize() method and the additionalSetup() method. 185 * - process() is where the meat of the application is, 186 * i.e. where the primary application work takes place. 187 * - shutDown() is called at the end of successful (no 188 * exceptions thrown) program execution. It is meant to be 189 * used to allow an application to clean up after itself, like 190 * closing files, network connections, etc. 191 * 192 * Why are there so many methods defined? The main reason is to 193 * allow further differentiation when specializing frameworks. 194 * That is, there are derived classes that provide further 195 * frameworks capabilities where initialization must occur in a 196 * very specific order, but the subclasses need to be able to 197 * override specific behaviors. 198 * 199 * @subsection exit Exit Codes 200 * 201 * The BasicFramework class defines a data member named \a 202 * exitCode. This is intended to be used as the return value 203 * for main() (see the example in \ref overview). It is 204 * initialized to 0, which indicates successful completion of 205 * applications. Any non-zero return from main will be 206 * interpreted by the shell as a failed execution. While 207 * BasicFramework will set \a exitCode to an error code for 208 * exceptions caught within run() or command-line processing 209 * errors within initialize(), implementers should remember two 210 * things: 211 * -# The implementer should set the \a exitCode variable to an 212 * appropriate value when terminating on failure for any 213 * condition not handled as described above. 214 * -# The implementer \b must explicitly return the value of \a 215 * exitCode in their main() function. This is not handled 216 * automatically by the frameworks. 217 * 218 * The following generic exit codes are defined within BasicFramework: 219 * - BasicFramework::EXCEPTION_ERROR 220 * - BasicFramework::OPTION_ERROR 221 * - BasicFramework::EXIST_ERROR 222 * 223 * Other exit codes can be defined as needed on a per-application basis. 224 * 225 * @section looped LoopedFramework Usage 226 * 227 * LoopedFramework is identical to BasicFramework with the 228 * following exceptions: 229 * - a boolean flag named \a timeToDie is added to control loop execution. 230 * - the process() method is called by completeProcessing() continuously 231 * until the \a timeToDie flag is set to true. 232 * 233 * LoopedFramework is meant to be used when executing a set of 234 * statements repeatedly. Derived classes should set \a 235 * timeToDie to true whenever an appropriate termination 236 * condition has been met. 237 * 238 * @section cmdopt Command-Line Options 239 * 240 * Command-line option processing used by the application 241 * frameworks involves the instantiation of objects derived from 242 * the CommandOption class. Usually this is done inside the 243 * application class constructor, however there may be 244 * occassions where the command option object is instantiated 245 * dynamically based on some conditional (typically only done in 246 * other frameworks). The CommandOption class and children do 247 * not have a default constructor, which is the primary reason 248 * for instantiating these objects in the application 249 * constructor. 250 * 251 * The CommandOption classes in most cases will let you specify 252 * a short command-line option (e.g. 'h' becomes -h on the 253 * command line), a long command-line option (e.g. "help" 254 * becomes --help on the command line), a description of the 255 * command line option to be printed when help is requested, and 256 * a flag indicating whether the command-line argument is 257 * required or not. The CommandOption class has several other 258 * constructor parameters but using that class directly rather 259 * than one of the child classes is pretty much unheard of. 260 * 261 * Really basic command-line option classes that are never directly used: 262 * - CommandOption 263 * - RequiredOption 264 * - CommandOptionWithArg 265 * 266 * Command-line options that take an argument of some sort, 267 * usually with format checking of that argument: 268 * | Class | Description | Example | 269 * | -------------- | ------------------------ | ----------------------- | 270 * | NoArg | Boolean or with count | \ref CommandOption1.cpp | 271 * | WithAnyArg | No arg format checking | \ref CommandOption1.cpp | 272 * | WithStringArg | Alpha chars only in arg | | 273 * | WithNumberArg | +/- integer arg | \ref CommandOption2.cpp | 274 * | WithDecimalArg | decimal argument | \ref CommandOption2.cpp | 275 * | WithTimeArg | multi-format time arg | | 276 * | WithSimpleTimeArg | pre-defined multi-format time arg | | 277 * | WithCommonTimeArg | formatted time arg | \ref CommandOption2.cpp | 278 * | WithPositionArg | formatted position arg | | 279 * | Rest | args with no option | \ref CommandOption1.cpp | 280 * 281 * Classes for defining relationships between real command-line arguments: 282 * | Class | Example | Requires | 283 * | --------- | ----------------------- | ------------------------- | 284 * | NOf | \ref CommandOption3.cpp | exactly N uses of x, y, z | 285 * | OneOf | \ref CommandOption3.cpp | at least one usage of x, y, z | 286 * | AllOf | \ref CommandOption4.cpp | all or none of x, y, z must be used | 287 * | Mutex | \ref CommandOption4.cpp | ONLY one of x, y, or z | 288 * | Dependent | \ref CommandOption4.cpp | e.g. if x is used, then y must be used | 289 * 290 * Classes for implementing logical checks in conjunction 291 * (i.e. as one of the "options") in the above classes: 292 * | Class | Example | Virtually set if | 293 * | --------- | ----------------------- | ------------------------- | 294 * | GroupOr | \ref CommandOption5.cpp | any of x, y or z are used | 295 * | GroupAnd | | all of x, y and z are used | 296 * 297 * Help options. These are handled specially by BasicFramework such that 298 * - CommandOptionHelp is the parent class for all help 299 * requested on the command-line. The use (on the 300 * command-line) of any instances of objects derived from this 301 * class will result in the frameworks terminating after the 302 * initialize() method completes. 303 * 304 * - CommandOptionHelpUsage is the command-line option help, 305 * that prints out the standard usage information (in 306 * conjunction with -h or --help arguments). An instance of 307 * this is already used in BasicFramework so you shouldn't 308 * ever need to directly use this class. 309 * 310 * - CommandOptionHelpSimple provides a very basic help feature 311 * that prints a pre-defined message. If you want to add a 312 * command-line option that prints out a simple text message 313 * and exits without further processing, this just might be 314 * the class for you. 315 * 316 * BasicFramework will exit after printing the appropriate help 317 * information when any of the above command-line option types 318 * are requested by the user. 319 * 320 * The arguments to the command-line arguments (e.g. for "-n 5", 321 * "5" is the argument) are available as a vector of strings 322 * (where each value in the vector corresponds to one use of the 323 * command-line argument) via the getValue() method. In most 324 * cases you will need to convert the strings to the appropriate 325 * data type yourself (time being an exception). 326 * 327 * As an example, if a user specifies "-n 5 -n 7 -n 11", 328 * getValue() will return an array of the strings "5","7,"11". 329 * A common method for handling cases where only one argument is 330 * allowed is to use the vector [] operator like 331 * "someOpt.getValue()[0]". 332 * 333 * A very common situation you will have is to limit the number 334 * of times a command-line argument can be used. This is 335 * usually done by calling the setMaxCount() method on the 336 * CommandOption-derived class in the application's constructor. 337 * See the example codes and CommandOption documentation for 338 * more details. 339 */ 340 341 /** @example CommandOption1.cpp 342 * This is a very simple example of how to add support for a 343 * command-line argument to a BasicFramework-derived 344 * application. */ 345 346 /** @example CommandOption2.cpp 347 * This is an example of how to add support for command-line 348 * arguments that incorporate some degree of checking of the 349 * option format (integer, float, time) to a 350 * BasicFramework-derived application. */ 351 352 /** @example CommandOption3.cpp 353 * Example use of CommandOptionNOf where two options are 354 * expected out of a set of various time options, and 355 * CommandOptionOneOf. */ 356 357 /** @example CommandOption4.cpp 358 * Example use of CommandOptionNOf where two options are 359 * expected out of a set of various time options, and 360 * CommandOptionOneOf. */ 361 362 /** @example CommandOption5.cpp 363 * Examples of logical command-line option groups. */ 364 365 /// @ingroup AppFrame 366 //@{ 367 368 /** 369 * This is a (very) basic framework for programs in the GPS 370 * toolkit. It is meant to be used by programs that start up, 371 * do some processing, and quit. 372 * 373 * The end user should define subclasses of this class, 374 * implementing those methods described as being meant to be 375 * overridden; initialize(), additionalSetup(), spinUp(), process(), 376 * and shutDown(). 377 * 378 * In use, the user will construct an object of the class 379 * derived from this, then call the run() method. 380 */ 381 class BasicFramework 382 { 383 public: 384 /** Exit code used when an exception has been caught in 385 * run(). Not guaranteed to be unique to this condition. */ 386 static const int EXCEPTION_ERROR = 1; 387 /** Exit code used when an error has occurred in processing 388 * command-line options. Not guaranteed to be unique to this 389 * condition. */ 390 static const int OPTION_ERROR = 2; 391 /** Exit code used when an input file does not exist or is 392 * not accessible. */ 393 static const int EXIST_ERROR = 2; 394 395 /** Constructor for BasicFramework. 396 * 397 * @param[in] applName name of the program (argv[0]). 398 * @param[in] applDesc text description of program's function 399 * (used by CommandOption help). 400 */ 401 BasicFramework( const std::string& applName, 402 const std::string& applDesc ) 403 throw(); 404 405 406 /// Destructor. ~BasicFramework()407 virtual ~BasicFramework() {}; 408 409 410 /** Process command line arguments. When this method is overridden, 411 * make sure to call the parent class's initialize(). 412 * 413 * @param[in] argc same as main() argc. 414 * @param[in] argv same as main() argv. 415 * @param[in] pretty Whether the 'pretty print' option will 416 * be used when printing descriptions. It 417 * is 'TRUE' by default. 418 * 419 * @return true if normal processing should proceed (i.e. no 420 * command line errors or help requests). 421 */ 422 virtual bool initialize( int argc, 423 char *argv[], 424 bool pretty = true ) 425 throw(); 426 427 428 /** Run the program. Processes only once (refer to subclasses 429 * for looped processing). 430 * 431 * @return false if an exception occurred 432 */ 433 bool run() throw(); 434 435 436 /** A place to store the exit code for the application. 437 * Defaults to 0 which indicates successful completion. 438 * It is recommended that your application: 439 * 1) Set this value on terminal error. 440 * 2) Return this value from main in all cases. */ 441 int exitCode; 442 443 444 protected: 445 446 int debugLevel; ///< Debug level for this run of the program. 447 int verboseLevel; ///< Verbose level for this run of the program. 448 std::string argv0; ///< Name of the program. 449 std::string appDesc; ///< Description of program's function. 450 451 /// Enable/increase debugging output. 452 CommandOptionNoArg debugOption; 453 /// Enable/increase informational output. 454 CommandOptionNoArg verboseOption; 455 /// Request command-line option usage. 456 CommandOptionHelpUsage helpOption; 457 458 459 /** 460 * Called by the run() method; calls additionalSetup(), 461 * spinUp(), and process(), in that order. Generally should 462 * not be overridden. 463 */ 464 virtual void completeProcessing(); 465 466 467 /** 468 * Additional set-up to be performed before starting 469 * processing. This generally involves things that are 470 * necessary for either the spinUp processing or main 471 * processing. This method should be implemeneted by the end-user. 472 */ additionalSetup()473 virtual void additionalSetup() 474 {} 475 476 477 /** 478 * Code to be executed AFTER initialize() and additionalSetup(). 479 * This method should be implemeneted by the end-user. 480 */ spinUp()481 virtual void spinUp() 482 {} 483 484 485 /** 486 * Processing to be performed. This method should be 487 * implemeneted by the end-user. 488 */ process()489 virtual void process() 490 {} 491 492 493 /** 494 * Clean-up processing to be done before the program ends. 495 * This method is executed outside of a try block and should 496 * be implemeneted by the end-user. 497 */ shutDown()498 virtual void shutDown() 499 {} 500 501 502 private: 503 504 505 // Do not allow the use of the default constructor. 506 BasicFramework(); 507 508 }; // End of class 'BasicFramework' 509 510 //@} 511 512 } // End of namespace gpstk 513 #endif // GPSTK_BASICFRAMEWORK_HPP 514