/// <summary>Export the passed FHIR version into the specified directory.</summary> /// <param name="info"> The information.</param> /// <param name="serverInfo"> Information describing the server.</param> /// <param name="options"> Options for controlling the operation.</param> /// <param name="exportDirectory">Directory to write files.</param> void ILanguage.Export( FhirVersionInfo info, FhirServerInfo serverInfo, ExporterOptions options, string exportDirectory) { // set internal vars so we don't pass them to every function // this is ugly, but the interface patterns get bad quickly because we need the type map to copy the FHIR info _info = info; _options = options; // create a filename for writing (single file for now) string filename = Path.Combine(exportDirectory, $"R{info.MajorVersion}.txt"); using (FileStream stream = new FileStream(filename, FileMode.Create)) using (ExportStreamWriter writer = new ExportStreamWriter(stream)) { _writer = writer; WriteHeader(); WritePrimitiveTypes(_info.PrimitiveTypes.Values); WriteComplexes(_info.ComplexTypes.Values, "Complex Types"); WriteComplexes(_info.Resources.Values, "Resources"); WriteOperations(_info.SystemOperations.Values, true, "System Operations"); WriteSearchParameters(_info.AllResourceParameters.Values, "All Resource Parameters"); WriteSearchParameters(_info.SearchResultParameters.Values, "Search Result Parameters"); WriteSearchParameters(_info.AllInteractionParameters.Values, "All Interaction Parameters"); WriteValueSets(_info.ValueSetsByUrl.Values, "Value Sets"); WriteFooter(); } }
/// <summary> /// Process a file group, specified by the file prefix (e.g., StructureDefinition). /// </summary> /// <param name="packageDir"> The package dir.</param> /// <param name="prefix"> The prefix.</param> /// <param name="fhirVersionInfo">[in,out] Information describing the fhir version.</param> private static void ProcessFileGroup( string packageDir, string prefix, ref FhirVersionInfo fhirVersionInfo) { // get the files in this directory string[] files = Directory.GetFiles(packageDir, $"{prefix}*.json", SearchOption.TopDirectoryOnly); // process these files ProcessPackageFiles(files, ref fhirVersionInfo); }
/// <summary>Filter for export.</summary> /// <exception cref="ArgumentNullException">Thrown when one or more required arguments are null.</exception> /// <param name="info">An already-filtered FhirVersionInfo.</param> /// <returns>A FhirServerInfo.</returns> public FhirServerInfo CopyForExport( FhirVersionInfo info) { if (info == null) { throw new ArgumentNullException(nameof(info)); } Dictionary <string, FhirServerResourceInfo> resourceInteractions = new Dictionary <string, FhirServerResourceInfo>(); foreach (KeyValuePair <string, FhirServerResourceInfo> kvp in ResourceInteractions) { if (!info.Resources.ContainsKey(kvp.Key)) { continue; } resourceInteractions.Add(kvp.Key, (FhirServerResourceInfo)kvp.Value.Clone()); } List <SystemRestfulInteraction> serverInteractions = new List <SystemRestfulInteraction>(); _serverInteractions.ForEach(i => serverInteractions.Add(i)); Dictionary <string, FhirServerSearchParam> serverSearchParameters = new Dictionary <string, FhirServerSearchParam>(); foreach (KeyValuePair <string, FhirServerSearchParam> kvp in ServerSearchParameters) { serverSearchParameters.Add(kvp.Key, (FhirServerSearchParam)kvp.Value.Clone()); } Dictionary <string, FhirServerOperation> serverOperations = new Dictionary <string, FhirServerOperation>(); foreach (KeyValuePair <string, FhirServerOperation> kvp in ServerOperations) { serverOperations.Add(kvp.Key, (FhirServerOperation)kvp.Value.Clone()); } return(new FhirServerInfo( serverInteractions, Url, FhirVersion, SoftwareName, SoftwareVersion, SoftwareReleaseDate, ImplementationDescription, ImplementationUrl, resourceInteractions, serverSearchParameters, serverOperations)); }
/// <summary>Export the passed FHIR version into the specified directory.</summary> /// <param name="info"> The information.</param> /// <param name="serverInfo"> Information describing the server.</param> /// <param name="options"> Options for controlling the operation.</param> /// <param name="exportDirectory">Directory to write files.</param> void ILanguage.Export( FhirVersionInfo info, FhirServerInfo serverInfo, ExporterOptions options, string exportDirectory) { // set internal vars so we don't pass them to every function // this is ugly, but the interface patterns get bad quickly because we need the type map to copy the FHIR info _info = info; _options = options; _exportedCodes = new HashSet <string>(); if (options.OptionalClassTypesToExport.Contains(ExporterOptions.FhirExportClassType.Enum)) { _exportEnums = true; } else { _exportEnums = false; } // create a filename for writing (single file for now) string filename = Path.Combine(exportDirectory, $"R{info.MajorVersion}.ts"); using (FileStream stream = new FileStream(filename, FileMode.Create)) using (ExportStreamWriter writer = new ExportStreamWriter(stream)) { _writer = writer; WriteHeader(); WriteComplexes(_info.ComplexTypes.Values, false); WriteComplexes(_info.Resources.Values, true); if (_exportEnums) { WriteValueSets(_info.ValueSetsByUrl.Values); } WriteFooter(); } }
/// <summary>Loads the local.</summary> /// <exception cref="ArgumentNullException"> Thrown when one or more required arguments are /// null.</exception> /// <exception cref="ArgumentOutOfRangeException">Thrown when one or more arguments are outside the /// required range.</exception> /// <param name="localLoadType"> Type of the local load.</param> /// <param name="officialExpansionsOnly">(Optional) True to official expansions only.</param> /// <returns>The local.</returns> public FhirVersionInfo LoadLocal( string localLoadType, bool officialExpansionsOnly = false) { if (string.IsNullOrEmpty(_localPublishDirectory)) { throw new ArgumentNullException($"Loading a local FHIR build requires a --fhir-publish-directory"); } GetLocalVersionInfo( out string fhirVersion, out string versionString, out string buildId, out string buildDate); int majorVersion = FhirVersionInfo.GetMajorVersion(versionString); if (majorVersion == 0) { throw new ArgumentOutOfRangeException($"Unknown FHIR version: {versionString}"); } _localVersion = new FhirVersionInfo(majorVersion) { ReleaseName = buildId, PackageName = $"hl7.fhir.r{majorVersion}.core", ExamplesPackageName = string.Empty, ExpansionsPackageName = $"hl7.fhir.r{majorVersion}.expansions", VersionString = versionString, IsDevBuild = true, DevBranch = string.Empty, IsLocalBuild = true, IsOnDisk = true, }; // load the package Loader.LoadLocalBuild(_localPublishDirectory, _fhirSpecDirectory, ref _localVersion, localLoadType, officialExpansionsOnly); return(_localVersion); }
/// <summary>Export the passed FHIR version into the specified directory.</summary> /// <param name="info"> The information.</param> /// <param name="serverInfo"> Information describing the server.</param> /// <param name="options"> Options for controlling the operation.</param> /// <param name="exportDirectory">Directory to write files.</param> void ILanguage.Export( FhirVersionInfo info, FhirServerInfo serverInfo, ExporterOptions options, string exportDirectory) { // set internal vars so we don't pass them to every function // this is ugly, but the interface patterns get bad quickly because we need the type map to copy the FHIR info _info = info; _options = options; Dictionary <string, CytoElement> elementDict = BuildNodes(); // create a filename for writing string filename = Path.Combine(exportDirectory, $"{_languageName}_R{info.MajorVersion}.json"); using (FileStream stream = new FileStream(filename, FileMode.Create)) using (StreamWriter writer = new StreamWriter(stream)) { JsonSerializer serializer = new JsonSerializer(); serializer.Serialize(writer, elementDict.Values); } }
/// <summary>Initializes a new instance of the <see cref="FhirServerInfo"/> class.</summary> /// <param name="serverInteractions"> The server interaction flags.</param> /// <param name="url"> FHIR Base URL for the server.</param> /// <param name="fhirVersion"> The server-reported FHIR version.</param> /// <param name="softwareName"> The FHIR Server software name.</param> /// <param name="softwareVersion"> The FHIR Server software version.</param> /// <param name="softwareReleaseDate"> The FHIR Server software release date.</param> /// <param name="implementationDescription">Information describing the implementation.</param> /// <param name="implementationUrl"> URL of the implementation.</param> /// <param name="resourceInteractions"> The server interactions by resource.</param> /// <param name="serverSearchParameters"> The search parameters for searching all resources.</param> /// <param name="serverOperations"> The operations defined at the system level operation.</param> public FhirServerInfo( List <string> serverInteractions, string url, string fhirVersion, string softwareName, string softwareVersion, string softwareReleaseDate, string implementationDescription, string implementationUrl, Dictionary <string, FhirServerResourceInfo> resourceInteractions, Dictionary <string, FhirServerSearchParam> serverSearchParameters, Dictionary <string, FhirServerOperation> serverOperations) { Url = url; FhirVersion = fhirVersion; _fhirMajorVersion = FhirVersionInfo.GetMajorVersion(fhirVersion); SoftwareName = softwareName; SoftwareVersion = softwareVersion; SoftwareReleaseDate = softwareReleaseDate; ImplementationDescription = implementationDescription; ImplementationUrl = implementationUrl; ResourceInteractions = resourceInteractions; ServerSearchParameters = serverSearchParameters; ServerOperations = serverOperations; _serverInteractions = new List <SystemRestfulInteraction>(); if (serverInteractions != null) { foreach (string interaction in serverInteractions) { _serverInteractions.Add(interaction.ToFhirEnum <SystemRestfulInteraction>()); } } }
/// <summary>Export the passed FHIR version into the specified directory.</summary> /// <param name="info"> The information.</param> /// <param name="serverInfo"> Information describing the server.</param> /// <param name="options"> Options for controlling the operation.</param> /// <param name="exportDirectory">Directory to write files.</param> void ILanguage.Export( FhirVersionInfo info, FhirServerInfo serverInfo, ExporterOptions options, string exportDirectory) { // set internal vars so we don't pass them to every function // this is ugly, but the interface patterns get bad quickly because we need the type map to copy the FHIR info _info = info; _options = options; if (options.OptionalClassTypesToExport.Contains(ExporterOptions.FhirExportClassType.Enum)) { _exportEnums = true; } else { _exportEnums = false; } if ((options.LanguageOptions != null) && (options.LanguageOptions.Count > 0)) { foreach (KeyValuePair <string, string> kvp in options.LanguageOptions) { string key = kvp.Key.ToUpperInvariant(); switch (key) { case "NAMESPACE": _namespace = kvp.Value; break; } } } _exportedResourceNamesAndTypes = new Dictionary <string, string>(); _exportedCodes = new HashSet <string>(); // create a filename for writing (single file for now) string filename = Path.Combine(exportDirectory, $"R{info.MajorVersion}.cs"); using (FileStream stream = new FileStream(filename, FileMode.Create)) using (ExportStreamWriter writer = new ExportStreamWriter(stream)) { _writer = writer; WriteHeader(); // open namespace _writer.WriteLineIndented($"namespace {_namespace}"); _writer.WriteLineIndented("{"); _writer.IncreaseIndent(); WriteComplexes(_info.ComplexTypes.Values, false); WriteComplexes(_info.Resources.Values, true); if (_exportEnums) { WriteValueSets(_info.ValueSetsByUrl.Values); } WritePolymorphicHelpers(); // close namespace _writer.DecreaseIndent(); _writer.WriteLineIndented("}"); WriteFooter(); } }
/// <summary>Initializes a new instance of the <see cref="FhirManager"/> class.</summary> /// <param name="npmDirectory"> Pathname of the npm directory.</param> /// <param name="fhirPublishDirectory">Pathname of the fhir build directory.</param> private FhirManager(string npmDirectory, string fhirPublishDirectory) { // set locals _fhirSpecDirectory = npmDirectory; _localPublishDirectory = fhirPublishDirectory; _localVersion = null; _knownVersions = new Dictionary <int, SortedSet <string> >() { { 2, new SortedSet <string>() { "1.0.2" } }, { 3, new SortedSet <string>() { "3.0.2" } }, { 4, new SortedSet <string>() { "4.0.1" } }, { 5, new SortedSet <string>() { "4.4.0", "4.5.0" } }, }; // build the dictionary of published versions* _publishedVersionDict = new Dictionary <string, FhirVersionInfo>() { { "1.0.2", new FhirVersionInfo(2) { ReleaseName = "DSTU2", PackageName = "hl7.fhir.r2.core", ExamplesPackageName = "hl7.fhir.r2.examples", ExpansionsPackageName = "hl7.fhir.r2.expansions", VersionString = "1.0.2", IsDevBuild = false, IsLocalBuild = false, IsOnDisk = false, } }, { "3.0.2", new FhirVersionInfo(3) { ReleaseName = "STU3", PackageName = "hl7.fhir.r3.core", ExamplesPackageName = "hl7.fhir.r3.examples", ExpansionsPackageName = "hl7.fhir.r3.expansions", VersionString = "3.0.2", IsDevBuild = false, IsLocalBuild = false, IsOnDisk = false, } }, { "4.0.1", new FhirVersionInfo(4) { ReleaseName = "R4", PackageName = "hl7.fhir.r4.core", ExamplesPackageName = "hl7.fhir.r4.examples", ExpansionsPackageName = "hl7.fhir.r4.expansions", VersionString = "4.0.1", IsDevBuild = false, IsLocalBuild = false, IsOnDisk = false, } }, { "4.4.0", new FhirVersionInfo(5) { ReleaseName = "2020May", PackageName = "hl7.fhir.r5.core", ExamplesPackageName = string.Empty, // "hl7.fhir.r5.examples", ExpansionsPackageName = "hl7.fhir.r5.expansions", VersionString = "4.4.0", IsDevBuild = false, IsLocalBuild = false, IsOnDisk = false, } }, { "4.5.0", new FhirVersionInfo(5) { ReleaseName = "2020Sep", PackageName = "hl7.fhir.r5.core", ExamplesPackageName = string.Empty, // "hl7.fhir.r5.examples", ExpansionsPackageName = "hl7.fhir.r5.expansions", VersionString = "4.5.0", IsDevBuild = false, IsLocalBuild = false, IsOnDisk = false, } }, }; }
/// <summary>Loads a published version of FHIR.</summary> /// <exception cref="ArgumentOutOfRangeException">Thrown when one or more arguments are outside the /// required range.</exception> /// <exception cref="ArgumentException"> Thrown when one or more arguments have /// unsupported or illegal values.</exception> /// <param name="majorRelease"> The release number of FHIR to load (e.g., 2 for DSTU2).</param> /// <param name="versions"> The specific version of FHIR to load, or 'latest' for /// highest known version.</param> /// <param name="offlineMode"> (Optional) True to allow, false to suppress the download.</param> /// <param name="officialExpansionsOnly">(Optional) True to official expansions only.</param> /// <returns>True if it succeeds, false if it fails.</returns> public FhirVersionInfo LoadPublished( int majorRelease, string versions, bool offlineMode = false, bool officialExpansionsOnly = false) { HashSet <string> versionsToLoad = new HashSet <string>(); // check major version if (!_knownVersions.ContainsKey(majorRelease)) { throw new ArgumentOutOfRangeException($"Unknown Published FHIR version: {majorRelease}"); } // figure out which version(s) we are loading if (string.IsNullOrEmpty(versions) || (versions == "latest")) { versionsToLoad.Add(_knownVersions[majorRelease].Max); } else { // NOTE: we'll have to support multiple versions of a release in the future, was easier to just put this in now string[] versionSplit = versions.Split(','); foreach (string version in versionSplit) { if (version == "latest") { if (!versionsToLoad.Contains(_knownVersions[majorRelease].Max)) { versionsToLoad.Add(_knownVersions[majorRelease].Max); } continue; } if (!_knownVersions[majorRelease].Contains(version)) { throw new ArgumentException($"Invalid version {version} for R{majorRelease}"); } versionsToLoad.Add(version); } } if (versionsToLoad.Count == 0) { throw new ArgumentException($"Could not find version to load: R{majorRelease}, versions: {versions}"); } // for now, only load the first version we encountered string versionToLoad = versionsToLoad.ElementAt(0); // grab the correct basic version info FhirVersionInfo info = _publishedVersionDict[versionToLoad]; // grab the packages we need FindOrDownload( info.ReleaseName, info.PackageName, info.VersionString, offlineMode); FindOrDownload( info.ReleaseName, info.ExpansionsPackageName, info.VersionString, offlineMode); FindOrDownload( info.ReleaseName, info.ExamplesPackageName, info.VersionString, offlineMode, true); // load the package Loader.LoadPackage(_fhirSpecDirectory, ref info, officialExpansionsOnly); // update our version information _publishedVersionDict[versionToLoad] = info; // return this record return(info); }
/// <summary>Loads a package.</summary> /// <exception cref="ArgumentNullException">Thrown when one or more required arguments are null.</exception> /// <exception cref="FileNotFoundException">Thrown when the requested file is not present.</exception> /// <param name="fhirSpecDirectory"> Pathname of the FHIR spec directory.</param> /// <param name="fhirVersionInfo"> [in,out] Information describing the FHIR version.</param> /// <param name="officialExpansionsOnly">True to official expansions only.</param> public static void LoadPackage( string fhirSpecDirectory, ref FhirVersionInfo fhirVersionInfo, bool officialExpansionsOnly) { // sanity checks if (fhirVersionInfo == null) { Console.WriteLine($"LoadPackage <<< invalid version info is NULL, cannot load {fhirSpecDirectory}"); throw new ArgumentNullException(nameof(fhirVersionInfo)); } // first load value sets if (!TryFindPackage( fhirVersionInfo.ReleaseName, fhirVersionInfo.ExpansionsPackageName, fhirVersionInfo.VersionString, fhirSpecDirectory, out string expansionDir)) { Console.WriteLine($"LoadPackage <<< cannot find package for {fhirVersionInfo.ReleaseName}: {fhirVersionInfo.ExpansionsPackageName}!"); throw new FileNotFoundException($"Cannot find package for {fhirVersionInfo.ReleaseName}: {fhirVersionInfo.ExpansionsPackageName}"); } // load package info FhirPackageInfo expansionPackageInfo = FhirPackageInfo.Load(expansionDir); // tell the user what's going on Console.WriteLine($"LoadPackage <<< Found: {expansionPackageInfo.Name} version: {expansionPackageInfo.Version}"); // find the package if (!TryFindPackage( fhirVersionInfo.ReleaseName, fhirVersionInfo.PackageName, fhirVersionInfo.VersionString, fhirSpecDirectory, out string packageDir)) { Console.WriteLine($"LoadPackage <<< cannot find package for {fhirVersionInfo.ReleaseName}: {fhirVersionInfo.PackageName}!"); throw new FileNotFoundException($"Cannot find package for {fhirVersionInfo.ReleaseName}: {fhirVersionInfo.PackageName}"); } // load package info FhirPackageInfo packageInfo = FhirPackageInfo.Load(packageDir); // tell the user what's going on Console.WriteLine($"LoadPackage <<< Found: {packageInfo.Name} version: {packageInfo.Version}"); // update our structure fhirVersionInfo.VersionString = packageInfo.Version; // process Code Systems ProcessFileGroup(packageDir, "CodeSystem", ref fhirVersionInfo); // process Value Set expansions if (officialExpansionsOnly) { ProcessFileGroup(expansionDir, "ValueSet", ref fhirVersionInfo); } else { ProcessFileGroup(packageDir, "ValueSet", ref fhirVersionInfo); } // process structure definitions ProcessFileGroup(packageDir, "StructureDefinition", ref fhirVersionInfo); // process search parameters (adds to resources) ProcessFileGroup(packageDir, "SearchParameter", ref fhirVersionInfo); // process operations (adds to resources and version info (server level)) ProcessFileGroup(packageDir, "OperationDefinition", ref fhirVersionInfo); // add version-specific "MAGIC" items AddSearchMagicParameters(ref fhirVersionInfo); // make sure we cleared the last line Console.WriteLine($"LoadPackage <<< Loaded and Parsed FHIR {fhirVersionInfo.ReleaseName}{new string(' ', 100)}"); }
/// <summary>Process the package files.</summary> /// <exception cref="InvalidDataException">Thrown when an Invalid Data error condition occurs.</exception> /// <param name="files"> The files.</param> /// <param name="fhirVersionInfo">[in,out] Information describing the fhir version.</param> private static void ProcessPackageFiles( string[] files, ref FhirVersionInfo fhirVersionInfo) { // traverse the files foreach (string filename in files) { // check for skipping file if (FhirVersionInfo.ShouldSkipFile(Path.GetFileName(filename))) { // skip this file continue; } // parse the name into parts we want string shortName = Path.GetFileNameWithoutExtension(filename); string[] components = shortName.Split('-'); string resourceHint = components[0]; string resourceName = shortName.Substring(resourceHint.Length + 1); // attempt to load this file try { Console.Write($"v{fhirVersionInfo.MajorVersion}: {shortName,-85}\r"); // check for ignored types if (fhirVersionInfo.ShouldIgnoreResource(resourceHint)) { // skip continue; } // this should be listed in process types (validation check) if (!fhirVersionInfo.ShouldProcessResource(resourceHint)) { // type not found Console.WriteLine($"\nProcessPackageFiles <<< Unhandled type: {shortName}"); throw new InvalidDataException($"Unhandled type: {shortName}"); } // read the file string contents = File.ReadAllText(filename); // parse the file - note: using var here is siginificantly more performant than object var resource = fhirVersionInfo.ParseResource(contents); // check type matching if (!resource.GetType().Name.Equals(resourceHint, StringComparison.Ordinal)) { // type not found Console.WriteLine($"\nProcessPackageFiles <<<" + $" Mismatched type: {shortName}," + $" should be {resourceHint} parsed to:{resource.GetType().Name}"); throw new InvalidDataException($"Mismatched type: {shortName}: {resourceHint} != {resource.GetType().Name}"); } // process this resource fhirVersionInfo.ProcessResource(resource); } catch (Exception ex) { Console.WriteLine(string.Empty); Console.WriteLine($"LoadPackage <<< Failed to process file: {filename}: \n{ex}\n--------------"); throw; } } }
/// <summary>Adds the search magic parameters.</summary> /// <param name="info">[in,out] The information.</param> private static void AddSearchMagicParameters(ref FhirVersionInfo info) { switch (info.MajorVersion) { case 2: info.AddVersionedParam(FhirVersionInfo.SearchMagicParameter.Global, "_content", "string"); info.AddVersionedParam(FhirVersionInfo.SearchMagicParameter.Global, "_list", "string"); info.AddVersionedParam(FhirVersionInfo.SearchMagicParameter.Result, "_sort", "string"); info.AddVersionedParam(FhirVersionInfo.SearchMagicParameter.Result, "_count", "string"); info.AddVersionedParam(FhirVersionInfo.SearchMagicParameter.Result, "_include", "string"); info.AddVersionedParam(FhirVersionInfo.SearchMagicParameter.Result, "_revinclude", "string"); info.AddVersionedParam(FhirVersionInfo.SearchMagicParameter.Result, "_summary", "string"); info.AddVersionedParam(FhirVersionInfo.SearchMagicParameter.Result, "_elements", "string"); info.AddVersionedParam(FhirVersionInfo.SearchMagicParameter.Result, "_contained", "string"); info.AddVersionedParam(FhirVersionInfo.SearchMagicParameter.Result, "_containedType", "string"); info.AddVersionedParam(FhirVersionInfo.SearchMagicParameter.Interaction, "_format", "string"); break; case 3: info.AddVersionedParam(FhirVersionInfo.SearchMagicParameter.Global, "_text", "string"); info.AddVersionedParam(FhirVersionInfo.SearchMagicParameter.Global, "_content", "string"); info.AddVersionedParam(FhirVersionInfo.SearchMagicParameter.Global, "_list", "string"); info.AddVersionedParam(FhirVersionInfo.SearchMagicParameter.Global, "_has", "string"); info.AddVersionedParam(FhirVersionInfo.SearchMagicParameter.Global, "_type", "string"); info.AddVersionedParam(FhirVersionInfo.SearchMagicParameter.Result, "_sort", "string"); info.AddVersionedParam(FhirVersionInfo.SearchMagicParameter.Result, "_count", "string"); info.AddVersionedParam(FhirVersionInfo.SearchMagicParameter.Result, "_include", "string"); info.AddVersionedParam(FhirVersionInfo.SearchMagicParameter.Result, "_revinclude", "string"); info.AddVersionedParam(FhirVersionInfo.SearchMagicParameter.Result, "_summary", "string"); info.AddVersionedParam(FhirVersionInfo.SearchMagicParameter.Result, "_elements", "string"); info.AddVersionedParam(FhirVersionInfo.SearchMagicParameter.Result, "_contained", "string"); info.AddVersionedParam(FhirVersionInfo.SearchMagicParameter.Result, "_containedType", "string"); info.AddVersionedParam(FhirVersionInfo.SearchMagicParameter.Interaction, "_format", "string"); break; case 4: default: info.AddVersionedParam(FhirVersionInfo.SearchMagicParameter.Global, "_text", "string"); info.AddVersionedParam(FhirVersionInfo.SearchMagicParameter.Global, "_content", "string"); info.AddVersionedParam(FhirVersionInfo.SearchMagicParameter.Global, "_list", "string"); info.AddVersionedParam(FhirVersionInfo.SearchMagicParameter.Global, "_has", "string"); info.AddVersionedParam(FhirVersionInfo.SearchMagicParameter.Global, "_type", "string"); info.AddVersionedParam(FhirVersionInfo.SearchMagicParameter.Result, "_sort", "string"); info.AddVersionedParam(FhirVersionInfo.SearchMagicParameter.Result, "_count", "string"); info.AddVersionedParam(FhirVersionInfo.SearchMagicParameter.Result, "_include", "string"); info.AddVersionedParam(FhirVersionInfo.SearchMagicParameter.Result, "_revinclude", "string"); info.AddVersionedParam(FhirVersionInfo.SearchMagicParameter.Result, "_summary", "string"); info.AddVersionedParam(FhirVersionInfo.SearchMagicParameter.Result, "_total", "string"); info.AddVersionedParam(FhirVersionInfo.SearchMagicParameter.Result, "_elements", "string"); info.AddVersionedParam(FhirVersionInfo.SearchMagicParameter.Result, "_contained", "string"); info.AddVersionedParam(FhirVersionInfo.SearchMagicParameter.Result, "_containedType", "string"); info.AddVersionedParam(FhirVersionInfo.SearchMagicParameter.Interaction, "_format", "string"); info.AddVersionedParam(FhirVersionInfo.SearchMagicParameter.Interaction, "_pretty", "string"); break; } }
/// <summary>Loads a package.</summary> /// <exception cref="ArgumentNullException">Thrown when one or more required arguments are null.</exception> /// <param name="localPublishDirectory"> Local FHIR Publish directory.</param> /// <param name="fhirSpecDirectory"> Pathname of the FHIR spec directory.</param> /// <param name="fhirVersionInfo"> [in,out] Information describing the FHIR version.</param> /// <param name="localLoadType"> Type of the local load.</param> /// <param name="officialExpansionsOnly">True to official expansions only.</param> public static void LoadLocalBuild( string localPublishDirectory, string fhirSpecDirectory, ref FhirVersionInfo fhirVersionInfo, string localLoadType, bool officialExpansionsOnly) { // sanity checks if (fhirVersionInfo == null) { Console.WriteLine($"LoadLocalBuild <<< invalid version info is NULL, cannot load {localPublishDirectory}"); throw new ArgumentNullException(nameof(fhirVersionInfo)); } // tell the user what's going on Console.WriteLine( $"LoadLocalBuild <<<" + $" Found: {fhirVersionInfo.PackageName}" + $" version: {fhirVersionInfo.VersionString}" + $" build: {fhirVersionInfo.ReleaseName}"); string expansionDir; string packageDir; if (localLoadType == "latest") { FhirPackageDownloader.CopyAndExtract( localPublishDirectory, fhirVersionInfo.ExpansionsPackageName, fhirVersionInfo.VersionString, fhirSpecDirectory, out expansionDir); expansionDir = Path.Combine(expansionDir, "package"); } else { expansionDir = Path.Combine( fhirSpecDirectory, $"local-{fhirVersionInfo.ExpansionsPackageName}-{fhirVersionInfo.VersionString}", "package"); } // load package info FhirPackageInfo expansionPackageInfo = FhirPackageInfo.Load(expansionDir); // tell the user what's going on Console.WriteLine($"LoadPackage <<< Found: {expansionPackageInfo.Name} version: {expansionPackageInfo.Version}"); if (localLoadType == "latest") { FhirPackageDownloader.CopyAndExtract( localPublishDirectory, fhirVersionInfo.PackageName, fhirVersionInfo.VersionString, fhirSpecDirectory, out packageDir); packageDir = Path.Combine(packageDir, "package"); } else { packageDir = Path.Combine( fhirSpecDirectory, $"local-{fhirVersionInfo.PackageName}-{fhirVersionInfo.VersionString}", "package"); } // load package info FhirPackageInfo packageInfo = FhirPackageInfo.Load(packageDir); // tell the user what's going on Console.WriteLine($"LoadPackage <<< Found: {packageInfo.Name} version: {packageInfo.Version}"); // update our structure fhirVersionInfo.VersionString = packageInfo.Version; // process Code Systems ProcessFileGroup(packageDir, "CodeSystem", ref fhirVersionInfo); // process Value Set expansions if (officialExpansionsOnly) { ProcessFileGroup(expansionDir, "ValueSet", ref fhirVersionInfo); } else { ProcessFileGroup(packageDir, "ValueSet", ref fhirVersionInfo); } // process structure definitions ProcessFileGroup(packageDir, "StructureDefinition", ref fhirVersionInfo); // process search parameters (adds to resources) ProcessFileGroup(packageDir, "SearchParameter", ref fhirVersionInfo); // process operations (adds to resources and version info (server level)) ProcessFileGroup(packageDir, "OperationDefinition", ref fhirVersionInfo); // add version-specific "MAGIC" items AddSearchMagicParameters(ref fhirVersionInfo); // make sure we cleared the last line Console.WriteLine($"LoadPackage <<< Loaded and Parsed FHIR {fhirVersionInfo.ReleaseName}{new string(' ', 100)}"); }
/// <summary>Exports.</summary> /// <exception cref="ArgumentNullException">Thrown when one or more required arguments are null.</exception> /// <param name="sourceFhirInfo"> Information describing the source FHIR version information.</param> /// <param name="sourceServerInfo">Information describing the source server.</param> /// <param name="exportLanguage"> The export language.</param> /// <param name="options"> Options for controlling the operation.</param> /// <param name="outputPath"> The output filename.</param> /// <param name="isPartOfBatch"> True if is part of batch, false if not.</param> /// <returns>A List of files written by the export operation.</returns> public static List <string> Export( FhirVersionInfo sourceFhirInfo, FhirServerInfo sourceServerInfo, ILanguage exportLanguage, ExporterOptions options, string outputPath, bool isPartOfBatch) { List <string> filesWritten = new List <string>(); if (sourceFhirInfo == null) { throw new ArgumentNullException(nameof(sourceFhirInfo)); } if (exportLanguage == null) { throw new ArgumentNullException(nameof(exportLanguage)); } if (options == null) { throw new ArgumentNullException(nameof(options)); } if (string.IsNullOrEmpty(outputPath)) { throw new ArgumentNullException(nameof(outputPath)); } // check for rooted vs relative if (!Path.IsPathRooted(outputPath)) { outputPath = Path.Combine(Directory.GetCurrentDirectory(), outputPath); } // resolve directory oddness (e.g., follow ..'s, etc.) outputPath = Path.GetFullPath(outputPath); string tempDir; if (Path.HasExtension(outputPath)) { tempDir = Path.Combine(Path.GetDirectoryName(outputPath), $"{exportLanguage.LanguageName}-{DateTime.Now.Ticks}"); } else { tempDir = Path.Combine(outputPath, $"{exportLanguage.LanguageName}-{DateTime.Now.Ticks}"); } if (!Directory.Exists(tempDir)) { Directory.CreateDirectory(tempDir); } bool copyPrimitives = false; if (exportLanguage.RequiredExportClassTypes.Contains(ExporterOptions.FhirExportClassType.PrimitiveType) || options.OptionalClassTypesToExport.Contains(ExporterOptions.FhirExportClassType.PrimitiveType)) { copyPrimitives = true; } bool copyComplexTypes = false; if (exportLanguage.RequiredExportClassTypes.Contains(ExporterOptions.FhirExportClassType.ComplexType) || options.OptionalClassTypesToExport.Contains(ExporterOptions.FhirExportClassType.ComplexType)) { copyComplexTypes = true; } bool copyResources = false; if (exportLanguage.RequiredExportClassTypes.Contains(ExporterOptions.FhirExportClassType.Resource) || options.OptionalClassTypesToExport.Contains(ExporterOptions.FhirExportClassType.Resource)) { copyResources = true; } bool copyProfiles = false; if (exportLanguage.RequiredExportClassTypes.Contains(ExporterOptions.FhirExportClassType.Profile) || options.OptionalClassTypesToExport.Contains(ExporterOptions.FhirExportClassType.Profile)) { copyProfiles = true; } // create a copy of the FHIR information for use in this export FhirVersionInfo info = sourceFhirInfo.CopyForExport( exportLanguage.FhirPrimitiveTypeMap, options.ExportList, copyPrimitives: copyPrimitives, copyComplexTypes: copyComplexTypes, copyResources: copyResources, copyExtensions: true, copyProfiles: copyProfiles, options.ExtensionUrls, options.ExtensionElementPaths, sourceServerInfo, options.IncludeExperimental); FhirServerInfo serverInfo = null; if (sourceServerInfo != null) { serverInfo = sourceServerInfo.CopyForExport(info); } // perform our export exportLanguage.Export( info, serverInfo, options, tempDir); string[] exportedFiles = Directory.GetFiles(tempDir, string.Empty, SearchOption.AllDirectories); string requestedExtension = string.Empty; if (Path.HasExtension(outputPath)) { requestedExtension = Path.GetExtension(outputPath).ToUpperInvariant(); } if (requestedExtension == ".ZIP") { if (File.Exists(outputPath)) { File.Delete(outputPath); } // zip the files in the directory for download/output CreateZip(outputPath, tempDir); // tell the caller the file we wrote filesWritten.Add(outputPath); // clean up DeleteDirectory(tempDir); return(filesWritten); } if ((exportedFiles.Length == 1) && (!string.IsNullOrEmpty(requestedExtension))) { if (File.Exists(outputPath)) { File.Delete(outputPath); } File.Move(exportedFiles[0], outputPath); filesWritten.Add(outputPath); DeleteDirectory(tempDir); return(filesWritten); } if (exportedFiles.Length == 1) { string filename = Path.Combine( outputPath, $"{exportLanguage.LanguageName}_R{info.MajorVersion}"); filename = Path.ChangeExtension(filename, exportLanguage.SingleFileExportExtension); if (File.Exists(filename)) { File.Delete(filename); } File.Move(exportedFiles[0], filename); filesWritten.Add(filename); DeleteDirectory(tempDir); return(filesWritten); } string path = outputPath; if (isPartOfBatch) { path = Path.Combine(outputPath, $"{exportLanguage.LanguageName}_R{info.MajorVersion}"); } if (!Directory.Exists(path)) { Directory.CreateDirectory(path); } int duplicateLen = tempDir.Length + 1; foreach (string file in exportedFiles) { string exportName = Path.Combine(path, file.Substring(duplicateLen)); if (!TryMoveFile(file, exportName)) { throw new Exception($"Failed to move file {file} into the requested export location!"); } filesWritten.Add(exportName); } DeleteDirectory(tempDir); return(filesWritten); }