001package org.hl7.fhir.dstu3.model; 002 003import java.util.ArrayList; 004import java.util.Collection; 005import java.util.HashSet; 006import java.util.List; 007import java.util.Set; 008 009import org.hl7.fhir.dstu3.context.IWorkerContext; 010import org.hl7.fhir.dstu3.model.ElementDefinition.ElementDefinitionBindingComponent; 011import org.hl7.fhir.dstu3.model.ExpressionNode.CollectionStatus; 012import org.hl7.fhir.exceptions.DefinitionException; 013import org.hl7.fhir.utilities.Utilities; 014 015public class TypeDetails { 016 public static class ProfiledType { 017 private String uri; 018 private List<String> profiles; // or, not and 019 private List<ElementDefinitionBindingComponent> bindings; 020 021 public ProfiledType(String n) { 022 uri = ns(n); 023 } 024 025 public String getUri() { 026 return uri; 027 } 028 029 public boolean hasProfiles() { 030 return profiles != null && profiles.size() > 0; 031 } 032 public List<String> getProfiles() { 033 return profiles; 034 } 035 036 public boolean hasBindings() { 037 return bindings != null && bindings.size() > 0; 038 } 039 public List<ElementDefinitionBindingComponent> getBindings() { 040 return bindings; 041 } 042 043 public static String ns(String n) { 044 return Utilities.isAbsoluteUrl(n) ? n : "http://hl7.org/fhir/StructureDefinition/"+n; 045 } 046 047 public void addProfile(String profile) { 048 profiles = new ArrayList<String>(); 049 profiles.add(profile); 050 } 051 052 public void addBinding(ElementDefinitionBindingComponent binding) { 053 bindings = new ArrayList<ElementDefinitionBindingComponent>(); 054 bindings.add(binding); 055 } 056 057 public boolean hasBinding(ElementDefinitionBindingComponent b) { 058 return false; // todo: do we need to do this? 059 } 060 } 061 062 private List<ProfiledType> types = new ArrayList<ProfiledType>(); 063 private CollectionStatus collectionStatus; 064 public TypeDetails(CollectionStatus collectionStatus, String... names) { 065 super(); 066 this.collectionStatus = collectionStatus; 067 for (String n : names) { 068 this.types.add(new ProfiledType(n)); 069 } 070 } 071 public TypeDetails(CollectionStatus collectionStatus, Set<String> names) { 072 super(); 073 this.collectionStatus = collectionStatus; 074 for (String n : names) { 075 addType(new ProfiledType(n)); 076 } 077 } 078 public TypeDetails(CollectionStatus collectionStatus, ProfiledType pt) { 079 super(); 080 this.collectionStatus = collectionStatus; 081 this.types.add(pt); 082 } 083 public String addType(String n) { 084 ProfiledType pt = new ProfiledType(n); 085 String res = pt.uri; 086 addType(pt); 087 return res; 088 } 089 public String addType(String n, String p) { 090 ProfiledType pt = new ProfiledType(n); 091 pt.addProfile(p); 092 String res = pt.uri; 093 addType(pt); 094 return res; 095 } 096 public void addType(ProfiledType pt) { 097 for (ProfiledType et : types) { 098 if (et.uri.equals(pt.uri)) { 099 if (pt.profiles != null) { 100 for (String p : pt.profiles) { 101 if (et.profiles == null) 102 et.profiles = new ArrayList<String>(); 103 if (!et.profiles.contains(p)) 104 et.profiles.add(p); 105 } 106 } 107 if (pt.bindings != null) { 108 for (ElementDefinitionBindingComponent b : pt.bindings) { 109 if (et.bindings == null) 110 et.bindings = new ArrayList<ElementDefinitionBindingComponent>(); 111 if (!et.hasBinding(b)) 112 et.bindings.add(b); 113 } 114 } 115 return; 116 } 117 } 118 types.add(pt); 119 } 120 121 public void addTypes(Collection<String> names) { 122 for (String n : names) 123 addType(new ProfiledType(n)); 124 } 125 126 public boolean hasType(IWorkerContext context, String... tn) { 127 for (String n: tn) { 128 String t = ProfiledType.ns(n); 129 if (typesContains(t)) 130 return true; 131 } 132 for (String n: tn) { 133 String id = n.contains("#") ? n.substring(0, n.indexOf("#")) : n; 134 String tail = null; 135 if (n.contains("#")) { 136 tail = n.substring( n.indexOf("#")+1); 137 tail = tail.substring(tail.indexOf(".")); 138 } 139 String t = ProfiledType.ns(n); 140 StructureDefinition sd = context.fetchResource(StructureDefinition.class, t); 141 while (sd != null) { 142 if (tail == null && typesContains(sd.getUrl())) 143 return true; 144 if (tail != null && typesContains(sd.getUrl()+"#"+sd.getType()+tail)) 145 return true; 146 if (sd.hasBaseDefinition()) 147 sd = context.fetchResource(StructureDefinition.class, sd.getBaseDefinition()); 148 else 149 sd = null; 150 } 151 } 152 return false; 153 } 154 155 private boolean typesContains(String t) { 156 for (ProfiledType pt : types) 157 if (pt.uri.equals(t)) 158 return true; 159 return false; 160 } 161 162 public void update(TypeDetails source) { 163 for (ProfiledType pt : source.types) 164 addType(pt); 165 if (collectionStatus == null) 166 collectionStatus = source.collectionStatus; 167 else if (source.collectionStatus == CollectionStatus.UNORDERED) 168 collectionStatus = source.collectionStatus; 169 else 170 collectionStatus = CollectionStatus.ORDERED; 171 } 172 public TypeDetails union(TypeDetails right) { 173 TypeDetails result = new TypeDetails(null); 174 if (right.collectionStatus == CollectionStatus.UNORDERED || collectionStatus == CollectionStatus.UNORDERED) 175 result.collectionStatus = CollectionStatus.UNORDERED; 176 else 177 result.collectionStatus = CollectionStatus.ORDERED; 178 for (ProfiledType pt : types) 179 result.addType(pt); 180 for (ProfiledType pt : right.types) 181 result.addType(pt); 182 return result; 183 } 184 185 public boolean hasNoTypes() { 186 return types.isEmpty(); 187 } 188 public Set<String> getTypes() { 189 Set<String> res = new HashSet<String>(); 190 for (ProfiledType pt : types) 191 res.add(pt.uri); 192 return res; 193 } 194 public TypeDetails toSingleton() { 195 TypeDetails result = new TypeDetails(CollectionStatus.SINGLETON); 196 result.types.addAll(types); 197 return result; 198 } 199 public CollectionStatus getCollectionStatus() { 200 return collectionStatus; 201 } 202 public boolean hasType(Set<String> tn) { 203 for (String n: tn) { 204 String t = ProfiledType.ns(n); 205 if (typesContains(t)) 206 return true; 207 } 208 return false; 209 } 210 public String describe() { 211 return getTypes().toString(); 212 } 213 public String getType() { 214 for (ProfiledType pt : types) 215 return pt.uri; 216 return null; 217 } 218 @Override 219 public String toString() { 220 return (collectionStatus == null ? collectionStatus.SINGLETON.toString() : collectionStatus.toString()) + getTypes().toString(); 221 } 222 public String getTypeCode() throws DefinitionException { 223 if (types.size() != 1) 224 throw new DefinitionException("Multiple types? ("+types.toString()+")"); 225 for (ProfiledType pt : types) 226 if (pt.uri.startsWith("http://hl7.org/fhir/StructureDefinition/")) 227 return pt.uri.substring(40); 228 else 229 return pt.uri; 230 return null; 231 } 232 public List<ProfiledType> getProfiledTypes() { 233 return types; 234 } 235 public boolean hasBinding() { 236 for (ProfiledType pt : types) { 237 if (pt.hasBindings()) 238 return true; 239 } 240 return false; 241 } 242 public ElementDefinitionBindingComponent getBinding() { 243 for (ProfiledType pt : types) { 244 for (ElementDefinitionBindingComponent b : pt.getBindings()) 245 return b; 246 } 247 return null; 248 } 249}