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