From cc702266fee605a616d4af36a08edbcb1c9aa5ba Mon Sep 17 00:00:00 2001 From: Yannick Schaus Date: Fri, 17 Jan 2020 15:28:05 +0100 Subject: [PATCH] Refactor dashboard tiles into core (#1329) * Refactor dashboard tiles into core Move the tile concept from the dashboard UI to the org.openhab.core.ui bundle, and add a REST resource (/rest/ui/tiles) to retrieve the list of tiles i.e. registered UIs. Signed-off-by: Yannick Schaus --- bom/openhab-core/pom.xml | 6 + .../org.openhab.core.io.rest.ui/.classpath | 27 +++++ bundles/org.openhab.core.io.rest.ui/.project | 23 ++++ bundles/org.openhab.core.io.rest.ui/NOTICE | 14 +++ bundles/org.openhab.core.io.rest.ui/pom.xml | 30 +++++ .../org/openhab/core/io/rest/ui/TileDTO.java | 35 ++++++ .../core/io/rest/ui/internal/UIResource.java | 89 ++++++++++++++ .../core/ui/internal/tiles/TileService.java | 111 ++++++++++++++++++ .../core/ui/tiles/ExternalServiceTile.java | 97 +++++++++++++++ .../java/org/openhab/core/ui/tiles/Tile.java | 53 +++++++++ .../openhab/core/ui/tiles/TileProvider.java | 24 ++++ bundles/pom.xml | 1 + .../openhab-core/src/main/feature/feature.xml | 1 + 13 files changed, 511 insertions(+) create mode 100644 bundles/org.openhab.core.io.rest.ui/.classpath create mode 100644 bundles/org.openhab.core.io.rest.ui/.project create mode 100644 bundles/org.openhab.core.io.rest.ui/NOTICE create mode 100644 bundles/org.openhab.core.io.rest.ui/pom.xml create mode 100644 bundles/org.openhab.core.io.rest.ui/src/main/java/org/openhab/core/io/rest/ui/TileDTO.java create mode 100644 bundles/org.openhab.core.io.rest.ui/src/main/java/org/openhab/core/io/rest/ui/internal/UIResource.java create mode 100644 bundles/org.openhab.core.ui/src/main/java/org/openhab/core/ui/internal/tiles/TileService.java create mode 100644 bundles/org.openhab.core.ui/src/main/java/org/openhab/core/ui/tiles/ExternalServiceTile.java create mode 100644 bundles/org.openhab.core.ui/src/main/java/org/openhab/core/ui/tiles/Tile.java create mode 100644 bundles/org.openhab.core.ui/src/main/java/org/openhab/core/ui/tiles/TileProvider.java diff --git a/bom/openhab-core/pom.xml b/bom/openhab-core/pom.xml index 0fa7c7a00..01cac75cd 100644 --- a/bom/openhab-core/pom.xml +++ b/bom/openhab-core/pom.xml @@ -256,6 +256,12 @@ ${project.version} compile + + org.openhab.core.bundles + org.openhab.core.io.rest.ui + ${project.version} + compile + org.openhab.core.bundles org.openhab.core.io.rest.voice diff --git a/bundles/org.openhab.core.io.rest.ui/.classpath b/bundles/org.openhab.core.io.rest.ui/.classpath new file mode 100644 index 000000000..3721ade03 --- /dev/null +++ b/bundles/org.openhab.core.io.rest.ui/.classpath @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/bundles/org.openhab.core.io.rest.ui/.project b/bundles/org.openhab.core.io.rest.ui/.project new file mode 100644 index 000000000..b2decf844 --- /dev/null +++ b/bundles/org.openhab.core.io.rest.ui/.project @@ -0,0 +1,23 @@ + + + org.openhab.core.io.rest.ui + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.m2e.core.maven2Builder + + + + + + org.eclipse.jdt.core.javanature + org.eclipse.m2e.core.maven2Nature + + diff --git a/bundles/org.openhab.core.io.rest.ui/NOTICE b/bundles/org.openhab.core.io.rest.ui/NOTICE new file mode 100644 index 000000000..6c17d0d8a --- /dev/null +++ b/bundles/org.openhab.core.io.rest.ui/NOTICE @@ -0,0 +1,14 @@ +This content is produced and maintained by the openHAB project. + +* Project home: https://www.openhab.org + +== Declared Project Licenses + +This program and the accompanying materials are made available under the terms +of the Eclipse Public License 2.0 which is available at +https://www.eclipse.org/legal/epl-2.0/. + +== Source Code + +https://github.com/openhab/openhab-core + diff --git a/bundles/org.openhab.core.io.rest.ui/pom.xml b/bundles/org.openhab.core.io.rest.ui/pom.xml new file mode 100644 index 000000000..db4702202 --- /dev/null +++ b/bundles/org.openhab.core.io.rest.ui/pom.xml @@ -0,0 +1,30 @@ + + + + 4.0.0 + + + org.openhab.core.bundles + org.openhab.core.reactor.bundles + 3.0.0-SNAPSHOT + + + org.openhab.core.io.rest.ui + + openHAB Core :: Bundles :: UI REST Interface + + + + org.openhab.core.bundles + org.openhab.core.ui + ${project.version} + + + org.openhab.core.bundles + org.openhab.core.io.rest + ${project.version} + + + + diff --git a/bundles/org.openhab.core.io.rest.ui/src/main/java/org/openhab/core/io/rest/ui/TileDTO.java b/bundles/org.openhab.core.io.rest.ui/src/main/java/org/openhab/core/io/rest/ui/TileDTO.java new file mode 100644 index 000000000..d1912f8bd --- /dev/null +++ b/bundles/org.openhab.core.io.rest.ui/src/main/java/org/openhab/core/io/rest/ui/TileDTO.java @@ -0,0 +1,35 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.core.io.rest.ui; + +/** + * This is an data transfer object for a UI tile. + * + * @author Yannick Schaus - Initial contribution + */ +public class TileDTO { + + public String name; + public String url; + public String overlay; + public String imageUrl; + + public TileDTO(String name, String url, String overlay, String imageUrl) { + super(); + this.name = name; + this.url = url; + this.overlay = overlay; + this.imageUrl = imageUrl; + } + +} diff --git a/bundles/org.openhab.core.io.rest.ui/src/main/java/org/openhab/core/io/rest/ui/internal/UIResource.java b/bundles/org.openhab.core.io.rest.ui/src/main/java/org/openhab/core/io/rest/ui/internal/UIResource.java new file mode 100644 index 000000000..bf333a6eb --- /dev/null +++ b/bundles/org.openhab.core.io.rest.ui/src/main/java/org/openhab/core/io/rest/ui/internal/UIResource.java @@ -0,0 +1,89 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.core.io.rest.ui.internal; + +import java.util.stream.Stream; + +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.UriInfo; + +import org.openhab.core.io.rest.RESTResource; +import org.openhab.core.io.rest.Stream2JSONInputStream; +import org.openhab.core.io.rest.ui.TileDTO; +import org.openhab.core.ui.tiles.Tile; +import org.openhab.core.ui.tiles.TileProvider; +import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.Reference; +import org.osgi.service.component.annotations.ReferenceCardinality; +import org.osgi.service.component.annotations.ReferencePolicy; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; + +/** + * This class acts as a REST resource for the UI resources and is registered with the + * Jersey servlet. + * + * @author Yannick Schaus - Initial contribution + */ +@Path(UIResource.PATH_UI) +@Api(value = UIResource.PATH_UI) +@Component(service = { RESTResource.class, UIResource.class }) +public class UIResource implements RESTResource { + private final Logger logger = LoggerFactory.getLogger(UIResource.class); + + /** The URI path to this resource */ + public static final String PATH_UI = "ui"; + + @Context + private UriInfo uriInfo; + + private TileProvider tileProvider; + + @GET + @Path("/tiles") + @Produces({ MediaType.APPLICATION_JSON }) + @ApiOperation(value = "Get all registered UI tiles.") + @ApiResponses(value = { @ApiResponse(code = 200, message = "OK", response = Tile.class) }) + public Response getAll() { + Stream tiles = tileProvider.getTiles().map(this::toTileDTO); + return Response.ok(new Stream2JSONInputStream(tiles)).build(); + } + + @Override + public boolean isSatisfied() { + return tileProvider != null; + } + + @Reference(cardinality = ReferenceCardinality.OPTIONAL, policy = ReferencePolicy.DYNAMIC) + protected void setTileProvider(TileProvider tileProvider) { + this.tileProvider = tileProvider; + } + + protected void unsetTileProvider(TileProvider tileProvider) { + this.tileProvider = null; + } + + private TileDTO toTileDTO(Tile tile) { + return new TileDTO(tile.getName(), tile.getUrl(), tile.getOverlay(), tile.getImageUrl()); + } +} diff --git a/bundles/org.openhab.core.ui/src/main/java/org/openhab/core/ui/internal/tiles/TileService.java b/bundles/org.openhab.core.ui/src/main/java/org/openhab/core/ui/internal/tiles/TileService.java new file mode 100644 index 000000000..daab0b2ce --- /dev/null +++ b/bundles/org.openhab.core.ui/src/main/java/org/openhab/core/ui/internal/tiles/TileService.java @@ -0,0 +1,111 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.core.ui.internal.tiles; + +import java.util.Map; +import java.util.Set; +import java.util.concurrent.CopyOnWriteArraySet; +import java.util.stream.Stream; + +import org.openhab.core.ui.tiles.ExternalServiceTile; +import org.openhab.core.ui.tiles.Tile; +import org.openhab.core.ui.tiles.TileProvider; +import org.osgi.service.cm.ConfigurationAdmin; +import org.osgi.service.component.ComponentContext; +import org.osgi.service.component.annotations.Activate; +import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.Deactivate; +import org.osgi.service.component.annotations.Reference; +import org.osgi.service.component.annotations.ReferenceCardinality; +import org.osgi.service.component.annotations.ReferencePolicy; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * This component registers the UI tiles. + * + * @author Kai Kreuzer - Initial contribution + * @author Laurent Garnier - internationalization + * @author Hilbrand Bouwkamp - internationalization + * @author Yannick Schaus - refactor into tile service, remove dashboard components + */ +@Component(immediate = true, name = "org.openhab.core.ui.tiles") +public class TileService implements TileProvider { + + private static final Logger logger = LoggerFactory.getLogger(TileService.class); + + protected ConfigurationAdmin configurationAdmin; + + protected Set tiles = new CopyOnWriteArraySet<>(); + + private final static String LINK_NAME = "link-name"; + private final static String LINK_URL = "link-url"; + private final static String LINK_IMAGEURL = "link-imageurl"; + + @Activate + protected void activate(ComponentContext componentContext, Map properties) { + addTilesForExternalServices(properties); + } + + @Deactivate + protected void deactivate(ComponentContext componentContext) { + } + + @Reference + protected void setConfigurationAdmin(ConfigurationAdmin configurationAdmin) { + this.configurationAdmin = configurationAdmin; + } + + protected void unsetConfigurationAdmin(ConfigurationAdmin configurationAdmin) { + this.configurationAdmin = null; + } + + @Reference(cardinality = ReferenceCardinality.MULTIPLE, policy = ReferencePolicy.DYNAMIC) + protected void addTile(Tile tile) { + tiles.add(tile); + } + + protected void removeTile(Tile tile) { + tiles.remove(tile); + } + + @Override + public Stream getTiles() { + return tiles.stream(); + } + + private void addTilesForExternalServices(Map properties) { + for (String key : properties.keySet()) { + if (key.endsWith(LINK_NAME)) { + if (key.length() > LINK_NAME.length()) { + // get prefix from link name + String linkname = key.substring(0, key.length() - LINK_NAME.length()); + + String name = (String) properties.get(linkname + LINK_NAME); + String url = (String) properties.get(linkname + LINK_URL); + String imageUrl = (String) properties.get(linkname + LINK_IMAGEURL); + + Tile newTile = new ExternalServiceTile.TileBuilder().withName(name).withUrl(url) + .withImageUrl(imageUrl).build(); + + if (name != null && url != null && !name.isEmpty() && !url.isEmpty()) { + addTile(newTile); + logger.debug("Tile added: {}", newTile); + } else { + logger.warn("Ignore invalid tile '{}': {}", linkname, newTile); + } + } + } + } + } +} diff --git a/bundles/org.openhab.core.ui/src/main/java/org/openhab/core/ui/tiles/ExternalServiceTile.java b/bundles/org.openhab.core.ui/src/main/java/org/openhab/core/ui/tiles/ExternalServiceTile.java new file mode 100644 index 000000000..bcef666dc --- /dev/null +++ b/bundles/org.openhab.core.ui/src/main/java/org/openhab/core/ui/tiles/ExternalServiceTile.java @@ -0,0 +1,97 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.core.ui.tiles; + +/** + * The dashboard tile for external services. + * + * @author Pauli Anttila - Initial contribution + * @author Yannick Schaus - moved into core, remove references to dashboard + */ +public class ExternalServiceTile implements Tile { + private String name; + private String url; + private String overlay; + private String imageUrl; + + private ExternalServiceTile(TileBuilder builder) { + this.name = builder.name; + this.url = builder.url; + this.overlay = builder.overlay; + this.imageUrl = builder.imageUrl; + } + + @Override + public String getName() { + return name; + } + + @Override + public String getUrl() { + return url; + } + + @Override + public String getOverlay() { + return overlay; + } + + @Override + public String getImageUrl() { + return imageUrl; + } + + @Override + public String toString() { + final int MAXLEN = 100; + + String limitedImageUrl = imageUrl; + if (limitedImageUrl != null && limitedImageUrl.length() > MAXLEN) { + limitedImageUrl = imageUrl.substring(0, MAXLEN) + "..."; + } + + return "[name=" + name + ", url=" + url + ", overlay=" + overlay + ", imageUrl=" + limitedImageUrl + "]"; + } + + public static class TileBuilder { + + private String name; + private String url; + private String overlay; + private String imageUrl; + + public TileBuilder withName(String name) { + this.name = name; + return this; + } + + public TileBuilder withUrl(String url) { + this.url = url; + return this; + } + + public TileBuilder withOverlay(String overlay) { + this.overlay = overlay; + return this; + } + + public TileBuilder withImageUrl(String imageUrl) { + this.imageUrl = imageUrl; + return this; + } + + public ExternalServiceTile build() { + return new ExternalServiceTile(this); + } + } +} diff --git a/bundles/org.openhab.core.ui/src/main/java/org/openhab/core/ui/tiles/Tile.java b/bundles/org.openhab.core.ui/src/main/java/org/openhab/core/ui/tiles/Tile.java new file mode 100644 index 000000000..6a6a482da --- /dev/null +++ b/bundles/org.openhab.core.ui/src/main/java/org/openhab/core/ui/tiles/Tile.java @@ -0,0 +1,53 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.core.ui.tiles; + +/** + * A tile can be registered by an UI as a service in order to appear on the main openHAB UI. + * + * @author Kai Kreuzer - initial contribution + * @author Yannick Schaus - refactored into core, remove references to dashboard + * + */ +public interface Tile { + + /** + * The name that should appear on the tile + * + * @return name of the tile + */ + String getName(); + + /** + * The url to point to (if it is a local UI, it should be a relative path starting with "../") + * + * @return the url + */ + String getUrl(); + + /** + * The url to point to for the tile. + * (if it is a local UI, it should be a relative path starting with "../") + * + * @return the tile url + */ + String getImageUrl(); + + /** + * An HTML5 overlay icon to use for the tile, e.g. "html5", "android" or "apple". + * + * @return the overlay to use + */ + String getOverlay(); + +} diff --git a/bundles/org.openhab.core.ui/src/main/java/org/openhab/core/ui/tiles/TileProvider.java b/bundles/org.openhab.core.ui/src/main/java/org/openhab/core/ui/tiles/TileProvider.java new file mode 100644 index 000000000..fa9e2fb56 --- /dev/null +++ b/bundles/org.openhab.core.ui/src/main/java/org/openhab/core/ui/tiles/TileProvider.java @@ -0,0 +1,24 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.core.ui.tiles; + +import java.util.stream.Stream; + +/** + * Interface for a component providing UI tiles. + * + * @author Yannick Schaus - initial contribution + */ +public interface TileProvider { + public Stream getTiles(); +} diff --git a/bundles/pom.xml b/bundles/pom.xml index c0747c227..7d0831216 100644 --- a/bundles/pom.xml +++ b/bundles/pom.xml @@ -67,6 +67,7 @@ org.openhab.core.io.rest.optimize org.openhab.core.io.rest.sitemap org.openhab.core.io.rest.sse + org.openhab.core.io.rest.ui org.openhab.core.io.rest.voice org.openhab.core.io.transport.dbus org.openhab.core.io.transport.mdns diff --git a/features/karaf/openhab-core/src/main/feature/feature.xml b/features/karaf/openhab-core/src/main/feature/feature.xml index 824829f79..e5ec16588 100644 --- a/features/karaf/openhab-core/src/main/feature/feature.xml +++ b/features/karaf/openhab-core/src/main/feature/feature.xml @@ -415,6 +415,7 @@ openhab-core-model-item openhab-core-model-sitemap mvn:org.openhab.core.bundles/org.openhab.core.ui/${project.version} + mvn:org.openhab.core.bundles/org.openhab.core.io.rest.ui/${project.version}