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