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}