001package org.hl7.fhir.dstu3.elementmodel;
002
003/*-
004 * #%L
005 * org.hl7.fhir.dstu3
006 * %%
007 * Copyright (C) 2014 - 2019 Health Level 7
008 * %%
009 * Licensed under the Apache License, Version 2.0 (the "License");
010 * you may not use this file except in compliance with the License.
011 * You may obtain a copy of the License at
012 * 
013 *      http://www.apache.org/licenses/LICENSE-2.0
014 * 
015 * Unless required by applicable law or agreed to in writing, software
016 * distributed under the License is distributed on an "AS IS" BASIS,
017 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
018 * See the License for the specific language governing permissions and
019 * limitations under the License.
020 * #L%
021 */
022
023
024import java.io.ByteArrayInputStream;
025import java.io.ByteArrayOutputStream;
026import java.io.IOException;
027import java.util.ArrayList;
028import java.util.List;
029
030import org.hl7.fhir.dstu3.conformance.ProfileUtilities;
031import org.hl7.fhir.dstu3.context.IWorkerContext;
032import org.hl7.fhir.dstu3.formats.IParser.OutputStyle;
033import org.hl7.fhir.dstu3.model.Base;
034import org.hl7.fhir.dstu3.model.CodeableConcept;
035import org.hl7.fhir.dstu3.model.Coding;
036import org.hl7.fhir.dstu3.model.ElementDefinition;
037import org.hl7.fhir.dstu3.model.Factory;
038import org.hl7.fhir.dstu3.model.Identifier;
039import org.hl7.fhir.dstu3.model.PrimitiveType;
040import org.hl7.fhir.dstu3.model.Reference;
041import org.hl7.fhir.dstu3.model.Resource;
042import org.hl7.fhir.dstu3.model.StructureDefinition;
043import org.hl7.fhir.dstu3.model.StructureDefinition.StructureDefinitionKind;
044import org.hl7.fhir.dstu3.model.Type;
045import org.hl7.fhir.exceptions.DefinitionException;
046import org.hl7.fhir.exceptions.FHIRException;
047import org.hl7.fhir.exceptions.FHIRFormatError;
048
049
050
051public class ObjectConverter  {
052
053  private IWorkerContext context;
054
055  public ObjectConverter(IWorkerContext context) {
056    this.context = context;
057  }
058
059  public Element convert(Resource ig) throws IOException, FHIRFormatError, DefinitionException {
060    if (ig == null)
061      return null;
062    ByteArrayOutputStream bs = new ByteArrayOutputStream();
063    org.hl7.fhir.dstu3.formats.JsonParser jp = new org.hl7.fhir.dstu3.formats.JsonParser();
064    jp.compose(bs, ig);
065    ByteArrayInputStream bi = new ByteArrayInputStream(bs.toByteArray());
066    return new JsonParser(context).parse(bi);
067  }
068
069  public Element convert(Property property, Type type) throws FHIRException {
070    return convertElement(property, type);
071  }
072  
073  private Element convertElement(Property property, Base base) throws FHIRException {
074    if (base == null)
075      return null;
076    String tn = base.fhirType();
077    StructureDefinition sd = context.fetchTypeDefinition(tn);
078    if (sd == null)
079      throw new FHIRException("Unable to find definition for type "+tn);
080    Element res = new Element(property.getName(), property);
081    if (sd.getKind() == StructureDefinitionKind.PRIMITIVETYPE) 
082      res.setValue(((PrimitiveType) base).asStringValue());
083
084    List<ElementDefinition> children = ProfileUtilities.getChildMap(sd, sd.getSnapshot().getElementFirstRep()); 
085    for (ElementDefinition child : children) {
086      String n = tail(child.getPath());
087      if (sd.getKind() != StructureDefinitionKind.PRIMITIVETYPE || !"value".equals(n)) {
088        Base[] values = base.getProperty(n.hashCode(), n, false);
089        if (values != null)
090          for (Base value : values) {
091            res.getChildren().add(convertElement(new Property(context, child, sd), value));
092          }
093      }
094    }
095    return res;
096  }
097
098  private String tail(String path) {
099    if (path.contains("."))
100      return path.substring(path.lastIndexOf('.')+1);
101    else
102      return path;
103  }
104
105  public Type convertToType(Element element) throws FHIRException {
106    Type b = new Factory().create(element.fhirType());
107    if (b instanceof PrimitiveType) {
108      ((PrimitiveType) b).setValueAsString(element.primitiveValue());
109    } else {
110      for (Element child : element.getChildren()) {
111        b.setProperty(child.getName(), convertToType(child));
112      }
113    }
114    return b;
115  }
116
117  public Resource convert(Element element) throws FHIRException {
118    ByteArrayOutputStream bo = new ByteArrayOutputStream();
119    try {
120      new JsonParser(context).compose(element, bo, OutputStyle.NORMAL, null);
121      return new org.hl7.fhir.dstu3.formats.JsonParser().parse(bo.toByteArray());
122    } catch (IOException e) {
123      // won't happen
124      throw new FHIRException(e);
125    }
126    
127  }
128
129  public static CodeableConcept readAsCodeableConcept(Element element) {
130    CodeableConcept cc = new CodeableConcept();
131    List<Element> list = new ArrayList<Element>();
132    element.getNamedChildren("coding", list);
133    for (Element item : list)
134      cc.addCoding(readAsCoding(item));
135    cc.setText(element.getNamedChildValue("text"));
136    return cc;
137  }
138
139  public static Coding readAsCoding(Element item) {
140    Coding c = new Coding();
141    c.setSystem(item.getNamedChildValue("system"));
142    c.setVersion(item.getNamedChildValue("version"));
143    c.setCode(item.getNamedChildValue("code"));
144    c.setDisplay(item.getNamedChildValue("display"));
145    return c;
146  }
147
148  public static Identifier readAsIdentifier(Element item) {
149    Identifier r = new Identifier();
150    r.setSystem(item.getNamedChildValue("system"));
151    r.setValue(item.getNamedChildValue("value"));
152    return r;
153  }
154
155  public static Reference readAsReference(Element item) {
156    Reference r = new Reference();
157    r.setDisplay(item.getNamedChildValue("display"));
158    r.setReference(item.getNamedChildValue("reference"));
159    List<Element> identifier = item.getChildrenByName("identifier");
160    if (identifier.isEmpty() == false) {
161      r.setIdentifier(readAsIdentifier(identifier.get(0)));
162    }
163    return r;
164  }
165
166}