Exemple #1
0
        /// <summary>
        /// Persist the person relationship
        /// </summary>
        public SVC.Core.DataTypes.VersionedDomainIdentifier Persist(System.Data.IDbConnection conn, System.Data.IDbTransaction tx, System.ComponentModel.IComponent data, bool isUpdate)
        {
            // Is this a replacement
            var pp = new PersonPersister();
            PersonRegistrationRef refr = data as PersonRegistrationRef;
            Person psn     = pp.GetPerson(conn, tx, refr.AlternateIdentifiers[0], true);
            Person cntrPsn = data.Site.Container as Person;

            if (psn == null || cntrPsn == null)
            {
                throw new ConstraintException(ApplicationContext.LocaleService.GetString("DBCF00B"));
            }
            else if (psn.Id == cntrPsn.Id)
            {
                throw new ConstraintException(ApplicationContext.LocaleService.GetString("DBCF00D"));
            }

            // Load the container person from DB so we get all data
            Person dbCntrPsn = pp.GetPerson(conn, tx, new SVC.Core.DataTypes.DomainIdentifier()
            {
                Domain     = ApplicationContext.ConfigurationService.OidRegistrar.GetOid(ClientRegistryOids.CLIENT_CRID).Oid,
                Identifier = cntrPsn.Id.ToString()
            }, true);

            pp.MergePersons(dbCntrPsn, cntrPsn);

            // Load the components for the person
#if DEBUG
            Trace.TraceInformation("Registration reference {0} > {1}", psn.Id, dbCntrPsn.Id);
#endif
            DbUtil.DePersistComponents(conn, psn, this, true);

            if (psn == null || dbCntrPsn == null)
            {
                throw new ConstraintException(ApplicationContext.LocaleService.GetString("DBCF00B"));
            }
            dbCntrPsn.Site = (data.Site.Container as IComponent).Site;

            var role     = (refr.Site as HealthServiceRecordSite).SiteRoleType;
            var symbolic = (refr.Site as HealthServiceRecordSite).IsSymbolic; // If true, the replacement does not cascade and is a symbolic replacement of only the identifiers listed

            // Replacement?
            if (role == HealthServiceRecordSiteRoleType.ReplacementOf)
            {
                // First, we obsolete all records with the existing person
                foreach (var id in psn.AlternateIdentifiers.FindAll(o => refr.AlternateIdentifiers.Exists(a => a.Domain == o.Domain)))
                {
                    id.UpdateMode = SVC.Core.DataTypes.UpdateModeType.Remove;
                }
                //psn.AlternateIdentifiers.RemoveAll(o => o.UpdateMode != SVC.Core.DataTypes.UpdateModeType.Remove);

                // Not symbolic, means that we do a hard replace
                // Symbolic replace = Just replace the reference to that identifier
                // Hard replace = Merge the new and old record and then replace them
                if (!symbolic)
                {
#if DEBUG
                    Trace.TraceInformation("Performing an administrative migration of identifiers and information from {0} > {1}", psn.Id, dbCntrPsn.Id);
#endif
                    // Now to copy the components of the current version down
                    //foreach (IComponent cmp in refr.Site.Container.Components)
                    //    if (cmp != refr)
                    //        dbCntrPsn.Add((cmp as HealthServiceRecordComponent).Clone() as IComponent);

                    // Merge the two records in memory taking the newer data
                    // This is a merge from old to new in order to capture any data elements
                    // that have been updated in the old that might be newer (or more accurate) than the
                    // the new
                    if (psn.AlternateIdentifiers == null)
                    {
                        dbCntrPsn.AlternateIdentifiers = new List <SVC.Core.DataTypes.DomainIdentifier>();
                    }
                    else if (psn.OtherIdentifiers == null)
                    {
                        dbCntrPsn.OtherIdentifiers = new List <KeyValuePair <SVC.Core.DataTypes.CodeValue, SVC.Core.DataTypes.DomainIdentifier> >();
                    }
                    foreach (var id in psn.AlternateIdentifiers)
                    {
                        // Remove the identifier from the original
                        id.UpdateMode = SVC.Core.DataTypes.UpdateModeType.Remove;

                        // If this is a duplicate id then don't add
                        if (dbCntrPsn.AlternateIdentifiers.Exists(i => i.Domain == id.Domain && i.Identifier == id.Identifier))
                        {
                            continue;
                        }

                        bool isPrivate = false;
                        var  oidData   = ApplicationContext.ConfigurationService.OidRegistrar.FindData(id.Domain);
                        if (oidData != null)
                        {
                            isPrivate = !(oidData.Attributes.Exists(o => o.Key == "IsMergeSurvivor") && Convert.ToBoolean(oidData.Attributes.Find(o => o.Key == "IsMergeSurvivor").Value));
                        }

                        // Add to alternate identifiers
                        dbCntrPsn.AlternateIdentifiers.Add(new SVC.Core.DataTypes.DomainIdentifier()
                        {
                            AssigningAuthority = id.AssigningAuthority,
                            UpdateMode         = SVC.Core.DataTypes.UpdateModeType.AddOrUpdate,
                            IsLicenseAuthority = false,
                            IsPrivate          = isPrivate, // TODO: Make this a configuration flag (cntrPsn.AlternateIdentifiers.Exists(i=>i.Domain == id.Domain)),
                            Identifier         = id.Identifier,
                            Domain             = id.Domain
                        });
                    }
                    foreach (var id in psn.OtherIdentifiers)
                    {
                        // Remove the identifier from the original
                        id.Value.UpdateMode = SVC.Core.DataTypes.UpdateModeType.Remove;

                        // If this is a duplicate id then don't add
                        if (dbCntrPsn.OtherIdentifiers.Exists(i => i.Value.Domain == id.Value.Domain && i.Value.Identifier == id.Value.Identifier))
                        {
                            continue;
                        }

                        // Add to other identifiers
                        var oth = new KeyValuePair <SVC.Core.DataTypes.CodeValue, SVC.Core.DataTypes.DomainIdentifier>(
                            id.Key,
                            new SVC.Core.DataTypes.DomainIdentifier()
                        {
                            AssigningAuthority = id.Value.AssigningAuthority,
                            UpdateMode         = SVC.Core.DataTypes.UpdateModeType.Add,
                            IsLicenseAuthority = false,
                            IsPrivate          = (dbCntrPsn.OtherIdentifiers.Exists(i => i.Value.Domain == id.Value.Domain)),
                            Identifier         = id.Value.Identifier,
                            Domain             = id.Value.Domain
                        });

                        // Copy extensions
                        var extns = psn.FindAllExtensions(o => o.PropertyPath == String.Format("OtherIdentifiers[{0}{1}]", oth.Value.Domain, oth.Value.Identifier));
                        if (extns != null)
                        {
                            foreach (var ex in extns)
                            {
                                if (dbCntrPsn.FindExtension(o => o.PropertyPath == ex.PropertyPath && o.Name == ex.Name) == null)
                                {
                                    dbCntrPsn.Add(ex);
                                }
                            }
                        }
                        dbCntrPsn.OtherIdentifiers.Add(oth);
                    }



                    // Make sure we don't update what we don't need to
                    dbCntrPsn.Addresses        = psn.Addresses = null;
                    dbCntrPsn.Citizenship      = psn.Citizenship = null;
                    dbCntrPsn.Employment       = psn.Employment = null;
                    dbCntrPsn.Language         = psn.Language = null;
                    dbCntrPsn.Names            = psn.Names = null;
                    dbCntrPsn.Race             = psn.Race = null;
                    dbCntrPsn.TelecomAddresses = psn.TelecomAddresses = null;
                    dbCntrPsn.BirthTime        = psn.BirthTime = null;
                    dbCntrPsn.DeceasedTime     = psn.DeceasedTime = null;

                    // Remove the old person from the db
                    psn.Status = SVC.Core.ComponentModel.Components.StatusType.Obsolete; // obsolete the old person
                }
                else // migrate identifiers
                {
                    foreach (var id in refr.AlternateIdentifiers)
                    {
                        bool isPrivate = false;
                        var  oidData   = ApplicationContext.ConfigurationService.OidRegistrar.FindData(id.Domain);
                        if (oidData != null)
                        {
                            isPrivate = !(oidData.Attributes.Exists(o => o.Key == "IsMergeSurvivor") && Convert.ToBoolean(oidData.Attributes.Find(o => o.Key == "IsMergeSurvivor").Value));
                        }

                        dbCntrPsn.AlternateIdentifiers.Add(new SVC.Core.DataTypes.DomainIdentifier()
                        {
                            AssigningAuthority = id.AssigningAuthority,
                            UpdateMode         = SVC.Core.DataTypes.UpdateModeType.AddOrUpdate,
                            IsLicenseAuthority = false,
                            IsPrivate          = isPrivate, // TODO: Make this a configuration flag (cntrPsn.AlternateIdentifiers.Exists(i=>i.Domain == id.Domain)),
                            Identifier         = id.Identifier,
                            Domain             = id.Domain
                        });
                    }

                    // set to ignore
                    if (psn.Names != null)
                    {
                        foreach (var rc in psn.Names)
                        {
                            rc.UpdateMode = SVC.Core.DataTypes.UpdateModeType.Ignore;
                        }
                    }

                    // set to ignore
                    if (psn.Addresses != null)
                    {
                        foreach (var rc in psn.Addresses)
                        {
                            rc.UpdateMode = SVC.Core.DataTypes.UpdateModeType.Ignore;
                        }
                    }

                    // set to ignore
                    if (psn.Race != null)
                    {
                        foreach (var rc in psn.Race)
                        {
                            rc.UpdateMode = SVC.Core.DataTypes.UpdateModeType.Ignore;
                        }
                    }
                }
                // Now update the person
                //psn.Site = refr.Site;
                //pp.Persist(conn, tx, psn, true); // update the person record
#if DEBUG
                Trace.TraceInformation("Step 1 : Prepare update to person #{0}", psn.Id, cntrPsn.Id, !symbolic);
#endif
                var regEvent      = this.GetRegistrationEvent(conn, tx, psn); // get the registration event
                var changeSummary = DbUtil.GetRegistrationEvent(refr).FindComponent(HealthServiceRecordSiteRoleType.ReasonFor | HealthServiceRecordSiteRoleType.OlderVersionOf) as ChangeSummary;
                if (changeSummary != null)
                {
                    regEvent.RemoveAllFromRole(HealthServiceRecordSiteRoleType.ReasonFor | HealthServiceRecordSiteRoleType.OlderVersionOf);
                    regEvent.Add(new ChangeSummary()
                    {
                        ChangeType    = changeSummary.ChangeType,
                        EffectiveTime = changeSummary.EffectiveTime,
                        LanguageCode  = changeSummary.LanguageCode,
                        Status        = changeSummary.Status,
                        Timestamp     = changeSummary.Timestamp
                    }, "CHG", HealthServiceRecordSiteRoleType.ReasonFor | HealthServiceRecordSiteRoleType.OlderVersionOf, null);
                }
                if (!symbolic)
                {
                    regEvent.Status = StatusType.Obsolete; // obsolete
                }
                regEvent.RemoveAllFromRole(HealthServiceRecordSiteRoleType.SubjectOf);
                regEvent.Add(psn, "SUBJ", HealthServiceRecordSiteRoleType.SubjectOf, null);

#if DEBUG
                Trace.TraceInformation("Step 2 : Perform update to person #{0}", psn.Id);
#endif
                new RegistrationEventPersister().Persist(conn, tx, regEvent, true);

                refr.AlternateIdentifiers.Clear();
                refr.AlternateIdentifiers.Add(new SVC.Core.DataTypes.DomainIdentifier()
                {
                    Domain     = ApplicationContext.ConfigurationService.OidRegistrar.GetOid("CR_CID").Oid,
                    Identifier = psn.Id.ToString()
                });

                //pp.CreatePersonVersion(conn, tx, psn);
                //DbUtil.PersistComponents(conn, tx, false, this, psn);

                // Now, we have to prepare an event so that this all makes sense
                // if we de-persist the most recent version (to reflect changes made)
                // Store the merged new record

#if DEBUG
                Trace.TraceInformation("Step 3 : Perform update to person #{0}", dbCntrPsn.Id);
#endif
                pp.CreatePersonVersion(conn, tx, dbCntrPsn);

                // Components
                DbUtil.PersistComponents(conn, tx, false, this, dbCntrPsn);
                // Now update the backreference to up the chain it gets updated
                cntrPsn.VersionId = dbCntrPsn.VersionId;
            }

            // Create the link
#if DEBUG
            Trace.TraceInformation("Creating link between persons {0} > {1}", psn.Id, dbCntrPsn.Id);
#endif
            using (var cmd = DbUtil.CreateCommandStoredProc(conn, tx))
            {
                cmd.CommandText = "crt_psn_lnk";
                cmd.Parameters.Add(DbUtil.CreateParameterIn(cmd, "psn_id_in", DbType.Decimal, dbCntrPsn.Id));
                cmd.Parameters.Add(DbUtil.CreateParameterIn(cmd, "psn_vrsn_id_in", DbType.Decimal, dbCntrPsn.VersionId));
                cmd.Parameters.Add(DbUtil.CreateParameterIn(cmd, "lnk_psn_id_in", DbType.Decimal, psn.Id));
                cmd.Parameters.Add(DbUtil.CreateParameterIn(cmd, "lnk_cls_in", DbType.Decimal, (decimal)role));
                cmd.Parameters.Add(DbUtil.CreateParameterIn(cmd, "symbolic_in", DbType.Boolean, symbolic));
                cmd.ExecuteNonQuery();
            }

            // Send notification that duplicates were resolved
            //if (symbolic)
            //{
            //    // Send an duplicates resolved message
            //    IClientNotificationService notificationService = ApplicationContext.CurrentContext.GetService(typeof(IClientNotificationService)) as IClientNotificationService;
            //    if (notificationService != null)
            //        notificationService.NotifyDuplicatesResolved(cntrPsn, refr.AlternateIdentifiers[0]);
            //}
            refr.Id = psn.Id;


            // Person identifier
            return(new SVC.Core.DataTypes.VersionedDomainIdentifier()
            {
                Identifier = psn.Id.ToString(),
                Version = psn.VersionId.ToString()
            });
        }
