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.utilities.validation.ValidationMessage;
043
044public class OperationOutcomeUtilities {
045
046
047  public static OperationOutcomeIssueComponent convertToIssue(ValidationMessage message, OperationOutcome op) {
048    OperationOutcomeIssueComponent issue = new OperationOutcome.OperationOutcomeIssueComponent();
049    issue.setUserData("source.vm", message);   
050    issue.setCode(convert(message.getType()));
051    
052    if (message.getLocation() != null) {
053      // message location has a fhirPath in it. We need to populate the expression
054      issue.addExpression(message.getLocation());
055    }
056    // pass through line/col if they're present
057    if (message.getLine() >= 0)
058      issue.addExtension().setUrl(ToolingExtensions.EXT_ISSUE_LINE).setValue(new IntegerType(message.getLine()));
059    if (message.getCol() >= 0)
060      issue.addExtension().setUrl(ToolingExtensions.EXT_ISSUE_COL).setValue(new IntegerType(message.getCol()));
061    issue.setSeverity(convert(message.getLevel()));
062    CodeableConcept c = new CodeableConcept();
063    c.setText(message.getMessage());
064    issue.setDetails(c);
065    if (message.getSource() != null) {
066      issue.getExtension().add(ToolingExtensions.makeIssueSource(message.getSource()));
067    }
068    if (message.getMessageId() != null) {
069      issue.getExtension().add(ToolingExtensions.makeIssueMessageId(message.getMessageId()));
070    }
071    issue.setUserData("source.msg", message);
072    return issue;
073  }
074
075  private static IssueSeverity convert(org.hl7.fhir.utilities.validation.ValidationMessage.IssueSeverity level) {
076    switch (level) {
077    case FATAL : return IssueSeverity.FATAL;
078    case ERROR : return IssueSeverity.ERROR;
079    case WARNING : return IssueSeverity.WARNING;
080    case INFORMATION : return IssueSeverity.INFORMATION;
081         case NULL : return IssueSeverity.NULL;
082    }
083    return IssueSeverity.NULL;
084  }
085
086  private static IssueType convert(org.hl7.fhir.utilities.validation.ValidationMessage.IssueType type) {
087    switch (type) {
088    case INVALID: 
089    case STRUCTURE: return IssueType.STRUCTURE;
090    case REQUIRED: return IssueType.REQUIRED;
091    case VALUE: return IssueType.VALUE;
092    case INVARIANT: return IssueType.INVARIANT;
093    case SECURITY: return IssueType.SECURITY;
094    case LOGIN: return IssueType.LOGIN;
095    case UNKNOWN: return IssueType.UNKNOWN;
096    case EXPIRED: return IssueType.EXPIRED;
097    case FORBIDDEN: return IssueType.FORBIDDEN;
098    case SUPPRESSED: return IssueType.SUPPRESSED;
099    case PROCESSING: return IssueType.PROCESSING;
100    case NOTSUPPORTED: return IssueType.NOTSUPPORTED;
101    case DUPLICATE: return IssueType.DUPLICATE;
102    case NOTFOUND: return IssueType.NOTFOUND;
103    case TOOLONG: return IssueType.TOOLONG;
104    case CODEINVALID: return IssueType.CODEINVALID;
105    case EXTENSION: return IssueType.EXTENSION;
106    case TOOCOSTLY: return IssueType.TOOCOSTLY;
107    case BUSINESSRULE: return IssueType.BUSINESSRULE;
108    case CONFLICT: return IssueType.CONFLICT;
109    case INCOMPLETE: return IssueType.INCOMPLETE;
110    case TRANSIENT: return IssueType.TRANSIENT;
111    case LOCKERROR: return IssueType.LOCKERROR;
112    case NOSTORE: return IssueType.NOSTORE;
113    case EXCEPTION: return IssueType.EXCEPTION;
114    case TIMEOUT: return IssueType.TIMEOUT;
115    case THROTTLED: return IssueType.THROTTLED;
116    case INFORMATIONAL: return IssueType.INFORMATIONAL;
117          case NULL: return IssueType.NULL;
118    case DELETED: return IssueType.DELETED;
119    case MULTIPLEMATCHES: return IssueType.MULTIPLEMATCHES;
120    default:
121      return IssueType.NULL;
122    }
123  }
124
125  public static OperationOutcome createOutcome(List<ValidationMessage> messages) {
126    OperationOutcome res = new OperationOutcome();
127    for (ValidationMessage vm : messages) {
128      res.addIssue(convertToIssue(vm, res));
129    }
130    return res;
131  }
132  
133
134  public static OperationOutcomeIssueComponent convertToIssueSimple(ValidationMessage message, OperationOutcome op) {
135    OperationOutcomeIssueComponent issue = new OperationOutcome.OperationOutcomeIssueComponent();
136    issue.setUserData("source.vm", message);   
137    issue.setCode(convert(message.getType()));
138    
139    if (message.getLocation() != null) {
140      // message location has a fhirPath in it. We need to populate the expression
141      issue.addExpression(message.getLocation());
142    }
143    if (message.getLine() >= 0 && message.getCol() >= 0) {
144      issue.setDiagnostics("["+message.getLine()+","+message.getCol()+"]");
145    }
146    issue.setSeverity(convert(message.getLevel()));
147    CodeableConcept c = new CodeableConcept();
148    c.setText(message.getMessage());
149    issue.setDetails(c);
150    return issue;
151  }
152
153  public static OperationOutcome createOutcomeSimple(List<ValidationMessage> messages) {
154    OperationOutcome res = new OperationOutcome();
155    for (ValidationMessage vm : messages) {
156      res.addIssue(convertToIssueSimple(vm, res));
157    }
158    return res;
159  }
160
161}