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