/// <summary> /// Deserialize JSON into a FHIR MeasureReport /// </summary> public static void DeserializeJson(this MeasureReport current, ref Utf8JsonReader reader, JsonSerializerOptions options) { string propertyName; while (reader.Read()) { if (reader.TokenType == JsonTokenType.EndObject) { return; } if (reader.TokenType == JsonTokenType.PropertyName) { propertyName = reader.GetString(); if (Hl7.Fhir.Serialization.FhirSerializerOptions.Debug) { Console.WriteLine($"MeasureReport >>> MeasureReport.{propertyName}, depth: {reader.CurrentDepth}, pos: {reader.BytesConsumed}"); } reader.Read(); current.DeserializeJsonProperty(ref reader, options, propertyName); } } throw new JsonException($"MeasureReport: invalid state! depth: {reader.CurrentDepth}, pos: {reader.BytesConsumed}"); }
/// <summary>Adds a report.</summary> /// <exception cref="ArgumentNullException">Thrown when one or more required arguments are null.</exception> /// <exception cref="ArgumentException"> Thrown when one or more arguments have unsupported or /// illegal values.</exception> /// <param name="report">The report.</param> public void AddReport(MeasureReport report) { if (report == null) { throw new ArgumentNullException(nameof(report)); } if (report.Reporter.Reference != _orgRef) { throw new ArgumentException($"Invalid Reporter: {report.Reporter} != collection org: {_orgRef}"); } if (_reportById.ContainsKey(report.Id)) { return; } if (!_periods.Contains(report.Period.End)) { _periods.Add(report.Period.End); } _reportById.Add(report.Id, report); _reportByKey.Add(GetKey(report), report); }
/// <summary>Adds a group to report to 'reportGroup'.</summary> /// <param name="report"> The report.</param> /// <param name="reportGroup">Group the report belongs to.</param> private static void AddGroupToReport( MeasureReport report, MeasureReport.GroupComponent reportGroup) { if (reportGroup.Population.Count == 0) { reportGroup.Population = null; } if (reportGroup.Stratifier.Count == 0) { reportGroup.Stratifier = null; } report.Group.Add(reportGroup); }
/// <summary>Reports for cdc grouped measure.</summary> /// <param name="id"> [out] The identifier.</param> /// <param name="measure">The measure.</param> /// <param name="data"> The data.</param> /// <returns>A MeasureReport.</returns> private static MeasureReport ReportForMeasure( out string id, Measure measure, ReportData data) { id = FhirIds.NextId; MeasureReport report = new MeasureReport() { Meta = new Meta() { Profile = new string[] { FhirSystems.MeasureReport, }, Security = FhirTriplet.SecurityTest.GetCodingList(), }, Id = id, Status = MeasureReport.MeasureReportStatus.Complete, Type = MeasureReport.MeasureReportType.Summary, Date = new FhirDateTime(new DateTimeOffset(DateTime.Now)).ToString(), Period = data.FhirPeriod(), Measure = measure.Url, Group = new List <MeasureReport.GroupComponent>(), }; if (data.ReportDate != null) { report.Date = new FhirDateTime(new DateTimeOffset((DateTime)data.ReportDate !)).ToString(); } if (data.CoveredLocation != null) { report.Subject = new ResourceReference( $"Location/{data.CoveredLocation.Id}", data.CoveredLocation.Name); if (data.CoveredOrganization != null) { report.Subject.AddExtension( "http://build.fhir.org/ig/AudaciousInquiry/saner-ig/connectathon/locations", new FhirString(data.CoveredOrganization.Id)); } #if false // 2020.05.05 - figure out if we still want contained data.CoveredLocation.ToFhir( out ResourceReference resourceReference, out Resource contained); report.Subject = resourceReference; if (contained != null) { if (report.Contained == null) { report.Contained = new List <Resource>(); } report.Contained.Add(contained); } #endif } if (data.Reporter != null) { report.Reporter = new ResourceReference( $"Organization/{data.Reporter.Id}", data.Reporter.Name); #if false // 2020.05.05 - figure out if we still want contained data.Reporter.ToFhir( out ResourceReference resourceReference, out Resource contained); report.Reporter = resourceReference; if (contained != null) { if (report.Contained == null) { report.Contained = new List <Resource>(); } report.Contained.Add(contained); } #endif } if ((data.Reporter == null) && (data.CoveredOrganization != null)) { report.Reporter = new ResourceReference( $"Organization/{data.CoveredOrganization.Id}", data.CoveredOrganization.Name); #if false // 2020.05.05 - figure out if we still want contained data.CoveredOrganization.ToFhir( out ResourceReference resourceReference, out Resource contained); report.Reporter = resourceReference; if (contained != null) { if (report.Contained == null) { report.Contained = new List <Resource>(); } report.Contained.Add(contained); } #endif } foreach (Measure.GroupComponent measureGroup in measure.Group) { if ((measureGroup.Code == null) || (measureGroup.Code.Coding == null) || (measureGroup.Code.Coding.Count == 0)) { continue; } string groupName = measureGroup.Code.Coding[0].Code; MeasureReport.GroupComponent reportGroup = new MeasureReport.GroupComponent() { Code = measureGroup.Code, Population = new List <MeasureReport.PopulationComponent>(), Stratifier = new List <MeasureReport.StratifierComponent>(), }; if (data.Values.ContainsKey(groupName)) { if (data.Values[groupName].Score != null) { reportGroup.MeasureScore = new Quantity() { Value = data.Values[groupName].Score, }; } } if ((measureGroup.Population == null) || (measureGroup.Population.Count == 0)) { if (data.Values.ContainsKey(groupName)) { reportGroup.MeasureScore = new Quantity() { Value = data.Values[groupName].Score, }; } AddGroupToReport(report, reportGroup); continue; } foreach (Measure.PopulationComponent population in measureGroup.Population) { if ((population.Code == null) || (population.Code.Coding == null) || (population.Code.Coding.Count == 0)) { continue; } string populationSystem = null; string populationName = null; string populationCode = null; foreach (Coding popCoding in population.Code.Coding) { if ((popCoding.System == FhirSystems.MeasurePopulation) || (popCoding.System == FhirSystems.SanerAggregateBool) || (popCoding.System == FhirSystems.SanerAggregateChoice)) { populationSystem = popCoding.System; populationCode = popCoding.Code; } if (data.Values.ContainsKey(popCoding.Code)) { populationName = popCoding.Code; } } if (populationSystem == FhirSystems.SanerAggregateBool) { if (populationCode == "true") { reportGroup.Population.Add(new MeasureReport.PopulationComponent() { Code = population.Code, Count = (data.Values[groupName].BoolValue == true) ? 1 : 0, }); } else { { reportGroup.Population.Add(new MeasureReport.PopulationComponent() { Code = population.Code, Count = (data.Values[groupName].BoolValue == false) ? 1 : 0, }); } } continue; } if (!string.IsNullOrEmpty(populationName)) { switch (populationCode) { case "initial-population": reportGroup.Population.Add(new MeasureReport.PopulationComponent() { Code = population.Code, Count = (int)data.Values[populationName].Score, }); break; case "measure-population": reportGroup.Population.Add(new MeasureReport.PopulationComponent() { Code = population.Code, Count = (int)data.Values[populationName].Score, }); break; case "measure-observation": // ignore break; case "numerator": reportGroup.Population.Add(new MeasureReport.PopulationComponent() { Code = population.Code, Count = data.Values[populationName].Numerator ?? (int)data.Values[populationName].Score, }); break; case "denominator": reportGroup.Population.Add(new MeasureReport.PopulationComponent() { Code = population.Code, Count = data.Values[populationName].Denominator ?? (int?)data.Values[populationName].Score ?? 1, }); break; default: if (data.Values.ContainsKey(populationName)) { reportGroup.Population.Add(new MeasureReport.PopulationComponent() { Code = population.Code, Count = (int)data.Values[populationName].Score, }); } else { reportGroup.Population.Add(new MeasureReport.PopulationComponent() { Code = population.Code, }); } break; } } } AddGroupToReport(report, reportGroup); } return(report); }
/// <summary> /// Serialize a FHIR MeasureReport into JSON /// </summary> public static void SerializeJson(this MeasureReport current, Utf8JsonWriter writer, JsonSerializerOptions options, bool includeStartObject = true) { if (includeStartObject) { writer.WriteStartObject(); } writer.WriteString("resourceType", "MeasureReport"); // Complex: MeasureReport, Export: MeasureReport, Base: DomainResource (DomainResource) ((Hl7.Fhir.Model.DomainResource)current).SerializeJson(writer, options, false); if ((current.Identifier != null) && (current.Identifier.Count != 0)) { writer.WritePropertyName("identifier"); writer.WriteStartArray(); foreach (Identifier val in current.Identifier) { val.SerializeJson(writer, options, true); } writer.WriteEndArray(); } writer.WriteString("status", Hl7.Fhir.Utility.EnumUtility.GetLiteral(current.StatusElement.Value)); writer.WriteString("type", Hl7.Fhir.Utility.EnumUtility.GetLiteral(current.TypeElement.Value)); writer.WriteString("measure", current.MeasureElement.Value); if (current.Subject != null) { writer.WritePropertyName("subject"); current.Subject.SerializeJson(writer, options); } if (current.DateElement != null) { if (!string.IsNullOrEmpty(current.DateElement.Value)) { writer.WriteString("date", current.DateElement.Value); } if (current.DateElement.HasExtensions() || (!string.IsNullOrEmpty(current.DateElement.ElementId))) { JsonStreamUtilities.SerializeExtensionList(writer, options, "_date", false, current.DateElement.Extension, current.DateElement.ElementId); } } if (current.Reporter != null) { writer.WritePropertyName("reporter"); current.Reporter.SerializeJson(writer, options); } writer.WritePropertyName("period"); current.Period.SerializeJson(writer, options); if (current.ImprovementNotation != null) { writer.WritePropertyName("improvementNotation"); current.ImprovementNotation.SerializeJson(writer, options); } if ((current.Group != null) && (current.Group.Count != 0)) { writer.WritePropertyName("group"); writer.WriteStartArray(); foreach (MeasureReport.GroupComponent val in current.Group) { val.SerializeJson(writer, options, true); } writer.WriteEndArray(); } if ((current.EvaluatedResource != null) && (current.EvaluatedResource.Count != 0)) { writer.WritePropertyName("evaluatedResource"); writer.WriteStartArray(); foreach (ResourceReference val in current.EvaluatedResource) { val.SerializeJson(writer, options, true); } writer.WriteEndArray(); } if (includeStartObject) { writer.WriteEndObject(); } }
/// <summary> /// Deserialize JSON into a FHIR MeasureReport /// </summary> public static void DeserializeJsonProperty(this MeasureReport current, ref Utf8JsonReader reader, JsonSerializerOptions options, string propertyName) { switch (propertyName) { case "identifier": if ((reader.TokenType != JsonTokenType.StartArray) || (!reader.Read())) { throw new JsonException($"MeasureReport error reading 'identifier' expected StartArray, found {reader.TokenType}! depth: {reader.CurrentDepth}, pos: {reader.BytesConsumed}"); } current.Identifier = new List <Identifier>(); while (reader.TokenType != JsonTokenType.EndArray) { Hl7.Fhir.Model.Identifier v_Identifier = new Hl7.Fhir.Model.Identifier(); v_Identifier.DeserializeJson(ref reader, options); current.Identifier.Add(v_Identifier); if (!reader.Read()) { throw new JsonException($"MeasureReport error reading 'identifier' array, read failed! depth: {reader.CurrentDepth}, pos: {reader.BytesConsumed}"); } if (reader.TokenType == JsonTokenType.EndObject) { reader.Read(); } } if (current.Identifier.Count == 0) { current.Identifier = null; } break; case "status": if (reader.TokenType == JsonTokenType.Null) { current.StatusElement = new Code <Hl7.Fhir.Model.MeasureReport.MeasureReportStatus>(); reader.Skip(); } else { current.StatusElement = new Code <Hl7.Fhir.Model.MeasureReport.MeasureReportStatus>(Hl7.Fhir.Utility.EnumUtility.ParseLiteral <Hl7.Fhir.Model.MeasureReport.MeasureReportStatus>(reader.GetString())); } break; case "_status": if (current.StatusElement == null) { current.StatusElement = new Code <Hl7.Fhir.Model.MeasureReport.MeasureReportStatus>(); } ((Hl7.Fhir.Model.Element)current.StatusElement).DeserializeJson(ref reader, options); break; case "type": if (reader.TokenType == JsonTokenType.Null) { current.TypeElement = new Code <Hl7.Fhir.Model.MeasureReport.MeasureReportType>(); reader.Skip(); } else { current.TypeElement = new Code <Hl7.Fhir.Model.MeasureReport.MeasureReportType>(Hl7.Fhir.Utility.EnumUtility.ParseLiteral <Hl7.Fhir.Model.MeasureReport.MeasureReportType>(reader.GetString())); } break; case "_type": if (current.TypeElement == null) { current.TypeElement = new Code <Hl7.Fhir.Model.MeasureReport.MeasureReportType>(); } ((Hl7.Fhir.Model.Element)current.TypeElement).DeserializeJson(ref reader, options); break; case "measure": if (reader.TokenType == JsonTokenType.Null) { current.MeasureElement = new Canonical(); reader.Skip(); } else { current.MeasureElement = new Canonical(reader.GetString()); } break; case "_measure": if (current.MeasureElement == null) { current.MeasureElement = new Canonical(); } ((Hl7.Fhir.Model.Element)current.MeasureElement).DeserializeJson(ref reader, options); break; case "subject": current.Subject = new Hl7.Fhir.Model.ResourceReference(); ((Hl7.Fhir.Model.ResourceReference)current.Subject).DeserializeJson(ref reader, options); break; case "date": if (reader.TokenType == JsonTokenType.Null) { current.DateElement = new FhirDateTime(); reader.Skip(); } else { current.DateElement = new FhirDateTime(reader.GetString()); } break; case "_date": if (current.DateElement == null) { current.DateElement = new FhirDateTime(); } ((Hl7.Fhir.Model.Element)current.DateElement).DeserializeJson(ref reader, options); break; case "reporter": current.Reporter = new Hl7.Fhir.Model.ResourceReference(); ((Hl7.Fhir.Model.ResourceReference)current.Reporter).DeserializeJson(ref reader, options); break; case "period": current.Period = new Hl7.Fhir.Model.Period(); ((Hl7.Fhir.Model.Period)current.Period).DeserializeJson(ref reader, options); break; case "improvementNotation": current.ImprovementNotation = new Hl7.Fhir.Model.CodeableConcept(); ((Hl7.Fhir.Model.CodeableConcept)current.ImprovementNotation).DeserializeJson(ref reader, options); break; case "group": if ((reader.TokenType != JsonTokenType.StartArray) || (!reader.Read())) { throw new JsonException($"MeasureReport error reading 'group' expected StartArray, found {reader.TokenType}! depth: {reader.CurrentDepth}, pos: {reader.BytesConsumed}"); } current.Group = new List <MeasureReport.GroupComponent>(); while (reader.TokenType != JsonTokenType.EndArray) { Hl7.Fhir.Model.MeasureReport.GroupComponent v_Group = new Hl7.Fhir.Model.MeasureReport.GroupComponent(); v_Group.DeserializeJson(ref reader, options); current.Group.Add(v_Group); if (!reader.Read()) { throw new JsonException($"MeasureReport error reading 'group' array, read failed! depth: {reader.CurrentDepth}, pos: {reader.BytesConsumed}"); } if (reader.TokenType == JsonTokenType.EndObject) { reader.Read(); } } if (current.Group.Count == 0) { current.Group = null; } break; case "evaluatedResource": if ((reader.TokenType != JsonTokenType.StartArray) || (!reader.Read())) { throw new JsonException($"MeasureReport error reading 'evaluatedResource' expected StartArray, found {reader.TokenType}! depth: {reader.CurrentDepth}, pos: {reader.BytesConsumed}"); } current.EvaluatedResource = new List <ResourceReference>(); while (reader.TokenType != JsonTokenType.EndArray) { Hl7.Fhir.Model.ResourceReference v_EvaluatedResource = new Hl7.Fhir.Model.ResourceReference(); v_EvaluatedResource.DeserializeJson(ref reader, options); current.EvaluatedResource.Add(v_EvaluatedResource); if (!reader.Read()) { throw new JsonException($"MeasureReport error reading 'evaluatedResource' array, read failed! depth: {reader.CurrentDepth}, pos: {reader.BytesConsumed}"); } if (reader.TokenType == JsonTokenType.EndObject) { reader.Read(); } } if (current.EvaluatedResource.Count == 0) { current.EvaluatedResource = null; } break; // Complex: MeasureReport, Export: MeasureReport, Base: DomainResource default: ((Hl7.Fhir.Model.DomainResource)current).DeserializeJsonProperty(ref reader, options, propertyName); break; } }
/// <summary>Loads from directory.</summary> /// <exception cref="DirectoryNotFoundException">Thrown when the requested directory is not /// present.</exception> /// <param name="dir"> The dir.</param> private static void LoadFromDirectory(string dir) { if (!Directory.Exists(dir)) { throw new DirectoryNotFoundException($"input directory: {dir} not found!"); } string[] files = Directory.GetFiles(dir, "*.json", SearchOption.AllDirectories); foreach (string filename in files) { Bundle bundle = _fhirJsonParser.Parse <Bundle>(File.ReadAllText(filename)); if ((bundle.Entry == null) || (bundle.Entry.Count == 0)) { continue; } // traverse the bundle entries foreach (Bundle.EntryComponent entry in bundle.Entry) { if ((entry == null) || (entry.Resource == null)) { continue; } switch (entry.Resource.TypeName) { case "Organization": string orgRef = $"Organization/{entry.Resource.Id}"; if (!_orgsByRef.ContainsKey(orgRef)) { _orgsByRef.Add(orgRef, (Organization)entry.Resource); } break; case "Location": // only load site locations Location loc = (Location)entry.Resource; if ((loc.PhysicalType != null) && (loc.PhysicalType.Coding != null) && (loc.PhysicalType.Coding.Count != 0) && (loc.PhysicalType.Coding[0].Code == "si")) { string locRef = $"Location/{entry.Resource.Id}"; if (!_locationsByRef.ContainsKey(locRef)) { _locationsByRef.Add(locRef, loc); } } break; case "Measure": Measure measure = (Measure)entry.Resource; if (!_measuresByUrl.ContainsKey(measure.Url)) { _measuresByUrl.Add(measure.Url, measure); } break; case "MeasureReport": MeasureReport report = (MeasureReport)entry.Resource; if (!_reportsByOrgRef.ContainsKey(report.Reporter.Reference)) { _reportsByOrgRef.Add( report.Reporter.Reference, new ReportCollection(report.Reporter.Reference)); } _reportsByOrgRef[report.Reporter.Reference].AddReport(report); break; } } } }
/// <summary>Gets a key.</summary> /// <param name="report">The report.</param> /// <returns>The key.</returns> private static string GetKey(MeasureReport report) { return($"{report.Period.End}{report.Measure}"); }