
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.r5.utils.UserDataNames; 016import org.hl7.fhir.utilities.MarkedToMoveToAdjunctPackage; 017import org.hl7.fhir.utilities.Utilities; 018 019@MarkedToMoveToAdjunctPackage 020public class TypeManager { 021 022 023 private CanonicalResourceManager<StructureDefinition> structures; 024 private Map<String, Set<StructureDefinition>> typeDefinitions = new HashMap<>(); 025 private Map<String, Set<StructureDefinition>> fhirTypeDefinitions = new HashMap<>(); 026 private Set<String> primitiveNames = new HashSet<>(); 027 private Set<String> dataTypeNames = new HashSet<>(); 028 029 public TypeManager(CanonicalResourceManager<StructureDefinition> structures) { 030 super(); 031 this.structures = structures; 032 reload(); 033 } 034 035 public void reload() { 036 typeDefinitions.clear(); 037 primitiveNames.clear(); 038 dataTypeNames.clear(); 039 for (CanonicalResourceManager<StructureDefinition>.CachedCanonicalResource<StructureDefinition> cr : structures.getCachedList()) { 040 if (!"constraint".equals(cr.getDerivation())) { 041 see(cr.getResource()); 042 } 043 } 044 } 045 046 protected Iterable<String> getTypeNames() { 047 return typeDefinitions.keySet(); 048 } 049 050 public void see(CanonicalResourceProxy r) { 051 if (!"constraint".equals(r.getDerivation())) { 052 see((StructureDefinition) r.getResource()); 053 } 054 } 055 056 public void see(StructureDefinition sd) { 057 if (sd.getDerivation() != TypeDerivationRule.CONSTRAINT && (sd.getSourcePackage() == null || !sd.getSourcePackage().isExamplesPackage())) { 058 String type = sd.getType(); 059 Set<StructureDefinition> types = typeDefinitions.get(type); 060 if (types == null) { 061 types = new HashSet<>(); 062 typeDefinitions.put(type, types); 063 } 064 types.add(sd); 065 if (sd.getUrl().startsWith("http://hl7.org/fhir/StructureDefinition/") || "true".equals(sd.getUserString(UserDataNames.loader_custom_resource))) { 066 types = fhirTypeDefinitions.get(type); 067 if (types == null) { 068 types = new HashSet<>(); 069 fhirTypeDefinitions.put(type, types); 070 } 071 types.add(sd); 072 } 073 if (Utilities.isAbsoluteUrl(type)) { 074 type = sd.getTypeTail(); 075 types = typeDefinitions.get(type); 076 if (types == null) { 077 types = new HashSet<>(); 078 typeDefinitions.put(type, types); 079 } 080 types.add(sd); 081 } 082 if (sd.getKind() == StructureDefinitionKind.PRIMITIVETYPE) { 083 primitiveNames.add(sd.getType()); 084 } else if (sd.getKind() == StructureDefinitionKind.COMPLEXTYPE) { 085 dataTypeNames.add(sd.getType()); 086 } 087 } 088 } 089 090 091 public List<StructureDefinition> getDefinitions(String typeName) { 092 List<StructureDefinition> list = new ArrayList<>(); 093 Set<StructureDefinition> defined = typeDefinitions.get(typeName); 094 if (defined != null) { 095 list.addAll(defined); 096 } 097 return list; 098 } 099 100 public StructureDefinition fetchTypeDefinition(String typeName) { 101 Set<StructureDefinition> types = typeDefinitions.get(typeName); 102 if (types == null) { 103 return null; // throw new FHIRException("Unresolved type "+typeName+" (0)"); 104 } else if (types.size() == 1) { 105 return types.iterator().next(); 106 } else { 107 types = fhirTypeDefinitions.get(typeName); 108 if (types == null) { 109 return null; 110 } else if (types.size() != 1) { 111 throw new FHIRException("Ambiguous type "+typeName+" ("+types.toString()+") (contact Grahame Grieve for investigation)"); 112 } else { 113 return types.iterator().next(); 114 } 115 } 116 } 117 118 public boolean isPrimitive(String type) { 119 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")) { 120 return true; 121 } else { 122 StructureDefinition sd = structures.get(type); 123 return sd != null && sd.getKind() == StructureDefinitionKind.PRIMITIVETYPE; 124 } 125 } 126 127 public boolean isDataType(String type) { 128 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", 129 "ContactDetail", "Contributor", "DataRequirement", "Expression", "ParameterDefinition", "RelatedArtifact", "TriggerDefinition", "UsageContext")) { 130 return true; 131 } else { 132 StructureDefinition sd = structures.get(type); 133 return sd != null && sd.getKind() == StructureDefinitionKind.COMPLEXTYPE; 134 } 135 } 136 137 public void unload() { 138 139 structures.unload(); 140 typeDefinitions.clear(); 141 fhirTypeDefinitions.clear(); 142 primitiveNames.clear(); 143 dataTypeNames.clear(); 144 } 145 146}