001package org.hl7.fhir.r5.renderers.spreadsheets; 002 003import java.io.FileOutputStream; 004import java.io.IOException; 005import java.io.OutputStream; 006import java.util.List; 007 008import org.apache.poi.ss.usermodel.Row; 009import org.apache.poi.ss.usermodel.Sheet; 010import org.hl7.fhir.exceptions.DefinitionException; 011import org.hl7.fhir.r5.context.IWorkerContext; 012import org.hl7.fhir.r5.context.SimpleWorkerContext; 013import org.hl7.fhir.r5.model.CanonicalType; 014import org.hl7.fhir.r5.model.CodeSystem; 015import org.hl7.fhir.r5.model.CodeSystem.CodeSystemFilterComponent; 016import org.hl7.fhir.r5.model.CodeSystem.ConceptDefinitionComponent; 017import org.hl7.fhir.r5.model.CodeSystem.PropertyComponent; 018import org.hl7.fhir.r5.model.ElementDefinition; 019import org.hl7.fhir.r5.model.Enumeration; 020import org.hl7.fhir.r5.model.Enumerations.FilterOperator; 021import org.hl7.fhir.r5.model.ValueSet; 022import org.hl7.fhir.r5.model.ValueSet.ConceptReferenceComponent; 023import org.hl7.fhir.r5.model.ValueSet.ConceptSetComponent; 024import org.hl7.fhir.r5.model.ValueSet.ConceptSetFilterComponent; 025import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionContainsComponent; 026import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionParameterComponent; 027import org.hl7.fhir.r5.model.StructureDefinition.StructureDefinitionMappingComponent; 028import org.hl7.fhir.utilities.CommaSeparatedStringBuilder; 029import org.hl7.fhir.utilities.i18n.I18nConstants; 030 031public class CodeSystemSpreadsheetGenerator extends CanonicalSpreadsheetGenerator { 032 033 public CodeSystemSpreadsheetGenerator(IWorkerContext context) { 034 super(context); 035 } 036 037 public boolean canGenerate(CodeSystem cs) { 038 return true; 039 } 040 041 public CodeSystemSpreadsheetGenerator renderCodeSystem(CodeSystem cs) throws IOException { 042 if (cs == null) { 043 System.out.println("no code system!"); 044 } 045 addCodeSystemMetadata(renderCanonicalResource(cs, false), cs); 046 047 if (cs.hasProperty()) { 048 addProperties(cs.getProperty()); 049 } 050 if (cs.hasFilter()) { 051 addFilters(cs.getFilter()); 052 } 053 if (cs.hasConcept()) { 054 addConcepts(cs.getConcept()); 055 } 056 return this; 057 } 058 059 private void addCodeSystemMetadata(Sheet sheet, CodeSystem cs) { 060 addMetadataRow(sheet, "Case Sensitive", cs.getCaseSensitiveElement().asStringValue()); 061 addMetadataRow(sheet, "Value Set (all codes)", cs.getValueSet()); 062 addMetadataRow(sheet, "Hierarchy", cs.getHierarchyMeaningElement().asStringValue()); 063 addMetadataRow(sheet, "Compositional", cs.getCompositionalElement().asStringValue()); 064 addMetadataRow(sheet, "Version Needed?", cs.getVersionNeededElement().asStringValue()); 065 addMetadataRow(sheet, "Content", cs.getContentElement().asStringValue()); 066 addMetadataRow(sheet, "Supplements", cs.getSupplements()); 067 addMetadataRow(sheet, "Count", cs.getCountElement().asStringValue()); 068 } 069 070 private void addFilters(List<CodeSystemFilterComponent> filters) { 071 Sheet sheet = makeSheet("Filters"); 072 addHeaders(sheet, "Code", "Description", "Operators", "Value"); 073 for (CodeSystemFilterComponent f : filters) { 074 CommaSeparatedStringBuilder cs = new CommaSeparatedStringBuilder(); 075 for (Enumeration<FilterOperator> op : f.getOperator()) { 076 cs.append(op.asStringValue()); 077 } 078 addRow(sheet, f.getCode(), f.getDescription(), cs.toString(), f.getValue()); 079 } 080 } 081 082 private void addProperties(List<PropertyComponent> properties) { 083 Sheet sheet = makeSheet("Properties"); 084 addHeaders(sheet, "Code", "Uri", "Description", "Type"); 085 for (PropertyComponent p : properties) { 086 addRow(sheet, p.getCode(), p.getUri(), p.getDescription(), p.getTypeElement().asStringValue()); 087 } 088 } 089 090 private void addConcepts(List<ConceptDefinitionComponent> concepts) { 091 Sheet sheet = makeSheet("Concepts"); 092 addHeaders(sheet, "Level", "Code", "Display", "Definition"); //todo: properties and designations 093 addConcepts(sheet, 1, concepts); 094 } 095 096 private void addConcepts(Sheet sheet, int i, List<ConceptDefinitionComponent> concepts) { 097 for (ConceptDefinitionComponent c : concepts) { 098 addRow(sheet, Integer.toString(i), c.getCode(), c.getDisplay(), c.getDefinition()); 099 if (c.hasConcept()) { 100 addConcepts(sheet, i+1, c.getConcept()); 101 } 102 } 103 } 104 105 private void genExpansionParams(List<ValueSetExpansionParameterComponent> params) { 106 Sheet sheet = makeSheet("Expansion Parameters"); 107 addHeaders(sheet, "Parameter", "Value"); 108 for (ValueSetExpansionParameterComponent p : params) { 109 addRow(sheet, p.getName(), dr.displayDataType(p.getValue())); 110 } 111 } 112 113 private void genExpansion(List<ValueSetExpansionContainsComponent> list) { 114 Sheet sheet = makeSheet("Expansion"); 115 addHeaders(sheet, "Level", "System", "version", "Code", "Display", "Abstract", "Inactive"); 116 genExpansionEntry(1, list, sheet); 117 } 118 119 public void genExpansionEntry(int level, List<ValueSetExpansionContainsComponent> list, Sheet sheet) { 120 for (ValueSetExpansionContainsComponent p : list) { 121 addRow(sheet, Integer.toString(level), p.getSystem(), p.getVersion(), p.getCode(), p.getDisplay(), bool(p.getAbstract()), bool(p.getInactive())); 122 if (p.hasContains()) { 123 genExpansionEntry(level + 1, p.getContains(), sheet); 124 } 125 } 126 } 127 128 private String bool(boolean value) { 129 return value ? "" : "false"; 130 } 131 132// private void genInclude(ValueSet vs, ConceptSetComponent inc, String mode) { 133// if (inc.hasSystem()) { 134// genIncludeSystem(vs, inc, mode); 135// } else { 136// genIncludeValueSets(vs, inc, mode); 137// } 138// String subname = inc.hasSystem() ? : "ValueSets"; 139// 140// 141// Row headerRow = sheet.createRow(0); 142// for (int i = 0; i < titles.length; i++) { 143// addCell(headerRow, i, titles[i], styles.get("header")); 144// } 145// int i = titles.length - 1; 146// for (StructureDefinitionMappingComponent map : sd.getMapping()) { 147// i++; 148// addCell(headerRow, i, "Mapping: " + map.getName(), styles.get("header")); 149// } 150// 151// for (ElementDefinition child : sd.getSnapshot().getElement()) { 152// processElement(sheet, sd, child); 153// } 154// configureSheet(sheet, sd); 155// } 156 157// private void genIncludeValueSets(ValueSet vs, ConceptSetComponent inc, String mode) { 158// Sheet sheet = makeSheet(mode+" ValueSets"); 159// addValueSets(sheet, inc.getValueSet()); 160// configureSheet(sheet); 161// } 162// 163// private void genIncludeSystem(ValueSet vs, ConceptSetComponent inc, String mode) { 164// Sheet sheet = makeSheet(mode+" from "+dr.displaySystem(inc.getSystem())); 165// if (inc.hasValueSet()) { 166// addValueSets(sheet, inc.getValueSet()); 167// } 168// if (inc.hasFilter()) { 169// addFilters(sheet, inc.getFilter()); 170// } 171// if (inc.hasConcept()) { 172// addConcepts(sheet, inc.getConcept()); 173// } 174// if (!inc.hasConcept() && !inc.hasFilter()) { 175// addAllCodes(sheet); 176// } 177// addRow(sheet, "", ""); 178// addRow(sheet, "System URI", inc.getSystem()); 179// 180// configureSheet(sheet); 181// } 182 183 private void addAllCodes(Sheet sheet) { 184 addHeaders(sheet, "Codes"); 185 addRow(sheet, "All codes"); 186 } 187 188 private void addValueSets(Sheet sheet, List<CanonicalType> valueSets) { 189 addHeaders(sheet, "ValueSet URL"); 190 for (CanonicalType u : valueSets) { 191 addRow(sheet, u.getValue()); 192 } 193 } 194 195 private void configureSheet(Sheet sheet) { 196 sheet.setColumnWidth(0, columnPixels(30)); 197 sheet.setColumnWidth(1, columnPixels(40)); 198 sheet.setColumnWidth(1, columnPixels(50)); 199 } 200 201 private void addConcepts(Sheet sheet, List<ConceptReferenceComponent> concepts) { 202 addHeaders(sheet, "Concept", "Description"); // todo: designations 203 for (ConceptReferenceComponent cd : concepts) { 204 addRow(sheet, cd.getCode(), cd.getDisplay()); 205 } 206 } 207 208 private void addFilters(Sheet sheet, List<ConceptSetFilterComponent> filters) { 209 addHeaders(sheet, "Property", "Operation", "Value"); 210 for (ConceptSetFilterComponent f : filters) { 211 addRow(sheet, f.getProperty(), f.getOpElement().asStringValue(), f.getValue()); 212 } 213 } 214 215}