001package org.hl7.fhir.dstu3.elementmodel;
002
003import java.io.ByteArrayInputStream;
004import java.io.ByteArrayOutputStream;
005import java.io.IOException;
006import java.util.List;
007
008import org.hl7.fhir.dstu3.conformance.ProfileUtilities;
009import org.hl7.fhir.dstu3.context.IWorkerContext;
010import org.hl7.fhir.dstu3.formats.IParser.OutputStyle;
011import org.hl7.fhir.dstu3.model.Base;
012import org.hl7.fhir.dstu3.model.ElementDefinition;
013import org.hl7.fhir.dstu3.model.Factory;
014import org.hl7.fhir.dstu3.model.PrimitiveType;
015import org.hl7.fhir.dstu3.model.Resource;
016import org.hl7.fhir.dstu3.model.StructureDefinition;
017import org.hl7.fhir.dstu3.model.StructureDefinition.StructureDefinitionKind;
018import org.hl7.fhir.dstu3.model.Type;
019import org.hl7.fhir.exceptions.DefinitionException;
020import org.hl7.fhir.exceptions.FHIRException;
021import org.hl7.fhir.exceptions.FHIRFormatError;
022
023
024public class ObjectConverter  {
025
026  private IWorkerContext context;
027
028  public ObjectConverter(IWorkerContext context) {
029    this.context = context;
030  }
031
032  public Element convert(Resource ig) throws IOException, FHIRFormatError, DefinitionException {
033    if (ig == null)
034      return null;
035    ByteArrayOutputStream bs = new ByteArrayOutputStream();
036    org.hl7.fhir.dstu3.formats.JsonParser jp = new org.hl7.fhir.dstu3.formats.JsonParser();
037    jp.compose(bs, ig);
038    ByteArrayInputStream bi = new ByteArrayInputStream(bs.toByteArray());
039    return new JsonParser(context).parse(bi);
040  }
041
042  public Element convert(Property property, Type type) throws FHIRException {
043    return convertElement(property, type);
044  }
045  
046  private Element convertElement(Property property, Base base) throws FHIRException {
047    if (base == null)
048      return null;
049    String tn = base.fhirType();
050    StructureDefinition sd = context.fetchResource(StructureDefinition.class, "http://hl7.org/fhir/StructureDefinition/"+tn);
051    if (sd == null)
052      throw new FHIRException("Unable to find definition for type "+tn);
053    Element res = new Element(property.getName(), property);
054    if (sd.getKind() == StructureDefinitionKind.PRIMITIVETYPE) 
055      res.setValue(((PrimitiveType) base).asStringValue());
056
057    List<ElementDefinition> children = ProfileUtilities.getChildMap(sd, sd.getSnapshot().getElementFirstRep()); 
058    for (ElementDefinition child : children) {
059      String n = tail(child.getPath());
060      if (sd.getKind() != StructureDefinitionKind.PRIMITIVETYPE || !"value".equals(n)) {
061        Base[] values = base.getProperty(n.hashCode(), n, false);
062        if (values != null)
063          for (Base value : values) {
064            res.getChildren().add(convertElement(new Property(context, child, sd), value));
065          }
066      }
067    }
068    return res;
069  }
070
071  private String tail(String path) {
072    if (path.contains("."))
073      return path.substring(path.lastIndexOf('.')+1);
074    else
075      return path;
076  }
077
078  public Type convertToType(Element element) throws FHIRException {
079    Type b = new Factory().create(element.fhirType());
080    if (b instanceof PrimitiveType) {
081      ((PrimitiveType) b).setValueAsString(element.primitiveValue());
082    } else {
083      for (Element child : element.getChildren()) {
084        b.setProperty(child.getName(), convertToType(child));
085      }
086    }
087    return b;
088  }
089
090  public Resource convert(Element element) throws FHIRException {
091    ByteArrayOutputStream bo = new ByteArrayOutputStream();
092    try {
093      new JsonParser(context).compose(element, bo, OutputStyle.NORMAL, null);
094      return new org.hl7.fhir.dstu3.formats.JsonParser().parse(bo.toByteArray());
095    } catch (IOException e) {
096      // won't happen
097      throw new FHIRException(e);
098    }
099    
100  }
101
102
103}