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}