Skip to content

Commit

Permalink
Merge branch 'GeVa2072-feature/properties_annotation_emit_signal'
Browse files Browse the repository at this point in the history
  • Loading branch information
hypfvieh committed Aug 30, 2024
2 parents d0c4838 + 2280cd3 commit bf6347a
Show file tree
Hide file tree
Showing 5 changed files with 90 additions and 19 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.freedesktop.dbus.annotations;

import org.freedesktop.dbus.annotations.DBusProperty.Access;
import org.freedesktop.dbus.annotations.PropertiesEmitsChangedSignal.EmitChangeSignal;
import org.freedesktop.dbus.interfaces.Properties;

import java.lang.annotation.ElementType;
Expand Down Expand Up @@ -79,4 +80,26 @@
*/
Access access() default Access.READ_WRITE;

/**
* Annotation org.freedesktop.DBus.Property.EmitsChangedSignal.
* <b>From <a href="https://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces">DBUS Specification</a>:</b><br>
* If set to false, the org.freedesktop.DBus.Properties.PropertiesChanged signal,<br>
* see the section called “org.freedesktop.DBus.Properties” is not guaranteed to be emitted if the property changes.<br>
* <br>
* If set to const the property never changes value during the lifetime of the object it belongs to, <br>
* and hence the signal is never emitted for it. <br>
* <br>
* If set to invalidates the signal is emitted but the value is not included in the signal.<br>
* <br>
* If set to true the signal is emitted with the value included. <br>
* The value for the annotation defaults to true if the enclosing interface element does not specify the annotation.
* Otherwise it defaults to the value specified in the enclosing interface element.<br>
* <br>
* This annotation is intended to be used by code generators to implement client-side caching of property values. <br>
* For all properties for which the annotation is set to const, invalidates or true the client may unconditionally <br>
* cache the values as the properties don't change or notifications are generated for them if they do.
*
* @return emitChangeSignal
*/
EmitChangeSignal emitChangeSignal() default EmitChangeSignal.TRUE;
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
package org.freedesktop.dbus.annotations;

import org.freedesktop.dbus.annotations.PropertiesEmitsChangedSignal.EmitChangeSignal;
import org.freedesktop.dbus.types.Variant;

import java.lang.annotation.ElementType;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.annotation.*;

/**
* Appends information about properties in the interface. The annotated properties are added to the introspection data.
Expand Down Expand Up @@ -46,16 +43,16 @@
String name();

/**
* type of the property, in case of complex types please create custom interface that extends {@link org.freedesktop.dbus.TypeRef}
* type of the property, in case of complex types please create custom interface that extends {@link org.freedesktop.dbus.TypeRef}.
*
* @return type
*/
Class<?> type() default Variant.class;

/**
* Property access type
* Specifies the access type of this property.
*
* @return access
* @return access type, never null
*/
Access access() default Access.READ_WRITE;

Expand All @@ -74,4 +71,12 @@ public String getAccessName() {
return accessName;
}
}

