mirror of
https://github.com/danieldemus/openhab-core.git
synced 2026-07-29 12:34:22 +02:00
[marketplace] Add add-on handler for block libraries (#2598)
Related to https://github.com/openhab/openhab-webui/pull/1225. This add-on handler supports installing block libraries in the UIComponentRegistry, `ui:blocks` namespace. It is very similar to the CommunityUIWidgetAddonHandler, as the format is the same, so are the features and implementation, the only differences being: - Supported content type: `application/vnd.openhab.uicomponent;type=blocks` (vs. `application/vnd.openhab.uicomponent;type=widget`) - Discourse category nb.: 76 (vs. 75) - Inferred Add-on type: "automation" (vs. "ui") Signed-off-by: Yannick Schaus <github@schaus.net>
This commit is contained in:
+121
@@ -0,0 +1,121 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2021 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.addon.marketplace.internal.community;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.text.SimpleDateFormat;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.core.addon.Addon;
|
||||
import org.openhab.core.addon.marketplace.MarketplaceAddonHandler;
|
||||
import org.openhab.core.addon.marketplace.MarketplaceHandlerException;
|
||||
import org.openhab.core.ui.components.RootUIComponent;
|
||||
import org.openhab.core.ui.components.UIComponentRegistry;
|
||||
import org.openhab.core.ui.components.UIComponentRegistryFactory;
|
||||
import org.osgi.service.component.annotations.Activate;
|
||||
import org.osgi.service.component.annotations.Component;
|
||||
import org.osgi.service.component.annotations.Reference;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
|
||||
|
||||
/**
|
||||
* A {@link MarketplaceAddonHandler} implementation, which handles block libraries as YAML files and installs
|
||||
* them by adding them to the {@link UIComponentRegistry} for the ui:blocks namespace.
|
||||
*
|
||||
* @author Yannick Schaus - Initial contribution and API
|
||||
*
|
||||
*/
|
||||
@Component(immediate = true)
|
||||
@NonNullByDefault
|
||||
public class CommunityBlockLibaryAddonHandler implements MarketplaceAddonHandler {
|
||||
private static final String YAML_DOWNLOAD_URL_PROPERTY = "yaml_download_url";
|
||||
private static final String YAML_CONTENT_PROPERTY = "yaml_content";
|
||||
private static final String BLOCKLIBRARIES_CONTENT_TYPE = "application/vnd.openhab.uicomponent;type=blocks";
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(CommunityBlockLibaryAddonHandler.class);
|
||||
ObjectMapper yamlMapper;
|
||||
|
||||
private UIComponentRegistry blocksRegistry;
|
||||
|
||||
@Activate
|
||||
public CommunityBlockLibaryAddonHandler(final @Reference UIComponentRegistryFactory uiComponentRegistryFactory) {
|
||||
this.blocksRegistry = uiComponentRegistryFactory.getRegistry("ui:blocks");
|
||||
this.yamlMapper = new ObjectMapper(new YAMLFactory());
|
||||
yamlMapper.findAndRegisterModules();
|
||||
this.yamlMapper.setDateFormat(new SimpleDateFormat("MMM d, yyyy, hh:mm:ss aa"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supports(String type, String contentType) {
|
||||
return "automation".equals(type) && BLOCKLIBRARIES_CONTENT_TYPE.equals(contentType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInstalled(String id) {
|
||||
return blocksRegistry.getAll().stream().anyMatch(w -> w.hasTag(id));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void install(Addon addon) throws MarketplaceHandlerException {
|
||||
try {
|
||||
String yamlDownloadUrl = (String) addon.getProperties().get(YAML_DOWNLOAD_URL_PROPERTY);
|
||||
String yamlContent = (String) addon.getProperties().get(YAML_CONTENT_PROPERTY);
|
||||
|
||||
if (yamlDownloadUrl != null) {
|
||||
addWidgetAsYAML(addon.getId(), getWidgetFromURL(yamlDownloadUrl));
|
||||
} else if (yamlContent != null) {
|
||||
addWidgetAsYAML(addon.getId(), yamlContent);
|
||||
} else {
|
||||
throw new IllegalArgumentException("Couldn't find the block library in the add-on entry");
|
||||
}
|
||||
} catch (IOException e) {
|
||||
logger.error("Block library from marketplace cannot be downloaded: {}", e.getMessage());
|
||||
throw new MarketplaceHandlerException("Widget cannot be downloaded.", e);
|
||||
} catch (Exception e) {
|
||||
logger.error("Block library from marketplace is invalid: {}", e.getMessage());
|
||||
throw new MarketplaceHandlerException("Widget is not valid.", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void uninstall(Addon addon) throws MarketplaceHandlerException {
|
||||
blocksRegistry.getAll().stream().filter(w -> w.hasTag(addon.getId())).forEach(w -> {
|
||||
blocksRegistry.remove(w.getUID());
|
||||
});
|
||||
}
|
||||
|
||||
private String getWidgetFromURL(String urlString) throws IOException {
|
||||
URL u = new URL(urlString);
|
||||
try (InputStream in = u.openStream()) {
|
||||
return new String(in.readAllBytes(), StandardCharsets.UTF_8);
|
||||
}
|
||||
}
|
||||
|
||||
private void addWidgetAsYAML(String id, String yaml) {
|
||||
try {
|
||||
RootUIComponent widget = yamlMapper.readValue(yaml, RootUIComponent.class);
|
||||
// add a tag with the add-on ID to be able to identify the block library in the registry
|
||||
widget.addTag(id);
|
||||
blocksRegistry.add(widget);
|
||||
} catch (IOException e) {
|
||||
logger.error("Unable to parse YAML: {}", e.getMessage());
|
||||
throw new IllegalArgumentException("Unable to parse YAML");
|
||||
}
|
||||
}
|
||||
}
|
||||
+6
@@ -75,6 +75,7 @@ public class CommunityMarketplaceAddonService implements AddonService {
|
||||
public static final String KAR_CONTENT_TYPE = "application/vnd.openhab.feature;type=karfile";
|
||||
public static final String RULETEMPLATES_CONTENT_TYPE = "application/vnd.openhab.ruletemplate";
|
||||
public static final String UIWIDGETS_CONTENT_TYPE = "application/vnd.openhab.uicomponent;type=widget";
|
||||
public static final String BLOCKLIBRARIES_CONTENT_TYPE = "application/vnd.openhab.uicomponent;type=blocks";
|
||||
|
||||
// constants for the configuration properties
|
||||
static final String CONFIG_URI = "system:marketplace";
|
||||
@@ -94,6 +95,7 @@ public class CommunityMarketplaceAddonService implements AddonService {
|
||||
private static final Integer BUNDLES_CATEGORY = 73;
|
||||
private static final Integer RULETEMPLATES_CATEGORY = 74;
|
||||
private static final Integer UIWIDGETS_CATEGORY = 75;
|
||||
private static final Integer BLOCKLIBRARIES_CATEGORY = 76;
|
||||
|
||||
private static final String PUBLISHED_TAG = "published";
|
||||
|
||||
@@ -281,6 +283,8 @@ public class CommunityMarketplaceAddonService implements AddonService {
|
||||
return TAG_ADDON_TYPE_MAP.get("automation");
|
||||
} else if (UIWIDGETS_CATEGORY.equals(category)) {
|
||||
return TAG_ADDON_TYPE_MAP.get("ui");
|
||||
} else if (BLOCKLIBRARIES_CATEGORY.equals(category)) {
|
||||
return TAG_ADDON_TYPE_MAP.get("automation");
|
||||
} else if (BUNDLES_CATEGORY.equals(category)) {
|
||||
// try to get it from tags if we have tags
|
||||
return tags.stream().map(TAG_ADDON_TYPE_MAP::get).filter(Objects::nonNull).findFirst().orElse(null);
|
||||
@@ -296,6 +300,8 @@ public class CommunityMarketplaceAddonService implements AddonService {
|
||||
return RULETEMPLATES_CONTENT_TYPE;
|
||||
} else if (UIWIDGETS_CATEGORY.equals(category)) {
|
||||
return UIWIDGETS_CONTENT_TYPE;
|
||||
} else if (BLOCKLIBRARIES_CATEGORY.equals(category)) {
|
||||
return BLOCKLIBRARIES_CONTENT_TYPE;
|
||||
} else if (BUNDLES_CATEGORY.equals(category)) {
|
||||
if (tags.contains("kar")) {
|
||||
return KAR_CONTENT_TYPE;
|
||||
|
||||
Reference in New Issue
Block a user