/// <summary> /// Map a user entity to a practitioner /// </summary> protected override Practitioner MapToFhir(UserEntity model, RestOperationContext restOperationContext) { // Is there a provider that matches this user? var provider = model.LoadCollection <EntityRelationship>("Relationships").FirstOrDefault(o => o.RelationshipTypeKey == EntityRelationshipTypeKeys.AssignedEntity)?.LoadProperty <Provider>("TargetEntity"); var retVal = DataTypeConverter.CreateResource <Practitioner>(model); // Identifiers retVal.Identifier = (provider?.Identifiers ?? model.Identifiers)?.Select(o => DataTypeConverter.ToFhirIdentifier(o)).ToList(); // ACtive retVal.Active = model.StatusConceptKey == StatusKeys.Active; // Names retVal.Name = (provider?.LoadCollection <EntityName>("Names") ?? model.LoadCollection <EntityName>("Names"))?.Select(o => DataTypeConverter.ToFhirHumanName(o)).ToList(); // Telecoms retVal.Telecom = (provider?.LoadCollection <EntityTelecomAddress>("Telecom") ?? model.LoadCollection <EntityTelecomAddress>("Telecom"))?.Select(o => DataTypeConverter.ToFhirTelecom(o)).ToList(); // Address retVal.Address = (provider?.LoadCollection <EntityAddress>("Addresses") ?? model.LoadCollection <EntityAddress>("Addresses"))?.Select(o => DataTypeConverter.ToFhirAddress(o)).ToList(); // Birthdate retVal.BirthDate = (provider?.DateOfBirth ?? model.DateOfBirth); var photo = (provider?.LoadCollection <EntityExtension>("Extensions") ?? model.LoadCollection <EntityExtension>("Extensions"))?.FirstOrDefault(o => o.ExtensionTypeKey == ExtensionTypeKeys.JpegPhotoExtension); if (photo != null) { retVal.Photo = new List <Attachment>() { new Attachment() { ContentType = "image/jpg", Data = photo.ExtensionValueXml } } } ; // Load the koala-fications retVal.Qualification = provider?.LoadCollection <Concept>("ProviderSpecialty").Select(o => new Qualification() { Code = DataTypeConverter.ToFhirCodeableConcept(o) }).ToList(); // Language of communication retVal.Communication = (provider?.LoadCollection <PersonLanguageCommunication>("LanguageCommunication") ?? model.LoadCollection <PersonLanguageCommunication>("LanguageCommunication"))?.Select(o => new FhirCodeableConcept(new Uri("http://tools.ietf.org/html/bcp47"), o.LanguageCode)).ToList(); return(retVal); }
/// <summary> /// Map to FHIR /// </summary> protected override SanteDB.Messaging.FHIR.Resources.Observation MapToFhir(Core.Model.Acts.Observation model, RestOperationContext restOperationContext) { var retVal = DataTypeConverter.CreateResource <SanteDB.Messaging.FHIR.Resources.Observation>(model); retVal.EffectiveDateTime = (FhirDate)model.ActTime.DateTime; retVal.Code = DataTypeConverter.ToFhirCodeableConcept(model.LoadProperty <Concept>("TypeConcept")); if (model.StatusConceptKey == StatusKeys.Completed) { retVal.Status = new FhirCode <ObservationStatus>(ObservationStatus.Final); } else if (model.StatusConceptKey == StatusKeys.Active) { retVal.Status = new FhirCode <ObservationStatus>(ObservationStatus.Preliminary); } else if (model.StatusConceptKey == StatusKeys.Nullified) { retVal.Status = new FhirCode <ObservationStatus>(ObservationStatus.EnteredInError); } if (model.Relationships.Any(o => o.RelationshipTypeKey == ActRelationshipTypeKeys.Replaces)) { retVal.Status = new FhirCode <ObservationStatus>(ObservationStatus.Corrected); } // RCT var rct = model.Participations.FirstOrDefault(o => o.ParticipationRoleKey == ActParticipationKey.RecordTarget); if (rct != null) { retVal.Subject = Reference.CreateResourceReference(new Patient() { Id = rct.PlayerEntityKey.ToString() }, restOperationContext.IncomingRequest.Url); } // Performer var prf = model.Participations.FirstOrDefault(o => o.ParticipationRoleKey == ActParticipationKey.Performer); if (prf != null) { retVal.Performer = Reference.CreateResourceReference(new Practitioner() { Id = rct.PlayerEntityKey.ToString() }, restOperationContext.IncomingRequest.Url); } retVal.Issued = new FhirInstant() { DateValue = model.CreationTime.DateTime }; // Value switch (model.ValueType) { case "CD": retVal.Value = DataTypeConverter.ToFhirCodeableConcept((model as Core.Model.Acts.CodedObservation).Value); break; case "PQ": retVal.Value = new FhirQuantity() { Value = (model as Core.Model.Acts.QuantityObservation).Value, Units = DataTypeConverter.ToFhirCodeableConcept((model as Core.Model.Acts.QuantityObservation).LoadProperty <Concept>("UnitOfMeasure"), "http://hl7.org/fhir/sid/ucum").GetPrimaryCode()?.Code?.Value }; break; case "ED": case "ST": retVal.Value = new FhirString((model as Core.Model.Acts.TextObservation).Value); break; } var loc = model.LoadCollection <ActParticipation>("Participations").FirstOrDefault(o => o.ParticipationRoleKey == ActParticipationKey.Location); if (loc != null) { retVal.Extension.Add(new Extension() { Url = "http://santedb.org/extensions/act/fhir/location", Value = new FhirString(loc.PlayerEntityKey.ToString()) }); } if (model.InterpretationConceptKey.HasValue) { retVal.Interpretation = DataTypeConverter.ToFhirCodeableConcept(model.LoadProperty <Concept>("InterpretationConcept")); } return(retVal); }
/// <summary> /// Map a patient object to FHIR. /// </summary> /// <param name="model">The patient to map to FHIR</param> /// <param name="restOperationContext">The current REST operation context</param> /// <returns>Returns the mapped FHIR resource.</returns> protected override Patient MapToFhir(Core.Model.Roles.Patient model, RestOperationContext restOperationContext) { var retVal = DataTypeConverter.CreateResource <Patient>(model); retVal.Active = model.StatusConceptKey == StatusKeys.Active; retVal.Address = model.LoadCollection <EntityAddress>("Addresses").Select(o => DataTypeConverter.ToFhirAddress(o)).ToList(); retVal.BirthDate = model.DateOfBirth; retVal.Deceased = model.DeceasedDate == DateTime.MinValue ? (object)new FhirBoolean(true) : model.DeceasedDate != null ? new FhirDate(model.DeceasedDate.Value) : null; retVal.Gender = DataTypeConverter.ToFhirCodeableConcept(model.LoadProperty <Concept>("GenderConcept"), "http://hl7.org/fhir/administrative-gender")?.GetPrimaryCode()?.Code; retVal.Identifier = model.Identifiers?.Select(o => DataTypeConverter.ToFhirIdentifier(o)).ToList(); retVal.MultipleBirth = model.MultipleBirthOrder == 0 ? (FhirElement) new FhirBoolean(true) : model.MultipleBirthOrder.HasValue ? new FhirInt(model.MultipleBirthOrder.Value) : null; retVal.Name = model.LoadCollection <EntityName>("Names").Select(o => DataTypeConverter.ToFhirHumanName(o)).ToList(); retVal.Timestamp = model.ModifiedOn.DateTime; retVal.Telecom = model.LoadCollection <EntityTelecomAddress>("Telecoms").Select(o => DataTypeConverter.ToFhirTelecom(o)).ToList(); // TODO: Relationships foreach (var rel in model.LoadCollection <EntityRelationship>("Relationships").Where(o => !o.InversionIndicator)) { // Family member if (rel.LoadProperty <Concept>(nameof(EntityRelationship.RelationshipType)).ConceptSetsXml.Contains(ConceptSetKeys.FamilyMember)) { // Create the relative object var relative = DataTypeConverter.CreateResource <RelatedPerson>(rel.LoadProperty <Person>(nameof(EntityRelationship.TargetEntity))); relative.Relationship = DataTypeConverter.ToFhirCodeableConcept(rel.LoadProperty <Concept>(nameof(EntityRelationship.RelationshipType))); relative.Address = DataTypeConverter.ToFhirAddress(rel.TargetEntity.Addresses.FirstOrDefault()); relative.Gender = DataTypeConverter.ToFhirCodeableConcept((rel.TargetEntity as Core.Model.Roles.Patient)?.LoadProperty <Concept>(nameof(Core.Model.Roles.Patient.GenderConcept))); relative.Identifier = rel.TargetEntity.LoadCollection <EntityIdentifier>(nameof(Entity.Identifiers)).Select(o => DataTypeConverter.ToFhirIdentifier(o)).ToList(); relative.Name = DataTypeConverter.ToFhirHumanName(rel.TargetEntity.LoadCollection <EntityName>(nameof(Entity.Names)).FirstOrDefault()); if (rel.TargetEntity is Core.Model.Roles.Patient) { relative.Patient = DataTypeConverter.CreateReference <Patient>(rel.TargetEntity, restOperationContext); } relative.Telecom = rel.TargetEntity.LoadCollection <EntityTelecomAddress>(nameof(Entity.Telecoms)).Select(o => DataTypeConverter.ToFhirTelecom(o)).ToList(); retVal.Contained.Add(new ContainedResource() { Item = relative }); } else if (rel.RelationshipTypeKey == EntityRelationshipTypeKeys.HealthcareProvider) { retVal.Provider = DataTypeConverter.CreateReference <Practitioner>(rel.LoadProperty <Entity>(nameof(EntityRelationship.TargetEntity)), restOperationContext); } else if (rel.RelationshipTypeKey == EntityRelationshipTypeKeys.Replaces) { retVal.Link.Add(new PatientLink() { Type = PatientLinkType.Replace, Other = Reference.CreateLocalResourceReference(rel.LoadProperty <Patient>(nameof(EntityRelationship.TargetEntity))) }); } else if (rel.RelationshipTypeKey == EntityRelationshipTypeKeys.Duplicate) { retVal.Link.Add(new PatientLink() { Type = PatientLinkType.SeeAlso, Other = Reference.CreateLocalResourceReference(rel.LoadProperty <Patient>(nameof(EntityRelationship.TargetEntity))) }); } else if (rel.RelationshipTypeKey?.ToString() == "97730a52-7e30-4dcd-94cd-fd532d111578") // MDM Master Record { if (rel.SourceEntityKey != model.Key) { retVal.Link.Add(new PatientLink() // Is a master { Type = PatientLinkType.SeeAlso, Other = Reference.CreateLocalResourceReference(rel.LoadProperty <Patient>(nameof(EntityRelationship.SourceEntity))) }); } else // Is a local { retVal.Link.Add(new PatientLink() { Type = PatientLinkType.Refer, Other = Reference.CreateLocalResourceReference(rel.LoadProperty <Patient>(nameof(EntityRelationship.TargetEntity))) }); } } } var photo = model.LoadCollection <EntityExtension>("Extensions").FirstOrDefault(o => o.ExtensionTypeKey == ExtensionTypeKeys.JpegPhotoExtension); if (photo != null) { retVal.Photo = new List <Attachment>() { new Attachment() { ContentType = "image/jpg", Data = photo.ExtensionValueXml } } } ; // TODO: Links return(retVal); }
/// <summary> /// Maps the specified <paramref name="resource"/> to the model type <see cref="ManufacturedMaterial"/> /// </summary> /// <param name="resource">The model resource to be mapped</param> /// <param name="restOperationContext">The operation context this request is executing on</param> /// <returns>The converted <see cref="ManufacturedMaterial"/></returns> protected override ManufacturedMaterial MapToModel(Medication resource, RestOperationContext restOperationContext) { throw new NotImplementedException(); }
/// <summary> /// Maps a OpenIZ bundle as FHIR /// </summary> protected override SanteDB.Messaging.FHIR.Resources.Bundle MapToFhir(Core.Model.Collection.Bundle model, RestOperationContext webOperationContext) { return(new SanteDB.Messaging.FHIR.Resources.Bundle() { Type = BundleType.Collection, // TODO: Actually construct a response bundle }); }
/// <summary> /// Map adverse events to the model /// </summary> protected override Act MapToModel(AdverseEvent resource, RestOperationContext restOperationContext) { throw new NotImplementedException(); }
/// <summary> /// Map to FHIR /// </summary> protected override SanteDB.Messaging.FHIR.Resources.Organization MapToFhir(Core.Model.Entities.Organization model, RestOperationContext webOperationContext) { return(DataTypeConverter.CreateResource <SanteDB.Messaging.FHIR.Resources.Organization>(model)); }
/// <summary> /// Map the specified patient encounter to a FHIR based encounter /// </summary> protected override Encounter MapToFhir(PatientEncounter model, RestOperationContext restOperationContext) { var retVal = DataTypeConverter.CreateResource <Encounter>(model); // Map the identifier retVal.Identifier = model.LoadCollection <ActIdentifier>("Identifiers").Select(o => DataTypeConverter.ToFhirIdentifier <Act>(o)).ToList(); // Map status keys switch (model.StatusConceptKey.ToString().ToUpper()) { case StatusKeyStrings.Active: retVal.Status = EncounterStatus.InProgress; break; case StatusKeyStrings.Cancelled: case StatusKeyStrings.Nullified: retVal.Status = EncounterStatus.Cancelled; break; case StatusKeyStrings.Completed: retVal.Status = EncounterStatus.Finished; break; } if (model.StartTime.HasValue || model.StopTime.HasValue) { retVal.Period = new FhirPeriod() { Start = model.StartTime?.DateTime, Stop = model.StopTime?.DateTime } } ; else { retVal.Period = new FhirPeriod() { Start = model.ActTime.DateTime, Stop = model.ActTime.DateTime } }; retVal.Reason = DataTypeConverter.ToFhirCodeableConcept(model.LoadProperty <Concept>("ReasonConcept")); retVal.Type = DataTypeConverter.ToFhirCodeableConcept(model.LoadProperty <Concept>("TypeConcept")); // Map associated var associated = model.LoadCollection <ActParticipation>("Participations"); // Subject of encounter retVal.Subject = DataTypeConverter.CreateReference <SanteDB.Messaging.FHIR.Resources.Patient>(associated.FirstOrDefault(o => o.ParticipationRoleKey == ActParticipationKey.RecordTarget)?.LoadProperty <Entity>("PlayerEntity"), restOperationContext); // Locations retVal.Location = associated.Where(o => o.LoadProperty <Entity>("PlayerEntity") is Place).Select(o => new EncounterLocation() { Period = new FhirPeriod() { Start = model.CreationTime.DateTime }, Location = DataTypeConverter.CreateReference <Location>(o.PlayerEntity, restOperationContext) }).ToList(); // Service provider var cst = associated.FirstOrDefault(o => o.LoadProperty <Entity>("PlayerEntity") is Core.Model.Entities.Organization && o.ParticipationRoleKey == ActParticipationKey.Custodian); if (cst != null) { retVal.ServiceProvider = DataTypeConverter.CreateReference <SanteDB.Messaging.FHIR.Resources.Organization>(cst.PlayerEntity, restOperationContext); } // Participants retVal.Participant = associated.Where(o => o.LoadProperty <Entity>("PlayerEntity") is Provider || o.LoadProperty <Entity>("PlayerEntity") is UserEntity).Select(o => new EncounterParticipant() { Period = new FhirPeriod() { Start = model.CreationTime.DateTime }, Type = new List <FhirCodeableConcept>() { DataTypeConverter.ToFhirCodeableConcept(o.LoadProperty <Concept>("ParticipationRole")) }, Individual = DataTypeConverter.CreateReference <Practitioner>(o.PlayerEntity, restOperationContext) }).ToList(); return(retVal); }
/// <summary> /// Maps a model instance to a FHIR instance. /// </summary> /// <param name="model">The model.</param> /// <param name="restOperationContext">The operation context the method is being called on</param> /// <returns>Returns the mapped FHIR resource.</returns> protected abstract TFhirResource MapToFhir(TModel model, RestOperationContext restOperationContext);
/// <summary> /// Map to FHIR /// </summary> protected override Condition MapToFhir(CodedObservation model, RestOperationContext restOperationContext) { var retVal = DataTypeConverter.CreateResource <Condition>(model); retVal.Identifier = model.LoadCollection <ActIdentifier>("Identifiers").Select(o => DataTypeConverter.ToFhirIdentifier <Act>(o)).ToList(); // Clinical status of the condition if (model.StatusConceptKey == StatusKeys.Active) { retVal.ClinicalStatus = ConditionClinicalStatus.Active; } else if (model.StatusConceptKey == StatusKeys.Completed) { retVal.ClinicalStatus = ConditionClinicalStatus.Resolved; } else if (model.StatusConceptKey == StatusKeys.Nullified) { retVal.VerificationStatus = ConditionVerificationStatus.EnteredInError; } else if (model.StatusConceptKey == StatusKeys.Obsolete) { retVal.ClinicalStatus = ConditionClinicalStatus.Inactive; } // Category retVal.Category.Add(new SanteDB.Messaging.FHIR.DataTypes.FhirCodeableConcept(new Uri("http://hl7.org/fhir/condition-category"), "encounter-diagnosis")); // Severity? var actRelationshipService = ApplicationServiceContext.Current.GetService <IDataPersistenceService <ActRelationship> >(); var severity = actRelationshipService.Query(o => o.SourceEntityKey == model.Key && o.RelationshipTypeKey == ActRelationshipTypeKeys.HasComponent && o.TargetAct.TypeConceptKey == ObservationTypeKeys.Severity, AuthenticationContext.Current.Principal); if (severity == null) // Perhaps we should get from neighbor if this is in an encounter { var contextAct = actRelationshipService.Query(o => o.TargetActKey == model.Key, AuthenticationContext.Current.Principal).FirstOrDefault(); if (contextAct != null) { severity = actRelationshipService.Query(o => o.SourceEntityKey == contextAct.SourceEntityKey && o.RelationshipTypeKey == ActRelationshipTypeKeys.HasComponent && o.TargetAct.TypeConceptKey == ObservationTypeKeys.Severity, AuthenticationContext.Current.Principal); } } // Severity if (severity != null) { retVal.Severity = DataTypeConverter.ToFhirCodeableConcept((severity as CodedObservation).LoadProperty <Concept>("Value")); } retVal.Code = DataTypeConverter.ToFhirCodeableConcept(model.LoadProperty <Concept>("Value")); // body sites? var sites = actRelationshipService.Query(o => o.SourceEntityKey == model.Key && o.RelationshipTypeKey == ActRelationshipTypeKeys.HasComponent && o.TargetAct.TypeConceptKey == ObservationTypeKeys.FindingSite, AuthenticationContext.Current.Principal); retVal.BodySite = sites.Select(o => DataTypeConverter.ToFhirCodeableConcept(o.LoadProperty <CodedObservation>("TargetAct").LoadProperty <Concept>("Value"))).ToList(); // Subject var recordTarget = model.LoadCollection <ActParticipation>("Participations").FirstOrDefault(o => o.ParticipationRoleKey == ActParticipationKey.RecordTarget); if (recordTarget != null) { this.traceSource.TraceInfo("RCT: {0}", recordTarget.PlayerEntityKey); retVal.Subject = DataTypeConverter.CreateReference <Patient>(recordTarget.LoadProperty <Entity>("PlayerEntity"), restOperationContext); } // Onset if (model.StartTime.HasValue || model.StopTime.HasValue) { retVal.Onset = new FhirPeriod() { Start = model.StartTime?.DateTime, Stop = model.StopTime?.DateTime } } ; else { retVal.Onset = new FhirDateTime(model.ActTime.DateTime); } retVal.AssertionDate = model.CreationTime.LocalDateTime; var author = model.LoadCollection <ActParticipation>("Participations").FirstOrDefault(o => o.ParticipationRoleKey == ActParticipationKey.Authororiginator); if (author != null) { retVal.Asserter = DataTypeConverter.CreatePlainReference <Practitioner>(author.LoadProperty <Entity>("PlayerEntity"), restOperationContext); } return(retVal); }
/// <summary> /// Maps a FHIR condition to a model /// </summary> /// <param name="resource">The FHIR condition to be mapped</param> /// <param name="restOperationContext">The REST operation context under which this method is called</param> /// <returns>The constructed model instance</returns> protected override CodedObservation MapToModel(Condition resource, RestOperationContext restOperationContext) { throw new NotImplementedException(); }
/// <summary> /// Map allergy intolerance from FHIR to a coded observation /// </summary> protected override CodedObservation MapToModel(AllergyIntolerance resource, RestOperationContext restOperationContext) { throw new NotImplementedException(); }
/// <summary> /// Map coded allergy intolerance resource to FHIR /// </summary> protected override AllergyIntolerance MapToFhir(CodedObservation model, RestOperationContext restOperationContext) { throw new NotImplementedException(); }
/// <summary> /// Maps the substance administration to FHIR. /// </summary> /// <param name="model">The model.</param> /// <param name="restOperationContext">The operation context in which this method is being called</param> /// <returns>Returns the mapped FHIR resource.</returns> protected override Immunization MapToFhir(SubstanceAdministration model, RestOperationContext restOperationContext) { var retVal = DataTypeConverter.CreateResource <Immunization>(model); retVal.DoseQuantity = new FhirQuantity() { Units = DataTypeConverter.ToFhirCodeableConcept(model.LoadProperty <Concept>("DoseUnit"), "http://hl7.org/fhir/sid/ucum").GetPrimaryCode()?.Code?.Value, Value = new FhirDecimal(model.DoseQuantity) }; retVal.Date = (FhirDate)model.ActTime.DateTime; retVal.Route = DataTypeConverter.ToFhirCodeableConcept(model.LoadProperty <Concept>(nameof(SubstanceAdministration.Route))); retVal.Site = DataTypeConverter.ToFhirCodeableConcept(model.LoadProperty <Concept>(nameof(SubstanceAdministration.Site))); retVal.Status = "completed"; //retVal.SelfReported = model.Tags.Any(o => o.TagKey == "selfReported" && Convert.ToBoolean(o.Value)); retVal.WasNotGiven = model.IsNegated; // Material var matPtcpt = model.Participations.FirstOrDefault(o => o.ParticipationRoleKey == ActParticipationKey.Consumable) ?? model.Participations.FirstOrDefault(o => o.ParticipationRoleKey == ActParticipationKey.Product); if (matPtcpt != null) { var matl = matPtcpt.LoadProperty <Material>(nameof(ActParticipation.PlayerEntity)); retVal.VaccineCode = DataTypeConverter.ToFhirCodeableConcept(matl.LoadProperty <Concept>(nameof(Act.TypeConcept))); retVal.ExpirationDate = matl.ExpiryDate.HasValue ? (FhirDate)matl.ExpiryDate : null; retVal.LotNumber = (matl as ManufacturedMaterial)?.LotNumber; } else { retVal.ExpirationDate = null; } // RCT var rct = model.Participations.FirstOrDefault(o => o.ParticipationRoleKey == ActParticipationKey.RecordTarget); if (rct != null) { retVal.Patient = DataTypeConverter.CreateReference <Patient>(rct.LoadProperty <Entity>("PlayerEntity"), restOperationContext); } // Performer var prf = model.Participations.FirstOrDefault(o => o.ParticipationRoleKey == ActParticipationKey.Performer); if (prf != null) { retVal.Performer = DataTypeConverter.CreateReference <Practitioner>(rct.LoadProperty <Entity>("PlayerEntity"), restOperationContext); } // Protocol foreach (var itm in model.Protocols) { ImmunizationProtocol protocol = new ImmunizationProtocol(); var dbProtocol = itm.LoadProperty <Protocol>(nameof(ActProtocol.Protocol)); protocol.DoseSequence = new FhirInt((int)model.SequenceId); // Protocol lookup protocol.Series = dbProtocol?.Name; retVal.VaccinationProtocol.Add(protocol); } if (retVal.VaccinationProtocol.Count == 0) { retVal.VaccinationProtocol.Add(new ImmunizationProtocol() { DoseSequence = (int)model.SequenceId }); } var loc = model.Participations.FirstOrDefault(o => o.ParticipationRoleKey == ActParticipationKey.Location); if (loc != null) { retVal.Extension.Add(new Extension() { Url = "http://santedb.org/extensions/act/fhir/location", Value = new FhirString(loc.PlayerEntityKey.ToString()) }); } return(retVal); }
/// <summary> /// Map an immunization FHIR resource to a substance administration. /// </summary> /// <param name="resource">The resource.</param> /// <param name="restOperationContext">The operation context in which this method is being called</param> /// <returns>Returns the mapped model.</returns> protected override SubstanceAdministration MapToModel(Immunization resource, RestOperationContext restOperationContext) { var substanceAdministration = new SubstanceAdministration { ActTime = resource.Date.DateValue.Value, DoseQuantity = resource.DoseQuantity?.Value.Value ?? 0, DoseUnit = resource.DoseQuantity != null?DataTypeConverter.ToConcept <String>(resource.DoseQuantity.Units.Value, "http://hl7.org/fhir/sid/ucum") : null, Extensions = resource.Extension?.Select(DataTypeConverter.ToActExtension).ToList(), Identifiers = resource.Identifier?.Select(DataTypeConverter.ToActIdentifier).ToList(), Key = Guid.NewGuid(), MoodConceptKey = ActMoodKeys.Eventoccurrence, StatusConceptKey = resource.Status == "completed" ? StatusKeys.Completed : StatusKeys.Nullified, RouteKey = DataTypeConverter.ToConcept(resource.Route)?.Key, SiteKey = DataTypeConverter.ToConcept(resource.Site)?.Key, }; Guid key; if (Guid.TryParse(resource.Id, out key)) { substanceAdministration.Key = key; } // Was not given if (resource.WasNotGiven?.Value == true) { substanceAdministration.IsNegated = true; } // Patient if (resource.Patient != null) { // Is the subject a uuid if (resource.Patient.ReferenceUrl.Value.StartsWith("urn:uuid:")) { substanceAdministration.Participations.Add(new ActParticipation(ActParticipationKey.RecordTarget, Guid.Parse(resource.Patient.ReferenceUrl.Value.Substring(9)))); } else { throw new NotSupportedException("Only UUID references are supported"); } } // Encounter if (resource.Encounter != null) { // Is the subject a uuid if (resource.Encounter.ReferenceUrl.Value.StartsWith("urn:uuid:")) { substanceAdministration.Relationships.Add(new ActRelationship(ActRelationshipTypeKeys.HasComponent, substanceAdministration.Key) { SourceEntityKey = Guid.Parse(resource.Encounter.ReferenceUrl.Value.Substring(9)) }); } else { throw new NotSupportedException("Only UUID references are supported"); } } // Find the material that was issued if (resource.VaccineCode != null) { var concept = DataTypeConverter.ToConcept(resource.VaccineCode); if (concept == null) { this.traceSource.TraceWarning("Ignoring administration {0} don't have concept mapped", resource.VaccineCode); return(null); } // Get the material int t = 0; var material = ApplicationServiceContext.Current.GetService <IRepositoryService <Material> >().Find(m => m.TypeConceptKey == concept.Key, 0, 1, out t).FirstOrDefault(); if (material == null) { this.traceSource.TraceWarning("Ignoring administration {0} don't have material registered for {1}", resource.VaccineCode, concept?.Mnemonic); return(null); } else { substanceAdministration.Participations.Add(new ActParticipation(ActParticipationKey.Product, material.Key)); if (resource.LotNumber != null) { // TODO: Need to also find where the GTIN is kept var mmaterial = ApplicationServiceContext.Current.GetService <IRepositoryService <ManufacturedMaterial> >().Find(o => o.LotNumber == resource.LotNumber && o.Relationships.Any(r => r.SourceEntityKey == material.Key && r.RelationshipTypeKey == EntityRelationshipTypeKeys.Instance)); substanceAdministration.Participations.Add(new ActParticipation(ActParticipationKey.Consumable, material.Key) { Quantity = 1 }); } // Get dose units if (substanceAdministration.DoseQuantity == 0) { substanceAdministration.DoseQuantity = 1; substanceAdministration.DoseUnitKey = material.QuantityConceptKey; } } } return(substanceAdministration); }
/// <summary> /// Map to model the encounter /// </summary> protected override PatientEncounter MapToModel(Encounter resource, RestOperationContext webOperationContext) { // Organization var status = resource.Status?.Value; var retVal = new PatientEncounter() { TypeConcept = DataTypeConverter.ToConcept(resource.Class, new Uri("http://openiz.org/conceptset/v3-ActEncounterCode")), StartTime = resource.Period?.Start?.DateValue, StopTime = resource.Period?.Stop?.DateValue, // TODO: Extensions Extensions = resource.Extension.Select(DataTypeConverter.ToActExtension).OfType <ActExtension>().ToList(), Identifiers = resource.Identifier.Select(DataTypeConverter.ToActIdentifier).ToList(), Key = Guid.NewGuid(), StatusConceptKey = status == EncounterStatus.Finished ? StatusKeys.Completed : status == EncounterStatus.Cancelled ? StatusKeys.Cancelled : status == EncounterStatus.InProgress || status == EncounterStatus.Arrived ? StatusKeys.Active : status == EncounterStatus.Planned ? StatusKeys.Active : StatusKeys.Obsolete, MoodConceptKey = status == EncounterStatus.Planned ? ActMoodKeys.Intent : ActMoodKeys.Eventoccurrence, ReasonConcept = DataTypeConverter.ToConcept(resource.Reason) }; // Parse key Guid key; if (!Guid.TryParse(resource.Id, out key)) { key = Guid.NewGuid(); } retVal.Key = key; // Attempt to resolve relationships if (resource.Subject != null) { // Is the subject a uuid if (resource.Subject.ReferenceUrl.Value.StartsWith("urn:uuid:")) { retVal.Participations.Add(new ActParticipation(ActParticipationKey.RecordTarget, Guid.Parse(resource.Subject.ReferenceUrl.Value.Substring(9)))); } else { throw new NotSupportedException("Only UUID references are supported"); } } // Attempt to resolve organiztaion if (resource.ServiceProvider != null) { // Is the subject a uuid if (resource.ServiceProvider.ReferenceUrl.Value.StartsWith("urn:uuid:")) { retVal.Participations.Add(new ActParticipation(ActParticipationKey.Custodian, Guid.Parse(resource.ServiceProvider.ReferenceUrl.Value.Substring(9)))); } else { throw new NotSupportedException("Only UUID references are supported"); } } // TODO : Other Participations return(retVal); }
/// <summary> /// Map to model /// </summary> public IdentifiedData MapToModel(BundleEntry bundleResource, RestOperationContext context, Bundle bundle) { return(this.MapToModel(bundleResource.Resource.Resource as Encounter, context)); }
/// <summary> /// Maps a FHIR resource to a model instance. /// </summary> /// <param name="resource">The resource.</param> /// <param name="restOperationContext">The operation context on which the operation is being called.</param> /// <returns>Returns the mapped model.</returns> protected abstract TModel MapToModel(TFhirResource resource, RestOperationContext restOperationContext);
/// <summary> /// Map to model /// </summary> public IdentifiedData MapToModel(BundleEntry bundleResource, RestOperationContext context, Bundle bundle) { return(this.MapToModel(bundleResource.Resource.Resource as SanteDB.Messaging.FHIR.Resources.Organization, context)); }
/// <summary> /// Map a practitioner to a user entity /// </summary> protected override UserEntity MapToModel(Practitioner resource, RestOperationContext restOperationContext) { throw new NotImplementedException(); }
/// <summary> /// Map to Model /// </summary> protected override Core.Model.Entities.Organization MapToModel(SanteDB.Messaging.FHIR.Resources.Organization resource, RestOperationContext webOperationContext) { // Organization var retVal = new Core.Model.Entities.Organization() { TypeConcept = DataTypeConverter.ToConcept(resource.Type), Addresses = resource.Address.Select(DataTypeConverter.ToEntityAddress).ToList(), CreationTime = DateTimeOffset.Now, // TODO: Extensions Extensions = resource.Extension.Select(DataTypeConverter.ToEntityExtension).OfType <EntityExtension>().ToList(), Identifiers = resource.Identifier.Select(DataTypeConverter.ToEntityIdentifier).ToList(), Key = Guid.NewGuid(), Names = new List <EntityName>() { new EntityName(NameUseKeys.OfficialRecord, resource.Name) }, StatusConceptKey = resource.Active?.Value == true ? StatusKeys.Active : StatusKeys.Obsolete, Telecoms = resource.Telecom.Select(DataTypeConverter.ToEntityTelecomAddress).ToList() }; Guid key; if (!Guid.TryParse(resource.Id, out key)) { key = Guid.NewGuid(); } retVal.Key = key; return(retVal); }
/// <summary> /// Maps a FHIR resource to a model instance. /// </summary> /// <param name="resource">The resource.</param> /// <returns>Returns the mapped model.</returns> /// <exception cref="System.NotImplementedException"></exception> protected override SubstanceAdministration MapToModel(ImmunizationRecommendation resource, RestOperationContext restOperationContext) { throw new NotImplementedException(); }
/// <summary> /// Maps the specified act to an adverse event /// </summary> protected override AdverseEvent MapToFhir(Act model, RestOperationContext restOperationContext) { var retVal = DataTypeConverter.CreateResource <AdverseEvent>(model); retVal.Identifier = DataTypeConverter.ToFhirIdentifier <Act>(model.Identifiers.FirstOrDefault()); retVal.Category = AdverseEventCategory.AdverseEvent; retVal.Type = DataTypeConverter.ToFhirCodeableConcept(model.LoadProperty <Concept>("TypeConcept")); var recordTarget = model.LoadCollection <ActParticipation>("Participations").FirstOrDefault(o => o.ParticipationRoleKey == ActParticipationKey.RecordTarget); if (recordTarget != null) { retVal.Subject = DataTypeConverter.CreateReference <Patient>(recordTarget.LoadProperty <Entity>("PlayerEntity"), restOperationContext); } // Main topic of the concern var subject = model.LoadCollection <ActRelationship>("Relationships").FirstOrDefault(o => o.RelationshipTypeKey == ActRelationshipTypeKeys.HasSubject)?.LoadProperty <Act>("TargetAct"); if (subject == null) { throw new InvalidOperationException("This act does not appear to be an adverse event"); } retVal.Date = subject.ActTime.DateTime; // Reactions = HasManifestation var reactions = subject.LoadCollection <ActRelationship>("Relationships").Where(o => o.RelationshipTypeKey == ActRelationshipTypeKeys.HasManifestation); retVal.Reaction = reactions.Select(o => DataTypeConverter.CreateReference <Condition>(o.LoadProperty <Act>("TargetAct"), restOperationContext)).ToList(); var location = model.LoadCollection <ActParticipation>("Participations").FirstOrDefault(o => o.ParticipationRoleKey == ActParticipationKey.Location); if (location != null) { retVal.Location = DataTypeConverter.CreateReference <Location>(location.LoadProperty <Entity>("PlayerEntity"), restOperationContext); } // Severity var severity = subject.LoadCollection <ActRelationship>("Relationships").First(o => o.RelationshipTypeKey == ActRelationshipTypeKeys.HasComponent && o.LoadProperty <Act>("TargetAct").TypeConceptKey == ObservationTypeKeys.Severity); if (severity != null) { retVal.Seriousness = DataTypeConverter.ToFhirCodeableConcept(severity.LoadProperty <CodedObservation>("TargetAct").Value, "http://hl7.org/fhir/adverse-event-seriousness"); } // Did the patient die? var causeOfDeath = model.LoadCollection <ActRelationship>("Relationships").FirstOrDefault(o => o.RelationshipTypeKey == ActRelationshipTypeKeys.IsCauseOf && o.LoadProperty <Act>("TargetAct").TypeConceptKey == ObservationTypeKeys.ClinicalState && (o.TargetAct as CodedObservation)?.ValueKey == Guid.Parse("6df3720b-857f-4ba2-826f-b7f1d3c3adbb")); if (causeOfDeath != null) { retVal.Outcome = new SanteDB.Messaging.FHIR.DataTypes.FhirCodeableConcept(new Uri("http://hl7.org/fhir/adverse-event-outcome"), "fatal"); } else if (model.StatusConceptKey == StatusKeys.Active) { retVal.Outcome = new SanteDB.Messaging.FHIR.DataTypes.FhirCodeableConcept(new Uri("http://hl7.org/fhir/adverse-event-outcome"), "ongoing"); } else if (model.StatusConceptKey == StatusKeys.Completed) { retVal.Outcome = new SanteDB.Messaging.FHIR.DataTypes.FhirCodeableConcept(new Uri("http://hl7.org/fhir/adverse-event-outcome"), "resolved"); } var author = model.LoadCollection <ActParticipation>("Participations").FirstOrDefault(o => o.ParticipationRoleKey == ActParticipationKey.Authororiginator); if (author != null) { retVal.Recorder = DataTypeConverter.CreatePlainReference <Practitioner>(author.LoadProperty <Entity>("PlayerEntity"), restOperationContext); } // Suspect entities var refersTo = model.LoadCollection <ActRelationship>("Relationships").Where(o => o.RelationshipTypeKey == ActRelationshipTypeKeys.RefersTo); if (refersTo.Count() > 0) { retVal.SuspectEntity = refersTo.Select(o => o.LoadProperty <Act>("TargetAct")).OfType <SubstanceAdministration>().Select(o => { var consumable = o.LoadCollection <ActParticipation>("Participations").FirstOrDefault(x => x.ParticipationRoleKey == ActParticipationKey.Consumable)?.LoadProperty <ManufacturedMaterial>("PlayerEntity"); if (consumable == null) { var product = o.LoadCollection <ActParticipation>("Participations").FirstOrDefault(x => x.ParticipationRoleKey == ActParticipationKey.Product)?.LoadProperty <Material>("PlayerEntity"); return(new AdverseEventSuspectEntity() { Instance = DataTypeConverter.CreatePlainReference <Substance>(product, restOperationContext) }); } else { return new AdverseEventSuspectEntity() { Instance = DataTypeConverter.CreatePlainReference <Medication>(consumable, restOperationContext) } }; }).ToList(); } return(retVal); }
/// <summary> /// Maps the outbound resource to FHIR. /// </summary> /// <param name="model">The model.</param> /// <returns>Returns the mapped FHIR resource.</returns> protected override ImmunizationRecommendation MapToFhir(SubstanceAdministration model, RestOperationContext restOperationContext) { ImmunizationRecommendation retVal = new ImmunizationRecommendation(); retVal.Id = model.Key.ToString(); retVal.Timestamp = DateTime.Now; retVal.Identifier = model.Identifiers.Select(o => DataTypeConverter.ToFhirIdentifier(o)).ToList(); var rct = model.Participations.FirstOrDefault(o => o.ParticipationRoleKey == ActParticipationKey.RecordTarget).PlayerEntity; if (rct != null) { retVal.Patient = Reference.CreateResourceReference(new Patient() { Id = model.Key.ToString(), VersionId = model.VersionKey.ToString() }, RestOperationContext.Current.IncomingRequest.Url); } var mat = model.Participations.FirstOrDefault(o => o.ParticipationRoleKey == ActParticipationKey.Product).PlayerEntity; // Recommend string status = (model.StopTime ?? model.ActTime) < DateTimeOffset.Now ? "overdue" : "due"; var recommendation = new SanteDB.Messaging.FHIR.Backbone.ImmunizationRecommendation() { Date = model.CreationTime.DateTime, DoseNumber = model.SequenceId, VaccineCode = DataTypeConverter.ToFhirCodeableConcept(mat?.TypeConcept), ForecastStatus = new FhirCodeableConcept(new Uri("http://hl7.org/fhir/conceptset/immunization-recommendation-status"), status), DateCriterion = new List <SanteDB.Messaging.FHIR.Backbone.ImmunizationRecommendationDateCriterion>() { new SanteDB.Messaging.FHIR.Backbone.ImmunizationRecommendationDateCriterion() { Code = new FhirCodeableConcept(new Uri("http://hl7.org/fhir/conceptset/immunization-recommendation-date-criterion"), "recommended"), Value = model.ActTime.DateTime } } }; if (model.StartTime.HasValue) { recommendation.DateCriterion.Add(new SanteDB.Messaging.FHIR.Backbone.ImmunizationRecommendationDateCriterion() { Code = new FhirCodeableConcept(new Uri("http://hl7.org/fhir/conceptset/immunization-recommendation-date-criterion"), "earliest"), Value = model.StartTime.Value.DateTime }); } if (model.StopTime.HasValue) { recommendation.DateCriterion.Add(new SanteDB.Messaging.FHIR.Backbone.ImmunizationRecommendationDateCriterion() { Code = new FhirCodeableConcept(new Uri("http://hl7.org/fhir/conceptset/immunization-recommendation-date-criterion"), "overdue"), Value = model.StopTime.Value.DateTime }); } retVal.Recommendation = new List <SanteDB.Messaging.FHIR.Backbone.ImmunizationRecommendation>() { recommendation }; return(retVal); }
/// <summary> /// Map FHIR resource to our bundle /// </summary> protected override Core.Model.Collection.Bundle MapToModel(SanteDB.Messaging.FHIR.Resources.Bundle resource, RestOperationContext webOperationContext) { var retVal = new Core.Model.Collection.Bundle(); foreach (var entry in resource.Entry) { var entryType = entry.Resource.Resource?.GetType(); if (entryType == null) { continue; } var handler = FhirResourceHandlerUtil.GetResourceHandler(entryType.GetCustomAttribute <XmlRootAttribute>().ElementName) as IBundleResourceHandler; if (handler == null) { this.traceSource.TraceWarning("Can't find bundle handler for {0}...", entryType.Name); continue; } retVal.Add(handler.MapToModel(entry, webOperationContext, resource)); } retVal.Item.RemoveAll(o => o == null); return(retVal); }
/// <summary> /// Creates a FHIR reference. /// </summary> /// <typeparam name="TResource">The type of the t resource.</typeparam> /// <param name="targetEntity">The target entity.</param> /// <returns>Returns a reference instance.</returns> public static Reference <TResource> CreateReference <TResource>(IVersionedEntity targetEntity, RestOperationContext context) where TResource : DomainResourceBase, new() { if (targetEntity == null) { throw new ArgumentNullException(nameof(targetEntity)); } else if (context == null) { throw new ArgumentNullException(nameof(context)); } var refer = Reference.CreateResourceReference(DataTypeConverter.CreateResource <TResource>(targetEntity), context.IncomingRequest.Url); refer.Display = (targetEntity as Entity)?.Names?.FirstOrDefault()?.ToString(); return(refer); }
/// <summary> /// Map the incoming FHIR reosurce to a MODEL resource /// </summary> /// <param name="resource">The resource to be mapped</param> /// <param name="restOperationContext">The operation context under which this method is being called</param> /// <returns></returns> protected override Place MapToModel(Location resource, RestOperationContext restOperationContext) { throw new NotImplementedException(); }
/// <summary> /// Creates a FHIR reference. /// </summary> /// <typeparam name="TResource">The type of the t resource.</typeparam> /// <param name="targetEntity">The target entity.</param> /// <returns>Returns a reference instance.</returns> public static Reference CreatePlainReference <TResource>(IVersionedEntity targetEntity, RestOperationContext context) where TResource : DomainResourceBase, new() { var refer = Reference.CreateResourceReference((DomainResourceBase)DataTypeConverter.CreateResource <TResource>(targetEntity), context.IncomingRequest.Url); refer.Display = (targetEntity as Entity)?.Names?.FirstOrDefault()?.ToString(); return(refer); }
/// <summary> /// Maps a FHIR based resource to a model based resource /// </summary> /// <param name="resource">The resource to be mapped</param> /// <param name="restOperationContext">The operation context under which this method is being called</param> /// <returns>The mapped material</returns> protected override Material MapToModel(Substance resource, RestOperationContext restOperationContext) { throw new NotImplementedException(); }
/// <summary> /// Map to model /// </summary> protected override Core.Model.Acts.Observation MapToModel(SanteDB.Messaging.FHIR.Resources.Observation resource, RestOperationContext restOperationContext) { throw new NotImplementedException(); }