Skip to content
This repository has been archived by the owner on May 7, 2020. It is now read-only.

Separate ChannelGroupType infrastructure from ChannelType #6072

Merged
merged 10 commits into from
Aug 20, 2018

Conversation

htreu
Copy link
Contributor

@htreu htreu commented Aug 17, 2018

This splits a ChannelTypeGroupProvider, ChannelTypeGroupRegistry and i18n classes from the ChannelType infrastructure.

Fixes cyclic dependency reported in #6054.

Henning Treu added 2 commits August 17, 2018 13:59
Signed-off-by: Henning Treu <henning.treu@telekom.de>
Signed-off-by: Henning Treu <henning.treu@telekom.de>
*/
@NonNullByDefault
@Component(immediate = true, service = ChannelI18nUtil.class)
public class ChannelI18nUtilImpl implements ChannelI18nUtil {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This one strucks me weird. We have so far XXXI18nUtil classes, which are no DS components and are simply instantiated by passing a TranslationProvider.

Doing an interface here with an impl class, which is then registered as a component seems to fall out of this pattern.
Is this rather supposed to be a ChannelI18nLocalizationService (or even a ChannelDefinitionI18nLocalizationService) instead?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, the first idea was to just expose the implementation class as a service. I had an offline review and this was one of the comments. will change back.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm afraid, you didn't read all of my comment:

We have so far XXXI18nUtil classes, which are no DS components and are simply instantiated by passing a TranslationProvider.

You have now refactored the class by removing the interface, but it still is a DS component.

@kaikreuzer
Copy link
Contributor

@cweitkamp You are very much invited to review this PR as well as you have implemented major parts of the translation infrastructure!

Signed-off-by: Henning Treu <henning.treu@telekom.de>
Copy link
Contributor

@cweitkamp cweitkamp left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like this change. It is not only a solution for #6054, it is an improvement for the framework. Thanks for your work.

While we are introducing dedicated util classes for localization of the different types I am wondering why we do not add a util class for the ChannelGroupType in the same way. I have left a comment inside the code too. After that we can consider to move all methods from ThingTypeI18nUtil into the related util classes. Wdyt?

The rest looks pretty good. Only some minor remarks.

@@ -274,16 +274,16 @@ public String getBindingId() {
@SuppressWarnings("rawtypes")
ServiceReference ref = bundleContext.getServiceReference(ChannelTypeRegistry.class.getName());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have to get a ServiceReference for the ChannelGroupTypeRegistry here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

actually the whole method is unused. Removed.

}
return builder.build();
protected void unsetChannelI18nUtil(ChannelI18nUtil channelI18nUtil) {
this.channelI18nUtil = null;
}

private List<ChannelGroupDefinition> createLocalizedChannelGroupDefinitions(final Bundle bundle,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are introducing translation services / util classes for every single entity now thus this method could be factored out to its own service / util class too.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I only did the ChannelI18nUtil because the createLocalizedChannelDefinitions method is used in both ThingTypeI18nLoc... and ChannelGroupTypeI18nLoc....
I would like to keep further refactorings out of this PR and consolidate, move, clean up in a separate PR.

@@ -64,21 +52,21 @@ public ChannelType getChannelType(ChannelTypeUID channelTypeUID, Locale locale)

@Reference
public void setThingTypeI18nLocalizationService(
final ThingTypeI18nLocalizationService thingTypeI18nLocalizationService) {
this.thingTypeI18nLocalizationService = thingTypeI18nLocalizationService;
final ChannelTypeI18nLocalizationService thingTypeI18nLocalizationService) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please rename the method argument too.

}

public void unsetThingTypeI18nLocalizationService(
final ThingTypeI18nLocalizationService thingTypeI18nLocalizationService) {
this.thingTypeI18nLocalizationService = null;
final ChannelTypeI18nLocalizationService thingTypeI18nLocalizationService) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please rename the method argument too.

import java.util.Locale;

import org.eclipse.smarthome.config.xml.AbstractXmlBasedProvider;
import org.eclipse.smarthome.core.thing.UID;
import org.eclipse.smarthome.core.thing.i18n.ChannelGroupTypeI18nLocalizationService;
import org.eclipse.smarthome.core.thing.i18n.ThingTypeI18nLocalizationService;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This import is not needed anymore.

import java.util.Locale;

import org.eclipse.smarthome.config.xml.AbstractXmlBasedProvider;
import org.eclipse.smarthome.core.thing.UID;
import org.eclipse.smarthome.core.thing.i18n.ChannelTypeI18nLocalizationService;
import org.eclipse.smarthome.core.thing.i18n.ThingTypeI18nLocalizationService;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This import is not needed anymore.

@@ -25,9 +25,8 @@
import java.util.stream.Stream;

import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.smarthome.core.thing.i18n.ChannelTypeI18nLocalizationService;
import org.eclipse.smarthome.core.thing.i18n.ThingTypeI18nLocalizationService;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This import is not needed anymore.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you see this comment?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks, was overlooked first.

*/
@NonNullByDefault
@Component(immediate = true, service = ChannelI18nUtil.class)
public class ChannelI18nUtil {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we should rename this class to ChannelTypeI18nUtil?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Its currently localising a list of ChannelDefinitions which is not an ideal method signature imho. As said in the other comment I would like to (see a) clean up in another PR.

}

@Reference(cardinality = ReferenceCardinality.MULTIPLE, policy = ReferencePolicy.DYNAMIC)
protected void addChannelTypeProvider(ChannelGroupTypeProvider channelTypeProviders) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please rename the argument to channelTypeProviders.

this.channelGroupTypeProviders.add(channelTypeProviders);
}

