/// <summary>
        /// Map a practitioner to a user entity
        /// </summary>
        protected override Provider MapToModel(Practitioner resource)
        {
            Provider retVal = null;

            if (Guid.TryParse(resource.Id, out var key))
            {
                retVal = this.m_repository.Get(key);
            }
            else if (resource.Identifier.Any())
            {
                foreach (var ii in resource.Identifier.Select(DataTypeConverter.ToEntityIdentifier))
                {
                    if (ii.LoadProperty(o => o.Authority).IsUnique)
                    {
                        retVal = this.m_repository.Find(o => o.Identifiers.Where(i => i.AuthorityKey == ii.AuthorityKey).Any(i => i.Value == ii.Value)).FirstOrDefault();
                    }
                    if (retVal != null)
                    {
                        break;
                    }
                }
            }

            if (retVal == null)
            {
                retVal = new Provider
                {
                    Key = Guid.NewGuid()
                };
            }

            // Organization
            retVal.Addresses = resource.Address.Select(DataTypeConverter.ToEntityAddress).ToList();
            // TODO: Extensions
            retVal.Identifiers           = resource.Identifier.Select(DataTypeConverter.ToEntityIdentifier).ToList();
            retVal.Names                 = resource.Name.Select(DataTypeConverter.ToEntityName).ToList();
            retVal.StatusConceptKey      = !resource.Active.HasValue || resource.Active == true ? StatusKeys.Active : StatusKeys.Inactive;
            retVal.Telecoms              = resource.Telecom.Select(DataTypeConverter.ToEntityTelecomAddress).ToList();
            retVal.Extensions            = resource.Extension.Select(o => DataTypeConverter.ToEntityExtension(o, retVal)).OfType <EntityExtension>().ToList();
            retVal.GenderConceptKey      = resource.Gender == null ? NullReasonKeys.Unknown : DataTypeConverter.ToConcept(new Coding("http://hl7.org/fhir/administrative-gender", Hl7.Fhir.Utility.EnumUtility.GetLiteral(resource.Gender)))?.Key;
            retVal.DateOfBirthXml        = resource.BirthDate;
            retVal.DateOfBirthPrecision  = DatePrecision.Day;
            retVal.LanguageCommunication = resource.Communication.Select(c => DataTypeConverter.ToLanguageCommunication(c, false)).ToList();

            if (resource.Photo != null && resource.Photo.Any())
            {
                retVal.Extensions.RemoveAll(o => o.ExtensionTypeKey == ExtensionTypeKeys.JpegPhotoExtension);
                retVal.Extensions.Add(new EntityExtension(ExtensionTypeKeys.JpegPhotoExtension, resource.Photo.First().Data));
            }

            if (resource.Qualification.Any())
            {
                retVal.ProviderSpecialty = DataTypeConverter.ToConcept(resource.Qualification.First().Code);
            }

            return(retVal);
        }
Beispiel #2
0
        /// <summary>
        /// Maps a FHIR patient resource to an HDSI patient.
        /// </summary>
        /// <param name="resource">The resource.</param>
        /// <returns>Returns the mapped model.</returns>
        protected override Core.Model.Roles.Patient MapToModel(Patient resource)
        {
            Core.Model.Roles.Patient patient = null;

            // Attempt to XRef
            if (Guid.TryParse(resource.Id, out Guid key))
            {
                patient = this.m_repository.Get(key);

                // Patient doesn't exist?
                if (patient == null)
                {
                    patient = new Core.Model.Roles.Patient
                    {
                        Key = key
                    };
                }
            }
            else if (resource.Identifier.Any())
            {
                foreach (var ii in resource.Identifier.Select(DataTypeConverter.ToEntityIdentifier))
                {
                    if (ii.LoadProperty(o => o.Authority).IsUnique)
                    {
                        patient = this.m_repository.Find(o => o.Identifiers.Where(i => i.AuthorityKey == ii.AuthorityKey).Any(i => i.Value == ii.Value)).FirstOrDefault();
                    }
                    if (patient != null)
                    {
                        break;
                    }
                }

                if (patient == null)
                {
                    patient = new Core.Model.Roles.Patient
                    {
                        Key = Guid.NewGuid()
                    };
                }
            }
            else
            {
                patient = new Core.Model.Roles.Patient
                {
                    Key = Guid.NewGuid()
                };
            }

            patient.Addresses             = resource.Address.Select(DataTypeConverter.ToEntityAddress).ToList();
            patient.CreationTime          = DateTimeOffset.Now;
            patient.GenderConceptKey      = resource.Gender == null ? null : DataTypeConverter.ToConcept(new Coding("http://hl7.org/fhir/administrative-gender", Hl7.Fhir.Utility.EnumUtility.GetLiteral(resource.Gender)))?.Key;
            patient.Identifiers           = resource.Identifier.Select(DataTypeConverter.ToEntityIdentifier).ToList();
            patient.LanguageCommunication = resource.Communication.Select(DataTypeConverter.ToLanguageCommunication).ToList();
            patient.Names            = resource.Name.Select(DataTypeConverter.ToEntityName).ToList();
            patient.StatusConceptKey = resource.Active == null || resource.Active == true ? StatusKeys.Active : StatusKeys.Inactive;
            patient.Telecoms         = resource.Telecom.Select(DataTypeConverter.ToEntityTelecomAddress).OfType <EntityTelecomAddress>().ToList();
            patient.Relationships    = resource.Contact.Select(r => DataTypeConverter.ToEntityRelationship(r, resource)).ToList();
            patient.Extensions       = resource.Extension.Select(o => DataTypeConverter.ToEntityExtension(o, patient)).ToList();

            patient.DateOfBirth = DataTypeConverter.ToDateTimeOffset(resource.BirthDate, out var dateOfBirthPrecision)?.DateTime;
            // TODO: fix
            // HACK: the date of birth precision CK only allows "Y", "M", or "D" for the precision value
            patient.DateOfBirthPrecision = dateOfBirthPrecision == DatePrecision.Full ? DatePrecision.Day : dateOfBirthPrecision;

            switch (resource.Deceased)
            {
            case FhirDateTime dtValue when !String.IsNullOrEmpty(dtValue.Value):
                patient.DeceasedDate = DataTypeConverter.ToDateTimeOffset(dtValue.Value, out var datePrecision)?.DateTime;
                // TODO: fix
                // HACK: the deceased date precision CK only allows "Y", "M", or "D" for the precision value
                patient.DeceasedDatePrecision = datePrecision == DatePrecision.Full ? DatePrecision.Day : datePrecision;
                break;

            case FhirBoolean boolValue when boolValue.Value.GetValueOrDefault():
                // we don't have a field for "deceased indicator" to say that the patient is dead, but we don't know that actual date/time of death
                // should find a better way to do this
                patient.DeceasedDate = DateTime.MinValue;

                patient.DeceasedDatePrecision = DatePrecision.Year;
                break;
            }

            switch (resource.MultipleBirth)
            {
            case FhirBoolean boolBirth when boolBirth.Value.GetValueOrDefault():
                patient.MultipleBirthOrder = 0;

                break;

            case Integer intBirth:
                patient.MultipleBirthOrder = intBirth.Value;
                break;
            }

            if (resource.GeneralPractitioner != null)
            {
                patient.Relationships.AddRange(resource.GeneralPractitioner.Select(r =>
                {
                    var referenceKey = DataTypeConverter.ResolveEntity <Core.Model.Roles.Provider>(r, resource) as Entity ?? DataTypeConverter.ResolveEntity <Core.Model.Entities.Organization>(r, resource);

                    if (referenceKey == null)
                    {
                        this.m_tracer.TraceError("Can't locate a registered general practitioner");
                        throw new KeyNotFoundException(m_localizationService.FormatString("error.type.KeyNotFoundException.cannotLocateRegistered", new
                        {
                            param = "general practitioner"
                        }));
                    }

                    return(new EntityRelationship(EntityRelationshipTypeKeys.HealthcareProvider, referenceKey));
                }));
            }
            if (resource.ManagingOrganization != null)
            {
                var referenceKey = DataTypeConverter.ResolveEntity <Core.Model.Entities.Organization>(resource.ManagingOrganization, resource);

                if (referenceKey == null)
                {
                    this.m_tracer.TraceError("Can't locate a registered managing organization");

                    throw new KeyNotFoundException(m_localizationService.FormatString("error.type.KeyNotFoundException.cannotLocateRegistered", new
                    {
                        param = "managing organization"
                    }));
                }

                patient.Relationships.Add(new EntityRelationship(EntityRelationshipTypeKeys.Scoper, referenceKey));
            }

            // Process contained related persons
            foreach (var itm in resource.Contained.OfType <RelatedPerson>())
            {
                var er = FhirResourceHandlerUtil.GetMappersFor(ResourceType.RelatedPerson).First().MapToModel(itm) as Core.Model.Entities.EntityRelationship;

                // Relationship bindings
                er.ClassificationKey = RelationshipClassKeys.ContainedObjectLink;
                er.SourceEntityKey   = patient.Key;

                // Now add rels to me
                patient.Relationships.Add(er);
            }

            // Links
            foreach (var lnk in resource.Link)
            {
                switch (lnk.Type.Value)
                {
                case Patient.LinkType.Replaces:
                {
                    // Find the victim
                    var replacee = DataTypeConverter.ResolveEntity <Core.Model.Roles.Patient>(lnk.Other, resource);

                    if (replacee == null)
                    {
                        this.m_tracer.TraceError($"Cannot locate patient referenced by {lnk.Type} relationship");
                        throw new KeyNotFoundException(m_localizationService.FormatString("error.messaging.fhir.patientResource.cannotLocatePatient", new
                            {
                                param = lnk.Type
                            }));
                    }

                    replacee.StatusConceptKey = StatusKeys.Obsolete;
                    patient.Relationships.Add(new EntityRelationship(EntityRelationshipTypeKeys.Replaces, replacee));
                    break;
                }

                case Patient.LinkType.ReplacedBy:
                {
                    // Find the new
                    var replacer = DataTypeConverter.ResolveEntity <Core.Model.Roles.Patient>(lnk.Other, resource);

                    if (replacer == null)
                    {
                        this.m_tracer.TraceError($"Cannot locate patient referenced by {lnk.Type} relationship");
                        throw new KeyNotFoundException(m_localizationService.FormatString("error.messaging.fhir.patientResource.cannotLocatePatient", new
                            {
                                param = lnk.Type
                            }));
                    }

                    patient.StatusConceptKey = StatusKeys.Obsolete;
                    patient.Relationships.Add(new EntityRelationship(EntityRelationshipTypeKeys.Replaces, patient)
                        {
                            HolderKey = replacer.Key
                        });
                    break;
                }

                case Patient.LinkType.Seealso:
                {
                    var referee = DataTypeConverter.ResolveEntity <Entity>(lnk.Other, resource);        // We use Entity here in lieu Patient since the code below can handle the MDM layer

                    // Is this a current MDM link?
                    if (referee.GetTag(FhirConstants.PlaceholderTag) == "true")         // The referee wants us to become the data
                    {
                        patient.Key = referee.Key;
                    }
                    else if (referee.LoadCollection(o => o.Relationships).Any(r => r.RelationshipTypeKey == MDM_MASTER_LINK) &&
                             referee.GetTag("$mdm.type") == "M")       // HACK: This is a master and someone is attempting to point another record at it
                    {
                        patient.Relationships.Add(new EntityRelationship()
                            {
                                RelationshipTypeKey = MDM_MASTER_LINK,
                                SourceEntityKey     = referee.Key,
                                TargetEntityKey     = patient.Key
                            });
                    }
                    else
                    {
                        patient.Relationships.Add(new EntityRelationship(EntityRelationshipTypeKeys.EquivalentEntity, referee));
                    }
                    break;
                }

                case Patient.LinkType.Refer:     // This points to a more detailed view of the patient
                {
                    var referee = DataTypeConverter.ResolveEntity <Entity>(lnk.Other, resource);
                    if (referee.GetTag("$mdm.type") == "M")         // HACK: MDM User is attempting to point this at another Master (note: THE MDM LAYER WON'T LIKE THIS)
                    {
                        patient.Relationships.Add(new EntityRelationship(MDM_MASTER_LINK, referee));
                    }
                    else
                    {
                        this.m_tracer.TraceError($"Setting refer relationships to source of truth is not supported");
                        throw new NotSupportedException(m_localizationService.GetString("error.type.NotSupportedException.userMessage"));
                    }

                    break;         // TODO: These are special cases of references
                }
                }
            }

            if (resource.Photo != null && resource.Photo.Any())
            {
                patient.Extensions.RemoveAll(o => o.ExtensionTypeKey == ExtensionTypeKeys.JpegPhotoExtension);
                patient.Extensions.Add(new EntityExtension(ExtensionTypeKeys.JpegPhotoExtension, resource.Photo.First().Data));
            }

            return(patient);
        }
Beispiel #3
0
        /// <summary>
        /// Map to Model
        /// </summary>
        protected override Core.Model.Entities.Organization MapToModel(Hl7.Fhir.Model.Organization resource)
        {
            Core.Model.Entities.Organization retVal = null;
            if (Guid.TryParse(resource.Id, out Guid key))
            {
                retVal = this.m_repository.Get(key);
            }
            else if (resource.Identifier?.Count > 0)
            {
                foreach (var ii in resource.Identifier.Select(DataTypeConverter.ToEntityIdentifier))
                {
                    if (ii.LoadProperty(o => o.Authority).IsUnique)
                    {
                        retVal = this.m_repository.Find(o => o.Identifiers.Where(i => i.AuthorityKey == ii.AuthorityKey).Any(i => i.Value == ii.Value)).FirstOrDefault();
                    }
                    if (retVal != null)
                    {
                        break;
                    }
                }
            }
            if (retVal == null)
            {
                retVal = new Core.Model.Entities.Organization()
                {
                    Key = Guid.NewGuid()
                };
            }

            // Organization
            retVal.TypeConcept = resource.Type.Select(o => DataTypeConverter.ToConcept(o)).OfType <Concept>().FirstOrDefault();
            retVal.Addresses   = resource.Address.Select(DataTypeConverter.ToEntityAddress).ToList();

            // TODO: Extensions
            retVal.Identifiers = resource.Identifier.Select(DataTypeConverter.ToEntityIdentifier).ToList();
            retVal.Names       = new List <EntityName>()
            {
                new EntityName(NameUseKeys.OfficialRecord, resource.Name)
            };
            retVal.Names.AddRange(resource.Alias.Select(o => new EntityName(NameUseKeys.Pseudonym, o)));
            retVal.StatusConceptKey = !resource.Active.HasValue || resource.Active == true ? StatusKeys.Active : StatusKeys.Inactive;
            retVal.Telecoms         = resource.Telecom.Select(DataTypeConverter.ToEntityTelecomAddress).OfType <EntityTelecomAddress>().ToList();

            if (resource.PartOf != null)
            {
                var reference = DataTypeConverter.ResolveEntity <Core.Model.Entities.Organization>(resource.PartOf, resource);
                if (reference == null)
                {
                    this.m_tracer.TraceError($"Could not resolve {resource.PartOf.Reference}");
                    throw new KeyNotFoundException(m_localizationService.FormatString("error.type.KeyNotFoundException.couldNotResolve", new
                    {
                        param = resource.PartOf.Reference
                    }));
                }

                // point the child organization entity at the target organization entity with a relationship of parent
                retVal.Relationships.Add(new EntityRelationship(EntityRelationshipTypeKeys.Parent, reference));
            }
            retVal.Extensions = resource.Extension.Select(o => DataTypeConverter.ToEntityExtension(o, retVal)).OfType <EntityExtension>().ToList();
            return(retVal);
        }