|
|
|
@ -57,6 +57,7 @@ import org.thingsboard.server.dao.service.Validator; |
|
|
|
import org.thingsboard.server.dao.service.validator.ResourceDataValidator; |
|
|
|
|
|
|
|
import java.nio.charset.StandardCharsets; |
|
|
|
import java.util.ArrayList; |
|
|
|
import java.util.Base64; |
|
|
|
import java.util.Collection; |
|
|
|
import java.util.Collections; |
|
|
|
@ -401,18 +402,33 @@ public class BaseResourceService extends AbstractCachedEntityService<ResourceInf |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public boolean updateResourcesUsage(Dashboard dashboard) { |
|
|
|
public boolean updateResourcesUsage(TenantId tenantId, Dashboard dashboard) { |
|
|
|
if (dashboard.getConfiguration() == null) { |
|
|
|
return false; |
|
|
|
} |
|
|
|
Map<String, String> links = getResourcesLinks(dashboard.getResources()); |
|
|
|
return updateResourcesUsage(dashboard.getTenantId(), dashboard.getConfiguration(), DASHBOARD_RESOURCES_MAPPING, links); |
|
|
|
return updateResourcesUsage(tenantId, List.of(dashboard.getConfiguration()), List.of(DASHBOARD_RESOURCES_MAPPING), links); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public boolean updateResourcesUsage(WidgetTypeDetails widgetTypeDetails) { |
|
|
|
public boolean updateResourcesUsage(TenantId tenantId, WidgetTypeDetails widgetTypeDetails) { |
|
|
|
Map<String, String> links = getResourcesLinks(widgetTypeDetails.getResources()); |
|
|
|
boolean updated = updateResourcesUsage(widgetTypeDetails.getTenantId(), widgetTypeDetails.getDescriptor(), WIDGET_RESOURCES_MAPPING, links); |
|
|
|
List<JsonNode> jsonNodes = new ArrayList<>(2); |
|
|
|
List<Map<String, String>> mappings = new ArrayList<>(2); |
|
|
|
|
|
|
|
if (widgetTypeDetails.getDescriptor() != null) { |
|
|
|
jsonNodes.add(widgetTypeDetails.getDescriptor()); |
|
|
|
mappings.add(WIDGET_RESOURCES_MAPPING); |
|
|
|
} |
|
|
|
|
|
|
|
JsonNode defaultConfig = widgetTypeDetails.getDefaultConfig(); |
|
|
|
if (defaultConfig != null) { |
|
|
|
updated |= updateResourcesUsage(widgetTypeDetails.getTenantId(), defaultConfig, WIDGET_DEFAULT_CONFIG_RESOURCES_MAPPING, links); |
|
|
|
jsonNodes.add(defaultConfig); |
|
|
|
mappings.add(WIDGET_DEFAULT_CONFIG_RESOURCES_MAPPING); |
|
|
|
} |
|
|
|
|
|
|
|
boolean updated = updateResourcesUsage(tenantId, jsonNodes, mappings, links); |
|
|
|
if (defaultConfig != null) { |
|
|
|
widgetTypeDetails.setDefaultConfig(defaultConfig); |
|
|
|
} |
|
|
|
return updated; |
|
|
|
@ -433,8 +449,9 @@ public class BaseResourceService extends AbstractCachedEntityService<ResourceInf |
|
|
|
return links; |
|
|
|
} |
|
|
|
|
|
|
|
private boolean updateResourcesUsage(TenantId tenantId, JsonNode jsonNode, Map<String, String> mapping, Map<String, String> links) { |
|
|
|
return processResources(jsonNode, mapping, value -> { |
|
|
|
private boolean updateResourcesUsage(TenantId tenantId, List<JsonNode> jsonNodes, List<Map<String, String>> mappings, Map<String, String> links) { |
|
|
|
log.trace("[{}] updateResourcesUsage (new links: {}) for {}", tenantId, links, jsonNodes); |
|
|
|
return processResources(jsonNodes, mappings, value -> { |
|
|
|
String link = getResourceLink(value); |
|
|
|
if (link != null) { |
|
|
|
String newLink = links.get(link); |
|
|
|
@ -462,23 +479,31 @@ public class BaseResourceService extends AbstractCachedEntityService<ResourceInf |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public Collection<TbResourceInfo> getUsedResources(Dashboard dashboard) { |
|
|
|
return getUsedResources(dashboard.getTenantId(), dashboard.getConfiguration(), DASHBOARD_RESOURCES_MAPPING).values(); |
|
|
|
public Collection<TbResourceInfo> getUsedResources(TenantId tenantId, Dashboard dashboard) { |
|
|
|
return getUsedResources(tenantId, List.of(dashboard.getConfiguration()), List.of(DASHBOARD_RESOURCES_MAPPING)).values(); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public Collection<TbResourceInfo> getUsedResources(WidgetTypeDetails widgetTypeDetails) { |
|
|
|
Map<TbResourceId, TbResourceInfo> resources = getUsedResources(widgetTypeDetails.getTenantId(), widgetTypeDetails.getDescriptor(), WIDGET_RESOURCES_MAPPING); |
|
|
|
public Collection<TbResourceInfo> getUsedResources(TenantId tenantId, WidgetTypeDetails widgetTypeDetails) { |
|
|
|
List<JsonNode> jsonNodes = new ArrayList<>(2); |
|
|
|
List<Map<String, String>> mappings = new ArrayList<>(2); |
|
|
|
|
|
|
|
jsonNodes.add(widgetTypeDetails.getDescriptor()); |
|
|
|
mappings.add(WIDGET_RESOURCES_MAPPING); |
|
|
|
|
|
|
|
JsonNode defaultConfig = widgetTypeDetails.getDefaultConfig(); |
|
|
|
if (defaultConfig != null) { |
|
|
|
resources.putAll(getUsedResources(widgetTypeDetails.getTenantId(), defaultConfig, WIDGET_DEFAULT_CONFIG_RESOURCES_MAPPING)); |
|
|
|
jsonNodes.add(defaultConfig); |
|
|
|
mappings.add(WIDGET_DEFAULT_CONFIG_RESOURCES_MAPPING); |
|
|
|
} |
|
|
|
return resources.values(); |
|
|
|
|
|
|
|
return getUsedResources(tenantId, jsonNodes, mappings).values(); |
|
|
|
} |
|
|
|
|
|
|
|
private Map<TbResourceId, TbResourceInfo> getUsedResources(TenantId tenantId, JsonNode jsonNode, Map<String, String> mapping) { |
|
|
|
private Map<TbResourceId, TbResourceInfo> getUsedResources(TenantId tenantId, List<JsonNode> jsonNodes, List<Map<String, String>> mappings) { |
|
|
|
Map<TbResourceId, TbResourceInfo> resources = new HashMap<>(); |
|
|
|
processResources(jsonNode, mapping, value -> { |
|
|
|
log.trace("[{}] getUsedResources for {}", tenantId, jsonNodes); |
|
|
|
processResources(jsonNodes, mappings, value -> { |
|
|
|
String link = getResourceLink(value); |
|
|
|
if (link == null) { |
|
|
|
return value; |
|
|
|
@ -517,32 +542,57 @@ public class BaseResourceService extends AbstractCachedEntityService<ResourceInf |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
private boolean processResources(JsonNode jsonNode, Map<String, String> mapping, UnaryOperator<String> processor) { |
|
|
|
private boolean processResources(List<JsonNode> jsonNodes, List<Map<String, String>> mappings, UnaryOperator<String> processor) { |
|
|
|
AtomicBoolean updated = new AtomicBoolean(false); |
|
|
|
JacksonUtil.replaceByMapping(jsonNode, mapping, Collections.emptyMap(), (name, urlNode) -> { |
|
|
|
String value = null; |
|
|
|
if (urlNode.isTextual()) { // link is in the right place
|
|
|
|
value = urlNode.asText(); |
|
|
|
} else { |
|
|
|
JsonNode id = urlNode.get("id"); // old structure is used
|
|
|
|
if (id != null && id.isTextual()) { |
|
|
|
value = id.asText(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if (StringUtils.isNotBlank(value)) { |
|
|
|
value = processor.apply(value); |
|
|
|
} else { |
|
|
|
value = ""; |
|
|
|
} |
|
|
|
for (int i = 0; i < jsonNodes.size(); i++) { |
|
|
|
JsonNode jsonNode = jsonNodes.get(i); |
|
|
|
// processing by mappings first
|
|
|
|
if (i <= mappings.size() - 1) { |
|
|
|
JacksonUtil.replaceByMapping(jsonNode, mappings.get(i), Collections.emptyMap(), (name, urlNode) -> { |
|
|
|
String value = null; |
|
|
|
if (urlNode.isTextual()) { // link is in the right place
|
|
|
|
value = urlNode.asText(); |
|
|
|
} else { |
|
|
|
JsonNode id = urlNode.get("id"); // old structure is used
|
|
|
|
if (id != null && id.isTextual()) { |
|
|
|
value = id.asText(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
JsonNode newValue = new TextNode(value); |
|
|
|
if (!newValue.toString().equals(urlNode.toString())) { |
|
|
|
updated.set(true); |
|
|
|
log.trace("Replaced '{}' with '{}'", urlNode, newValue); |
|
|
|
if (StringUtils.isNotBlank(value)) { |
|
|
|
value = processor.apply(value); |
|
|
|
} else { |
|
|
|
value = ""; |
|
|
|
} |
|
|
|
|
|
|
|
JsonNode newValue = new TextNode(value); |
|
|
|
if (!newValue.toString().equals(urlNode.toString())) { |
|
|
|
updated.set(true); |
|
|
|
log.trace("Replaced by mapping '{}' ({}) with '{}'", value, name, newValue); |
|
|
|
} |
|
|
|
return newValue; |
|
|
|
}); |
|
|
|
} |
|
|
|
return newValue; |
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
// processing all
|
|
|
|
JacksonUtil.replaceAll(jsonNode, "", (name, value) -> { |
|
|
|
if (!StringUtils.startsWith(value, DataConstants.TB_RESOURCE_PREFIX + "/api/resource/")) { |
|
|
|
return value; |
|
|
|
} |
|
|
|
|
|
|
|
String newValue = processor.apply(value); |
|
|
|
if (StringUtils.equals(value, newValue)) { |
|
|
|
return value; |
|
|
|
} else { |
|
|
|
updated.set(true); |
|
|
|
log.trace("Replaced '{}' ({}) with '{}'", value, name, newValue); |
|
|
|
return newValue; |
|
|
|
} |
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
|
return updated.get(); |
|
|
|
} |
|
|
|
|
|
|
|
@ -555,7 +605,7 @@ public class BaseResourceService extends AbstractCachedEntityService<ResourceInf |
|
|
|
importResources(dashboard.getTenantId(), dashboard.getResources()); |
|
|
|
} |
|
|
|
imageService.updateImagesUsage(dashboard); |
|
|
|
updateResourcesUsage(dashboard); |
|
|
|
updateResourcesUsage(dashboard.getTenantId(), dashboard); |
|
|
|
|
|
|
|
data = JacksonUtil.writeValueAsBytes(dashboard); |
|
|
|
} |
|
|
|
|