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