All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.mongodb.kafka.connect.sink.converter.LazyBsonDocument Maven / Gradle / Ivy

There is a newer version: 1.13.1
Show newest version
/*
 * Copyright 2008-present MongoDB, Inc.
 *
 * 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
 *
 *   http://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 com.mongodb.kafka.connect.sink.converter;

import static java.lang.String.format;

import java.io.InvalidObjectException;
import java.io.ObjectInputStream;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
import java.util.function.BiFunction;

import org.apache.kafka.connect.data.Schema;
import org.apache.kafka.connect.errors.DataException;
import org.apache.kafka.connect.sink.SinkRecord;

import org.bson.BsonDocument;
import org.bson.BsonValue;

import com.mongodb.lang.Nullable;

public class LazyBsonDocument extends BsonDocument {
  private static final long serialVersionUID = 1L;

  private final transient SinkRecord record;
  private final transient Type dataType;
  private final transient BiFunction converter;

  private BsonDocument unwrapped;

  public enum Type {
    KEY,
    VALUE
  }

  /**
   * Construct a new instance with the given suppler of the document.
   *
   * @param record the sink record to convert
   * @param converter the converter for the sink record
   */
  public LazyBsonDocument(
      final SinkRecord record,
      final Type dataType,
      final BiFunction converter) {
    if (record == null) {
      throw new IllegalArgumentException("record can not be null");
    } else if (dataType == null) {
      throw new IllegalArgumentException("dataType can not be null");
    } else if (converter == null) {
      throw new IllegalArgumentException("converter can not be null");
    }
    this.record = record;
    this.dataType = dataType;
    this.converter = converter;
  }

  @Override
  public int size() {
    return getUnwrapped().size();
  }

  @Override
  public boolean isEmpty() {
    return getUnwrapped().isEmpty();
  }

  @Override
  public boolean containsKey(final Object key) {
    return getUnwrapped().containsKey(key);
  }

  @Override
  public boolean containsValue(final Object value) {
    return getUnwrapped().containsValue(value);
  }

  @Override
  public BsonValue get(final Object key) {
    return getUnwrapped().get(key);
  }

  @Override
  public BsonValue put(final String key, final BsonValue value) {
    return getUnwrapped().put(key, value);
  }

  @Override
  public BsonValue remove(final Object key) {
    return getUnwrapped().remove(key);
  }

  @Override
  public void putAll(final Map m) {
    getUnwrapped().putAll(m);
  }

  @Override
  public void clear() {
    getUnwrapped().clear();
  }

  @Override
  public Set keySet() {
    return getUnwrapped().keySet();
  }

  @Override
  public Collection values() {
    return getUnwrapped().values();
  }

  @Override
  public Set> entrySet() {
    return getUnwrapped().entrySet();
  }

  @Override
  public boolean equals(final Object o) {
    return getUnwrapped().equals(o);
  }

  @Override
  public int hashCode() {
    return getUnwrapped().hashCode();
  }

  @Override
  public String toString() {
    return getUnwrapped().toString();
  }

  @Override
  public BsonDocument clone() {
    return unwrapped != null
        ? unwrapped.clone()
        : new LazyBsonDocument(record, dataType, converter);
  }

  private BsonDocument getUnwrapped() {
    if (unwrapped == null) {
      switch (dataType) {
        case KEY:
          try {
            unwrapped = converter.apply(record.keySchema(), record.key());
          } catch (Exception e) {
            throw new DataException(
                format(
                    "Could not convert key %s into a BsonDocument.",
                    unambiguousToString(record.key())),
                e);
          }
          break;
        case VALUE:
          try {
            unwrapped = converter.apply(record.valueSchema(), record.value());
          } catch (Exception e) {
            throw new DataException(
                format(
                    "Could not convert value %s into a BsonDocument.",
                    unambiguousToString(record.value())),
                e);
          }
          break;
        default:
          throw new DataException(format("Unknown data type %s.", dataType));
      }
    }
    return unwrapped;
  }

  // see https://docs.oracle.com/javase/6/docs/platform/serialization/spec/output.html
  private Object writeReplace() {
    return getUnwrapped();
  }

  // see https://docs.oracle.com/javase/6/docs/platform/serialization/spec/input.html
  private void readObject(final ObjectInputStream stream) throws InvalidObjectException {
    throw new InvalidObjectException("Proxy required");
  }

  private static String unambiguousToString(@Nullable final Object v) {
    String vToString = String.valueOf(v);
    if (v == null) {
      return format("'%s' (null reference)", vToString);
    } else if (vToString.equals(String.valueOf((Object) null))) {
      return format("'%s' (%s, not a null reference)", vToString, v.getClass().getName());
    } else {
      return format("'%s' (%s)", vToString, v.getClass().getName());
    }
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy