Skip to content

Commit da78b82

Browse files
committed
reserve semantics namespace
Signed-off-by: Mark Herwege <mark.herwege@telenet.be>
1 parent e065bea commit da78b82

4 files changed

Lines changed: 106 additions & 15 deletions

File tree

bundles/org.openhab.core.io.rest.core/src/main/java/org/openhab/core/io/rest/core/internal/item/ItemResource.java

Lines changed: 25 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -765,14 +765,20 @@ public Response addMetadata(@PathParam("itemName") @Parameter(description = "ite
765765
value = "";
766766
}
767767

768-
MetadataKey key = new MetadataKey(namespace, itemName);
769-
Metadata md = new Metadata(key, value, metadata.config);
770-
if (metadataRegistry.get(key) == null) {
771-
metadataRegistry.add(md);
772-
return Response.status(Status.CREATED).type(MediaType.TEXT_PLAIN).build();
773-
} else {
774-
metadataRegistry.update(md);
775-
return Response.ok(null, MediaType.TEXT_PLAIN).build();
768+
try {
769+
MetadataKey key = new MetadataKey(namespace, itemName);
770+
Metadata md = new Metadata(key, value, metadata.config);
771+
if (metadataRegistry.get(key) == null) {
772+
metadataRegistry.add(md);
773+
return Response.status(Status.CREATED).type(MediaType.TEXT_PLAIN).build();
774+
} else {
775+
if (metadataRegistry.update(md) == null) {
776+
return Response.status(Status.METHOD_NOT_ALLOWED).build();
777+
}
778+
return Response.ok(null, MediaType.TEXT_PLAIN).build();
779+
}
780+
} catch (IllegalStateException e) {
781+
return Response.status(Status.METHOD_NOT_ALLOWED.getStatusCode(), e.getMessage()).build();
776782
}
777783
}
778784

@@ -783,7 +789,7 @@ public Response addMetadata(@PathParam("itemName") @Parameter(description = "ite
783789
@SecurityRequirement(name = "oauth2", scopes = { "admin" }) }, responses = {
784790
@ApiResponse(responseCode = "200", description = "OK"),
785791
@ApiResponse(responseCode = "404", description = "Item not found."),
786-
@ApiResponse(responseCode = "405", description = "Meta data not editable.") })
792+
@ApiResponse(responseCode = "405", description = "Metadata not editable.") })
787793
public Response removeMetadata(@PathParam("itemName") @Parameter(description = "item name") String itemName,
788794
@Nullable @PathParam("namespace") @Parameter(description = "namespace") String namespace) {
789795
Item item = getItem(itemName);
@@ -795,13 +801,17 @@ public Response removeMetadata(@PathParam("itemName") @Parameter(description = "
795801
if (namespace == null) {
796802
metadataRegistry.removeItemMetadata(itemName);
797803
} else {
798-
MetadataKey key = new MetadataKey(namespace, itemName);
799-
if (metadataRegistry.get(key) != null) {
800-
if (metadataRegistry.remove(key) == null) {
801-
return Response.status(Status.CONFLICT).build();
804+
try {
805+
MetadataKey key = new MetadataKey(namespace, itemName);
806+
if (metadataRegistry.get(key) != null) {
807+
if (metadataRegistry.remove(key) == null) {
808+
return Response.status(Status.METHOD_NOT_ALLOWED).build();
809+
}
810+
} else {
811+
return Response.status(Status.NOT_FOUND).build();
802812
}
803-
} else {
804-
return Response.status(Status.NOT_FOUND).build();
813+
} catch (IllegalStateException e) {
814+
return Response.status(Status.METHOD_NOT_ALLOWED.getStatusCode(), e.getMessage()).build();
805815
}
806816
}
807817

bundles/org.openhab.core.semantics/src/main/java/org/openhab/core/semantics/internal/SemanticsMetadataProvider.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import java.util.List;
1919
import java.util.Map;
2020
import java.util.Map.Entry;
21+
import java.util.Set;
2122
import java.util.TreeMap;
2223

2324
import org.eclipse.jdt.annotation.NonNullByDefault;
@@ -108,6 +109,11 @@ public Collection<Metadata> getAll() {
108109
return semantics.values();
109110
}
110111

112+
@Override
113+
public Collection<String> getReservedNamespaces() {
114+
return Set.of(NAMESPACE);
115+
}
116+
111117
/**
112118
* Updates the semantic metadata for an item and notifies all listeners about changes
113119
*

bundles/org.openhab.core/src/main/java/org/openhab/core/internal/items/MetadataRegistryImpl.java

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,15 @@
1313
package org.openhab.core.internal.items;
1414

1515
import java.util.Collection;
16+
import java.util.Map;
17+
import java.util.concurrent.ConcurrentHashMap;
1618
import java.util.stream.Collectors;
1719

1820
import org.eclipse.jdt.annotation.NonNullByDefault;
21+
import org.eclipse.jdt.annotation.Nullable;
1922
import org.openhab.core.common.registry.AbstractRegistry;
23+
import org.openhab.core.common.registry.ManagedProvider;
24+
import org.openhab.core.common.registry.Provider;
2025
import org.openhab.core.events.EventPublisher;
2126
import org.openhab.core.items.ManagedMetadataProvider;
2227
import org.openhab.core.items.Metadata;
@@ -37,12 +42,15 @@
3742
* keeps track of all declared metadata of all metadata providers.
3843
*
3944
* @author Kai Kreuzer - Initial contribution
45+
* @author Mark Herwege - semantics namespace not in managed provider
4046
*/
4147
@Component(immediate = true, service = MetadataRegistry.class)
4248
@NonNullByDefault
4349
public class MetadataRegistryImpl extends AbstractRegistry<Metadata, MetadataKey, MetadataProvider>
4450
implements MetadataRegistry {
4551

52+
private Map<String, MetadataProvider> reservedNamespaces = new ConcurrentHashMap<>();
53+
4654
@Activate
4755
public MetadataRegistryImpl(final @Reference ReadyService readyService) {
4856
super(MetadataProvider.class);
@@ -114,4 +122,49 @@ public void removeItemMetadata(String itemName) {
114122
getManagedProvider()
115123
.ifPresent(managedProvider -> ((ManagedMetadataProvider) managedProvider).removeItemMetadata(itemName));
116124
}
125+
126+
@Override
127+
public Metadata add(Metadata element) {
128+
String namespace = element.getUID().getNamespace();
129+
if (reservedNamespaces.get(namespace) == null || reservedNamespaces.get(namespace) instanceof ManagedProvider) {
130+
return super.add(element);
131+
}
132+
throw new IllegalStateException("Cannot add metadata to '" + namespace + "' namespace");
133+
}
134+
135+
@Override
136+
public @Nullable Metadata update(Metadata element) {
137+
String namespace = element.getUID().getNamespace();
138+
if (reservedNamespaces.get(namespace) == null || reservedNamespaces.get(namespace) instanceof ManagedProvider) {
139+
return super.update(element);
140+
}
141+
throw new IllegalStateException("Cannot update metadata in '" + namespace + "' namespace");
142+
}
143+
144+
@Override
145+
public @Nullable Metadata remove(MetadataKey key) {
146+
String namespace = key.getNamespace();
147+
if (reservedNamespaces.get(namespace) == null || reservedNamespaces.get(namespace) instanceof ManagedProvider) {
148+
return super.remove(key);
149+
}
150+
throw new IllegalStateException("Cannot remove metadata from '" + namespace + "' namespace");
151+
}
152+
153+
@Override
154+
protected void addProvider(Provider<Metadata> provider) {
155+
if (provider instanceof MetadataProvider metadataProvider) {
156+
metadataProvider.getReservedNamespaces().stream()
157+
.forEach(namespace -> reservedNamespaces.putIfAbsent(namespace, metadataProvider));
158+
}
159+
super.addProvider(provider);
160+
}
161+
162+
@Override
163+
protected void removeProvider(Provider<Metadata> provider) {
164+
if (provider instanceof MetadataProvider metadataProvider) {
165+
metadataProvider.getReservedNamespaces().stream()
166+
.forEach(namespace -> reservedNamespaces.remove(namespace, metadataProvider));
167+
}
168+
super.removeProvider(provider);
169+
}
117170
}

bundles/org.openhab.core/src/main/java/org/openhab/core/items/MetadataProvider.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,38 @@
1212
*/
1313
package org.openhab.core.items;
1414

15+
import java.util.Collection;
16+
import java.util.Set;
17+
1518
import org.eclipse.jdt.annotation.NonNullByDefault;
19+
import org.openhab.core.common.registry.ManagedProvider;
1620
import org.openhab.core.common.registry.Provider;
1721

1822
/**
1923
* This is a marker interface for metadata provider implementations that should be used to register those as an OSGi
2024
* service.
2125
*
2226
* @author Kai Kreuzer - Initial contribution
27+
* @author Mark Herwege - Added reserved namespaces
2328
*/
2429
@NonNullByDefault
2530
public interface MetadataProvider extends Provider<Metadata> {
2631

32+
/**
33+
* A {@link MetadataProvider} implementation can reserve a metadata namespace. Only a single provider for this
34+
* namespace can provide metadata for this namespace. Updating metadata in this namespace will have to be with this
35+
* provider, and is refused if the provider is not a {@link ManagedProvider}.
36+
*
37+
* This is useful if providers calculate metadata and this metadata is not meant to be persisted with a
38+
* {@link ManagedProvider}. An example is semantics metadata provided by the {@link SemanticsMetadataProvider}.
39+
* Implementations are expected to return an immutable {@link Collection}.
40+
*
41+
* The default implementation returns an empty {@link Set}.
42+
*
43+
* @return collection reserved namespaces
44+
*/
45+
public default Collection<String> getReservedNamespaces() {
46+
return Set.of();
47+
}
48+
2749
}

0 commit comments

Comments
 (0)