/// <summary>
        /// Find a client
        /// </summary>
        public Client FindClient(DomainIdentifier identifier)
        {
            PersonPersister persister = new PersonPersister();

            // HACK: I norder to work around Client Registry Hack
            ApplicationContext.CurrentContext = Context;
            // First we want to find the appropriate helper
            IDbConnection conn = DatabasePersistenceService.ReadOnlyConnectionManager.GetConnection();

            try
            {
                var    tPerson = persister.GetPerson(conn, null, identifier, true);
                Client retVal  = new Client()
                {
                    AlternateIdentifiers = tPerson.AlternateIdentifiers,
                    BirthTime            = tPerson.BirthTime,
                    GenderCode           = tPerson.GenderCode,
                    Id               = tPerson.Id,
                    IsMasked         = tPerson.IsMasked,
                    LegalName        = tPerson.Names == null || tPerson.Names.Count == 0 ? null : tPerson.Names.Find(n => n.Use == NameSet.NameSetUse.Legal) ?? tPerson.Names[0],
                    PerminantAddress = tPerson.Addresses == null || tPerson.Addresses.Count == 0 ? null : tPerson.Addresses.Find(n => n.Use == AddressSet.AddressSetUse.HomeAddress) ?? tPerson.Addresses[0],
                    TelecomAddresses = tPerson.TelecomAddresses
                };
                retVal.Add(tPerson, "PSN", SVC.Core.ComponentModel.HealthServiceRecordSiteRoleType.TargetOf, null);
                return(retVal);
            }
            finally
            {
                DatabasePersistenceService.ConnectionManager.ReleaseConnection(conn);
            }
        }
Пример #2
0
        /// <summary>
        /// Build the filter
        /// </summary>
        public string BuildFilter(IComponent data, bool forceExact)
        {
            PersonalRelationship prs = data as PersonalRelationship;

            // Subject relative
            Person subjectRelative = new Person()
            {
                RoleCode = PersonRole.PRS | PersonRole.PAT,
                Site     = data.Site
            };

            if (prs.LegalName != null)
            {
                subjectRelative.Names = new List <NameSet>()
                {
                    prs.LegalName
                }
            }
            ;
            if (prs.AlternateIdentifiers != null && prs.AlternateIdentifiers.Count > 0)
            {
                subjectRelative.AlternateIdentifiers = new List <DomainIdentifier>(prs.AlternateIdentifiers);
            }

            PersonPersister prsp         = new PersonPersister();
            var             filterString = prsp.BuildFilter(subjectRelative, forceExact);

            var registrationEvent = DbUtil.GetRegistrationEvent(data);

            StringBuilder sb = new StringBuilder();

            if (registrationEvent != null) // We don't discriminate on queries for related persons
            {
                if (registrationEvent.EventClassifier == RegistrationEventType.Register || registrationEvent.EventClassifier == RegistrationEventType.Replace)
                {
                    return(""); // We don't discriminate against registration events based on who they're related to
                }
                else
                {
                    sb.Append("SELECT DISTINCT REG_VRSN_ID FROM PSN_VRSN_TBL INNER JOIN PSN_RLTNSHP_TBL ON (PSN_VRSN_TBL.PSN_ID = PSN_RLTNSHP_TBL.TRG_PSN_ID) WHERE PSN_VRSN_TBL.OBSLT_UTC IS NULL AND PSN_VRSN_TBL.PSN_VRSN_ID BETWEEN PSN_RLTNSHP_TBL.EFFT_VRSN_ID AND COALESCE(PSN_RLTNSHP_TBL.OBSLT_VRSN_ID, PSN_VRSN_TBL.PSN_VRSN_ID) ");
                }
            }
            else
            {
                sb.Append("SELECT DISTINCT TRG_PSN_ID AS PSN_ID FROM PSN_RLTNSHP_TBL WHERE OBSLT_UTC IS NULL ");
            }

            sb.AppendFormat(" AND KIND_CS = '{0}' AND SRC_PSN_ID IN (SELECT PSN_TBL.PSN_ID FROM ({1}) AS PSN_TBL) ", prs.RelationshipKind.Replace("'", "''"), filterString);

            return(sb.ToString());
            //return String.Empty;
        }
Пример #3
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()
            });
        }
