package org.hl7.fhir.dstu3.model; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.List; import java.util.Set; import org.hl7.fhir.dstu3.context.IWorkerContext; import org.hl7.fhir.dstu3.model.ElementDefinition.ElementDefinitionBindingComponent; import org.hl7.fhir.dstu3.model.ExpressionNode.CollectionStatus; import org.hl7.fhir.exceptions.DefinitionException; import org.hl7.fhir.utilities.Utilities; public class TypeDetails { public static class ProfiledType { private String uri; private List<String> profiles; // or, not and private List<ElementDefinitionBindingComponent> bindings; public ProfiledType(String n) { uri = ns(n); } public String getUri() { return uri; } public boolean hasProfiles() { return profiles != null && profiles.size() > 0; } public List<String> getProfiles() { return profiles; } public boolean hasBindings() { return bindings != null && bindings.size() > 0; } public List<ElementDefinitionBindingComponent> getBindings() { return bindings; } public static String ns(String n) { return Utilities.isAbsoluteUrl(n) ? n : "http://hl7.org/fhir/StructureDefinition/"+n; } public void addProfile(String profile) { profiles = new ArrayList<String>(); profiles.add(profile); } public void addBinding(ElementDefinitionBindingComponent binding) { bindings = new ArrayList<ElementDefinitionBindingComponent>(); bindings.add(binding); } public boolean hasBinding(ElementDefinitionBindingComponent b) { return false; // todo: do we need to do this? } } private List<ProfiledType> types = new ArrayList<ProfiledType>(); private CollectionStatus collectionStatus; public TypeDetails(CollectionStatus collectionStatus, String... names) { super(); this.collectionStatus = collectionStatus; for (String n : names) { this.types.add(new ProfiledType(n)); } } public TypeDetails(CollectionStatus collectionStatus, Set<String> names) { super(); this.collectionStatus = collectionStatus; for (String n : names) { addType(new ProfiledType(n)); } } public TypeDetails(CollectionStatus collectionStatus, ProfiledType pt) { super(); this.collectionStatus = collectionStatus; this.types.add(pt); } public String addType(String n) { ProfiledType pt = new ProfiledType(n); String res = pt.uri; addType(pt); return res; } public String addType(String n, String p) { ProfiledType pt = new ProfiledType(n); pt.addProfile(p); String res = pt.uri; addType(pt); return res; } public void addType(ProfiledType pt) { for (ProfiledType et : types) { if (et.uri.equals(pt.uri)) { if (pt.profiles != null) { for (String p : pt.profiles) { if (et.profiles == null) et.profiles = new ArrayList<String>(); if (!et.profiles.contains(p)) et.profiles.add(p); } } if (pt.bindings != null) { for (ElementDefinitionBindingComponent b : pt.bindings) { if (et.bindings == null) et.bindings = new ArrayList<ElementDefinitionBindingComponent>(); if (!et.hasBinding(b)) et.bindings.add(b); } } return; } } types.add(pt); } public void addTypes(Collection<String> names) { for (String n : names) addType(new ProfiledType(n)); } public boolean hasType(IWorkerContext context, String... tn) { for (String n: tn) { String t = ProfiledType.ns(n); if (typesContains(t)) return true; } for (String n: tn) { String id = n.contains("#") ? n.substring(0, n.indexOf("#")) : n; String tail = null; if (n.contains("#")) { tail = n.substring( n.indexOf("#")+1); tail = tail.substring(tail.indexOf(".")); } String t = ProfiledType.ns(n); StructureDefinition sd = context.fetchResource(StructureDefinition.class, t); while (sd != null) { if (tail == null && typesContains(sd.getUrl())) return true; if (tail != null && typesContains(sd.getUrl()+"#"+sd.getType()+tail)) return true; if (sd.hasBaseDefinition()) sd = context.fetchResource(StructureDefinition.class, sd.getBaseDefinition()); else sd = null; } } return false; } private boolean typesContains(String t) { for (ProfiledType pt : types) if (pt.uri.equals(t)) return true; return false; } public void update(TypeDetails source) { for (ProfiledType pt : source.types) addType(pt); if (collectionStatus == null) collectionStatus = source.collectionStatus; else if (source.collectionStatus == CollectionStatus.UNORDERED) collectionStatus = source.collectionStatus; else collectionStatus = CollectionStatus.ORDERED; } public TypeDetails union(TypeDetails right) { TypeDetails result = new TypeDetails(null); if (right.collectionStatus == CollectionStatus.UNORDERED || collectionStatus == CollectionStatus.UNORDERED) result.collectionStatus = CollectionStatus.UNORDERED; else result.collectionStatus = CollectionStatus.ORDERED; for (ProfiledType pt : types) result.addType(pt); for (ProfiledType pt : right.types) result.addType(pt); return result; } public boolean hasNoTypes() { return types.isEmpty(); } public Set<String> getTypes() { Set<String> res = new HashSet<String>(); for (ProfiledType pt : types) res.add(pt.uri); return res; } public TypeDetails toSingleton() { TypeDetails result = new TypeDetails(CollectionStatus.SINGLETON); result.types.addAll(types); return result; } public CollectionStatus getCollectionStatus() { return collectionStatus; } public boolean hasType(Set<String> tn) { for (String n: tn) { String t = ProfiledType.ns(n); if (typesContains(t)) return true; } return false; } public String describe() { return getTypes().toString(); } public String getType() { for (ProfiledType pt : types) return pt.uri; return null; } @Override public String toString() { return (collectionStatus == null ? collectionStatus.SINGLETON.toString() : collectionStatus.toString()) + getTypes().toString(); } public String getTypeCode() throws DefinitionException { if (types.size() != 1) throw new DefinitionException("Multiple types? ("+types.toString()+")"); for (ProfiledType pt : types) if (pt.uri.startsWith("http://hl7.org/fhir/StructureDefinition/")) return pt.uri.substring(40); else return pt.uri; return null; } public List<ProfiledType> getProfiledTypes() { return types; } public boolean hasBinding() { for (ProfiledType pt : types) { if (pt.hasBindings()) return true; } return false; } public ElementDefinitionBindingComponent getBinding() { for (ProfiledType pt : types) { for (ElementDefinitionBindingComponent b : pt.getBindings()) return b; } return null; } }