= Reference target plugin

Configuration Plugin to update a target filter for a Reference

== Example

Injecting a component based on a configuration Property.

[source,java]
----
@ObjectClassDefinition(...)
@interface Config {

	@AttributeDefinition(name = "Component-ID")
	String component_id(); // (1)

}
----

[source,java]
----
@Designate(ocd = Config.class /* (2) */, factory = true)
@Component(...)
@GenerateTargetsFromReferences("component") // (3)
public class MyOpenemsComponent extends AbstractOpenemsComponent implements OpenemsComponent {

    @Reference(target = "(id=${config.component_id})")  // (4)
    private OpenemsComponent component; // (5)

    ...

}
----

1. Simple Configuration Property to configure a component id for a Component.
2. Use correct Configuration class in annotation
3. Define for which attributes the target filter should be generated (in this example the name of the variable at point 5)
4. Define the target filter with your variable
5. Your variable of the injected component

== Migration

=== Don't use OpenemsComponent.updateReferenceFilter

[source,java]
----
OpenemsComponent.updateReferenceFilter(...)
----

Don't use this method in a activate or modified method to update a filter based on a configuration value.
Use the above mentioned way.

=== Use correct activate Method (e.g. Modbus-Component)

In most cases a modbus component gets injected so the following activate is used:

[source,java]
----
@Activate
private void activate(ComponentContext context, Config config) throws OpenemsException {
	if (super.activate(context, config.id(), config.alias(), config.enabled(), config.modbusUnitId(), this.cm,
			"Modbus", config.modbus_id())) {
		return;
	}
}

----

But this method

[source,java]
----
OpenemsComponent.updateReferenceFilter(...)
----

is called which we don't want.

Use the following activate:

[source,java]
----
@Activate
private void activate(ComponentContext context, Config config) throws OpenemsException {
    super.activate(context, config.id(), config.alias(), config.enabled(), config.modbusUnitId());
}
----
Add the target filter `target = "(&(id=${config.modbus_id})(enabled=true))"`
[source,java]
----
import static org.osgi.service.component.annotations.ReferenceCardinality.MANDATORY;
import static org.osgi.service.component.annotations.ReferencePolicy.STATIC;
import static org.osgi.service.component.annotations.ReferencePolicyOption.GREEDY;

public class MyOpenemsModbusComponent extends AbstractOpenemsModbusComponent implements OpenemsComponent {

    @Override
    @Reference(//
            policy = STATIC, policyOption = GREEDY, cardinality = MANDATORY, //
            target = "(&(id=${config.modbus_id})(enabled=true))" //
    )
    protected void setModbus(BridgeModbus modbus) {
        super.setModbus(modbus);
    }

    ...

}
----
Add the configuration annotation `@GenerateTargetsFromReferences("Modbus")`
[source,java]
----
import io.openems.common.referencetarget.GenerateTargetsFromReferences;

@GenerateTargetsFromReferences("Modbus")
public class MyOpenemsModbusComponent extends AbstractOpenemsModbusComponent implements OpenemsComponent {

    ...

}
----

=== After all these changes the following variables are not needed anymore and can be removed:

==== Remove `Modbus_target` from the configuration

Main:
[source,java]
----
@ObjectClassDefinition(...)
@interface Config {

	@AttributeDefinition(name = "Modbus target filter", description = "This is auto-generated by 'Modbus-ID'.")
	String Modbus_target() default "(enabled=true)";

}
----
Test:
[source,java]
----
public class MyConfig {

	...

	@Override
	public String Modbus_target() {
		return ConfigUtils.generateReferenceTargetFilter(this.id(), this.modbus_id());
	}
}
----

==== Remove the ConfigurationAdmin reference

Main:
[source,java]
----
@Reference
private ConfigurationAdmin cm;
----
For Tests remove `.addReference("cm", new DummyConfigurationAdmin())`
[source,java]
----
new ComponentTest(new MyModbusDeviceImpl()) //
	.addReference("cm", new DummyConfigurationAdmin()) //
----


https://github.com/OpenEMS/openems/tree/develop/io.openems.core.referencetarget[Source Code icon:github[]]