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