1+ using Moryx . Cli . Template ;
2+ using Moryx . Cli . Template . Models ;
3+ using Moryx . Cli . Commands . Extensions ;
4+ using Moryx . Cli . Template . StateBaseTemplate ;
5+ using Moryx . Cli . Template . Exceptions ;
6+ using Moryx . Cli . Template . StateTemplate ;
7+
8+ namespace Moryx . Cli . Commands
9+ {
10+ internal class AddStates
11+ {
12+ const string StateBase = "StateBase" ;
13+ const string SpecificState = "SpecificState" ;
14+
15+ internal static CommandResult Exec ( TemplateSettings settings , string resource , IEnumerable < string > states , List < string > transitions )
16+ {
17+ return CommandBase . Exec ( settings , ( fileNames ) => Add ( settings , fileNames , resource , states ) ) ;
18+ }
19+
20+ private static CommandResult Add ( TemplateSettings settings , List < string > cleanedResourceNames , string resource , IEnumerable < string > states )
21+ {
22+ if ( ! ResourceExists ( settings , resource ) )
23+ {
24+ return CommandResult . WithError ( $ "Resource `{ resource } ` not found. Make sure that a `{ resource } .cs` exists in the project.") ;
25+ }
26+
27+ var projectFileNames = cleanedResourceNames . InitialProjects ( ) ;
28+ var StateBaseFileName = cleanedResourceNames . StateBaseFile ( ) ;
29+
30+ var dictionary = Template . Template . PrepareFileStructure ( settings . AppName , StateBaseFileName , projectFileNames ) ;
31+ var targetPath = Path . Combine ( settings . TargetDirectory , "src" , $ "{ settings . AppName } .Resources", resource ) ;
32+ var newStateBaseFileName = Path . Combine ( targetPath , $ "{ resource } StateBase.cs") ;
33+
34+ if ( ! File . Exists ( newStateBaseFileName ) )
35+ {
36+ var files = Template . Template . WriteFilesToDisk (
37+ dictionary ,
38+ settings ,
39+ _ => newStateBaseFileName ) ;
40+
41+ Template . Template . ReplacePlaceHoldersInsideFiles (
42+ files ,
43+ new Dictionary < string , string >
44+ {
45+ { Template . Template . AppPlaceholder , settings . AppName } ,
46+ { Template . Template . StateBasePlaceholder , $ "{ resource } StateBase" } ,
47+ { Template . Template . ResourcePlaceholder , resource } ,
48+ } ) ;
49+
50+ if ( ! states . Any ( ) )
51+ {
52+ states =
53+ [
54+ "Idle" ,
55+ "ReadyToWork" ,
56+ "Running" ,
57+ "ProcessAborting" ,
58+ "SessionComplete" ,
59+ ] ;
60+ }
61+ }
62+
63+ var msg = new List < string > ( ) ;
64+ var warnings = new List < string > ( ) ;
65+ var stateBaseTemplate = StateBaseTemplate . FromFile ( newStateBaseFileName ) ;
66+
67+ foreach ( var state in states )
68+ {
69+ var stateType = state . ToLower ( ) . EndsWith ( "state" )
70+ ? state
71+ : state + "State" ;
72+
73+ stateType = stateType . Capitalize ( ) ;
74+
75+ try
76+ {
77+ var stateFileName = cleanedResourceNames . StateFile ( ) ;
78+
79+ dictionary = Template . Template . PrepareFileStructure ( settings . AppName , stateFileName , projectFileNames ) ;
80+ var filename = Path . Combine ( targetPath , $ "{ stateType } .cs") ;
81+ if ( ! File . Exists ( filename ) )
82+ {
83+ var files = Template . Template . WriteFilesToDisk (
84+ dictionary ,
85+ settings ,
86+ _ => filename ) ;
87+
88+ Template . Template . ReplacePlaceHoldersInsideFiles (
89+ files ,
90+ new Dictionary < string , string >
91+ {
92+ { Template . Template . AppPlaceholder , settings . AppName } ,
93+ { Template . Template . StatePlaceholder , stateType } ,
94+ { Template . Template . ResourcePlaceholder , resource } ,
95+ { Template . Template . StateBasePlaceholder , $ "{ resource } StateBase" } ,
96+ } ) ;
97+
98+ stateBaseTemplate = stateBaseTemplate . AddState ( stateType ) ;
99+
100+ msg . Add ( $ "Successfully added { stateType } state") ;
101+ }
102+ else
103+ {
104+ warnings . Add ( $ "Could not add { stateType } . `{ Path . GetFileName ( filename ) } ` already exists!") ;
105+ }
106+ }
107+ catch ( Exception ex )
108+ {
109+ warnings . Add ( $ "Failed to add state `{ stateType } `! " + ex . Message ) ;
110+ }
111+ }
112+
113+ stateBaseTemplate . SaveToFile ( newStateBaseFileName ) ;
114+
115+ UpdateResource (
116+ settings ,
117+ resource ,
118+ success => msg . Add ( success ) ,
119+ warning => warnings . Add ( warning ) ) ;
120+
121+ return CommandResult . IsOk ( string . Join ( "\n " , msg ) , string . Join ( "\n " , warnings ) ) ;
122+ }
123+
124+ private static void UpdateResource ( TemplateSettings settings , string resource , Action < string > onSuccess , Action < string > onWarning )
125+ {
126+ var dir = Path . Combine ( settings . TargetDirectory , "src" , $ "{ settings . AppName } .Resources") ;
127+ var files = Directory . GetFiles (
128+ dir ,
129+ $ "{ resource } .cs",
130+ new EnumerationOptions
131+ {
132+ ReturnSpecialDirectories = false ,
133+ RecurseSubdirectories = true
134+ } ) ;
135+ if ( files . Length == 0 )
136+ {
137+ onWarning ( $ "Filename `{ resource } .cs` not found. Could not update resource.") ;
138+ return ;
139+ }
140+ if ( files . Length > 1 )
141+ {
142+ onWarning ( $ "Filename `{ resource } .cs` is ambiguous. Could not update resource.") ;
143+ return ;
144+ }
145+ var filename = files . Single ( ) ;
146+
147+ try
148+ {
149+ var template = StateTemplate . FromFile ( filename ) ;
150+ template = template . ImplementIStateContext ( resource ) ;
151+ template . SaveToFile ( filename ) ;
152+ onSuccess ( $ "Updated `{ resource } .cs`") ;
153+ }
154+ catch ( Exception )
155+ {
156+ onWarning ( $ "Failed to update `{ resource } .cs`") ;
157+ }
158+ }
159+
160+ private static bool ResourceExists ( TemplateSettings settings , string resource )
161+ {
162+ var files = Directory . GetFiles (
163+ Path . Combine ( settings . TargetDirectory ) ,
164+ $ "{ resource } .cs",
165+ new EnumerationOptions
166+ {
167+ ReturnSpecialDirectories = false ,
168+ RecurseSubdirectories = true
169+ } ) ;
170+ return files . Length > 0 ;
171+ }
172+ }
173+ }
0 commit comments