
001/*- 002 * #%L 003 * HAPI FHIR Storage api 004 * %% 005 * Copyright (C) 2014 - 2025 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.jpa.subscription.model; 021 022import ca.uhn.fhir.context.FhirContext; 023import ca.uhn.fhir.interceptor.model.RequestPartitionId; 024import ca.uhn.fhir.parser.IParser; 025import ca.uhn.fhir.rest.api.EncodingEnum; 026import ca.uhn.fhir.rest.server.messaging.BaseResourceMessage; 027import ca.uhn.fhir.rest.server.messaging.IResourceMessage; 028import com.fasterxml.jackson.annotation.JsonIgnore; 029import com.fasterxml.jackson.annotation.JsonProperty; 030import jakarta.annotation.Nullable; 031import org.apache.commons.lang3.builder.ToStringBuilder; 032import org.hl7.fhir.instance.model.api.IBaseResource; 033import org.hl7.fhir.instance.model.api.IIdType; 034 035import java.util.Objects; 036 037import static org.apache.commons.lang3.StringUtils.isNotBlank; 038 039@SuppressWarnings("WeakerAccess") 040public class ResourceDeliveryMessage extends BaseResourceMessage implements IResourceMessage { 041 042 @JsonProperty("canonicalSubscription") 043 private CanonicalSubscription mySubscription; 044 045 @JsonProperty("partitionId") 046 private RequestPartitionId myPartitionId; 047 048 @JsonProperty("payload") 049 private String myPayloadString; 050 051 @JsonProperty("payloadId") 052 private String myPayloadId; 053 054 @JsonIgnore 055 private transient IBaseResource myPayloadDecoded; 056 057 /** 058 * Constructor 059 */ 060 public ResourceDeliveryMessage() { 061 super(); 062 myPartitionId = RequestPartitionId.defaultPartition(); 063 } 064 065 public IBaseResource getPayload(FhirContext theCtx) { 066 IBaseResource retVal = myPayloadDecoded; 067 if (retVal == null && isNotBlank(myPayloadString)) { 068 IParser parser = EncodingEnum.detectEncoding(myPayloadString).newParser(theCtx); 069 retVal = parser.parseResource(myPayloadString); 070 myPayloadDecoded = retVal; 071 } 072 return retVal; 073 } 074 075 public String getPayloadString() { 076 if (this.myPayloadString != null) { 077 return this.myPayloadString; 078 } 079 080 return ""; 081 } 082 083 public IIdType getPayloadId(FhirContext theCtx) { 084 IIdType retVal = null; 085 if (myPayloadId != null) { 086 retVal = theCtx.getVersion().newIdType().setValue(myPayloadId); 087 } 088 return retVal; 089 } 090 091 public CanonicalSubscription getSubscription() { 092 return mySubscription; 093 } 094 095 public void setSubscription(CanonicalSubscription theSubscription) { 096 mySubscription = theSubscription; 097 } 098 099 public void setPayload(FhirContext theCtx, IBaseResource thePayload, EncodingEnum theEncoding) { 100 /* 101 * Note that we populate the raw string but don't keep the parsed resource around when we set this. This 102 * has two reasons: 103 * - If we build up a big queue of these on an in-memory queue, we aren't taking up double the memory 104 * - If use a serializing queue, we aren't behaving differently (and therefore possibly missing things 105 * in tests) 106 */ 107 myPayloadString = theEncoding.newParser(theCtx).encodeResourceToString(thePayload); 108 myPayloadId = thePayload.getIdElement().toUnqualifiedVersionless().getValue(); 109 } 110 111 public void setPayloadToNull() { 112 myPayloadString = null; 113 } 114 115 @Override 116 public String getPayloadId() { 117 return myPayloadId; 118 } 119 120 @Override 121 public void setPayloadId(IIdType thePayloadId) { 122 myPayloadId = null; 123 if (thePayloadId != null) { 124 myPayloadId = thePayloadId.getValue(); 125 } 126 } 127 128 public RequestPartitionId getRequestPartitionId() { 129 return myPartitionId; 130 } 131 132 public void setPartitionId(RequestPartitionId thePartitionId) { 133 myPartitionId = thePartitionId; 134 } 135 136 @Override 137 public String toString() { 138 return new ToStringBuilder(this) 139 .append("mySubscription", mySubscription == null ? "null" : mySubscription.getIdElementString()) 140 // it isn't safe to log payloads 141 .append("myPayloadString", "[Not Logged]") 142 .append("myPayload", myPayloadDecoded) 143 .append("myPayloadId", myPayloadId) 144 .append("myPartitionId", myPartitionId) 145 .append("myOperationType", getOperationType()) 146 .toString(); 147 } 148 149 /** 150 * Helper method to fetch the subscription ID 151 */ 152 public String getSubscriptionId(FhirContext theFhirContext) { 153 String retVal = null; 154 if (getSubscription() != null) { 155 IIdType idElement = getSubscription().getIdElement(theFhirContext); 156 if (idElement != null) { 157 retVal = idElement.getValue(); 158 } 159 } 160 return retVal; 161 } 162 163 @Nullable 164 @Override 165 public String getPayloadMessageKey() { 166 return Objects.toString(super.getPayloadMessageKey(), myPayloadId); 167 } 168}