/// <summary> /// Internal notification logic /// </summary> private void NotifyInternal(object state) { // Get the state try { NotificationQueueWorkItem workItem = state as NotificationQueueWorkItem; ILocalizationService locale = this.Context.GetService(typeof(ILocalizationService)) as ILocalizationService; IDataPersistenceService idps = this.Context.GetService(typeof(IDataPersistenceService)) as IDataPersistenceService; if (workItem == null) { throw new ArgumentException("workItem"); } var evt = workItem.Event; if (idps != null) { evt = idps.GetContainer(workItem.Event.AlternateIdentifier, true) as RegistrationEvent; } var subject = workItem.Event.FindComponent(SVC.Core.ComponentModel.HealthServiceRecordSiteRoleType.SubjectOf) as Person; if (subject == null) { throw new InvalidOperationException(locale.GetString("NTFE001")); } // Now determine who will receive updates Trace.TraceInformation("Searching for targets for patient notification..."); List <TargetConfiguration> targets = null; lock (s_syncLock) { targets = s_configuration.Targets.FindAll(o => o.NotificationDomain.Exists(delegate(NotificationDomainConfiguration dc) { bool action = dc.Actions.Exists(act => (act.Action & workItem.Action) == workItem.Action); bool domain = dc.Domain == "*" || subject.AlternateIdentifiers.Exists(id => id.Domain == dc.Domain); return(action && domain); } )); } Trace.TraceInformation("{0} targets for patient notification found..."); // Notify the targets foreach (var itm in targets) { itm.Notifier.Context = this.Context; itm.Notifier.Notify(workItem); } } catch (Exception e) { Trace.TraceError(e.ToString()); } }
/// <summary> /// Get one registration event /// </summary> public Core.ComponentModel.RegistrationEvent GetRegistrationEvent(decimal id) { // Get all Services IAuditorService auditSvc = ApplicationContext.CurrentContext.GetService(typeof(IAuditorService)) as IAuditorService; IDataPersistenceService repSvc = ApplicationContext.CurrentContext.GetService(typeof(IDataPersistenceService)) as IDataPersistenceService; // Audit message AuditData audit = this.ConstructAuditData(ActionType.Read, EventIdentifierType.Export); audit.EventTypeCode = new CodeValue("ADM_GetRegistrationEvent"); try { // Result identifiers var retVal = repSvc.GetContainer(new VersionedDomainIdentifier() { Domain = ApplicationContext.ConfigurationService.OidRegistrar.GetOid("REG_EVT").Oid, Identifier = id.ToString() }, false) as RegistrationEvent; // Add audit data if (retVal != null) { audit.AuditableObjects.Add(new AuditableObject() { IDTypeCode = AuditableObjectIdType.ReportNumber, LifecycleType = AuditableObjectLifecycle.Export, ObjectId = String.Format("{0}^^^&{1}&ISO", retVal.AlternateIdentifier.Identifier, retVal.AlternateIdentifier.Domain), Role = AuditableObjectRole.MasterFile, Type = AuditableObjectType.SystemObject, QueryData = Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes("loadFast=false")) }); } return(retVal); } catch (Exception e) { Trace.TraceError("Could not execute GetRegistration : {0}", e.ToString()); audit.Outcome = OutcomeIndicator.EpicFail; #if DEBUG throw new FaultException(new FaultReason(e.ToString()), new FaultCode(e.GetType().Name)); #else throw new FaultException(new FaultReason(e.Message), new FaultCode(e.GetType().Name)); #endif } finally { if (auditSvc != null) { auditSvc.SendAudit(audit); } } }
/// <summary> /// Read a patint resource /// </summary> public SVC.Messaging.FHIR.FhirOperationResult Read(string id, string versionId) { FhirOperationResult result = new FhirOperationResult(); result.Details = new List <IResultDetail>(); result.Results = new List <ResourceBase>(); // Data persistence service IDataPersistenceService dataPersistence = ApplicationContext.CurrentContext.GetService(typeof(IDataPersistenceService)) as IDataPersistenceService; var container = dataPersistence.GetContainer(new VersionedDomainIdentifier() { Domain = this.DataDomain, Identifier = id, Version = String.IsNullOrEmpty(versionId) ? null : versionId }, String.IsNullOrEmpty(versionId)); // Container was not found if (container == null) { result.Outcome = ResultCode.NotAvailable; } else { var processor = FhirMessageProcessorUtil.GetComponentProcessor(container.GetType()); // Was there a history? if (versionId == null) { result.Results.Add(processor.ProcessComponent(container as IComponent, result.Details)); } else if (versionId == String.Empty) // Get all versions { while (container != null) { var hsrc = container as HealthServiceRecordContainer; var resource = processor.ProcessComponent(container as IComponent, result.Details); if (hsrc.IsMasked) // record is masked so add a detected issue { result.Issues.Add(new SVC.Core.Issues.DetectedIssue() { MitigatedBy = ManagementType.OtherActionTaken, Severity = IssueSeverityType.Moderate, Text = String.Format("{0}/_history/{1} will not be returned as it has been masked", resource.Id, resource.VersionId), Type = IssueType.DetectedIssue }); } else { result.Results.Add(resource); } container = hsrc.FindComponent(HealthServiceRecordSiteRoleType.OlderVersionOf) as IContainer; } } else // Some version { while (container != null) { var hsrc = container as HealthServiceRecordContainer; var resource = processor.ProcessComponent(container as IComponent, result.Details); container = hsrc.FindComponent(HealthServiceRecordSiteRoleType.ReplacementOf) as IContainer; if (resource != null && resource.VersionId.ToString() != versionId) { continue; } if (hsrc.IsMasked) // record is masked so add a detected issue { result.Issues.Add(new SVC.Core.Issues.DetectedIssue() { MitigatedBy = ManagementType.OtherActionTaken, Severity = IssueSeverityType.Moderate, Text = String.Format("{0}/_history/{1} will not be returned as it has been masked", resource.Id, resource.VersionId), Type = IssueType.DetectedIssue }); } else { result.Results.Add(resource); } } } result.Outcome = ResultCode.Accepted; } result.Results.RemoveAll(o => o == null); return(result); }
/// <summary> /// Get recent activity /// </summary> public RegistrationEventCollection GetRecentActivity(TimestampSet timeRange, int offset, int count, bool identifierOnly) { // Get all Services IAuditorService auditSvc = ApplicationContext.CurrentContext.GetService(typeof(IAuditorService)) as IAuditorService; IDataRegistrationService regSvc = ApplicationContext.CurrentContext.GetService(typeof(IDataRegistrationService)) as IDataRegistrationService; IDataPersistenceService repSvc = ApplicationContext.CurrentContext.GetService(typeof(IDataPersistenceService)) as IDataPersistenceService; // Audit message AuditData audit = this.ConstructAuditData(ActionType.Read, EventIdentifierType.Export); audit.EventTypeCode = new CodeValue("ADM_GetRegistrations"); try { // Result identifiers VersionedDomainIdentifier[] vids = null; var dummyQuery = new QueryEvent(); dummyQuery.Add(new RegistrationEvent() { EventClassifier = RegistrationEventType.Register, EffectiveTime = timeRange }, "SUBJ", SVC.Core.ComponentModel.HealthServiceRecordSiteRoleType.SubjectOf, null); vids = regSvc.QueryRecord(dummyQuery); RegistrationEventCollection retVal = new RegistrationEventCollection(); Object syncLock = new object(); retVal.Count = vids.Length; // Now fetch each one asynchronously if (!identifierOnly) { using (WaitThreadPool thdPool = new WaitThreadPool(Environment.ProcessorCount * 2)) { foreach (var id in vids.Skip(offset).Take(count)) { thdPool.QueueUserWorkItem( delegate(object state) { try { var itm = repSvc.GetContainer(state as VersionedDomainIdentifier, true); lock (syncLock) retVal.Event.Add(itm as RegistrationEvent); } catch (Exception e) { Trace.TraceError("Could not fetch result {0} : {1}", (state as VersionedDomainIdentifier).Identifier, e.ToString()); } } , id); } // Wait until fetch is done thdPool.WaitOne(new TimeSpan(0, 0, 30), false); } //retVal.Event.Sort((a, b) => b.Timestamp.CompareTo(a.Timestamp)); // Add audit data foreach (var res in retVal.Event) { audit.AuditableObjects.Add(new AuditableObject() { IDTypeCode = AuditableObjectIdType.ReportNumber, LifecycleType = AuditableObjectLifecycle.Export, ObjectId = String.Format("{0}^^^&{1}&ISO", res.AlternateIdentifier.Identifier, res.AlternateIdentifier.Domain), Role = AuditableObjectRole.MasterFile, Type = AuditableObjectType.SystemObject, QueryData = Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes("loadFast=true")) }); } } return(retVal); } catch (Exception e) { Trace.TraceError("Could not execute GetRegistrations : {0}", e.ToString()); audit.Outcome = OutcomeIndicator.EpicFail; #if DEBUG throw new FaultException(new FaultReason(e.ToString()), new FaultCode(e.GetType().Name)); #else throw new FaultException(new FaultReason(e.Message), new FaultCode(e.GetType().Name)); #endif } finally { if (auditSvc != null) { auditSvc.SendAudit(audit); } } }
/// <summary> /// Perform a merge /// </summary> public Core.ComponentModel.RegistrationEvent Merge(decimal[] sourceIds, decimal targetId) { // Get all Services IAuditorService auditSvc = ApplicationContext.CurrentContext.GetService(typeof(IAuditorService)) as IAuditorService; IDataPersistenceService repSvc = ApplicationContext.CurrentContext.GetService(typeof(IDataPersistenceService)) as IDataPersistenceService; IClientRegistryMergeService mergeSvc = ApplicationContext.CurrentContext.GetService(typeof(IClientRegistryMergeService)) as IClientRegistryMergeService; // Audit message List <AuditData> auditMessages = new List <AuditData>(); try { // Prepare merge List <VersionedDomainIdentifier> domainId = new List <VersionedDomainIdentifier>(sourceIds.Length); foreach (var srcId in sourceIds) { domainId.Add(new VersionedDomainIdentifier() { Domain = ApplicationContext.ConfigurationService.OidRegistrar.GetOid("REG_EVT").Oid, Identifier = srcId.ToString() }); var am = ConstructAuditData(ActionType.Delete, EventIdentifierType.Import); am.EventTypeCode = new CodeValue("ADM_Merge"); am.AuditableObjects.Add(new AuditableObject() { IDTypeCode = AuditableObjectIdType.ReportNumber, LifecycleType = AuditableObjectLifecycle.LogicalDeletion, ObjectId = String.Format("{0}^^^&{1}&ISO", srcId, ApplicationContext.ConfigurationService.OidRegistrar.GetOid("REG_EVT").Oid), Role = AuditableObjectRole.MasterFile, Type = AuditableObjectType.SystemObject }); auditMessages.Add(am); } VersionedDomainIdentifier survivorId = new VersionedDomainIdentifier() { Domain = ApplicationContext.ConfigurationService.OidRegistrar.GetOid("REG_EVT").Oid, Identifier = targetId.ToString() }; var updateAudit = ConstructAuditData(ActionType.Update, EventIdentifierType.Import); updateAudit.EventTypeCode = new CodeValue("ADM_Merge"); updateAudit.AuditableObjects.Add(new AuditableObject() { IDTypeCode = AuditableObjectIdType.ReportNumber, LifecycleType = AuditableObjectLifecycle.Amendment, ObjectId = String.Format("{0}^^^&{1}&ISO", survivorId.Identifier, survivorId.Domain), Role = AuditableObjectRole.MasterFile, Type = AuditableObjectType.SystemObject }); auditMessages.Add(updateAudit); // Merge mergeSvc.Resolve(domainId, survivorId, DataPersistenceMode.Production); // Now load return(repSvc.GetContainer(survivorId, true) as RegistrationEvent); } catch (Exception e) { foreach (var am in auditMessages) { am.Outcome = OutcomeIndicator.EpicFail; } Trace.TraceError("Could not execute Merge : {0}", e.ToString()); #if DEBUG throw new FaultException(new FaultReason(e.ToString()), new FaultCode(e.GetType().Name)); #else throw new FaultException(new FaultReason(e.Message), new FaultCode(e.GetType().Name)); #endif } finally { if (auditSvc != null) { foreach (var am in auditMessages) { auditSvc.SendAudit(am); } } } }
/// <summary> /// Get all merge candidates /// </summary> public ConflictCollection GetConflicts(int offset, int count, bool identifierOnly) { // Get all Services IAuditorService auditSvc = ApplicationContext.CurrentContext.GetService(typeof(IAuditorService)) as IAuditorService; IDataPersistenceService repSvc = ApplicationContext.CurrentContext.GetService(typeof(IDataPersistenceService)) as IDataPersistenceService; IClientRegistryMergeService mergeSvc = ApplicationContext.CurrentContext.GetService(typeof(IClientRegistryMergeService)) as IClientRegistryMergeService; // Audit message AuditData audit = this.ConstructAuditData(ActionType.Read, EventIdentifierType.Export); audit.EventTypeCode = new CodeValue("ADM_GetConflicts"); try { // Get all with a merge var mergeResults = mergeSvc.GetOutstandingConflicts(); var retVal = new ConflictCollection(); retVal.Count = mergeResults.Count(); // Loop and load foreach (var merge in mergeResults.Skip(offset).Take(count)) { // Construct the return, and load match Conflict conf = new Conflict(); if (!identifierOnly) { conf.Source = repSvc.GetContainer(merge, true) as RegistrationEvent; // Add audit data audit.AuditableObjects.Add(new AuditableObject() { IDTypeCode = AuditableObjectIdType.ReportNumber, LifecycleType = AuditableObjectLifecycle.Export, ObjectId = String.Format("{0}^^^&{1}&ISO", conf.Source.AlternateIdentifier.Identifier, conf.Source.AlternateIdentifier.Domain), Role = AuditableObjectRole.MasterFile, Type = AuditableObjectType.SystemObject, QueryData = Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes("loadFast=false")) }); } // Load the matches foreach (var match in mergeSvc.GetConflicts(merge)) { if (!identifierOnly) { var matchRecord = repSvc.GetContainer(match, true) as RegistrationEvent; conf.Match.Add(matchRecord); // Add audit data audit.AuditableObjects.Add(new AuditableObject() { IDTypeCode = AuditableObjectIdType.ReportNumber, LifecycleType = AuditableObjectLifecycle.Export, ObjectId = String.Format("{0}^^^&{1}&ISO", matchRecord.AlternateIdentifier.Identifier, matchRecord.AlternateIdentifier.Domain), Role = AuditableObjectRole.MasterFile, Type = AuditableObjectType.SystemObject, QueryData = Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes("loadFast=false")) }); } else { conf.Match.Add(new RegistrationEvent() { AlternateIdentifier = match }); } } retVal.Conflict.Add(conf); } return(retVal); } catch (Exception e) { Trace.TraceError("Could not execute GetConflicts : {0}", e.ToString()); audit.Outcome = OutcomeIndicator.EpicFail; #if DEBUG throw new FaultException(new FaultReason(e.ToString()), new FaultCode(e.GetType().Name)); #else throw new FaultException(new FaultReason(e.Message), new FaultCode(e.GetType().Name)); #endif } finally { if (auditSvc != null) { auditSvc.SendAudit(audit); } } }