001package org.hl7.fhir.r5.renderers.spreadsheets;
002
003import java.io.IOException;
004import java.util.List;
005
006import org.apache.poi.ss.usermodel.Sheet;
007import org.hl7.fhir.r5.context.IWorkerContext;
008import org.hl7.fhir.r5.model.CanonicalType;
009import org.hl7.fhir.r5.model.ValueSet;
010import org.hl7.fhir.r5.model.ValueSet.ConceptReferenceComponent;
011import org.hl7.fhir.r5.model.ValueSet.ConceptSetComponent;
012import org.hl7.fhir.r5.model.ValueSet.ConceptSetFilterComponent;
013import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionContainsComponent;
014import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionParameterComponent;
015
016public class ValueSetSpreadsheetGenerator extends CanonicalSpreadsheetGenerator {
017
018  public ValueSetSpreadsheetGenerator(IWorkerContext context) {
019    super(context);
020  }
021
022  public boolean canGenerate(ValueSet vs) {
023    return true;
024  }
025
026  public ValueSetSpreadsheetGenerator renderValueSet(ValueSet vs) throws IOException {
027    if (vs == null) {
028      System.out.println("no valueset!");
029    }
030    addValueSetMetadata(renderCanonicalResource(vs, false), vs);
031    int i = 0;
032    for (ConceptSetComponent inc : vs.getCompose().getInclude()) {
033      genInclude(vs, inc, "Include", i++);
034    }
035    for (ConceptSetComponent exc : vs.getCompose().getExclude()) {
036      genInclude(vs, exc, "Exclude", i++);
037    }   
038    if (vs.hasExpansion()) {
039      if (vs.getExpansion().hasParameter()) {
040        genExpansionParams(vs.getExpansion().getParameter());        
041      }
042      genExpansion(vs.getExpansion().getContains());
043    }
044    return this;
045  }
046
047  private void addValueSetMetadata(Sheet sheet, ValueSet vs) {
048    addMetadataRow(sheet, "Immutable", vs.getImmutableElement().toString());
049  }
050
051  private void genExpansionParams(List<ValueSetExpansionParameterComponent> params) {
052    Sheet sheet = makeSheet("Expansion Parameters");
053    addHeaders(sheet, "Parameter", "Value");
054    for (ValueSetExpansionParameterComponent p : params) {
055      addRow(sheet, p.getName(), dr.displayDataType(p.getValue()));          
056    }    
057  }
058
059  private void genExpansion(List<ValueSetExpansionContainsComponent> list) {
060    Sheet sheet = makeSheet("Expansion");
061    addHeaders(sheet, "Level", "System", "version", "Code", "Display", "Abstract", "Inactive");
062    genExpansionEntry(1, list, sheet);    
063  }
064
065  public void genExpansionEntry(int level, List<ValueSetExpansionContainsComponent> list, Sheet sheet) {
066    for (ValueSetExpansionContainsComponent p : list) {
067      addRow(sheet, Integer.toString(level), p.getSystem(), p.getVersion(), p.getCode(), p.getDisplay(), bool(p.getAbstract()), bool(p.getInactive()));  
068      if (p.hasContains()) {
069        genExpansionEntry(level + 1, p.getContains(), sheet);
070      }
071    }
072  }
073  
074  private String bool(boolean value) {    
075    return value ? "" : "false";
076  }
077
078  private void genInclude(ValueSet vs, ConceptSetComponent inc, String mode, int count) {
079    if (inc.hasSystem()) {
080      genIncludeSystem(vs, inc, mode, count);
081    } else {
082      genIncludeValueSets(vs, inc, mode, count);      
083    }
084//    String subname = inc.hasSystem() ?  : "ValueSets";
085//    
086//
087//  Row headerRow = sheet.createRow(0);
088//  for (int i = 0; i < titles.length; i++) {
089//    addCell(headerRow, i, titles[i], styles.get("header"));
090//  }
091//  int i = titles.length - 1;
092//  for (StructureDefinitionMappingComponent map : sd.getMapping()) {
093//    i++;
094//    addCell(headerRow, i, "Mapping: " + map.getName(), styles.get("header"));
095//  }    
096//
097//  for (ElementDefinition child : sd.getSnapshot().getElement()) {
098//    processElement(sheet, sd, child);
099//  }
100//  configureSheet(sheet, sd);
101  }
102
103  private void genIncludeValueSets(ValueSet vs, ConceptSetComponent inc, String mode, int count) {
104    Sheet sheet = makeSheet(mode+" ValueSet #"+count);
105    addValueSets(sheet, inc.getValueSet()); 
106    configureSheet(sheet);
107  }
108
109  private void genIncludeSystem(ValueSet vs, ConceptSetComponent inc, String mode, int count) {
110    Sheet sheet = makeSheet(mode+" #"+count);
111    if (inc.hasValueSet()) {
112      addValueSets(sheet, inc.getValueSet());
113    }
114    if (inc.hasFilter()) {
115      addFilters(sheet, inc.getFilter());
116    }
117    if (inc.hasConcept()) {
118      addConcepts(sheet, inc.getConcept());
119    }
120    if (!inc.hasConcept() && !inc.hasFilter()) {
121      addAllCodes(sheet);
122    }
123    addRow(sheet, "", "");          
124    addRow(sheet, "System URI", inc.getSystem());          
125    
126    configureSheet(sheet);
127  }
128
129  private void addAllCodes(Sheet sheet) {
130    addHeaders(sheet, "Codes");     
131    addRow(sheet, "All codes");          
132  }
133
134  private void addValueSets(Sheet sheet, List<CanonicalType> valueSets) {
135    addHeaders(sheet, "ValueSet URL");
136    for (CanonicalType u : valueSets) {
137      addRow(sheet, u.getValue());
138    }
139  }
140
141  private void configureSheet(Sheet sheet) {
142    sheet.setColumnWidth(0, columnPixels(30));
143    sheet.setColumnWidth(1, columnPixels(40));
144    sheet.setColumnWidth(1, columnPixels(50));
145  }
146
147  private void addConcepts(Sheet sheet, List<ConceptReferenceComponent> concepts) {
148    addHeaders(sheet, "Concept", "Description"); // todo: designations    
149    for (ConceptReferenceComponent cd : concepts) {
150      addRow(sheet, cd.getCode(), cd.getDisplay());      
151    }    
152  }
153
154  private void addFilters(Sheet sheet, List<ConceptSetFilterComponent> filters) {
155    addHeaders(sheet, "Property", "Operation", "Value");    
156    for (ConceptSetFilterComponent f : filters) {
157      addRow(sheet, f.getProperty(), f.getOpElement().asStringValue(), f.getValue());
158    }
159  }
160
161}