001package org.hl7.fhir.r4.utils;
002
003/*
004  Copyright (c) 2011+, HL7, Inc.
005  All rights reserved.
006  
007  Redistribution and use in source and binary forms, with or without modification, 
008  are permitted provided that the following conditions are met:
009    
010   * Redistributions of source code must retain the above copyright notice, this 
011     list of conditions and the following disclaimer.
012   * Redistributions in binary form must reproduce the above copyright notice, 
013     this list of conditions and the following disclaimer in the documentation 
014     and/or other materials provided with the distribution.
015   * Neither the name of HL7 nor the names of its contributors may be used to 
016     endorse or promote products derived from this software without specific 
017     prior written permission.
018  
019  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
020  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
021  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
022  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
023  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
024  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
025  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
026  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
027  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
028  POSSIBILITY OF SUCH DAMAGE.
029  
030 */
031
032import java.io.OutputStreamWriter;
033import java.util.ArrayList;
034import java.util.List;
035
036import org.hl7.fhir.exceptions.FHIRException;
037import org.hl7.fhir.r4.context.IWorkerContext;
038import org.hl7.fhir.r4.model.ElementDefinition;
039import org.hl7.fhir.r4.model.StructureDefinition;
040import org.hl7.fhir.r4.model.StructureDefinition.StructureDefinitionKind;
041import org.hl7.fhir.r4.model.StructureDefinition.TypeDerivationRule;
042import org.hl7.fhir.utilities.Utilities;
043
044@Deprecated
045public class ProtoBufGenerator {
046
047  private IWorkerContext context;
048  private StructureDefinition definition;
049  private OutputStreamWriter destination;
050  private int cursor;
051  private Message message;
052
053  private class Field {
054    private String name;
055    private boolean required;
056    private boolean repeating;
057    private String type;
058  }
059
060  private class Message {
061    private String name;
062    private List<Field> fields = new ArrayList<Field>();
063    private List<Message> messages = new ArrayList<Message>();
064
065    public Message(String name) {
066      super();
067      this.name = name;
068    }
069
070  }
071
072  public ProtoBufGenerator(IWorkerContext context) {
073    super();
074    this.context = context;
075  }
076
077  public ProtoBufGenerator(IWorkerContext context, StructureDefinition definition, OutputStreamWriter destination) {
078    super();
079    this.context = context;
080    this.definition = definition;
081    this.destination = destination;
082  }
083
084  public IWorkerContext getContext() {
085    return context;
086  }
087
088  public StructureDefinition getDefinition() {
089    return definition;
090  }
091
092  public void setDefinition(StructureDefinition definition) {
093    this.definition = definition;
094  }
095
096  public OutputStreamWriter getDestination() {
097    return destination;
098  }
099
100  public void setDestination(OutputStreamWriter destination) {
101    this.destination = destination;
102  }
103
104  public void build() throws FHIRException {
105    if (definition == null)
106      throw new FHIRException("A definition must be provided");
107    if (destination == null)
108      throw new FHIRException("A destination must be provided");
109
110    if (definition.getDerivation() == TypeDerivationRule.CONSTRAINT)
111      throw new FHIRException("derivation = constraint is not supported yet");
112
113    message = new Message(definition.getSnapshot().getElement().get(0).getPath());
114    cursor = 1;
115    while (cursor < definition.getSnapshot().getElement().size()) {
116      ElementDefinition ed = definition.getSnapshot().getElement().get(0);
117      Field fld = new Field();
118      fld.name = tail(ed.getPath());
119      fld.required = (ed.getMin() == 1);
120      fld.repeating = (!ed.getMax().equals("1"));
121      message.fields.add(fld);
122      if (ed.getType().size() != 1)
123        fld.type = "Unknown";
124      else {
125        StructureDefinition td = context.fetchTypeDefinition(ed.getTypeFirstRep().getWorkingCode());
126        if (td == null)
127          fld.type = "Unresolved";
128        else if (td.getKind() == StructureDefinitionKind.PRIMITIVETYPE) {
129          fld.type = protoTypeForFhirType(ed.getTypeFirstRep().getWorkingCode());
130          fld = new Field();
131          fld.name = tail(ed.getPath()) + "Extra";
132          fld.repeating = (!ed.getMax().equals("1"));
133          fld.type = "Primitive";
134          message.fields.add(fld);
135        } else
136          fld.type = ed.getTypeFirstRep().getWorkingCode();
137      }
138    }
139  }
140
141  private String protoTypeForFhirType(String code) {
142    if (Utilities.existsInList(code, "integer", "unsignedInt", "positiveInt"))
143      return "int23";
144    else if (code.equals("boolean"))
145      return "bool";
146    else
147      return "string";
148  }
149
150  private String tail(String path) {
151    return path.substring(path.lastIndexOf(".") + 1);
152  }
153
154}