
001package org.hl7.fhir.r4.utils.formats; 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.ByteArrayOutputStream; 033import java.io.IOException; 034import java.io.OutputStream; 035import java.io.UnsupportedEncodingException; 036import java.util.ArrayList; 037import java.util.Enumeration; 038import java.util.List; 039 040import org.hl7.fhir.r4.formats.IParser.OutputStyle; 041import org.hl7.fhir.r4.formats.JsonParser; 042import org.hl7.fhir.r4.formats.XmlParser; 043import org.hl7.fhir.r4.model.Coding; 044import org.hl7.fhir.r4.model.ElementDefinition; 045import org.hl7.fhir.r4.model.ElementDefinition.ElementDefinitionConstraintComponent; 046import org.hl7.fhir.r4.model.ElementDefinition.ElementDefinitionMappingComponent; 047import org.hl7.fhir.r4.model.ElementDefinition.ElementDefinitionSlicingDiscriminatorComponent; 048import org.hl7.fhir.r4.model.ElementDefinition.TypeRefComponent; 049import org.hl7.fhir.r4.model.IdType; 050import org.hl7.fhir.r4.model.StringType; 051import org.hl7.fhir.r4.model.StructureDefinition; 052import org.hl7.fhir.r4.model.StructureDefinition.StructureDefinitionMappingComponent; 053import org.hl7.fhir.r4.model.Type; 054import org.hl7.fhir.r4.model.UriType; 055import org.hl7.fhir.utilities.TextStreamWriter; 056 057@Deprecated 058public class CSVWriter extends TextStreamWriter { 059 060 private StructureDefinition def; 061 private List<StructureDefinitionMappingComponent> mapKeys = new ArrayList<StructureDefinitionMappingComponent>(); 062 private List<CSVLine> lines = new ArrayList<CSVLine>(); 063 private XmlParser xml = new XmlParser(); 064 private JsonParser json = new JsonParser(); 065 private boolean asXml; 066 067 private class CSVLine { 068 private String line = ""; 069 070 public void addString(String s) { 071 line = line + (line.equals("") ? "" : ",") + "\"" + csvEscape(s) + "\""; 072 } 073 074 public void addString(StringType s) { 075 addString(s == null ? "" : s.getValue()); 076 } 077 078 public void addValue(String s) { 079 line = line + (line.equals("") ? "" : ",") + s; 080 } 081 082 public void addValue(int s) { 083 line = line + (line.equals("") ? "" : ",") + s; 084 } 085 086 public void addBoolean(boolean b) { 087 addValue(b ? "Y" : ""); 088 } 089 090 protected String csvEscape(String s) { 091 if (s == null) 092 return ""; 093 else if (s.contains("\"")) 094 return s.substring(0, s.indexOf("\"")) + "\"\"" + csvEscape(s.substring(s.indexOf("\"") + 1)); 095 else 096 return s; 097 } 098 099 public String toString() { 100 return line; 101 } 102 } 103 104 public CSVWriter(OutputStream out, StructureDefinition def, boolean asXml) throws UnsupportedEncodingException { 105 super(out); 106 this.asXml = asXml; 107 this.def = def; 108 CSVLine header = new CSVLine(); 109 lines.add(header); 110 header.addString("Path"); // A 111 header.addString("Slice Name"); // B 112 header.addString("Alias(s)"); // C 113 header.addString("Label"); // D 114 header.addString("Min"); // E 115 header.addString("Max"); // F 116 header.addString("Must Support?"); // G 117 header.addString("Is Modifier?"); // H 118 header.addString("Is Summary?"); // I 119 header.addString("Type(s)"); // J 120 header.addString("Short"); // K 121 header.addString("Definition"); // L 122 header.addString("Comments"); // M 123 header.addString("Requirements"); // N 124 header.addString("Default Value"); // O 125 header.addString("Meaning When Missing"); // P 126 header.addString("Fixed Value"); // Q 127 header.addString("Pattern"); // R 128 header.addString("Example"); // S 129 header.addString("Minimum Value"); // T 130 header.addString("Maximum Value"); // U 131 header.addString("Maximum Length"); // V 132 header.addString("Binding Strength"); // W 133 header.addString("Binding Description"); // X 134 header.addString("Binding Value Set"); // Y 135 header.addString("Code"); // Z 136 header.addString("Slicing Discriminator");// AA 137 header.addString("Slicing Description"); // AB 138 header.addString("Slicing Ordered"); // AC 139 header.addString("Slicing Rules"); // AD 140 header.addString("Base Path"); // AE 141 header.addString("Base Min"); // AF 142 header.addString("Base Max"); // AG 143 header.addString("Condition(s)"); // AH 144 header.addString("Constraint(s)"); // AI 145 for (StructureDefinitionMappingComponent map : def.getMapping()) { 146 header.addString("Mapping: " + map.getName()); 147 } 148 } 149 150 /* 151 * private void findMapKeys(StructureDefinition def, 152 * List<StructureDefinitionMappingComponent> maps, IWorkerContext context) { 153 * maps.addAll(def.getMapping()); if (def.getBaseDefinition()!=null) { 154 * StructureDefinition base = context.fetchResource(StructureDefinition.class, 155 * def.getBaseDefinition()); findMapKeys(base, maps, context); } } 156 */ 157 158 public void processElement(ElementDefinition ed) throws Exception { 159 CSVLine line = new CSVLine(); 160 lines.add(line); 161 line.addString(ed.getPath()); 162 line.addString(ed.getSliceName()); 163 line.addString(itemList(ed.getAlias())); 164 line.addString(ed.getLabel()); 165 line.addValue(ed.getMin()); 166 line.addValue(ed.getMax()); 167 line.addString(ed.getMustSupport() ? "Y" : ""); 168 line.addString(ed.getIsModifier() ? "Y" : ""); 169 line.addString(ed.getIsSummary() ? "Y" : ""); 170 line.addString(itemList(ed.getType())); 171 line.addString(ed.getShort()); 172 line.addString(ed.getDefinition()); 173 line.addString(ed.getComment()); 174 line.addString(ed.getRequirements()); 175 line.addString(ed.getDefaultValue() != null ? renderType(ed.getDefaultValue()) : ""); 176 line.addString(ed.getMeaningWhenMissing()); 177 line.addString(ed.hasFixed() ? renderType(ed.getFixed()) : ""); 178 line.addString(ed.hasPattern() ? renderType(ed.getPattern()) : ""); 179 line.addString(ed.hasExample() ? renderType(ed.getExample().get(0).getValue()) : ""); // todo...? 180 line.addString(ed.hasMinValue() ? renderType(ed.getMinValue()) : ""); 181 line.addString(ed.hasMaxValue() ? renderType(ed.getMaxValue()) : ""); 182 line.addValue((ed.hasMaxLength() ? Integer.toString(ed.getMaxLength()) : "")); 183 if (ed.hasBinding()) { 184 line.addString(ed.getBinding().getStrength() != null ? ed.getBinding().getStrength().toCode() : ""); 185 line.addString(ed.getBinding().getDescription()); 186 if (ed.getBinding().getValueSet() == null) 187 line.addString(""); 188 else 189 line.addString(ed.getBinding().getValueSet()); 190 } else { 191 line.addValue(""); 192 line.addValue(""); 193 line.addValue(""); 194 } 195 line.addString(itemList(ed.getCode())); 196 if (ed.hasSlicing()) { 197 line.addString(itemList(ed.getSlicing().getDiscriminator())); 198 line.addString(ed.getSlicing().getDescription()); 199 line.addBoolean(ed.getSlicing().getOrdered()); 200 line.addString(ed.getSlicing().getRules() != null ? ed.getSlicing().getRules().toCode() : ""); 201 } else { 202 line.addValue(""); 203 line.addValue(""); 204 line.addValue(""); 205 } 206 if (ed.getBase() != null) { 207 line.addString(ed.getBase().getPath()); 208 line.addValue(ed.getBase().getMin()); 209 line.addValue(ed.getBase().getMax()); 210 } else { 211 line.addValue(""); 212 line.addValue(""); 213 line.addValue(""); 214 } 215 line.addString(itemList(ed.getCondition())); 216 line.addString(itemList(ed.getConstraint())); 217 for (StructureDefinitionMappingComponent mapKey : def.getMapping()) { 218 for (ElementDefinitionMappingComponent map : ed.getMapping()) { 219 if (map.getIdentity().equals(mapKey.getIdentity())) 220 line.addString(map.getMap()); 221 } 222 } 223 } 224 225 private String itemList(List l) { 226 StringBuilder s = new StringBuilder(); 227 for (int i = 0; i < l.size(); i++) { 228 Object o = l.get(i); 229 String val = ""; 230 if (o instanceof StringType) { 231 val = ((StringType) o).getValue(); 232 } else if (o instanceof UriType) { 233 val = ((UriType) o).getValue(); 234 } else if (o instanceof IdType) { 235 val = ((IdType) o).getValue(); 236 } else if (o instanceof Enumeration<?>) { 237 val = o.toString(); 238 } else if (o instanceof TypeRefComponent) { 239 TypeRefComponent t = (TypeRefComponent) o; 240 val = t.getWorkingCode() + (t.getProfile() == null ? "" : " {" + t.getProfile() + "}") 241 + (t.getTargetProfile() == null ? "" : " {" + t.getTargetProfile() + "}") 242 + (t.getAggregation() == null || t.getAggregation().isEmpty() ? "" 243 : " (" + itemList(t.getAggregation()) + ")"); 244 } else if (o instanceof Coding) { 245 Coding t = (Coding) o; 246 val = (t.getSystem() == null ? "" : t.getSystem()) + (t.getCode() == null ? "" : "#" + t.getCode()) 247 + (t.getDisplay() == null ? "" : " (" + t.getDisplay() + ")"); 248 } else if (o instanceof ElementDefinitionConstraintComponent) { 249 ElementDefinitionConstraintComponent c = (ElementDefinitionConstraintComponent) o; 250 val = c.getKey() + ":" + c.getHuman() + " {" + c.getExpression() + "}"; 251 } else if (o instanceof ElementDefinitionSlicingDiscriminatorComponent) { 252 ElementDefinitionSlicingDiscriminatorComponent c = (ElementDefinitionSlicingDiscriminatorComponent) o; 253 val = c.getType().toCode() + ":" + c.getPath() + "}"; 254 255 } else { 256 val = o.toString(); 257 val = val.substring(val.indexOf("[") + 1); 258 val = val.substring(0, val.indexOf("]")); 259 } 260 s = s.append(val); 261 if (i == 0) 262 s.append("\n"); 263 } 264 return s.toString(); 265 } 266 267 private String renderType(Type value) throws Exception { 268 String s = null; 269 ByteArrayOutputStream bs = new ByteArrayOutputStream(); 270 if (asXml) { 271 xml.setOutputStyle(OutputStyle.PRETTY); 272 xml.compose(bs, "", value); 273 bs.close(); 274 s = bs.toString(); 275 s = s.substring(s.indexOf("\n") + 2); 276 } else { 277 json.setOutputStyle(OutputStyle.PRETTY); 278 json.compose(bs, value, ""); 279 bs.close(); 280 s = bs.toString(); 281 } 282 return s; 283 } 284 285 public void dump() throws IOException { 286 for (CSVLine l : lines) 287 ln(l.toString()); 288 289 flush(); 290 close(); 291 } 292 293}