io.micronaut.pulsar.processor.PulsarArgumentHandler Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of micronaut-pulsar Show documentation
Show all versions of micronaut-pulsar Show documentation
Integration between Micronaut and Apache Pulsar
The newest version!
/*
* Copyright 2017-2022 original 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 io.micronaut.pulsar.processor;
import io.micronaut.core.annotation.AnnotationValue;
import io.micronaut.core.annotation.Internal;
import io.micronaut.core.annotation.Nullable;
import io.micronaut.core.type.Argument;
import io.micronaut.messaging.annotation.MessageBody;
import io.micronaut.messaging.annotation.MessageHeader;
import io.micronaut.pulsar.annotation.MessageKey;
import io.micronaut.pulsar.annotation.MessageProperties;
import org.apache.pulsar.client.api.Consumer;
import org.apache.pulsar.client.api.Message;
import java.util.*;
/**
* Helper processor class for arguments and headers on Pulsar consumers / processors.
*
* @author Haris Secic
* @since 1.1
*/
@Internal
public final class PulsarArgumentHandler {
private final LinkedHashMap> methodArguments;
private final Map headers;
public PulsarArgumentHandler(Argument>[] methodArguments, final String methodPath) {
this.methodArguments = processArguments(methodArguments, methodPath);
this.headers = processSingleHeaders(methodArguments);
if (hasHeaderList() && hasHeadersMap()) {
throw new IllegalArgumentException("Cannot have both MessageProperties and individual mappings with " +
"MessageHeader on the same method.");
}
}
private static Map processSingleHeaders(final Argument>[] arguments) {
final Map headers = new HashMap<>(arguments.length);
// ensuring order compared to other arguments so no pre-filtering
for (int i = 0; i < arguments.length; i++) {
final Argument> arg = arguments[i];
final Optional> annotation = arg.findAnnotation(MessageHeader.class);
if (!annotation.isPresent()) {
continue;
}
final String name = annotation.get().stringValue().orElse(arg.getName());
headers.put(name, i);
}
return Collections.unmodifiableMap(headers);
}
private static LinkedHashMap> processArguments(final Argument>[] arguments, final String methodPath) {
final LinkedHashMap> ordered = new LinkedHashMap<>(arguments.length);
if (arguments.length == 1) {
ordered.put("body", arguments[0]);
return ordered;
}
for (Argument> nonHeaderArg : arguments) {
if (nonHeaderArg.isAnnotationPresent(MessageBody.class)) {
if (ordered.containsKey("body")) {
throw new IllegalArgumentException("Only 1 argument can be mapped as MessageBody on " + methodPath + ".");
}
ordered.put("body", nonHeaderArg);
} else if (nonHeaderArg.isAnnotationPresent(MessageKey.class)) {
if (ordered.containsKey("key")) {
throw new IllegalArgumentException("Only 1 argument can be mapped as MessageKey on " + methodPath + ".");
}
ordered.put("key", nonHeaderArg);
} else if (nonHeaderArg.isAnnotationPresent(MessageProperties.class)) {
if (ordered.containsKey("headers")) {
throw new IllegalArgumentException("Only 1 argument can be mapped as MessageProperties on " + methodPath + ".");
}
ordered.put(nonHeaderArg.getName(), nonHeaderArg);
} else if (Consumer.class.isAssignableFrom(nonHeaderArg.getType())) {
if (ordered.containsKey("consumer")) {
throw new IllegalArgumentException("Only 1 argument can be of type Consumer on " + methodPath + ".");
}
ordered.put("consumer", nonHeaderArg);
} else if (!nonHeaderArg.isAnnotationPresent(MessageHeader.class)) {
throw new IllegalArgumentException("Argument must be annotated with MessageBody, MessageKey, " +
"or MessageProperties when more than 1 are present for " + methodPath);
}
}
if (ordered.containsKey("headers")) {
final Argument> map = ordered.get("headers");
if (!Map.class.isAssignableFrom(map.getType())) {
throw new IllegalArgumentException("Argument annotated with @MessageProperties must be a map");
}
if (!Arrays.stream(map.getTypeParameters()).allMatch(x -> String.class.isAssignableFrom(x.getType()))) {
throw new IllegalArgumentException("MessageProperties map can only contain string keys and values");
}
}
if (!ordered.containsKey("body")) {
throw new IllegalArgumentException("Annotation io.micronaut.messaging.annotation.MessageBody" +
" must be present on a single parameter when more than 1 parameter is used with the consumer.");
}
return ordered;
}
public Argument> getBodyArgument() {
return methodArguments.get("body");
}
public boolean isMessageWrapper() {
return Message.class.isAssignableFrom(methodArguments.get("body").getType());
}
@Nullable
public Argument> getKeyArgument() {
return methodArguments.get("key");
}
public boolean hasHeaderList() {
return !headers.isEmpty();
}
public boolean hasHeadersMap() {
return methodArguments.containsKey("headers");
}
public Map argumentOrder() {
final Map order = new HashMap<>(methodArguments.size());
int i = 0;
for (String key : methodArguments.keySet()) {
order.put(key, i);
i++;
}
return Collections.unmodifiableMap(order);
}
public Map headersOrder() {
return headers;
}
public int size() {
return argumentOrder().size() + headers.size();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy