REST API: (Optionally) include hidden widgets in sitemap API response (#499)

Also-by: Danny Baumann <dannybaumann@web.de>
Signed-off-by: Kai Kreuzer <kai@openhab.org>
This commit is contained in:
Kai Kreuzer 2019-01-31 16:46:25 +01:00 committed by Markus Rathgeb
parent 0d1828f819
commit 9f27727e09
8 changed files with 43 additions and 159 deletions

View File

@ -24,6 +24,12 @@
<artifactId>org.openhab.core.ui</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.openhab.core.bundles</groupId>
<artifactId>org.openhab.core.test</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.openhab.core.bom</groupId>
<artifactId>org.openhab.core.bom.compile-model</artifactId>

View File

@ -237,11 +237,13 @@ public class SitemapResource implements RESTResource, SitemapSubscriptionCallbac
public Response getSitemapData(@Context HttpHeaders headers,
@HeaderParam(HttpHeaders.ACCEPT_LANGUAGE) @ApiParam(value = "language") String language,
@PathParam("sitemapname") @ApiParam(value = "sitemap name") String sitemapname,
@QueryParam("type") String type, @QueryParam("jsoncallback") @DefaultValue("callback") String callback) {
@QueryParam("type") String type, @QueryParam("jsoncallback") @DefaultValue("callback") String callback,
@QueryParam("includeHidden") @ApiParam(value = "include hidden widgets", required = false) boolean includeHiddenWidgets) {
final Locale locale = localeService.getLocale(language);
logger.debug("Received HTTP GET request from IP {} at '{}' for media type '{}'.", request.getRemoteAddr(),
uriInfo.getPath(), type);
Object responseObject = getSitemapBean(sitemapname, uriInfo.getBaseUriBuilder().build(), locale);
Object responseObject = getSitemapBean(sitemapname, uriInfo.getBaseUriBuilder().build(), locale,
includeHiddenWidgets);
return Response.ok(responseObject).build();
}
@ -256,7 +258,8 @@ public class SitemapResource implements RESTResource, SitemapSubscriptionCallbac
@HeaderParam(HttpHeaders.ACCEPT_LANGUAGE) @ApiParam(value = "language") String language,
@PathParam("sitemapname") @ApiParam(value = "sitemap name") String sitemapname,
@PathParam("pageid") @ApiParam(value = "page id") String pageId,
@QueryParam("subscriptionid") @ApiParam(value = "subscriptionid", required = false) String subscriptionId) {
@QueryParam("subscriptionid") @ApiParam(value = "subscriptionid", required = false) String subscriptionId,
@QueryParam("includeHidden") @ApiParam(value = "include hidden widgets", required = false) boolean includeHiddenWidgets) {
final Locale locale = localeService.getLocale(language);
logger.debug("Received HTTP GET request from IP {} at '{}'", request.getRemoteAddr(), uriInfo.getPath());
@ -277,7 +280,8 @@ public class SitemapResource implements RESTResource, SitemapSubscriptionCallbac
// we notice this information in the response object.
timeout = blockUnlessChangeOccurs(sitemapname, pageId);
}
PageDTO responseObject = getPageBean(sitemapname, pageId, uriInfo.getBaseUriBuilder().build(), locale, timeout);
PageDTO responseObject = getPageBean(sitemapname, pageId, uriInfo.getBaseUriBuilder().build(), locale, timeout,
includeHiddenWidgets);
return Response.ok(responseObject).build();
}
@ -345,31 +349,33 @@ public class SitemapResource implements RESTResource, SitemapSubscriptionCallbac
return eventOutput;
}
private PageDTO getPageBean(String sitemapName, String pageId, URI uri, Locale locale, boolean timeout) {
private PageDTO getPageBean(String sitemapName, String pageId, URI uri, Locale locale, boolean timeout,
boolean includeHidden) {
Sitemap sitemap = getSitemap(sitemapName);
if (sitemap != null) {
if (pageId.equals(sitemap.getName())) {
EList<Widget> children = itemUIRegistry.getChildren(sitemap);
return createPageBean(sitemapName, sitemap.getLabel(), sitemap.getIcon(), sitemap.getName(), children,
false, isLeaf(children), uri, locale, timeout);
false, isLeaf(children), uri, locale, timeout, includeHidden);
} else {
Widget pageWidget = itemUIRegistry.getWidget(sitemap, pageId);
if (pageWidget instanceof LinkableWidget) {
EList<Widget> children = itemUIRegistry.getChildren((LinkableWidget) pageWidget);
PageDTO pageBean = createPageBean(sitemapName, itemUIRegistry.getLabel(pageWidget),
itemUIRegistry.getCategory(pageWidget), pageId, children, false, isLeaf(children), uri,
locale, timeout);
locale, timeout, includeHidden);
EObject parentPage = pageWidget.eContainer();
while (parentPage instanceof Frame) {
parentPage = parentPage.eContainer();
}
if (parentPage instanceof Widget) {
String parentId = itemUIRegistry.getWidgetId((Widget) parentPage);
pageBean.parent = getPageBean(sitemapName, parentId, uri, locale, timeout);
pageBean.parent = getPageBean(sitemapName, parentId, uri, locale, timeout, includeHidden);
pageBean.parent.widgets = null;
pageBean.parent.parent = null;
} else if (parentPage instanceof Sitemap) {
pageBean.parent = getPageBean(sitemapName, sitemap.getName(), uri, locale, timeout);
pageBean.parent = getPageBean(sitemapName, sitemap.getName(), uri, locale, timeout,
includeHidden);
pageBean.parent.widgets = null;
}
return pageBean;
@ -421,10 +427,10 @@ public class SitemapResource implements RESTResource, SitemapSubscriptionCallbac
return beans;
}
public SitemapDTO getSitemapBean(String sitemapname, URI uri, Locale locale) {
private SitemapDTO getSitemapBean(String sitemapname, URI uri, Locale locale, boolean includeHiddenWidgets) {
Sitemap sitemap = getSitemap(sitemapname);
if (sitemap != null) {
return createSitemapBean(sitemapname, sitemap, uri, locale);
return createSitemapBean(sitemapname, sitemap, uri, locale, includeHiddenWidgets);
} else {
logger.info("Received HTTP GET request at '{}' for the unknown sitemap '{}'.", uriInfo.getPath(),
sitemapname);
@ -432,7 +438,8 @@ public class SitemapResource implements RESTResource, SitemapSubscriptionCallbac
}
}
private SitemapDTO createSitemapBean(String sitemapName, Sitemap sitemap, URI uri, Locale locale) {
private SitemapDTO createSitemapBean(String sitemapName, Sitemap sitemap, URI uri, Locale locale,
boolean includeHiddenWidgets) {
SitemapDTO bean = new SitemapDTO();
bean.name = sitemapName;
@ -441,12 +448,12 @@ public class SitemapResource implements RESTResource, SitemapSubscriptionCallbac
bean.link = UriBuilder.fromUri(uri).path(SitemapResource.PATH_SITEMAPS).path(bean.name).build().toASCIIString();
bean.homepage = createPageBean(sitemap.getName(), sitemap.getLabel(), sitemap.getIcon(), sitemap.getName(),
itemUIRegistry.getChildren(sitemap), true, false, uri, locale, false);
itemUIRegistry.getChildren(sitemap), true, false, uri, locale, false, includeHiddenWidgets);
return bean;
}
private PageDTO createPageBean(String sitemapName, String title, String icon, String pageId, EList<Widget> children,
boolean drillDown, boolean isLeaf, URI uri, Locale locale, boolean timeout) {
boolean drillDown, boolean isLeaf, URI uri, Locale locale, boolean timeout, boolean includeHiddenWidgets) {
PageDTO bean = new PageDTO();
bean.timeout = timeout;
bean.id = pageId;
@ -457,7 +464,8 @@ public class SitemapResource implements RESTResource, SitemapSubscriptionCallbac
if (children != null) {
for (Widget widget : children) {
String widgetId = itemUIRegistry.getWidgetId(widget);
WidgetDTO subWidget = createWidgetBean(sitemapName, widget, drillDown, uri, widgetId, locale);
WidgetDTO subWidget = createWidgetBean(sitemapName, widget, drillDown, uri, widgetId, locale,
includeHiddenWidgets);
if (subWidget != null) {
bean.widgets.add(subWidget);
}
@ -469,9 +477,9 @@ public class SitemapResource implements RESTResource, SitemapSubscriptionCallbac
}
private WidgetDTO createWidgetBean(String sitemapName, Widget widget, boolean drillDown, URI uri, String widgetId,
Locale locale) {
Locale locale, boolean evenIfHidden) {
// Test visibility
if (!itemUIRegistry.getVisiblity(widget)) {
if (!evenIfHidden && !itemUIRegistry.getVisiblity(widget)) {
return null;
}
@ -500,13 +508,15 @@ public class SitemapResource implements RESTResource, SitemapSubscriptionCallbac
bean.valuecolor = itemUIRegistry.getValueColor(widget);
bean.label = itemUIRegistry.getLabel(widget);
bean.type = widget.eClass().getName();
bean.visibility = itemUIRegistry.getVisiblity(widget);
if (widget instanceof LinkableWidget) {
LinkableWidget linkableWidget = (LinkableWidget) widget;
EList<Widget> children = itemUIRegistry.getChildren(linkableWidget);
if (widget instanceof Frame) {
for (Widget child : children) {
String wID = itemUIRegistry.getWidgetId(child);
WidgetDTO subWidget = createWidgetBean(sitemapName, child, drillDown, uri, wID, locale);
WidgetDTO subWidget = createWidgetBean(sitemapName, child, drillDown, uri, wID, locale,
evenIfHidden);
if (subWidget != null) {
bean.widgets.add(subWidget);
}
@ -515,7 +525,7 @@ public class SitemapResource implements RESTResource, SitemapSubscriptionCallbac
String pageName = itemUIRegistry.getWidgetId(linkableWidget);
bean.linkedPage = createPageBean(sitemapName, itemUIRegistry.getLabel(widget),
itemUIRegistry.getCategory(widget), pageName, drillDown ? children : null, drillDown,
isLeaf(children), uri, locale, false);
isLeaf(children), uri, locale, false, evenIfHidden);
}
}
if (widget instanceof Switch) {
@ -830,4 +840,4 @@ public class SitemapResource implements RESTResource, SitemapSubscriptionCallbac
return itemUIRegistry != null && subscriptions != null && localeService != null;
}
}
}

View File

@ -30,6 +30,7 @@ public class WidgetDTO {
public String widgetId;
public String type;
public String name;
public boolean visibility;
public String label;
public String icon;

View File

@ -173,7 +173,7 @@ public class SitemapResourceTest extends JavaTest {
// non-null is sufficient here.
when(headers.getRequestHeader(HTTP_HEADER_X_ATMOSPHERE_TRANSPORT)).thenReturn(Collections.emptyList());
Response response = sitemapResource.getPageData(headers, null, SITEMAP_MODEL_NAME, SITEMAP_NAME, null);
Response response = sitemapResource.getPageData(headers, null, SITEMAP_MODEL_NAME, SITEMAP_NAME, null, false);
PageDTO pageDTO = (PageDTO) response.getEntity();
assertThat(pageDTO.timeout, is(false)); // assert that the item state change did trigger the blocking method to
@ -194,7 +194,7 @@ public class SitemapResourceTest extends JavaTest {
// non-null is sufficient here.
when(headers.getRequestHeader(HTTP_HEADER_X_ATMOSPHERE_TRANSPORT)).thenReturn(Collections.emptyList());
Response response = sitemapResource.getPageData(headers, null, SITEMAP_MODEL_NAME, SITEMAP_NAME, null);
Response response = sitemapResource.getPageData(headers, null, SITEMAP_MODEL_NAME, SITEMAP_NAME, null, false);
PageDTO pageDTO = (PageDTO) response.getEntity();
assertThat(pageDTO.timeout, is(false)); // assert that the item state change did trigger the blocking method to
@ -215,7 +215,7 @@ public class SitemapResourceTest extends JavaTest {
// non-null is sufficient here.
when(headers.getRequestHeader(HTTP_HEADER_X_ATMOSPHERE_TRANSPORT)).thenReturn(Collections.emptyList());
Response response = sitemapResource.getPageData(headers, null, SITEMAP_MODEL_NAME, SITEMAP_NAME, null);
Response response = sitemapResource.getPageData(headers, null, SITEMAP_MODEL_NAME, SITEMAP_NAME, null, false);
PageDTO pageDTO = (PageDTO) response.getEntity();
assertThat(pageDTO.timeout, is(false)); // assert that the item state change did trigger the blocking method to
@ -236,7 +236,7 @@ public class SitemapResourceTest extends JavaTest {
// non-null is sufficient here.
when(headers.getRequestHeader(HTTP_HEADER_X_ATMOSPHERE_TRANSPORT)).thenReturn(Collections.emptyList());
Response response = sitemapResource.getPageData(headers, null, SITEMAP_MODEL_NAME, SITEMAP_NAME, null);
Response response = sitemapResource.getPageData(headers, null, SITEMAP_MODEL_NAME, SITEMAP_NAME, null, false);
PageDTO pageDTO = (PageDTO) response.getEntity();
assertThat(pageDTO.timeout, is(false)); // assert that the item state change did trigger the blocking method to
@ -251,7 +251,7 @@ public class SitemapResourceTest extends JavaTest {
// Disable long polling
when(headers.getRequestHeader(HTTP_HEADER_X_ATMOSPHERE_TRANSPORT)).thenReturn(null);
Response response = sitemapResource.getPageData(headers, null, SITEMAP_MODEL_NAME, SITEMAP_NAME, null);
Response response = sitemapResource.getPageData(headers, null, SITEMAP_MODEL_NAME, SITEMAP_NAME, null, false);
PageDTO pageDTO = (PageDTO) response.getEntity();
assertThat(pageDTO.id, is(SITEMAP_NAME));

View File

@ -24,7 +24,7 @@ import java.util.List;
*/
public class RootBean {
public final String version = "1";
public final String version = "2";
public final List<Links> links = new ArrayList<Links>();

View File

@ -1,19 +0,0 @@
This content is produced and maintained by the Eclipse SmartHome project.
* Project home: https://eclipse.org/smarthome/
== 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/eclipse/smarthome
== Copyright Holders
See the NOTICE file distributed with the source code at
https://github.com/eclipse/smarthome/blob/master/NOTICE
for detailed information regarding copyright ownership.

View File

@ -1,45 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<launchConfiguration type="org.eclipse.pde.ui.JunitLaunchConfig">
<booleanAttribute key="append.args" value="true"/>
<stringAttribute key="application" value="org.eclipse.pde.junit.runtime.coretestapplication"/>
<booleanAttribute key="askclear" value="false"/>
<booleanAttribute key="automaticAdd" value="false"/>
<booleanAttribute key="automaticValidate" value="true"/>
<stringAttribute key="bootstrap" value=""/>
<stringAttribute key="checked" value="[NONE]"/>
<booleanAttribute key="clearConfig" value="true"/>
<booleanAttribute key="clearws" value="true"/>
<booleanAttribute key="clearwslog" value="false"/>
<stringAttribute key="configLocation" value="${workspace_loc}/.metadata/.plugins/org.eclipse.pde.core/pde-junit"/>
<booleanAttribute key="default" value="false"/>
<booleanAttribute key="includeOptional" value="false"/>
<stringAttribute key="location" value="${workspace_loc}/../junit-workspace"/>
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
<listEntry value="/org.eclipse.smarthome.io.rest.sitemap.test"/>
</listAttribute>
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
<listEntry value="4"/>
</listAttribute>
<stringAttribute key="org.eclipse.jdt.junit.CONTAINER" value="=org.eclipse.smarthome.io.rest.sitemap.test"/>
<booleanAttribute key="org.eclipse.jdt.junit.KEEPRUNNING_ATTR" value="false"/>
<stringAttribute key="org.eclipse.jdt.junit.TESTNAME" value=""/>
<stringAttribute key="org.eclipse.jdt.junit.TEST_KIND" value="org.eclipse.jdt.junit.loader.junit4"/>
<booleanAttribute key="org.eclipse.jdt.launching.ATTR_USE_START_ON_FIRST_THREAD" value="true"/>
<stringAttribute key="org.eclipse.jdt.launching.JRE_CONTAINER" value="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value=""/>
<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-os ${target.os} -ws ${target.ws} -arch ${target.arch} -nl ${target.nl} -consoleLog"/>
<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="org.eclipse.smarthome.io.rest.sitemap.test"/>
<stringAttribute key="org.eclipse.jdt.launching.SOURCE_PATH_PROVIDER" value="org.eclipse.pde.ui.workbenchClasspathProvider"/>
<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-ea"/>
<stringAttribute key="pde.version" value="3.3"/>
<stringAttribute key="product" value="org.eclipse.equinox.p2.director.app.product"/>
<booleanAttribute key="run_in_ui_thread" value="true"/>
<stringAttribute key="selected_target_plugins" value="ch.qos.logback.classic@default:default,ch.qos.logback.core@default:default,ch.qos.logback.slf4j@default:false,com.eclipsesource.jaxrs.jersey-min@default:default,com.eclipsesource.jaxrs.swagger-all@default:default,com.google.gson@default:default,com.google.guava@default:default,com.google.inject@default:default,com.jayway.jsonpath.json-path@default:default,javax.activation@default:default,javax.inject@default:default,javax.measure.unit-api@default:default,javax.servlet@default:default,javax.transaction@default:false,javax.xml@default:default,net.bytebuddy.byte-buddy-agent@default:default,net.bytebuddy.byte-buddy@default:default,net.minidev.json-smart@default:default,org.antlr.runtime@default:default,org.apache.ant@default:default,org.apache.commons.cli@default:default,org.apache.commons.collections@default:default,org.apache.commons.io@default:default,org.apache.commons.lang@default:default,org.apache.commons.logging@default:default,org.apache.commons.net@default:default,org.apache.felix.gogo.command@default:default,org.apache.felix.gogo.runtime@default:default,org.codehaus.groovy@default:default,org.eclipse.core.contenttype@default:default,org.eclipse.core.jobs@default:default,org.eclipse.core.runtime@default:true,org.eclipse.emf.common@default:default,org.eclipse.emf.ecore.xmi@default:default,org.eclipse.emf.ecore@default:default,org.eclipse.emf.mwe.core@default:default,org.eclipse.emf.mwe2.runtime@default:default,org.eclipse.equinox.app@default:default,org.eclipse.equinox.common@2:true,org.eclipse.equinox.preferences@default:default,org.eclipse.equinox.region@default:false,org.eclipse.equinox.registry@default:default,org.eclipse.equinox.transforms.hook@default:false,org.eclipse.equinox.weaving.hook@default:false,org.eclipse.jdt.annotation@default:default,org.eclipse.jetty.client@default:default,org.eclipse.jetty.http@default:default,org.eclipse.jetty.io@default:default,org.eclipse.jetty.proxy@default:default,org.eclipse.jetty.security@default:default,org.eclipse.jetty.server@default:default,org.eclipse.jetty.servlet@default:default,org.eclipse.jetty.util@default:default,org.eclipse.lsp4j.jsonrpc@default:default,org.eclipse.lsp4j@default:default,org.eclipse.osgi.services@default:default,org.eclipse.osgi.util@default:default,org.eclipse.osgi@-1:true,org.eclipse.smarthome.model.core@default:default,org.eclipse.smarthome.model.item@default:default,org.eclipse.smarthome.model.sitemap@default:default,org.eclipse.xtend.lib.macro@default:default,org.eclipse.xtend.lib@default:default,org.eclipse.xtend@default:default,org.eclipse.xtext.common.types@default:default,org.eclipse.xtext.util@default:default,org.eclipse.xtext.xbase.lib@default:default,org.eclipse.xtext.xbase@default:default,org.eclipse.xtext@default:default,org.hamcrest.core@default:default,org.hamcrest.integration@default:default,org.hamcrest.library@default:default,org.hamcrest.text@default:default,org.hamcrest@default:default,org.junit@default:default,org.jupnp@default:default,org.mockito.mockito-core@default:default,org.objectweb.asm@default:default,org.objenesis@default:default,org.slf4j.api@default:default,org.slf4j.log4j@default:default,tec.uom.lib.uom-lib-common@default:default,tec.uom.se@default:default"/>
<stringAttribute key="selected_workspace_plugins" value="org.eclipse.smarthome.config.core@default:default,org.eclipse.smarthome.config.discovery@default:default,org.eclipse.smarthome.config.xml@default:default,org.eclipse.smarthome.core.persistence@default:default,org.eclipse.smarthome.core.thing@default:default,org.eclipse.smarthome.core.transform@default:default,org.eclipse.smarthome.core@default:default,org.eclipse.smarthome.io.console@default:default,org.eclipse.smarthome.io.http@default:default,org.eclipse.smarthome.io.rest.core@default:default,org.eclipse.smarthome.io.rest.sitemap.test@default:false,org.eclipse.smarthome.io.rest.sitemap@default:default,org.eclipse.smarthome.io.rest@default:default,org.eclipse.smarthome.test@default:default,org.eclipse.smarthome.ui@default:default"/>
<booleanAttribute key="show_selected_only" value="false"/>
<booleanAttribute key="tracing" value="false"/>
<booleanAttribute key="useCustomFeatures" value="false"/>
<booleanAttribute key="useDefaultConfig" value="true"/>
<booleanAttribute key="useDefaultConfigArea" value="false"/>
<booleanAttribute key="useProduct" value="false"/>
</launchConfiguration>

View File

@ -1,69 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.openhab.core.itests</groupId>
<artifactId>org.openhab.core.reactor.itests</artifactId>
<version>2.5.0-SNAPSHOT</version>
</parent>
<artifactId>org.openhab.core.io.rest.sitemap.tests</artifactId>
<packaging>eclipse-test-plugin</packaging>
<name>openHAB Core :: Integration Tests :: Sitemap REST Interface Tests</name>
<build>
<plugins>
<plugin>
<groupId>${tycho-groupid}</groupId>
<artifactId>target-platform-configuration</artifactId>
<configuration>
<environments combine.self="override"></environments>
<dependency-resolution>
<extraRequirements>
<requirement>
<type>eclipse-plugin</type>
<id>org.eclipse.equinox.ds</id>
<versionRange>0.0.0</versionRange>
</requirement>
<requirement>
<type>eclipse-plugin</type>
<id>org.eclipse.equinox.event</id>
<versionRange>0.0.0</versionRange>
</requirement>
</extraRequirements>
</dependency-resolution>
</configuration>
</plugin>
<plugin>
<groupId>${tycho-groupid}</groupId>
<artifactId>tycho-surefire-plugin</artifactId>
<configuration>
<bundleStartLevel>
<bundle>
<id>org.eclipse.equinox.ds</id>
<level>1</level>
<autoStart>true</autoStart>
</bundle>
<bundle>
<id>org.eclipse.equinox.event</id>
<level>4</level>
<autoStart>true</autoStart>
</bundle>
<bundle>
<id>org.eclipse.smarthome.core</id>
<level>4</level>
<autoStart>true</autoStart>
</bundle>
<bundle>
<id>org.eclipse.smarthome.config.core</id>
<level>4</level>
<autoStart>true</autoStart>
</bundle>
</bundleStartLevel>
</configuration>
</plugin>
</plugins>
</build>
</project>