bool ILanguangeExporter.AppendCodes(
            ref StringBuilder sb,
            FhirProperty property,
            string parentName
            )
        {
            // **** put a comment ****

            sb.Append($"/**\n * Code Values for the {parentName}.{property.Name} field\n */\n");

            // **** open our enum ***

            sb.Append($"export enum {parentName}{property.NameCapitalized}Codes {{\n");

            // **** start adding values ****

            foreach (string code in property.CodeValues)
            {
                FhirTypeManager.SanitizeForCode(code, _reservedWordsSet, out string name, out string value);

                sb.Append($"\t{name.ToUpper()} = \"{value}\",\n");
            }

            // **** close our enum ***

            sb.Append("}\n");

            return(true);
        }
        bool ILanguangeExporter.AppendCodes(
            ref StringBuilder sb,
            FhirProperty property,
            string parentName
            )
        {
            // **** put a comment ****

            sb.Append($"\t///<summary>Code Values for the {parentName}.{property.Name} field</summary>\n");

            // **** open our enum ***

            sb.Append($"\tpublic sealed class {parentName}{property.NameCapitalized}Codes {{\n");

            // **** start adding values ****

            foreach (string code in property.CodeValues)
            {
                FhirTypeManager.SanitizeForCode(code, _reservedWordsSet, out string name, out string value);

                sb.Append($"\t\tpublic const string {name.ToUpper()} = \"{value}\";\n");
            }

            // **** close our enum ***

            sb.Append("\t}\n");

            return(true);
        }
예제 #3
0
        ///-------------------------------------------------------------------------------------------------
        /// <summary>Main entry-point for this application.</summary>
        ///
        /// <remarks>Gino Canessa, 7/12/2019.</remarks>
        ///
        /// <param name="args">An array of command-line argument strings.</param>
        ///-------------------------------------------------------------------------------------------------

        static void Main(string[] args)
        {
            // **** start timing ****

            Stopwatch timingWatch = Stopwatch.StartNew();

            // **** initialize our manager ****

            FhirTypeManager.Init();

            // **** process based on command line arguments ****

            Parser.Default.ParseArguments <Options>(args)
            .WithParsed <Options>(options => {
                ProcessFhirDirectory(
                    options
                    );
            })
            .WithNotParsed(errors => { Console.WriteLine("Invalid arguments"); });

            // **** done ****

            long elapsedMs = timingWatch.ElapsedMilliseconds;

            Console.WriteLine($"Finished in: {elapsedMs / 1000.0} s");
        }
예제 #4
0
        ///-------------------------------------------------------------------------------------------------
        /// <summary>Process the structure primitive type.</summary>
        ///
        /// <remarks>Gino Canessa, 8/12/2019.</remarks>
        ///
        /// <param name="sd">      The SD.</param>
        /// <param name="filename">Filename of the file.</param>
        ///-------------------------------------------------------------------------------------------------

        static void ProcessStructurePrimitiveType(fhir.StructureDefinition sd, string filename)
        {
            //Console.WriteLine($"Primitive: {sd.Name}:{GetJsonTypeFromStructure(sd)} - {filename}");

            // **** add our type ****

            FhirTypeManager.ProcessSpreadsheetType(sd.Name, GetPrimitiveJsonTypeFromStructure(sd), sd.Description, true, filename);
        }
예제 #5
0
        ///-------------------------------------------------------------------------------------------------
        /// <summary>Process the data elements table.</summary>
        ///
        /// <remarks>Gino Canessa, 7/8/2019.</remarks>
        ///
        /// <param name="dt">              The dt.</param>
        /// <param name="isPrimitive">     True if is primitive, false if not.</param>
        /// <param name="sourceFilename">  Filename of the source file.</param>
        /// <param name="firstElementName">[out] Name of the first element.</param>
        ///-------------------------------------------------------------------------------------------------

        static void ProcessDataElementsTable(
            DataTable dt,
            bool isPrimitive,
            string sourceFilename,
            out string firstElementName
            )
        {
            // **** grab the indexes of the columns we care about ****

            int ordinalElement     = dt.Columns["Element"].Ordinal;
            int ordinalCardinality = dt.Columns["Card."].Ordinal;
            int ordinalType        = dt.Columns["Type"].Ordinal;
            int ordinalComment     = dt.Columns["Definition"].Ordinal;
            int ordinalShortName   = dt.Columns["Short Name"].Ordinal;

            // **** check for no rows ****

            if ((dt.Rows == null) || (dt.Rows.Count == 0))
            {
                firstElementName = "";
                return;
            }

            // **** grab the element name from the first row ****

            firstElementName = dt.Rows[0][ordinalElement].ToString();

            // **** iterate over the items in this table ****

            foreach (DataRow row in dt.Rows)
            {
                // **** grab our data ****

                string element     = row[ordinalElement].ToString();
                string cardinality = row[ordinalCardinality].ToString();
                string baseType    = row[ordinalType].ToString();
                string comment     = row[ordinalComment].ToString();

                // **** check for no comment (use short name) ****

                if (string.IsNullOrEmpty(comment))
                {
                    comment = row[ordinalShortName].ToString();
                }

                // **** skip empty rows ****

                if (string.IsNullOrEmpty(element))
                {
                    continue;
                }

                // **** process this field ****

                FhirTypeManager.ProcessSpreadsheetDataElement(element, baseType, comment, cardinality, isPrimitive, sourceFilename);
            }
        }
        bool ILanguangeExporter.AppendValueSetCodeConcept(
            ref StringBuilder sb,
            string sanitizedValueSetName,
            string sanitizedCodeName,
            fhir.CodeSystemConcept concept,
            string systemUrl
            )
        {
            string comment;

            // **** start with a comment ****

            if (!string.IsNullOrEmpty(concept.Definition))
            {
                comment = FhirTypeManager.SanitizeComment(concept.Definition, _lineComment, _indentChar, 2);
            }
            else if (!string.IsNullOrEmpty(concept.Display))
            {
                comment = FhirTypeManager.SanitizeComment(concept.Display, _lineComment, _indentChar, 2);
            }
            else
            {
                comment = $"Value for '{concept.Code}'</summary>\n";
            }

            // **** coding is exported inline (before internal and external interfaces) ****

            sb.Append($"const {sanitizedValueSetName}_{sanitizedCodeName}: Coding = {{\n");
            sb.Append($"\t\tcode: \"{concept.Code}\",\n");
            if (!string.IsNullOrEmpty(concept.Display))
            {
                sb.Append($"\t\tdisplay: \"{concept.Display.Replace("\"", "\\\"")}\",\n");
            }
            sb.Append($"\t\tsystem: \"{systemUrl}\"\n");
            sb.Append($"\t}};\n");

            // **** add this code to our interface ****

            //_valueSetInterfaceSB.Append($"\t/**\n\t * {comment}\n\t */\n");
            //_valueSetInterfaceSB.Append($"\t{sanitizedCodeName}: Coding,\n");

            // **** add this code to our export ****

            _valueSetExportSB.Append($"\t/**\n\t * {comment}\n\t */\n");
            _valueSetExportSB.Append($"\t{sanitizedCodeName}: {sanitizedValueSetName}_{sanitizedCodeName},\n");

            return(true);
        }
        bool ILanguangeExporter.AppendFhirProperty(
            ref StringBuilder sb,
            FhirProperty property,
            string typeName,
            bool useLowerCaseName
            )
        {
            // **** always use lower-case start ****

            string name = FhirTypeManager.SanitizeForProperty(property.Name, _reservedWordsSet);

            string comment = FhirTypeManager.SanitizeComment(property.Comment, _lineComment, _indentChar, 2);

            string optionalFlagString = (_flagOptionals && property.IsOptional) ? "?" : "";

            // **** ****

            if (property.IsArray)
            {
                sb.Append(
                    $"\t/**\n" +
                    $"\t * {comment}\n" +
                    //$"\t * Cardinality: {property.Cardinality}\n" +
                    $"\t */\n" +
                    $"\t{name}{optionalFlagString}: {typeName}[];\n" +
                    $"\t/**\n" +
                    $"\t * May contain extended information for property: '{name}'\n" +
                    $"\t */\n" +
                    $"\t_{name}?: Element[];\n"
                    );

                return(true);
            }

            sb.Append(
                $"\t/**\n" +
                $"\t * {comment}\n" +
                //$"\t * Cardinality: {property.Cardinality}\n" +
                $"\t */\n" +
                $"\t{name}{optionalFlagString}: {typeName};\n" +
                $"\t/**\n" +
                $"\t * May contain extended information for property: '{name}'\n" +
                $"\t */\n" +
                $"\t_{name}?: Element;\n"
                );

            return(true);
        }
예제 #8
0
        ///-------------------------------------------------------------------------------------------------
        /// <summary>Writes a C#.</summary>
        ///
        /// <remarks>Gino Canessa, 8/12/2019.</remarks>
        ///
        /// <param name="options">Options for controlling the operation.</param>
        ///-------------------------------------------------------------------------------------------------

        static void WriteCSharp(Options options, int style)
        {
            LanguageCSharp lang = new LanguageCSharp();

            // **** set the style ****

            lang.LanguageStyle = style;

            // **** enable/disable polymorphic deserialization ****

            lang.PolymorphicDeserialization = options.LanguageCSharpPolymorphic;

            // **** for our filename ****

            string filename;

            // **** check for having an extension ****

            if (Path.HasExtension(options.OutputFile))
            {
                filename = options.OutputFile;
            }
            else
            {
                filename = $"{options.OutputFile}{lang.GetFilenamePartForStyle}.{((ILanguangeExporter)lang).SourceFileExtension}";
            }

            // **** ****

            Console.WriteLine($"Writing C# ({lang.GetStyleName}) file: {filename}");

            // **** start our file ****

            using (StreamWriter writer = new StreamWriter(filename))
            {
                // **** output our data ****

                FhirTypeManager.OutputForLang(
                    writer,
                    lang,
                    options.TypesToOutput,
                    options.OutputNamespace,
                    options.ExcludeCodes
                    );
                writer.Flush();
            }
        }
예제 #9
0
        ///-------------------------------------------------------------------------------------------------
        /// <summary>Process the XML spreadsheets in a directory, as described by options.</summary>
        ///
        /// <remarks>Gino Canessa, 12/5/2019.</remarks>
        ///
        /// <param name="options">Options for controlling the operation.</param>
        ///
        /// <returns>True if it succeeds, false if it fails.</returns>
        ///-------------------------------------------------------------------------------------------------

        static bool ProcessXmlSpreadsheetsFor(Options options)
        {
            string dir = Path.Combine(options.FhirDirectory, "source");

            // **** check for this directory existing ****

            if (!Directory.Exists(dir))
            {
                Console.WriteLine("Source directory not found! Skipping XML Spreadsheets");
                return(false);
            }

            // **** build our list of types to include ****

            string[] types = options.TypesForXmlSpreadsheets.Split('|');

            // **** traverse the types we want ****

            foreach (string typeName in types)
            {
                // **** build the filename we expect ****

                string filename = Path.Combine(options.FhirDirectory, "source", typeName, $"{typeName}-spreadsheet.xml");

                // **** check for this file ****

                if (!File.Exists(filename))
                {
                    Console.WriteLine($"Could not find {filename}, will not process XML spreadsheet!");
                    continue;
                }

                // **** remove this type (and subtypes) from the current list ****

                FhirTypeManager.RemoveType(typeName);

                // **** process this file ****

                ProcessResourceXmlFile(filename, false);
            }

            // **** ok ****

            return(true);
        }
        bool ILanguangeExporter.AppendValueSetOpen(ref StringBuilder sb, string sanitizedAlias, string sanitizedName, fhir.ValueSet valueSet)
        {
            // **** start with a comment ****

            if (!string.IsNullOrEmpty(valueSet.Description))
            {
                sb.Append($"\t///<summary>{FhirTypeManager.SanitizeComment(valueSet.Description, _lineComment, _indentChar, 1)}</summary>\n");
            }
            else
            {
                sb.Append($"\t///<summary>Expanded ValueSet from {valueSet.Url}</summary>\n");
            }

            // **** open our value set ****

            sb.Append($"\tpublic abstract class {sanitizedName}\n\t{{\n");

            return(true);
        }
예제 #11
0
        ///-------------------------------------------------------------------------------------------------
        /// <summary>Process the primitive table.</summary>
        ///
        /// <remarks>Gino Canessa, 7/5/2019.</remarks>
        ///
        /// <param name="dt">The dt.</param>
        ///-------------------------------------------------------------------------------------------------

        static void ProcessPrimitiveTable(DataTable dt, string sourceFilename)
        {
            // **** grab the indexes of the columns we care about ****

            int ordinalName    = dt.Columns["Data Type"].Ordinal;
            int ordinalType    = dt.Columns["Json"].Ordinal;
            int ordinalComment = dt.Columns["Definition"].Ordinal;

            // **** iterate over the items in this table ****

            foreach (DataRow row in dt.Rows)
            {
                // **** grab our data ****

                string name     = row[ordinalName].ToString();
                string baseType = row[ordinalType].ToString();
                string comment  = row[ordinalComment].ToString();

                FhirTypeManager.ProcessSpreadsheetType(name, baseType, comment, true, sourceFilename);
            }
        }
예제 #12
0
        ///-------------------------------------------------------------------------------------------------
        /// <summary>Process the restrictions table.</summary>
        ///
        /// <remarks>Gino Canessa, 7/10/2019.</remarks>
        ///
        /// <param name="dt">             The dt.</param>
        /// <param name="elementBaseName">Name of the element base.</param>
        /// <param name="isPrimitive">    True if is primitive, false if not.</param>
        /// <param name="sourceFilename"> Filename of the source file.</param>
        ///-------------------------------------------------------------------------------------------------

        static void ProcessRestrictionsTable(
            DataTable dt,
            string elementBaseName,
            bool isPrimitive,
            string sourceFilename
            )
        {
            // **** grab the indexes of the columns we care about ****

            int ordinalName    = dt.Columns["Name"].Ordinal;
            int ordinalComment = dt.Columns["Definition"].Ordinal;

            // **** iterate over the items in this table ****

            foreach (DataRow row in dt.Rows)
            {
                // **** grab our data ****

                string name    = row[ordinalName].ToString();
                string comment = row[ordinalComment].ToString();

                // **** skip empty rows ****

                if (string.IsNullOrEmpty(name))
                {
                    continue;
                }

                // **** skip standard restrictions (not interested right now) ****

                if (name.Equals(elementBaseName, StringComparison.Ordinal))
                {
                    continue;
                }

                // **** make this a type ****

                FhirTypeManager.ProcessSpreadsheetType(name, elementBaseName, comment, isPrimitive, sourceFilename);
            }
        }
        bool ILanguangeExporter.AppendValueSetOpen(ref StringBuilder sb, string sanitizedAlias, string sanitizedName, ValueSet valueSet)
        {
            // **** clear our related objects for the value set ****

            //_valueSetInterfaceSB.Clear();
            _valueSetExportSB.Clear();

            string comment;

            // **** start with a comment ****

            if (!string.IsNullOrEmpty(valueSet.Description))
            {
                comment =
                    $"/**\n" +
                    $" * {FhirTypeManager.SanitizeComment(valueSet.Description, _lineComment, _indentChar, 1)}\n" +
                    $" */\n";
            }
            else
            {
                comment =
                    $"/**\n" +
                    $" * Expanded ValueSet from {valueSet.Url}\n" +
                    $" */\n";
            }

            // **** add our comment ****

            //_valueSetInterfaceSB.Append(comment);
            _valueSetExportSB.Append(comment);

            // **** open our value set (interface has to be before export) ****

            //_valueSetInterfaceSB.Append($"interface {sanitizedName}_Interface {{\n");
            //_valueSetExportSB.Append($"export const {sanitizedName}: {sanitizedName}_Interface = {{\n");
            _valueSetExportSB.Append($"export const {sanitizedName} = {{\n");

            return(true);
        }
예제 #14
0
        ///-------------------------------------------------------------------------------------------------
        /// <summary>Writes the TypeScript file</summary>
        ///
        /// <remarks>Gino Canessa, 7/31/2019.</remarks>
        ///
        /// <param name="options">Options for controlling the operation.</param>
        ///-------------------------------------------------------------------------------------------------

        static void WriteTypeScript(Options options)
        {
            LanguageTypeScript lang = new LanguageTypeScript();

            string filename;

            // **** check for having an extension ****

            if (Path.HasExtension(options.OutputFile))
            {
                filename = options.OutputFile;
            }
            else
            {
                filename = $"{options.OutputFile}.{((ILanguangeExporter)lang).SourceFileExtension}";
            }

            // **** ****

            Console.WriteLine($"Writing TypeScript file: {filename}");

            // **** start our file ****

            using (StreamWriter writer = new StreamWriter(filename))
            {
                // **** output our data ****

                FhirTypeManager.OutputForLang(
                    writer,
                    lang,
                    options.TypesToOutput,
                    options.OutputNamespace,
                    options.ExcludeCodes
                    );
                writer.Flush();
            }
        }
        bool ILanguangeExporter.AppendValueSetCodeConcept(
            ref StringBuilder sb,
            string sanitizedValueSetName,
            string sanitizedCodeName,
            fhir.CodeSystemConcept concept,
            string systemUrl
            )
        {
            // **** start with a comment ****

            if (!string.IsNullOrEmpty(concept.Definition))
            {
                sb.Append($"\t\t///<summary>{FhirTypeManager.SanitizeComment(concept.Definition, _lineComment, _indentChar, 2)}</summary>\n");
            }
            else if (!string.IsNullOrEmpty(concept.Display))
            {
                sb.Append($"\t\t///<summary>{FhirTypeManager.SanitizeComment(concept.Display, _lineComment, _indentChar, 2)}</summary>\n");
            }
            else
            {
                sb.Append($"\t\t///<summary>Value for '{concept.Code}'</summary>\n");
            }

            // **** start our coding ****

            sb.Append($"\t\tpublic static readonly Coding {sanitizedCodeName} = new Coding\n\t\t{{\n");
            sb.Append($"\t\t\tCode = \"{concept.Code}\",\n");
            if (!string.IsNullOrEmpty(concept.Display))
            {
                sb.Append($"\t\t\tDisplay = \"{concept.Display.Replace("\"", "\\\"")}\",\n");
            }
            sb.Append($"\t\t\tSystem = \"{systemUrl}\"\n");
            sb.Append($"\t\t}};\n");

            return(true);
        }
        bool ILanguangeExporter.AppendFhirProperty(
            ref StringBuilder sb,
            FhirProperty property,
            string typeName,
            bool useLowerCaseName
            )
        {
            string nameCamel  = FhirTypeManager.SanitizeForProperty(property.Name, _reservedWordsSet);
            string namePascal = FhirTypeManager.SanitizeForProperty(property.NameCapitalized, _reservedWordsSet);

            string propertyName;
            string extendedName;

            if (useLowerCaseName)
            {
                propertyName = nameCamel;
                extendedName = nameCamel;
            }
            else
            {
                switch (LanguageStyle)
                {
                case (int)CSharpStyle.SystemTextJson:
                    propertyName = namePascal;
                    extendedName = namePascal;
                    break;

                case (int)CSharpStyle.Newtonsoft:
                    propertyName = namePascal;
                    extendedName = namePascal;
                    break;

                case (int)CSharpStyle.Plain:
                default:
                    propertyName = namePascal;
                    extendedName = nameCamel;
                    break;
                }
            }

            string propertyAnnotation = "";
            string extendedAnnotation = "";

            switch (LanguageStyle)
            {
            case (int)CSharpStyle.SystemTextJson:
                propertyAnnotation = $"\t\t[JsonPropertyName(\"{property.Name}\")]\n";
                extendedAnnotation = $"\t\t[JsonPropertyName(\"_{property.Name}\")]\n";
                break;

            case (int)CSharpStyle.Newtonsoft:
                propertyAnnotation = $"\t\t[JsonProperty(PropertyName = \"{property.Name}\")]\n";
                extendedAnnotation = $"\t\t[JsonProperty(PropertyName = \"_{property.Name}\")]\n";
                break;

            case (int)CSharpStyle.Plain:
            default:

                break;
            }

            string comment = FhirTypeManager.SanitizeComment(property.Comment, _lineComment, _indentChar, 2);

            string optionalFlagString = (_flagOptionals && property.IsOptional) ? "?" : "";

            // **** nullable reference types are not allowed in current C# ****

            switch (typeName)
            {
            case "bool":
            case "decimal":
            case "DateTime":
            case "int":
            case "uint":
            case "Guid":

                // **** ignore - types can be optional ****
                break;

            default:
                // **** do not allow reference types to be null (for now) ****
                optionalFlagString = "";
                break;
            }

            // **** ****

            if (property.IsArray)
            {
                sb.Append(
                    $"\t\t///<summary>{comment}</summary>\n" +
                    propertyAnnotation +
                    $"\t\tpublic {typeName}[] {propertyName} {{ get; set; }}\n" +
                    $"\t\t///<summary>May contain extended information for property: '{propertyName}'</summary>\n" +
                    extendedAnnotation +
                    $"\t\tpublic Element[] _{extendedName} {{ get; set; }}\n");

                return(true);
            }

            sb.Append(
                $"\t\t///<summary>{comment}</summary>\n" +
                propertyAnnotation +
                $"\t\tpublic {typeName}{optionalFlagString} {propertyName} {{ get; set; }}\n" +
                $"\t\t///<summary>May contain extended information for property: '{propertyName}'</summary>\n" +
                extendedAnnotation +
                $"\t\tpublic Element _{extendedName} {{ get; set; }}\n");

            return(true);
        }
        bool ILanguangeExporter.AppendFhirTypeOpen(ref StringBuilder sb, FhirType fhirType)
        {
            string comment = FhirTypeManager.SanitizeComment(fhirType.Comment, _lineComment, _indentChar, 1);

            if ((fhirType.Properties == null) || (fhirType.Properties.Count == 0))
            {
                //string typeName = string.IsNullOrEmpty(fhirType.TypeName) ? "object" : fhirType.TypeName;

                sb.Append(
                    $"/**\n" +
                    $" * {comment}\n" +
                    $" * From: {fhirType.SourceFilename}\n" +
                    $" */\n" +
                    $"export type {fhirType.Name} = {fhirType.TypeName};\n"
                    );
                return(true);
            }

            // **** start with the interface open ****

            if (string.IsNullOrEmpty(fhirType.TypeName) || fhirType.Name.Equals("Element"))
            {
                sb.Append(
                    $"/**\n" +
                    $" * {comment}\n" +
                    $" * From: {fhirType.SourceFilename}\n" +
                    $" */\n" +
                    $"export interface {fhirType.Name} {{\n"
                    );
            }
            else if (fhirType.Name.Equals(fhirType.TypeName, StringComparison.Ordinal))
            {
                sb.Append(
                    $"/**\n" +
                    $" * {comment}\n" +
                    $" * From: {fhirType.SourceFilename}\n" +
                    $" */\n" +
                    $"export interface {fhirType.Name} extends Element {{\n"
                    );
            }
            else
            {
                sb.Append(
                    $"/**\n" +
                    $" * {comment}\n" +
                    $" * From: {fhirType.SourceFilename}\n" +
                    $" */\n" +
                    $"export interface {fhirType.Name} extends {fhirType.TypeName} {{\n"
                    );
            }

            // **** output resource type first (if necessary) ****

            if (FhirTypeManager.DoesTypeRequireResourceTag(fhirType.Name))
            {
                sb.Append(
                    $"\t/** Resource Type Name (for serialization) */\n" +
                    $"\tresourceType: '{fhirType.Name}';\n"
                    );
            }

            return(true);
        }
예제 #18
0
        static void AddMissingTypes()
        {
            // TODO(ginoc): Remove once we find the actual definition of xhtml

            if (!FhirTypeManager.Exists("xhtml"))
            {
                FhirTypeManager.ProcessSpreadsheetType(
                    "xhtml",
                    "string",
                    "WARN: xhtml is defined as string as a definition cannot be found!",
                    true,
                    "definition-file-not-found"
                    );
            }

            // TODO(ginoc): Remove once we find the actual definition of SimpleQuantity

            if (!FhirTypeManager.Exists("SimpleQuantity"))
            {
                FhirTypeManager.ProcessSpreadsheetType(
                    "SimpleQuantity",
                    "Quantity",
                    "WARN: SimpleQuantity definition cannot be found!",
                    false,
                    "definition-file-not-found"
                    );
            }

            // TODO(ginoc): Remove once we find the actual definition of MoneyQuantity

            if (!FhirTypeManager.Exists("MoneyQuantity"))
            {
                FhirTypeManager.ProcessSpreadsheetType(
                    "MoneyQuantity",
                    "Quantity",
                    "WARN: MoneyQuantity definition cannot be found!",
                    false,
                    "definition-file-not-found"
                    );
            }

            // TODO(ginoc): Remove once we find the actual definition of Logical

            if (!FhirTypeManager.Exists("Logical"))
            {
                FhirTypeManager.ProcessSpreadsheetType(
                    "Logical",
                    "Element",
                    "WARN: Logical definition cannot be found!",
                    false,
                    "definition-file-not-found"
                    );
            }

            // TODO(ginoc): Remove once we find the actual definition of Structure (only seen in datatypes/actiondefinition.xml)

            if (!FhirTypeManager.Exists("Structure"))
            {
                FhirTypeManager.ProcessSpreadsheetType(
                    "Structure",
                    "Element",
                    "WARN: Structure definition cannot be found!",
                    false,
                    "definition-file-not-found"
                    );
            }
        }
예제 #19
0
        static bool ProcessPublishedJson(Options options)
        {
            string dir = Path.Combine(options.FhirDirectory, "publish");

            // **** check for this directory existing ****

            if (!Directory.Exists(dir))
            {
                Console.WriteLine("Publish directory not found!");
                return(false);
            }

            // **** get all canonical files in the publish directory ****

            string[] files = Directory.GetFiles(dir, "*.canonical.json", SearchOption.AllDirectories);

            // **** traverse the files ****

            foreach (string filename in files)
            {
                // **** read the contents ****

                string contents = File.ReadAllText(filename);

                // **** act depending on contents ****

                if (contents.Contains("\"resourceType\":\"StructureDefinition\""))
                {
                    // **** check for ignoring these ****

                    if (options.UseOnlyXmlSpreadsheets)
                    {
                        continue;
                    }

                    // **** parse into an object we can work with ****

                    fhir.StructureDefinition sd = JsonConvert.DeserializeObject <fhir.StructureDefinition>(contents);

                    // **** process this structure definition ****

                    ProcessStructureDefinition(sd, filename);

                    // **** done with this file ****

                    continue;
                }

                if (contents.Contains("\"resourceType\":\"CodeSystem\""))
                {
                    if (options.ExcludeCodeSystems)
                    {
                        continue;
                    }

                    // **** parse into an object we can work with ****

                    fhir.CodeSystem cs = JsonConvert.DeserializeObject <fhir.CodeSystem>(contents);

                    // **** process this code system ****

                    FhirTypeManager.LoadCodeSystem(cs);

                    // **** done with this file ****

                    continue;
                }

                if (contents.Contains("\"resourceType\":\"ValueSet\""))
                {
                    if (options.ExcludeValueSets)
                    {
                        continue;
                    }

                    // **** parse into an object we can work with ****

                    fhir.ValueSet vs = JsonConvert.DeserializeObject <fhir.ValueSet>(contents);

                    // **** process this value set ****

                    FhirTypeManager.LoadValueSet(vs, filename);

                    // **** done with this file ****

                    continue;
                }
            }


            // **** success *****

            return(true);
        }
예제 #20
0
        ///-------------------------------------------------------------------------------------------------
        /// <summary>Process the structure type.</summary>
        ///
        /// <remarks>Gino Canessa, 8/20/2019.</remarks>
        ///
        /// <param name="sd">      The SD.</param>
        /// <param name="filename">Filename of the file.</param>
        ///-------------------------------------------------------------------------------------------------

        static void ProcessStructureType(fhir.StructureDefinition sd, string filename)
        {
            // **** figure out if this is a derived type ****

            string baseType = GetJsonTypeFromStructure(sd);

            if (string.IsNullOrEmpty(baseType))
            {
                // **** use the base type ****

                baseType = sd.Type;
            }

            // **** reformat circular references ****

            if (baseType.Equals(sd.Id, StringComparison.Ordinal))
            {
                baseType = "";
            }

            // **** traverse the elements ****

            for (int elementIndex = 0; elementIndex < sd.Snapshot.Element.Length; elementIndex++)
            {
                fhir.ElementDefinition element = sd.Snapshot.Element[elementIndex];

                // **** check for initial element (need to change type) ****

                if (elementIndex == 0)
                {
                    // **** use the base type ****

                    FhirTypeManager.ProcessSpreadsheetDataElement(
                        sd.Name,
                        baseType,
                        sd.Description,
                        $"{element.Min}..{element.Max}",
                        false,
                        filename
                        );

                    // **** check for defining a base type ****

                    if (!element.Id.Equals(sd.Name, StringComparison.Ordinal))
                    {
                        // **** make sure this node exists too ****

                        FhirTypeManager.ProcessSpreadsheetDataElement(
                            element.Id,
                            element.Base.Path,
                            element.Definition,
                            $"{element.Min}..{element.Max}",
                            false,
                            filename
                            );
                    }

                    // **** no more processing for this entry ****

                    continue;
                }

                // **** check for inherited property ****

                if ((element.Base != null) &&
                    (!string.IsNullOrEmpty(element.Base.Path)) &&
                    (!element.Base.Path.Equals(element.Id, StringComparison.Ordinal)))
                {
                    // **** skip this ****

                    continue;
                }

                // **** check for type information ****

                if ((element.Type != null) && (element.Type.Length > 0) && (element.Type[0].Code != null))
                {
                    // **** grab the valueSet if present ****

                    string valueSet = "";
                    if ((element.Binding != null) && (!string.IsNullOrEmpty(element.Binding.ValueSet)))
                    {
                        valueSet = element.Binding.ValueSet;
                    }

                    string cardinality = element.Type.Length > 1 ? "0..1" : $"{element.Min}..{element.Max}";

                    // **** traverse the types for this element ****

                    foreach (ElementDefinitionType defType in element.Type)
                    {
                        string typeCode = defType.Code;

                        // **** check for the FHIR Type extension ****

                        if ((defType.Extension != null) &&
                            (defType.Extension.Length > 0))
                        {
                            foreach (Extension ext in defType.Extension)
                            {
                                if (ext.Url.Equals(
                                        "http://hl7.org/fhir/StructureDefinition/structuredefinition-fhir-type",
                                        StringComparison.Ordinal))
                                {
                                    typeCode = ext.ValueUrl ?? ext.ValueUri;
                                }
                            }
                        }

                        // **** remove array info from name (if necessary) ****

                        string elementName = element.Path.Replace(
                            "[x]",
                            string.Concat(
                                typeCode.Substring(0, 1).ToUpper(),
                                typeCode.Substring(1)
                                )
                            );

                        // **** check for a code type ****

                        if (typeCode == "code")
                        {
                            string[] codeValues = element.Short.Split('|');

                            // **** process this field ****

                            FhirTypeManager.ProcessSpreadsheetDataElement(
                                elementName,
                                typeCode,
                                (element.Comment == null) ? element.Definition : element.Comment,
                                $"{element.Min}..{element.Max}",
                                false,
                                filename,
                                codeValues
                                );

                            // **** done with this field ****

                            continue;
                        }

                        // **** process this field ****

                        FhirTypeManager.ProcessSpreadsheetDataElement(
                            elementName,
                            typeCode,
                            element.Definition,
                            cardinality,
                            false,
                            filename,
                            valueSet: valueSet
                            );
                    }
                }

                // **** check for extension type information ****

                else if ((element.Type != null) && (element.Type.Length > 0) && (element.Type[0].Extension != null))
                {
                    // **** find the json type ****

                    string propertyType = "";

                    foreach (Extension ext in element.Type[0].Extension)
                    {
                        if (ext.Url.EndsWith("fhir-type"))
                        {
                            propertyType = ext.ValueUrl ?? ext.ValueUri;
                            break;
                        }
                    }

                    // **** process this field ****

                    FhirTypeManager.ProcessSpreadsheetDataElement(
                        element.Path,
                        propertyType,
                        element.Definition,
                        $"{element.Min}..{element.Max}",
                        false,
                        filename
                        );
                }

                // **** check for extension type information ****

                else if ((element.Type != null) && (element.Type.Length > 0) && (element.Type[0]._Code != null))
                {
                    // **** find the json type ****

                    string propertyType = "";

                    foreach (Extension ext in element.Type[0]._Code.Extension)
                    {
                        if (ext.Url.EndsWith("json-type"))
                        {
                            propertyType = ext.ValueString;
                            break;
                        }
                    }

                    // **** process this field ****

                    FhirTypeManager.ProcessSpreadsheetDataElement(
                        element.Path,
                        propertyType,
                        element.Definition,
                        $"{element.Min}..{element.Max}",
                        false,
                        filename
                        );
                }

                // **** use base path ****

                else
                {
                    // **** grab the assumed type ****

                    string propertyType = "";

                    // **** check for override ****

                    if (!string.IsNullOrEmpty(element.ContentReference))
                    {
                        propertyType = FhirPathToCamelCase(element.ContentReference);
                    }

                    // **** assume base path if nothing else filled out ****

                    if (string.IsNullOrEmpty(propertyType))
                    {
                        propertyType = FhirPathToCamelCase(element.Base.Path);
                    }

                    // **** process this field ****

                    FhirTypeManager.ProcessSpreadsheetDataElement(
                        element.Path,
                        propertyType,
                        element.Definition,
                        $"{element.Min}..{element.Max}",
                        false,
                        filename
                        );
                }
            }
        }
