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