openhab-core/bundles/org.openhab.core.automation
Markus Rathgeb 1ac2e8978b automation: remove specific handling for CompositeModuleHandlerFactory (#764)
The member variable "compositeFactory" that holds the
"CompositeModuleHandlerFactory" instance is set in the activation method
by calling the constructor of of "CompositeModuleHandlerFactory".
This reference is destroyed and unset in the deactivate method.

There exists DS managed multiple optional references to
"ModuleHandlerFactory".
The "add" logic does not touch the "compositeFactory" variable.
The "remove" logic checks if the given service reference is a
"CompositeModuleHandlerFactory" and unsets the "compositeFactory" member
variable.

If e.g. a module handler factory is injected that also implements the
CompositeModuleHandlerFactory the CompositeModuleHandlerFactory created
by the activate method is still be used. If that specific module handler
factory is removed again, the variable "compositeFactory" is unset and
there is NO CompositeModuleHandlerFactory present anymore.

There are two options:
* The instance created in the activate method should be used as long as
  no other one is injected.
* The instance created in the activate method should be used all the
  time.

The whole code base does not contain another specific implementation for
CompositeModuleHandlerFactory, so there is no (at least in openHAB Core)
change that a CompositeModuleHandlerFactory is injected.

So instead of adding a non deterministic usage of "some" composite
module handler factory (which will require a fix of the "set module
handler factory method" and some others), let's drop the buggy code in
the "remove module handler factory" and use the manually created
composite module handler factory all the time.

Signed-off-by: Markus Rathgeb <maggu2810@gmail.com>
2019-04-28 16:19:06 +02:00
..
src/main automation: remove specific handling for CompositeModuleHandlerFactory (#764) 2019-04-28 16:19:06 +02:00
.classpath update Maven project settings (Eclipse IDE) 2019-02-06 15:56:00 +01:00
.project mavenize openHAB and integrate mavenized ESH repository (#467) 2019-01-28 13:07:31 +01:00
NOTICE Updated NOTICE files to openHAB (#578) 2019-02-15 10:46:18 +01:00
pom.xml mavenize openHAB and integrate mavenized ESH repository (#467) 2019-01-28 13:07:31 +01:00
README.md mavenize openHAB and integrate mavenized ESH repository (#467) 2019-01-28 13:07:31 +01:00

Action modules via annotated classes

Action modules can be defined by writing classes and annotating their methods with special annotations. The framework offers two providers, namely AnnotatedActionModuleTypeProvider and AnnotatedThingActionModuleTypeProvider, which collect these annotated elements and dynamically create the according action modules.

Types of annotated classes

There are three different ways to offer action modules via annotations:

Service

If the goal is to provide an action which is independent of a specific ThingHandler and which should only exists as one single instance, it should be implemented as a service. This service has to implement the org.openhab.core.automation.AnnotatedActions interface. It can be configured like any other framework service via a ConfigDescription, however its category should be RuleActions.

Multi Service

This case is similar to the one above, except for that it can be instantiated and thus configured multiple times. The service also has to implement the org.openhab.core.automation.AnnotatedActions interface. It makes use of the multi service infrastructure of the framework and the specified "Service context" becomes the identifier for the specific configuration. Its category should also be RuleActions.

Thing

For actions that need access to the logic of a ThingHandler, one has to implement a service which implements the org.eclipse.smarthome.core.thing.binding.AnnotatedActionThingHandlerService interface. The ThingHandler has to override the Collection<Class> getServices() method from the BaseThingHandler and return the class of the aforementioned service. The framework takes care of registering and un-registering of that service.

Annotations

Service classes mentioned above should have the following annotations:

  • @ActionScope(name = "myScope"): This annotation has to be on the class and myScope defines the first part of the ModuleType UID, for example binding.myBindinName or twitter.
  • @RuleAction(label = "@text/myLabel", description = "myDescription text"): Each method that should be offered as an action has to have this annotation. The method name will be the second part of the ModuleType uid (after the scope, separated by a "."). There are more parameters available, basically all fields which are part of org.openhab.core.automation.type.ActionType. Translations are also possible if @text/id placeholders are used and the bundle providing the actions offers the corresponding files.
  • @ActionOutput(name = "output1", type = "java.lang.String"): This annotation (or multiple of it) has to be on the return type of the method and specifies under which name and type a result will be available. Usually the type should be the fully qualified Java type, but in the future it will be extented to support further types.
  • @ActionInput(name = "input1"): This annotation has to be before a parameter of the method to name the input for the module. If the annotation is omitted, the implicit name will be "pN", whereas "N" will be the position of the parameter, i.e. 0-n.

Method definition

Each annotated method inside of such a service will be turned into an Action ModuleType, i.e. one can have multiple module type definitions per service if multiple methods are annotated. In addition to the annotations the methods should have a proper name since it is used inside the ModuleType uid. The return type of a method should be Map<String, Object>, because the automation engine uses this mapping between all its modules, or void if it does not provide any outputs. However, there is one shortcut for simple dataypes like boolean, String, int, double, and float. Such return types will automatically be put into a map with the predefined keyword "result" for the following modules to process. Within the implementation of the method, only those output names which are specified as @ActionOutput annotations should be used, i.e. the resulting map should only contain those which also appear in an @ActionOutput annotation.

Examples

For examples, please see the package org.eclipse.smarthome.magic.binding.internal.automation.modules inside the org.eclipse.smarthome.magic bundle.