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