예제 #21
0
        ///-------------------------------------------------------------------------------------------------
        /// <summary>Process the fhir directory described by options.</summary>
        ///
        /// <remarks>Gino Canessa, 7/15/2019.</remarks>
        ///
        /// <param name="options">Options for controlling the operation.</param>
        ///-------------------------------------------------------------------------------------------------

        static void ProcessFhirDirectory(Options options)
        {
            // **** make sure the directory exists ****

            if (!Directory.Exists(options.FhirDirectory))
            {
                Console.WriteLine($"Specified FHIR directory: {options.FhirDirectory} not found!");
                return;
            }

            // **** delete the output file if it exists ****

            if (File.Exists(options.OutputFile))
            {
                File.Delete(options.OutputFile);
            }

            // **** process all of the json files (only once) ****

            ProcessPublishedJson(options);

            // **** process XML spreadsheets (if necessary) ****

            if (options.UseOnlyXmlSpreadsheets)
            {
                ProcessXmlSpreadsheets(options);
            }

            // **** check for manual spreadsheet overrides ****

            if ((!options.UseOnlyXmlSpreadsheets) &&
                (!string.IsNullOrEmpty(options.TypesForXmlSpreadsheets)))
            {
                ProcessXmlSpreadsheetsFor(options);
            }

            // **** expand value sets ****

            FhirTypeManager.ExpandValueSets();

            // **** trim our output to match requested types ****

            FhirTypeManager.TrimForMatchingNames(options.TypesToOutput);

            // **** do ResourceType checks ****

            while (FhirTypeManager.PerformResourceTypeChecks() != 0)
            {
            }

            // **** check for writing typescript ****

            if (options.LanguageTypeScript)
            {
                WriteTypeScript(options);
            }

            if (options.LanguageCSharpCore)
            {
                WriteCSharp(options, (int)LanguageCSharp.CSharpStyle.SystemTextJson);
            }

            if (options.LanguageCSharpPlain)
            {
                WriteCSharp(options, (int)LanguageCSharp.CSharpStyle.Plain);
            }

            if ((options.LanguageCSharpNewtonsoft) || (options.LanguageCSharpDefault))
            {
                WriteCSharp(options, (int)LanguageCSharp.CSharpStyle.Newtonsoft);
            }

            // **** done ****

            Console.WriteLine("...Done!");
        }
        bool ILanguangeExporter.AppendFhirTypeOpen(ref StringBuilder sb, FhirType fhirType)
        {
            string comment = FhirTypeManager.SanitizeComment(fhirType.Comment, _lineComment, _indentChar, 1);

            // **** start with the interface open ****

            if (string.IsNullOrEmpty(fhirType.TypeName) || fhirType.Name.Equals("Element"))
            {
                sb.Append(
                    $"\t///<summary>\n" +
                    $"\t///{comment}\n" +
                    $"\t///</summary>\n" +
                    $"\t///<source-file>{fhirType.SourceFilename}</source-file>\n" +
                    $"\tpublic class {fhirType.NameCapitalized}\n" +
                    $"\t{{\n"
                    );
            }
            else if (fhirType.Name.Equals(fhirType.TypeName, StringComparison.Ordinal))
            {
                sb.Append(
                    $"\t///<summary>\n" +
                    $"\t///{comment}\n" +
                    $"\t///</summary>\n" +
                    $"\t///<source-file>{fhirType.SourceFilename}</source-file>\n" +
                    $"\tpublic class {fhirType.NameCapitalized} : Element\n" +
                    $"\t{{\n"
                    );
            }
            else
            {
                sb.Append(
                    $"\t///<summary>\n" +
                    $"\t///{comment}\n" +
                    $"\t///</summary>\n" +
                    $"\t///<source-file>{fhirType.SourceFilename}</source-file>\n" +
                    $"\tpublic class {fhirType.NameCapitalized} : {fhirType.TypeName}\n" +
                    $"\t{{\n");
            }

            // **** output resource type first (if necessary) ****

            if (FhirTypeManager.DoesTypeRequireResourceTag(fhirType.Name))
            {
                // **** add this resource to our list (for polymorphic deserialization) ****

                _exportedResourceNamesAndTypes.Add(fhirType.Name, fhirType.NameCapitalized);

                // **** output the correct ResourceType field based on style ****

                switch (LanguageStyle)
                {
                case (int)CSharpStyle.SystemTextJson:
                    sb.Append(
                        $"\t\t///<summary>Resource Type Name (for serialization)</summary>\n" +
                        $"\t\t[JsonPropertyName(\"resourceType\")]\n" +
                        $"\t\tpublic string ResourceType => \"{fhirType.Name}\";\n"
                        );
                    break;

                case (int)CSharpStyle.Newtonsoft:
                    sb.Append(
                        $"\t\t///<summary>Resource Type Name (for serialization)</summary>\n" +
                        $"\t\t[JsonProperty(PropertyName = \"resourceType\")]\n" +
                        $"\t\tpublic string ResourceType => \"{fhirType.Name}\";\n"
                        );
                    break;

                case (int)CSharpStyle.Plain:
                default:
                    sb.Append(
                        $"\t\t///<summary>Resource Type Name (for serialization)</summary>\n" +
                        $"\t\tpublic string ResourceType => \"{fhirType.Name}\";\n"
                        );
                    break;
                }
            }

            return(true);
        }