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}