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