Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow bulk deletion of metadata #2984

Merged
merged 1 commit into from
Jul 18, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,19 @@
package org.openhab.core.io.console.internal.extension;

import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.core.io.console.Console;
import org.openhab.core.io.console.extensions.AbstractConsoleCommandExtension;
import org.openhab.core.io.console.extensions.ConsoleCommandExtension;
import org.openhab.core.items.Item;
import org.openhab.core.items.ItemRegistry;
import org.openhab.core.items.Metadata;
import org.openhab.core.items.MetadataKey;
Expand All @@ -36,6 +40,7 @@
* Console command extension for the {@link MetadataRegistry}.
*
* @author Andre Fuechsel - Initial contribution
* @author Jan N. Klug - Added removal of orphaned metadata
*/
@Component(service = ConsoleCommandExtension.class)
@NonNullByDefault
Expand All @@ -45,6 +50,7 @@ public class MetadataConsoleCommandExtension extends AbstractConsoleCommandExten
private static final String SUBCMD_LIST_INTERNAL = "listinternal";
private static final String SUBCMD_ADD = "add";
private static final String SUBCMD_REMOVE = "remove";
private static final String SUBCMD_ORPHAN = "orphan";

private final ItemRegistry itemRegistry;
private final MetadataRegistry metadataRegistry;
Expand All @@ -59,15 +65,17 @@ public MetadataConsoleCommandExtension(final @Reference ItemRegistry itemRegistr

@Override
public List<String> getUsages() {
return Arrays.asList(new String[] {
return Arrays.asList( //
buildCommandUsage(SUBCMD_LIST + " [<itemName> [<namespace>]]",
"lists all available metadata, can be filtered for a specifc item and namespace"),
buildCommandUsage(SUBCMD_LIST_INTERNAL + " [<itemName> [<namespace>]]",
"lists all available INTERNAL metadata, can be filtered for a specifc item and namespace"),
buildCommandUsage(SUBCMD_REMOVE + " <itemName> [<namespace>]",
"removes metadata for the specific item (for all namespaces or for the given namespace only)"),
buildCommandUsage(SUBCMD_ADD + " <itemName> <namespace> <value> [\"{key1=value1, key2=value2, ...}\"]",
"adds or updates metadata value (and optional config values) for the specific item in the given namespace") });
"adds or updates metadata value (and optional config values) for the specific item in the given namespace"),
buildCommandUsage(SUBCMD_ORPHAN + " list|purge",
"lists or removes all metadata for which no corresponding item is present"));
}

@Override
Expand All @@ -88,6 +96,14 @@ public void execute(String[] args, Console console) {
addMetadata(console, args[1], args[2], args[3], args.length > 4 ? args[4] : null);
}
break;
case SUBCMD_ORPHAN:
if (args.length == 2 && (args[1].equals("list") || args[1].equals("purge"))) {
orphan(console, args[1], metadataRegistry.getAll(), itemRegistry.getAll());
} else {
console.println("Specify action 'list' or 'purge' to be executed: orphan <list|purge>");
}
return;

case SUBCMD_REMOVE:
removeMetadata(console, args[1], args.length > 2 ? args[2] : null);
break;
Expand Down Expand Up @@ -134,10 +150,10 @@ private void addMetadata(Console console, String itemName, String namespace, Str
Metadata metadata = new Metadata(key, value, configMap);
if (metadataRegistry.get(key) != null) {
metadataRegistry.update(metadata);
console.println("Updated: " + metadata.toString());
console.println("Updated: " + metadata);
} else {
metadataRegistry.add(metadata);
console.println("Added: " + metadata.toString());
console.println("Added: " + metadata);
}
}
}
Expand All @@ -154,7 +170,7 @@ private void addMetadata(Console console, String itemName, String namespace, Str
Map<String, Object> map = new HashMap<>();
for (String part : configStr.split("\\s*,\\s*")) {
String[] subparts = part.split("=", 2);
if (subparts.length == 2 && subparts[0] != null && subparts[1] != null) {
if (subparts.length == 2) {
map.put(subparts[0].trim(), subparts[1].trim());
}
}
Expand All @@ -177,9 +193,22 @@ private void removeMetadata(Console console, String itemName, @Nullable String n
private void removeMetadata(Console console, MetadataKey key) {
Metadata metadata = metadataRegistry.remove(key);
if (metadata != null) {
console.println("Removed: " + metadata.toString());
console.println("Removed: " + metadata);
} else {
console.println("Metadata element for " + key + " could not be found.");
}
}

private void orphan(Console console, String action, Collection<Metadata> metadata, Collection<Item> items) {
Collection<String> itemNames = items.stream().map(Item::getName).collect(Collectors.toCollection(HashSet::new));

metadata.forEach(md -> {
if (!itemNames.contains(md.getUID().getItemName())) {
console.println("Item missing: " + md.getUID());
if ("purge".equals(action)) {
metadataRegistry.remove(md.getUID());
}
}
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -591,20 +591,24 @@ public Response addMetadata(@PathParam("itemname") @Parameter(description = "ite
@ApiResponse(responseCode = "404", description = "Item not found."),
@ApiResponse(responseCode = "405", description = "Meta data not editable.") })
public Response removeMetadata(@PathParam("itemname") @Parameter(description = "item name") String itemname,
@PathParam("namespace") @Parameter(description = "namespace") String namespace) {
@Nullable @PathParam("namespace") @Parameter(description = "namespace") String namespace) {
Item item = getItem(itemname);

if (item == null) {
return Response.status(Status.NOT_FOUND).build();
}

MetadataKey key = new MetadataKey(namespace, itemname);
if (metadataRegistry.get(key) != null) {
if (metadataRegistry.remove(key) == null) {
return Response.status(Status.CONFLICT).build();
}
if (namespace == null) {
metadataRegistry.removeItemMetadata(itemname);
} else {
return Response.status(Status.NOT_FOUND).build();
MetadataKey key = new MetadataKey(namespace, itemname);
if (metadataRegistry.get(key) != null) {
if (metadataRegistry.remove(key) == null) {
return Response.status(Status.CONFLICT).build();
}
} else {
return Response.status(Status.NOT_FOUND).build();
}
}

return Response.ok(null, MediaType.TEXT_PLAIN).build();
Expand Down