public MeasurementEventNormalizationService(
     ITelemetryLogger log,
     IContentTemplate contentTemplate,
     IExceptionTelemetryProcessor exceptionTelemetryProcessor)
     : this(log, contentTemplate, new EventDataWithJsonBodyToJTokenConverter(), exceptionTelemetryProcessor, 1)
 {
 }
Exemplo n.º 2
0
 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>();
 }
Exemplo n.º 4
0
        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;
            }
        }
Exemplo n.º 6
0
        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));
 }
Exemplo n.º 8
0
        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);
            }
        }
Exemplo n.º 9
0
        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);
        }
Exemplo n.º 10
0
        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);
        }
Exemplo n.º 11
0
        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());
        }
Exemplo n.º 19
0
        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.
            }
        }
Exemplo n.º 20
0
        /// <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;
 }
Exemplo n.º 23
0
 public MeasurementEventNormalizationService(ITelemetryLogger log, IContentTemplate contentTemplate)
     : this(log, contentTemplate, new EventDataWithJsonBodyToJTokenConverter(), 3)
 {
 }
Exemplo n.º 24
0
 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);
        }