All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.hl7.fhir.r4.ips.IPSBuilder Maven / Gradle / Ivy

Go to download

Builds the hapi fhir r4. Requires hapi-fhir-base and hapi-fhir-utilities be built first and be excluded from any other poms requiring it.

The newest version!
package org.hl7.fhir.r4.ips;

import java.util.Date;
import java.util.List;

import org.hl7.fhir.r4.ips.IPSBuilder.TypeAndId;
import org.hl7.fhir.r4.model.Age;
import org.hl7.fhir.r4.model.Annotation;
import org.hl7.fhir.r4.model.Bundle;
import org.hl7.fhir.r4.model.Bundle.BundleEntryComponent;
import org.hl7.fhir.r4.model.Bundle.BundleType;
import org.hl7.fhir.r4.model.CodeableConcept;
import org.hl7.fhir.r4.model.Coding;
import org.hl7.fhir.r4.model.Composition;
import org.hl7.fhir.r4.model.Patient;
import org.hl7.fhir.r4.model.Period;
import org.hl7.fhir.r4.model.Quantity;
import org.hl7.fhir.r4.model.Range;
import org.hl7.fhir.r4.model.Reference;
import org.hl7.fhir.r4.model.Type;
import org.hl7.fhir.r4.model.Composition.CompositionStatus;
import org.hl7.fhir.r4.model.Composition.SectionComponent;
import org.hl7.fhir.r4.model.Condition;
import org.hl7.fhir.r4.model.Device;
import org.hl7.fhir.r4.model.DomainResource;
import org.hl7.fhir.r4.model.Dosage;
import org.hl7.fhir.r4.model.Identifier;
import org.hl7.fhir.r4.model.Medication;
import org.hl7.fhir.r4.model.MedicationStatement;
import org.hl7.fhir.r4.model.Narrative.NarrativeStatus;
import org.hl7.fhir.r4.utils.client.FHIRToolingClient;
import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.utilities.VersionUtil;
import org.hl7.fhir.utilities.xhtml.XhtmlNode;

public class IPSBuilder {

  public static class TypeAndId {
    private String type;
    private String id;
    protected TypeAndId(String type, String id) {
      super();
      this.type = type;
      this.id = id;
    }
    public String getType() {
      return type;
    }
    public String getId() {
      return id;
    }
  }

  public static Bundle generateIPS(FHIRToolingClient server, String patientId) {
    Patient pat = server.fetchResource(Patient.class, patientId);
    Bundle bnd = initBundle();
    Composition cmp = initComposition(bnd, server.getAddress(), pat);
    pat = processPatient(bnd, server.getAddress(), pat);
//    addMedications(bnd, cmp, server, patientId);
    addConditions(bnd, cmp, server, patientId);
    return bnd;
  }

  private static Bundle initBundle() {
    Bundle bnd = new Bundle();
    bnd.getIdentifier().setSystem("urn:ietf:rfc:3986");
    bnd.getIdentifier().setValue(Utilities.makeUuidUrn());
    bnd.setType(BundleType.DOCUMENT);
    bnd.setTimestamp(new Date());
    return bnd;
  }
  
  private static Composition initComposition(Bundle bnd, String url, Patient pat) {
    Composition cmp = new Composition();
    cmp.setIdBase(Utilities.makeUuidLC());
    cmp.setStatus(CompositionStatus.FINAL);
    cmp.getType().addCoding().setSystem("http://loinc.org").setCode("60591-5");
    cmp.setDate(new Date());
    cmp.setTitle("International Patient Summary");
    cmp.getSubject().setReference("Patient/"+pat.getIdBase());
    cmp.addAuthor().setReference("Device/java");
    bnd.addEntry().setResource(cmp).setFullUrl(Utilities.pathURL(url, "Composition", cmp.getIdBase()));
    Device dev = new Device();
    dev.setId("java");
    dev.addDeviceName().setName("Java Core Library");
    dev.addVersion().setValue(VersionUtil.getVersion());
    bnd.addEntry().setResource(dev).setFullUrl(Utilities.pathURL(url, "Device", dev.getIdBase()));
    return cmp;
  }

  private static Patient processPatient(Bundle bnd,  String url, Patient pat) {
    bnd.addEntry().setResource(pat).setFullUrl(Utilities.pathURL(url, "Patient", pat.getIdBase()));
    return pat;
  }
  
