001package org.hl7.fhir.r5.context; 002 003import java.util.ArrayList; 004import java.util.HashMap; 005import java.util.HashSet; 006import java.util.List; 007import java.util.Map; 008import java.util.Set; 009 010import org.hl7.fhir.exceptions.FHIRException; 011import org.hl7.fhir.r5.context.CanonicalResourceManager.CanonicalResourceProxy; 012import org.hl7.fhir.r5.model.StructureDefinition; 013import org.hl7.fhir.r5.model.StructureDefinition.StructureDefinitionKind; 014import org.hl7.fhir.r5.model.StructureDefinition.TypeDerivationRule; 015import org.hl7.fhir.utilities.Utilities; 016 017public class TypeManager { 018 019 020 private CanonicalResourceManager<StructureDefinition> structures; 021 private Map<String, Set<StructureDefinition>> typeDefinitions = new HashMap<>(); 022 private Map<String, Set<StructureDefinition>> fhirTypeDefinitions = new HashMap<>(); 023 private Set<String> primitiveNames = new HashSet<>(); 024 private Set<String> dataTypeNames = new HashSet<>(); 025 026 public TypeManager(CanonicalResourceManager<StructureDefinition> structures) { 027 super(); 028 this.structures = structures; 029 reload(); 030 } 031 032 public void reload() { 033 typeDefinitions.clear(); 034 primitiveNames.clear(); 035 dataTypeNames.clear(); 036 for (CanonicalResourceManager<StructureDefinition>.CachedCanonicalResource<StructureDefinition> cr : structures.getCachedList()) { 037 if (!"constraint".equals(cr.getDerivation())) { 038 see(cr.getResource()); 039 } 040 } 041 } 042 043 public void see(CanonicalResourceProxy r) { 044 if (!"constraint".equals(r.getDerivation())) { 045 see((StructureDefinition) r.getResource()); 046 } 047 } 048 049 public void see(StructureDefinition sd) { 050 if (sd.getDerivation() != TypeDerivationRule.CONSTRAINT && (sd.getSourcePackage() == null || !sd.getSourcePackage().isExamplesPackage())) { 051 String type = sd.getType(); 052 Set<StructureDefinition> types = typeDefinitions.get(type); 053 if (types == null) { 054 types = new HashSet<>(); 055 typeDefinitions.put(type, types); 056 } 057 types.add(sd); 058 if (sd.getUrl().startsWith("http://hl7.org/fhir/StructureDefinition/")) { 059 types = fhirTypeDefinitions.get(type); 060 if (types == null) { 061 types = new HashSet<>(); 062 fhirTypeDefinitions.put(type, types); 063 } 064 types.add(sd); 065 } 066 if (Utilities.isAbsoluteUrl(type)) { 067 type = sd.getTypeTail(); 068 types = typeDefinitions.get(type); 069 if (types == null) { 070 types = new HashSet<>(); 071 typeDefinitions.put(type, types); 072 } 073 types.add(sd); 074 } 075 if (sd.getKind() == StructureDefinitionKind.PRIMITIVETYPE) { 076 primitiveNames.add(sd.getType()); 077 } else if (sd.getKind() == StructureDefinitionKind.COMPLEXTYPE) { 078 dataTypeNames.add(sd.getType()); 079 } 080 } 081 } 082 083 084 public List<StructureDefinition> getDefinitions(String typeName) { 085 List<StructureDefinition> list = new ArrayList<>(); 086 Set<StructureDefinition> defined = typeDefinitions.get(typeName); 087 if (defined != null) { 088 list.addAll(defined); 089 } 090 return list; 091 } 092 093 public StructureDefinition fetchTypeDefinition(String typeName) { 094 Set<StructureDefinition> types = typeDefinitions.get(typeName); 095 if (types == null) { 096 return null; // throw new FHIRException("Unresolved type "+typeName+" (0)"); 097 } else if (types.size() == 1) { 098 return types.iterator().next(); 099 } else { 100 types = fhirTypeDefinitions.get(typeName); 101 if (types == null) { 102 return null; 103 } else if (types.size() != 1) { 104 throw new FHIRException("Ambiguous type "+typeName+" ("+types.toString()+") (contact Grahame Grieve for investigation)"); 105 } else { 106 return types.iterator().next(); 107 } 108 } 109 } 110 111 public boolean isPrimitive(String type) { 112 if (primitiveNames.contains(type) || Utilities.existsInList(type, "boolean", "integer", "integer64", "string", "decimal", "uri", "base64Binary", "instant", "date", "dateTime", "time", "code", "oid", "id", "markdown", "unsignedInt", "positiveInt", "uuid", "xhtml", "url", "canonical")) { 113 return true; 114 } else { 115 StructureDefinition sd = structures.get(type); 116 return sd != null && sd.getKind() == StructureDefinitionKind.PRIMITIVETYPE; 117 } 118 } 119 120 public boolean isDataType(String type) { 121 if (dataTypeNames.contains(type) || Utilities.existsInList(type, "Address", "Age", "Annotation", "Attachment", "CodeableConcept", "Coding", "ContactPoint", "Count", "Distance", "Duration", "HumanName", "Identifier", "Money", "Period", "Quantity", "Range", "Ratio", "Reference", "SampledData", "Signature", "Timing", 122 "ContactDetail", "Contributor", "DataRequirement", "Expression", "ParameterDefinition", "RelatedArtifact", "TriggerDefinition", "UsageContext")) { 123 return true; 124 } else { 125 StructureDefinition sd = structures.get(type); 126 return sd != null && sd.getKind() == StructureDefinitionKind.COMPLEXTYPE; 127 } 128 } 129 130 public void unload() { 131 132 structures.unload(); 133 typeDefinitions.clear(); 134 fhirTypeDefinitions.clear(); 135 primitiveNames.clear(); 136 dataTypeNames.clear(); 137 } 138 139}