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}