Example #1
0
        /// <summary>
        /// Start creating a class.
        /// </summary>
        public bool StartClass(String className, Type fhirBaseClassType)
        {
            this.fhirBaseClassType = fhirBaseClassType;
            this.className         = className;
            string fhirTypeName = fhirBaseClassType.FriendlyName();

            this.classBlock = this.nameSpaceBlock.AppendBlock();
            this.classBlock
            .BlankLine()
            .SummaryOpen()
            .Summary($"Extension class to add slicing helper methods to {fhirTypeName}")
            .SummaryClose()
            .AppendLine($"public static class {className}")
            .OpenBrace()
            ;

            this.subClassBlock = classBlock.AppendBlock();
            this.subClassBlock.AppendLine($"#region {className} sub classes");

            this.fieldsBlock = classBlock.AppendBlock();
            this.fieldsBlock.AppendLine($"#region fields {className} fields");

            this.methodsBlock = classBlock.AppendBlock();
            this.methodsBlock.AppendLine($"#region methods {className} methods");

            return(true);
        }
Example #2
0
        public CSSliceCreator(String className,
                              CSCodeFormatter csCode,
                              CodeBlockNested subClassBlock,
                              CodeBlockNested methodsBlock,
                              ElementDefinitionNode elementNode,
                              Type fhirBaseClassType)
        {
            if (subClassBlock is null)
            {
                throw new ArgumentNullException(nameof(subClassBlock));
            }
            if (methodsBlock is null)
            {
                throw new ArgumentNullException(nameof(methodsBlock));
            }
            if (elementNode is null)
            {
                throw new ArgumentNullException(nameof(elementNode));
            }

            this.csCode = csCode;
            if (elementNode is null)
            {
                throw new ArgumentNullException(nameof(elementNode));
            }

            this.className         = className;
            this.subClassBlock     = subClassBlock.AppendBlock();
            this.methodsBlock      = methodsBlock.AppendBlock();
            this.elementNode       = elementNode;
            this.fhirBaseClassType = fhirBaseClassType;
        }
Example #3
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;
                }
            }
        }
Example #4
0
        void ConstructDataType(CodeBlockNested methods,
                               CodeBlockNested construct,
                               FHIRAllTypes fhirType)
        {
            if (GenerateCommon.Ignore(fhirType))
            {
                return;
            }

            this.tempCounter = 0;
            String fhirTypeName = ModelInfo.FhirTypeToFhirTypeName(fhirType);
            Type   csType       = ModelInfo.GetTypeForFhirType(fhirTypeName);
            String csTypeName   = csType.FriendlyName();

            construct
            .AppendCode($"case \"{fhirTypeName}\": // {fhirType}  - DataType")
            .OpenBrace()
            .AppendCode($"propertyType = \"{fhirTypeName}\";")
            .AppendCode($"return Construct(block, ({csTypeName})fix, varName);")
            .CloseBrace()
            .BlankLine()
            ;

            CodeBlockNested m = methods.AppendBlock();

            m
            .BlankLine()
            .AppendLine($"/// <summary>")
            .AppendLine($"/// Return c# text to create indicated element.")
            .AppendLine($"/// </summary>")
            .AppendCode($"static public bool Construct(CodeBlockNested block,")
            .AppendCode($"    {csTypeName} fix,")
            .AppendCode($"    String varName)")
            .OpenBrace()
            //.AppendCode($"const String fcn = \"Construct({fhirTypeName})\";")
            .BlankLine()
            .AppendCode($"if (block is null)")
            .AppendCode($"    throw new ArgumentNullException(nameof(block));")
            .AppendCode($"block")
            .AppendCode($"    .OpenBrace()")
            .AppendCode($"    .AppendCode(\"{csTypeName} temp = new {csTypeName}();\")")
            .AppendCode($"    ;")
            .AppendCode($"if (fix != null)")
            .OpenBrace()
            ;

            FixElements(m, csType, "fix", "temp");

            m
            .CloseBrace()
            .AppendCode($"block")
            .AppendCode($"    .AppendCode($\"{{varName}} = temp;\")")
            .AppendCode($"    .CloseBrace()")
            .AppendCode($"    ;")
            .AppendCode($"return  true;")
            .CloseBrace()
            ;
        }
        void ConstructDataType(CodeBlockNested methods,
                               CodeBlockNested construct,
                               FHIRAllTypes fhirType)
        {
            if (Ignore(fhirType))
            {
                return;
            }

            String fhirTypeName = ModelInfo.FhirTypeToFhirTypeName(fhirType);
            Type   csType       = ModelInfo.GetTypeForFhirType(fhirTypeName);
            String csTypeName   = csType.FriendlyName();

            construct
            .AppendCode($"case \"{fhirTypeName}\": // {fhirType}  - DataType")
            .OpenBrace()
            .AppendCode($"propertyType = \"{fhirTypeName}\";")
            .AppendCode($"return Construct(block, ({csTypeName})fix, methodName, methodAccess);")
            .CloseBrace()
            .BlankLine()
            ;

            CodeBlockNested m = methods.AppendBlock();

            m
            .BlankLine()
            .AppendLine($"/// <summary>")
            .AppendLine($"/// Return c# text to create indicated element.")
            .AppendLine($"/// </summary>")
            .AppendCode($"static public bool Construct(CodeBlockNested block,")
            .AppendCode($"    {csTypeName} fix,")
            .AppendCode($"    String methodName,")
            .AppendCode($"    String methodAccess = \"public\")")
            .OpenBrace()
            //.AppendCode($"const String fcn = \"Construct({fhirTypeName})\";")
            .BlankLine()
            .AppendCode($"block")
            .AppendCode($"    .AppendCode($\"{{methodAccess}} {csTypeName} {{methodName}}()\")")
            .AppendCode($"    .OpenBrace()")
            .AppendCode($"    .AppendCode(\"{csTypeName} retVal = new {csTypeName}();\")")
            .AppendCode($"    ;")
            .AppendCode($"if (fix != null)")
            .OpenBrace()
            ;

            FixElements(m, csType, "fix", "retVal");

            m
            .CloseBrace()
            .AppendCode($"block")
            .AppendCode($"    .AppendCode(\"return retVal;\")")
            .AppendCode($"    .CloseBrace()")
            .AppendCode($"    ;")
            .AppendCode($"return  true;")
            .CloseBrace()
            ;
        }
Example #6
0
        /// <summary>
        /// Create method to set element at indicated path to passed value.
        /// </summary>
        public bool GenerateSetElements(CodeBlockNested block,
                                        ElementDefinitionNode node,
                                        String baseName,
                                        String path,
                                        String leafNodeValue = null)
        {
            const String    fcn = nameof(GenerateSetElements);
            CodeBlockNested childBlock;

            if (block is null)
            {
                throw new ArgumentNullException(nameof(block));
            }
            if (node is null)
            {
                throw new ArgumentNullException(nameof(node));
            }
            if (path is null)
            {
                throw new ArgumentNullException(nameof(path));
            }

            void GenerateSetChildCode(ref string containerName,
                                      Type containerType,
                                      string itemName,
                                      Type itemType,
                                      String value)
            {
                if (containerName is null)
                {
                    throw new ArgumentNullException(nameof(containerName));
                }
                if (itemName is null)
                {
                    throw new ArgumentNullException(nameof(itemName));
                }

                String containerTypeName = containerType.FriendlyName();
                String itemTypeName      = itemType.FriendlyName();

                if (value == null)
                {
                    value = $"new {itemTypeName}()";
                }

                if (containerType.IsList())
                {
                    childBlock
                    .AppendCode($"if ({containerName}.Count == 0)")
                    .AppendCode($"    {containerName}.Add({value});")
                    ;
                    containerName = $"{containerName}[0].{itemName}";
                }
                else
                {
                    childBlock
                    .AppendCode($"if ({containerName}.{itemName} == null)")
                    .AppendCode($"    {containerName}.{itemName} = {value};")
                    ;
                    containerName = $"{containerName}.{itemName}";
                }
            }

            String[] pathItems = path.Split('.');
            Int32    i         = 0;

            if (pathItems[0] == node.Name)
            {
                i += 1;
            }

            childBlock = block.AppendBlock();
            String fullName = baseName;

            while (i < pathItems.Length)
            {
                String pathItem = pathItems[i];
                if (pathItem.StartsWith("resolve("))
                {
                    this.Gen.ConversionError(this.GetType().Name, fcn, $"TODO: FhirPath operator {pathItem} not implemented");
                    return(false);
                }
                else if (pathItem.StartsWith("extension(\""))
                {
                    this.Gen.ConversionError(this.GetType().Name, fcn, $"TODO: FhirPath operator {pathItem} not implemented");
                    return(false);
                }
                else if (pathItem.StartsWith("ofType("))
                {
                    this.Gen.ConversionError(this.GetType().Name, fcn, $"TODO: FhirPath operator {pathItem} not implemented");
                    return(false);
                }
                else
                {
                    if (node.TryGetAnyChild(pathItem, out ElementDefinitionNode next) == false)
                    {
                        this.Gen.ConversionError(this.GetType().Name, fcn, $"Child {pathItem} not found");
                        return(false);
                    }

                    PropertyInfo childProperty = node.FhirItemType.GetPropertyByFhirName(pathItem);
                    String       value         = null;
                    if (i == pathItems.Length - 1)
                    {
                        value = leafNodeValue;
                    }
                    GenerateSetChildCode(ref fullName, node.FhirItemType, childProperty.Name, next.FhirType, value);
                    node = next;
                }
                i += 1;
            }
            return(true);
        }
Example #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);
        }
Example #8
0
        bool DefineSliceOnValueDiscriminator(Int32 index,
                                             CodeBlockNested sliceDiscriminators,
                                             ElementDefinitionNode sliceNode,
                                             String varName,
                                             ElementDefinition.DiscriminatorComponent discriminator,
                                             String valueFilterMethod,
                                             String leafType)
        {
            const String fcn = nameof(DefineSliceOnValueDiscriminator);

            var     selectedNodes = sliceNode.Select(discriminator.Path).ToArray();
            var     fixedNodes    = selectedNodes.FixedValues().ToArray();
            Element fixedValue    = fixedNodes.SingleOrDefault();

            if (fixedValue == null)
            {
                this.gen.ConversionError(this.GetType().Name, fcn, $"Slice node lacks fixed element {discriminator.Path}");
                return(false);
            }

            String sliceName = sliceNode.Element.SliceName;

            CodeBlockNested valueMethodBlock = sliceClassMethods.AppendBlock();

            valueFilterMethod = CSMisc.ValueFilterName(CSMisc.MakePath(sliceNode.SlicePath(), discriminator.Path));
            // Note: We are defining method here, after we know the return value type.
            valueMethodBlock
            .BlankLine()
            .SummaryOpen()
            .AppendCode($"/// Return all elements for discriminator # {index+1}'")
            .SummaryLines(discriminator.ToFormatedJson())
            .SummaryClose()
            ;

            {
                GenerateFhirPathSearch g = new GenerateFhirPathSearch(this.gen);
                if (g.Generate(valueMethodBlock, "static", valueFilterMethod, elementNode, discriminator.Path, out Type leaf) == false)
                {
                    return(false);
                }
                leafType = leaf.FriendlyName();
            }


            String tempVarName = $"sliceOnValueDiscriminator";

            sliceDiscriminators
            .OpenBrace()
            .AppendLine($"/// Define discriminator'")
            .AppendLines("/// ", discriminator.ToFormatedJson().ToLines())
            .AppendCode($"var {tempVarName} = new SliceOnValueDiscriminator<{baseItemTypeName}, {leafType}>()")
            .OpenBrace()
            .AppendCode($"Path = \"{discriminator.Path}\",")
            .AppendCode($"ValueFilter = {valueFilterMethod}")
            .CloseBrace(";")
            ;

            ElementFixCode.Construct(sliceDiscriminators, fixedValue, $"{tempVarName}.Pattern", out String propertyType);

            sliceDiscriminators
            .AppendCode($"{varName} = {tempVarName};")
            .CloseBrace("")
            ;

            return(true);
        }
Example #9
0
        void GenerateCIMPLDataType(CodeBlockNested entryBlock,
                                   CodeBlockNested mapBlock,
                                   FHIRAllTypes fhirType)
        {
            String fhirTypeName = ModelInfo.FhirTypeToFhirTypeName(fhirType);
            Type   fhirCSType   = ModelInfo.GetTypeForFhirType(fhirTypeName);

            entryBlock
            .BlankLine()
            .AppendLine($"// Fhir data element {fhirTypeName} definition")
            .AppendCode($"Entry: {fhirTypeName}")
            ;


            CodeBlockNested item = entryBlock.AppendBlock();
            CodeBlockNested vars = entryBlock.AppendBlock();

            foreach (PropertyInfo pi in fhirCSType.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";
                    }

                    String name = attribute.Name.ToMachineName();
                    item
                    .AppendCode($"Property: {name} {min}..{max}")
                    ;

                    String typeName   = null;
                    String csTypeName = csType.FriendlyName();
                    switch (csTypeName)
                    {
                    case "string":
                        OutputProperty(attribute, item, min, max);
                        break;

                    default:
                        typeName = ModelInfo.GetFhirTypeNameForType(pi.PropertyType);
                        if (String.IsNullOrEmpty(typeName))
                        {
                            throw new Exception($"Can not determine fhir type for c# type {csTypeName}");
                        }
                        break;
                    }

                    vars
                    .BlankLine()
                    .AppendCode($"Element: {name}")
                    .AppendCode($"Value: {typeName}")
                    ;

                    //    methods
                    //        .AppendCode($"case \"{attribute.Name}\":")
                    //        .OpenBrace()
                    //        .AppendCode($"ElementDefinition e = new ElementDefinition")
                    //        .OpenBrace()
                    //        .AppendCode($"Path = $\"{{parentPath}}.{attribute.Name}\",")
                    //        .AppendCode($"Short = \"{fhirType}.{attribute.Name} common attribute\",")
                    //        .AppendCode($"Min = {min},")
                    //        .AppendCode($"Max = \"{max}\"")
                    //        .CloseBrace(";")
                    //        .AppendCode($"retVal = new ElementNode(this, e, typeof({pi.PropertyType.FriendlyName()}), nameof({fhirCSType.FriendlyName()}.{pi.Name}));")
                    //        .AppendCode($"retVal.AutoGeneratedFlag = true;")
                    //        .AppendCode($"break;")
                    //        .CloseBrace(";")
                    //        ;
                }
            }
        }
Example #10
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);
        }
Example #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);
        }
Example #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);
        }
Example #13
0
        //$$$ Delete
        /// <summary>
        /// Traverse children using simple fhir path query.
        /// Return selected elements, or null if not found.
        /// </summary>
        public bool Generate(CodeBlockNested block,
                             String methodModifiers,
                             String methodName,
                             ElementDefinitionNode node,
                             String path,
                             out Type leafType)
        {
            const String fcn = nameof(Generate);

            if (block is null)
            {
                throw new ArgumentNullException(nameof(block));
            }
            if (methodModifiers is null)
            {
                throw new ArgumentNullException(nameof(methodModifiers));
            }
            if (methodName is null)
            {
                throw new ArgumentNullException(nameof(methodName));
            }
            if (node is null)
            {
                throw new ArgumentNullException(nameof(node));
            }
            if (path is null)
            {
                throw new ArgumentNullException(nameof(path));
            }

            //String fhirTypeName = node.FhirType.FriendlyName();
            String fhirItemTypeName = node.FhirItemType.FriendlyName();
            // we need to write header after we determine leaf node type.
            CodeBlockNested methodHeaderBlock = block.AppendBlock();

            block
            .OpenBrace()
            .BlankLine()
            ;

            childBlock = block.AppendBlock();

            String[] pathItems = path.Split('.');
            Int32    i         = 0;

            if (pathItems[0] == node.Name)
            {
                i += 1;
            }

            Int32 resultCounter = 0;

            leafType = null;
            String resultThis = "head";

            while (i < pathItems.Length)
            {
                resultCounter += 1;
                String resultNext = $"result{resultCounter}";

                String pathItem = pathItems[i++];
                if (pathItem.StartsWith("resolve("))
                {
                    this.gen.ConversionError(this.GetType().Name, fcn, $"TODO: FhirPath operator {pathItem} not implemented");
                    return(false);
                }
                else if (pathItem.StartsWith("extension(\""))
                {
                    this.gen.ConversionError(this.GetType().Name, fcn, $"TODO: FhirPath operator {pathItem} not implemented");
                    return(false);
                }
                else if (pathItem.StartsWith("ofType("))
                {
                    this.gen.ConversionError(this.GetType().Name, fcn, $"TODO: FhirPath operator {pathItem} not implemented");
                    return(false);
                }
                else
                {
                    if (node.TryGetAnyChild(pathItem, out ElementDefinitionNode next) == false)
                    {
                        this.gen.ConversionError(this.GetType().Name, fcn, $"Child {pathItem} not found");
                        return(false);
                    }

                    Type         nodeType          = node.FhirItemType;
                    PropertyInfo childProperty     = nodeType.GetPropertyByFhirName(pathItem);
                    String       childPropertyName = childProperty.Name;
                    String       childMethodName   = GenerateGetChild(childPropertyName, nodeType, childProperty.PropertyType);

                    block.AppendCode($"IEnumerable<{next.FhirItemType.FriendlyName()}> {resultNext} = {childMethodName}({resultThis});");
                    resultThis = resultNext;
                    node       = next;
                }
            }

            block
            .AppendCode($"return {resultThis};")
            .CloseBrace()
            ;

            leafType = node.FhirItemType;

            methodHeaderBlock
            .AppendCode($"{methodModifiers} IEnumerable<{leafType.FriendlyName()}> {methodName}(IEnumerable<{fhirItemTypeName}> head)")
            ;
            return(true);
        }