Skip to content

Commit

Permalink
Configurable ItemChannelLinks
Browse files Browse the repository at this point in the history
This allows adding some configuration properties onto links, e.g. though

  Switch someItem {
      channel="a:b:c:channel" [
          foo="bar",
          answer=42,
          always=true
      ]
  }

or the REST API.

As a consequence, ItemChannelLinks now also can be updated through the REST API.

fixes eclipse-archived#583
Signed-off-by: Simon Kaufmann <simon.kfm@googlemail.com>
  • Loading branch information
Simon Kaufmann committed Sep 22, 2017
1 parent 8da1e67 commit 455b687
Show file tree
Hide file tree
Showing 18 changed files with 187 additions and 50 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
*/
package org.eclipse.smarthome.core.thing.link;

import org.eclipse.smarthome.config.core.Configuration;
import org.eclipse.smarthome.core.items.Item;
import org.eclipse.smarthome.core.thing.ChannelUID;

Expand All @@ -15,10 +16,12 @@
*
* @author Dennis Nobel - Initial contribution, Added getIDFor method
* @author Jochen Hiller - Bugfix 455434: added default constructor, object is now mutable
* @author Simon Kaufmann - added configuration
*/
public class ItemChannelLink extends AbstractLink {

private ChannelUID channelUID;
private final ChannelUID channelUID;
private final Configuration configuration;

/**
* Default constructor in package scope only. Will allow to instantiate this
Expand All @@ -27,16 +30,26 @@ public class ItemChannelLink extends AbstractLink {
ItemChannelLink() {
super();
this.channelUID = null;
this.configuration = new Configuration();
}

public ItemChannelLink(String itemName, ChannelUID channelUID) {
this(itemName, channelUID, new Configuration());
}

public ItemChannelLink(String itemName, ChannelUID channelUID, Configuration configuration) {
super(itemName);
this.channelUID = channelUID;
this.configuration = configuration;
}

@Override
public ChannelUID getLinkedUID() {
return this.channelUID;
}

public Configuration getConfiguration() {
return configuration;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -63,14 +63,6 @@ public Set<ChannelUID> getBoundChannels(String itemName) {
return channelUIDs;
}

/**
* Channels can not be updated, so this methods throws an {@link UnsupportedOperationException}.
*/
@Override
public ItemChannelLink update(ItemChannelLink element) {
throw new UnsupportedOperationException("Channels can not be updated.");
}

@Override
public Set<String> getLinkedItemNames(UID uid) {
final Set<String> linkedItems = new LinkedHashSet<>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
*/
package org.eclipse.smarthome.core.thing.link.dto;

import java.util.Map;

/**
* This is a data transfer object that is used to serialize links.
*
Expand All @@ -15,16 +17,18 @@
public class ItemChannelLinkDTO extends AbstractLinkDTO {

public String channelUID;
public Map<String, Object> configuration;

/**
* Default constructor for deserialization e.g. by Gson.
*/
protected ItemChannelLinkDTO() {
}

public ItemChannelLinkDTO(String itemName, String channelUID) {
public ItemChannelLinkDTO(String itemName, String channelUID, Map<String, Object> configuration) {
super(itemName);
this.channelUID = channelUID;
this.configuration = configuration;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,8 @@ private static String buildTopic(String topic, AbstractLink itemChannelLink) {
}

private static ItemChannelLinkDTO map(ItemChannelLink itemChannelLink) {
return new ItemChannelLinkDTO(itemChannelLink.getItemName(), itemChannelLink.getLinkedUID().toString());
return new ItemChannelLinkDTO(itemChannelLink.getItemName(), itemChannelLink.getLinkedUID().toString(),
itemChannelLink.getConfiguration().getProperties());
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,13 @@
import javax.ws.rs.core.Response.Status;
import javax.ws.rs.core.UriInfo;

import org.eclipse.smarthome.config.core.Configuration;
import org.eclipse.smarthome.core.auth.Role;
import org.eclipse.smarthome.core.thing.ChannelUID;
import org.eclipse.smarthome.core.thing.link.AbstractLink;
import org.eclipse.smarthome.core.thing.link.ItemChannelLink;
import org.eclipse.smarthome.core.thing.link.ItemChannelLinkRegistry;
import org.eclipse.smarthome.core.thing.link.ThingLinkManager;
import org.eclipse.smarthome.core.thing.link.dto.AbstractLinkDTO;
import org.eclipse.smarthome.core.thing.link.dto.ItemChannelLinkDTO;
import org.eclipse.smarthome.io.rest.JSONResponse;
import org.eclipse.smarthome.io.rest.RESTResource;
Expand Down Expand Up @@ -68,7 +68,7 @@ public class ItemChannelLinkResource implements RESTResource {
@ApiResponses(value = {
@ApiResponse(code = 200, message = "OK", response = ItemChannelLinkDTO.class, responseContainer = "Collection") })
public Response getAll() {
Stream<AbstractLinkDTO> linkStream = itemChannelLinkRegistry.getAll().stream().map(this::toBeans);
Stream<ItemChannelLinkDTO> linkStream = itemChannelLinkRegistry.getAll().stream().map(this::toBeans);
return Response.ok(new Stream2JSONInputStream(linkStream)).build();
}

Expand All @@ -85,10 +85,27 @@ public Response isAutomatic() {
@Path("/{itemName}/{channelUID}")
@ApiOperation(value = "Links item to a channel.")
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK"),
@ApiResponse(code = 400, message = "Item already linked to the channel.") })
@ApiResponse(code = 400, message = "Content does not match the path") })
public Response link(@PathParam("itemName") @ApiParam(value = "itemName") String itemName,
@PathParam("channelUID") @ApiParam(value = "channelUID") String channelUid) {
itemChannelLinkRegistry.add(new ItemChannelLink(itemName, new ChannelUID(channelUid)));
@PathParam("channelUID") @ApiParam(value = "channelUID") String channelUid,
@ApiParam(value = "link data", required = false) ItemChannelLinkDTO bean) {
ItemChannelLink link;
if (bean == null) {
link = new ItemChannelLink(itemName, new ChannelUID(channelUid), new Configuration());
} else {
if (bean.channelUID != null && !bean.channelUID.equals(channelUid)) {
return Response.status(Status.BAD_REQUEST).build();
}
if (bean.itemName != null && !bean.itemName.equals(itemName)) {
return Response.status(Status.BAD_REQUEST).build();
}
link = new ItemChannelLink(itemName, new ChannelUID(channelUid), new Configuration(bean.configuration));
}
if (itemChannelLinkRegistry.get(link.getUID()) == null) {
itemChannelLinkRegistry.add(link);
} else {
itemChannelLinkRegistry.update(link);
}
return Response.ok().build();
}

Expand Down Expand Up @@ -132,8 +149,9 @@ protected void unsetItemChannelLinkRegistry(ItemChannelLinkRegistry itemChannelL
this.itemChannelLinkRegistry = null;
}

private AbstractLinkDTO toBeans(ItemChannelLink link) {
return new ItemChannelLinkDTO(link.getItemName(), link.getLinkedUID().toString());
private ItemChannelLinkDTO toBeans(ItemChannelLink link) {
return new ItemChannelLinkDTO(link.getItemName(), link.getLinkedUID().toString(),
link.getConfiguration().getProperties());
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Bundle-SymbolicName: org.eclipse.smarthome.model.core;singleton:=true
Bundle-Vendor: Eclipse.org/SmartHome
Bundle-Version: 0.9.0.qualifier
Export-Package: org.eclipse.smarthome.model.core
Export-Package: org.eclipse.smarthome.model.core,
org.eclipse.smarthome.model.core.valueconverter
Import-Package:
com.google.common.base,
com.google.common.collect,
Expand All @@ -27,8 +28,11 @@ Import-Package:
org.eclipse.smarthome.core.service,
org.eclipse.smarthome.model.core,
org.eclipse.xtext.common.types.impl,
org.eclipse.xtext.conversion,
org.eclipse.xtext.nodemodel,
org.eclipse.xtext.resource,
org.eclipse.xtext.resource.impl,
org.eclipse.xtext.util,
org.osgi.framework,
org.osgi.service.component,
org.slf4j
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.smarthome.model.thing.valueconverter;
package org.eclipse.smarthome.model.core.valueconverter;

import java.math.BigDecimal;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ Import-Package:
org.apache.commons.lang,
org.apache.log4j,
org.eclipse.jdt.annotation;resolution:=optional,
org.eclipse.smarthome.config.core,
org.eclipse.smarthome.core.autoupdate,
org.eclipse.smarthome.core.common.registry,
org.eclipse.smarthome.core.items,
Expand All @@ -31,6 +32,7 @@ Import-Package:
org.eclipse.smarthome.core.library.types,
org.eclipse.smarthome.core.types,
org.eclipse.smarthome.model.core,
org.eclipse.smarthome.model.core.valueconverter,
org.eclipse.xtext.xbase.lib,
org.osgi.framework,
org.slf4j
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,26 @@ ModelItemType :
;

ModelBinding:
type=ID '=' configuration=STRING
type=ID '=' configuration=STRING
('['
properties+=ModelProperty? (',' properties+=ModelProperty)*
']')?
;

ModelProperty:
key=ID '=' value=ValueType
;

ValueType returns ecore::EJavaObject:
STRING | NUMBER | BOOLEAN
;

BOOLEAN returns ecore::EBoolean:
'true' | 'false'
;

NUMBER returns ecore::EBigDecimal:
ID ('.' ID )?
;

terminal ID : '^'?('a'..'z'|'A'..'Z'|'_'|'0'..'9') ('a'..'z'|'A'..'Z'|'_'|'-'|'0'..'9')*;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,21 @@ package
*/
org.eclipse.smarthome.model

import org.eclipse.xtext.linking.lazy.LazyURIEncoder
import com.google.inject.Binder
import com.google.inject.name.Names
import org.eclipse.smarthome.model.internal.valueconverter.ItemValueConverters
import org.eclipse.xtext.conversion.IValueConverterService
import org.eclipse.xtext.linking.lazy.LazyURIEncoder

/**
* Use this class to register components to be used at runtime / without the Equinox extension registry.
*/
class ItemsRuntimeModule extends org.eclipse.smarthome.model.AbstractItemsRuntimeModule {
class ItemsRuntimeModule extends AbstractItemsRuntimeModule {

override Class<? extends IValueConverterService> bindIValueConverterService() {
return ItemValueConverters
}

override void configureUseIndexFragmentsForLazyLinking(Binder binder) {
binder.bind(Boolean.TYPE).annotatedWith(Names.named(LazyURIEncoder.USE_INDEXED_FRAGMENTS_BINDING)).toInstance(
Boolean.FALSE)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/**
* Copyright (c) 2014-2017 by the respective copyright holders.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.smarthome.model.internal.valueconverter;

import org.eclipse.smarthome.model.core.valueconverter.ValueTypeToStringConverter;
import org.eclipse.xtext.common.services.DefaultTerminalConverters;
import org.eclipse.xtext.conversion.IValueConverter;
import org.eclipse.xtext.conversion.ValueConverter;

import com.google.inject.Inject;

/**
* Registers {@link IValueConverter}s for the items language.
*
* @author Simon Kaufmann - initial contribution and API.
*
*/
public class ItemValueConverters extends DefaultTerminalConverters {

@Inject
private ValueTypeToStringConverter valueTypeToStringConverter;

@ValueConverter(rule = "ValueType")
public IValueConverter<Object> ValueType() {
return valueTypeToStringConverter;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,15 @@
import java.util.concurrent.ConcurrentHashMap;

import org.apache.commons.lang.StringUtils;
import org.eclipse.smarthome.config.core.Configuration;
import org.eclipse.smarthome.core.autoupdate.AutoUpdateBindingConfigProvider;

/**
* <p>
* This class can parse information from the generic binding format and provides AutoUpdate binding information from it.
* If no binding configuration is provided <code>autoupdate</code> is evaluated to true. This means every received
* <code>Command</code> will update its corresponding <code>State</code> by default.
*
*
* <p>
* This class registers as a {@link AutoUpdateBindingConfigProvider} service as well.
*
Expand Down Expand Up @@ -60,8 +61,8 @@ public void validateItemType(String itemType, String bindingConfig) throws Bindi
}

@Override
public void processBindingConfiguration(String context, String itemType, String itemName, String bindingConfig)
throws BindingConfigParseException {
public void processBindingConfiguration(String context, String itemType, String itemName, String bindingConfig,
Configuration configuration) throws BindingConfigParseException {
Set<String> itemNames = contextMap.get(context);
if (itemNames == null) {
itemNames = new HashSet<String>();
Expand Down
Loading

0 comments on commit 455b687

Please sign in to comment.