001package ca.uhn.fhir.util; 002 003/* 004 * #%L 005 * HAPI FHIR - Core Library 006 * %% 007 * Copyright (C) 2014 - 2016 University Health Network 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 */ 022import static org.apache.commons.lang3.StringUtils.isNotBlank; 023 024import java.util.List; 025 026import org.hl7.fhir.instance.model.api.IBase; 027import org.hl7.fhir.instance.model.api.IBaseOperationOutcome; 028import org.hl7.fhir.instance.model.api.IBaseResource; 029import org.hl7.fhir.instance.model.api.IPrimitiveType; 030 031import ca.uhn.fhir.context.BaseRuntimeChildDefinition; 032import ca.uhn.fhir.context.BaseRuntimeElementCompositeDefinition; 033import ca.uhn.fhir.context.BaseRuntimeElementDefinition; 034import ca.uhn.fhir.context.FhirContext; 035import ca.uhn.fhir.context.FhirVersionEnum; 036import ca.uhn.fhir.context.RuntimeResourceDefinition; 037import ca.uhn.fhir.rest.server.exceptions.InternalErrorException; 038 039/** 040 * Utilities for dealing with OperationOutcome resources across various model versions 041 */ 042public class OperationOutcomeUtil { 043 044// /** 045// * Add an issue to an OperationOutcome 046// * 047// * @param theCtx 048// * The fhir context 049// * @param theOperationOutcome 050// * The OO resource to add to 051// * @param theSeverity 052// * The severity (e.g. "error") 053// * @param theDetails 054// * The details string 055// * @param theCode 056// */ 057// public static void addIssue(FhirContext theCtx, IBaseOperationOutcome theOperationOutcome, String theSeverity, String theDetails, String theCode) { 058// IBase issue = createIssue(theCtx, theOperationOutcome); 059// populateDetails(theCtx, issue, theSeverity, theDetails, null, theCode); 060// } 061 062 /** 063 * Add an issue to an OperationOutcome 064 * 065 * @param theCtx 066 * The fhir context 067 * @param theOperationOutcome 068 * The OO resource to add to 069 * @param theSeverity 070 * The severity (e.g. "error") 071 * @param theDetails 072 * The details string 073 * @param theCode 074 */ 075 public static void addIssue(FhirContext theCtx, IBaseOperationOutcome theOperationOutcome, String theSeverity, String theDetails, String theLocation, String theCode) { 076 IBase issue = createIssue(theCtx, theOperationOutcome); 077 populateDetails(theCtx, issue, theSeverity, theDetails, theLocation, theCode); 078 } 079 080 private static IBase createIssue(FhirContext theCtx, IBaseResource theOutcome) { 081 RuntimeResourceDefinition ooDef = theCtx.getResourceDefinition(theOutcome); 082 BaseRuntimeChildDefinition issueChild = ooDef.getChildByName("issue"); 083 BaseRuntimeElementCompositeDefinition<?> issueElement = (BaseRuntimeElementCompositeDefinition<?>) issueChild.getChildByName("issue"); 084 085 IBase issue = issueElement.newInstance(); 086 issueChild.getMutator().addValue(theOutcome, issue); 087 return issue; 088 } 089 090 public static String getFirstIssueDetails(FhirContext theCtx, IBaseOperationOutcome theOutcome) { 091 if (theCtx.getVersion().getVersion().isNewerThan(FhirVersionEnum.DSTU1)) { 092 return getFirstIssueStringPart(theCtx, theOutcome, "diagnostics"); 093 } else { 094 return getFirstIssueStringPart(theCtx, theOutcome, "details"); 095 } 096 } 097 098 public static String getFirstIssueLocation(FhirContext theCtx, IBaseOperationOutcome theOutcome) { 099 return getFirstIssueStringPart(theCtx, theOutcome, "location"); 100 } 101 102 private static String getFirstIssueStringPart(FhirContext theCtx, IBaseOperationOutcome theOutcome, String name) { 103 if (theOutcome == null) { 104 return null; 105 } 106 107 RuntimeResourceDefinition ooDef = theCtx.getResourceDefinition(theOutcome); 108 BaseRuntimeChildDefinition issueChild = ooDef.getChildByName("issue"); 109 110 List<IBase> issues = issueChild.getAccessor().getValues(theOutcome); 111 if (issues.isEmpty()) { 112 return null; 113 } 114 115 IBase issue = issues.get(0); 116 BaseRuntimeElementCompositeDefinition<?> issueElement = (BaseRuntimeElementCompositeDefinition<?>) theCtx.getElementDefinition(issue.getClass()); 117 BaseRuntimeChildDefinition detailsChild = issueElement.getChildByName(name); 118 119 List<IBase> details = detailsChild.getAccessor().getValues(issue); 120 if (details.isEmpty()) { 121 return null; 122 } 123 return ((IPrimitiveType<?>) details.get(0)).getValueAsString(); 124 } 125 126 /** 127 * Returns true if the given OperationOutcome has 1 or more Operation.issue repetitions 128 */ 129 public static boolean hasIssues(FhirContext theCtx, IBaseOperationOutcome theOutcome) { 130 if (theOutcome == null) { 131 return false; 132 } 133 RuntimeResourceDefinition ooDef = theCtx.getResourceDefinition(theOutcome); 134 BaseRuntimeChildDefinition issueChild = ooDef.getChildByName("issue"); 135 return issueChild.getAccessor().getValues(theOutcome).size() > 0; 136 } 137 138 public static IBaseOperationOutcome newInstance(FhirContext theCtx) { 139 RuntimeResourceDefinition ooDef = theCtx.getResourceDefinition("OperationOutcome"); 140 try { 141 return (IBaseOperationOutcome) ooDef.getImplementingClass().newInstance(); 142 } catch (InstantiationException e) { 143 throw new InternalErrorException("Unable to instantiate OperationOutcome", e); 144 } catch (IllegalAccessException e) { 145 throw new InternalErrorException("Unable to instantiate OperationOutcome", e); 146 } 147 } 148 149 private static void populateDetails(FhirContext theCtx, IBase theIssue, String theSeverity, String theDetails, String theLocation, String theCode) { 150 BaseRuntimeElementCompositeDefinition<?> issueElement = (BaseRuntimeElementCompositeDefinition<?>) theCtx.getElementDefinition(theIssue.getClass()); 151 BaseRuntimeChildDefinition detailsChild; 152 if (theCtx.getVersion().getVersion().isNewerThan(FhirVersionEnum.DSTU1)) { 153 detailsChild = issueElement.getChildByName("diagnostics"); 154 155 BaseRuntimeChildDefinition codeChild = issueElement.getChildByName("code"); 156 IPrimitiveType<?> codeElem = (IPrimitiveType<?>) codeChild.getChildByName("code").newInstance(codeChild.getInstanceConstructorArguments()); 157 codeElem.setValueAsString(theCode); 158 codeChild.getMutator().addValue(theIssue, codeElem); 159 } else { 160 detailsChild = issueElement.getChildByName("details"); 161 } 162 163 BaseRuntimeElementDefinition<?> stringDef = detailsChild.getChildByName(detailsChild.getElementName()); 164 BaseRuntimeChildDefinition severityChild = issueElement.getChildByName("severity"); 165 BaseRuntimeChildDefinition locationChild = issueElement.getChildByName("location"); 166 167 IPrimitiveType<?> severityElem = (IPrimitiveType<?>) severityChild.getChildByName("severity").newInstance(severityChild.getInstanceConstructorArguments()); 168 severityElem.setValueAsString(theSeverity); 169 severityChild.getMutator().addValue(theIssue, severityElem); 170 171 IPrimitiveType<?> string = (IPrimitiveType<?>) stringDef.newInstance(); 172 string.setValueAsString(theDetails); 173 detailsChild.getMutator().setValue(theIssue, string); 174 175 if (isNotBlank(theLocation)) { 176 IPrimitiveType<?> locationElem = (IPrimitiveType<?>) locationChild.getChildByName("location").newInstance(locationChild.getInstanceConstructorArguments()); 177 locationElem.setValueAsString(theLocation); 178 locationChild.getMutator().addValue(theIssue, locationElem); 179 } 180 } 181 182}