/// <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>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>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>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> /// Attempts to get server information a FhirServerInfo from the given string. /// </summary> /// <param name="serverUrl"> URL of the server.</param> /// <param name="serverInfo">[out] Information describing the server.</param> /// <returns>True if it succeeds, false if it fails.</returns> public static bool TryGetServerInfo( string serverUrl, out FhirServerInfo serverInfo) { if (string.IsNullOrEmpty(serverUrl)) { serverInfo = null; return(false); } HttpClient client = null; HttpRequestMessage request = null; try { Uri serverUri = new Uri(serverUrl); client = new HttpClient(); request = new HttpRequestMessage() { Method = HttpMethod.Get, RequestUri = new Uri(serverUri, "metadata"), Headers = { Accept = { new MediaTypeWithQualityHeaderValue("application/fhir+json"), }, }, }; Console.WriteLine($"Requesting metadata from {request.RequestUri}..."); HttpResponseMessage response = client.SendAsync(request).Result; if (response.StatusCode != System.Net.HttpStatusCode.OK) { Console.WriteLine($"Request to {request.RequestUri} failed! {response.StatusCode}"); serverInfo = null; return(false); } string content = response.Content.ReadAsStringAsync().Result; if (string.IsNullOrEmpty(content)) { Console.WriteLine($"Request to {request.RequestUri} returned empty body!"); serverInfo = null; return(false); } ServerFhirVersionStruct version = JsonConvert.DeserializeObject <ServerFhirVersionStruct>(content); if (string.IsNullOrEmpty(version.FhirVersion)) { Console.WriteLine($"Could not determine the FHIR version for {serverUrl}!"); serverInfo = null; return(false); } Console.WriteLine($"Connected to {serverUrl}, FHIR version: {version.FhirVersion}"); IFhirConverter fhirConverter = ConverterHelper.ConverterForVersion(version.FhirVersion); object metadata = fhirConverter.ParseResource(content); fhirConverter.ProcessMetadata(metadata, serverUrl, out serverInfo); if (serverInfo != null) { Console.WriteLine($"Server Information from {serverUrl}:"); Console.WriteLine($"\t FHIR Version: {serverInfo.FhirVersion}"); Console.WriteLine($"\t Software Name: {serverInfo.SoftwareName}"); Console.WriteLine($"\tSoftware Version: {serverInfo.SoftwareVersion}"); Console.WriteLine($"\t Release Date: {serverInfo.SoftwareReleaseDate}"); Console.WriteLine($"\t Description: {serverInfo.ImplementationDescription}"); Console.WriteLine($"\t Resources: {serverInfo.ResourceInteractions.Count}"); return(true); } } #pragma warning disable CA1031 // Do not catch general exception types catch (Exception ex) #pragma warning restore CA1031 // Do not catch general exception types { Console.WriteLine($"Failed to get server info from: {serverUrl}, {ex.Message}"); serverInfo = null; return(false); } finally { if (request != null) { request.Dispose(); } if (client != null) { client.Dispose(); } } serverInfo = null; return(false); }
/// <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); }