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