/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ChangeStreamEvent.java
Java | 223 lines | 110 code | 38 blank | 75 comment | 22 complexity | 46e3337a5cb6fecb1eea3a9faae7ac91 MD5 | raw file
- /*
- * Copyright 2018-2021 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- package org.springframework.data.mongodb.core;
- import java.time.Instant;
- import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
- import org.bson.BsonTimestamp;
- import org.bson.BsonValue;
- import org.bson.Document;
- import org.springframework.data.mongodb.core.convert.MongoConverter;
- import org.springframework.data.mongodb.core.messaging.Message;
- import org.springframework.lang.Nullable;
- import org.springframework.util.ClassUtils;
- import org.springframework.util.ObjectUtils;
- import com.mongodb.client.model.changestream.ChangeStreamDocument;
- import com.mongodb.client.model.changestream.OperationType;
- /**
- * {@link Message} implementation specific to MongoDB <a href="https://docs.mongodb.com/manual/changeStreams/">Change
- * Streams</a>.
- *
- * @author Christoph Strobl
- * @author Mark Paluch
- * @since 2.1
- */
- public class ChangeStreamEvent<T> {
- @SuppressWarnings("rawtypes") //
- private static final AtomicReferenceFieldUpdater<ChangeStreamEvent, Object> CONVERTED_UPDATER = AtomicReferenceFieldUpdater
- .newUpdater(ChangeStreamEvent.class, Object.class, "converted");
- private final @Nullable ChangeStreamDocument<Document> raw;
- private final Class<T> targetType;
- private final MongoConverter converter;
- // accessed through CONVERTED_UPDATER.
- private volatile @Nullable T converted;
- /**
- * @param raw can be {@literal null}.
- * @param targetType must not be {@literal null}.
- * @param converter must not be {@literal null}.
- */
- public ChangeStreamEvent(@Nullable ChangeStreamDocument<Document> raw, Class<T> targetType,
- MongoConverter converter) {
- this.raw = raw;
- this.targetType = targetType;
- this.converter = converter;
- }
- /**
- * Get the raw {@link ChangeStreamDocument} as emitted by the driver.
- *
- * @return can be {@literal null}.
- */
- @Nullable
- public ChangeStreamDocument<Document> getRaw() {
- return raw;
- }
- /**
- * Get the {@link ChangeStreamDocument#getClusterTime() cluster time} as {@link Instant} the event was emitted at.
- *
- * @return can be {@literal null}.
- */
- @Nullable
- public Instant getTimestamp() {
- return getBsonTimestamp() != null ? converter.getConversionService().convert(raw.getClusterTime(), Instant.class)
- : null;
- }
- /**
- * Get the {@link ChangeStreamDocument#getClusterTime() cluster time}.
- *
- * @return can be {@literal null}.
- * @since 2.2
- */
- @Nullable
- public BsonTimestamp getBsonTimestamp() {
- return raw != null ? raw.getClusterTime() : null;
- }
- /**
- * Get the {@link ChangeStreamDocument#getResumeToken() resume token} for this event.
- *
- * @return can be {@literal null}.
- */
- @Nullable
- public BsonValue getResumeToken() {
- return raw != null ? raw.getResumeToken() : null;
- }
- /**
- * Get the {@link ChangeStreamDocument#getOperationType() operation type} for this event.
- *
- * @return can be {@literal null}.
- */
- @Nullable
- public OperationType getOperationType() {
- return raw != null ? raw.getOperationType() : null;
- }
- /**
- * Get the database name the event was originated at.
- *
- * @return can be {@literal null}.
- */
- @Nullable
- public String getDatabaseName() {
- return raw != null ? raw.getNamespace().getDatabaseName() : null;
- }
- /**
- * Get the collection name the event was originated at.
- *
- * @return can be {@literal null}.
- */
- @Nullable
- public String getCollectionName() {
- return raw != null ? raw.getNamespace().getCollectionName() : null;
- }
- /**
- * Get the potentially converted {@link ChangeStreamDocument#getFullDocument()}.
- *
- * @return {@literal null} when {@link #getRaw()} or {@link ChangeStreamDocument#getFullDocument()} is
- * {@literal null}.
- */
- @Nullable
- public T getBody() {
- if (raw == null) {
- return null;
- }
- Document fullDocument = raw.getFullDocument();
- if (fullDocument == null) {
- return targetType.cast(fullDocument);
- }
- return getConverted(fullDocument);
- }
- @SuppressWarnings("unchecked")
- private T getConverted(Document fullDocument) {
- return (T) doGetConverted(fullDocument);
- }
- private Object doGetConverted(Document fullDocument) {
- Object result = CONVERTED_UPDATER.get(this);
- if (result != null) {
- return result;
- }
- if (ClassUtils.isAssignable(Document.class, fullDocument.getClass())) {
- result = converter.read(targetType, fullDocument);
- return CONVERTED_UPDATER.compareAndSet(this, null, result) ? result : CONVERTED_UPDATER.get(this);
- }
- if (converter.getConversionService().canConvert(fullDocument.getClass(), targetType)) {
- result = converter.getConversionService().convert(fullDocument, targetType);
- return CONVERTED_UPDATER.compareAndSet(this, null, result) ? result : CONVERTED_UPDATER.get(this);
- }
- throw new IllegalArgumentException(
- String.format("No converter found capable of converting %s to %s", fullDocument.getClass(), targetType));
- }
- /*
- * (non-Javadoc)
- * @see java.lang.Object#toString()
- */
- @Override
- public String toString() {
- return "ChangeStreamEvent {" + "raw=" + raw + ", targetType=" + targetType + '}';
- }
- @Override
- public boolean equals(Object o) {
- if (this == o)
- return true;
- if (o == null || getClass() != o.getClass())
- return false;
- ChangeStreamEvent<?> that = (ChangeStreamEvent<?>) o;
- if (!ObjectUtils.nullSafeEquals(this.raw, that.raw)) {
- return false;
- }
- return ObjectUtils.nullSafeEquals(this.targetType, that.targetType);
- }
- @Override
- public int hashCode() {
- int result = raw != null ? raw.hashCode() : 0;
- result = 31 * result + ObjectUtils.nullSafeHashCode(targetType);
- return result;
- }
- }