001package org.hl7.fhir.r5.utils;
002
003import java.util.ArrayList;
004import java.util.Arrays;
005import java.util.List;
006
007import org.hl7.fhir.r5.model.CanonicalResource;
008import org.hl7.fhir.r5.model.CapabilityStatement;
009import org.hl7.fhir.r5.model.CapabilityStatement.CapabilityStatementRestComponent;
010import org.hl7.fhir.r5.model.CapabilityStatement.CapabilityStatementRestResourceComponent;
011import org.hl7.fhir.r5.model.CapabilityStatement.CapabilityStatementRestResourceOperationComponent;
012import org.hl7.fhir.r5.model.CapabilityStatement.CapabilityStatementRestResourceSearchParamComponent;
013import org.hl7.fhir.r5.model.CapabilityStatement.ResourceInteractionComponent;
014import org.hl7.fhir.r5.model.CapabilityStatement.SystemInteractionComponent;
015import org.hl7.fhir.r5.model.CodeSystem;
016import org.hl7.fhir.r5.model.CodeSystem.CodeSystemFilterComponent;
017import org.hl7.fhir.r5.model.CodeSystem.ConceptDefinitionComponent;
018import org.hl7.fhir.r5.model.CodeSystem.PropertyComponent;
019import org.hl7.fhir.r5.model.ConceptMap;
020import org.hl7.fhir.r5.model.ConceptMap.AdditionalAttributeComponent;
021import org.hl7.fhir.r5.model.ConceptMap.ConceptMapGroupComponent;
022import org.hl7.fhir.r5.model.ConceptMap.SourceElementComponent;
023import org.hl7.fhir.r5.model.ConceptMap.TargetElementComponent;
024import org.hl7.fhir.r5.model.DomainResource;
025import org.hl7.fhir.r5.model.ElementDefinition;
026import org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionBindingAdditionalComponent;
027import org.hl7.fhir.r5.model.NamingSystem;
028import org.hl7.fhir.r5.model.NamingSystem.NamingSystemUniqueIdComponent;
029import org.hl7.fhir.r5.model.OperationDefinition;
030import org.hl7.fhir.r5.model.OperationDefinition.OperationDefinitionOverloadComponent;
031import org.hl7.fhir.r5.model.OperationDefinition.OperationDefinitionParameterComponent;
032import org.hl7.fhir.r5.model.Questionnaire;
033import org.hl7.fhir.r5.model.Questionnaire.QuestionnaireItemComponent;
034import org.hl7.fhir.r5.model.Resource;
035import org.hl7.fhir.r5.model.SearchParameter;
036import org.hl7.fhir.r5.model.StructureDefinition;
037import org.hl7.fhir.r5.model.StructureDefinition.StructureDefinitionKind;
038import org.hl7.fhir.r5.model.ValueSet;
039import org.hl7.fhir.utilities.Utilities;
040
041public class ResourceMinifier {
042
043  private static final List<String> VALIDATION_EXTENSIONS =
044      Arrays.asList(ToolingExtensions.EXT_OBLIGATION_INHERITS, ToolingExtensions.EXT_OBLIGATION_PROFILE_FLAG);
045
046  public boolean isMinified(String resName) {
047    return Utilities.existsInList(resName, "StructureDefinition", "CodeSystem", "ValueSet", "CapabilityStatement",
048       "ConceptMap", "NamingSystem", "OperationDefinition", "SearchParameter", "Questionnaire");
049  }
050  
051  public boolean minify(Resource res) {
052    if (res instanceof StructureDefinition) {
053      return minifySD((StructureDefinition) res);
054    } else if (res instanceof ValueSet) {
055      minifyVS((ValueSet) res);
056    } else if (res instanceof CodeSystem) {
057      minifyCS((CodeSystem) res);
058    } else if (res instanceof CapabilityStatement) {
059      minifyCS((CapabilityStatement) res);
060    } else if (res instanceof ConceptMap) {
061      minifyCM((ConceptMap) res);
062    } else if (res instanceof NamingSystem) {
063      minifyNS((NamingSystem) res);
064    } else if (res instanceof OperationDefinition) {
065      minifyOD((OperationDefinition) res);
066    } else if (res instanceof Questionnaire) {
067      minifyQ((Questionnaire) res);
068    } else if (res instanceof SearchParameter) {
069      minifySP((SearchParameter) res);
070    }
071    return true;
072  }
073
074  private void minifySP(SearchParameter sp) {
075    minCR(sp);
076    // nothing
077  }
078
079  private void minifyQ(Questionnaire q) {
080    minCR(q);
081
082    q.setApprovalDate(null);
083    q.setLastReviewDate(null);
084    q.setEffectivePeriod(null);
085    q.setCode(null);
086    for (QuestionnaireItemComponent item : q.getItem()) {
087      minifyQItem(item);
088      
089    }
090  }
091
092  private void minifyQItem(QuestionnaireItemComponent item) {
093    item.setCode(null);
094    item.setPrefix(null);
095    item.setText(null);
096    for (QuestionnaireItemComponent child : item.getItem()) {
097      minifyQItem(child);
098    }
099  }
100
101  private void minifyOD(OperationDefinition od) {
102    minCR(od);
103    od.setComment(null);
104    for (OperationDefinitionParameterComponent p : od.getParameter()) {
105      minifyODP(p);
106    }
107    for (OperationDefinitionOverloadComponent ol : od.getOverload()) {
108      ol.setComment(null);
109    }
110  }
111
112  private void minifyODP(OperationDefinitionParameterComponent p) {
113    p.setDocumentation(null);
114    for (OperationDefinitionParameterComponent pp : p.getPart()) {
115      minifyODP(pp);
116    }
117  }
118
119  private void minifyNS(NamingSystem ns) {
120    minCR(ns);
121
122    ns.setApprovalDate(null);
123    ns.setLastReviewDate(null);
124    ns.setEffectivePeriod(null);
125    ns.setTopic(null);
126    ns.setAuthor(null);
127    ns.setEditor(null);
128    ns.setReviewer(null);
129    ns.setEndorser(null);
130    ns.setRelatedArtifact(null);
131    
132    ns.setUsage(null);
133    for (NamingSystemUniqueIdComponent id : ns.getUniqueId()) {
134      id.setComment(null);
135    }
136  }
137
138  private void minifyCM(ConceptMap cm) {
139    minCR(cm);
140    
141    cm.setApprovalDate(null);
142    cm.setLastReviewDate(null);
143    cm.setEffectivePeriod(null);
144    cm.setTopic(null);
145    cm.setAuthor(null);
146    cm.setEditor(null);
147    cm.setReviewer(null);
148    cm.setEndorser(null);
149    cm.setRelatedArtifact(null);
150
151    for (org.hl7.fhir.r5.model.ConceptMap.PropertyComponent prop : cm.getProperty()) {
152      prop.setDescription(null);
153    }
154    for (AdditionalAttributeComponent attr : cm.getAdditionalAttribute()) {
155      attr.setDescription(null);
156    }
157    for (ConceptMapGroupComponent group : cm.getGroup()) {
158      for (SourceElementComponent elem : group.getElement()) {
159        for (TargetElementComponent tgt : elem.getTarget()) {
160          tgt.setComment(null);
161        }
162      }
163    }
164  }
165
166  private void minifyCS(CapabilityStatement cs) {
167    minCR(cs);
168    
169    cs.setSoftware(null);
170    cs.setImplementation(null);
171    for (CapabilityStatementRestComponent rest : cs.getRest()) {
172      rest.setDocumentation(null);
173      rest.setSecurity(null);
174      for (CapabilityStatementRestResourceComponent res : rest.getResource()) {
175        res.setDocumentation(null);
176        for (ResourceInteractionComponent intr : res.getInteraction()) {
177          intr.setDocumentation(null);
178        }
179        for (CapabilityStatementRestResourceSearchParamComponent srch : res.getSearchParam()) {
180          srch.setDocumentation(null);
181        }
182        for (CapabilityStatementRestResourceOperationComponent op : res.getOperation()) {
183          op.setDocumentation(null);
184        }
185      }
186      for (SystemInteractionComponent intr : rest.getInteraction()) {
187        intr.setDocumentation(null);
188      }
189      for (CapabilityStatementRestResourceSearchParamComponent srch : rest.getSearchParam()) {
190        srch.setDocumentation(null);
191      }
192      for (CapabilityStatementRestResourceOperationComponent op : rest.getOperation()) {
193        op.setDocumentation(null);
194      }
195    }
196    cs.setMessaging(null);
197    cs.setDocument(null);
198  }
199  
200  private void minifyCS(CodeSystem cs) {
201    minCR(cs);
202    
203    cs.setApprovalDate(null);
204    cs.setLastReviewDate(null);
205    cs.setEffectivePeriod(null);
206    cs.setTopic(null);
207    cs.setAuthor(null);
208    cs.setEditor(null);
209    cs.setReviewer(null);
210    cs.setEndorser(null);
211    cs.setRelatedArtifact(null);
212
213    for (CodeSystemFilterComponent filter : cs.getFilter()) {
214      filter.setDescription(null);
215    }
216    for (PropertyComponent prop : cs.getProperty()) {
217      prop.setDescription(null);
218    }
219    for (ConceptDefinitionComponent cc : cs.getConcept()) {
220      minify(cc);
221    }
222  }
223  
224  private void minify(ConceptDefinitionComponent cc) {
225    cc.setDefinition(null);
226    for (ConceptDefinitionComponent ccc : cc.getConcept()) {
227      minify(ccc);
228    }
229  }
230
231  private void minifyVS(ValueSet vs) {
232    minCR(vs);
233    
234    vs.setApprovalDate(null);
235    vs.setLastReviewDate(null);
236    vs.setEffectivePeriod(null);
237    vs.setTopic(null);
238    vs.setAuthor(null);
239    vs.setEditor(null);
240    vs.setReviewer(null);
241    vs.setEndorser(null);
242    vs.setRelatedArtifact(null);
243    // can't remove anything else
244  }
245
246  private boolean minifySD(StructureDefinition sd) {
247    if (sd.getKind() == StructureDefinitionKind.LOGICAL) {
248      return false;
249    }
250    minCR(sd);
251    sd.setKeyword(null);
252    sd.setMapping(null);
253    if (sd.hasDifferential()) {
254      sd.setSnapshot(null);
255    }
256    for (ElementDefinition ed : sd.getDifferential().getElement()) {
257      minifyED(ed);
258    }
259    return true;
260  }
261
262  private void minifyED(ElementDefinition ed) {
263    ed.setLabel(null);
264    ed.setCode(null);
265    ed.getSlicing().setDescription(null);
266    ed.setShort(null);
267    ed.setDefinition(null);
268    ed.setComment(null);
269    ed.setRequirements(null);
270    ed.setAlias(null);
271    ed.setDefaultValue(null);
272    ed.setOrderMeaning(null);
273    ed.setMeaningWhenMissing(null);
274    ed.setExample(null);
275    ed.setIsModifierReason(null);
276    ed.getBinding().setDescription(null);
277    for (ElementDefinitionBindingAdditionalComponent abn : ed.getBinding().getAdditional()) {
278      abn.setDocumentation(null);
279      abn.setShortDoco(null);
280    }
281    ed.setMapping(null);
282    ed.setMustSupportElement(null);
283  }
284
285  private void minCR(CanonicalResource cr) {
286    minDR(cr);
287    cr.setIdentifier(null);
288    cr.setPublisher(null);
289    cr.setContact(null);
290    cr.setDescription(null);
291    cr.setPurpose(null);
292    cr.setCopyright(null);
293    cr.setCopyrightLabel(null);
294  }
295
296  private void minDR(DomainResource dr) {
297    minRes(dr);
298    dr.setText(null);
299    List<Resource> del = new ArrayList<>();
300    for (Resource res : dr.getContained()) {
301      if (isMinified(res.fhirType())) {
302        minify(res);
303      } else {
304        del.add(res);
305      }
306    }
307    dr.getContained().removeAll(del);
308    dr.getExtension().removeIf(ext -> !Utilities.existsInList(ext.getUrl(), VALIDATION_EXTENSIONS));
309  }
310
311  private void minRes(Resource res) {
312    res.setMeta(null);
313    res.setImplicitRules(null);
314  }
315  
316}