--- /dev/null
+package org.asamk.signal.dbus;
+
+import org.asamk.Signal;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.function.Consumer;
+import java.util.function.Supplier;
+
+public class DbusInterfacePropertiesHandler {
+
+ private final String interfaceName;
+ private final List<DbusProperty<?>> properties;
+
+ public DbusInterfacePropertiesHandler(
+ final String interfaceName, final List<DbusProperty<?>> properties
+ ) {
+ this.interfaceName = interfaceName;
+ this.properties = properties;
+ }
+
+ public String getInterfaceName() {
+ return interfaceName;
+ }
+
+ @SuppressWarnings("unchecked")
+ private <T> DbusProperty<T> findProperty(String propertyName) {
+ final var property = properties.stream().filter(p -> p.getName().equals(propertyName)).findFirst();
+ if (property.isEmpty()) {
+ throw new Signal.Error.Failure("Property not found");
+ }
+ return (DbusProperty<T>) property.get();
+ }
+
+ <T> Consumer<T> getSetter(String propertyName) {
+ return this.<T>findProperty(propertyName).getSetter();
+ }
+
+ <T> Supplier<T> getGetter(String propertyName) {
+ return this.<T>findProperty(propertyName).getGetter();
+ }
+
+ Collection<DbusProperty<?>> getProperties() {
+ return properties;
+ }
+}
--- /dev/null
+package org.asamk.signal.dbus;
+
+import org.asamk.Signal;
+import org.freedesktop.dbus.interfaces.Properties;
+import org.freedesktop.dbus.types.Variant;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+public abstract class DbusProperties implements Properties {
+
+ private final List<DbusInterfacePropertiesHandler> handlers = new ArrayList<>();
+
+ protected void addPropertiesHandler(DbusInterfacePropertiesHandler handler) {
+ this.handlers.add(handler);
+ }
+
+ DbusInterfacePropertiesHandler getHandler(String interfaceName) {
+ final var handler = getHandlerOptional(interfaceName);
+ if (handler.isEmpty()) {
+ throw new Signal.Error.Failure("Property not found");
+ }
+ return handler.get();
+ }
+
+ private java.util.Optional<DbusInterfacePropertiesHandler> getHandlerOptional(final String interfaceName) {
+ return handlers.stream().filter(h -> h.getInterfaceName().equals(interfaceName)).findFirst();
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public <A> A Get(final String interface_name, final String property_name) {
+ final var handler = getHandler(interface_name);
+ final var getter = handler.getGetter(property_name);
+ if (getter == null) {
+ throw new Signal.Error.Failure("Property not found");
+ }
+ return (A) getter.get();
+ }
+
+ @Override
+ public <A> void Set(final String interface_name, final String property_name, final A value) {
+ final var handler = getHandler(interface_name);
+ final var setter = handler.getSetter(property_name);
+ if (setter == null) {
+ throw new Signal.Error.Failure("Property not found");
+ }
+ setter.accept(value);
+ }
+
+ @Override
+ public Map<String, Variant<?>> GetAll(final String interface_name) {
+ final var handler = getHandlerOptional(interface_name);
+ if (handler.isEmpty()) {
+ return Map.of();
+ }
+
+ return handler.get()
+ .getProperties()
+ .stream()
+ .filter(p -> p.getGetter() != null)
+ .collect(Collectors.toMap(DbusProperty::getName, p -> new Variant<>(p.getGetter().get())));
+ }
+}
--- /dev/null
+package org.asamk.signal.dbus;
+
+import java.util.function.Consumer;
+import java.util.function.Supplier;
+
+public class DbusProperty<T> {
+
+ private final String name;
+ private final Supplier<T> getter;
+ private final Consumer<T> setter;
+
+ public DbusProperty(final String name, final Supplier<T> getter, final Consumer<T> setter) {
+ this.name = name;
+ this.getter = getter;
+ this.setter = setter;
+ }
+
+ public DbusProperty(final String name, final Supplier<T> getter) {
+ this.name = name;
+ this.getter = getter;
+ this.setter = null;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public Consumer<T> getSetter() {
+ return setter;
+ }
+
+ public Supplier<T> getGetter() {
+ return getter;
+ }
+}