Esempio n. 1
0
        bool AppIfNotNull(CodeBlockNested concept,
                          String penId,
                          String name,
                          Object value)
        {
            if (value is System.DBNull)
            {
                return(false);
            }

            String sValue = value.ToString();

            sValue = sValue.Trim()
                     .Replace("\r", "")
            ;
            if (String.IsNullOrEmpty(sValue) == false)
            {
                String[] lines = FormatMultiLineText(sValue).ToArray();
                concept.AppendLine($"    .{name}(\"{penId}\",");
                Int32 i = 0;
                while (i < lines.Length - 1)
                {
                    concept.AppendLine($"        {lines[i++]}");
                }
                concept.AppendLine($"        {lines[i]})");
            }

            return(true);
        }
Esempio n. 2
0
        void Merge(CodeBlockNested codeBlock, CodeBlockNested mergeBlock)
        {
            foreach (CodeBlock mergeBlockChild in mergeBlock.Children)
            {
                switch (mergeBlockChild)
                {
                case CodeBlockText mergeBlockChildText:
                    // if the name starts with '!', then dont merge child
                    // text blocks. Throw away merge text.
                    if (mergeBlock.Name.StartsWith("!") == false)
                    {
                        foreach (String line in mergeBlockChild.AllLines())
                        {
                            codeBlock.AppendLine(line, "");
                        }
                    }
                    break;

                case CodeBlockNested mergeBlockChildNested:
                    CodeBlockNested codeBlockChildNested = codeBlock.Find(mergeBlockChildNested.Name);
                    if (codeBlockChildNested == null)
                    {
                        codeBlockChildNested = codeBlock.AppendBlock(mergeBlockChildNested.Name);
                        codeBlockChildNested.Load(mergeBlockChildNested.Lines(), false);
                    }
                    else
                    {
                        this.Merge(codeBlockChildNested, mergeBlockChildNested);
                    }
                    break;
                }
            }
        }
Esempio n. 3
0
        public CodeEditor CreateMapEditor(String path)
        {
            const String fcn = "CreateMapEditor";

            String mapName = $"{path}_map_r4";

            if (this.editorDict.ContainsKey(mapName) == true)
            {
                throw new ConvertErrorException(this.GetType().Name, fcn, $"Path {path} has already been processed.");
            }

            CodeEditor mapEditor = new CodeEditor();

            mapEditor.SavePath = Path.Combine(this.GeneratedPath, $"{mapName}.txt");

            CodeBlockNested mapBlock = mapEditor.Blocks.AppendBlock();

            mapBlock
            .AppendLine($"Grammar: Map 5.1")
            .AppendLine($"Namespace: fhir")
            .AppendLine($"Target: FHIR_R4")
            .BlankLine()
            ;

            this.editorDict.Add(mapName, mapEditor);
            return(mapEditor);
        }
Esempio n. 4
0
        void BuildCodeSystem(CSInfo ci)
        {
            CodeBlockNested csFields = ci.ClassCode.Blocks.Find("Fields");

            csFields
            .AppendCode($"const string System = \"{ci.CodeSystem.Url}\";");
            ;

            if (ci.CodeSystem.Filter.Count > 0)
            {
                throw new NotImplementedException("Have not implemented CodeSystem.Filter");
            }

            foreach (CodeSystem.ConceptDefinitionComponent component in ci.CodeSystem.Concept)
            {
                String display = component.Display?.Replace("\"", "'");
                String code    = component.Code;

                csFields
                .BlankLine()
                .AppendLine("/// <summary>")
                ;
                if (component.Definition != null)
                {
                    foreach (String line in component.Definition.Split('\n'))
                    {
                        String s = line
                                   .Trim()
                                   .Replace("\r", "")
                                   .Replace("%", "\\%")
                        ;
                        s = WebUtility.HtmlEncode(s);
                        csFields.AppendLine($"/// {s}");
                    }
                }

                csFields
                .AppendLine("/// </summary>")
                .AppendCode($"public static Coding {CSMisc.CodeName(component.Code)} = new Coding(System, \"{code}\", \"{display}\");")
                ;
            }
        }
Esempio n. 5
0
        void GenerateCIMPLDataTypes()
        {
            CodeEditor entryEditor = new CodeEditor();
            CodeEditor mapEditor   = new CodeEditor();

            CodeBlockNested entryBlock = entryEditor.Blocks.AppendBlock();

            entryBlock
            .AppendLine($"Grammar: DataElement 6.0")
            .AppendLine($"Namespace: fhir")
            .AppendLine($"Description: \"Base fhir element definitions. Autogenerated\"")
            ;

            CodeBlockNested mapBlock = mapEditor.Blocks.AppendBlock();

            mapBlock
            .AppendLine($"Grammar: Map 5.1")
            .AppendLine($"Namespace: fhir")
            .AppendLine($"Target: FHIR_R4")
            ;

            GenerateCIMPLDataType(entryBlock, mapBlock, FHIRAllTypes.Ratio);
            GenerateCIMPLDataType(entryBlock, mapBlock, FHIRAllTypes.Period);
            GenerateCIMPLDataType(entryBlock, mapBlock, FHIRAllTypes.Range);
            GenerateCIMPLDataType(entryBlock, mapBlock, FHIRAllTypes.Attachment);
            GenerateCIMPLDataType(entryBlock, mapBlock, FHIRAllTypes.Identifier);
            GenerateCIMPLDataType(entryBlock, mapBlock, FHIRAllTypes.Annotation);
            GenerateCIMPLDataType(entryBlock, mapBlock, FHIRAllTypes.HumanName);
            GenerateCIMPLDataType(entryBlock, mapBlock, FHIRAllTypes.CodeableConcept);

            GenerateCIMPLDataType(entryBlock, mapBlock, FHIRAllTypes.ContactPoint);
            GenerateCIMPLDataType(entryBlock, mapBlock, FHIRAllTypes.Coding);
            GenerateCIMPLDataType(entryBlock, mapBlock, FHIRAllTypes.Money);
            GenerateCIMPLDataType(entryBlock, mapBlock, FHIRAllTypes.Address);
            GenerateCIMPLDataType(entryBlock, mapBlock, FHIRAllTypes.Timing);
            GenerateCIMPLDataType(entryBlock, mapBlock, FHIRAllTypes.Quantity);
            GenerateCIMPLDataType(entryBlock, mapBlock, FHIRAllTypes.SampledData);
            GenerateCIMPLDataType(entryBlock, mapBlock, FHIRAllTypes.Signature);
            GenerateCIMPLDataType(entryBlock, mapBlock, FHIRAllTypes.Age);
            GenerateCIMPLDataType(entryBlock, mapBlock, FHIRAllTypes.Distance);
            GenerateCIMPLDataType(entryBlock, mapBlock, FHIRAllTypes.Duration);
            GenerateCIMPLDataType(entryBlock, mapBlock, FHIRAllTypes.Count);
            GenerateCIMPLDataType(entryBlock, mapBlock, FHIRAllTypes.MoneyQuantity);
            GenerateCIMPLDataType(entryBlock, mapBlock, FHIRAllTypes.SimpleQuantity);

            GenerateCIMPLDataType(entryBlock, mapBlock, FHIRAllTypes.Extension);

            entryEditor.Save(@"\Development\MITRE\cimpl\Fhir-BreastRadiologyReport\CIMPL\Fhir\BaseTypes.txt");
            mapEditor.Save(@"\Development\MITRE\cimpl\Fhir-BreastRadiologyReport\CIMPL\Fhir\BaseTypes_map_r4.txt");
        }
Esempio n. 6
0
        /// <summary>
        /// Create code editor for new entry and save it in save editor list.
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        public CodeEditor CreateEntryEditor(String path)
        {
            const String fcn = "CreateEntryEditor";

            if (this.editorDict.ContainsKey(path) == true)
            {
                throw new ConvertErrorException(this.GetType().Name, fcn, $"Path {path} has already been processed.");
            }

            CodeEditor codeEditor = new CodeEditor();

            codeEditor.SavePath = Path.Combine(this.GeneratedPath, $"{path}.txt");
            CodeBlockNested block = codeEditor.Blocks.AppendBlock();

            block
            .AppendLine($"Grammar: DataElement 6.0")
            .AppendLine($"Namespace: fhir")
            .AppendLine($"Description: \"Fhir {path} definition. Autogenerated\"")
            .BlankLine()
            ;

            this.editorDict.Add(path, codeEditor);
            return(codeEditor);
        }
Esempio n. 7
0
        /// <summary>
        /// Generate Construct method.
        /// </summary>
        public void Generate(String outputPath)
        {
            CodeEditor editor = new CodeEditor();

            CodeBlockNested main = editor.Blocks.AppendBlock();

            main
            .AppendLine($"using System;")
            .AppendLine($"using System.Linq;")
            .AppendLine($"using System.Collections.Generic;")
            .AppendLine($"using System.Reflection;")
            .AppendLine($"using System.Text;")
            .AppendLine($"using FhirKhit.Tools;")
            .AppendLine($"using Hl7.Fhir.Introspection;")
            .AppendLine($"using Hl7.Fhir.Model;")
            .AppendLine($"using Hl7.Fhir.Support.Model;")
            .AppendLine($"using System.Diagnostics;")
            .AppendLine($"using Hl7.FhirPath;")
            .BlankLine()
            .AppendLine($"namespace FhirKhit.SliceGen.CSApi")
            .OpenBrace()
            .SummaryOpen()
            .Summary("This class will generate code to create an element that has the same values as the passed value.")
            .Summary("This class was automatically generated by GenerateFixCodes.cs.")
            .Summary("Do not hand modify this file!")
            .SummaryClose()
            .AppendLine($"public static class ElementFixCode")
            .OpenBrace()
            ;
            CodeBlockNested construct = main.AppendBlock();
            CodeBlockNested methods   = main.AppendBlock();

            main
            .CloseBrace()
            .CloseBrace()
            ;

            construct
            .AppendLine("static String CleanString(String s) => s.Replace(\"\\\"\", \"\\\\\\\"\");")
            .AppendLine($"/// <summary>")
            .AppendLine($"/// Return c# text to create indicated element.")
            .AppendLine($"/// </summary>")
            .AppendLine($"static public bool Construct(CodeBlockNested block,")
            .AppendCode($"    Element fix,")
            .AppendCode($"    String varName,")
            .AppendCode($"    out String propertyType)")
            .OpenBrace()
            //.AppendCode($"const String fcn = \"Construct\";")
            .BlankLine()
            .AppendCode($"if (fix is null)")
            .AppendCode($"    throw new ArgumentNullException(nameof(fix));")
            .AppendCode($"propertyType = null;")
            .AppendCode($"switch (fix.TypeName)")
            .OpenBrace()
            ;

            foreach (FHIRAllTypes fhirType in Enum.GetValues(typeof(FHIRAllTypes)).OfType <FHIRAllTypes>())
            {
                String fhirTypeName = ModelInfo.FhirTypeToFhirTypeName(fhirType);

                if (ModelInfo.IsPrimitive(fhirType))
                {
                    ConstructPrimitive(methods, construct, fhirType);
                }
                else if (ModelInfo.IsDataType(fhirType))
                {
                    ConstructDataType(methods, construct, fhirType);
                }
            }

            construct
            .CloseBrace()
            .AppendCode($"return false;")
            .CloseBrace()
            ;

            editor.Save(outputPath);
        }
