001package org.hl7.fhir.r4.elementmodel;
002
003import java.io.*;
004import java.util.ArrayList;
005import java.util.List;
006
007import org.hl7.fhir.r4.elementmodel.Element;
008import org.hl7.fhir.r4.model.Identifier;
009import org.hl7.fhir.r4.model.Reference;
010import org.hl7.fhir.exceptions.*;
011import org.hl7.fhir.r4.conformance.ProfileUtilities;
012import org.hl7.fhir.r4.context.IWorkerContext;
013import org.hl7.fhir.r4.formats.IParser.OutputStyle;
014import org.hl7.fhir.r4.model.*;
015import org.hl7.fhir.r4.model.StructureDefinition.StructureDefinitionKind;
016import org.hl7.fhir.utilities.TextFile;
017
018
019public class ObjectConverter  {
020
021  private IWorkerContext context;
022
023  public ObjectConverter(IWorkerContext context) {
024    this.context = context;
025  }
026
027  public Element convert(Resource ig) throws IOException, FHIRException {
028    if (ig == null)
029      return null;
030    ByteArrayOutputStream bs = new ByteArrayOutputStream();
031    org.hl7.fhir.r4.formats.JsonParser jp = new org.hl7.fhir.r4.formats.JsonParser();
032    jp.compose(bs, ig);
033    ByteArrayInputStream bi = new ByteArrayInputStream(bs.toByteArray());
034    return new JsonParser(context).parse(bi);
035  }
036
037  public Element convert(Property property, Type type) throws FHIRException {
038    return convertElement(property, type);
039  }
040  
041  private Element convertElement(Property property, Base base) throws FHIRException {
042    if (base == null)
043      return null;
044    String tn = base.fhirType();
045    StructureDefinition sd = context.fetchResource(StructureDefinition.class, ProfileUtilities.sdNs(tn, context.getOverrideVersionNs()));
046    if (sd == null)
047      throw new FHIRException("Unable to find definition for type "+tn);
048    Element res = new Element(property.getName(), property);
049    if (sd.getKind() == StructureDefinitionKind.PRIMITIVETYPE) 
050      res.setValue(((PrimitiveType) base).asStringValue());
051
052    List<ElementDefinition> children = ProfileUtilities.getChildMap(sd, sd.getSnapshot().getElementFirstRep()); 
053    for (ElementDefinition child : children) {
054      String n = tail(child.getPath());
055      if (sd.getKind() != StructureDefinitionKind.PRIMITIVETYPE || !"value".equals(n)) {
056        Base[] values = base.getProperty(n.hashCode(), n, false);
057        if (values != null)
058          for (Base value : values) {
059            res.getChildren().add(convertElement(new Property(context, child, sd), value));
060          }
061      }
062    }
063    return res;
064  }
065
066  private String tail(String path) {
067    if (path.contains("."))
068      return path.substring(path.lastIndexOf('.')+1);
069    else
070      return path;
071  }
072
073  public Type convertToType(Element element) throws FHIRException {
074    Type b = new Factory().create(element.fhirType());
075    if (b instanceof PrimitiveType) {
076      ((PrimitiveType) b).setValueAsString(element.primitiveValue());
077    } else {
078      for (Element child : element.getChildren()) {
079        b.setProperty(child.getName(), convertToType(child));
080      }
081    }
082    return b;
083  }
084
085  public Resource convert(Element element) throws FHIRException {
086    ByteArrayOutputStream bo = new ByteArrayOutputStream();
087    try {
088      new JsonParser(context).compose(element, bo, OutputStyle.NORMAL, null);
089//      TextFile.bytesToFile(bo.toByteArray(), "c:\\temp\\json.json");
090      return new org.hl7.fhir.r4.formats.JsonParser().parse(bo.toByteArray());
091    } catch (IOException e) {
092      // won't happen
093      throw new FHIRException(e);
094    }
095    
096  }
097
098  public static CodeableConcept readAsCodeableConcept(Element element) {
099    CodeableConcept cc = new CodeableConcept();
100    List<Element> list = new ArrayList<Element>();
101    element.getNamedChildren("coding", list);
102    for (Element item : list)
103      cc.addCoding(readAsCoding(item));
104    cc.setText(element.getNamedChildValue("text"));
105    return cc;
106  }
107
108  public static Coding readAsCoding(Element item) {
109    Coding c = new Coding();
110    c.setSystem(item.getNamedChildValue("system"));
111    c.setVersion(item.getNamedChildValue("version"));
112    c.setCode(item.getNamedChildValue("code"));
113    c.setDisplay(item.getNamedChildValue("display"));
114    return c;
115  }
116
117  public static Identifier readAsIdentifier(Element item) {
118    Identifier r = new Identifier();
119    r.setSystem(item.getNamedChildValue("system"));
120    r.setValue(item.getNamedChildValue("value"));
121    return r;
122  }
123
124  public static Reference readAsReference(Element item) {
125    Reference r = new Reference();
126    r.setDisplay(item.getNamedChildValue("display"));
127    r.setReference(item.getNamedChildValue("reference"));
128    r.setType(item.getNamedChildValue("type"));
129    List<Element> identifier = item.getChildrenByName("identifier");
130    if (identifier.isEmpty() == false) {
131      r.setIdentifier(readAsIdentifier(identifier.get(0)));
132    }
133    return r;
134  }
135
136}