001package ca.uhn.fhir.model.base.composite;
002
003/*
004 * #%L
005 * HAPI FHIR - Core Library
006 * %%
007 * Copyright (C) 2014 - 2021 Smile CDR, Inc.
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 static org.apache.commons.lang3.StringUtils.isBlank;
024
025import org.hl7.fhir.instance.model.api.IBaseDatatype;
026import org.hl7.fhir.instance.model.api.IBaseReference;
027import org.hl7.fhir.instance.model.api.IBaseResource;
028import org.hl7.fhir.instance.model.api.IIdType;
029
030import ca.uhn.fhir.context.RuntimeResourceDefinition;
031import ca.uhn.fhir.model.api.BaseIdentifiableElement;
032import ca.uhn.fhir.model.api.IResource;
033import ca.uhn.fhir.model.primitive.IdDt;
034import ca.uhn.fhir.model.primitive.StringDt;
035import ca.uhn.fhir.rest.client.api.IRestfulClient;
036
037public abstract class BaseResourceReferenceDt extends BaseIdentifiableElement implements IBaseDatatype, IBaseReference {
038
039        private static final long serialVersionUID = 1L;
040        
041        private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(BaseResourceReferenceDt.class);
042        private IBaseResource myResource;
043
044        /**
045         * Constructor
046         */
047        public BaseResourceReferenceDt() {
048                // nothing
049        }
050
051        /**
052         * Constructor
053         * 
054         * @param theResource
055         *           The loaded resource itself
056         */
057        public BaseResourceReferenceDt(IResource theResource) {
058                myResource = theResource;
059                setReference(theResource.getId());
060        }
061
062        @Override
063        public abstract StringDt getDisplayElement();
064
065        public abstract IdDt getReference();
066
067        /**
068         * Gets the actual loaded and parsed resource instance, <b>if it is already present</b>. This method will return the
069         * resource instance only if it has previously been loaded using {@link #loadResource(IRestfulClient)} or it was
070         * contained within the resource containing this resource.
071         *
072         * See the FHIR specification section on <a
073         * href="http://www.hl7.org/implement/standards/fhir/references.html#id">contained resources</a> for more
074         * information.
075         * 
076         * @see #loadResource(IRestfulClient)
077         */
078        @Override
079        public IBaseResource getResource() {
080                return myResource;
081        }
082
083        @Override
084        protected boolean isBaseEmpty() {
085                return super.isBaseEmpty() && myResource == null;
086        }
087
088        /**
089         * Returns the referenced resource, fetching it <b>if it has not already been loaded</b>. This method invokes the
090         * HTTP client to retrieve the resource unless it has already been loaded, or was a contained resource in which case
091         * it is simply returned.
092         */
093        public IBaseResource loadResource(IRestfulClient theClient) {
094                if (myResource != null) {
095                        return myResource;
096                }
097
098                IdDt resourceId = getReference();
099                if (resourceId == null || isBlank(resourceId.getValue())) {
100                        throw new IllegalStateException("Reference has no resource ID defined");
101                }
102                if (isBlank(resourceId.getBaseUrl()) || isBlank(resourceId.getResourceType())) {
103                        throw new IllegalStateException("Reference is not complete (must be in the form [baseUrl]/[resource type]/[resource ID]) - Reference is: " + resourceId.getValue());
104                }
105
106                String resourceUrl = resourceId.getValue();
107
108                ourLog.debug("Loading resource at URL: {}", resourceUrl);
109
110                RuntimeResourceDefinition definition = theClient.getFhirContext().getResourceDefinition(resourceId.getResourceType());
111                Class<? extends IBaseResource> resourceType = definition.getImplementingClass();
112                myResource = theClient.fetchResourceFromUrl(resourceType, resourceUrl);
113                myResource.setId(resourceUrl);
114                return myResource;
115        }
116
117        public abstract BaseResourceReferenceDt setReference(IdDt theReference);
118
119        public BaseResourceReferenceDt setReference(IIdType theReference) {
120                if (theReference instanceof IdDt) {
121                        setReference((IdDt) theReference);
122                } else if (theReference != null) {
123                        setReference(new IdDt(theReference.getValue()));
124                } else {
125                        setReference((IdDt) null);
126                }
127                return this;
128        }
129
130        @Override
131        public BaseResourceReferenceDt setResource(IBaseResource theResource) {
132                myResource = theResource;
133                return this;
134        }
135
136        @Override
137        public String toString() {
138                org.apache.commons.lang3.builder.ToStringBuilder b = new org.apache.commons.lang3.builder.ToStringBuilder(this, org.apache.commons.lang3.builder.ToStringStyle.SHORT_PREFIX_STYLE);
139                b.append("reference", getReference().getValueAsString());
140                b.append("loaded", getResource() != null);
141                return b.toString();
142        }
143
144}