001package ca.uhn.fhir.rest.server.messaging; 002 003/*- 004 * #%L 005 * HAPI FHIR - Server Framework 006 * %% 007 * Copyright (C) 2014 - 2022 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 023 024 025import ca.uhn.fhir.model.api.IModelJson; 026import com.fasterxml.jackson.annotation.JsonProperty; 027import org.apache.commons.lang3.Validate; 028 029import javax.annotation.Nullable; 030import java.util.HashMap; 031import java.util.Map; 032import java.util.Optional; 033 034@SuppressWarnings("WeakerAccess") 035public abstract class BaseResourceMessage implements IResourceMessage, IModelJson { 036 037 @JsonProperty("operationType") 038 protected BaseResourceModifiedMessage.OperationTypeEnum myOperationType; 039 040 @JsonProperty("attributes") 041 private Map<String, String> myAttributes; 042 043 @JsonProperty("transactionId") 044 private String myTransactionId; 045 046 @JsonProperty("mediaType") 047 private String myMediaType; 048 049 /** 050 * This is used by any message going to kafka for topic partition selection purposes. 051 */ 052 @JsonProperty("messageKey") 053 private String myMessageKey; 054 055 /** 056 * Returns an attribute stored in this message. 057 * <p> 058 * Attributes are just a spot for user data of any kind to be 059 * added to the message for pasing along the subscription processing 060 * pipeline (typically by interceptors). Values will be carried from the beginning to the end. 061 * </p> 062 * <p> 063 * Note that messages are designed to be passed into queueing systems 064 * and serialized as JSON. As a result, only strings are currently allowed 065 * as values. 066 * </p> 067 */ 068 public Optional<String> getAttribute(String theKey) { 069 Validate.notBlank(theKey); 070 if (myAttributes == null) { 071 return Optional.empty(); 072 } 073 return Optional.ofNullable(myAttributes.get(theKey)); 074 } 075 076 /** 077 * Sets an attribute stored in this message. 078 * <p> 079 * Attributes are just a spot for user data of any kind to be 080 * added to the message for passing along the subscription processing 081 * pipeline (typically by interceptors). Values will be carried from the beginning to the end. 082 * </p> 083 * <p> 084 * Note that messages are designed to be passed into queueing systems 085 * and serialized as JSON. As a result, only strings are currently allowed 086 * as values. 087 * </p> 088 * 089 * @param theKey The key (must not be null or blank) 090 * @param theValue The value (must not be null) 091 */ 092 public void setAttribute(String theKey, String theValue) { 093 Validate.notBlank(theKey); 094 Validate.notNull(theValue); 095 if (myAttributes == null) { 096 myAttributes = new HashMap<>(); 097 } 098 myAttributes.put(theKey, theValue); 099 } 100 101 /** 102 * Copies any attributes from the given message into this messsage. 103 * 104 * @see #setAttribute(String, String) 105 * @see #getAttribute(String) 106 */ 107 public void copyAdditionalPropertiesFrom(BaseResourceMessage theMsg) { 108 if (theMsg.myAttributes != null) { 109 if (myAttributes == null) { 110 myAttributes = new HashMap<>(); 111 } 112 myAttributes.putAll(theMsg.myAttributes); 113 } 114 } 115 116 /** 117 * Returns the {@link OperationTypeEnum} that is occurring to the Resource of the message 118 * 119 * @return the operation type. 120 */ 121 public BaseResourceModifiedMessage.OperationTypeEnum getOperationType() { 122 return myOperationType; 123 } 124 125 /** 126 * Sets the {@link OperationTypeEnum} occuring to the resource of the message. 127 * 128 * @param theOperationType The operation type to set. 129 */ 130 public void setOperationType(BaseResourceModifiedMessage.OperationTypeEnum theOperationType) { 131 myOperationType = theOperationType; 132 } 133 134 /** 135 * Retrieve the transaction ID related to this message. 136 * 137 * @return the transaction ID, or null. 138 */ 139 @Nullable 140 public String getTransactionId() { 141 return myTransactionId; 142 } 143 144 /** 145 * Adds a transaction ID to this message. This ID can be used for many purposes. For example, performing tracing 146 * across asynchronous hooks, tying data together, or downstream logging purposes. 147 * 148 * One current internal implementation uses this field to tie back MDM processing results (which are asynchronous) 149 * to the original transaction log that caused the MDM processing to occur. 150 * 151 * @param theTransactionId An ID representing a transaction of relevance to this message. 152 */ 153 public void setTransactionId(String theTransactionId) { 154 myTransactionId = theTransactionId; 155 } 156 157 public String getMediaType() { 158 return myMediaType; 159 } 160 161 public void setMediaType(String theMediaType) { 162 myMediaType = theMediaType; 163 } 164 165 @Nullable 166 public String getMessageKeyOrNull() { 167 return myMessageKey; 168 } 169 170 public void setMessageKey(String theMessageKey) { 171 myMessageKey = theMessageKey; 172 } 173 174 public enum OperationTypeEnum { 175 CREATE, 176 UPDATE, 177 DELETE, 178 MANUALLY_TRIGGERED, 179 TRANSACTION 180 } 181}