Esempio n. 8
0
        void GenerateFindCommonChildren()
        {
            CodeEditor editor = new CodeEditor();

            CodeBlockNested main = editor.Blocks.AppendBlock();

            main
            .AppendLine($"using System;")
            .AppendLine($"using System.Linq;")
            .AppendLine($"using System.Collections.Generic;")
            .AppendLine($"using System.Reflection;")
            .AppendLine($"using System.Text;")
            .AppendLine($"using FhirKhit.Tools;")
            .AppendLine($"using Hl7.Fhir.Introspection;")
            .AppendLine($"using Hl7.Fhir.Model;")
            .AppendLine($"using Hl7.Fhir.Support.Model;")
            .AppendLine($"using System.Diagnostics;")
            .AppendLine($"using Hl7.FhirPath;")
            .BlankLine()
#if FHIR_R3
            .AppendLine($"namespace FhirKhit.Tools.R3")
#elif FHIR_R4
            .AppendLine($"namespace FhirKhit.Tools.R4")
#endif
            .OpenBrace()
            .AppendCode($"public partial class ElementDefinitionNode")
            .OpenBrace()
            ;
            CodeBlockNested construct = main.AppendBlock();
            CodeBlockNested methods   = main.AppendBlock();

            main
            .CloseBrace()
            .CloseBrace()
            ;

            construct
            .SummaryOpen()
            .Summary($"Create ElementDefinitionNode for child of common/primitive Fhir data type elements")
            .SummaryClose()
            .AppendCode($"public ElementDefinitionNode FindCommonChild(String parentPath, String childName)")
            .OpenBrace()
            .AppendCode($"switch (this.FhirItemType.FriendlyName())")
            .OpenBrace()
            ;

            GenerateFindCommonChild(construct, methods, FHIRAllTypes.Ratio);
            GenerateFindCommonChild(construct, methods, FHIRAllTypes.Period);
            GenerateFindCommonChild(construct, methods, FHIRAllTypes.Range);
            GenerateFindCommonChild(construct, methods, FHIRAllTypes.Attachment);
            GenerateFindCommonChild(construct, methods, FHIRAllTypes.Identifier);
            GenerateFindCommonChild(construct, methods, FHIRAllTypes.Annotation);
            GenerateFindCommonChild(construct, methods, FHIRAllTypes.HumanName);
            GenerateFindCommonChild(construct, methods, FHIRAllTypes.CodeableConcept);

            GenerateFindCommonChild(construct, methods, FHIRAllTypes.ContactPoint);
            GenerateFindCommonChild(construct, methods, FHIRAllTypes.Coding);
            GenerateFindCommonChild(construct, methods, FHIRAllTypes.Money);
            GenerateFindCommonChild(construct, methods, FHIRAllTypes.Address);
            GenerateFindCommonChild(construct, methods, FHIRAllTypes.Timing);
            GenerateFindCommonChild(construct, methods, FHIRAllTypes.Quantity);
            GenerateFindCommonChild(construct, methods, FHIRAllTypes.SampledData);
            GenerateFindCommonChild(construct, methods, FHIRAllTypes.Signature);
            GenerateFindCommonChild(construct, methods, FHIRAllTypes.Age);
            GenerateFindCommonChild(construct, methods, FHIRAllTypes.Distance);
            GenerateFindCommonChild(construct, methods, FHIRAllTypes.Duration);
            GenerateFindCommonChild(construct, methods, FHIRAllTypes.Count);
#if FHIR_R4
            GenerateFindCommonChild(construct, methods, FHIRAllTypes.MoneyQuantity);
#endif
            GenerateFindCommonChild(construct, methods, FHIRAllTypes.SimpleQuantity);
            GenerateFindCommonChild(construct, methods, FHIRAllTypes.Extension);

            construct
            .AppendCode($"default: return null;")
            .CloseBrace()
            .CloseBrace()
            ;

#if FHIR_R3
            String outputPath = Path.Combine(DirHelper.FindParentDir("Tools"),
                                             "FhirKhit.Tools.R3",
                                             "ElementDefinitionNode.FindChild.cs");
#elif FHIR_R4
            String outputPath = Path.Combine(DirHelper.FindParentDir("Tools"),
                                             "FhirKhit.Tools.R4",
                                             "ElementDefinitionNode.FindChild.cs");
#endif
            editor.Save(outputPath);
        }
Esempio n. 9
0
        void WriteIds(String className,
                      String outputCodePath,
                      String csBlockName,
                      IEnumerable <String> penIdsEnum)
        {
            String[] penIds = penIdsEnum.ToArray();

            CodeEditor editor = new CodeEditor();

            editor.Load(Path.Combine(DirHelper.FindParentDir("BreastRadiology.XUnitTests"),
                                     "ResourcesMaker",
                                     outputCodePath));

            CodeBlockNested concepts = editor.Blocks.Find(csBlockName);

            if (concepts == null)
            {
                throw new Exception($"Can not find editor block {csBlockName}");
            }

            concepts.Clear();
            concepts.AppendLine($"#region Codes");
            for (Int32 i = 0; i < penIds.Length; i++)
            {
                String penId = penIds[i];
                UpdateClass(className, penId);

                if (this.spreadSheetData.TryGetRow(penId, out DataRow row) == false)
                {
                    throw new Exception($"Missing value for penid '{penId}'");
                }

                String code             = FormatCode(row[this.spreadSheetData.itemNameCol].ToString());
                String conceptBlockName = CodeValue(code);

                String App(String s, Object t, String sb)
                {
                    switch (t)
                    {
                    case DBNull dbNullValue:
                        return(s);

                    case String stringValue:
                        // verify we have correct column.
                        if (stringValue != sb)
                        {
                            Trace.WriteLine($"Invalid Modality '{stringValue}'. Expected {sb}");
                        }
                        if (String.IsNullOrEmpty(s) == false)
                        {
                            s += " | ";
                        }
                        s += $"Modalities.{sb}";
                        return(s);

                    default:
                        throw new Exception("Invalid excel cell value");
                    }
                }

                String validWith = App("", row[this.spreadSheetData.mgCol], "MG");
                ;
                validWith = App(validWith, row[this.spreadSheetData.mriCol], "MRI");
                validWith = App(validWith, row[this.spreadSheetData.nmCol], "NM");
                validWith = App(validWith, row[this.spreadSheetData.usCol], "US");

                concepts
                .AppendLine($"new ConceptDef()")
                .AppendLine($"    .SetCode(\"{conceptBlockName}\")")
                .AppendLine($"    .SetDisplay(\"{code}\")")
                //.AppendLine($"    .SetDefinition(\"[PR] {code}\")")
                .AppendLine($"    .MammoId(\"{penId}\")")
                ;
                if (String.IsNullOrEmpty(validWith) == false)
                {
                    concepts.AppendLine($"    .ValidModalities({validWith})");
                }

                AppIfNotNull(concepts, penId, "SetDicom", row[DicomCol]);
                AppIfNotNull(concepts, penId, "SetSnomedCode", row[SnomedCol]);
                //AppIfNotNull(concepts, penId, "SetOneToMany", row[13]);
                AppIfNotNull(concepts, penId, "SetSnomedDescription", row[SnomedDescriptionCol]);
                //AppIfNotNull(concepts, "SetICD10", row[ICD10Col]);
                if (AppIfNotNull(concepts, penId, "SetUMLS", row[UMLSCol]) == false)
                {
                    AppIfNotNull(concepts, penId, "SetACR", row[ACRCol]);
                }
                if (i < penIds.Length - 1)
                {
                    concepts
                    .AppendLine($",");
                }
            }

            concepts.AppendLine($"#endregion // Codes");
            editor.Save();
        }
Esempio n. 10
0
        void GenerateComplex(FHIRAllTypes fhirType,
                             String genDir)
        {
            String fhirTypeName = ModelInfo.FhirTypeToFhirTypeName(fhirType);
            Type   csType       = ModelInfo.GetTypeForFhirType(fhirTypeName);

            if (csType == null)
            {
                return;
            }

            Trace.WriteLine($"Generating fhir complex '{fhirType}'");
            CodeEditor      instanceEditor = new CodeEditor();
            CodeBlockNested instanceBlock  = instanceEditor.Blocks.AppendBlock();

            String instanceName = $"{fhirType.ToString()}_Item";

            instanceBlock
            .AppendLine("using System;")
            .AppendLine("using System.Diagnostics;")
            .AppendLine("using System.IO;")
            .AppendLine("using System.Linq;")
            .AppendLine("using Hl7.Fhir.Model;")
            .BlankLine()
            .AppendCode("namespace FhirKhit.Maker.Common")
            .OpenBrace()
            .AppendCode($"public class {instanceName} : Complex_Item")
            .OpenBrace()
            .DefineBlock(out CodeBlockNested fields)
            .CloseBrace()
            .CloseBrace()
            ;

            foreach (PropertyInfo pi in csType.GetProperties())
            {
                FhirElementAttribute attribute = pi.GetCustomAttribute <FhirElementAttribute>();
                if (attribute != null)
                {
                    //String min;
                    //String max;
                    //Type csType;
                    if (pi.PropertyType.IsList())
                    {
                        //min = "0";
                        //max = "*";
                        //csType = pi.PropertyType.GenericTypeArguments[0];
                    }
                    if (pi.PropertyType.IsNullable())
                    {
                        //min = "0";
                        //max = "1";
                        //csType = pi.PropertyType.GenericTypeArguments[0];
                    }
                    else
                    {
                        //csType = pi.PropertyType;
                        //min = "1";
                        //max = "1";
                    }
                }
                ;
            }
            //fields
            //;

            instanceEditor.Save(Path.Combine(genDir, $"{instanceName}.cs"));
        }
Esempio n. 11
0
        public void FhirConstructB()
        {
            CodeEditor editor = new CodeEditor();

            CodeBlockNested main = editor.Blocks.AppendBlock();

            main
            .AppendLine($"using System;")
            .AppendLine($"using System.Linq;")
            .AppendLine($"using System.Collections.Generic;")
            .AppendLine($"using System.Reflection;")
            .AppendLine($"using System.Text;")
            .AppendLine($"using FhirKhit.ProfGen.PGShared;")
            .AppendLine($"using FhirKhit.ProfGen.PGShared.CodeGen.CSApi.Extensions;")
            .AppendLine($"using FhirKhit.Tools;")
            .AppendLine($"using Hl7.Fhir.Introspection;")
            .AppendLine($"using Hl7.Fhir.Model;")
            .AppendLine($"using Hl7.Fhir.Support.Model;")
            .AppendLine($"using System.Diagnostics;")
            .AppendLine($"using Hl7.FhirPath;")
            .BlankLine()
            .AppendLine($"namespace FhirKhit.ProfGen.GenTests")
            .OpenBrace()
            .AppendCode($"public class FhirConstructUse")
            .OpenBrace()
            ;
            CodeBlockNested construct = main.AppendBlock();
            CodeBlockNested methods   = main.AppendBlock();

            main
            .CloseBrace()
            .CloseBrace()
            ;

            construct
            .AppendLine($"/// <summary>")
            .AppendLine($"/// generate code for eqch fhri element. Makes sure it compiles.")
            .AppendLine($"/// </summary>")
            .AppendCode($"public void Use()")
            .OpenBrace()
            .BlankLine()
            ;

            Int32 varNum = 0;

            foreach (FHIRAllTypes fhirType in Enum.GetValues(typeof(FHIRAllTypes)).OfType <FHIRAllTypes>())
            {
                Trace.WriteLine($"fhirType {fhirType}");
                String fhirTypeName = ModelInfo.FhirTypeToFhirTypeName(fhirType);
                Type   fhirCSType   = ModelInfo.GetTypeForFhirType(fhirTypeName);

                if (ModelInfo.IsPrimitive(fhirType))
                {
                    String varName1    = $"x{++varNum}";
                    String methodName1 = $"Method{++varNum}";

                    construct
                    .AppendCode($"{fhirCSType} {varName1} = {methodName1}();")
                    ;

                    Element fix = CreateFix(fhirCSType);
                    FhirConstruct.Construct(methods, fix, methodName1, out String propertyType1);
                }
                else if (ModelInfo.IsDataType(fhirType))
                {
                    if (Ignore(fhirType) == false)
                    {
                        String varName1    = $"x{++varNum}";
                        String methodName1 = $"Method{++varNum}";

                        construct
                        .AppendCode($"{fhirCSType} {varName1} = {methodName1}();")
                        ;

                        Element fix = CreateFix(fhirCSType);
                        FhirConstruct.Construct(methods, fix, methodName1, out String propertyType1);
                    }
                }
            }

            construct
            .CloseBrace()
            ;


#if FHIR_R2
            String outputPath = Path.Combine(DirHelper.FindParentDir("Projects"),
                                             "ProfGen",
                                             "R2",
                                             "FhirKhit.ProfGen.GenTests.R2",
                                             "Generated",
                                             "FhirConstructUse.cs");
#elif FHIR_R3
            String outputPath = Path.Combine(DirHelper.FindParentDir("Projects"),
                                             "ProfGen",
                                             "R3",
                                             "FhirKhit.ProfGen.GenTests.R3",
                                             "Generated",
                                             "FhirConstructUse.cs");
#elif FHIR_R4
            String outputPath = Path.Combine(DirHelper.FindParentDir("Projects"),
                                             "ProfGen",
                                             "R4",
                                             "FhirKhit.ProfGen.GenTests.R4",
                                             "Generated",
                                             "FhirConstructUse.cs");
#endif
            editor.Save(outputPath);
        }
Esempio n. 12
0
        public void FhirConstructA()
        {
            CodeEditor editor = new CodeEditor();

            CodeBlockNested main = editor.Blocks.AppendBlock();

            main
            .AppendLine($"using System;")
            .AppendLine($"using System.Linq;")
            .AppendLine($"using System.Collections.Generic;")
            .AppendLine($"using System.Reflection;")
            .AppendLine($"using System.Text;")
            .AppendLine($"using FhirKhit.ProfGen.PGShared;")
            .AppendLine($"using FhirKhit.ProfGen.PGShared.CodeGen.CSApi.Extensions;")
            .AppendLine($"using FhirKhit.Tools;")
            .AppendLine($"using Hl7.Fhir.Introspection;")
            .AppendLine($"using Hl7.Fhir.Model;")
            .AppendLine($"using Hl7.Fhir.Support.Model;")
            .AppendLine($"using System.Diagnostics;")
            .AppendLine($"using Hl7.FhirPath;")
            .BlankLine()
            .AppendLine($"namespace FhirKhit.ProfGen.CSApi")
            .OpenBrace()
            .AppendLine($"public static class FhirConstruct")
            .OpenBrace()
            ;
            CodeBlockNested construct = main.AppendBlock();
            CodeBlockNested methods   = main.AppendBlock();

            main
            .CloseBrace()
            .CloseBrace()
            ;

            construct
            .AppendLine($"/// <summary>")
            .AppendLine($"/// Return c# text to create indicated element.")
            .AppendLine($"/// </summary>")
            .AppendLine($"static public bool Construct(CodeBlockNested block,")
            .AppendCode($"    Element fix,")
            .AppendCode($"    String methodName,")
            .AppendCode($"    out String propertyType)")
            .OpenBrace()
            //.AppendCode($"const String fcn = \"Construct\";")
            .BlankLine()
            .AppendCode($"propertyType = null;")
            .AppendCode($"switch (fix.TypeName)")
            .OpenBrace()
            ;

            foreach (FHIRAllTypes fhirType in Enum.GetValues(typeof(FHIRAllTypes)).OfType <FHIRAllTypes>())
            {
                String fhirTypeName = ModelInfo.FhirTypeToFhirTypeName(fhirType);

                if (ModelInfo.IsPrimitive(fhirType))
                {
                    ConstructPrimitive(methods, construct, fhirType);
                }
                else if (ModelInfo.IsDataType(fhirType))
                {
                    ConstructDataType(methods, construct, fhirType);
                }
            }

            construct
            .CloseBrace()
            .AppendCode($"return false;")
            .CloseBrace()
            ;

            String outputPath = Path.Combine(DirHelper.FindParentDir("Projects"),
                                             "ProfGen",
                                             "PGShared",
                                             "FhirKhit.ProfGen.PGShared",
                                             "CodeGen",
                                             "CSApi",
                                             "FhirConstruct.cs");

            editor.Save(outputPath);
        }