/**
* Property which defines if a signal is emitted when the annotated property was changed.
*
* @return emitChangeSignal, never null
*/
EmitChangeSignal emitChangeSignal() default EmitChangeSignal.TRUE;

}
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,21 @@
@Retention(RetentionPolicy.RUNTIME)
@DBusInterfaceName("org.freedesktop.DBus.Property.EmitsChangedSignal")
public @interface PropertiesEmitsChangedSignal {

EmitChangeSignal value();

/**
* The different values which are supported for emitting a signal.
*/
enum EmitChangeSignal {
TRUE, INVALIDATES, CONST, FALSE;
/** The signal is emitted with the value included. */
TRUE,
/** The signal is emitted but the value is not included in the signal. */
INVALIDATES,
/** The property never changes value during the lifetime of the object it belongs to, and hence the signal is never emitted for it. */
CONST,
/** It is not guaranteed to emit a signal if the property changes. */
FALSE;

@Override
public String toString() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import org.freedesktop.dbus.*;
import org.freedesktop.dbus.annotations.*;
import org.freedesktop.dbus.annotations.DBusProperty.Access;
import org.freedesktop.dbus.annotations.PropertiesEmitsChangedSignal.EmitChangeSignal;
import org.freedesktop.dbus.connections.AbstractConnection;
import org.freedesktop.dbus.exceptions.DBusException;
import org.freedesktop.dbus.exceptions.DBusExecutionException;
Expand Down Expand Up @@ -62,9 +63,7 @@ protected String generateAnnotationsXml(AnnotatedElement _c) {
String value = "";
try {
Method m = t.getMethod("value");
if (m != null) {
value = m.invoke(a).toString();
}
value = m.invoke(a).toString();
} catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException _ex) {
LoggerFactory.getLogger(getClass()).trace("Could not find value", _ex);
}
Expand All @@ -84,7 +83,7 @@ protected String generateAnnotationsXml(AnnotatedElement _c) {
* @throws DBusException in case of unknown data types
*/
protected String generatePropertyXml(DBusProperty _property) throws DBusException {
return generatePropertyXml(_property.name(), _property.type(), _property.access());
return generatePropertyXml(_property.name(), _property.type(), _property.access(), _property.emitChangeSignal());
}

/**
Expand All @@ -96,7 +95,7 @@ protected String generatePropertyXml(DBusProperty _property) throws DBusExceptio
* @return xml with property definition
* @throws DBusException in case of unknown data types
*/
protected String generatePropertyXml(String _propertyName, Class<?> _propertyTypeClass, Access _access) throws DBusException {
protected String generatePropertyXml(String _propertyName, Class<?> _propertyTypeClass, Access _access, EmitChangeSignal _emitChangeSignal) throws DBusException {
String propertyTypeString;
if (TypeRef.class.isAssignableFrom(_propertyTypeClass)) {
Type actualType = Optional.ofNullable(Util.unwrapTypeRef(_propertyTypeClass))
Expand All @@ -115,6 +114,11 @@ protected String generatePropertyXml(String _propertyName, Class<?> _propertyTyp
}

String access = _access.getAccessName();
if (_emitChangeSignal != null && _emitChangeSignal != EmitChangeSignal.TRUE) {
return "<property name=\"" + _propertyName + "\" type=\"" + propertyTypeString + "\" access=\"" + access + "\">"
+ "\n <annotation name=\"org.freedesktop.DBus.Property.EmitsChangedSignal\" value=\"" + _emitChangeSignal.name().toLowerCase()
+ "\"/>\n </property>\n";
}
return "<property name=\"" + _propertyName + "\" type=\"" + propertyTypeString + "\" access=\"" + access + "\" />";
}

Expand All @@ -126,6 +130,11 @@ protected String generatePropertyXml(String _propertyName, Class<?> _propertyTyp
* @throws DBusException in case of unknown data types
*/
protected String generatePropertiesXml(Class<?> _clz) throws DBusException {

EmitChangeSignal globalChangeSignal = Optional.ofNullable(_clz.getAnnotation(PropertiesEmitsChangedSignal.class))
.map(e -> e.value())
.orElse(EmitChangeSignal.TRUE);

StringBuilder xml = new StringBuilder();
Map<String, PropertyRef> map = new HashMap<>();
DBusProperties properties = _clz.getAnnotation(DBusProperties.class);
Expand Down Expand Up @@ -163,16 +172,23 @@ protected String generatePropertiesXml(Class<?> _clz) throws DBusException {
throw new DBusException(MessageFormat.format(
"Property ''{0}'' has access mode ''{1}'' defined multiple times.", name, access));
} else {
map.put(name, new PropertyRef(name, type, Access.READ_WRITE));
// if the signal of the annotation is null or the same as the default (TRUE),
// use whatever the global annotation defines
// this means DBusBoundProperty has precedence over the global annotation
EmitChangeSignal emitSignal = Optional.ofNullable(propertyAnnot.emitChangeSignal())
.filter(s -> s == globalChangeSignal)
.orElse(globalChangeSignal);

map.put(name, new PropertyRef(name, type, Access.READ_WRITE, emitSignal));
}
} else {
map.put(name, ref);
}
}
}

for (var ref : map.values()) {
xml.append(" ").append(generatePropertyXml(ref.getName(), ref.getType(), ref.getAccess())).append("\n");
for (PropertyRef ref : map.values()) {
xml.append(" ").append(generatePropertyXml(ref.getName(), ref.getType(), ref.getAccess(), ref.getEmitChangeSignal())).append("\n");
}

return xml.toString();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import org.freedesktop.dbus.annotations.DBusBoundProperty;
import org.freedesktop.dbus.annotations.DBusProperty;
import org.freedesktop.dbus.annotations.DBusProperty.Access;
import org.freedesktop.dbus.annotations.PropertiesEmitsChangedSignal.EmitChangeSignal;

import java.lang.reflect.Method;
import java.util.Objects;
Expand All @@ -15,21 +16,31 @@
* @author Brett Smith
* @since 5.0.0 - 2023-10-20
*/
public final class PropertyRef {
public final class PropertyRef {

private final String name;
private final Class<?> type;
private final DBusProperty.Access access;
private final EmitChangeSignal emitChangeSignal;

public PropertyRef(String _name, Class<?> _type, Access _access) {
super();
this.name = _name;
this.type = _type;
this.access = _access;
this.emitChangeSignal = EmitChangeSignal.TRUE;
}

public PropertyRef(String _name, Class<?> _type, Access _access, EmitChangeSignal _emitChangeSignal) {
super();
this.name = _name;
this.type = _type;
this.access = _access;
this.emitChangeSignal = _emitChangeSignal;
}

public PropertyRef(DBusProperty _property) {
this(_property.name(), _property.type(), _property.access());
this(_property.name(), _property.type(), _property.access(), _property.emitChangeSignal());
}

@Override
Expand Down Expand Up @@ -64,6 +75,10 @@ public DBusProperty.Access getAccess() {
return access;
}

public EmitChangeSignal getEmitChangeSignal() {
return emitChangeSignal;
}

public static Access accessForMethod(Method _method) {
DBusBoundProperty annotation = _method.getAnnotation(DBusBoundProperty.class);
Access access = _method.getName().toLowerCase().startsWith("set") ? Access.WRITE : Access.READ;
Expand Down Expand Up @@ -95,4 +110,5 @@ public static void checkMethod(Method _method) {
throw new IllegalArgumentException("WRITE properties must have exactly 1 parameter, and return void.");
}
}

}

0 comments on commit bf6347a

Please sign in to comment.