001package org.hl7.fhir.r4.elementmodel;
002
003import java.io.IOException;
004import java.io.InputStream;
005import java.io.OutputStream;
006import java.util.List;
007
008import org.hl7.fhir.r4.context.IWorkerContext;
009import org.hl7.fhir.r4.formats.FormatUtilities;
010import org.hl7.fhir.r4.formats.IParser.OutputStyle;
011import org.hl7.fhir.r4.model.StructureDefinition;
012import org.hl7.fhir.r4.model.StructureDefinition.StructureDefinitionKind;
013import org.hl7.fhir.r4.utils.ToolingExtensions;
014import org.hl7.fhir.exceptions.DefinitionException;
015import org.hl7.fhir.exceptions.FHIRException;
016import org.hl7.fhir.exceptions.FHIRFormatError;
017import org.hl7.fhir.utilities.Utilities;
018import org.hl7.fhir.utilities.validation.ValidationMessage;
019import org.hl7.fhir.utilities.validation.ValidationMessage.IssueSeverity;
020import org.hl7.fhir.utilities.validation.ValidationMessage.IssueType;
021import org.hl7.fhir.utilities.validation.ValidationMessage.Source;
022
023public abstract class ParserBase {
024
025  public interface ILinkResolver {
026    String resolveType(String type);
027    String resolveProperty(Property property);
028    String resolvePage(String string);
029  }
030  
031  public enum ValidationPolicy { NONE, QUICK, EVERYTHING }
032
033  public boolean isPrimitive(String code) {
034    return Utilities.existsInList(code, "boolean", "integer", "string", "decimal", "uri", "base64Binary", "instant", "date", "dateTime", "time", "code", "oid", "id", "markdown", "unsignedInt", "positiveInt", "xhtml", "url", "canonical");
035    
036//    StructureDefinition sd = context.fetchResource(StructureDefinition.class, "http://hl7.org/fhir/StructureDefinition/"+code);
037//    return sd != null && sd.getKind() == StructureDefinitionKind.PRIMITIVETYPE;
038        }
039
040        protected IWorkerContext context;
041        protected ValidationPolicy policy;
042  protected List<ValidationMessage> errors;
043  protected ILinkResolver linkResolver;
044
045        public ParserBase(IWorkerContext context) {
046                super();
047                this.context = context;
048                policy = ValidationPolicy.NONE;
049        }
050
051        public void setupValidation(ValidationPolicy policy, List<ValidationMessage> errors) {
052          this.policy = policy;
053          this.errors = errors;
054        }
055
056  public abstract Element parse(InputStream stream) throws IOException, FHIRFormatError, DefinitionException, FHIRException;
057
058        public abstract void compose(Element e, OutputStream destination, OutputStyle style, String base)  throws FHIRException, IOException;
059
060        
061        public void logError(int line, int col, String path, IssueType type, String message, IssueSeverity level) throws FHIRFormatError {
062          if (policy == ValidationPolicy.EVERYTHING) {
063            ValidationMessage msg = new ValidationMessage(Source.InstanceValidator, type, line, col, path, message, level);
064            errors.add(msg);
065          } else if (level == IssueSeverity.FATAL || (level == IssueSeverity.ERROR && policy == ValidationPolicy.QUICK))
066            throw new FHIRFormatError(message+String.format(" at line %d col %d", line, col));
067        }
068        
069        
070        protected StructureDefinition getDefinition(int line, int col, String ns, String name) throws FHIRFormatError {
071    if (ns == null) {
072      logError(line, col, name, IssueType.STRUCTURE, "This cannot be parsed as a FHIR object (no namespace)", IssueSeverity.FATAL);
073      return null;
074    }
075    if (name == null) {
076      logError(line, col, name, IssueType.STRUCTURE, "This cannot be parsed as a FHIR object (no name)", IssueSeverity.FATAL);
077      return null;
078        }
079          for (StructureDefinition sd : context.allStructures()) {
080            if (name.equals(sd.getIdElement().getIdPart()) && !sd.getUrl().startsWith("http://hl7.org/fhir/StructureDefinition/de-")) {
081              if((ns == null || ns.equals(FormatUtilities.FHIR_NS)) && !ToolingExtensions.hasExtension(sd, "http://hl7.org/fhir/StructureDefinition/elementdefinition-namespace"))
082                return sd;
083              String sns = ToolingExtensions.readStringExtension(sd, "http://hl7.org/fhir/StructureDefinition/elementdefinition-namespace");
084              if (ns != null && ns.equals(sns))
085                return sd;
086            }
087          }
088          logError(line, col, name, IssueType.STRUCTURE, "This does not appear to be a FHIR resource (unknown namespace/name '"+ns+"::"+name+"')", IssueSeverity.FATAL);
089          return null;
090  }
091
092        protected StructureDefinition getDefinition(int line, int col, String name) throws FHIRFormatError {
093    if (name == null) {
094      logError(line, col, name, IssueType.STRUCTURE, "This cannot be parsed as a FHIR object (no name)", IssueSeverity.FATAL);
095      return null;
096        }
097    // first pass: only look at base definitions
098          for (StructureDefinition sd : context.allStructures()) {
099            if (sd.getUrl().equals("http://hl7.org/fhir/StructureDefinition/"+name)) {
100              return sd;
101            }
102          }
103    for (StructureDefinition sd : context.allStructures()) {
104      if (name.equals(sd.getIdElement().getIdPart())) {
105        return sd;
106      }
107    }
108          logError(line, col, name, IssueType.STRUCTURE, "This does not appear to be a FHIR resource (unknown name '"+name+"')", IssueSeverity.FATAL);
109          return null;
110  }
111
112  public ILinkResolver getLinkResolver() {
113    return linkResolver;
114  }
115
116  public ParserBase setLinkResolver(ILinkResolver linkResolver) {
117    this.linkResolver = linkResolver;
118    return this;
119  }
120
121
122
123  
124}