  private static void addMedications(Bundle bnd, Composition cmp, FHIRToolingClient server, String patientId) {
    Bundle sb = server.search("MedicationStatement", "?patient="+patientId+"&_include=MedicationStatement:medication&_include=MedicationStatement:source");
    SectionComponent sct = cmp.addSection();
    sct.setTitle("Medications");
    sct.getCode().addCoding().setSystem("http://loinc.org").setCode("10160-0");
    sct.getText().setStatus(NarrativeStatus.GENERATED);
    var x = sct.getText().getDiv();
    var tbl = x.table("grid");
    var tr = tbl.tr();
    tr.th().tx("Medication");
    tr.th().tx("Category");
    tr.th().tx("Status");
    tr.th().tx("When");
    tr.th().tx("Dosage");
    tr.th().tx("Reason");
    tr.th().tx("Source");
    tr.th().tx("Notes");

    boolean ok = false;
    for (BundleEntryComponent be : sb.getEntry()) {
      if (be.hasResource() && be.getResource() instanceof MedicationStatement) {
        MedicationStatement mdstmt = (MedicationStatement) be.getResource();
        ok = true;
        bnd.addEntry().setResource(mdstmt).setFullUrl(Utilities.pathURL(server.getAddress(), "MedicationStatement", mdstmt.getIdBase()));
        sct.addEntry().setReference("MedicationStatement/"+mdstmt.getIdBase());
        tr = tbl.tr();
        if (mdstmt.hasMedicationReference()) {
          Medication med = findMedication(sb, server, mdstmt, mdstmt.getMedicationReference());
          if (med == null) {
            tr.td().b().tx("Unknown?");
          } else {
            tr.td().tx(summarise(med));
            bnd.addEntry().setResource(med).setFullUrl(Utilities.pathURL(server.getAddress(), "Medication", med.getIdBase()));
          }
        } else {
          tr.td().tx(genCC(mdstmt.getMedicationCodeableConcept()));
        }
        tr.td().tx(genCC(mdstmt.getCategory()));
        var td = tr.td();
        td.tx(mdstmt.getStatus().getDisplay());
        if (mdstmt.hasStatusReason()) {
          td.tx(" (");
          td.tx(genCC(mdstmt.getStatusReason()));
          td.tx(")");
        }
        tr.td().tx(genDT(mdstmt.getEffective()));
        genDosages(tr.td(), mdstmt.getDosage());
        tr.td().tx(genReference(mdstmt, mdstmt.getInformationSource(), bnd, sb, server));
        genNotes(tr.td(), mdstmt.getNote());
      }
    }
    if (!ok) {
      Condition cnd = new Condition();
      cnd.setId(Utilities.makeUuidLC());

      cnd.getText().setStatus(NarrativeStatus.GENERATED);
      var rx = cnd.getText().getDiv();
      rx.tx("No information is provided about the patient's medical problems");
      tr = tbl.tr();
      tr.td().colspan(7).tx("No information is provided about the patient's medical problems");
      cnd.getClinicalStatus().addCoding().setSystem("http://terminology.hl7.org/CodeSystem/condition-clinical").setCode("active").setDisplay("Active");
      cnd.getCode().addCoding().setSystem("http://hl7.org/fhir/uv/ips/CodeSystem/absent-unknown-uv-ips").setCode("no-problem-info").setDisplay("No information about current problems");
      cnd.getSubject().setReference("Patient/"+patientId);
    }
  }


  private static void genDosages(XhtmlNode x, List dosages) {
    if (dosages == null || dosages.size() == 0) {
      
    } else if (dosages.size() == 1) {
      genDosage(x, dosages.get(0));
    } else {
      var ul = x.ul();
      for (Dosage d : dosages) {
        genDosage(ul.li(), d);
      }
    } 
  }