Пример #4
0
        /// <summary>
        /// Persist a component to the database
        /// </summary>
        public MARC.HI.EHRS.SVC.Core.DataTypes.VersionedDomainIdentifier Persist(System.Data.IDbConnection conn, System.Data.IDbTransaction tx, System.ComponentModel.IComponent data, bool isUpdate)
        {
            // Get config service
            ISystemConfigurationService configService = ApplicationContext.ConfigurationService; //ApplicationContext.Current.GetService(typeof(ISystemConfigurationService)) as ISystemConfigurationService;

            // Create the personal relationship in a strongly typed fashion
            PersonalRelationship pr   = data as PersonalRelationship;
            Person clientContainer    = pr.Site.Container as Person,
                   relationshipPerson = null;

            // Get the person persister
            var persister = new PersonPersister();

            // First, let's see if we can fetch the client
            if (pr.Id != default(decimal))
            {
                var personalRelationship = this.DePersist(conn, pr.Id, pr.Site.Container, (pr.Site as HealthServiceRecordSite).SiteRoleType, true) as PersonalRelationship;
                relationshipPerson = personalRelationship.FindComponent(HealthServiceRecordSiteRoleType.SubjectOf) as Person;
            }
            else if (pr.AlternateIdentifiers != null)
            {
                int i = 0;
                while (relationshipPerson == null && i < pr.AlternateIdentifiers.Count)
                {
                    relationshipPerson = persister.GetPerson(conn, tx, pr.AlternateIdentifiers[i++], true);
                }
            }

            if (relationshipPerson == null)
            {
                List <DomainIdentifier> candidateId = new List <DomainIdentifier>();

                // Is this an existing person (same name and relation)
                using (IDbCommand cmd = DbUtil.CreateCommandStoredProc(conn, tx))
                {
                    cmd.CommandText = "get_psn_rltnshps";
                    cmd.Parameters.Add(DbUtil.CreateParameterIn(cmd, "src_psn_id_in", DbType.Decimal, clientContainer.Id));
                    cmd.Parameters.Add(DbUtil.CreateParameterIn(cmd, "src_psn_vrsn_id_in", DbType.Decimal, clientContainer.VersionId));
                    using (IDataReader rdr = cmd.ExecuteReader())
                    {
                        while (rdr.Read())
                        {
                            if (rdr["kind_cs"].ToString() == pr.RelationshipKind)
                            {
                                candidateId.Add(new DomainIdentifier()
                                {
                                    Domain     = configService.OidRegistrar.GetOid("CR_CID").Oid,
                                    Identifier = rdr["src_psn_id"].ToString()
                                });
                            }
                        }
                    }
                }

                // Now load candidates and check
                foreach (var id in candidateId)
                {
                    var candidate = persister.GetPerson(conn, tx, id, true);
                    if (NON_DUPLICATE_REL.Contains(pr.RelationshipKind))
                    {
                        relationshipPerson = candidate;
                        break;
                    }
                    else if (candidate.Names.Exists(n => n.SimilarityTo(pr.LegalName) >= DatabasePersistenceService.ValidationSettings.PersonNameMatch))
                    {
                        relationshipPerson = candidate;
                        break;
                    }
                }
            }
            // Did we get one?
            // If not, then we need to register a patient in the database
            if (relationshipPerson == null)
            {
                if (pr.LegalName == null)
                {
                    throw new DataException(ApplicationContext.LocaleService.GetString("DBCF00B"));
                }
                relationshipPerson = new Person()
                {
                    AlternateIdentifiers = pr.AlternateIdentifiers,
                    Names = new List <NameSet>()
                    {
                        pr.LegalName
                    },
                    Addresses = new List <AddressSet>()
                    {
                        pr.PerminantAddress
                    },
                    GenderCode       = pr.GenderCode,
                    BirthTime        = pr.BirthTime,
                    TelecomAddresses = pr.TelecomAddresses,
                    Status           = StatusType.Active,
                    RoleCode         = PersonRole.PRS
                };

                var registrationEvent = DbUtil.GetRegistrationEvent(pr).Clone() as RegistrationEvent;
                registrationEvent.Id = default(decimal);
                registrationEvent.EventClassifier = RegistrationEventType.ComponentEvent;
                registrationEvent.RemoveAllFromRole(HealthServiceRecordSiteRoleType.SubjectOf);
                registrationEvent.Add(relationshipPerson, "SUBJ", HealthServiceRecordSiteRoleType.SubjectOf, null);
                registrationEvent.Status = StatusType.Completed;

                // Persist or merge?
                new RegistrationEventPersister().Persist(conn, tx, registrationEvent, isUpdate);
                //var clientIdentifier = persister.Persist(conn, tx, relationshipPerson, isUpdate); // Should persist
            }
            else if (relationshipPerson.RoleCode != PersonRole.PAT)
            {
                var updatedPerson = new Person()
                {
                    Id = relationshipPerson.Id,
                    AlternateIdentifiers = pr.AlternateIdentifiers,
                    Names = new List <NameSet>()
                    {
                        pr.LegalName
                    },
                    Addresses = new List <AddressSet>()
                    {
                    },
                    GenderCode       = pr.GenderCode,
                    BirthTime        = pr.BirthTime,
                    TelecomAddresses = pr.TelecomAddresses,
                    Status           = StatusType.Active,
                    RoleCode         = relationshipPerson.RoleCode
                };

                if (pr.PerminantAddress != null)
                {
                    updatedPerson.Addresses.Add(pr.PerminantAddress);
                }

                persister.MergePersons(updatedPerson, relationshipPerson, true);
                relationshipPerson = updatedPerson;

                var registrationEvent = DbUtil.GetRegistrationEvent(pr).Clone() as RegistrationEvent;
                registrationEvent.Id = default(decimal);
                registrationEvent.EventClassifier = RegistrationEventType.ComponentEvent;
                registrationEvent.RemoveAllFromRole(HealthServiceRecordSiteRoleType.SubjectOf);
                registrationEvent.Add(relationshipPerson, "SUBJ", HealthServiceRecordSiteRoleType.SubjectOf, null);
                registrationEvent.Status = StatusType.Completed;
                new RegistrationEventPersister().Persist(conn, tx, registrationEvent, isUpdate);
            }

            // Validate
            if (!NON_DUPLICATE_REL.Contains(pr.RelationshipKind) && pr.AlternateIdentifiers.Count == 0 && !relationshipPerson.Names.Exists(o => QueryUtil.MatchName(pr.LegalName, o) >= DatabasePersistenceService.ValidationSettings.PersonNameMatch))
            {
                throw new DataException(ApplicationContext.LocaleService.GetString("DBCF00A"));
            }
            // If the container for this personal relationship is a client, then we'll need to link that
            // personal relationship with the client to whom they have a relation with.
            if (clientContainer != null) // We need to do some linking
            {
                pr.Id = LinkClients(conn, tx, relationshipPerson.Id, clientContainer.Id, pr.RelationshipKind, pr.Status);
            }
            else if (clientContainer == null) // We need to do some digging to find out "who" this person is related to (the record target)
            {
                throw new ConstraintException(ApplicationContext.LocaleService.GetString("DBCF003"));
            }

            // todo: Container is a HSR

            return(new VersionedDomainIdentifier()
            {
                Domain = configService.OidRegistrar.GetOid(ClientRegistryOids.RELATIONSHIP_OID).Oid,
                Identifier = pr.Id.ToString()
            });
        }
Пример #5
0
        /// <summary>
        /// De-persist a record from the database
        /// </summary>
        public System.ComponentModel.IComponent DePersist(System.Data.IDbConnection conn, decimal identifier, IContainer container, HealthServiceRecordSiteRoleType?roleType, bool loadFast)
        {
            // Return value
            PersonalRelationship retVal = new PersonalRelationship();

            // De-persist the observation record
            ISystemConfigurationService sysConfig = ApplicationContext.ConfigurationService;

            // De-persist
            using (IDbCommand cmd = DbUtil.CreateCommandStoredProc(conn, null))
            {
                cmd.CommandText = "get_psn_rltnshp";
                cmd.Parameters.Add(DbUtil.CreateParameterIn(cmd, "psn_rltnshp_id_in", DbType.Decimal, identifier));
                String clientId = String.Empty;
                // Execute the reader
                using (IDataReader rdr = cmd.ExecuteReader())
                {
                    if (rdr.Read())
                    {
                        retVal.Id = identifier;
                        retVal.RelationshipKind = Convert.ToString(rdr["kind_cs"]);

                        // Add prs
                        retVal.AlternateIdentifiers.Add(new DomainIdentifier()
                        {
                            Domain     = sysConfig.OidRegistrar.GetOid(ClientRegistryOids.RELATIONSHIP_OID).Oid,
                            Identifier = rdr["rltnshp_id"].ToString()
                        });
                        retVal.Id = Convert.ToDecimal(rdr["rltnshp_id"]);
                        clientId  = rdr["src_psn_id"].ToString();
                    }
                    else
                    {
                        return(null);
                    }
                }
                // First, de-persist the client portions
                var clientDataRetVal = new PersonPersister().GetPerson(conn, null, new DomainIdentifier()
                {
                    Domain     = sysConfig.OidRegistrar.GetOid(ClientRegistryOids.CLIENT_CRID).Oid,
                    Identifier = clientId.ToString()
                }, true);

                if (clientDataRetVal.Names != null)
                {
                    retVal.LegalName = clientDataRetVal.Names.Find(o => o.Use == NameSet.NameSetUse.Legal) ?? clientDataRetVal.Names[0];
                }

                if (clientDataRetVal.RoleCode == PersonRole.PAT)
                {
                    retVal.AlternateIdentifiers.AddRange(clientDataRetVal.AlternateIdentifiers.Where(o => o.Domain != sysConfig.OidRegistrar.GetOid(ClientRegistryOids.RELATIONSHIP_OID).Oid));
                }
                else
                {
                    retVal.AlternateIdentifiers.AddRange(clientDataRetVal.AlternateIdentifiers.Where(o => o.Domain != sysConfig.OidRegistrar.GetOid(ClientRegistryOids.CLIENT_CRID).Oid));
                }

                retVal.Add(clientDataRetVal, "SUBJ", HealthServiceRecordSiteRoleType.SubjectOf, null);
            }

            return(retVal);
        }
Пример #6
0
        /// <summary>
        /// Update container
        /// </summary>
        public VersionedDomainIdentifier UpdateContainer(System.ComponentModel.IContainer storageData, DataPersistenceMode mode)
        {
            if (m_disposed)
            {
                throw new ObjectDisposedException("DatabasePersistenceService");
            }

            if (storageData == null)
            {
                throw new ArgumentNullException("storageData");
            }

            // Get the persister
            IComponentPersister         persister     = GetPersister(storageData.GetType());
            ISystemConfigurationService configService = ApplicationContext.ConfigurationService;

            if (persister != null)
            {
                IDbTransaction tx   = null;
                IDbConnection  conn = null;
                try
                {
                    conn = DatabasePersistenceService.ConnectionManager.GetConnection();

                    RegistrationEvent hsrEvent = storageData as RegistrationEvent;

                    // Is the record something that we have access to?
                    if (hsrEvent.AlternateIdentifier != null && !hsrEvent.AlternateIdentifier.Domain.Equals(configService.OidRegistrar.GetOid(ClientRegistryOids.REGISTRATION_EVENT).Oid))
                    {
                        throw new ArgumentException(String.Format("The record OID '{0}' cannot be retrieved by this repository, expecting OID '{1}'",
                                                                  hsrEvent.AlternateIdentifier.Domain, configService.OidRegistrar.GetOid(ClientRegistryOids.REGISTRATION_EVENT).Oid));
                    }

                    decimal tryDec         = default(decimal);
                    bool    isDirectUpdate = false;

                    // Is there no event identifier ?
                    if (hsrEvent.AlternateIdentifier != null && !Decimal.TryParse(hsrEvent.AlternateIdentifier.Identifier, out tryDec))
                    {
                        throw new ArgumentException(String.Format("The identifier '{0}' is not a valid identifier for this repository", hsrEvent.AlternateIdentifier.Identifier));
                    }
                    else if (hsrEvent.AlternateIdentifier == null) // The alternate identifier is null ... so we need to look up the registration event to version ... interesting....
                    {
                        this.EnrichRegistrationEvent(conn, tx, hsrEvent);
                    }
                    else
                    {
                        // Get the person name
                        isDirectUpdate = true; // Explicit update
                    }

                    // Validate and duplicate the components that are to be loaded as part of the new version
                    var oldHsrEvent = GetContainer(hsrEvent.AlternateIdentifier, true) as RegistrationEvent; // Get the old container
                    if (oldHsrEvent == null)
                    {
                        throw new MissingPrimaryKeyException(String.Format("Record {1}^^^&{0}&ISO does not exist", hsrEvent.AlternateIdentifier.Domain, hsrEvent.AlternateIdentifier.Identifier));
                    }

                    PersonPersister cp = new PersonPersister();

                    // Validate the old record target
                    Person oldRecordTarget = oldHsrEvent.FindComponent(HealthServiceRecordSiteRoleType.SubjectOf) as Person,
                           newRecordTarget = hsrEvent.FindComponent(HealthServiceRecordSiteRoleType.SubjectOf) as Person;

                    Person verifyRecordTarget = null;
                    if (!isDirectUpdate)
                    {
                        Trace.TraceInformation("Not Direct update, enriching the Patient Data");
                        int idCheck = 0;
                        while (verifyRecordTarget == null || idCheck > newRecordTarget.AlternateIdentifiers.Count)
                        {
                            verifyRecordTarget = cp.GetPerson(conn, null, newRecordTarget.AlternateIdentifiers[idCheck++], true);
                        }

                        if (verifyRecordTarget == null || oldRecordTarget.Id != verifyRecordTarget.Id)
                        {
                            throw new ConstraintException("The update request specifies a different subject than the request currently stored");
                        }
                    }
                    else
                    {
                        verifyRecordTarget = oldRecordTarget;
                    }
                    //newRecordTarget.VersionId = verifyRecordTarget.VersionId;
                    newRecordTarget.Id = verifyRecordTarget.Id;

                    // VAlidate classific
                    if (oldHsrEvent.EventClassifier != hsrEvent.EventClassifier &&
                        (hsrEvent.EventClassifier & RegistrationEventType.Register) == RegistrationEventType.None)
                    {
                        throw new ConstraintException("Record type mis-match between update data and the data already in the persistence store");
                    }

                    if (oldHsrEvent.LanguageCode != hsrEvent.LanguageCode)
                    {
                        throw new ConstraintException("Record language mis-match between update data and data already in persistence store. To change the language use a \"replaces\" relationship rather than an update");
                    }

                    // Are we performing a component update? If so the only two components we want freshened are the CommentOn (for adding comments)
                    // and the ReasonFor | OlderVersionOf comment for change summaries
                    if ((hsrEvent.EventClassifier & RegistrationEventType.ComponentEvent) != 0)
                    {
                        for (int i = hsrEvent.XmlComponents.Count - 1; i >= 0; i--)
                        {
                            if (((hsrEvent.XmlComponents[i].Site as HealthServiceRecordSite).SiteRoleType & (HealthServiceRecordSiteRoleType.CommentOn | HealthServiceRecordSiteRoleType.ReasonFor | HealthServiceRecordSiteRoleType.OlderVersionOf | HealthServiceRecordSiteRoleType.TargetOf)) == 0)
                            {
                                hsrEvent.Remove(hsrEvent.XmlComponents[i]);
                            }
                        }
                    }

                    // Copy over any components that aren't already specified or updated in the new record
                    // Merge the old and new. Sets the update mode appropriately
                    cp.MergePersons(newRecordTarget, oldRecordTarget);

                    // Next we copy this as a replacement of
                    hsrEvent.RemoveAllFromRole(HealthServiceRecordSiteRoleType.SubjectOf);
                    hsrEvent.Add(newRecordTarget, "SUBJ", HealthServiceRecordSiteRoleType.SubjectOf, null);

                    // Begin and update
                    tx = conn.BeginTransaction();

                    var retVal = persister.Persist(conn, tx, storageData as IComponent, true);

                    if (m_configuration.OverridePersistenceMode.HasValue)
                    {
                        mode = m_configuration.OverridePersistenceMode.Value;
                    }

                    if (mode == DataPersistenceMode.Production)
                    {
                        tx.Commit();
                        tx = null;

                        // Mark conflicts if any are outstanding pointing at the old versionj
                        if (this.m_clientRegistryMerge != null)
                        {
                            var existingConflicts = this.m_clientRegistryMerge.GetConflicts(oldHsrEvent.AlternateIdentifier);
                            if (existingConflicts.Count() > 0)
                            {
                                Trace.TraceInformation("Obsoleting existing conlflicts resolved");
                                this.m_clientRegistryMerge.ObsoleteConflicts(oldHsrEvent.AlternateIdentifier);
                            }
                            this.m_threadPool.QueueUserWorkItem(this.MarkConflictsAsync, retVal);
                        }

                        // Notify register
                        if (this.m_notificationService != null)
                        {
                            if (hsrEvent.Mode == RegistrationEventType.Replace)
                            {
                                this.m_notificationService.NotifyDuplicatesResolved(hsrEvent);
                            }
                            else
                            {
                                this.m_notificationService.NotifyUpdate(hsrEvent);
                            }
                        }
                    }
                    else
                    {
                        tx.Rollback();
                    }


                    return(retVal);
                }
                catch (Exception e)
                {
                    if (tx != null)
                    {
                        tx.Rollback();
                    }
                    throw;
                }
                finally
                {
                    if (tx != null)
                    {
                        tx.Dispose();
                    }
                    if (conn != null)
                    {
                        DatabasePersistenceService.ConnectionManager.ReleaseConnection(conn);
                        conn = null;
                    }
                }
            }
            else
            {
                Trace.TraceError("Can't find a persistence handler for type '{0}'", storageData.GetType().Name);
                throw new DataException(String.Format("Can't persist type '{0}'", storageData.GetType().Name));
            }
        }