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