Skip to content

Commit

Permalink
[hypfvieh#130] DBusProperty annotation added
Browse files Browse the repository at this point in the history
  • Loading branch information
mk868 committed Feb 22, 2021
1 parent d2a353e commit 79d11bb
Show file tree
Hide file tree
Showing 4 changed files with 170 additions and 5 deletions.
15 changes: 15 additions & 0 deletions dbus-java/src/main/java/org/freedesktop/dbus/TypeRef.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package org.freedesktop.dbus;

/**
* Interface for retrieving generic type information with reflection.
* <p>
* Examples:
* <pre>{@code
* public interface ListOfStrings extends TypeRef<List<String>> {
* }
* } </pre>
*
* @param <T> generic type
*/
public interface TypeRef<T> {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package org.freedesktop.dbus.annotations;

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

/**
* Container for the multiple {@link DBusProperty} annotations in the single class.
* You probably don't want to use this annotation in your code, please use {@link DBusProperty}.
*
* @see DBusProperty
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface DBusProperties {

/**
* Container for multiple properties
*
* @return value
*/
DBusProperty[] value();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package org.freedesktop.dbus.annotations;

import org.freedesktop.dbus.types.Variant;

import java.lang.annotation.*;

/**
* Appends information about properties in the interface. The annotated properties are added to the introspection data.
* In case of complex type of the property please use {@link org.freedesktop.dbus.TypeRef}.
* <p>
* Usage:
* </p>
* <pre>{@code
* @DBusInterfaceName("com.example.Bar")
* @DBusProperty(name = "Name", type = String.class)
* @DBusProperty(name = "ListOfVariables", type = List.class, access = Access.READ)
* @DBusProperty(name = "MapOfStringList", type = ComplexTypeWithMapAndList.class, access = Access.READ)
* public interface Bar extends DBusInterface {
*
* // TypeRef allows to provide detailed information about type
* interface ComplexTypeWithMapAndList extends TypeRef<Map<String, List<String>>> {
* }
* }
* }</pre>
*
* @see org.freedesktop.dbus.interfaces.DBusInterface
* @see org.freedesktop.dbus.TypeRef
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Repeatable(DBusProperties.class)
public @interface DBusProperty {

/**
* Property name
*
* @return name
*/
String name();

/**
* 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
*
* @return access
*/
Access access() default Access.READ_WRITE;

enum Access {
READ("read"),
READ_WRITE("readwrite"),
WRITE("write");

private final String accessName;

Access(String accessName) {
this.accessName = accessName;
}

public String getAccessName() {
return accessName;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,20 @@
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.freedesktop.dbus.Marshalling;
import org.freedesktop.dbus.MethodTuple;
import org.freedesktop.dbus.StrongReference;
import org.freedesktop.dbus.Tuple;
import org.freedesktop.dbus.TypeRef;
import org.freedesktop.dbus.annotations.DBusInterfaceName;
import org.freedesktop.dbus.annotations.DBusMemberName;
import org.freedesktop.dbus.annotations.DBusProperties;
import org.freedesktop.dbus.annotations.DBusProperty;
import org.freedesktop.dbus.connections.AbstractConnection;
import org.freedesktop.dbus.exceptions.DBusException;
import org.freedesktop.dbus.exceptions.DBusExecutionException;
Expand All @@ -49,11 +54,18 @@ public ExportedObject(DBusInterface _object, boolean _weakreferences) throws DBu
}
introspectiondata = "";
methods = getExportedMethods(_object.getClass());
introspectiondata +=
" <interface name=\"org.freedesktop.DBus.Introspectable\">\n" + " <method name=\"Introspect\">\n"
+ " <arg type=\"s\" direction=\"out\"/>\n" + " </method>\n" + " </interface>\n";
introspectiondata += " <interface name=\"org.freedesktop.DBus.Peer\">\n" + " <method name=\"Ping\">\n"
+ " </method>\n" + " </interface>\n";
introspectiondata += " <interface name=\"org.freedesktop.DBus.Introspectable\">\n" +
" <method name=\"Introspect\">\n" +
" <arg type=\"s\" direction=\"out\"/>\n" +
" </method>\n" +
" </interface>\n";
introspectiondata += " <interface name=\"org.freedesktop.DBus.Peer\">\n" +
" <method name=\"Ping\">\n" +
" </method>\n" +
" <method name=\"GetMachineId\">\n" +
" <arg type=\"s\" name=\"machine_uuid\" direction=\"out\"/>\n" +
" </method>\n" +
" </interface>\n";
}

private String getAnnotations(AnnotatedElement c) {
Expand Down Expand Up @@ -82,6 +94,49 @@ private String getAnnotations(AnnotatedElement c) {
return ans;
}

protected String getProperty(DBusProperty property) throws DBusException {
Class<?> propertyTypeClass = property.type();
String propertyTypeString;
if (TypeRef.class.isAssignableFrom(propertyTypeClass)) {
Type actualType = Arrays.stream(propertyTypeClass.getGenericInterfaces())
.filter(t -> t instanceof ParameterizedType)
.map(t -> (ParameterizedType) t)
.filter(t -> TypeRef.class.equals(t.getRawType()))
.map(t -> t.getActualTypeArguments()[0]) // TypeRef has one generic argument
.findFirst()
.orElseThrow(() ->
new DBusException("Could not read TypeRef type for property '" + property.name() + "'")
);
propertyTypeString = Marshalling.getDBusType(new Type[]{actualType});
} else if (List.class.equals(propertyTypeClass)) {
// default non generic list types
propertyTypeString = "av";
} else if (Map.class.equals(propertyTypeClass)) {
// default non generic map type
propertyTypeString = "a{vv}";
} else {
propertyTypeString = Marshalling.getDBusType(new Type[]{propertyTypeClass});
}

String access = property.access().getAccessName();
return "<property name=\"" + property.name() + "\" type=\"" + propertyTypeString + "\" access=\"" + access + "\" />";
}

protected String getProperties(Class<?> c) throws DBusException {
StringBuilder xml = new StringBuilder();
DBusProperties properties = c.getAnnotation(DBusProperties.class);
if (properties != null) {
for (DBusProperty property : properties.value()) {
xml.append(" ").append(getProperty(property)).append("\n");
}
}
DBusProperty property = c.getAnnotation(DBusProperty.class);
if (property != null) {
xml.append(" ").append(getProperty(property)).append("\n");
}
return xml.toString();
}

private Map<MethodTuple, Method> getExportedMethods(Class<?> c) throws DBusException {
if (DBusInterface.class.equals(c)) {
return new HashMap<MethodTuple, Method>();
Expand Down Expand Up @@ -165,6 +220,7 @@ private Map<MethodTuple, Method> getExportedMethods(Class<?> c) throws DBusExcep
m.put(new MethodTuple(name, ms), meth);
}
}
introspectiondata += getProperties(c);
for (Class<?> sig : c.getDeclaredClasses()) {
if (DBusSignal.class.isAssignableFrom(sig)) {
String name;
Expand Down

0 comments on commit 79d11bb

Please sign in to comment.