Skip to content

Commit

Permalink
Thing actions: Process @ActionOutput for actions with single return…
Browse files Browse the repository at this point in the history
… value & Enforce proper annotations (#4430)

See discussion in openhab/openhab-addons#17504 (comment).

This adds processing of the ActionOutput annotation for Thing actions with a single return value, which allows providing a label for use in the UI.
The output name for those actions is "result", which is now the default value in the @ActionOutput annotation. If a binding overrides the default name, a warning is logged.

If a Thing action returns a Map<String, Object> but does not provide the @ActionOutputs annotation, a warning is logged.

Signed-off-by: Florian Hotze <dev@florianhotze.com>
  • Loading branch information
florian-h05 authored Oct 27, 2024
1 parent 922a206 commit 7f5fbbb
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
package org.openhab.core.automation.annotation;

import static java.lang.annotation.RetentionPolicy.RUNTIME;
import static org.openhab.core.automation.internal.module.handler.AnnotationActionHandler.MODULE_RESULT;

import java.lang.annotation.ElementType;
import java.lang.annotation.Repeatable;
Expand All @@ -39,7 +40,7 @@
*
* @return the name of the output parameter
*/
String name();
String name() default MODULE_RESULT;

/**
* Type of the output parameter
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
@NonNullByDefault
public class AnnotationActionHandler extends BaseActionModuleHandler {

private static final String MODULE_RESULT = "result";
public static final String MODULE_RESULT = "result";

private final Logger logger = LoggerFactory.getLogger(AnnotationActionHandler.class);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
*/
package org.openhab.core.automation.module.provider;

import static org.openhab.core.automation.internal.module.handler.AnnotationActionHandler.MODULE_RESULT;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
Expand Down Expand Up @@ -143,17 +145,36 @@ private List<Input> getInputsFromAction(Method method) {
return inputs;
}

private Output getOutputFromActionOutputAnnotation(ActionOutput ruleActionOutput, @Nullable String nameOverride) {
return new Output((nameOverride != null ? nameOverride : ruleActionOutput.name()), ruleActionOutput.type(),
ruleActionOutput.label(), ruleActionOutput.description(),
Arrays.stream(ruleActionOutput.tags()).collect(Collectors.toSet()), ruleActionOutput.reference(),
ruleActionOutput.defaultValue());
}

private List<Output> getOutputsFromAction(Method method) {
List<Output> outputs = new ArrayList<>();
// ActionOutputs annotation
if (method.isAnnotationPresent(ActionOutputs.class)) {
for (ActionOutput ruleActionOutput : method.getAnnotationsByType(ActionOutput.class)) {
Output output = new Output(ruleActionOutput.name(), ruleActionOutput.type(), ruleActionOutput.label(),
ruleActionOutput.description(),
Arrays.stream(ruleActionOutput.tags()).collect(Collectors.toSet()),
ruleActionOutput.reference(), ruleActionOutput.defaultValue());

outputs.add(output);
for (ActionOutput ruleActionOutput : method.getAnnotation(ActionOutputs.class).value()) {
outputs.add(getOutputFromActionOutputAnnotation(ruleActionOutput, null));
}
// no ActionOutputs annotation, but a Map<String, Object> return type
} else if (method.getAnnotatedReturnType().toString()
.equals("java.util.Map<java.lang.String, java.lang.Object>")) {
logger.warn(
"Method {}::{} returns a Map<String, Object> but is not annotated with ActionOutputs. This should be fixed in the binding.",
method.getDeclaringClass().getSimpleName(), method.getName());
return outputs;
// no ActionOutputs annotation and no Map<String, Object> return type, but a single ActionOutput annotation
} else if (method.isAnnotationPresent(ActionOutput.class)) {
ActionOutput ruleActionOutput = method.getAnnotation(ActionOutput.class);
if (!ruleActionOutput.name().equals(MODULE_RESULT)) {
logger.warn(
"Method {}::{} has a single output but does not use the default output name in the ActionOutput annotation. This should be fixed in the binding.",
method.getDeclaringClass().getSimpleName(), method.getName());
}
outputs.add(getOutputFromActionOutputAnnotation(ruleActionOutput, MODULE_RESULT));
}
return outputs;
}
Expand Down

0 comments on commit 7f5fbbb

Please sign in to comment.