1 /**
2  * Copyright: Copyright (c) 2012 Jacob Carlborg. All rights reserved.
3  * Authors: Jacob Carlborg
4  * Version: Initial created: May 3, 2012
5  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0)
6  */
7 module dstack.application.Application;
8 
9 import tango.io.Stdout;
10 
11 import mambo.core._;
12 import mambo.sys.System;
13 import mambo.util.Singleton;
14 import mambo.arguments.Arguments;
15 
16 import dstack.application.ApplicationException;
17 import dstack.application.Configuration;
18 
19 abstract class Application
20 {
21 	Configuration config;
22 
23 	private
24 	{
25 		Arguments arguments_;
26 		string[] rawArgs;
27 		bool help;
28 	}
29 
30 	static int start (this T) (string[] args)
31 	{
32 		Application app = T.instance;
33 		app.initialize(args);
34 
35 		return app.help ? ExitCode.success : app._start();
36 	}
37 
38 	protected abstract void run ();
39 
40 	@property protected Arguments arguments () ()
41 	{
42 		return arguments_;
43 	}
44 
45 	protected auto arguments (Args...) (Args args) if (Args.length > 0)
46 	{
47 		return arguments_.option.opCall(args);
48 	}
49 
50 	protected void setupArguments () { }
51 
52 	private bool processArguments ()
53 	{
54 		return arguments.parse(rawArgs);
55 	}
56 
57 	protected void showHelp ()
58 	{
59 		println(arguments.helpText);
60 	}
61 
62 private:
63 
64 	bool initialize (string[] args)
65 	{
66 		arguments_ = new Arguments;
67 		rawArgs = args;
68 
69 		handleArguments();
70 
71 		return true;
72 	}
73 
74 	void handleArguments ()
75 	{
76 		_setupArguments();
77 		auto valid = processArguments();
78 
79         if (!valid && !arguments.help)
80 			println(arguments.formatter.errors(&stderr.layout.sprint));
81 
82 		if (arguments.help || !valid || rawArgs.length <= 1)
83 		{
84 			help = true;
85 			showHelp();
86         }
87 	}
88 
89 	void _setupArguments ()
90 	{
91 		arguments.formatter.appName = config.appName.toLower;
92 		arguments.formatter.appVersion = config.appVersion;
93 		arguments("help", "Show this message and exit").aliased('h');
94 		setupArguments();
95 	}
96 
97 	int _start ()
98 	{
99 		debug
100 			return debugStart();
101 
102 		else
103 			return releaseStart();
104 	}
105 
106 	int releaseStart ()
107 	{
108 		try
109 			run();
110 
111 		catch (ApplicationException e)
112 		{
113 			println("An error occurred: ", e);
114 			return ExitCode.failure;
115 		}
116 
117 		catch (Throwable e)
118 		{
119 			println("An unknown error occurred: ", e);
120 			throw e;
121 		}
122 
123 		return ExitCode.success;
124 	}
125 
126 	int debugStart ()
127 	{
128 		run();
129 		return ExitCode.success;
130 	}
131 }