001package org.hl7.fhir.r5.comparison; 002 003import java.io.IOException; 004import java.util.HashMap; 005import java.util.Map; 006import java.util.UUID; 007 008import org.hl7.fhir.exceptions.DefinitionException; 009import org.hl7.fhir.exceptions.FHIRException; 010import org.hl7.fhir.exceptions.FHIRFormatError; 011import org.hl7.fhir.r5.comparison.CapabilityStatementComparer.CapabilityStatementComparison; 012import org.hl7.fhir.r5.comparison.CodeSystemComparer.CodeSystemComparison; 013import org.hl7.fhir.r5.comparison.ProfileComparer.ProfileComparison; 014import org.hl7.fhir.r5.comparison.ResourceComparer.ResourceComparison; 015import org.hl7.fhir.r5.comparison.ValueSetComparer.ValueSetComparison; 016import org.hl7.fhir.r5.conformance.profile.ProfileKnowledgeProvider; 017import org.hl7.fhir.r5.conformance.profile.ProfileUtilities; 018import org.hl7.fhir.r5.context.IWorkerContext; 019import org.hl7.fhir.r5.model.CanonicalResource; 020import org.hl7.fhir.r5.model.CapabilityStatement; 021import org.hl7.fhir.r5.model.CodeSystem; 022import org.hl7.fhir.r5.model.Resource; 023import org.hl7.fhir.r5.model.StructureDefinition; 024import org.hl7.fhir.r5.model.ValueSet; 025 026public class ComparisonSession { 027 028 029 private Map<String, ResourceComparison> compares = new HashMap<>(); 030 private IWorkerContext contextLeft; 031 private IWorkerContext contextRight; 032 private String sessiondId; 033 private int count; 034 private boolean debug; 035 private String title; 036 private ProfileKnowledgeProvider pkpLeft; 037 private ProfileKnowledgeProvider pkpRight; 038 039 public ComparisonSession(IWorkerContext contextLeft, IWorkerContext contextRight, String title, ProfileKnowledgeProvider pkpLeft, ProfileKnowledgeProvider pkpRight) { 040 super(); 041 this.contextLeft = contextLeft; 042 this.contextRight = contextRight; 043 this.sessiondId = UUID.randomUUID().toString().toLowerCase(); 044 this.title = title; 045 this.pkpLeft = pkpLeft; 046 this.pkpRight = pkpRight; 047 debug = false; 048 } 049 050 public IWorkerContext getContextLeft() { 051 return contextLeft; 052 } 053 054 public IWorkerContext getContextRight() { 055 return contextRight; 056 } 057 058 public String getTitle() { 059 return title; 060 } 061 062 public ResourceComparison compare(String left, Resource leftSource, String right, Resource rightSource) throws DefinitionException, FHIRFormatError, IOException { 063 CanonicalResource l = (CanonicalResource) contextLeft.fetchResource(Resource.class, left, leftSource); 064 if (l == null) { 065 throw new DefinitionException("Unable to resolve "+left); 066 } 067 CanonicalResource r = (CanonicalResource) contextRight.fetchResource(Resource.class, right, rightSource); 068 if (r == null) { 069 throw new DefinitionException("Unable to resolve "+right); 070 } 071 return compare(l, r); 072 } 073 074 public ResourceComparison compare(CanonicalResource left, CanonicalResource right) throws DefinitionException, FHIRFormatError, IOException { 075 if (left != null && right != null) { 076 String key = key(left.getUrl(), left.getVersion(), right.getUrl(), right.getVersion()); 077 if (compares.containsKey(key)) { 078 // if null then the comparison is in progress. 079 // this can happen when profiles refer to each other 080 return compares.get(key); 081 } 082 compares.put(key, null); 083 try { 084 if (left instanceof CodeSystem && right instanceof CodeSystem) { 085 CodeSystemComparer cs = new CodeSystemComparer(this); 086 CodeSystemComparison csc = cs.compare((CodeSystem) left, (CodeSystem) right); 087 compares.put(key, csc); 088 return csc; 089 } else if (left instanceof ValueSet && right instanceof ValueSet) { 090 ValueSetComparer cs = new ValueSetComparer(this); 091 ValueSetComparison csc = cs.compare((ValueSet) left, (ValueSet) right); 092 compares.put(key, csc); 093 return csc; 094 } else if (left instanceof StructureDefinition && right instanceof StructureDefinition) { 095 ProfileComparer cs = new ProfileComparer(this, new ProfileUtilities(contextLeft, null, pkpLeft), new ProfileUtilities(contextRight, null, pkpRight)); 096 ProfileComparison csc = cs.compare((StructureDefinition) left, (StructureDefinition) right); 097 compares.put(key, csc); 098 return csc; 099 } else if (left instanceof CapabilityStatement && right instanceof CapabilityStatement) { 100 CapabilityStatementComparer cs = new CapabilityStatementComparer(this); 101 CapabilityStatementComparison csc = cs.compare((CapabilityStatement) left, (CapabilityStatement) right); 102 compares.put(key, csc); 103 return csc; 104 } else { 105 throw new FHIRException("Unable to compare resources of type "+left.fhirType()+" and "+right.fhirType()); 106 } 107 } catch (Throwable e) { 108 if (debug) { 109 e.printStackTrace(); 110 } 111 ResourceComparer.PlaceHolderComparison csc = new ResourceComparer.PlaceHolderComparison(left, right, e); 112 compares.put(key, csc); 113 return csc; 114 } 115 } else if (left != null) { 116 String key = key(left.getUrl(), left.getVersion(), left.getUrl(), left.getVersion()); 117 if (compares.containsKey(key)) { 118 return compares.get(key); 119 } 120 ResourceComparer.PlaceHolderComparison csc = new ResourceComparer.PlaceHolderComparison(left, right); 121 compares.put(key, csc); 122 return csc; 123 } else { 124 String key = key(right.getUrl(), right.getVersion(), right.getUrl(), right.getVersion()); 125 if (compares.containsKey(key)) { 126 return compares.get(key); 127 } 128 ResourceComparer.PlaceHolderComparison csc = new ResourceComparer.PlaceHolderComparison(left, right); 129 compares.put(key, csc); 130 return csc; 131 } 132 } 133 134 private String key(String urlL, String verL, String urlR, String verR) { 135 return urlL+"|"+verL+"||"+urlR+"|"+verR; 136 } 137 138 public void identify(CanonicalResource res) { 139 count++; 140 res.setId(sessiondId+"-"+count); 141 res.setUrl("http://hl7.org/fhir/comparison/"+res.fhirType()+"/"+res.getId()); 142 } 143 144 public void identify(ResourceComparison res) { 145 count++; 146 } 147 148 public boolean isDebug() { 149 return debug; 150 } 151 152 public void setDebug(boolean debug) { 153 this.debug = debug; 154 } 155 156 public Map<String, ResourceComparison> getCompares() { 157 return compares; 158 } 159 160 public ProfileKnowledgeProvider getPkpLeft() { 161 return pkpLeft; 162 } 163 164 public ProfileKnowledgeProvider getPkpRight() { 165 return pkpRight; 166 } 167}