
001package org.hl7.fhir.r5.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 032 033 034import java.io.OutputStreamWriter; 035import java.util.ArrayList; 036import java.util.List; 037 038import org.hl7.fhir.exceptions.FHIRException; 039import org.hl7.fhir.r5.context.IWorkerContext; 040import org.hl7.fhir.r5.model.ElementDefinition; 041import org.hl7.fhir.r5.model.StructureDefinition; 042import org.hl7.fhir.r5.model.StructureDefinition.StructureDefinitionKind; 043import org.hl7.fhir.r5.model.StructureDefinition.TypeDerivationRule; 044import org.hl7.fhir.utilities.MarkedToMoveToAdjunctPackage; 045import org.hl7.fhir.utilities.Utilities; 046 047@MarkedToMoveToAdjunctPackage 048public class ProtoBufGenerator { 049 050 private IWorkerContext context; 051 private StructureDefinition definition; 052 private OutputStreamWriter destination; 053 private int cursor; 054 private Message message; 055 056 private class Field { 057 private String name; 058 private boolean required; 059 private boolean repeating; 060 private String type; 061 } 062 063 private class Message { 064 private String name; 065 private List<Field> fields = new ArrayList<Field>(); 066 private List<Message> messages = new ArrayList<Message>(); 067 public Message(String name) { 068 super(); 069 this.name = name; 070 } 071 072 073 } 074 075 public ProtoBufGenerator(IWorkerContext context) { 076 super(); 077 this.context = context; 078 } 079 080 public ProtoBufGenerator(IWorkerContext context, StructureDefinition definition, OutputStreamWriter destination) { 081 super(); 082 this.context = context; 083 this.definition = definition; 084 this.destination = destination; 085 } 086 087 public IWorkerContext getContext() { 088 return context; 089 } 090 091 public StructureDefinition getDefinition() { 092 return definition; 093 } 094 095 public void setDefinition(StructureDefinition definition) { 096 this.definition = definition; 097 } 098 099 public OutputStreamWriter getDestination() { 100 return destination; 101 } 102 103 public void setDestination(OutputStreamWriter destination) { 104 this.destination = destination; 105 } 106 107 108 public void build() throws FHIRException { 109 if (definition == null) 110 throw new FHIRException("A definition must be provided"); 111 if (destination == null) 112 throw new FHIRException("A destination must be provided"); 113 114 if (definition.getDerivation() == TypeDerivationRule.CONSTRAINT) 115 throw new FHIRException("derivation = constraint is not supported yet"); 116 117 message = new Message(definition.getSnapshot().getElement().get(0).getPath()); 118 cursor = 1; 119 while (cursor < definition.getSnapshot().getElement().size()) { 120 ElementDefinition ed = definition.getSnapshot().getElement().get(0); 121 Field fld = new Field(); 122 fld.name = tail(ed.getPath()); 123 fld.required = (ed.getMin() == 1); 124 fld.repeating = (!ed.getMax().equals("1")); 125 message.fields.add(fld); 126 if (ed.getType().size() != 1) 127 fld.type = "Unknown"; 128 else { 129 StructureDefinition td = context.fetchTypeDefinition(ed.getTypeFirstRep().getWorkingCode()); 130 if (td == null) 131 fld.type = "Unresolved"; 132 else if (td.getKind() == StructureDefinitionKind.PRIMITIVETYPE) { 133 fld.type = protoTypeForFhirType(ed.getTypeFirstRep().getWorkingCode()); 134 fld = new Field(); 135 fld.name = tail(ed.getPath())+"Extra"; 136 fld.repeating = (!ed.getMax().equals("1")); 137 fld.type = "Primitive"; 138 message.fields.add(fld); 139 } else 140 fld.type = ed.getTypeFirstRep().getWorkingCode(); 141 } 142 } 143 } 144 145 private String protoTypeForFhirType(String code) { 146 if (Utilities.existsInList(code, "integer", "unsignedInt", "positiveInt")) 147 return "int23"; 148 else if (code.equals("boolean")) 149 return "bool"; 150 else 151 return "string"; 152 } 153 154 private String tail(String path) { 155 return path.substring(path.lastIndexOf(".")+1); 156 } 157 158 159}