protected void removeChannelTypeProvider(ChannelGroupTypeProvider channelTypeProviders) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See above.

…eUID

Signed-off-by: Henning Treu <henning.treu@telekom.de>
@htreu
Copy link
Contributor Author

htreu commented Aug 18, 2018

I did the cosmetic changes, thanks @cweitkamp for the review. As said in the comments - in case you are okay with it - I would like the clean up in a separate PR.

@maggu2810
Copy link
Contributor

Can't we remove the immediate activation?

@cweitkamp
Copy link
Contributor

@htreu Yes of course, I am okay with it. It was just a thought coming to my mind while reading through the code and I did not want to loose it.

Signed-off-by: Henning Treu <henning.treu@telekom.de>
@htreu
Copy link
Contributor Author

htreu commented Aug 20, 2018

@maggu2810 I did switch all ChannelType related services to delayed activation. The default setup runs on my machine, but to be honest I can not overlook the exact impact of this change.
@ALL: Please test & review.

…ete import

Signed-off-by: Henning Treu <henning.treu@telekom.de>
@maggu2810
Copy link
Contributor

maggu2810 commented Aug 20, 2018

Didn't there exist similar cicular references as before?

  • XmlChannelGroupTypeProvider 1..1 ChannelGroupTypeI18nLocalizationService
  • ChannelGroupTypeI18nLocalizationService 1..1 ChannelI18nUtil
  • ChannelI18nUtil 1..1 ChannelTypeRegistry
  • ChannelTypeRegistry 0..n ChannelTypeProvider

@kaikreuzer
Copy link
Contributor

I am still very much against a DS service ChannelI18nUtil - see #6072 (comment). This does not seem to be right.

@kaikreuzer
Copy link
Contributor

There exists a typo: Channell

@maggu2810 Where do you see "Channell"?

@maggu2810
Copy link
Contributor

@maggu2810 Where do you see "Channell"?

It need to take two more coffees 😉 (the lower "L" and the upper "i" confused me).

@kaikreuzer
Copy link
Contributor

Ok, better have some more cooofffffeee 🤣

Signed-off-by: Henning Treu <henning.treu@telekom.de>
@htreu
Copy link
Contributor Author

htreu commented Aug 20, 2018

@maggu2810 the cycle is broken apart because XmlChannelGroupTypeProvider is not a ChannelTypeProvider anymore. Its now a ChannelGroupTypeProvider.

Copy link
Contributor

@cweitkamp cweitkamp left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All my comments have been addressed. Thanks.

*
*/
@NonNullByDefault
class ChannelI18nUtil {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of defining it package private, wouldn't the proper way be to move it to an internal package?

return builder.build();
@Activate
protected void activate() {
channelI18nUtil = new ChannelI18nUtil(channelTypeI18nLocalizationService, channelTypeRegistry);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should also set it to null in a deactivate method.


@Activate
protected void activate() {
channelI18nUtil = new ChannelI18nUtil(channelTypeI18nLocalizationService, channelTypeRegistry);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should also set it to null in a deactivate method.

}

@Reference(cardinality = ReferenceCardinality.MULTIPLE, policy = ReferencePolicy.DYNAMIC)
protected void addChannelTypeProvider(ChannelGroupTypeProvider channelGroupTypeProvider) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

method should be called addChannelGroupTypeProvider

this.channelGroupTypeProviders.add(channelGroupTypeProvider);
}

protected void removeChannelTypeProvider(ChannelGroupTypeProvider channelGroupTypeProvider) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

method should be called removeChannelGroupTypeProvider

* The {@link ChannelGroupTypeRegistry} tracks all {@link ChannelGroupType}s provided by
* registered {@link ChannelGroupTypeProvider}s.
*
* @author Dennis Nobel - Initial contribution
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As this is a completely new class, better put your own name here.

*
* @see ChannelGroupTypeRegistry
*
* @author Dennis Nobel - Initial contribution
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As this is a completely new class, better put your own name here.

Henning Treu added 3 commits August 20, 2018 15:30
Signed-off-by: Henning Treu <henning.treu@telekom.de>
Signed-off-by: Henning Treu <henning.treu@telekom.de>
Signed-off-by: Henning Treu <henning.treu@telekom.de>
Copy link
Contributor

@kaikreuzer kaikreuzer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the updates, lgtm! Let's wait for Travis.

@kaikreuzer kaikreuzer merged commit 71f772f into eclipse-archived:master Aug 20, 2018
@kaikreuzer
Copy link
Contributor

Marked as "API Breaking" as I just found this in the openHAB build:

[ERROR] /scratch/jenkins/workspace/sandbox-openhab2-release/openhab2-addons/addons/binding/org.openhab.binding.nest.test/src/test/java/org/openhab/binding/nest/handler/NestThingHandlerOSGiTest.java:[195] 
[ERROR] 	.getChannelGroupType(channelGroupDefinition.getTypeUID());
[ERROR] 	 ^^^^^^^^^^^^^^^^^^^
[ERROR] The method getChannelGroupType(ChannelGroupTypeUID) is undefined for the type ChannelTypeRegistry
[ERROR] 1 problem (1 error)

Should not be too severe as hopefully not many people use the ChannelTypeRegistry directly.

@maggu2810
Copy link
Contributor

If it is already API breaking, why not removing the deprecated default methods from the ChannelTypeProvider?

    @Deprecated
    @Nullable
    default ChannelGroupType getChannelGroupType(ChannelGroupTypeUID channelGroupTypeUID, @Nullable Locale locale) {
        return null;
    }

    /**
     * @deprecated The {@link ChannelGroupTypeProvider} is now to be implemented/used instead.
     */
    @Deprecated
    @Nullable
    default Collection<ChannelGroupType> getChannelGroupTypes(@Nullable Locale locale) {
r

@kaikreuzer
Copy link
Contributor

Because ChannelTypeProvider is something that many bindings implement (and they are allowed to) - it is fair to give them a grace period to adapt to the new interface.

The registry is instead normally considered an internal service and not to be used by extensions (my finding above was merely a test that made use of it).

kaikreuzer pushed a commit that referenced this pull request Aug 24, 2018
…6109)

With #6072 the ChannelGroupType infrastructure was separated from ChannelType.
This contribution applies corresponding adaptions to the homematic binding.

Signed-off-by: Michael Reitler <michael.reitler@telekom.de>
@htreu htreu added this to the 0.10.0 milestone Oct 30, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants