HeaderFieldExtractor.java
/*
* SPDX-FileCopyrightText: 2025 Lucimber UG
* SPDX-License-Identifier: Apache-2.0
*/
package com.lucimber.dbus.util;
import com.lucimber.dbus.message.HeaderField;
import com.lucimber.dbus.type.DBusType;
import com.lucimber.dbus.type.DBusVariant;
import io.netty.handler.codec.CorruptedFrameException;
import java.util.Map;
import java.util.Optional;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Utility class for extracting typed values from D-Bus message header fields. This class provides a
* generic way to extract and validate header field values, eliminating code duplication in message
* decoders.
*/
public final class HeaderFieldExtractor {
private static final Logger LOGGER = LoggerFactory.getLogger(HeaderFieldExtractor.class);
private HeaderFieldExtractor() {
// Utility class
}
/**
* Extracts an optional header field value of the specified type.
*
* @param <T> the expected D-Bus type
* @param headerFields the map of header fields
* @param field the header field to extract
* @param expectedType the expected type class
* @return an Optional containing the value if present and of correct type
* @throws CorruptedFrameException if the field is present but of wrong type
*/
public static <T extends DBusType> Optional<T> extractOptional(
Map<HeaderField, DBusVariant> headerFields, HeaderField field, Class<T> expectedType) {
LOGGER.trace(LoggerUtils.MARSHALLING, "Getting {} from message header", field.name());
DBusVariant variant = headerFields.get(field);
if (variant == null) {
return Optional.empty();
}
DBusType variantValue = variant.getDelegate();
if (expectedType.isInstance(variantValue)) {
return Optional.of(expectedType.cast(variantValue));
} else {
String msg =
String.format(
"%s in message header is of wrong type. Expected %s but got %s",
field.name(),
expectedType.getSimpleName(),
variantValue.getClass().getSimpleName());
throw new CorruptedFrameException(msg);
}
}
/**
* Extracts a required header field value of the specified type.
*
* @param <T> the expected D-Bus type
* @param headerFields the map of header fields
* @param field the header field to extract
* @param expectedType the expected type class
* @return the value if present and of correct type
* @throws CorruptedFrameException if the field is missing or of wrong type
*/
public static <T extends DBusType> T extractRequired(
Map<HeaderField, DBusVariant> headerFields, HeaderField field, Class<T> expectedType) {
return extractOptional(headerFields, field, expectedType)
.orElseThrow(
() ->
new CorruptedFrameException(
String.format(
"Missing %s in message header", field.name())));
}
/**
* Extracts an optional string header field value.
*
* @param headerFields the map of header fields
* @param field the header field to extract
* @return an Optional containing the string value if present
* @throws CorruptedFrameException if the field is present but not a string
*/
public static Optional<String> extractOptionalString(
Map<HeaderField, DBusVariant> headerFields, HeaderField field) {
return extractOptional(headerFields, field, com.lucimber.dbus.type.DBusString.class)
.map(com.lucimber.dbus.type.DBusString::getDelegate);
}
/**
* Extracts a required string header field value.
*
* @param headerFields the map of header fields
* @param field the header field to extract
* @return the string value
* @throws CorruptedFrameException if the field is missing or not a string
*/
public static String extractRequiredString(
Map<HeaderField, DBusVariant> headerFields, HeaderField field) {
return extractRequired(headerFields, field, com.lucimber.dbus.type.DBusString.class)
.getDelegate();
}
}