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

org.eclipse.ditto.connectivity.service.messaging.kafka.KafkaPublishTarget Maven / Gradle / Ivy

/*
 * Copyright (c) 2017 Contributors to the Eclipse Foundation
 *
 * See the NOTICE file(s) distributed with this work for additional
 * information regarding copyright ownership.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0
 *
 * SPDX-License-Identifier: EPL-2.0
 */
package org.eclipse.ditto.connectivity.service.messaging.kafka;

import java.text.MessageFormat;
import java.util.Objects;
import java.util.Optional;

import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable;

import org.apache.kafka.common.errors.InvalidTopicException;
import org.apache.kafka.common.internals.Topic;
import org.eclipse.ditto.connectivity.model.ConnectionConfigurationInvalidException;
import org.eclipse.ditto.connectivity.service.messaging.PublishTarget;

/**
 * A Kafka target to which messages can be published.
 */
@Immutable
final class KafkaPublishTarget implements PublishTarget {

    static final String KEY_SEPARATOR = "/";
    static final String PARTITION_SEPARATOR = "#";

    private final String topic;
    private final String key;
    private final Integer partition;

    private KafkaPublishTarget(final String topic, @Nullable final String key, @Nullable final Integer partition) {
        this.topic = topic;
        this.key = key;
        this.partition = partition;
    }

    static KafkaPublishTarget fromTargetAddress(final String targetAddress) {
        if (containsKey(targetAddress)) {
            return fromTargetAddressWithKey(targetAddress);
        } else if (containsPartition(targetAddress)) {
            return fromTargetAddressWithPartition(targetAddress);
        }

        return fromTargetAddressWithOnlyTopic(targetAddress);
    }

    static boolean containsKey(final String targetAddress) {
        final int index = targetAddress.indexOf(KEY_SEPARATOR);
        return index > 0 && index < targetAddress.length();
    }

    private static KafkaPublishTarget fromTargetAddressWithKey(final String targetAddress) {
        final String[] split = targetAddress.split(KEY_SEPARATOR, 2);
        final String topic = validateTopic(split[0]);
        final String key = validateKey(split[1]);
        return new KafkaPublishTarget(topic, key, null);
    }

    @Nullable
    private static String validateKey(final String key) {
        return key.isEmpty() ? null : key;
    }

    static boolean containsPartition(final String targetAddress) {
        final int index = targetAddress.indexOf(PARTITION_SEPARATOR);
        return index > 0 && index < targetAddress.length();
    }

    private static KafkaPublishTarget fromTargetAddressWithPartition(final String targetAddress) {
        final String[] split = targetAddress.split(PARTITION_SEPARATOR, 2);
        final String topic = validateTopic(split[0]);
        final Integer partition = validatePartition(split[1]);
        return new KafkaPublishTarget(topic, null, partition);
    }

    @Nullable
    private static Integer validatePartition(final String partitionString) {
        if (partitionString.isEmpty()) {
            return null;
        }
        return parsePartitionOrThrow(partitionString);
    }

    private static KafkaPublishTarget fromTargetAddressWithOnlyTopic(final String targetAddress) {
        validateTopic(targetAddress);
        return new KafkaPublishTarget(targetAddress, null, null);
    }

    private static String validateTopic(final String topic) {
        try {
            Topic.validate(topic);
            return topic;
        } catch (final InvalidTopicException e) {
            throw ConnectionConfigurationInvalidException.newBuilder(e.getMessage())
                    .cause(e)
                    .build();
        }
    }

    private static Integer parsePartitionOrThrow(final String partitionString) {
        try {
            return Integer.parseInt(partitionString);
        } catch (final NumberFormatException e) {
            final String message = MessageFormat.format("Can not parse partition number from {0}", partitionString);
            throw ConnectionConfigurationInvalidException.newBuilder(message)
                    .cause(e)
                    .build();
        }
    }

    String getTopic() {
        return topic;
    }

    Optional getKey() {
        return Optional.ofNullable(key);
    }

    Optional getPartition() {
        return Optional.ofNullable(partition);
    }

    @Override
    public boolean equals(@Nullable final Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        final KafkaPublishTarget that = (KafkaPublishTarget) o;
        return Objects.equals(topic, that.topic) &&
                Objects.equals(key, that.key) &&
                Objects.equals(partition, that.partition);
    }

    @Override
    public int hashCode() {
        return Objects.hash(topic, key, partition);
    }

    @Override
    public String toString() {
        return getClass().getSimpleName() + " [" +
                "topic=" + topic +
                ", key=" + key +
                ", partition=" + partition +
                "]";
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy