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

org.hl7.fhir.r4b.renderers.DiagnosticReportRenderer Maven / Gradle / Ivy

The newest version!
package org.hl7.fhir.r4b.renderers;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;

import org.hl7.fhir.exceptions.DefinitionException;
import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.exceptions.FHIRFormatError;
import org.hl7.fhir.r4b.model.DomainResource;
import org.hl7.fhir.r4b.model.Resource;
import org.hl7.fhir.r4b.model.Base;
import org.hl7.fhir.r4b.model.DataType;
import org.hl7.fhir.r4b.model.DiagnosticReport;
import org.hl7.fhir.r4b.renderers.utils.BaseWrappers.BaseWrapper;
import org.hl7.fhir.r4b.renderers.utils.BaseWrappers.PropertyWrapper;
import org.hl7.fhir.r4b.renderers.utils.BaseWrappers.ResourceWrapper;
import org.hl7.fhir.r4b.renderers.utils.DirectWrappers;
import org.hl7.fhir.r4b.renderers.utils.RenderingContext;
import org.hl7.fhir.r4b.renderers.utils.Resolver.ResourceContext;
import org.hl7.fhir.r4b.renderers.utils.Resolver.ResourceWithReference;
import org.hl7.fhir.r4b.utils.EOperationOutcome;
import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.utilities.xhtml.XhtmlNode;

/**
 * Rendering framework:
 * 
 * See R5 rendering framework to render R4B resources
 * 
 */
@Deprecated
public class DiagnosticReportRenderer extends ResourceRenderer {

  public class ObservationNode {
    private String ref;
    private ResourceWithReference obs;
    private List contained;
  }

  public DiagnosticReportRenderer(RenderingContext context) {
    super(context);
  }

  public DiagnosticReportRenderer(RenderingContext context, ResourceContext rcontext) {
    super(context, rcontext);
  }

  public boolean render(XhtmlNode x, Resource dr) throws IOException, FHIRException, EOperationOutcome {
    return render(x, (DiagnosticReport) dr);
  }

  public boolean render(XhtmlNode x, ResourceWrapper dr) throws IOException, FHIRException, EOperationOutcome {
    XhtmlNode h2 = x.h2();
    render(h2, getProperty(dr, "code").value());
    h2.tx(" ");
    PropertyWrapper pw = getProperty(dr, "category");
    if (valued(pw)) {
      h2.tx("(");
      boolean first = true;
      for (BaseWrapper b : pw.getValues()) {
        if (first)
          first = false;
        else
          h2.tx(", ");
        render(h2, b);
      }
      h2.tx(") ");
    }
    XhtmlNode tbl = x.table("grid");
    XhtmlNode tr;
    if (dr.has("subject")) {
      tr = tbl.tr();
      tr.td().tx("Subject");
      populateSubjectSummary(tr.td(), getProperty(dr, "subject").value());
    }

    DataType eff = null;
    DataType iss = null;

    if (dr.has("effective[x]")) {
      tr = tbl.tr();
      tr.td().tx("When For");
      eff = (DataType) getProperty(dr, "effective[x]").value().getBase();
      render(tr.td(), eff);
    }
    if (dr.has("issued")) {
      tr = tbl.tr();
      tr.td().tx("Reported");
      eff = (DataType) getProperty(dr, "issued").value().getBase();
      render(tr.td(), getProperty(dr, "issued").value());
    }

    pw = getProperty(dr, "perfomer");
    if (valued(pw)) {
      tr = tbl.tr();
      tr.td().tx(Utilities.pluralize("Performer", pw.getValues().size()));
      XhtmlNode tdr = tr.td();
      for (BaseWrapper v : pw.getValues()) {
        tdr.tx(" ");
        render(tdr, v);
      }
    }
    pw = getProperty(dr, "identifier");
    if (valued(pw)) {
      tr = tbl.tr();
      tr.td().tx(Utilities.pluralize("Identifier", pw.getValues().size()) + ":");
      XhtmlNode tdr = tr.td();
      for (BaseWrapper v : pw.getValues()) {
        tdr.tx(" ");
        render(tdr, v);
      }
    }
    pw = getProperty(dr, "request");
    if (valued(pw)) {
      tr = tbl.tr();
      tr.td().tx(Utilities.pluralize("Request", pw.getValues().size()) + ":");
      XhtmlNode tdr = tr.td();
      for (BaseWrapper v : pw.getValues()) {
        tdr.tx(" ");
        render(tdr, v);
      }
      tdr.br();
    }

    x.para().b().tx("Report Details");

    pw = getProperty(dr, "result");
    if (valued(pw)) {
      List observations = fetchObservations(pw.getValues(), dr);
      buildObservationsTable(x, observations, eff, iss);
    }

    pw = getProperty(dr, "conclusion");
    if (valued(pw)) {
      render(x.para(), pw.value());
    }

    pw = getProperty(dr, "conclusionCode");
    if (!valued(pw)) {
      pw = getProperty(dr, "codedDiagnosis");
    }
    if (valued(pw)) {
      XhtmlNode p = x.para();
      p.b().tx("Coded Conclusions :");
      XhtmlNode ul = x.ul();
      for (BaseWrapper v : pw.getValues()) {
        render(ul.li(), v);
      }
    }
    return false;
  }

  public boolean render(XhtmlNode x, DiagnosticReport dr) throws IOException, FHIRException, EOperationOutcome {
    render(x, new DirectWrappers.ResourceWrapperDirect(this.context, dr));

    return true;
  }

  public void describe(XhtmlNode x, DiagnosticReport dr) {
    x.tx(display(dr));
  }

  public String display(DiagnosticReport dr) {
    return display(dr.getCode());
  }

  @Override
  public String display(Resource r) throws UnsupportedEncodingException, IOException {
    return display((DiagnosticReport) r);
  }

  @Override
  public String display(ResourceWrapper r) throws UnsupportedEncodingException, IOException {
    return "Not done yet";
  }

  private void populateSubjectSummary(XhtmlNode container, BaseWrapper subject)
      throws UnsupportedEncodingException, FHIRException, IOException, EOperationOutcome {
    ResourceWrapper r = fetchResource(subject);
    if (r == null)
      container.tx("Unable to get Patient Details");
    else if (r.getName().equals("Patient"))
      generatePatientSummary(container, r);
    else
      container.tx("Not done yet");
  }

  private void generatePatientSummary(XhtmlNode c, ResourceWrapper r)
      throws FHIRFormatError, DefinitionException, FHIRException, IOException, EOperationOutcome {
    new PatientRenderer(context).describe(c, r);
  }

  private List fetchObservations(List list, ResourceWrapper rw)
      throws UnsupportedEncodingException, FHIRException, IOException {
    List res = new ArrayList();
    for (BaseWrapper b : list) {
      if (b.has("reference")) {
        ObservationNode obs = new ObservationNode();
        obs.ref = b.get("reference").primitiveValue();
        obs.obs = resolveReference(rw, obs.ref);
        if (obs.obs != null && obs.obs.getResource() != null) {
          PropertyWrapper t = getProperty(obs.obs.getResource(), "contained");
          if (t != null && t.hasValues()) {
            obs.contained = fetchObservations(t.getValues(), rw);
          }
        }
        res.add(obs);
      }
    }
    return res;
  }

  private void buildObservationsTable(XhtmlNode root, List observations, DataType eff, DataType iss)
      throws UnsupportedEncodingException, FHIRException, IOException {
    XhtmlNode tbl = root.table("grid");
    boolean refRange = scanObsForRefRange(observations);
    boolean flags = scanObsForFlags(observations);
    boolean note = scanObsForNote(observations);
    boolean effectiveTime = scanObsForEffective(observations, eff);
    boolean issued = scanObsForIssued(observations, iss);
    int cs = 2;
    if (refRange)
      cs++;
    if (flags)
      cs++;
    if (note)
      cs++;
    if (issued)
      cs++;
    if (effectiveTime)
      cs++;
    XhtmlNode tr = tbl.tr();
    tr.td().b().tx("Code");
    tr.td().b().tx("Value");
    if (refRange) {
      tr.td().b().tx("Reference Range");
    }
    if (flags) {
      tr.td().b().tx("Flags");
    }
    if (note) {
      tr.td().b().tx("Note");
    }
    if (effectiveTime) {
      tr.td().b().tx("When For");
    }
    if (issued) {
      tr.td().b().tx("Reported");
    }
    for (ObservationNode o : observations) {
      addObservationToTable(tbl, o, 0, Integer.toString(cs), refRange, flags, note, effectiveTime, issued, eff, iss);
    }
  }

  private boolean scanObsForRefRange(List observations) {
    for (ObservationNode o : observations) {
      if (o.obs != null && o.obs.getResource() != null) {
        PropertyWrapper pw = getProperty(o.obs.getResource(), "referenceRange");
        if (valued(pw)) {
          return true;
        }
      }
      if (o.contained != null) {
        if (scanObsForRefRange(o.contained)) {
          return true;
        }
      }
    }
    return false;
  }

  private boolean scanObsForNote(List observations) {
    for (ObservationNode o : observations) {
      if (o.obs != null && o.obs.getResource() != null) {
        PropertyWrapper pw = getProperty(o.obs.getResource(), "note");
        if (valued(pw)) {
          return true;
        }
      }
      if (o.contained != null) {
        if (scanObsForNote(o.contained)) {
          return true;
        }
      }
    }
    return false;
  }

  private boolean scanObsForIssued(List observations, DataType iss)
      throws UnsupportedEncodingException, FHIRException, IOException {
    for (ObservationNode o : observations) {
      if (o.obs != null && o.obs.getResource() != null) {
        PropertyWrapper pw = getProperty(o.obs.getResource(), "issued");
        if (valued(pw)) {
          if (!Base.compareDeep(pw.value().getBase(), iss, true)) {
            return true;
          }
        }
      }
      if (o.contained != null) {
        if (scanObsForIssued(o.contained, iss)) {
          return true;
        }
      }
    }
    return false;
  }

  private boolean scanObsForEffective(List observations, DataType eff)
      throws UnsupportedEncodingException, FHIRException, IOException {
    for (ObservationNode o : observations) {
      if (o.obs != null && o.obs.getResource() != null) {
        PropertyWrapper pw = getProperty(o.obs.getResource(), "effective[x]");
        if (valued(pw)) {
          if (!Base.compareDeep(pw.value().getBase(), eff, true)) {
            return true;
          }
        }
      }
      if (o.contained != null) {
        if (scanObsForEffective(o.contained, eff)) {
          return true;
        }
      }
    }
    return false;
  }

  private boolean scanObsForFlags(List observations)
      throws UnsupportedEncodingException, FHIRException, IOException {
    for (ObservationNode o : observations) {
      if (o.obs != null && o.obs.getResource() != null) {
        PropertyWrapper pw = getProperty(o.obs.getResource(), "interpretation");
        if (valued(pw)) {
          return true;
        }
        pw = getProperty(o.obs.getResource(), "status");
        if (valued(pw)) {
          if (!pw.value().getBase().primitiveValue().equals("final")) {
            return true;
          }
        }

      }
      if (o.contained != null) {
        if (scanObsForFlags(o.contained)) {
          return true;
        }
      }
    }
    return false;
  }

  private void addObservationToTable(XhtmlNode tbl, ObservationNode o, int i, String cs, boolean refRange,
      boolean flags, boolean note, boolean effectiveTime, boolean issued, DataType eff, DataType iss)
      throws UnsupportedEncodingException, FHIRException, IOException {
    XhtmlNode tr = tbl.tr();
    if (o.obs != null && o.obs.getReference() == null) {
      XhtmlNode td = tr.td().colspan(cs);
      td.i().tx("This Observation could not be resolved");
    } else {
      if (o.obs != null && o.obs.getResource() != null) {
        addObservationToTable(tr, o.obs.getResource(), i, o.obs.getReference(), refRange, flags, note, effectiveTime,
            issued, eff, iss);
      } else {
        XhtmlNode td = tr.td().colspan(cs);
        td.i().tx("Observation");
      }
      if (o.contained != null) {
        for (ObservationNode c : o.contained) {
          addObservationToTable(tbl, c, i + 1, cs, refRange, flags, note, effectiveTime, issued, eff, iss);
        }
      }
    }
  }

  private void addObservationToTable(XhtmlNode tr, ResourceWrapper obs, int i, String ref, boolean refRange,
      boolean flags, boolean note, boolean effectiveTime, boolean issued, DataType eff, DataType iss)
      throws UnsupportedEncodingException, FHIRException, IOException {

    // code (+bodysite)
    XhtmlNode td = tr.td();
    PropertyWrapper pw = getProperty(obs, "code");
    if (valued(pw)) {
      render(td.ah(ref), pw.value());
    }
    pw = getProperty(obs, "bodySite");
    if (valued(pw)) {
      td.tx(" (");
      render(td, pw.value());
      td.tx(")");
    }

    // value / dataAbsentReason (in red)
    td = tr.td();
    pw = getProperty(obs, "value[x]");
    if (valued(pw)) {
      render(td, pw.value());
    } else {
      pw = getProperty(obs, "dataAbsentReason");
      if (valued(pw)) {
        XhtmlNode span = td.span("color: maroon", "Error");
        span.tx("Error: ");
        render(span.b(), pw.value());
      }
    }
    if (refRange) {
      // reference range
      td = tr.td();
      pw = getProperty(obs, "referenceRange");
      if (valued(pw)) {
        boolean first = true;
        for (BaseWrapper v : pw.getValues()) {
          if (first)
            first = false;
          else
            td.br();
          PropertyWrapper pwr = getProperty(v, "type");
          if (valued(pwr)) {
            render(td, pwr.value());
            td.tx(": ");
          }
          PropertyWrapper pwt = getProperty(v, "text");
          if (valued(pwt)) {
            render(td, pwt.value());
          } else {
            PropertyWrapper pwl = getProperty(v, "low");
            PropertyWrapper pwh = getProperty(v, "high");
            if (valued(pwl) && valued(pwh)) {
              render(td, pwl.value());
              td.tx(" - ");
              render(td, pwh.value());
            } else if (valued(pwl)) {
              td.tx(">");
              render(td, pwl.value());
            } else if (valued(pwh)) {
              td.tx("<");
              render(td, pwh.value());
            } else {
              td.tx("??");
            }
          }
          pwr = getProperty(v, "appliesTo");
          PropertyWrapper pwrA = getProperty(v, "age");
          if (valued(pwr) || valued(pwrA)) {
            boolean firstA = true;
            td.tx(" for ");
            if (valued(pwr)) {
              for (BaseWrapper va : pwr.getValues()) {
                if (firstA)
                  firstA = false;
                else
                  td.tx(", ");
                render(td, va);
              }
            }
            if (valued(pwrA)) {
              if (firstA)
                firstA = false;
              else
                td.tx(", ");
              td.tx("Age ");
              render(td, pwrA.value());
            }
          }
        }
      }
    }
    if (flags) {
      // flags (status other than F, interpretation, )
      td = tr.td();
      boolean first = true;
      pw = getProperty(obs, "status");
      if (valued(pw)) {
        if (!pw.value().getBase().primitiveValue().equals("final")) {
          if (first)
            first = false;
          else
            td.br();
          render(td, pw.value());
        }
      }
      pw = getProperty(obs, "interpretation");
      if (valued(pw)) {
        for (BaseWrapper v : pw.getValues()) {
          if (first)
            first = false;
          else
            td.br();
          render(td, v);
        }
      }
    }

    if (note) {
      td = tr.td();
      pw = getProperty(obs, "note");
      if (valued(pw)) {
        render(td, pw.value());
      }
    }
    if (effectiveTime) {
      // effective if different to DR
      td = tr.td();
      pw = getProperty(obs, "effective[x]");
      if (valued(pw)) {
        if (!Base.compareDeep(pw.value().getBase(), eff, true)) {
          render(td, pw.value());
        }
      }
    }
    if (issued) {
      // issued if different to DR
      td = tr.td();
      pw = getProperty(obs, "issued");
      if (valued(pw)) {
        if (!Base.compareDeep(pw.value().getBase(), eff, true)) {
          render(td, pw.value());
        }
      }
    }
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy