private void AddSupportedPortDetails(ClassFileGenerator cfg, string implementedPort, bool isImplemented = true) { var type = implementedPort.Split()[0]; var name = implementedPort.Split()[1]; if (type.StartsWith("IEvent") && !type.StartsWith("IEventB")) { if (isImplemented) { cfg.AddField("EventConnector", $"{name}Connector", accessLevel: "private", defaultValue: $"new EventConnector() {{ InstanceName = \"{name}Connector\" }}", region: "Input instances"); List <string> methodBody = new List <string>(); methodBody.Add($"({name}Connector as IEvent).Execute();"); cfg.AddMethod("IEvent.Execute", region: $"{type} implementation", methodBody: methodBody); } else { cfg.AddField("EventConnector", $"{name}Connector", accessLevel: "private", defaultValue: $"new EventConnector() {{ InstanceName = \"{name}Connector\" }}", region: "Output instances"); } } else if (type.StartsWith("IDataFlow")) { if (type.StartsWith("IDataFlowB")) { } else { var internalDataType = type.Replace("IDataFlow<", ""); internalDataType = internalDataType.Substring(0, internalDataType.Length - 1); if (isImplemented) { cfg.AddField($"DataFlowConnector<{internalDataType}>", $"{name}Connector", accessLevel: "private", defaultValue: $"new DataFlowConnector<{internalDataType}>() {{ InstanceName = \"{name}Connector\" }}", region: "Input instances"); string setterBody = $"{{({name}Connector as IDataFlow<{internalDataType}>).Data = value;}}"; cfg.AddProperty(internalDataType, $"{type}.Data", region: $"{type} implementation", setterBody: setterBody); } else { cfg.AddField($"Apply<{internalDataType}, {internalDataType}>", $"{name}Connector", accessLevel: "private", defaultValue: $"new Apply<{internalDataType}, {internalDataType}>() {{ InstanceName = \"{name}Connector\", Lambda = input => input }}", region: "Output instances"); } } } else if (type.StartsWith("IUI")) { cfg.AddMethod("IUI.GetWPFElement", returnType: "UIElement", region: $"{type} implementation"); } }
private void Create() { try { var cfg = new ClassFileGenerator() { Namespace = $"{NamespacePrefix}{Enum.GetName(typeof(Enums.ALALayer), Layer)}", ClassName = ClassName, ImplementedInterfaces = ImplementedPorts.Select(s => s.Split().First()).ToList(), // Just get interface types IsInterface = Layer == Enums.ALALayer.ProgrammingParadigms }; if (Layer != Enums.ALALayer.ProgrammingParadigms) { cfg.Regions.Add("Public fields and properties"); cfg.Regions.Add("Private fields"); cfg.Regions.Add("Ports"); cfg.AddProperty("string", "InstanceName", accessLevel: "public", defaultValue: "\"Default\"", region: "Public fields and properties", isAutoProperty: true); } else { cfg.Regions.Add("Properties"); cfg.Regions.Add("Methods"); } // Add usings cfg.Usings.Add("System.Windows"); if (Layer == Enums.ALALayer.ProgrammingParadigms) { cfg.Usings.Add($"{NamespacePrefix}Libraries"); } else if (Layer == Enums.ALALayer.DomainAbstractions) { cfg.Usings.Add($"{NamespacePrefix}Libraries"); cfg.Usings.Add($"{NamespacePrefix}ProgrammingParadigms"); } else if (Layer == Enums.ALALayer.Application) { cfg.Usings.Add($"{NamespacePrefix}Libraries"); cfg.Usings.Add($"{NamespacePrefix}ProgrammingParadigms"); cfg.Usings.Add($"{NamespacePrefix}DomainAbstractions"); } List <string> description = new List <string> { "" }; int portCounter = 1; if (!(Layer == Enums.ALALayer.ProgrammingParadigms)) { if (Layer == Enums.ALALayer.Application) { cfg.Regions.Add("Input instances"); cfg.Regions.Add("Output instances"); } ; description.Add("Ports:"); // Create implementation stubs foreach (var implementedPort in ImplementedPorts) { var type = implementedPort.Split()[0]; cfg.Regions.Add($"{type} implementation"); AddSupportedPortDetails(cfg, implementedPort, isImplemented: true); description.Add($"{portCounter}. {implementedPort.Replace("<", "<").Replace(">", ">")}:"); portCounter++; } foreach (var providedPort in ProvidedPorts) { var split = providedPort.Split(); if (split.Length < 2) { continue; } var type = split[0]; var name = split[1]; if (type.StartsWith("List<")) { cfg.AddField(type, name, accessLevel: "private", region: "Ports", defaultValue: $"new {type}()"); } else { cfg.AddField(type, name, accessLevel: "private", region: "Ports"); } description.Add($"{portCounter}. {providedPort.Replace("<", "<").Replace(">", ">")}:"); portCounter++; AddSupportedPortDetails(cfg, providedPort, isImplemented: false); } } cfg.Description = description; if (Layer == Enums.ALALayer.Application) { // Add landmarks for wiring code insertion List <string> constructorBody = new List <string>(); constructorBody.Add($"// BEGIN AUTO-GENERATED INSTANTIATIONS FOR {ClassName}.xmind"); constructorBody.Add($"// END AUTO-GENERATED INSTANTIATIONS FOR {ClassName}.xmind"); constructorBody.Add($""); constructorBody.Add($"// BEGIN AUTO-GENERATED WIRING FOR {ClassName}.xmind"); constructorBody.Add($"// END AUTO-GENERATED WIRING FOR {ClassName}.xmind"); constructorBody.Add($""); constructorBody.Add($"// BEGIN MANUAL INSTANTIATIONS FOR {ClassName}.xmind"); constructorBody.Add($"// END MANUAL INSTANTIATIONS FOR {ClassName}.xmind"); constructorBody.Add($""); constructorBody.Add($"// BEGIN MANUAL WIRING FOR {ClassName}.xmind"); constructorBody.Add($"// END MANUAL WIRING FOR {ClassName}.xmind"); cfg.ConstructorBody = constructorBody; // Add PostWiringInitialize List <string> postWiringInitializeBody = new List <string>(); postWiringInitializeBody.Add("// Mapping to virtual ports"); // postWiringInitializeBody.Add("// Utilities.ConnectToVirtualPort(outputInstance, \"portOnOutputInstance\", portInStoryAbstraction);"); // postWiringInitializeBody.Add(""); foreach (var providedPort in ProvidedPorts) { var type = providedPort.Split()[0]; var name = providedPort.Split()[1]; // Connector should be an Apply<type, type> if (type.StartsWith("IDataFlow") && !type.StartsWith("IDataFlowB")) { // postWiringInitializeBody.Add($"Utilities.ConnectToVirtualPort({name}Connector, \"output\", {name});"); postWiringInitializeBody.Add($"if ({name} != null) {name}Connector.WireTo({name}, \"output\");"); } else if (type.StartsWith("IEvent") && !type.StartsWith("IEventB")) { // postWiringInitializeBody.Add($"Utilities.ConnectToVirtualPort({name}Connector, \"complete\", {name});"); postWiringInitializeBody.Add($"if ({name} != null) {name}Connector.WireTo({name}, \"complete\");"); } } postWiringInitializeBody.Add(""); postWiringInitializeBody.Add("// IDataFlowB and IEventB event handlers"); // postWiringInitializeBody.Add("// if (inputDataFlowBPort != null)"); // postWiringInitializeBody.Add("// {"); // postWiringInitializeBody.Add("// inputDataFlowBPort.DataChanged += () => (inputInstance as IDataFlow<T>).Data = inputDataFlowBPort.Data;"); // postWiringInitializeBody.Add("// }"); foreach (var providedPort in ProvidedPorts) { var type = providedPort.Split()[0]; var name = providedPort.Split()[1]; // Connector should be an Apply<type, type> if (type.StartsWith("IDataFlowB")) { postWiringInitializeBody.Add($"if ({name} != null)"); postWiringInitializeBody.Add($"{{"); postWiringInitializeBody.Add($" {name}.DataChanged += () => ({name}Connector as IDataFlow<T>).Data = {name}.Data;"); postWiringInitializeBody.Add($"}}"); postWiringInitializeBody.Add(""); } else if (type.StartsWith("IEventB")) { postWiringInitializeBody.Add($"if ({name} != null)"); postWiringInitializeBody.Add($"{{"); postWiringInitializeBody.Add($" {name}.EventHappened += () => ({name}Connector as IEvent).Execute();"); postWiringInitializeBody.Add($"}}"); postWiringInitializeBody.Add(""); } } postWiringInitializeBody.Add("// Send out initial values"); postWiringInitializeBody.Add("// (instanceNeedingInitialValue as IDataFlow<T>).Data = defaultValue;"); cfg.Regions.Add("PostWiringInitialize"); cfg.AddMethod("PostWiringInitialize", accessLevel: "private", methodBody: postWiringInitializeBody, region: "PostWiringInitialize"); } var classFileTemplateContents = cfg.BuildFile(); if (WriteFile && Directory.Exists(Path.GetDirectoryName(FilePath))) { var classNameWithoutTypes = GetClassNameWithoutTypes(ClassName); File.WriteAllText(Path.Combine(FilePath, $"{classNameWithoutTypes}.cs"), classFileTemplateContents); if (Layer == Enums.ALALayer.Application && File.Exists(Path.Combine(FilePath, $"baseStoryAbstraction.xmind"))) { // Create xmind diagram File.Copy(Path.Combine(FilePath, $"baseStoryAbstraction.xmind"), Path.Combine(FilePath, $"{classNameWithoutTypes}.xmind")); } } if (fileContentsOutput != null) { fileContentsOutput.Data = classFileTemplateContents; } } catch (Exception e) { } }