package edu.gatech.i3l.fhir.dstu2.entities;
import static ca.uhn.fhir.model.dstu2.resource.Procedure.SP_ENCOUNTER;
import static ca.uhn.fhir.model.dstu2.resource.Procedure.SP_PATIENT;
import java.util.Date;
import javax.persistence.Access;
import javax.persistence.AccessType;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.validation.constraints.NotNull;
import ca.uhn.fhir.context.FhirVersionEnum;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.dstu2.composite.CodeableConceptDt;
import ca.uhn.fhir.model.dstu2.composite.CodingDt;
import ca.uhn.fhir.model.dstu2.composite.ResourceReferenceDt;
import ca.uhn.fhir.model.dstu2.resource.Procedure;
import ca.uhn.fhir.model.dstu2.valueset.ProcedureStatusEnum;
import ca.uhn.fhir.model.primitive.DateTimeDt;
import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.model.primitive.InstantDt;
import edu.gatech.i3l.fhir.jpa.entity.BaseResourceEntity;
import edu.gatech.i3l.fhir.jpa.entity.IResourceEntity;
@Entity
@Table(name = "procedure_occurrence")
public class ProcedureOccurrence extends BaseResourceEntity {
private static final String RES_TYPE = "Procedure";
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "procedure_occurrence_id")
@Access(AccessType.PROPERTY)
private Long id;
@ManyToOne(cascade = CascadeType.MERGE)
@JoinColumn(name = "person_id", nullable = false)
@NotNull
private PersonComplement person;
@ManyToOne(cascade = CascadeType.MERGE)
@JoinColumn(name = "procedure_concept_id")
private Concept procedureConcept;
@Column(name = "procedure_date", nullable = false)
@Temporal(TemporalType.DATE)
@NotNull
private Date date;
@ManyToOne(cascade = { CascadeType.MERGE })
@JoinColumn(name = "procedure_type_concept_id")
private Concept procedureTypeConcept;
@ManyToOne
@JoinColumn(name = "modifier_concept_id")
private Concept modifierConcept;
@Column(name="quantity")
private Long quantity;
@ManyToOne // (cascade = { CascadeType.MERGE }, fetch = FetchType.LAZY)
@JoinColumn(name = "provider_id")
private Provider provider;
@ManyToOne
@JoinColumn(name = "visit_occurrence_id")
private VisitOccurrence visitOccurrence;
@Column(name = "procedure_source_value")
private String procedureSourceValue;
@ManyToOne
@JoinColumn(name = "procedure_source_concept_id")
private Concept procedureSourceConcept;
@Column(name = "qualifier_source_value")
private String qualifierSourceValue;
public ProcedureOccurrence() {
super();
}
public ProcedureOccurrence(Long id, PersonComplement person, Concept procedureConcept, Date date, Concept procedureTypeConcept,
Concept modifierConcept, Long quantity, Provider provider, VisitOccurrence visitOccurrence,
String procedureSourceValue, Concept procedureSourceConcept, String qualifierSourceValue) {
super();
this.id = id;
this.person = person;
this.procedureConcept = procedureConcept;
this.date = date;
this.procedureTypeConcept = procedureTypeConcept;
this.modifierConcept = modifierConcept;
this.quantity = quantity;
this.provider = provider;
this.visitOccurrence = visitOccurrence;
this.procedureSourceValue = procedureSourceValue;
this.procedureSourceConcept = procedureSourceConcept;
this.qualifierSourceValue = qualifierSourceValue;
}
@Override
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public PersonComplement getPerson() {
return person;
}
public void setPerson(PersonComplement person) {
this.person = person;
}
public Concept getProcedureConcept() {
return procedureConcept;
}
public void setProcedureConcept(Concept procedureConcept) {
this.procedureConcept = procedureConcept;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
public Concept getProcedureTypeConcept() {
return procedureTypeConcept;
}
public void setProcedureTypeConcept(Concept procedureTypeConcept) {
this.procedureTypeConcept = procedureTypeConcept;
}
public Concept getModifierConcept() {
return modifierConcept;
}
public void setModifierConcept(Concept modifierConcept) {
this.modifierConcept = modifierConcept;
}
public Long getQuantity() {
return quantity;
}
public void setQuantity(Long quantity) {
this.quantity = quantity;
}
public Provider getProvider() {
return provider;
}
public void setProvider(Provider provider) {
this.provider = provider;
}
public VisitOccurrence getVisitOccurrence() {
return visitOccurrence;
}
public void setVisitOccurrence(VisitOccurrence visitOccurrence) {
this.visitOccurrence = visitOccurrence;
}
public String getProcedureSourceValue() {
return procedureSourceValue;
}
public void setProcedureSourceValue(String procedureSourceValue) {
this.procedureSourceValue = procedureSourceValue;
}
public Concept getProcedureSourceConcept() {
return procedureSourceConcept;
}
public void setProcedureSourceConcept(Concept procedureSourceConcept) {
this.procedureSourceConcept = procedureSourceConcept;
}
public String getQualifierSourceValue() {
return qualifierSourceValue;
}
public void setQualifierSourceValue(String qualifierSourceValue) {
this.qualifierSourceValue = qualifierSourceValue;
}
@Override
public FhirVersionEnum getFhirVersion() {
// TODO Auto-generated method stub
return FhirVersionEnum.DSTU2;
}
@Override
public String getResourceType() {
return RES_TYPE;
}
@Override
public InstantDt getUpdated() {
// TODO Auto-generated method stub
return null;
}
@Override
public String translateSearchParam(String theSearchParam) {
switch (theSearchParam) {
case SP_PATIENT:
return "person";
case SP_ENCOUNTER:
return "visitOccurrence";
default:
break;
}
return theSearchParam;
}
@Override
public IResource getRelatedResource() {
Procedure procedure = new Procedure();
procedure.setId(this.getIdDt());
// Set patient
ResourceReferenceDt patientReference = new ResourceReferenceDt(new IdDt(person.getResourceType(), person.getId()));
String patientName = "";
if (person.getGivenName1() != null && !person.getGivenName1().isEmpty()) {
patientName = person.getGivenName1();
}
if (person.getGivenName2() != null && !person.getGivenName2().isEmpty()) {
patientName += " "+person.getGivenName2();
}
if (person.getFamilyName() != null && !person.getFamilyName().isEmpty()) {
patientName += " "+person.getFamilyName();
}
patientReference.setDisplay(patientName);
procedure.setSubject(patientReference);
//TODO: revisit this. For now just set to in-progress
procedure.setStatus(ProcedureStatusEnum.IN_PROGRESS);
String theSystem = procedureConcept.getVocabulary().getSystemUri();
String theCode = procedureConcept.getConceptCode();
CodeableConceptDt procedureCodeConcept = new CodeableConceptDt();
if (theSystem != "") {
// Create coding here. We have one coding in this condition as OMOP
// allows one coding concept per condition.
// In the future, if we want to allow multiple coding concepts here,
// we need to do it here.
CodingDt coding = new CodingDt(theSystem, theCode);
coding.setDisplay(procedureConcept.getName());
procedureCodeConcept.addCoding(coding);
procedure.setCode(procedureCodeConcept);
}
// FHIR does not require the coding. If our System URI is not mappable
// from OMOP database, then coding would be empty. Set Text here. Even text
// is not required in FHIR. But, then no reason to have this condition, I think...
String theText = procedureConcept.getName() + ", " + procedureConcept.getVocabulary().getName() + ", "
+ procedureConcept.getConceptCode();
//
// System.out.println("Procedure:"+theText);
//
procedureCodeConcept.setText(theText);
// procedure.setCode(procedureCodeConcept);
//procedure.setType(procedureCodeConcept);
DateTimeDt DateDt = new DateTimeDt(date);
procedure.setPerformed(DateDt);
//TODO: where is code??? For now, I put it in the Note. This is CPT code.
// Now code is available. SO, we don't need this.
//procedure.setNotes(this.getProcedureConcept().getConceptCode());
return procedure;
}
@Override
public IResourceEntity constructEntityFromResource(IResource resource) {
// TODO CREATE UPDATE not implemented
return null;
}
}