001package org.hl7.fhir.dstu3.context; 002 003/*- 004 * #%L 005 * org.hl7.fhir.dstu3 006 * %% 007 * Copyright (C) 2014 - 2019 Health Level 7 008 * %% 009 * Licensed under the Apache License, Version 2.0 (the "License"); 010 * you may not use this file except in compliance with the License. 011 * You may obtain a copy of the License at 012 * 013 * http://www.apache.org/licenses/LICENSE-2.0 014 * 015 * Unless required by applicable law or agreed to in writing, software 016 * distributed under the License is distributed on an "AS IS" BASIS, 017 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 018 * See the License for the specific language governing permissions and 019 * limitations under the License. 020 * #L% 021 */ 022 023 024import java.io.ByteArrayInputStream; 025import java.io.File; 026import java.io.FileInputStream; 027import java.io.FileNotFoundException; 028import java.io.IOException; 029import java.io.InputStream; 030import java.net.URISyntaxException; 031import java.util.ArrayList; 032import java.util.Arrays; 033import java.util.Collections; 034import java.util.HashMap; 035import java.util.HashSet; 036import java.util.List; 037import java.util.Map; 038import java.util.Set; 039import java.util.zip.ZipEntry; 040import java.util.zip.ZipInputStream; 041 042import org.apache.commons.io.IOUtils; 043import org.hl7.fhir.dstu3.conformance.ProfileUtilities; 044import org.hl7.fhir.dstu3.conformance.ProfileUtilities.ProfileKnowledgeProvider; 045import org.hl7.fhir.dstu3.context.IWorkerContext.ILoggingService.LogCategory; 046import org.hl7.fhir.dstu3.formats.IParser; 047import org.hl7.fhir.dstu3.formats.JsonParser; 048import org.hl7.fhir.dstu3.formats.ParserType; 049import org.hl7.fhir.dstu3.formats.XmlParser; 050import org.hl7.fhir.dstu3.model.Bundle; 051import org.hl7.fhir.dstu3.model.Bundle.BundleEntryComponent; 052import org.hl7.fhir.dstu3.model.CodeSystem; 053import org.hl7.fhir.dstu3.model.ConceptMap; 054import org.hl7.fhir.dstu3.model.ElementDefinition.ElementDefinitionBindingComponent; 055import org.hl7.fhir.dstu3.model.MetadataResource; 056import org.hl7.fhir.dstu3.model.NamingSystem; 057import org.hl7.fhir.dstu3.model.NamingSystem.NamingSystemIdentifierType; 058import org.hl7.fhir.dstu3.model.NamingSystem.NamingSystemUniqueIdComponent; 059import org.hl7.fhir.dstu3.model.OperationDefinition; 060import org.hl7.fhir.dstu3.model.Questionnaire; 061import org.hl7.fhir.dstu3.model.Resource; 062import org.hl7.fhir.dstu3.model.ResourceType; 063import org.hl7.fhir.dstu3.model.SearchParameter; 064import org.hl7.fhir.dstu3.model.StructureDefinition; 065import org.hl7.fhir.dstu3.model.StructureDefinition.StructureDefinitionKind; 066import org.hl7.fhir.dstu3.model.StructureDefinition.TypeDerivationRule; 067import org.hl7.fhir.dstu3.model.StructureMap; 068import org.hl7.fhir.dstu3.model.StructureMap.StructureMapModelMode; 069import org.hl7.fhir.dstu3.model.StructureMap.StructureMapStructureComponent; 070import org.hl7.fhir.dstu3.model.ValueSet; 071import org.hl7.fhir.dstu3.terminologies.ValueSetExpansionCache; 072import org.hl7.fhir.dstu3.utils.INarrativeGenerator; 073import org.hl7.fhir.dstu3.utils.IResourceValidator; 074import org.hl7.fhir.dstu3.utils.NarrativeGenerator; 075import org.hl7.fhir.dstu3.utils.client.FHIRToolingClient; 076import org.hl7.fhir.exceptions.DefinitionException; 077import org.hl7.fhir.exceptions.FHIRException; 078import org.hl7.fhir.exceptions.FHIRFormatError; 079import org.hl7.fhir.utilities.CSFileInputStream; 080import org.hl7.fhir.utilities.OIDUtils; 081import org.hl7.fhir.utilities.Utilities; 082import org.hl7.fhir.utilities.cache.NpmPackage; 083import org.hl7.fhir.utilities.validation.ValidationMessage; 084import org.hl7.fhir.utilities.validation.ValidationMessage.IssueType; 085import org.hl7.fhir.utilities.validation.ValidationMessage.Source; 086 087import ca.uhn.fhir.parser.DataFormatException; 088 089/* 090 * This is a stand alone implementation of worker context for use inside a tool. 091 * It loads from the validation package (validation-min.xml.zip), and has a 092 * very light client to connect to an open unauthenticated terminology service 093 */ 094 095public class SimpleWorkerContext extends BaseWorkerContext implements IWorkerContext, ProfileKnowledgeProvider { 096 097 public interface IContextResourceLoader { 098 Bundle loadBundle(InputStream stream, boolean isJson) throws FHIRException, IOException; 099 } 100 101 public interface IValidatorFactory { 102 IResourceValidator makeValidator(IWorkerContext ctxts) throws FHIRException; 103 } 104 105 // all maps are to the full URI 106 private Map<String, StructureDefinition> structures = new HashMap<String, StructureDefinition>(); 107 private List<NamingSystem> systems = new ArrayList<NamingSystem>(); 108 private Questionnaire questionnaire; 109 private Map<String, byte[]> binaries = new HashMap<String, byte[]>(); 110 private String version; 111 private String revision; 112 private String date; 113 private IValidatorFactory validatorFactory; 114 115 // -- Initializations 116 /** 117 * Load the working context from the validation pack 118 * 119 * @param path 120 * filename of the validation pack 121 * @return 122 * @throws IOException 123 * @throws FileNotFoundException 124 * @throws FHIRException 125 * @throws Exception 126 */ 127 public static SimpleWorkerContext fromPack(String path) throws FileNotFoundException, IOException, FHIRException { 128 SimpleWorkerContext res = new SimpleWorkerContext(); 129 res.loadFromPack(path, null); 130 return res; 131 } 132 133 public static SimpleWorkerContext fromPackage(NpmPackage pi, boolean allowDuplicates) throws FileNotFoundException, IOException, FHIRException { 134 SimpleWorkerContext res = new SimpleWorkerContext(); 135 res.setAllowLoadingDuplicates(allowDuplicates); 136 res.loadFromPackage(pi, null); 137 return res; 138 } 139 140 public static SimpleWorkerContext fromPackage(NpmPackage pi) throws FileNotFoundException, IOException, FHIRException { 141 SimpleWorkerContext res = new SimpleWorkerContext(); 142 res.loadFromPackage(pi, null); 143 return res; 144 } 145 146 public static SimpleWorkerContext fromPackage(NpmPackage pi, IContextResourceLoader loader) throws FileNotFoundException, IOException, FHIRException { 147 SimpleWorkerContext res = new SimpleWorkerContext(); 148 res.setAllowLoadingDuplicates(true); 149 res.version = pi.getNpm().get("version").getAsString(); 150 res.loadFromPackage(pi, loader); 151 return res; 152 } 153 154 public static SimpleWorkerContext fromPack(String path, boolean allowDuplicates) throws FileNotFoundException, IOException, FHIRException { 155 SimpleWorkerContext res = new SimpleWorkerContext(); 156 res.allowLoadingDuplicates = allowDuplicates; 157 res.loadFromPack(path, null); 158 return res; 159 } 160 161 public static SimpleWorkerContext fromPack(String path, IContextResourceLoader loader) throws FileNotFoundException, IOException, FHIRException { 162 SimpleWorkerContext res = new SimpleWorkerContext(); 163 res.loadFromPack(path, loader); 164 return res; 165 } 166 167 public static SimpleWorkerContext fromClassPath() throws IOException, FHIRException { 168 SimpleWorkerContext res = new SimpleWorkerContext(); 169 res.loadFromStream(SimpleWorkerContext.class.getResourceAsStream("validation.json.zip"), null); 170 return res; 171 } 172 173 public static SimpleWorkerContext fromClassPath(String name) throws IOException, FHIRException { 174 InputStream s = SimpleWorkerContext.class.getResourceAsStream("/"+name); 175 SimpleWorkerContext res = new SimpleWorkerContext(); 176 res.loadFromStream(s, null); 177 return res; 178 } 179 180 public static SimpleWorkerContext fromDefinitions(Map<String, byte[]> source) throws IOException, FHIRException { 181 SimpleWorkerContext res = new SimpleWorkerContext(); 182 for (String name : source.keySet()) { 183 res.loadDefinitionItem(name, new ByteArrayInputStream(source.get(name)), null); 184 } 185 return res; 186 } 187 188 public static SimpleWorkerContext fromDefinitions(Map<String, byte[]> source, IContextResourceLoader loader) throws FileNotFoundException, IOException, FHIRException { 189 SimpleWorkerContext res = new SimpleWorkerContext(); 190 for (String name : source.keySet()) { 191 try { 192 res.loadDefinitionItem(name, new ByteArrayInputStream(source.get(name)), loader); 193 } catch (Exception e) { 194 System.out.println("Error loading "+name+": "+e.getMessage()); 195 throw new FHIRException("Error loading "+name+": "+e.getMessage(), e); 196 } 197 } 198 return res; 199 } 200 private void loadDefinitionItem(String name, InputStream stream, IContextResourceLoader loader) throws IOException, FHIRException { 201 if (name.endsWith(".xml")) 202 loadFromFile(stream, name, loader); 203 else if (name.endsWith(".json")) 204 loadFromFileJson(stream, name, loader); 205 else if (name.equals("version.info")) 206 readVersionInfo(stream); 207 else 208 loadBytes(name, stream); 209 } 210 211 public String connectToTSServer(String url) throws URISyntaxException { 212 txServer = new FHIRToolingClient(url); 213 txServer.setTimeout(30000); 214 return txServer.getCapabilitiesStatementQuick().getSoftware().getVersion(); 215 } 216 217 public void loadFromFile(InputStream stream, String name, IContextResourceLoader loader) throws IOException, FHIRException { 218 Resource f; 219 try { 220 if (loader != null) 221 f = loader.loadBundle(stream, false); 222 else { 223 XmlParser xml = new XmlParser(); 224 f = xml.parse(stream); 225 } 226 } catch (DataFormatException e1) { 227 throw new org.hl7.fhir.exceptions.FHIRFormatError("Error parsing "+name+":" +e1.getMessage(), e1); 228 } catch (Exception e1) { 229 throw new org.hl7.fhir.exceptions.FHIRFormatError("Error parsing "+name+":" +e1.getMessage(), e1); 230 } 231 if (f instanceof Bundle) { 232 Bundle bnd = (Bundle) f; 233 for (BundleEntryComponent e : bnd.getEntry()) { 234 if (e.getFullUrl() == null) { 235 logger.logDebugMessage(LogCategory.CONTEXT, "unidentified resource in " + name+" (no fullUrl)"); 236 } 237 seeResource(e.getFullUrl(), e.getResource()); 238 } 239 } else if (f instanceof MetadataResource) { 240 MetadataResource m = (MetadataResource) f; 241 seeResource(m.getUrl(), m); 242 } 243 } 244 245 private void loadFromFileJson(InputStream stream, String name, IContextResourceLoader loader) throws IOException, FHIRException { 246 Bundle f; 247 try { 248 if (loader != null) 249 f = loader.loadBundle(stream, true); 250 else { 251 JsonParser json = new JsonParser(); 252 Resource r = json.parse(stream); 253 if (r instanceof Bundle) 254 f = (Bundle) r; 255 else { 256 f = new Bundle(); 257 f.addEntry().setResource(r); 258 } 259 } 260 } catch (FHIRFormatError e1) { 261 throw new org.hl7.fhir.exceptions.FHIRFormatError(e1.getMessage(), e1); 262 } 263 for (BundleEntryComponent e : f.getEntry()) { 264 if (e.getFullUrl() == null && logger != null) { 265 logger.logDebugMessage(LogCategory.CONTEXT, "unidentified resource in " + name+" (no fullUrl)"); 266 } 267 seeResource(e.getFullUrl(), e.getResource()); 268 } 269 } 270 271 public void seeResource(String url, Resource r) throws FHIRException { 272 if (r instanceof StructureDefinition) 273 seeProfile(url, (StructureDefinition) r); 274 else if (r instanceof ValueSet) 275 seeValueSet(url, (ValueSet) r); 276 else if (r instanceof CodeSystem) 277 seeCodeSystem(url, (CodeSystem) r); 278 else if (r instanceof OperationDefinition) 279 seeOperationDefinition(url, (OperationDefinition) r); 280 else if (r instanceof ConceptMap) 281 maps.put(((ConceptMap) r).getUrl(), (ConceptMap) r); 282 else if (r instanceof StructureMap) 283 transforms.put(((StructureMap) r).getUrl(), (StructureMap) r); 284 else if (r instanceof NamingSystem) 285 systems.add((NamingSystem) r); 286 } 287 288 private void seeOperationDefinition(String url, OperationDefinition r) { 289 operations.put(r.getUrl(), r); 290 } 291 292 public void seeValueSet(String url, ValueSet vs) throws DefinitionException { 293 if (Utilities.noString(url)) 294 url = vs.getUrl(); 295 if (valueSets.containsKey(vs.getUrl()) && !allowLoadingDuplicates) 296 throw new DefinitionException("Duplicate Profile " + vs.getUrl()); 297 valueSets.put(vs.getId(), vs); 298 valueSets.put(vs.getUrl(), vs); 299 if (!vs.getUrl().equals(url)) 300 valueSets.put(url, vs); 301 } 302 303 public void seeProfile(String url, StructureDefinition p) throws FHIRException { 304 if (Utilities.noString(url)) 305 url = p.getUrl(); 306 307 if (!p.hasSnapshot() && p.getKind() != StructureDefinitionKind.LOGICAL) { 308 if (!p.hasBaseDefinition()) 309 throw new DefinitionException("Profile "+p.getName()+" ("+p.getUrl()+") has no base and no snapshot"); 310 StructureDefinition sd = fetchResource(StructureDefinition.class, p.getBaseDefinition()); 311 if (sd == null) 312 throw new DefinitionException("Profile "+p.getName()+" ("+p.getUrl()+") base "+p.getBaseDefinition()+" could not be resolved"); 313 List<ValidationMessage> msgs = new ArrayList<ValidationMessage>(); 314 List<String> errors = new ArrayList<String>(); 315 ProfileUtilities pu = new ProfileUtilities(this, msgs, this); 316 pu.sortDifferential(sd, p, url, errors); 317 for (String err : errors) 318 msgs.add(new ValidationMessage(Source.ProfileValidator, IssueType.EXCEPTION,p.getUserString("path"), "Error sorting Differential: "+err, ValidationMessage.IssueSeverity.ERROR)); 319 pu.generateSnapshot(sd, p, p.getUrl(), p.getName()); 320 for (ValidationMessage msg : msgs) { 321 if (msg.getLevel() == ValidationMessage.IssueSeverity.ERROR || msg.getLevel() == ValidationMessage.IssueSeverity.FATAL) 322 throw new DefinitionException("Profile "+p.getName()+" ("+p.getUrl()+"). Error generating snapshot: "+msg.getMessage()); 323 } 324 if (!p.hasSnapshot()) 325 throw new DefinitionException("Profile "+p.getName()+" ("+p.getUrl()+"). Error generating snapshot"); 326 pu = null; 327 } 328 if (structures.containsKey(p.getUrl()) && !allowLoadingDuplicates) 329 throw new DefinitionException("Duplicate structures " + p.getUrl()); 330 structures.put(p.getId(), p); 331 structures.put(p.getUrl(), p); 332 if (!p.getUrl().equals(url)) 333 structures.put(url, p); 334 } 335 336 private void loadFromPack(String path, IContextResourceLoader loader) throws FileNotFoundException, IOException, FHIRException { 337 loadFromStream(new CSFileInputStream(path), loader); 338 } 339 340 public void loadFromPackage(NpmPackage pi, IContextResourceLoader loader, String... types) throws FileNotFoundException, IOException, FHIRException { 341 if (types.length == 0) 342 types = new String[] { "StructureDefinition", "ValueSet", "CodeSystem", "SearchParameter", "OperationDefinition", "Questionnaire","ConceptMap","StructureMap", "NamingSystem"}; 343 for (String s : pi.listResources(types)) { 344 loadDefinitionItem(s, pi.load("package", s), loader); 345 } 346 version = pi.version(); 347 } 348 349 public void loadFromFile(String file, IContextResourceLoader loader) throws IOException, FHIRException { 350 loadDefinitionItem(file, new CSFileInputStream(file), loader); 351 } 352 353 private void loadFromStream(InputStream stream, IContextResourceLoader loader) throws IOException, FHIRException { 354 ZipInputStream zip = new ZipInputStream(stream); 355 ZipEntry ze; 356 while ((ze = zip.getNextEntry()) != null) { 357 loadDefinitionItem(ze.getName(), zip, loader); 358 zip.closeEntry(); 359 } 360 zip.close(); 361 } 362 363 private void readVersionInfo(InputStream stream) throws IOException, DefinitionException { 364 byte[] bytes = IOUtils.toByteArray(stream); 365 binaries.put("version.info", bytes); 366 367 String[] vi = new String(bytes).split("\\r?\\n"); 368 for (String s : vi) { 369 if (s.startsWith("version=")) { 370 if (version == null) 371 version = s.substring(8); 372 else if (!version.equals(s.substring(8))) 373 throw new DefinitionException("Version mismatch. The context has version "+version+" loaded, and the new content being loaded is version "+s.substring(8)); 374 } 375 if (s.startsWith("revision=")) 376 revision = s.substring(9); 377 if (s.startsWith("date=")) 378 date = s.substring(5); 379 } 380 } 381 382 private void loadBytes(String name, InputStream stream) throws IOException { 383 byte[] bytes = IOUtils.toByteArray(stream); 384 binaries.put(name, bytes); 385 } 386 387 @Override 388 public IParser getParser(ParserType type) { 389 switch (type) { 390 case JSON: return newJsonParser(); 391 case XML: return newXmlParser(); 392 default: 393 throw new Error("Parser Type "+type.toString()+" not supported"); 394 } 395 } 396 397 @Override 398 public IParser getParser(String type) { 399 if (type.equalsIgnoreCase("JSON")) 400 return new JsonParser(); 401 if (type.equalsIgnoreCase("XML")) 402 return new XmlParser(); 403 throw new Error("Parser Type "+type.toString()+" not supported"); 404 } 405 406 @Override 407 public IParser newJsonParser() { 408 return new JsonParser(); 409 } 410 @Override 411 public IParser newXmlParser() { 412 return new XmlParser(); 413 } 414 415 @Override 416 public <T extends Resource> boolean hasResource(Class<T> class_, String uri) { 417 try { 418 return fetchResource(class_, uri) != null; 419 } catch (Exception e) { 420 return false; 421 } 422 } 423 424 @Override 425 public INarrativeGenerator getNarrativeGenerator(String prefix, String basePath) { 426 return new NarrativeGenerator(prefix, basePath, this); 427 } 428 429 @Override 430 public IResourceValidator newValidator() throws FHIRException { 431 if (validatorFactory == null) 432 throw new Error("No validator configured"); 433 return validatorFactory.makeValidator(this); 434 } 435 436 @Override 437 public <T extends Resource> T fetchResource(Class<T> class_, String uri) { 438 try { 439 return fetchResourceWithException(class_, uri); 440 } catch (FHIRException e) { 441 throw new Error(e); 442 } 443 } 444 @SuppressWarnings("unchecked") 445 @Override 446 public <T extends Resource> T fetchResourceWithException(Class<T> class_, String uri) throws FHIRException { 447 if (class_ == null) { 448 return null; 449 } 450 451 if (class_ == Questionnaire.class) 452 return (T) questionnaire; 453 454 if (class_ == StructureDefinition.class && !uri.contains("/")) 455 uri = "http://hl7.org/fhir/StructureDefinition/"+uri; 456 457 if (uri.startsWith("http:") || uri.startsWith("urn:") ) { 458 if (uri.contains("#")) 459 uri = uri.substring(0, uri.indexOf("#")); 460 if (class_ == Resource.class) { 461 if (structures.containsKey(uri)) 462 return (T) structures.get(uri); 463 if (valueSets.containsKey(uri)) 464 return (T) valueSets.get(uri); 465 if (codeSystems.containsKey(uri)) 466 return (T) codeSystems.get(uri); 467 if (operations.containsKey(uri)) 468 return (T) operations.get(uri); 469 if (searchParameters.containsKey(uri)) 470 return (T) searchParameters.get(uri); 471 if (maps.containsKey(uri)) 472 return (T) maps.get(uri); 473 if (transforms.containsKey(uri)) 474 return (T) transforms.get(uri); 475 return null; 476 } 477 if (class_ == StructureDefinition.class) { 478 if (structures.containsKey(uri)) 479 return (T) structures.get(uri); 480 else 481 return null; 482 } else if (class_ == ValueSet.class) { 483 if (valueSets.containsKey(uri)) 484 return (T) valueSets.get(uri); 485 else 486 return null; 487 } else if (class_ == CodeSystem.class) { 488 if (codeSystems.containsKey(uri)) 489 return (T) codeSystems.get(uri); 490 else 491 return null; 492 } else if (class_ == OperationDefinition.class) { 493 OperationDefinition od = operations.get(uri); 494 return (T) od; 495 } else if (class_ == SearchParameter.class) { 496 SearchParameter od = searchParameters.get(uri); 497 return (T) od; 498 } else if (class_ == ConceptMap.class) { 499 if (maps.containsKey(uri)) 500 return (T) maps.get(uri); 501 else 502 return null; 503 } else if (class_ == StructureMap.class) { 504 if (transforms.containsKey(uri)) 505 return (T) transforms.get(uri); 506 else 507 return null; 508 } 509 } 510 511 throw new FHIRException("fetching "+class_.getName()+" not done yet for URI '"+uri+"'"); 512 } 513 514 515 516 public int totalCount() { 517 return valueSets.size() + maps.size() + structures.size() + transforms.size(); 518 } 519 520 public void setCache(ValueSetExpansionCache cache) { 521 this.expansionCache = cache; 522 } 523 524 @Override 525 public List<String> getResourceNames() { 526 List<String> result = new ArrayList<String>(); 527 for (StructureDefinition sd : structures.values()) { 528 if (sd.getKind() == StructureDefinitionKind.RESOURCE && sd.getDerivation() == TypeDerivationRule.SPECIALIZATION) 529 result.add(sd.getName()); 530 } 531 Collections.sort(result); 532 return result; 533 } 534 535 @Override 536 public List<String> getTypeNames() { 537 List<String> result = new ArrayList<String>(); 538 for (StructureDefinition sd : structures.values()) { 539 if (sd.getKind() != StructureDefinitionKind.LOGICAL && sd.getDerivation() == TypeDerivationRule.SPECIALIZATION) 540 result.add(sd.getName()); 541 } 542 Collections.sort(result); 543 return result; 544 } 545 546 @Override 547 public String getAbbreviation(String name) { 548 return "xxx"; 549 } 550 551 @Override 552 public boolean isDatatype(String typeSimple) { 553 // TODO Auto-generated method stub 554 return false; 555 } 556 557 @Override 558 public boolean isResource(String t) { 559 StructureDefinition sd; 560 try { 561 sd = fetchResource(StructureDefinition.class, "http://hl7.org/fhir/StructureDefinition/"+t); 562 } catch (Exception e) { 563 return false; 564 } 565 if (sd == null) 566 return false; 567 if (sd.getDerivation() == TypeDerivationRule.CONSTRAINT) 568 return false; 569 return sd.getKind() == StructureDefinitionKind.RESOURCE; 570 } 571 572 @Override 573 public boolean hasLinkFor(String typeSimple) { 574 return false; 575 } 576 577 @Override 578 public String getLinkFor(String corePath, String typeSimple) { 579 return null; 580 } 581 582 @Override 583 public BindingResolution resolveBinding(StructureDefinition profile, ElementDefinitionBindingComponent binding, String path) { 584 return null; 585 } 586 587 @Override 588 public String getLinkForProfile(StructureDefinition profile, String url) { 589 return null; 590 } 591 592 public Questionnaire getQuestionnaire() { 593 return questionnaire; 594 } 595 596 public void setQuestionnaire(Questionnaire questionnaire) { 597 this.questionnaire = questionnaire; 598 } 599 600 @Override 601 public Set<String> typeTails() { 602 return new HashSet<String>(Arrays.asList("Integer","UnsignedInt","PositiveInt","Decimal","DateTime","Date","Time","Instant","String","Uri","Oid","Uuid","Id","Boolean","Code","Markdown","Base64Binary","Coding","CodeableConcept","Attachment","Identifier","Quantity","SampledData","Range","Period","Ratio","HumanName","Address","ContactPoint","Timing","Reference","Annotation","Signature","Meta")); 603 } 604 605 @Override 606 public List<StructureDefinition> allStructures() { 607 List<StructureDefinition> result = new ArrayList<StructureDefinition>(); 608 Set<StructureDefinition> set = new HashSet<StructureDefinition>(); 609 for (StructureDefinition sd : structures.values()) { 610 if (!set.contains(sd)) { 611 result.add(sd); 612 set.add(sd); 613 } 614 } 615 return result; 616 } 617 618 @Override 619 public List<MetadataResource> allConformanceResources() { 620 List<MetadataResource> result = new ArrayList<MetadataResource>(); 621 result.addAll(structures.values()); 622 result.addAll(codeSystems.values()); 623 result.addAll(valueSets.values()); 624 result.addAll(maps.values()); 625 result.addAll(transforms.values()); 626 return result; 627 } 628 629 @Override 630 public String oid2Uri(String oid) { 631 String uri = OIDUtils.getUriForOid(oid); 632 if (uri != null) 633 return uri; 634 for (NamingSystem ns : systems) { 635 if (hasOid(ns, oid)) { 636 uri = getUri(ns); 637 if (uri != null) 638 return null; 639 } 640 } 641 return null; 642 } 643 644 private String getUri(NamingSystem ns) { 645 for (NamingSystemUniqueIdComponent id : ns.getUniqueId()) { 646 if (id.getType() == NamingSystemIdentifierType.URI) 647 return id.getValue(); 648 } 649 return null; 650 } 651 652 private boolean hasOid(NamingSystem ns, String oid) { 653 for (NamingSystemUniqueIdComponent id : ns.getUniqueId()) { 654 if (id.getType() == NamingSystemIdentifierType.OID && id.getValue().equals(oid)) 655 return true; 656 } 657 return false; 658 } 659 660 661 662 663 public void loadFromFolder(String folder) throws FileNotFoundException, Exception { 664 for (String n : new File(folder).list()) { 665 if (n.endsWith(".json")) 666 loadFromFile(Utilities.path(folder, n), new JsonParser()); 667 else if (n.endsWith(".xml")) 668 loadFromFile(Utilities.path(folder, n), new XmlParser()); 669 } 670 } 671 672 private void loadFromFile(String filename, IParser p) throws FileNotFoundException, Exception { 673 Resource r; 674 try { 675 r = p.parse(new FileInputStream(filename)); 676 if (r.getResourceType() == ResourceType.Bundle) { 677 for (BundleEntryComponent e : ((Bundle) r).getEntry()) { 678 seeResource(null, e.getResource()); 679 } 680 } else { 681 seeResource(null, r); 682 } 683 } catch (Exception e) { 684 return; 685 } 686 } 687 688 689 public Map<String, byte[]> getBinaries() { 690 return binaries; 691 } 692 693 694 @Override 695 public boolean prependLinks() { 696 return false; 697 } 698 699 @Override 700 public boolean hasCache() { 701 return false; 702 } 703 704 @Override 705 public String getVersion() { 706 return version+"-"+revision; 707 } 708 709 public Map<String, StructureMap> getTransforms() { 710 return transforms; 711 } 712 713 public List<StructureMap> findTransformsforSource(String url) { 714 List<StructureMap> res = new ArrayList<StructureMap>(); 715 for (StructureMap map : transforms.values()) { 716 boolean match = false; 717 boolean ok = true; 718 for (StructureMapStructureComponent t : map.getStructure()) { 719 if (t.getMode() == StructureMapModelMode.SOURCE) { 720 match = match || t.getUrl().equals(url); 721 ok = ok && t.getUrl().equals(url); 722 } 723 } 724 if (match && ok) 725 res.add(map); 726 } 727 return res; 728 } 729 730 public IValidatorFactory getValidatorFactory() { 731 return validatorFactory; 732 } 733 734 public void setValidatorFactory(IValidatorFactory validatorFactory) { 735 this.validatorFactory = validatorFactory; 736 } 737 738 739 740}