public MeasurementEventNormalizationService( ITelemetryLogger log, IContentTemplate contentTemplate, IExceptionTelemetryProcessor exceptionTelemetryProcessor) : this(log, contentTemplate, new EventDataWithJsonBodyToJTokenConverter(), exceptionTelemetryProcessor, 1) { }
public MeasurementEventNormalizationService(ITelemetryLogger log, IContentTemplate contentTemplate, Data.IConverter <EventData, JToken> converter, int maxParallelism) { _log = EnsureArg.IsNotNull(log, nameof(log)); _contentTemplate = EnsureArg.IsNotNull(contentTemplate, nameof(contentTemplate)); _converter = EnsureArg.IsNotNull(converter, nameof(converter)); _maxParallelism = maxParallelism; }
public MeasurementEventNormalizationServiceTests() { _template = Substitute.For <IContentTemplate>(); _consumer = Substitute.For <IEnumerableAsyncCollector <IMeasurement> >(); _converter = Substitute.For <IConverter <EventData, JToken> >(); _logger = Substitute.For <ITelemetryLogger>(); _exceptionTelemetryProcessor = Substitute.For <IExceptionTelemetryProcessor>(); }
public CollectionContentTemplate RegisterTemplate(IContentTemplate contentTemplate) { EnsureArg.IsNotNull(contentTemplate, nameof(contentTemplate)); _templates.Add(contentTemplate); return(this); }
/// <summary>Inject the current page into the page handler.</summary> /// <param name="handler">The handler executing the request.</param> public virtual void InjectCurrentPage(PathData path, IHttpHandler handler) { IContentTemplate template = handler as IContentTemplate; if (template != null && path != null) { template.CurrentItem = path.CurrentPage; } }
private void CheckForTemplateCompatibility(IContentTemplate contentTemplate, ILookupTemplate <IFhirTemplate> fhirTemplate, TemplateResult validationResult) { var deviceTemplates = new List <MeasurementExtractor>(); var fhirTemplates = new List <CodeValueFhirTemplate>(); var availableFhirTemplates = string.Empty; // TODO: Confirm that outer template factories are always collections for both Device and Fhir Mappings. This implies that // customers must always wrap their templates inside of a CollectionXXX Template. if (contentTemplate is CollectionContentTemplate collectionContentTemplate) { deviceTemplates.AddRange(collectionContentTemplate.Templates.Select(t => t as MeasurementExtractor)); } if (fhirTemplate is FhirLookupTemplate fhirLookupTemplate) { fhirTemplates.AddRange(fhirLookupTemplate.Templates.Select(t => t as CodeValueFhirTemplate)); availableFhirTemplates = string.Join(" ,", fhirTemplates.Select(t => t.TypeName)); } foreach (var extractor in deviceTemplates) { try { var innerTemplate = extractor.Template; var matchingFhirTemplate = fhirTemplate.GetTemplate(innerTemplate.TypeName) as CodeValueFhirTemplate; var availableFhirValueNames = new HashSet <string>(GetFhirValues(matchingFhirTemplate).Select(v => v.ValueName)); var availableFhirValueNamesDisplay = string.Join(" ,", availableFhirValueNames); // Ensure all values are present if (extractor.Template.Values != null) { foreach (var v in extractor.Template.Values) { if (!availableFhirValueNames.Contains(v.ValueName)) { validationResult.CaptureWarning( $"The value [{v.ValueName}] in Device Mapping [{extractor.Template.TypeName}] is not represented within the Fhir Template of type [{innerTemplate.TypeName}]. Available values are: [{availableFhirValueNamesDisplay}]. No value will appear inside of Observations.", ValidationCategory.FHIRTRANSFORMATION, LineInfo.Default); } } } } catch (TemplateNotFoundException) { validationResult.CaptureWarning( $"No matching Fhir Template exists for Device Mapping [{extractor.Template.TypeName}]. Ensure case matches. Available Fhir Templates: [{availableFhirTemplates}].", ValidationCategory.FHIRTRANSFORMATION, LineInfo.Default); } catch (Exception e) { validationResult.CaptureException(e, ValidationCategory.FHIRTRANSFORMATION); } } }
public MeasurementEventNormalizationService( ITelemetryLogger log, IContentTemplate contentTemplate, Data.IConverter <EventData, JToken> converter, IExceptionTelemetryProcessor exceptionTelemetryProcessor, int maxParallelism, int asyncCollectorBatchSize = 200) { _log = EnsureArg.IsNotNull(log, nameof(log)); _contentTemplate = EnsureArg.IsNotNull(contentTemplate, nameof(contentTemplate)); _converter = EnsureArg.IsNotNull(converter, nameof(converter)); _exceptionTelemetryProcessor = EnsureArg.IsNotNull(exceptionTelemetryProcessor, nameof(exceptionTelemetryProcessor)); _maxParallelism = maxParallelism; _asyncCollectorBatchSize = EnsureArg.IsGt(asyncCollectorBatchSize, 0, nameof(asyncCollectorBatchSize)); }
protected virtual void ProcessDeviceEvent(JToken deviceEvent, IContentTemplate contentTemplate, DeviceResult validationResult) { try { foreach (var m in contentTemplate.GetMeasurements(deviceEvent)) { validationResult.Measurements.Add(m); } if (validationResult.Measurements.Count == 0) { validationResult.CaptureWarning("No measurements were produced for the given device data.", ValidationCategory.NORMALIZATION, LineInfo.Default); } } catch (Exception e) { validationResult.CaptureException(e, ValidationCategory.NORMALIZATION); } }
public void GivenInputWithNoMatchingFactories_WhenCreate_ThenException_Test(string json) { IContentTemplate nullReturn = null; var factoryA = Substitute.For <ITemplateFactory <TemplateContainer, IContentTemplate> >(); factoryA.Create(Arg.Is <TemplateContainer>(v => !v.MatchTemplateName("mockA"))).Returns(nullReturn); var factoryB = Substitute.For <ITemplateFactory <TemplateContainer, IContentTemplate> >(); factoryB.Create(Arg.Is <TemplateContainer>(v => !v.MatchTemplateName("mockC"))).Returns(nullReturn); var factory = new CollectionContentTemplateFactory(factoryA, factoryB); Assert.Throws <InvalidTemplateException>(() => factory.Create(json)); factoryA.ReceivedWithAnyArgs().Create(null); factoryB.ReceivedWithAnyArgs().Create(null); }
public void GivenInputWithMatchingFactories_WhenCreate_ThenTemplateReturned_Test(string json) { IContentTemplate nullReturn = null; var factoryA = Substitute.For <ITemplateFactory <TemplateContainer, IContentTemplate> >(); factoryA.Create(Arg.Is <TemplateContainer>(v => !v.MatchTemplateName("mockA"))).Returns(nullReturn); var factoryB = Substitute.For <ITemplateFactory <TemplateContainer, IContentTemplate> >(); factoryB.Create(Arg.Is <TemplateContainer>(v => !v.MatchTemplateName("mockB"))).Returns(nullReturn); var factory = new CollectionContentTemplateFactory(factoryA, factoryB); var template = factory.Create(json); Assert.NotNull(template); factoryA.ReceivedWithAnyArgs().Create(null); factoryB.ReceivedWithAnyArgs().Create(null); }
public ValidationResult PerformValidation( IEnumerable <JToken> deviceEvents, string deviceMappingContent, string fhirMappingContent, bool aggregateDeviceEvents = false) { if (string.IsNullOrWhiteSpace(deviceMappingContent) && string.IsNullOrWhiteSpace(fhirMappingContent)) { throw new ArgumentException($"At least one of [{nameof(deviceMappingContent)}] or [{nameof(fhirMappingContent)}] must be provided"); } var validationResult = new ValidationResult(); IContentTemplate contentTemplate = null; ILookupTemplate <IFhirTemplate> fhirTemplate = null; if (!string.IsNullOrEmpty(deviceMappingContent)) { contentTemplate = LoadDeviceTemplate(deviceMappingContent, validationResult.TemplateResult); } if (!string.IsNullOrEmpty(fhirMappingContent)) { fhirTemplate = LoadFhirTemplate(fhirMappingContent, validationResult.TemplateResult); } if (contentTemplate != null && fhirTemplate != null) { CheckForTemplateCompatibility(contentTemplate, fhirTemplate, validationResult.TemplateResult); } if (validationResult.TemplateResult.GetErrors(ErrorLevel.ERROR).Count() > 0) { // Fail early since there are errors with the template. return(validationResult); } ValidateDeviceEvents(deviceEvents, contentTemplate, fhirTemplate, validationResult, aggregateDeviceEvents); return(validationResult); }
public void GivenMultiValueTemplateAndValidTokenArrayWithAllValues_WhenGetMeasurements_ThenSingleMeasurementReturned_Test(IContentTemplate template) { var time = DateTime.UtcNow; var token = JToken.FromObject( new { Body = new[] { new { systolic = "120", diastolic = "80", device = "abc", date = time }, new { systolic = "122", diastolic = "82", device = "abc", date = time.AddMinutes(-1) }, new { systolic = "100", diastolic = "70", device = "abc", date = time.AddMinutes(-2) }, }, }); var result = template.GetMeasurements(token).ToArray(); Assert.NotNull(result); Assert.Collection( result, m => { Assert.Equal("bloodpressure", m.Type); Assert.Equal(time, m.OccurrenceTimeUtc); Assert.Equal("abc", m.DeviceId); Assert.Null(m.PatientId); Assert.Null(m.EncounterId); Assert.Null(m.CorrelationId); Assert.Collection( m.Properties, p => { Assert.Equal("systolic", p.Name); Assert.Equal("120", p.Value); }, p => { Assert.Equal("diastolic", p.Name); Assert.Equal("80", p.Value); }); }, m => { Assert.Equal("bloodpressure", m.Type); Assert.Equal(time.AddMinutes(-1), m.OccurrenceTimeUtc); Assert.Equal("abc", m.DeviceId); Assert.Null(m.PatientId); Assert.Null(m.EncounterId); Assert.Collection( m.Properties, p => { Assert.Equal("systolic", p.Name); Assert.Equal("122", p.Value); }, p => { Assert.Equal("diastolic", p.Name); Assert.Equal("82", p.Value); }); }, m => { Assert.Equal("bloodpressure", m.Type); Assert.Equal(time.AddMinutes(-2), m.OccurrenceTimeUtc); Assert.Equal("abc", m.DeviceId); Assert.Null(m.PatientId); Assert.Null(m.EncounterId); Assert.Collection( m.Properties, p => { Assert.Equal("systolic", p.Name); Assert.Equal("100", p.Value); }, p => { Assert.Equal("diastolic", p.Name); Assert.Equal("70", p.Value); }); }); }
public void GivenMultiValueTemplateAndValidTokenWithAllValues_WhenGetMeasurements_ThenSingleMeasurementReturned_Test(IContentTemplate template) { var time = DateTime.UtcNow; var token = JToken.FromObject(new { heartrate = "60", steps = "2", device = "abc", date = time }); var result = template.GetMeasurements(token).ToArray(); Assert.NotNull(result); Assert.Collection(result, m => { Assert.Equal("hrStepCombo", m.Type); Assert.Equal(time, m.OccurrenceTimeUtc); Assert.Equal("abc", m.DeviceId); Assert.Null(m.PatientId); Assert.Null(m.EncounterId); Assert.Null(m.CorrelationId); Assert.Collection( m.Properties, p => { Assert.Equal("hr", p.Name); Assert.Equal("60", p.Value); }, p => { Assert.Equal("steps", p.Name); Assert.Equal("2", p.Value); }); }); }
public void GivenTemplateWithCorrelationIdAndIdMissing_WhenGetMeasurements_ThenArgumentNullExceptionThrown_Test(IContentTemplate template) { var time = DateTime.UtcNow; var token = JToken.FromObject(new { heartrate = "60", device = "abc", date = time }); var ex = Assert.Throws <IncompatibleDataException>(() => template.GetMeasurements(token).ToArray()); Assert.Contains("Unable to extract required value for [CorrelationIdExpression]", ex.Message); }
public void GivenTemplateWithCorrelationIdAndIdPresent_WhenGetMeasurements_ThenCorrelationIdReturn_Test(IContentTemplate template) { var time = DateTime.UtcNow; var session = Guid.NewGuid().ToString(); var token = JToken.FromObject(new { heartrate = "60", device = "abc", date = time, session }); var result = template.GetMeasurements(token).ToArray(); Assert.NotNull(result); Assert.Collection(result, m => { Assert.Equal("heartrate", m.Type); Assert.Equal(time, m.OccurrenceTimeUtc); Assert.Equal("abc", m.DeviceId); Assert.Null(m.PatientId); Assert.Null(m.EncounterId); Assert.Equal(session, m.CorrelationId); Assert.Collection(m.Properties, p => { Assert.Equal("hr", p.Name); Assert.Equal("60", p.Value); }); }); }
public void GivenTemplateAndInvalidToken_WhenGetMeasurements_ThenEmptyIEnumerableReturned_Test(IContentTemplate contentTemplate) { var time = DateTime.UtcNow; var token = JToken.FromObject(new { foo = "60", device = "abc", date = time }); var result = contentTemplate.GetMeasurements(token).ToArray(); Assert.NotNull(result); Assert.Empty(result); }
public void GivenSingleValueOptionalContentTemplateAndValidToken_WhenGetMeasurements_ThenSingleMeasurementReturned_Test(IContentTemplate contentTemplate) { var time = DateTime.UtcNow; var token = JToken.FromObject(new { heartrate = "60", device = "abc", date = time, pid = "123", eid = "789" }); var result = contentTemplate.GetMeasurements(token).ToArray(); Assert.NotNull(result); Assert.Collection(result, m => { Assert.Equal("heartrate", m.Type); Assert.Equal(time, m.OccurrenceTimeUtc); Assert.Equal("abc", m.DeviceId); Assert.Equal("123", m.PatientId); Assert.Equal("789", m.EncounterId); Assert.Null(m.CorrelationId); Assert.Collection(m.Properties, p => { Assert.Equal("hr", p.Name); Assert.Equal("60", p.Value); }); }); }
public void GivenMultiValueRequiredTemplateAndValidTokenWithMissingValue_WhenGetMeasurements_ThenInvalidOperationException_Test(IContentTemplate template) { var time = DateTime.UtcNow; var token = JToken.FromObject( new { Body = new[] { new { systolic = "120", device = "abc", date = time }, }, }); Assert.Throws <IncompatibleDataException>(() => template.GetMeasurements(token).ToArray()); }
private void treeView1_NodeMouseDoubleClick(object sender, TreeNodeMouseClickEventArgs e) { var item = GetTemplateFromNode(); if (item != null) { SelectedTemplate = item; Close(); } else { // Do something here if we want to act on a folder node, for now there's no need. } }
/// <summary> /// Validates device events. This method then enriches the passed in ValidationResult object with DeviceResults. /// </summary> /// <param name="deviceEvents">The device events to validate</param> /// <param name="contentTemplate">The device mapping template</param> /// <param name="fhirTemplate">The fhir mapping template</param> /// <param name="validationResult">The ValidationResult</param> /// <param name="aggregateDeviceEvents">Indicates if DeviceResults should be aggregated</param> protected virtual void ValidateDeviceEvents( IEnumerable <JToken> deviceEvents, IContentTemplate contentTemplate, ILookupTemplate <IFhirTemplate> fhirTemplate, ValidationResult validationResult, bool aggregateDeviceEvents) { var aggregatedDeviceResults = new Dictionary <string, DeviceResult>(); foreach (var payload in deviceEvents) { if (payload != null && contentTemplate != null) { var deviceResult = new DeviceResult(); deviceResult.DeviceEvent = payload; ProcessDeviceEvent(payload, contentTemplate, deviceResult); if (fhirTemplate != null) { foreach (var m in deviceResult.Measurements) { ProcessNormalizedEvent(m, fhirTemplate, deviceResult); } } if (aggregateDeviceEvents) { /* * During aggregation we group DeviceEvents by the exceptions that they produce. * This allows us to return a DeviceResult with a sample Device Event payload, * the running count grouped DeviceEvents and the exception that they are grouped by. */ foreach (var exception in deviceResult.Exceptions) { if (aggregatedDeviceResults.TryGetValue(exception.Message, out DeviceResult result)) { // If we've already seen this error message before, simply increment the running total result.AggregatedCount++; } else { // Create a new DeviceResult to hold details about this new exception. var aggregatedDeviceResult = new DeviceResult() { DeviceEvent = deviceResult.DeviceEvent, // A sample device event which exhibits the error AggregatedCount = 1, Exceptions = new List <ValidationError>() { exception }, }; aggregatedDeviceResults[exception.Message] = aggregatedDeviceResult; validationResult.DeviceResults.Add(aggregatedDeviceResult); } } } else { validationResult.DeviceResults.Add(deviceResult); } } } }
public void GivenSingleValueTemplateAndNullTimestampToken_WhenGetMeasurements_Then_ExceptionIsThrown(IContentTemplate contentTemplate) { var time = DateTime.UtcNow; var token = JToken.FromObject(new { heartrate = "60", device = "abc", date = (DateTime?)null }); Assert.Throws <IncompatibleDataException>(() => contentTemplate.GetMeasurements(token).ToArray()); }
public ContentSaveRequestPacket(IContentTemplate contentObject, ContentType contentType) { ContentObject = contentObject; ContentType = contentType; }
public MeasurementEventNormalizationService(ITelemetryLogger log, IContentTemplate contentTemplate) : this(log, contentTemplate, new EventDataWithJsonBodyToJTokenConverter(), 3) { }
public CollectionContentTemplate RegisterTemplate(IContentTemplate contentTemplate) { _templates.Add(contentTemplate); return(this); }
public void GivenSingleValueCompoundAndTemplateAndPartialToken_WhenGetMeasurements_ThenEmptyIEnumerableReturned_Test(IContentTemplate template) { var time = DateTime.UtcNow; var token = JToken.FromObject(new { heartrate = "60", device = "abc", mdate = time }); var result = template.GetMeasurements(token).ToArray(); Assert.NotNull(result); Assert.Empty(result); }