Exemple #2
0
        /// <summary>
        /// De-persist the specified change summary
        /// </summary>
        public System.ComponentModel.IComponent DePersist(System.Data.IDbConnection conn, decimal identifier, System.ComponentModel.IContainer container, SVC.Core.ComponentModel.HealthServiceRecordSiteRoleType?role, bool loadFast)
        {
            // TODO: Ensure that when a parent with context conduction exists, to grab contextual data (authors, etc...) from the parent
            ChangeSummary retVal = new ChangeSummary();

            // Configuration service
            ISystemConfigurationService configService = ApplicationContext.ConfigurationService; //ApplicationContext.Current.GetService(typeof(ISystemConfigurationService)) as ISystemConfigurationService;

            // Get the health service event
            IDbCommand cmd = DbUtil.CreateCommandStoredProc(conn, null);

            try
            {
                cmd.CommandText = "get_hsr_crnt_vrsn";
                cmd.Parameters.Add(DbUtil.CreateParameterIn(cmd, "hsr_id_in", DbType.Decimal, identifier));

                decimal tsId          = default(decimal),
                        cdId          = default(decimal),
                        rplcVersionId = default(decimal);

                // Read data
                IDataReader reader = cmd.ExecuteReader();
                try
                {
                    if (!reader.Read())
                    {
                        return(null);
                    }

                    retVal.Id = Convert.ToDecimal(reader["hsr_id"]);
                    retVal.VersionIdentifier   = Convert.ToDecimal(reader["hsr_vrsn_id"]);
                    retVal.AlternateIdentifier = new VersionedDomainIdentifier()
                    {
                        Domain     = configService.OidRegistrar.GetOid(ClientRegistryOids.EVENT_OID).Oid,
                        Identifier = retVal.Id.ToString(),
                        Version    = retVal.VersionIdentifier.ToString()
                    };
                    retVal.LanguageCode = reader["lang_cs"].ToString();
                    retVal.Timestamp    = DateTime.Parse(Convert.ToString(reader["aut_utc"]));
                    retVal.Status       = (StatusType)Convert.ToDecimal(reader["status_cs_id"]);
                    tsId          = reader["efft_ts_set_id"] == DBNull.Value ? default(decimal) : Convert.ToDecimal(reader["efft_ts_set_id"]);
                    cdId          = Convert.ToDecimal(reader["evt_typ_cd_id"]);
                    rplcVersionId = reader["rplc_vrsn_id"] == DBNull.Value ? default(decimal) : Convert.ToDecimal(reader["rplc_vrsn_id"]);
                }
                finally
                {
                    reader.Close();
                }

                // Read codes and times
                retVal.ChangeType = DbUtil.GetCodedValue(conn, null, cdId);
                if (tsId != default(decimal))
                {
                    retVal.EffectiveTime = DbUtil.GetEffectiveTimestampSet(conn, null, tsId);
                }

                if (container != null)
                {
                    container.Add(retVal);
                }

                if (role.HasValue && (role.Value & HealthServiceRecordSiteRoleType.ReplacementOf) == HealthServiceRecordSiteRoleType.ReplacementOf)
                {
                    ;
                }
                else
                {
                    DbUtil.DePersistComponents(conn, retVal, this, loadFast);
                }
            }
            finally
            {
                cmd.Dispose();
            }

            return(retVal);
        }