001package org.hl7.fhir.r5.utils;
002
003import java.util.List;
004
005/*
006  Copyright (c) 2011+, HL7, Inc.
007  All rights reserved.
008  
009  Redistribution and use in source and binary forms, with or without modification, 
010  are permitted provided that the following conditions are met:
011    
012   * Redistributions of source code must retain the above copyright notice, this 
013     list of conditions and the following disclaimer.
014   * Redistributions in binary form must reproduce the above copyright notice, 
015     this list of conditions and the following disclaimer in the documentation 
016     and/or other materials provided with the distribution.
017   * Neither the name of HL7 nor the names of its contributors may be used to 
018     endorse or promote products derived from this software without specific 
019     prior written permission.
020  
021  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
022  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
023  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
024  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
025  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
026  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
027  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
028  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
029  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
030  POSSIBILITY OF SUCH DAMAGE.
031  
032 */
033
034
035
036import org.hl7.fhir.r5.model.CodeableConcept;
037import org.hl7.fhir.r5.model.IntegerType;
038import org.hl7.fhir.r5.model.OperationOutcome;
039import org.hl7.fhir.r5.model.OperationOutcome.IssueSeverity;
040import org.hl7.fhir.r5.model.OperationOutcome.IssueType;
041import org.hl7.fhir.r5.model.OperationOutcome.OperationOutcomeIssueComponent;
042import org.hl7.fhir.r5.model.StringType;
043import org.hl7.fhir.r5.model.UrlType;
044import org.hl7.fhir.utilities.CommaSeparatedStringBuilder;
045import org.hl7.fhir.utilities.validation.ValidationMessage;
046
047public class OperationOutcomeUtilities {
048
049
050  public static OperationOutcomeIssueComponent convertToIssue(ValidationMessage message, OperationOutcome op) {
051    OperationOutcomeIssueComponent issue = new OperationOutcome.OperationOutcomeIssueComponent();
052    issue.setUserData("source.vm", message);   
053    issue.setCode(convert(message.getType()));
054    
055    if (message.getLocation() != null) {
056      // message location has a fhirPath in it. We need to populate the expression
057      issue.addExpression(message.getLocation());
058    }
059    // pass through line/col if they're present
060    if (message.getLine() >= 0) {
061      issue.addExtension().setUrl(ToolingExtensions.EXT_ISSUE_LINE).setValue(new IntegerType(message.getLine()));
062    }
063    if (message.getCol() >= 0) {
064      issue.addExtension().setUrl(ToolingExtensions.EXT_ISSUE_COL).setValue(new IntegerType(message.getCol()));
065    }
066    issue.setSeverity(convert(message.getLevel()));
067    CodeableConcept c = new CodeableConcept();
068    c.setText(message.getMessage());
069    issue.setDetails(c);
070    if (message.getSource() != null) {
071      issue.getExtension().add(ToolingExtensions.makeIssueSource(message.getSource()));
072    }
073    if (message.getMessageId() != null) {
074      issue.getExtension().add(ToolingExtensions.makeIssueMessageId(message.getMessageId()));
075    }
076    issue.setUserData("source.msg", message);
077    return issue;
078  }
079
080  public static IssueSeverity convert(org.hl7.fhir.utilities.validation.ValidationMessage.IssueSeverity level) {
081    switch (level) {
082    case FATAL : return IssueSeverity.FATAL;
083    case ERROR : return IssueSeverity.ERROR;
084    case WARNING : return IssueSeverity.WARNING;
085    case INFORMATION : return IssueSeverity.INFORMATION;
086   case NULL : return IssueSeverity.NULL;
087    }
088    return IssueSeverity.NULL;
089  }
090
091  public static org.hl7.fhir.utilities.validation.ValidationMessage.IssueSeverity convert(IssueSeverity level) {
092    switch (level) {
093    case FATAL : return org.hl7.fhir.utilities.validation.ValidationMessage.IssueSeverity.FATAL;
094    case ERROR : return org.hl7.fhir.utilities.validation.ValidationMessage.IssueSeverity.ERROR;
095    case WARNING : return org.hl7.fhir.utilities.validation.ValidationMessage.IssueSeverity.WARNING;
096    case INFORMATION : return org.hl7.fhir.utilities.validation.ValidationMessage.IssueSeverity.INFORMATION;
097   case NULL : return org.hl7.fhir.utilities.validation.ValidationMessage.IssueSeverity.NULL;
098    }
099    return org.hl7.fhir.utilities.validation.ValidationMessage.IssueSeverity.NULL;
100  }
101
102  private static IssueType convert(org.hl7.fhir.utilities.validation.ValidationMessage.IssueType type) {
103    switch (type) {
104    case INVALID: return IssueType.INVALID; 
105    case STRUCTURE: return IssueType.STRUCTURE;
106    case REQUIRED: return IssueType.REQUIRED;
107    case VALUE: return IssueType.VALUE;
108    case INVARIANT: return IssueType.INVARIANT;
109    case SECURITY: return IssueType.SECURITY;
110    case LOGIN: return IssueType.LOGIN;
111    case UNKNOWN: return IssueType.UNKNOWN;
112    case EXPIRED: return IssueType.EXPIRED;
113    case FORBIDDEN: return IssueType.FORBIDDEN;
114    case SUPPRESSED: return IssueType.SUPPRESSED;
115    case PROCESSING: return IssueType.PROCESSING;
116    case NOTSUPPORTED: return IssueType.NOTSUPPORTED;
117    case DUPLICATE: return IssueType.DUPLICATE;
118    case NOTFOUND: return IssueType.NOTFOUND;
119    case TOOLONG: return IssueType.TOOLONG;
120    case CODEINVALID: return IssueType.CODEINVALID;
121    case EXTENSION: return IssueType.EXTENSION;
122    case TOOCOSTLY: return IssueType.TOOCOSTLY;
123    case BUSINESSRULE: return IssueType.BUSINESSRULE;
124    case CONFLICT: return IssueType.CONFLICT;
125    case INCOMPLETE: return IssueType.INCOMPLETE;
126    case TRANSIENT: return IssueType.TRANSIENT;
127    case LOCKERROR: return IssueType.LOCKERROR;
128    case NOSTORE: return IssueType.NOSTORE;
129    case EXCEPTION: return IssueType.EXCEPTION;
130    case TIMEOUT: return IssueType.TIMEOUT;
131    case THROTTLED: return IssueType.THROTTLED;
132    case INFORMATIONAL: return IssueType.INFORMATIONAL;
133          case NULL: return IssueType.NULL;
134    case DELETED: return IssueType.DELETED;
135    case MULTIPLEMATCHES: return IssueType.MULTIPLEMATCHES;
136    default:
137      return IssueType.NULL;
138    }
139  }
140
141  public static OperationOutcome createOutcome(List<ValidationMessage> messages) {
142    OperationOutcome res = new OperationOutcome();
143    for (ValidationMessage vm : messages) {
144      res.addIssue(convertToIssue(vm, res));
145    }
146    return res;
147  }
148  
149
150  public static OperationOutcomeIssueComponent convertToIssueSimple(ValidationMessage message, OperationOutcome op) {
151    OperationOutcomeIssueComponent issue = new OperationOutcome.OperationOutcomeIssueComponent();
152    issue.setUserData("source.vm", message);   
153    issue.setCode(convert(message.getType()));
154    
155    if (message.getLocation() != null) {
156      // message location has a fhirPath in it. We need to populate the expression
157      issue.addExpression(message.getLocation());
158    }
159    if (message.getLine() >= 0 && message.getCol() >= 0) {
160      issue.setDiagnostics("["+message.getLine()+","+message.getCol()+"]");
161    }
162    issue.setSeverity(convert(message.getLevel()));
163    CodeableConcept c = new CodeableConcept();
164    c.setText(message.getMessage());
165    issue.setDetails(c);
166    if (message.sliceText != null) {
167      issue.addExtension(ToolingExtensions.EXT_ISSUE_SLICE_INFO, new StringType(CommaSeparatedStringBuilder.join("; ", message.sliceText)));
168    }
169    if (message.getServer() != null) {
170      issue.addExtension(ToolingExtensions.EXT_ISSUE_SERVER, new UrlType(message.getServer()));
171    }
172    return issue;
173  }
174
175  public static OperationOutcome createOutcomeSimple(List<ValidationMessage> messages) {
176    OperationOutcome res = new OperationOutcome();
177    for (ValidationMessage vm : messages) {
178      res.addIssue(convertToIssueSimple(vm, res));
179    }
180    return res;
181  }
182
183}