  private static void genDosage(XhtmlNode x, Dosage dosage) {
    x.tx(dosage.getText());
    if (dosage.hasAsNeeded()) {
      x.nbsp();
      if (dosage.hasAsNeededBooleanType()) {
        if (dosage.getAsNeededBooleanType().booleanValue()) {
          x.tx(" (as needed)");
        }
      } else {
        x.tx(genDT(dosage.getAsNeeded()));
      }
    } else if (dosage.hasTiming()) {
      x.nbsp();
      x.tx(genDT(dosage.getTiming()));
    }
    if (dosage.hasSite()) {
      x.tx(". ");
      x.tx(genDT(dosage.getSite()));
    }
    if (dosage.hasRoute()) {
      x.tx(". ");
      x.tx(genDT(dosage.getRoute()));
    }
  }

  private static Medication findMedication(Bundle sb, FHIRToolingClient server, MedicationStatement mdstmt, Reference ref) {
    if (ref == null || !ref.hasReference()) {
      return null;
    }
    if (ref.getReference().startsWith("#")) {
      
    } else {
      
    }
    return null;
  }

  private static void addConditions(Bundle bnd, Composition cmp, FHIRToolingClient server, String patientId) {
    Bundle sb = server.search("Condition", "?patient="+patientId+"&_include=Condition:asserter");
    SectionComponent sct = cmp.addSection();
    sct.setTitle("Problems");
    sct.getCode().addCoding().setSystem("http://loinc.org").setCode("11450-4");
    sct.getText().setStatus(NarrativeStatus.GENERATED);
    var x = sct.getText().getDiv();
    var tbl = x.table("grid");
    var tr = tbl.tr();
    tr.th().tx("Code");
    tr.th().tx("Category");
    tr.th().tx("Severity");
    tr.th().tx("Status");
    tr.th().tx("Onset");
    tr.th().tx("Abatement");
    tr.th().tx("Source");
    tr.th().tx("Notes");

    boolean ok = false;
    for (BundleEntryComponent be : sb.getEntry()) {
      if (be.hasResource() && be.getResource() instanceof Condition) {
        Condition cnd = (Condition) be.getResource();
        ok = true;
        bnd.addEntry().setResource(cnd).setFullUrl(Utilities.pathURL(server.getAddress(), "Condition", cnd.getIdBase()));
        sct.addEntry().setReference("Condition/"+cnd.getIdBase());
        tr = tbl.tr();
        tr.td().tx(genCC(cnd.getCode()));
        tr.td().tx(genCC(cnd.getCategory()));
        tr.td().tx(genCC(cnd.getSeverity()));
        tr.td().tx(genStatus(cnd));
        tr.td().tx(genDT(cnd.getOnset()));
        tr.td().tx(genDT(cnd.getAbatement()));
        tr.td().tx(genSource(cnd, bnd, sb, server));
        genNotes(tr.td(), cnd.getNote());

      }
    }
    if (!ok) {
      Condition cnd = new Condition();
      cnd.setId(Utilities.makeUuidLC());

      cnd.getText().setStatus(NarrativeStatus.GENERATED);
      var rx = cnd.getText().getDiv();
      rx.tx("No information is provided about the patient's medical problems");
      tr = tbl.tr();
      tr.td().colspan(7).tx("No information is provided about the patient's medical problems");
      cnd.getClinicalStatus().addCoding().setSystem("http://terminology.hl7.org/CodeSystem/condition-clinical").setCode("active").setDisplay("Active");
      cnd.getCode().addCoding().setSystem("http://hl7.org/fhir/uv/ips/CodeSystem/absent-unknown-uv-ips").setCode("no-problem-info").setDisplay("No information about current problems");
      cnd.getSubject().setReference("Patient/"+patientId);
    }
  }


