View Javadoc
1   package ca.uhn.fhir.validation;
2   
3   /*
4    * #%L
5    * HAPI FHIR - Core Library
6    * %%
7    * Copyright (C) 2014 - 2018 University Health Network
8    * %%
9    * Licensed under the Apache License, Version 2.0 (the "License");
10   * you may not use this file except in compliance with the License.
11   * You may obtain a copy of the License at
12   * 
13   *      http://www.apache.org/licenses/LICENSE-2.0
14   * 
15   * Unless required by applicable law or agreed to in writing, software
16   * distributed under the License is distributed on an "AS IS" BASIS,
17   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18   * See the License for the specific language governing permissions and
19   * limitations under the License.
20   * #L%
21   */
22  
23  import static org.apache.commons.lang3.StringUtils.isNotBlank;
24  
25  import java.util.Collections;
26  import java.util.List;
27  
28  import org.hl7.fhir.instance.model.api.IBaseOperationOutcome;
29  
30  import ca.uhn.fhir.context.FhirContext;
31  import ca.uhn.fhir.rest.api.Constants;
32  import ca.uhn.fhir.util.OperationOutcomeUtil;
33  
34  /**
35   * Encapsulates the results of validation
36   *
37   * @see ca.uhn.fhir.validation.FhirValidator
38   * @since 0.7
39   */
40  public class ValidationResult {
41  	private final FhirContext myCtx;
42  	private final boolean myIsSuccessful;
43  	private final List<SingleValidationMessage> myMessages;
44  
45  	public ValidationResult(FhirContext theCtx, List<SingleValidationMessage> theMessages) {
46  		boolean successful = true;
47  		myCtx = theCtx;
48  		myMessages = theMessages;
49  		for (SingleValidationMessage next : myMessages) {
50  			next.getSeverity();
51  			if (next.getSeverity() == null || next.getSeverity().ordinal() > ResultSeverityEnum.WARNING.ordinal()) {
52  				successful = false;
53  			}
54  		}
55  		myIsSuccessful = successful;
56  	}
57  
58  	public List<SingleValidationMessage> getMessages() {
59  		return Collections.unmodifiableList(myMessages);
60  	}
61  
62  	/**
63  	 * Was the validation successful (in other words, do we have no issues that are at
64  	 * severity {@link ResultSeverityEnum#ERROR} or {@link ResultSeverityEnum#FATAL}. A validation
65  	 * is still considered successful if it only has issues at level {@link ResultSeverityEnum#WARNING} or
66  	 * lower.
67  	 * 
68  	 * @return true if the validation was successful
69  	 */
70  	public boolean isSuccessful() {
71  		return myIsSuccessful;
72  	}
73  
74  	private String toDescription() {
75  		StringBuilder b = new StringBuilder(100);
76  		if (myMessages.size() > 0) {
77  			if (myMessages.get(0).getSeverity() != null) {
78  				b.append(myMessages.get(0).getSeverity().name());
79  				b.append(" - ");
80  			}
81  			b.append(myMessages.get(0).getMessage());
82  			b.append(" - ");
83  			b.append(myMessages.get(0).getLocationString());
84  		} else {
85  			b.append("No issues");
86  		}
87  		return b.toString();
88  	}
89  
90  	/**
91  	 * @deprecated Use {@link #toOperationOutcome()} instead since this method returns a view.
92  	 *             {@link #toOperationOutcome()} is identical to this method, but has a more suitable name so this method
93  	 *             will be removed at some point.
94  	 */
95  	@Deprecated
96  	public IBaseOperationOutcome getOperationOutcome() {
97  		return toOperationOutcome();
98  	}
99  
100 	/**
101 	 * Create an OperationOutcome resource which contains all of the messages found as a result of this validation
102 	 */
103 	public IBaseOperationOutcome toOperationOutcome() {
104 		IBaseOperationOutcome oo = (IBaseOperationOutcome) myCtx.getResourceDefinition("OperationOutcome").newInstance();
105 		populateOperationOutcome(oo);
106 		return oo;
107 	}
108 
109 	/**
110 	 * Populate an operation outcome with the results of the validation 
111 	 */
112 	public void populateOperationOutcome(IBaseOperationOutcome theOperationOutcome) {
113 		for (SingleValidationMessage next : myMessages) {
114 			String location;
115 			if (isNotBlank(next.getLocationString())) {
116 				location = next.getLocationString();
117 			} else if (next.getLocationLine() != null || next.getLocationCol() != null) {
118 				location = "Line[" + next.getLocationLine() + "] Col[" + next.getLocationCol() + "]";
119 			} else {
120 				location = null;
121 			}
122 			String severity = next.getSeverity() != null ? next.getSeverity().getCode() : null;
123 			OperationOutcomeUtil.addIssue(myCtx, theOperationOutcome, severity, next.getMessage(), location, Constants.OO_INFOSTATUS_PROCESSING);
124 		}
125 
126 		if (myMessages.isEmpty()) {
127 			String message = myCtx.getLocalizer().getMessage(ValidationResult.class, "noIssuesDetected");
128 			OperationOutcomeUtil.addIssue(myCtx, theOperationOutcome, "information", message, null, "informational");
129 		}
130 	}
131 
132 	@Override
133 	public String toString() {
134 		return "ValidationResult{" + "messageCount=" + myMessages.size() + ", isSuccessful=" + myIsSuccessful + ", description='" + toDescription() + '\'' + '}';
135 	}
136 }