001package ca.uhn.fhir.validation; 002 003import java.util.ArrayList; 004import java.util.List; 005 006/* 007 * #%L 008 * HAPI FHIR - Core Library 009 * %% 010 * Copyright (C) 2014 - 2017 University Health Network 011 * %% 012 * Licensed under the Apache License, Version 2.0 (the "License"); 013 * you may not use this file except in compliance with the License. 014 * You may obtain a copy of the License at 015 * 016 * http://www.apache.org/licenses/LICENSE-2.0 017 * 018 * Unless required by applicable law or agreed to in writing, software 019 * distributed under the License is distributed on an "AS IS" BASIS, 020 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 021 * See the License for the specific language governing permissions and 022 * limitations under the License. 023 * #L% 024 */ 025 026import org.hl7.fhir.instance.model.api.IBaseResource; 027 028import ca.uhn.fhir.context.FhirContext; 029import ca.uhn.fhir.parser.IParser; 030import ca.uhn.fhir.parser.LenientErrorHandler; 031import ca.uhn.fhir.rest.api.EncodingEnum; 032import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; 033import ca.uhn.fhir.util.ObjectUtil; 034 035public class ValidationContext<T> extends BaseValidationContext<T> implements IValidationContext<T> { 036 037 private final IEncoder myEncoder; 038 private final T myResource; 039 private String myResourceAsString; 040 private final EncodingEnum myResourceAsStringEncoding; 041 042 private ValidationContext(FhirContext theContext, T theResource, IEncoder theEncoder) { 043 this(theContext, theResource, theEncoder, new ArrayList<SingleValidationMessage>()); 044 } 045 046 private ValidationContext(FhirContext theContext, T theResource, IEncoder theEncoder, List<SingleValidationMessage> theMessages) { 047 super(theContext, theMessages); 048 myResource = theResource; 049 myEncoder = theEncoder; 050 if (theEncoder != null) { 051 myResourceAsStringEncoding = theEncoder.getEncoding(); 052 } else { 053 myResourceAsStringEncoding = null; 054 } 055 } 056 057 @Override 058 public T getResource() { 059 return myResource; 060 } 061 062 @Override 063 public String getResourceAsString() { 064 if (myResourceAsString == null) { 065 myResourceAsString = myEncoder.encode(); 066 } 067 return myResourceAsString; 068 } 069 070 @Override 071 public EncodingEnum getResourceAsStringEncoding() { 072 return myResourceAsStringEncoding; 073 } 074 075 public static <T extends IBaseResource> IValidationContext<T> forResource(final FhirContext theContext, final T theResource) { 076 return new ValidationContext<T>(theContext, theResource, new IEncoder() { 077 @Override 078 public String encode() { 079 return theContext.newXmlParser().encodeResourceToString(theResource); 080 } 081 082 @Override 083 public EncodingEnum getEncoding() { 084 return EncodingEnum.XML; 085 } 086 }); 087 } 088 089 private interface IEncoder { 090 String encode(); 091 092 EncodingEnum getEncoding(); 093 } 094 095 public static IValidationContext<IBaseResource> forText(final FhirContext theContext, final String theResourceBody) { 096 ObjectUtil.requireNonNull(theContext, "theContext can not be null"); 097 ObjectUtil.requireNotEmpty(theResourceBody, "theResourceBody can not be null or empty"); 098 return new BaseValidationContext<IBaseResource>(theContext) { 099 100 private EncodingEnum myEncoding; 101 private IBaseResource myParsed; 102 103 @Override 104 public IBaseResource getResource() { 105 if (myParsed == null) { 106 IParser parser = getResourceAsStringEncoding().newParser(getFhirContext()); 107 LenientErrorHandler errorHandler = new LenientErrorHandler(); 108 errorHandler.setErrorOnInvalidValue(false); 109 parser.setParserErrorHandler(errorHandler); 110 myParsed = parser.parseResource(getResourceAsString()); 111 } 112 return myParsed; 113 } 114 115 @Override 116 public String getResourceAsString() { 117 return theResourceBody; 118 } 119 120 @Override 121 public EncodingEnum getResourceAsStringEncoding() { 122 if (myEncoding == null) { 123 myEncoding = EncodingEnum.detectEncodingNoDefault(theResourceBody); 124 if (myEncoding == null) { 125 throw new InvalidRequestException(theContext.getLocalizer().getMessage(ValidationContext.class, "unableToDetermineEncoding")); 126 } 127 } 128 return myEncoding; 129 } 130 131 }; 132 } 133 134 public static IValidationContext<IBaseResource> subContext(final IValidationContext<IBaseResource> theCtx, final IBaseResource theResource) { 135 return new ValidationContext<IBaseResource>(theCtx.getFhirContext(), theResource, new IEncoder() { 136 @Override 137 public String encode() { 138 return theCtx.getFhirContext().newXmlParser().encodeResourceToString(theResource); 139 } 140 141 @Override 142 public EncodingEnum getEncoding() { 143 return EncodingEnum.XML; 144 } 145 }, theCtx.getMessages()); 146 } 147}