  private static String genReference(DomainResource src, Reference ref, Bundle bnd, Bundle search, FHIRToolingClient server) {
    if (ref == null || ref.isEmpty()) {
      return null;
    }
    boolean contained = false;
    DomainResource tgt = null;
    if (ref.hasReference()) {
      if (ref.getReference().startsWith("#")) {
        tgt = (DomainResource) src.getContained(ref.getReference());
        contained = true;
      } else {
        TypeAndId tid = getTypeAndId(server.getAddress(), ref.getReference());
        if (tid != null) {
          tgt = findInBundle(bnd, Utilities.pathURL(server.getAddress(), tid.getType(), tid.getId()));
          if (tgt == null) {
            tgt = findInBundle(search, Utilities.pathURL(server.getAddress(), tid.getType(), tid.getId()));
            if (tgt == null) {
              tgt = (DomainResource) server.read(tid.getType(), tid.getId());
            }
          } else {
            contained = true;
          }
        }
      }
    }
    if (tgt != null) {
      if (!contained) {
        bnd.addEntry().setResource(tgt).setFullUrl(Utilities.pathURL(server.getAddress(), tgt.fhirType(), tgt.getIdBase()));
      }
      return summarise(tgt);
    } else if (ref.hasDisplay()) {
      return ref.getDisplay();
    } else if (ref.hasReference()) {
      return ref.getReference();
    } else if (ref.hasIdentifier()) {
      return genIdentifier(ref.getIdentifier());
    } else {
      return "unknown";
    }
  }

  
  private static TypeAndId getTypeAndId(String baseUrl, String url) {
    if (Utilities.noString(url)) {
      return null;
    }
    if (url.startsWith(baseUrl+"/")) {
      url = url.substring(baseUrl.length()+1);
    }
    String[] p = url.split("\\/");
    if (p.length > 1) {
      if ("_history".equals(p[p.length-2]) && p.length > 3) {
        return new TypeAndId(p[p.length-4], p[p.length-3]);
      } else {
        return new TypeAndId(p[p.length-2], p[p.length-1]);
      }
    }
    return null;
  }

  private static DomainResource findInBundle(Bundle bnd, String url) {
    for (BundleEntryComponent be : bnd.getEntry()) {
      if (url.equals(be.getFullUrl()) && be.hasResource() && be.getResource() instanceof DomainResource) {
        return (DomainResource) be.getResource();
      }
    }
    return null;
  }

  private static String summarise(DomainResource tgt) {
    // TODO Auto-generated method stub
    return null;
  }

  private static String genIdentifier(Identifier id) {
    return id.getValue();
  }

  private static void genNotes(XhtmlNode td, List notes) {
    if (notes.size() > 0) {
      if (notes.size() == 1) {
        genNote(td, notes.get(0));
      } else {
        var ul = td.ul();
        for (Annotation a : notes) {
          genNote(ul.li(), a);
        }
      }
    }
  }

  private static void genNote(XhtmlNode td, Annotation annotation) {
    td.tx(annotation.getText());    
  }

  private static String genSource(Condition cnd, Bundle bnd, Bundle sb, FHIRToolingClient server) {
    if (cnd.hasAsserter()) {
      return genReference(cnd, cnd.getAsserter(), bnd, sb, server);
    } else if (cnd.hasRecorder()) {
      return genReference(cnd, cnd.getRecorder(), bnd, sb, server);
    } else {
      return null;
    }
  }

  private static String genDT(Type v) {
    if (v == null) {
      return null;
    }
    if (v.isPrimitive()) {
      return v.primitiveValue();
    }
    if (v instanceof Age) {
      return genQty((Age) v);
    }
    if (v instanceof Period) {
      Period p = (Period) v;
      return genDT(p.getStartElement())+" - "+genDT(p.getStartElement());
    }
    if (v instanceof Range) {
      Range p = (Range) v;
      return genDT(p.getLow())+" - "+genDT(p.getHigh());
    }
    return "not done: "+v.fhirType();
  }

  private static String genQty(Quantity v) {
    return v.getValue().toPlainString()+v.getUnit();
  }

  private static String genStatus(Condition cnd) {
    if (cnd.hasClinicalStatus() && cnd.hasVerificationStatus()) {
      return genCC(cnd.getClinicalStatus()) +"/"+genCC(cnd.getVerificationStatus());
    } else if (cnd.hasClinicalStatus()) {
      return genCC(cnd.getClinicalStatus());
    } else if (cnd.hasVerificationStatus()) {
      return genCC(cnd.getVerificationStatus());      
    } else {
      return null;
    }
  }

  private static String genCC(List list) {
    if (list != null && list.size() == 1) {
      return genCC(list.get(0));
    } else {
      return null;
    }
  }

  private static String genCC(CodeableConcept code) {
    if (code.hasText()) {
      return code.getText();
    } else if (code.hasCoding()) {
      Coding c = code.getCodingFirstRep();
      if (c.hasDisplay()) {
        return c.getDisplay();
      } else {
        return c.getCode();
      }
    } else {
      return null;
    }
  }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy