001package ca.uhn.fhir.validation;
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 */
022
023import org.hl7.fhir.instance.model.api.IBaseResource;
024
025import ca.uhn.fhir.context.FhirContext;
026import ca.uhn.fhir.model.api.Bundle;
027import ca.uhn.fhir.model.api.IResource;
028import ca.uhn.fhir.rest.method.MethodUtil;
029import ca.uhn.fhir.rest.server.EncodingEnum;
030import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
031import ca.uhn.fhir.util.ObjectUtil;
032
033public class ValidationContext<T> extends BaseValidationContext<T> implements IValidationContext<T> {
034
035        private final IEncoder myEncoder;
036        private final T myResource;
037        private String myResourceAsString;
038        private final EncodingEnum myResourceAsStringEncoding;
039
040        private ValidationContext(FhirContext theContext, T theResource, IEncoder theEncoder) {
041                super(theContext);
042                myResource = theResource;
043                myEncoder = theEncoder;
044                if (theEncoder != null) {
045                        myResourceAsStringEncoding = theEncoder.getEncoding();
046                } else {
047                        myResourceAsStringEncoding = null;
048                }
049        }
050
051        @Override
052        public T getResource() {
053                return myResource;
054        }
055
056        @Override
057        public String getResourceAsString() {
058                if (myResourceAsString == null) {
059                        myResourceAsString = myEncoder.encode();
060                }
061                return myResourceAsString;
062        }
063
064        @Override
065        public EncodingEnum getResourceAsStringEncoding() {
066                return myResourceAsStringEncoding;
067        }
068
069        public static IValidationContext<Bundle> forBundle(final FhirContext theContext, final Bundle theBundle) {
070                return new ValidationContext<Bundle>(theContext, theBundle, new IEncoder() {
071                        @Override
072                        public String encode() {
073                                return theContext.newXmlParser().encodeBundleToString(theBundle);
074                        }
075
076                        @Override
077                        public EncodingEnum getEncoding() {
078                                return EncodingEnum.XML;
079                        }
080                });
081        }
082
083        public static <T extends IBaseResource> IValidationContext<T> forResource(final FhirContext theContext, final T theResource) {
084                return new ValidationContext<T>(theContext, theResource, new IEncoder() {
085                        @Override
086                        public String encode() {
087                                return theContext.newXmlParser().encodeResourceToString(theResource);
088                        }
089
090                        @Override
091                        public EncodingEnum getEncoding() {
092                                return EncodingEnum.XML;
093                        }
094                });
095        }
096
097        public static IValidationContext<IBaseResource> newChild(final IValidationContext<Bundle> theContext, final IResource theResource) {
098                return new IValidationContext<IBaseResource>() {
099
100                        @Override
101                        public void addValidationMessage(SingleValidationMessage theMessage) {
102                                theContext.addValidationMessage(theMessage);
103                        }
104
105                        @Override
106                        public FhirContext getFhirContext() {
107                                return theContext.getFhirContext();
108                        }
109
110                        @Override
111                        public IBaseResource getResource() {
112                                return theResource;
113                        }
114
115                        @Override
116                        public String getResourceAsString() {
117                                return theContext.getFhirContext().newXmlParser().encodeResourceToString(theResource);
118                        }
119
120                        @Override
121                        public EncodingEnum getResourceAsStringEncoding() {
122                                return EncodingEnum.XML;
123                        }
124
125                        @Override
126                        public ValidationResult toResult() {
127                                return theContext.toResult();
128                        }
129                };
130        }
131
132        private interface IEncoder {
133                String encode();
134
135                EncodingEnum getEncoding();
136        }
137
138        public static IValidationContext<IBaseResource> forText(final FhirContext theContext, final String theResourceBody) {
139                ObjectUtil.requireNonNull(theContext, "theContext can not be null");
140                ObjectUtil.requireNotEmpty(theResourceBody, "theResourceBody can not be null or empty");
141                return new BaseValidationContext<IBaseResource>(theContext) {
142
143                        private EncodingEnum myEncoding;
144                        private IBaseResource myParsed;
145
146                        @Override
147                        public IBaseResource getResource() {
148                                if (myParsed == null) {
149                                        myParsed = getResourceAsStringEncoding().newParser(getFhirContext()).parseResource(getResourceAsString());
150                                }
151                                return myParsed;
152                        }
153
154                        @Override
155                        public String getResourceAsString() {
156                                return theResourceBody;
157                        }
158
159                        @Override
160                        public EncodingEnum getResourceAsStringEncoding() {
161                                if (myEncoding == null) {
162                                        myEncoding = MethodUtil.detectEncodingNoDefault(theResourceBody);
163                                        if (myEncoding == null) {
164                                                throw new InvalidRequestException(theContext.getLocalizer().getMessage(ValidationContext.class, "unableToDetermineEncoding"));
165                                        }
166                                }
167                                return myEncoding;
168                        }
169
170                };
171        }
172}