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