/// <summary> /// Redirect persistence event /// </summary> private void OnPrePersistenceEvent(object sender, DataPersistingEventArgs <T> e) { if (e.Data is Bundle bundle) { foreach (var itm in bundle.Item.ToArray()) { var masterRel = this.GetMasterRedirect(itm.Key, itm.GetType()); if (masterRel != null) { if (itm is Entity entity) // Add the MDM rel back so it can be saved { entity.Relationships.Add(masterRel as EntityRelationship); } } } } else if (e.Data.Key.HasValue) // update/insert { var masterRel = this.GetMasterRedirect(e.Data.Key); if (masterRel != null) // has a master, so update that instead { if (e.Data is Entity entity) // Add the MDM rel back so it can be saved { entity.Relationships.Add(masterRel as EntityRelationship); } } } }
/// <summary> /// Performs insert of object /// </summary> public virtual TEntity Insert(TEntity data) { // Demand permission this.DemandWrite(data); var persistenceService = ApplicationContext.Current.GetService <IDataPersistenceService <TEntity> >(); if (persistenceService == null) { throw new InvalidOperationException($"Unable to locate {nameof(IDataPersistenceService<TEntity>)}"); } var preEvent = new DataPersistingEventArgs <TEntity>(data, TransactionMode.Commit, AuthenticationContext.Current.Principal); this.Inserting?.Invoke(this, preEvent); if (preEvent.Cancel) { this.m_traceSource.TraceWarning("Pre-persistence event indicates cancel"); return(preEvent.Data); } data = preEvent.Data; data = this.Validate(data); var businessRulesService = ApplicationContext.Current.GetService <IBusinessRulesService <TEntity> >(); data = businessRulesService?.BeforeInsert(data) ?? data; data = persistenceService.Insert(data, TransactionMode.Commit, AuthenticationContext.Current.Principal); ApplicationContext.Current.GetService <IQueueManagerService>()?.Outbound.Enqueue(data, SynchronizationOperationType.Insert); data = businessRulesService?.AfterInsert(data) ?? data; this.Inserted?.Invoke(this, new DataPersistedEventArgs <TEntity>(data, TransactionMode.Commit, AuthenticationContext.Current.Principal)); return(data); }
/// <summary> /// Performs insert of object /// </summary> public virtual TEntity Insert(TEntity data) { // Demand permission this.DemandWrite(data); // Validate the resource data = this.Validate(data); // Fire pre-persistence triggers var prePersistence = new DataPersistingEventArgs <TEntity>(data, AuthenticationContext.Current.Principal); this.Inserting?.Invoke(this, prePersistence); if (prePersistence.Cancel) { this.m_traceSource.TraceWarning("Pre-persistence event signal cancel: {0}", data); return(prePersistence.Data); } // Did the pre-persistence service change the type to a batch var businessRulesService = ApplicationServiceContext.Current.GetBusinessRulesService <TEntity>(); var persistenceService = ApplicationServiceContext.Current.GetService <IDataPersistenceService <TEntity> >(); data = businessRulesService?.BeforeInsert(data) ?? prePersistence.Data; data = persistenceService.Insert(data, TransactionMode.Commit, AuthenticationContext.Current.Principal); businessRulesService?.AfterInsert(data); this.Inserted?.Invoke(this, new DataPersistedEventArgs <TEntity>(data, AuthenticationContext.Current.Principal)); return(data); }
/// <summary> /// Inserts the specified storage data. /// </summary> /// <param name="storageData">The storage data.</param> /// <param name="overrideAuthContext">The principal to use instead of the default.</param> /// <param name="mode">The mode.</param> /// <returns>Returns the inserted model instance.</returns> public TModel Insert(TModel storageData, TransactionMode mode, IPrincipal overrideAuthContext = null) { if (storageData == null) { throw new ArgumentNullException(nameof(storageData), "Value cannot be null"); } var preInsertArgs = new DataPersistingEventArgs <TModel>(storageData, overrideAuthContext); this.Inserting?.Invoke(this, preInsertArgs); if (preInsertArgs.Cancel) { traceSource.TraceEvent(EventLevel.Warning, $"Pre-event handler indicates abort insert for : {storageData}"); return(storageData); } using (var connection = Configuration.Provider.GetWriteConnection()) { connection.Open(); using (var transaction = connection.BeginTransaction()) { try { var existing = this.Get(connection, storageData.Key.Value, false, overrideAuthContext); if (existing != null) { throw new DuplicateNameException(storageData.Key?.ToString()); } else { this.traceSource.TraceEvent(EventLevel.Verbose, "INSERT {0}", storageData); storageData = this.Insert(connection, storageData); } if (mode == TransactionMode.Commit) { transaction.Commit(); } else { transaction.Rollback(); } this.Inserted?.Invoke(this, new DataPersistedEventArgs <TModel>(storageData, overrideAuthContext)); return(storageData); } catch (Exception e) { this.traceSource.TraceEvent(EventLevel.Error, "Error : {0}", e); transaction?.Rollback(); throw new DataPersistenceException(e.Message, e); } } } }
/// <summary> /// Represents the bundle operation /// </summary> protected void AdtPatientRegistrationInterceptor_Bundle(object sender, DataPersistingEventArgs <Bundle> e) { foreach (var itm in e.Data.Item.OfType <Patient>()) { AdtPatientRegistrationInterceptor_Behavior(sender, new DataPersistingEventArgs <Patient>(itm, e.Principal)); } e.Cancel = true; }
/// <summary> /// Obsoletes the specified storage data. /// </summary> /// <param name="storageData">The storage data.</param> /// <param name="overrideAuthContext">The principal to use instead of the default.</param> /// <param name="mode">The mode.</param> /// <returns>TModel.</returns> public TModel Obsolete(TModel storageData, TransactionMode mode, IPrincipal overrideAuthContext = null) { if (storageData == null) { throw new ArgumentNullException(nameof(storageData), "Value cannot be null"); } if (!storageData.Key.HasValue || storageData.Key == Guid.Empty) { throw new InvalidOperationException("Data missing key"); } var prePersistenceEventArgs = new DataPersistingEventArgs <TModel>(storageData, overrideAuthContext); this.Obsoleting?.Invoke(this, prePersistenceEventArgs); if (prePersistenceEventArgs.Cancel) { traceSource.TraceEvent(EventLevel.Warning, $"Pre-event handler indicates abort for {storageData}"); return(storageData); } using (var connection = Configuration.Provider.GetWriteConnection()) { connection.Open(); using (var transaction = connection.BeginTransaction()) { try { this.traceSource.TraceEvent(EventLevel.Verbose, $"OBSOLETE {storageData}"); storageData = this.Obsolete(connection, storageData); if (mode == TransactionMode.Commit) { transaction.Commit(); } else { transaction.Rollback(); } var args = new DataPersistedEventArgs <TModel>(storageData, overrideAuthContext); this.Obsoleted?.Invoke(this, args); return(storageData); } catch (Exception e) { traceSource.TraceEvent(EventLevel.Error, $"Error obsoleting: {storageData}"); transaction.Rollback(); throw new DataPersistenceException(e.Message, e); } } } }
public DiagnosticReport Insert(DiagnosticReport storageData, TransactionMode mode, IPrincipal overrideAuthContext = null) { var persistenceArgs = new DataPersistingEventArgs <DiagnosticReport>(storageData, mode, overrideAuthContext); this.Inserting?.Invoke(this, persistenceArgs); if (persistenceArgs.Cancel) { this.m_traceSource.TraceEvent(EventLevel.Warning, "Pre-persistence event cancelled the insertion"); return(persistenceArgs.Data); } try { var issueId = DateTimeOffset.Now.ToString("yyyy-MM-dd-HHmmss"); var subject = $"SANTEDB ISSUE MAILER #{issueId}"; var body = $"<html><body><p>{storageData.LoadProperty<SecurityUser>("CreatedBy")?.UserName ?? storageData?.Submitter?.LoadProperty<SecurityUser>("SecurityUser")?.UserName} has reported a bug</p><pre>{storageData.Note}</pre><p>You can reply directly to the reporter by pressing the Reply button in your mail client</p></body></html>"; var attachments = storageData.Attachments.Select(a => { if (a is DiagnosticBinaryAttachment bin) { return(new NotificationAttachment(a.FileName ?? a.FileDescription, a.ContentType ?? "application/x-gzip", bin.Content)); } else if (a is DiagnosticTextAttachment txt) { return(new NotificationAttachment(a.FileName ?? a.FileDescription, a.ContentType ?? "text/plain", txt.Content)); } else { return(new NotificationAttachment(a.FileName ?? a.FileDescription, a.ContentType ?? "text/plain", $"Unknown attachment - {a}")); } }).ToList(); // Attach the application information using (var ms = new MemoryStream()) { XmlSerializer xsz = XmlModelSerializerFactory.Current.CreateSerializer(typeof(DiagnosticApplicationInfo)); xsz.Serialize(ms, storageData.ApplicationInfo); attachments.Add(new NotificationAttachment("appinfo.xml", "text/xml", ms.ToArray())); } var notificationService = ApplicationServiceContext.Current.GetService <INotificationService>(); var recipients = this.m_configuration?.Recipients.Select(o => o.StartsWith("mailto:") ? o : $"mailto:{o}").ToArray(); notificationService?.Send(recipients, subject, body, null, true, attachments.ToArray()); // Invoke this.Inserted?.Invoke(this, new DataPersistedEventArgs <DiagnosticReport>(storageData, mode, overrideAuthContext)); storageData.CorrelationId = issueId; storageData.Key = Guid.NewGuid(); return(storageData); } catch (Exception ex) { this.m_traceSource.TraceEvent(EventLevel.Error, "Error sending to E-Mail: {0}", ex); throw new InvalidOperationException("Error sending diagnostic reports to administrative contacts", ex); } }
/// <summary> /// Remove the subscription /// </summary> public PubSubSubscriptionDefinition RemoveSubscription(Guid key) { this.m_policyEnforcementService.Demand(PermissionPolicyIdentifiers.DeletePubSubSubscription); var subscription = this.GetSubscription(key); if (subscription == null) { throw new KeyNotFoundException($"Subscription {key} not found"); } var preEvt = new DataPersistingEventArgs <PubSubSubscriptionDefinition>(subscription, TransactionMode.Commit, AuthenticationContext.Current.Principal); this.UnSubscribing?.Invoke(this, preEvt); if (preEvt.Cancel) { this.m_tracer.TraceWarning("Pre-Event Hook for UnSubscribing issued cancel"); return(preEvt.Data); } // Obsolete using (var conn = this.m_configuration.Provider.GetWriteConnection()) { try { conn.Open(); var dbExisting = conn.FirstOrDefault <DbSubscription>(o => o.Key == key); if (dbExisting == null) { throw new KeyNotFoundException($"Subscription {key} not found"); } // Get the authorship var se = this.m_securityRepository.GetSecurityEntity(AuthenticationContext.Current.Principal); if (se == null) { throw new KeyNotFoundException($"Unable to determine structure data for {AuthenticationContext.Current.Principal.Identity.Name}"); } subscription.ObsoletedByKey = dbExisting.ObsoletedByKey = se.Key.Value; subscription.ObsoletionTime = dbExisting.ObsoletionTime = DateTimeOffset.Now; subscription.IsActive = false; conn.Update(dbExisting); this.m_cache.Remove(key); var retVal = this.MapInstance(conn, dbExisting); this.UnSubscribed?.Invoke(this, new DataPersistedEventArgs <PubSubSubscriptionDefinition>(retVal, TransactionMode.Commit, AuthenticationContext.Current.Principal)); return(retVal); } catch (Exception e) { throw new Exception($"Error obsoleting subscription {key}", e); } } }
/// <summary> /// Save the specified entity (insert or update) /// </summary> public virtual TEntity Save(TEntity data) { // Demand permission this.DemandAlter(data); var persistenceService = ApplicationServiceContext.Current.GetService <IDataPersistenceService <TEntity> >(); if (persistenceService == null) { throw new InvalidOperationException($"Unable to locate {nameof(IDataPersistenceService<TEntity>)}"); } data = this.Validate(data); var businessRulesService = ApplicationServiceContext.Current.GetBusinessRulesService <TEntity>(); try { var preSave = new DataPersistingEventArgs <TEntity>(data, AuthenticationContext.Current.Principal); this.Saving?.Invoke(this, preSave); if (preSave.Cancel) { this.m_traceSource.TraceWarning("Persistence layer indicates pre-save cancel: {0}", data); return(preSave.Data); } else { data = preSave.Data; // Data may have been updated } if (data.Key.HasValue && persistenceService.Get(data.Key.Value, null, true, AuthenticationContext.Current.Principal) != null) { data = businessRulesService?.BeforeUpdate(data) ?? data; data = persistenceService.Update(data, TransactionMode.Commit, AuthenticationContext.Current.Principal); businessRulesService?.AfterUpdate(data); } else { data = businessRulesService?.BeforeInsert(data) ?? data; data = persistenceService.Insert(data, TransactionMode.Commit, AuthenticationContext.Current.Principal); businessRulesService?.AfterInsert(data); } this.Saved?.Invoke(this, new DataPersistedEventArgs <TEntity>(data, AuthenticationContext.Current.Principal)); return(data); } catch (KeyNotFoundException) { return(this.Insert(data)); } }
/// <summary> /// Obsolete the specified data /// </summary> public virtual TEntity Obsolete(Guid key) { // Demand permission this.DemandDelete(key); var persistenceService = ApplicationServiceContext.Current.GetService <IDataPersistenceService <TEntity> >(); if (persistenceService == null) { throw new InvalidOperationException(this.m_localizationService.FormatString("error.server.core.servicePersistence", new { param = nameof(IDataPersistenceService <TEntity>) })); } var entity = persistenceService.Get(key, null, true, AuthenticationContext.Current.Principal); if (entity == null) { throw new KeyNotFoundException(this.m_localizationService.FormatString("error.type.KeyNotFoundException.notFound", new { param = $"Entity {key}" })); } // Fire pre-persistence triggers var prePersistence = new DataPersistingEventArgs <TEntity>(entity, TransactionMode.Commit, AuthenticationContext.Current.Principal); this.Obsoleting?.Invoke(this, prePersistence); if (prePersistence.Cancel) { this.m_traceSource.TraceInfo("Pre-persistence event signal cancel obsolete: {0}", key); // Fired inserted trigger if (prePersistence.Success) { this.Obsoleted?.Invoke(this, new DataPersistedEventArgs <TEntity>(prePersistence.Data, TransactionMode.Commit, AuthenticationContext.Current.Principal)); } return(this.m_privacyService?.Apply(prePersistence.Data, AuthenticationContext.Current.Principal) ?? prePersistence.Data); } var businessRulesService = ApplicationServiceContext.Current.GetBusinessRulesService <TEntity>(); entity = businessRulesService?.BeforeObsolete(entity) ?? entity; entity = persistenceService.Obsolete(entity, TransactionMode.Commit, AuthenticationContext.Current.Principal); entity = businessRulesService?.AfterObsolete(entity) ?? entity; this.Obsoleted?.Invoke(this, new DataPersistedEventArgs <TEntity>(entity, TransactionMode.Commit, AuthenticationContext.Current.Principal)); return(this.m_privacyService?.Apply(entity, AuthenticationContext.Current.Principal) ?? entity); }
/// <summary> /// Obsolete the specified data /// </summary> public virtual TEntity Obsolete(Guid key) { // Demand permission this.DemandDelete(key); var persistenceService = ApplicationContext.Current.GetService <IDataPersistenceService <TEntity> >(); if (persistenceService == null) { throw new InvalidOperationException($"Unable to locate {nameof(IDataPersistenceService<TEntity>)}"); } var entity = persistenceService.Get(key, null, false, AuthenticationContext.SystemPrincipal); if (entity == null) { throw new KeyNotFoundException($"Entity {key} not found"); } var preEvent = new DataPersistingEventArgs <TEntity>(entity, TransactionMode.Commit, AuthenticationContext.Current.Principal); this.Obsoleting?.Invoke(this, preEvent); if (preEvent.Cancel) { this.m_traceSource.TraceWarning("Pre-persistence event indicates cancel"); return(preEvent.Data); } entity = preEvent.Data; var businessRulesService = ApplicationContext.Current.GetService <IBusinessRulesService <TEntity> >(); entity = businessRulesService?.BeforeObsolete(entity) ?? entity; entity = persistenceService.Obsolete(entity, TransactionMode.Commit, AuthenticationContext.Current.Principal); ApplicationContext.Current.GetService <IQueueManagerService>().Outbound.Enqueue(entity, SynchronizationOperationType.Obsolete); entity = businessRulesService?.AfterObsolete(entity) ?? entity; this.Obsoleted?.Invoke(this, new DataPersistedEventArgs <TEntity>(entity, TransactionMode.Commit, AuthenticationContext.Current.Principal)); return(entity); }
/// <summary> /// Obsolete the specified data /// </summary> public virtual TEntity Obsolete(Guid key) { // Demand permission this.DemandDelete(key); var persistenceService = ApplicationServiceContext.Current.GetService <IDataPersistenceService <TEntity> >(); if (persistenceService == null) { throw new InvalidOperationException($"Unable to locate {nameof(IDataPersistenceService<TEntity>)}"); } var entity = persistenceService.Get(key, null, true, AuthenticationContext.Current.Principal); if (entity == null) { throw new KeyNotFoundException($"Entity {key} not found"); } // Fire pre-persistence triggers var prePersistence = new DataPersistingEventArgs <TEntity>(entity, AuthenticationContext.Current.Principal); this.Obsoleting?.Invoke(this, prePersistence); if (prePersistence.Cancel) { this.m_traceSource.TraceWarning("Pre-persistence event signal cancel obsolete: {0}", key); return(prePersistence.Data); } var businessRulesService = ApplicationServiceContext.Current.GetBusinessRulesService <TEntity>(); entity = businessRulesService?.BeforeObsolete(entity) ?? entity; entity = persistenceService.Obsolete(entity, TransactionMode.Commit, AuthenticationContext.Current.Principal); entity = businessRulesService?.AfterObsolete(entity) ?? entity; this.Obsoleted?.Invoke(this, new DataPersistedEventArgs <TEntity>(entity, AuthenticationContext.Current.Principal)); return(entity); }
/// <summary> /// Chain invoke a bundle on inserted /// </summary> protected void OnInserting(object sender, DataPersistingEventArgs <Bundle> e) { e.Data = this.ChainInvoke(sender, e, e.Data, nameof(OnInserting), typeof(DataPersistingEventArgs <>)); }
/// <summary> /// As a bundle, we call the base on the contents of the data /// </summary> protected void OnPrePersistenceValidate(object sender, DataPersistingEventArgs <Bundle> e) { e.Data = this.ChainInvoke(sender, e, e.Data, nameof(OnPrePersistenceValidate), typeof(DataPersistingEventArgs <>)); }
/// <summary> /// Obsolete the specified identified data /// </summary> /// <param name="data">Data.</param> public virtual TData Obsolete(TData data, TransactionMode mode, IPrincipal principal) { if (data == null) { throw new ArgumentNullException(nameof(data)); } else if (!data.Key.HasValue || data.Key == Guid.Empty) { throw new InvalidOperationException("Data missing key"); } #if PERFMON Stopwatch sw = new Stopwatch(); sw.Start(); #endif DataPersistingEventArgs <TData> preArgs = new DataPersistingEventArgs <TData>(data, mode, principal); this.Obsoleting?.Invoke(this, preArgs); if (preArgs.Cancel) { this.m_tracer.TraceWarning("Pre-Event handler indicates abort for {0}", data); return(data); } // Obsolete object using (var context = this.CreateConnection(principal)) try { using (context.LockConnection()) { try { this.m_tracer.TraceVerbose("OBSOLETE {0}", data); context.Connection.BeginTransaction(); data = this.Obsolete(context, data); if (mode == TransactionMode.Commit) { context.Connection.Commit(); } else { context.Connection.Rollback(); } // Remove from the cache foreach (var itm in context.CacheOnCommit.AsParallel()) { ApplicationContext.Current.GetService <IDataCachingService>().Remove(itm.Key.Value); } } catch (Exception e) { this.m_tracer.TraceError("Error : {0}", e); context.Connection.Rollback(); throw new LocalPersistenceException(SynchronizationOperationType.Obsolete, data, e); } } this.Obsoleted?.Invoke(this, new DataPersistedEventArgs <TData>(data, mode, principal)); return(data); } catch (SQLiteException e) { this.m_tracer.TraceError("Error obsoleting data {1} : {0}", e, context.Connection); throw new DataPersistenceException($"Database error obsoleting {data}", e); } catch (Exception e) { throw new DataPersistenceException($"Error obsoleting {data}", e); } #if PERFMON finally { sw.Stop(); ApplicationContext.Current.PerformanceLog(typeof(TData).Name, nameof(Obsolete), "Complete", sw.Elapsed); } #endif }
/// <summary> /// Insert the specified data. /// </summary> /// <param name="data">Data.</param> public virtual TData Insert(TData data, TransactionMode mode, IPrincipal principal) { if (data == null) { throw new ArgumentNullException(nameof(data)); } DataPersistingEventArgs <TData> preArgs = new DataPersistingEventArgs <TData>(data, mode, principal); this.Inserting?.Invoke(this, preArgs); if (preArgs.Cancel) { this.m_tracer.TraceWarning("Pre-Event handler indicates abort insert for {0}", data); return(data); } #if PERFMON Stopwatch sw = new Stopwatch(); sw.Start(); #endif // Persist objectel using (var context = this.CreateConnection(principal)) try { using (context.LockConnection()) { try { // Does this object already exist? if (data.Key.HasValue && this.Get(context, data.Key.Value) != null) { throw new DuplicateKeyException($"Object {typeof(TData).Name} with key {data.Key} already exists"); } this.m_tracer.TraceVerbose("INSERT {0}", data); context.Connection.BeginTransaction(); data = this.Insert(context, data); if (mode == TransactionMode.Commit) { context.Connection.Commit(); } else { context.Connection.Rollback(); } // Remove from the cache foreach (var itm in context.CacheOnCommit.AsParallel()) { ApplicationContext.Current.GetService <IDataCachingService>().Add(itm); } } catch (Exception e) { this.m_tracer.TraceError("Error : {0}", e); context.Connection.Rollback(); throw new LocalPersistenceException(SynchronizationOperationType.Insert, data, e); } } this.Inserted?.Invoke(this, new DataPersistedEventArgs <TData>(data, mode, principal)); return(data); } catch (SQLiteException e) { this.m_tracer.TraceError("Error inserting data {1} : {0}", e, context.Connection); throw new DataPersistenceException($"Database error inserting {data}", e); } catch (Exception e) { throw new DataPersistenceException($"Error inserting {data}", e); } #if PERFMON finally { sw.Stop(); ApplicationContext.Current.PerformanceLog(typeof(TData).Name, nameof(Insert), "Complete", sw.Elapsed); } #endif }
/// <summary> /// Fire inserting event /// </summary> protected void FireInserting(DataPersistingEventArgs <TData> evt) { this.Inserting?.Invoke(this, evt); }
/// <summary> /// Register a subscription for <paramref name="modelType"/> /// </summary> public PubSubSubscriptionDefinition RegisterSubscription(Type modelType, string name, string description, PubSubEventType events, string hdsiFilter, Guid channelId, String supportAddress = null, DateTimeOffset?notBefore = null, DateTimeOffset?notAfter = null) { this.m_policyEnforcementService.Demand(PermissionPolicyIdentifiers.CreatePubSubSubscription); var subscription = new PubSubSubscriptionDefinition() { ChannelKey = channelId, Event = events, Filter = String.IsNullOrEmpty(hdsiFilter) ? null : new List <string>(hdsiFilter.Split('&')), IsActive = false, Name = name, Description = description, SupportContact = supportAddress, NotBefore = notBefore?.DateTime, NotAfter = notAfter?.DateTime, ResourceTypeName = modelType.GetSerializationName() }; var preEvent = new DataPersistingEventArgs <PubSubSubscriptionDefinition>(subscription, TransactionMode.Commit, AuthenticationContext.Current.Principal); this.Subscribing?.Invoke(this, preEvent); if (preEvent.Cancel) { this.m_tracer.TraceWarning("Pre-Event Hook Indicates Cancel"); return(preEvent.Data); } using (var conn = this.m_configuration.Provider.GetWriteConnection()) { try { conn.Open(); using (var tx = conn.BeginTransaction()) { // First construct db instance var dbSubscription = this.m_mapper.MapModelInstance <PubSubSubscriptionDefinition, DbSubscription>(subscription); // Get the authorship var se = this.m_securityRepository.GetSecurityEntity(AuthenticationContext.Current.Principal); if (se == null) { throw new KeyNotFoundException($"Unable to determine structure data for {AuthenticationContext.Current.Principal.Identity.Name}"); } dbSubscription.CreatedByKey = se.Key.Value; dbSubscription.CreationTime = DateTimeOffset.Now; dbSubscription = conn.Insert(dbSubscription); // Insert settings if (subscription.Filter != null) { foreach (var itm in subscription.Filter) { conn.Insert(new DbSubscriptionFilter() { SubscriptionKey = dbSubscription.Key.Value, Filter = itm }); } } tx.Commit(); subscription = this.MapInstance(conn, dbSubscription); this.Subscribed?.Invoke(this, new DataPersistedEventArgs <PubSubSubscriptionDefinition>(subscription, TransactionMode.Commit, AuthenticationContext.Current.Principal)); this.m_cache?.Add(subscription); return(subscription); } } catch (Exception e) { throw new Exception($"Error inserting subscription {subscription}", e); } } }
/// <summary> /// Save the specified entity (insert or update) /// </summary> public virtual TEntity Save(TEntity data) { // Demand permission this.DemandAlter(data); var persistenceService = ApplicationContext.Current.GetService <IDataPersistenceService <TEntity> >(); if (persistenceService == null) { throw new InvalidOperationException($"Unable to locate {nameof(IDataPersistenceService<TEntity>)}"); } data = this.Validate(data); var businessRulesService = ApplicationContext.Current.GetService <IBusinessRulesService <TEntity> >(); try { var preEvent = new DataPersistingEventArgs <TEntity>(data, TransactionMode.Commit, AuthenticationContext.Current.Principal); this.Saving?.Invoke(this, preEvent); if (preEvent.Cancel) { this.m_traceSource.TraceWarning("Pre-persistence event indicates cancel"); return(preEvent.Data); } data = preEvent.Data; // We need to know what the old version looked like so we can patch it TEntity old = null; // Data key if (data.Key.HasValue) { old = persistenceService.Get(data.Key.Value, null, false, AuthenticationContext.SystemPrincipal) as TEntity; if (old is Entity) { old = (TEntity)(old as Entity)?.Copy(); } else if (old is Act) { old = (TEntity)(old as Act)?.Copy(); } } // HACK: Lookup by ER src<>trg if (old == null && typeof(TEntity) == typeof(EntityRelationship)) { var tr = 0; var erd = data as EntityRelationship; old = (TEntity)(persistenceService as IDataPersistenceService <EntityRelationship>).Query(o => o.SourceEntityKey == erd.SourceEntityKey && o.TargetEntityKey == erd.TargetEntityKey, 0, 1, out tr, AuthenticationContext.SystemPrincipal).OfType <EntityRelationship>().FirstOrDefault().Clone(); } // Old does not exist if (old == null) { data = businessRulesService?.BeforeInsert(data) ?? data; data = persistenceService.Insert(data, TransactionMode.Commit, AuthenticationContext.Current.Principal); ApplicationContext.Current.GetService <IQueueManagerService>()?.Outbound.Enqueue(data, SynchronizationOperationType.Insert); data = businessRulesService?.AfterInsert(data) ?? data; this.Saved?.Invoke(this, new DataPersistedEventArgs <TEntity>(data, TransactionMode.Commit, AuthenticationContext.Current.Principal)); } else { data = businessRulesService?.BeforeUpdate(data) ?? data; data = persistenceService.Update(data, TransactionMode.Commit, AuthenticationContext.Current.Principal); // Use patches if (ApplicationContext.Current.Configuration.GetSection <SynchronizationConfigurationSection>().UsePatches) { var diff = ApplicationContext.Current.GetService <IPatchService>()?.Diff(old, this.Get(data.Key.Value), "participation"); if (diff != null) { ApplicationContext.Current.GetService <IQueueManagerService>()?.Outbound.Enqueue(diff, SynchronizationOperationType.Update); } else { ApplicationContext.Current.GetService <IQueueManagerService>()?.Outbound.Enqueue(data, SynchronizationOperationType.Update); } } else { ApplicationContext.Current.GetService <IQueueManagerService>()?.Outbound.Enqueue(data, SynchronizationOperationType.Update); } data = businessRulesService?.AfterUpdate(data) ?? data; this.Saved?.Invoke(this, new DataPersistedEventArgs <TEntity>(data, TransactionMode.Commit, AuthenticationContext.Current.Principal)); } return(data); } catch (KeyNotFoundException) { data = businessRulesService?.BeforeInsert(data) ?? data; data = persistenceService.Insert(data, TransactionMode.Commit, AuthenticationContext.Current.Principal); ApplicationContext.Current.GetService <IQueueManagerService>()?.Outbound.Enqueue(data, SynchronizationOperationType.Insert); data = businessRulesService?.AfterInsert(data) ?? data; this.Saved?.Invoke(this, new DataPersistedEventArgs <TEntity>(data, TransactionMode.Commit, AuthenticationContext.Current.Principal)); return(data); } }
/// <summary> /// Obsoletes the specified object /// </summary> public TData Obsolete(TData data, TransactionMode mode, IPrincipal overrideAuthContext) { if (data == null) { throw new ArgumentNullException(nameof(data)); } else if (data.Key == Guid.Empty) { throw new InvalidOperationException("Data missing key"); } DataPersistingEventArgs <TData> preArgs = new DataPersistingEventArgs <TData>(data, mode, overrideAuthContext); this.Obsoleting?.Invoke(this, preArgs); if (preArgs.Cancel) { this.m_tracer.TraceEvent(EventLevel.Warning, "Pre-Event handler indicates abort for {0}", data); return(data); } // Obsolete object using (var connection = this.m_settingsProvider.GetConfiguration().Provider.GetWriteConnection()) { try { connection.Open(); using (IDbTransaction tx = connection.BeginTransaction()) try { //connection.Connection.Open(); this.m_tracer.TraceEvent(EventLevel.Verbose, "OBSOLETE {0}", data); connection.EstablishProvenance(overrideAuthContext, (data as BaseEntityData)?.ObsoletedByKey); data = this.Obsolete(connection, data); if (mode == TransactionMode.Commit) { tx.Commit(); var cacheService = ApplicationServiceContext.Current.GetService <IDataCachingService>(); cacheService?.Remove(data); } else { tx.Rollback(); } var args = new DataPersistedEventArgs <TData>(data, mode, overrideAuthContext); this.Obsoleted?.Invoke(this, args); return(data); } catch (Exception e) { this.m_tracer.TraceEvent(EventLevel.Error, "Error : {0}", e); tx?.Rollback(); throw new DataPersistenceException(e.Message, e); } finally { } } finally { } } }
/// <summary> /// Update the specified container /// </summary> /// <param name="data">The data to be updated</param> /// <param name="principal">The principal for authorization</param> /// <param name="mode">The mode of operation</param> /// <returns>The updated model</returns> public TModel Update(TModel data, TransactionMode mode, IPrincipal principal) { if (data == null) { throw new ArgumentNullException(nameof(data)); } else if (data.Key == Guid.Empty) { throw new InvalidOperationException("Data missing key"); } DataPersistingEventArgs <TModel> preArgs = new DataPersistingEventArgs <TModel>(data, mode, principal); this.Updating?.Invoke(this, preArgs); if (preArgs.Cancel) { this.m_tracer.TraceWarning("Pre-Event handler indicates abort update for {0}", data); return(data); } // Persist object using (var connection = AdoAuditPersistenceService.GetConfiguration().Provider.GetWriteConnection()) { connection.Open(); using (IDbTransaction tx = connection.BeginTransaction()) try { //connection.Connection.Open(); connection.EstablishProvenance(principal, (data as NonVersionedEntityData)?.UpdatedByKey ?? (data as BaseEntityData)?.CreatedByKey); this.m_tracer.TraceVerbose("UPDATE {0}", data); data = this.UpdateInternal(connection, data, principal); connection.AddCacheCommit(data); data.LoadState = LoadState.FullLoad; // We just persisted this so it is fully loaded if (mode == TransactionMode.Commit) { tx.Commit(); foreach (var itm in connection.CacheOnCommit) { ApplicationServiceContext.Current.GetService <IDataCachingService>()?.Add(itm); } } else { tx.Rollback(); } var args = new DataPersistedEventArgs <TModel>(data, mode, principal); this.Updated?.Invoke(this, args); return(data); } catch (DbException e) { #if DEBUG this.m_tracer.TraceError("Error : {0} -- {1}", e, this.ObjectToString(data)); #else this.m_tracer.TraceError("Error : {0}", e.Message); #endif tx?.Rollback(); this.TranslateDbException(e); throw; } catch (Exception e) { #if DEBUG this.m_tracer.TraceError("Error : {0} -- {1}", e, this.ObjectToString(data)); #else this.m_tracer.TraceError("Error : {0}", e.Message); #endif tx?.Rollback(); // if the exception is key not found, we want the caller to know // so that a potential insert can take place if (e is KeyNotFoundException) { throw new KeyNotFoundException(e.Message, e); } // if the exception is anything else, we want to throw a data persistence exception throw new DataPersistenceException(e.Message, e); } finally { } } }
/// <summary> /// Save the specified entity (insert or update) /// </summary> public virtual TEntity Save(TEntity data) { // Demand permission this.DemandAlter(data); var persistenceService = ApplicationServiceContext.Current.GetService <IDataPersistenceService <TEntity> >(); if (persistenceService == null) { throw new InvalidOperationException(this.m_localizationService.FormatString("error.server.core.servicePersistence", new { param = nameof(IDataPersistenceService <TEntity>) })); } data = this.Validate(data); var businessRulesService = ApplicationServiceContext.Current.GetBusinessRulesService <TEntity>(); try { if (this.m_privacyService?.ValidateWrite(data, AuthenticationContext.Current.Principal) == false) { this.ThrowPrivacyValidationException(data); } var preSave = new DataPersistingEventArgs <TEntity>(data, TransactionMode.Commit, AuthenticationContext.Current.Principal); this.Saving?.Invoke(this, preSave); if (preSave.Cancel) { this.m_traceSource.TraceInfo("Persistence layer indicates pre-save cancel: {0}", data); // Fired inserted trigger if (preSave.Success) { this.Saved?.Invoke(this, new DataPersistedEventArgs <TEntity>(preSave.Data, TransactionMode.Commit, AuthenticationContext.Current.Principal)); } return(this.m_privacyService?.Apply(preSave.Data, AuthenticationContext.Current.Principal) ?? preSave.Data); } else { data = preSave.Data; // Data may have been updated } if (data.Key.HasValue && persistenceService.Get(data.Key.Value, null, true, AuthenticationContext.Current.Principal) != null) { data = businessRulesService?.BeforeUpdate(data) ?? data; data = persistenceService.Update(data, TransactionMode.Commit, AuthenticationContext.Current.Principal); businessRulesService?.AfterUpdate(data); } else { data = businessRulesService?.BeforeInsert(data) ?? data; data = persistenceService.Insert(data, TransactionMode.Commit, AuthenticationContext.Current.Principal); businessRulesService?.AfterInsert(data); } this.Saved?.Invoke(this, new DataPersistedEventArgs <TEntity>(data, TransactionMode.Commit, AuthenticationContext.Current.Principal)); return(this.m_privacyService?.Apply(data, AuthenticationContext.Current.Principal) ?? data); } catch (KeyNotFoundException) { return(this.Insert(data)); } }
/// <summary> /// Activates or de-activates <paramref name="key"/> /// </summary> public PubSubSubscriptionDefinition ActivateSubscription(Guid key, bool isActive) { this.m_policyEnforcementService.Demand(PermissionPolicyIdentifiers.EnablePubSubSubscription); // perform activation using (var conn = this.m_configuration.Provider.GetWriteConnection()) { try { conn.Open(); var dbExisting = conn.FirstOrDefault <DbSubscription>(o => o.Key == key); if (dbExisting == null) { throw new KeyNotFoundException($"Subscription {key} not found"); } var subscription = this.MapInstance(conn, dbExisting); var preEvt = new DataPersistingEventArgs <PubSubSubscriptionDefinition>(subscription, TransactionMode.Commit, AuthenticationContext.Current.Principal); if (isActive) { this.Activating?.Invoke(this, preEvt); } else { this.DeActivating?.Invoke(this, preEvt); } if (preEvt.Cancel) { this.m_tracer.TraceWarning("Pre-Event Hook for Activation issued cancel"); return(preEvt.Data); } var se = this.m_securityRepository.GetSecurityEntity(AuthenticationContext.Current.Principal); if (se == null) { throw new SecurityException($"Cannot determine SID for {AuthenticationContext.Current.Principal.Identity.Name}"); } dbExisting.IsActive = isActive; subscription.IsActive = isActive; subscription.UpdatedByKey = dbExisting.UpdatedByKey = se.Key.Value; subscription.UpdatedTime = dbExisting.UpdatedTime = DateTimeOffset.Now; dbExisting.ObsoletionTime = null; dbExisting.ObsoletedByKey = null; dbExisting.ObsoletedBySpecified = dbExisting.ObsoletionTimeSpecified = true; conn.Update(dbExisting); this.m_cache.Remove(key); if (isActive) { this.Activated?.Invoke(this, new DataPersistedEventArgs <PubSubSubscriptionDefinition>(subscription, TransactionMode.Commit, AuthenticationContext.Current.Principal)); } else { this.DeActivated?.Invoke(this, new DataPersistedEventArgs <PubSubSubscriptionDefinition>(subscription, TransactionMode.Commit, AuthenticationContext.Current.Principal)); } return(subscription); } catch (Exception e) { throw new Exception($"Error obsoleting subscription {key}", e); } } }
/// <summary> /// Insert the specified audit into the database /// </summary> public AuditData Insert(AuditData storageData, TransactionMode mode, IPrincipal overrideAuthContext = null) { // Pre-event trigger var preEvtData = new DataPersistingEventArgs <AuditData>(storageData, mode, overrideAuthContext); this.Inserting?.Invoke(this, preEvtData); if (preEvtData.Cancel) { this.m_traceSource.TraceEvent(EventLevel.Warning, "Pre-Event handler indicates abort insert {0}", storageData); return(storageData); } // Insert using (var context = this.m_configuration.Provider.GetWriteConnection()) { IDbTransaction tx = null; try { context.Open(); tx = context.BeginTransaction(); // Insert core var dbAudit = this.m_mapper.MapModelInstance <AuditData, DbAuditData>(storageData); var eventId = storageData.EventTypeCode; if (eventId != null) { dbAudit.EventTypeCode = this.GetOrCreateAuditCode(context, eventId).Key; } dbAudit.CreationTime = DateTimeOffset.Now; storageData.Key = Guid.NewGuid(); dbAudit.Key = storageData.Key.Value; context.Insert(dbAudit); // Insert secondary properties if (storageData.Actors != null) { foreach (var act in storageData.Actors) { var roleCode = this.GetOrCreateAuditCode(context, act.ActorRoleCode.FirstOrDefault()); DbAuditActor dbAct = null; if (roleCode != null) { dbAct = context.FirstOrDefault <DbAuditActor>(o => o.UserName == act.UserName && o.ActorRoleCode == roleCode.Key); } else { dbAct = context.FirstOrDefault <DbAuditActor>(o => o.UserName == act.UserName && o.ActorRoleCode == Guid.Empty); } if (dbAct == null) { dbAct = this.m_mapper.MapModelInstance <AuditActorData, DbAuditActor>(act); dbAct.ActorRoleCode = roleCode?.Key ?? Guid.Empty; dbAct = context.Insert(dbAct); } context.Insert(new DbAuditActorAssociation() { TargetKey = dbAct.Key, SourceKey = dbAudit.Key, UserIsRequestor = act.UserIsRequestor, AccessPoint = act.NetworkAccessPointId }); } } // Audit objects if (storageData.AuditableObjects != null) { foreach (var ao in storageData.AuditableObjects) { var dbAo = this.m_mapper.MapModelInstance <AuditableObject, DbAuditObject>(ao); dbAo.IDTypeCode = (int)(ao.IDTypeCode ?? 0); dbAo.LifecycleType = (int)(ao.LifecycleType ?? 0); dbAo.Role = (int)(ao.Role ?? 0); dbAo.Type = (int)(ao.Type); dbAo.AuditId = dbAudit.Key; if (ao.CustomIdTypeCode != null) { var code = this.GetOrCreateAuditCode(context, ao.CustomIdTypeCode); dbAo.CustomIdType = code.Key; } dbAo = context.Insert(dbAo); if (ao.ObjectData?.Count > 0) { foreach (var od in ao.ObjectData) { context.Insert(new DbAuditObjectData() { Name = od.Key, Value = od.Value, ObjectId = dbAo.Key }); } } } } // metadata if (storageData.Metadata != null) { foreach (var meta in storageData.Metadata.Where(o => !String.IsNullOrEmpty(o.Value) && o.Key != AuditMetadataKey.CorrelationToken)) { var kv = context.FirstOrDefault <DbAuditMetadataValue>(o => o.Value == meta.Value); if (kv == null) { kv = context.Insert(new DbAuditMetadataValue() { // TODO: Make this a common extension function (to trim) Value = meta.Value.Substring(0, meta.Value.Length > 256 ? 256 : meta.Value.Length) }); } context.Insert(new DbAuditMetadata() { AuditId = dbAudit.Key, MetadataKey = (int)meta.Key, ValueId = kv.Key }); } } if (mode == TransactionMode.Commit) { tx.Commit(); } else { tx.Rollback(); } var args = new DataPersistedEventArgs <AuditData>(storageData, mode, overrideAuthContext); this.Inserted?.Invoke(this, args); return(storageData); } catch (Exception ex) { tx?.Rollback(); throw new Exception($"Error inserting audit {storageData.Key}", ex); } } }
/// <summary> /// Insert the specified audit into the database /// </summary> public AuditData Insert(AuditData storageData, TransactionMode mode, IPrincipal overrideAuthContext = null) { // Pre-event trigger var preEvtData = new DataPersistingEventArgs <AuditData>(storageData, overrideAuthContext); this.Inserting?.Invoke(this, preEvtData); if (preEvtData.Cancel) { this.m_traceSource.TraceEvent(EventLevel.Warning, "Pre-Event handler indicates abort insert {0}", storageData); return(storageData); } // Insert using (var context = this.m_configuration.Provider.GetWriteConnection()) { IDbTransaction tx = null; try { context.Open(); tx = context.BeginTransaction(); // Insert core var dbAudit = this.m_mapper.MapModelInstance <AuditData, DbAuditData>(storageData); var eventId = storageData.EventTypeCode; if (eventId != null) { var existing = context.FirstOrDefault <DbAuditCode>(o => o.Code == eventId.Code && o.CodeSystem == eventId.CodeSystem); if (existing == null) { Guid codeId = Guid.NewGuid(); dbAudit.EventTypeCode = codeId; context.Insert(new DbAuditCode() { Code = eventId.Code, CodeSystem = eventId.CodeSystem, Key = codeId }); } else { dbAudit.EventTypeCode = existing.Key; } } dbAudit.CreationTime = DateTime.Now; storageData.Key = Guid.NewGuid(); dbAudit.Key = storageData.Key.Value; context.Insert(dbAudit); // Insert secondary properties if (storageData.Actors != null) { foreach (var act in storageData.Actors) { var dbAct = context.FirstOrDefault <DbAuditActor>(o => o.UserName == act.UserName); if (dbAct == null) { dbAct = this.m_mapper.MapModelInstance <AuditActorData, DbAuditActor>(act); dbAct.Key = Guid.NewGuid(); var roleCode = act.ActorRoleCode?.FirstOrDefault(); if (roleCode != null) { var existing = context.FirstOrDefault <DbAuditCode>(o => o.Code == roleCode.Code && o.CodeSystem == roleCode.CodeSystem); if (existing == null) { dbAct.ActorRoleCode = Guid.NewGuid(); context.Insert(new DbAuditCode() { Code = roleCode.Code, CodeSystem = roleCode.CodeSystem, Key = dbAct.ActorRoleCode }); } else { dbAct.ActorRoleCode = existing.Key; } } context.Insert(dbAct); } context.Insert(new DbAuditActorAssociation() { TargetKey = dbAct.Key, SourceKey = dbAudit.Key, UserIsRequestor = act.UserIsRequestor, AccessPoint = act.NetworkAccessPointId, Key = Guid.NewGuid() }); } } // Audit objects if (storageData.AuditableObjects != null) { foreach (var ao in storageData.AuditableObjects) { var dbAo = this.m_mapper.MapModelInstance <AuditableObject, DbAuditObject>(ao); dbAo.IDTypeCode = (int)(ao.IDTypeCode ?? 0); dbAo.LifecycleType = (int)(ao.LifecycleType ?? 0); dbAo.Role = (int)(ao.Role ?? 0); dbAo.Type = (int)(ao.Type); dbAo.AuditId = dbAudit.Key; dbAo.Key = Guid.NewGuid(); context.Insert(dbAo); } } // metadata if (storageData.Metadata != null) { foreach (var meta in storageData.Metadata.Where(o => !String.IsNullOrEmpty(o.Value))) { context.Insert(new DbAuditMetadata() { AuditId = dbAudit.Key, MetadataKey = (int)meta.Key, Value = meta.Value }); } } if (mode == TransactionMode.Commit) { tx.Commit(); } else { tx.Rollback(); } var args = new DataPersistedEventArgs <AuditData>(storageData, overrideAuthContext); this.Inserted?.Invoke(this, args); return(storageData); } catch (Exception ex) { tx?.Rollback(); throw new Exception($"Error inserting audit {storageData.Key}", ex); } } }
/// <summary> /// Represents when the ADT registration occurs /// </summary> protected void AdtPatientRegistrationInterceptor_Behavior(object sender, DataPersistingEventArgs <Patient> e) { AuthenticationContext.Current = new AuthenticationContext(AuthenticationContext.SystemPrincipal); e.Cancel = true; Patient pat = e.Data; // Perform notification IMessage notificationMessage; IGroup patientGroup; if (pat.PreviousVersionKey == null) { // Set the tag value and send an ADMIT patientGroup = notificationMessage = new ADT_A01(); (notificationMessage.GetStructure("MSH") as MSH).MessageType.TriggerEvent.Value = "A04"; (notificationMessage.GetStructure("MSH") as MSH).MessageType.MessageStructure.Value = "ADT_A01"; } else if (pat.Relationships.Any(o => o.RelationshipTypeKey == EntityRelationshipTypeKeys.Replaces && o.EffectiveVersionSequenceId == pat.VersionSequence)) { // Set the tag value and send an ADMIT notificationMessage = new ADT_A39(); patientGroup = (notificationMessage as ADT_A39).GetPATIENT(); (notificationMessage.GetStructure("MSH") as MSH).MessageType.TriggerEvent.Value = "A40"; (notificationMessage.GetStructure("MSH") as MSH).MessageType.MessageStructure.Value = "ADT_A40"; foreach (var mrg in pat.Relationships.Where(o => o.RelationshipTypeKey == EntityRelationshipTypeKeys.Replaces && o.EffectiveVersionSequenceId == pat.VersionSequence)) { var seg = patientGroup.GetStructure("MRG", patientGroup.GetAll("MRG").Length) as MRG; if (this.Configuration.ExportDomains.Any(o => o.DomainName == this.m_configuration.LocalAuthority.DomainName)) { var key = seg.PriorAlternatePatientIDRepetitionsUsed; seg.GetPriorAlternatePatientID(key).IDNumber.Value = mrg.TargetEntityKey.Value.ToString(); seg.GetPriorAlternatePatientID(key).IdentifierTypeCode.Value = "PI"; seg.GetPriorAlternatePatientID(key).AssigningAuthority.NamespaceID.Value = this.m_configuration.LocalAuthority.DomainName; seg.GetPriorAlternatePatientID(key).AssigningAuthority.UniversalID.Value = this.m_configuration.LocalAuthority.Oid; seg.GetPriorAlternatePatientID(key).AssigningAuthority.UniversalIDType.Value = "ISO"; } // Alternate identifiers foreach (var extrn in pat.Identifiers) { var key = seg.PriorAlternatePatientIDRepetitionsUsed; if (this.Configuration.ExportDomains.Any(o => o.DomainName == extrn.LoadProperty <AssigningAuthority>("Authority").DomainName)) { seg.GetPriorAlternatePatientID(key).IDNumber.Value = extrn.Value; seg.GetPriorAlternatePatientID(key).IdentifierTypeCode.Value = "PT"; seg.GetPriorAlternatePatientID(key).AssigningAuthority.NamespaceID.Value = extrn.LoadProperty <AssigningAuthority>("Authority")?.DomainName; seg.GetPriorAlternatePatientID(key).AssigningAuthority.UniversalID.Value = extrn.LoadProperty <AssigningAuthority>("Authority")?.Oid; seg.GetPriorAlternatePatientID(key).AssigningAuthority.UniversalIDType.Value = "ISO"; } } } } else { // Set the tag value and send an ADMIT patientGroup = notificationMessage = new ADT_A01(); (notificationMessage.GetStructure("MSH") as MSH).MessageType.TriggerEvent.Value = "A08"; (notificationMessage.GetStructure("MSH") as MSH).MessageType.MessageStructure.Value = "ADT_A08"; } if (!String.IsNullOrEmpty(this.Configuration.Version)) { (notificationMessage.GetStructure("MSH") as MSH).VersionID.VersionID.Value = this.Configuration.Version; } // Add SFT if (new Version(this.Configuration.Version ?? "2.5") >= new Version(2, 4)) { (notificationMessage.GetStructure("SFT", 0) as SFT).SetDefault(); } // Create the PID segment SegmentHandlers.GetSegmentHandler("PID").Create(e.Data, patientGroup, this.Configuration.ExportDomains.ToArray()); SegmentHandlers.GetSegmentHandler("PD1").Create(e.Data, patientGroup, this.Configuration.ExportDomains.ToArray()); SegmentHandlers.GetSegmentHandler("NK1").Create(e.Data, patientGroup, this.Configuration.ExportDomains.ToArray()); //SegmentHandlers.GetSegmentHandler("EVN").Create(e.Data, patientGroup, this.Configuration.ExportDomains.ToArray()); foreach (var itm in this.Configuration.Endpoints) { try { // TODO: Create an HL7 Queue (notificationMessage.GetStructure("MSH") as MSH).SetDefault(itm.ReceivingDevice, itm.ReceivingFacility, itm.SecurityToken); var response = itm.GetSender().SendAndReceive(notificationMessage); if (!(response.GetStructure("MSA") as MSA).AcknowledgmentCode.Value.EndsWith("A")) { throw new HL7Exception("Remote server rejected message"); } } catch (Exception ex) { this.m_tracer.TraceEvent(EventLevel.Error, "Error dispatching message {0} to {1}: {2} \r\n {3}", pat, itm.Address, ex, new PipeParser().Encode(notificationMessage)); } } }
/// <summary> /// Inserts the specified data /// </summary> public TData Insert(TData data, TransactionMode mode, IPrincipal overrideAuthContext) { if (data == null) { throw new ArgumentNullException(nameof(data)); } DataPersistingEventArgs <TData> preArgs = new DataPersistingEventArgs <TData>(data, mode, overrideAuthContext); this.Inserting?.Invoke(this, preArgs); if (preArgs.Cancel) { this.m_tracer.TraceEvent(EventLevel.Warning, "Pre-Event handler indicates abort insert for {0}", data); return(data); } // Persist object using (var connection = this.m_settingsProvider.GetConfiguration().Provider.GetWriteConnection()) { try { connection.Open(); using (IDbTransaction tx = connection.BeginTransaction()) try { // Disable inserting duplicate classified objects connection.EstablishProvenance(overrideAuthContext, (data as BaseEntityData)?.CreatedByKey); var existing = data.TryGetExisting(connection, true); if (existing != null) { if (this.m_settingsProvider.GetConfiguration().AutoUpdateExisting) { this.m_tracer.TraceEvent(EventLevel.Warning, "INSERT WOULD RESULT IN DUPLICATE CLASSIFIER: UPDATING INSTEAD {0}", data); data.Key = existing.Key; data = this.Update(connection, data); } else { throw new DuplicateNameException(data.Key?.ToString()); } } else { this.m_tracer.TraceEvent(EventLevel.Verbose, "INSERT {0}", data); data = this.Insert(connection, data); } data.LoadState = LoadState.FullLoad; // We just persisted so it is fully loaded if (mode == TransactionMode.Commit) { tx.Commit(); var cacheService = ApplicationServiceContext.Current.GetService <IDataCachingService>(); cacheService?.Add(data); } else { tx.Rollback(); } var args = new DataPersistedEventArgs <TData>(data, mode, overrideAuthContext); this.Inserted?.Invoke(this, args); return(data); } catch (DbException e) { #if DEBUG this.m_tracer.TraceEvent(EventLevel.Error, "Error : {0} -- {1}", e, this.ObjectToString(data)); #else this.m_tracer.TraceEvent(EventLevel.Error, "Error : {0}", e.Message); #endif tx?.Rollback(); throw new DataPersistenceException($"Error inserting {data}", this.TranslateDbException(e)); } catch (DataPersistenceException) { throw; } catch (Exception e) { this.m_tracer.TraceEvent(EventLevel.Error, "Error : {0} -- {1}", e, this.ObjectToString(data)); tx?.Rollback(); throw new DataPersistenceException(e.Message, e); } finally { } } finally { } } }
public DiagnosticReport Insert(DiagnosticReport storageData, TransactionMode mode, IPrincipal overrideAuthContext = null) { var persistenceArgs = new DataPersistingEventArgs <DiagnosticReport>(storageData, mode, overrideAuthContext); this.Inserting?.Invoke(this, persistenceArgs); if (persistenceArgs.Cancel) { this.m_traceSource.TraceEvent(EventLevel.Warning, "Pre-persistence event cancelled the insertion"); return(persistenceArgs.Data); } try { // Send var serviceClient = new JiraServiceClient(new RestClient(this.m_configuration)); serviceClient.Authenticate(new Model.JiraAuthenticationRequest(this.m_configuration.UserName, this.m_configuration.Password)); var issue = serviceClient.CreateIssue(new Model.JiraIssueRequest() { Fields = new Model.JiraIssueFields() { Description = storageData.Note, Summary = String.Format("SanteDB-DIAG: Issue from {0}", storageData?.Submitter?.Names?.FirstOrDefault()?.Component?.FirstOrDefault(n => n.ComponentTypeKey == NameComponentKeys.Given)?.Value), IssueType = new Model.JiraIdentifier("Bug"), Priority = new Model.JiraIdentifier("High"), Project = new Model.JiraKey(this.m_configuration.Project), Labels = new string[] { "SanteDBMobile" } } }); serviceClient.Client.Requesting += (o, e) => { e.AdditionalHeaders.Add("X-Atlassian-Token", "nocheck"); }; // Attachments List <MultipartAttachment> attachments = new List <MultipartAttachment>(); foreach (var itm in storageData.Attachments) { if (itm is DiagnosticBinaryAttachment) { var bin = itm as DiagnosticBinaryAttachment; attachments.Add(new MultipartAttachment(bin.Content, "application/x-gzip", bin.FileDescription, true)); } else { var txt = itm as DiagnosticTextAttachment; attachments.Add(new MultipartAttachment(Encoding.UTF8.GetBytes(txt.Content), "text/plain", txt.FileName, true)); } } // Attach the application information using (var ms = new MemoryStream()) { XmlSerializer xsz = XmlModelSerializerFactory.Current.CreateSerializer(typeof(DiagnosticApplicationInfo)); xsz.Serialize(ms, storageData.ApplicationInfo); attachments.Add(new MultipartAttachment(ms.ToArray(), "text/xml", "appinfo.xml", true)); } serviceClient.CreateAttachment(issue, attachments); storageData.CorrelationId = issue.Key; storageData.Key = Guid.NewGuid(); // Invoke this.Inserted?.Invoke(this, new DataPersistedEventArgs <DiagnosticReport>(storageData, mode, overrideAuthContext)); return(storageData); } catch (Exception ex) { this.m_traceSource.TraceEvent(EventLevel.Error, "Error sending to JIRA: {0}", ex); throw; } }
/// <summary> /// Update the specified object /// </summary> /// <param name="storageData"></param> /// <param name="principal"></param> /// <param name="mode"></param> /// <returns></returns> public TData Update(TData data, TransactionMode mode, IPrincipal overrideAuthContext) { if (data == null) { throw new ArgumentNullException(nameof(data)); } else if (data.Key == Guid.Empty) { throw new InvalidOperationException("Data missing key"); } DataPersistingEventArgs <TData> preArgs = new DataPersistingEventArgs <TData>(data, mode, overrideAuthContext); this.Updating?.Invoke(this, preArgs); if (preArgs.Cancel) { this.m_tracer.TraceEvent(EventLevel.Warning, "Pre-Event handler indicates abort update for {0}", data); return(data); } // Persist object using (var connection = this.m_settingsProvider.GetConfiguration().Provider.GetWriteConnection()) { try { connection.Open(); using (IDbTransaction tx = connection.BeginTransaction()) try { //connection.Connection.Open(); this.m_tracer.TraceEvent(EventLevel.Verbose, "UPDATE {0}", data); connection.EstablishProvenance(overrideAuthContext, (data as NonVersionedEntityData)?.UpdatedByKey ?? (data as BaseEntityData)?.CreatedByKey); data = Update(connection, data); data.LoadState = LoadState.FullLoad; // We just persisted this so it is fully loaded if (mode == TransactionMode.Commit) { tx.Commit(); var cacheService = ApplicationServiceContext.Current.GetService <IDataCachingService>(); cacheService?.Remove(data); } else { tx.Rollback(); } var args = new DataPersistedEventArgs <TData>(data, mode, overrideAuthContext); this.Updated?.Invoke(this, args); return(data); } catch (DbException e) { #if DEBUG this.m_tracer.TraceEvent(EventLevel.Error, "Error : {0} -- {1}", e, this.ObjectToString(data)); #else this.m_tracer.TraceEvent(EventLevel.Error, "Error : {0}", e.Message); #endif tx?.Rollback(); throw new DataPersistenceException($"Error updating {data}", this.TranslateDbException(e)); } catch (Exception e) { #if DEBUG this.m_tracer.TraceEvent(EventLevel.Error, "Error : {0} -- {1}", e, this.ObjectToString(data)); #else this.m_tracer.TraceEvent(EventLevel.Error, "Error : {0}", e.Message); #endif tx?.Rollback(); // if the exception is key not found, we want the caller to know // so that a potential insert can take place if (e is KeyNotFoundException) { throw new KeyNotFoundException($"Record {data} was not found for update", e); } // if the exception is anything else, we want to throw a data persistence exception throw new DataPersistenceException($"Error updating {data}", e); } finally { } } finally { } } }
/// <summary> /// Obsolete the specified key data /// </summary> /// <param name="storageData">The storage data to be obsoleted</param> /// <param name="principal">The principal to use to obsolete</param> /// <param name="mode">The mode of obsoletion</param> /// <returns>The obsoleted record</returns> public TModel Obsolete(TModel data, TransactionMode mode, IPrincipal principal) { if (data == null) { throw new ArgumentNullException(nameof(data)); } else if (data.Key == Guid.Empty) { throw new InvalidOperationException("Data missing key"); } DataPersistingEventArgs <TModel> preArgs = new DataPersistingEventArgs <TModel>(data, mode, principal); this.Obsoleting?.Invoke(this, preArgs); if (preArgs.Cancel) { this.m_tracer.TraceWarning("Pre-Event handler indicates abort for {0}", data); return(data); } // Obsolete object using (var connection = AdoAuditPersistenceService.GetConfiguration().Provider.GetWriteConnection()) { connection.Open(); using (IDbTransaction tx = connection.BeginTransaction()) try { //connection.Connection.Open(); this.m_tracer.TraceVerbose("OBSOLETE {0}", data); connection.EstablishProvenance(principal, (data as NonVersionedEntityData)?.ObsoletedByKey ?? (data as BaseEntityData)?.ObsoletedByKey); data = this.ObsoleteInternal(connection, data, principal); connection.AddCacheCommit(data); if (mode == TransactionMode.Commit) { tx.Commit(); foreach (var itm in connection.CacheOnCommit) { ApplicationServiceContext.Current.GetService <IDataCachingService>()?.Remove(itm.Key.Value); } } else { tx.Rollback(); } var args = new DataPersistedEventArgs <TModel>(data, mode, principal); this.Obsoleted?.Invoke(this, args); return(data); } catch (Exception e) { this.m_tracer.TraceError("Error : {0}", e); tx?.Rollback(); throw new DataPersistenceException(e.Message, e); } finally { } } }