mirror of
https://github.com/danieldemus/openhab-core.git
synced 2025-01-10 21:31:53 +01:00
Use ThingStorageEntity instead of ThingImpl/BridgeImpl for storage (#2914)
Signed-off-by: Jan N. Klug <github@klug.nrw>
This commit is contained in:
parent
2b4e5af21e
commit
d74277f798
@ -25,6 +25,8 @@ import org.openhab.core.OpenHAB;
|
||||
import org.openhab.core.config.core.ConfigurableService;
|
||||
import org.openhab.core.storage.Storage;
|
||||
import org.openhab.core.storage.StorageService;
|
||||
import org.openhab.core.storage.json.internal.migration.BridgeImplTypeMigrator;
|
||||
import org.openhab.core.storage.json.internal.migration.ThingImplTypeMigrator;
|
||||
import org.openhab.core.storage.json.internal.migration.TypeMigrator;
|
||||
import org.osgi.framework.Constants;
|
||||
import org.osgi.service.component.annotations.Activate;
|
||||
@ -51,7 +53,8 @@ public class JsonStorageService implements StorageService {
|
||||
/**
|
||||
* Contains a map of needed migrations, key is the storage name
|
||||
*/
|
||||
private static final Map<String, List<TypeMigrator>> MIGRATORS = Map.of();
|
||||
private static final Map<String, List<TypeMigrator>> MIGRATORS = Map.of( //
|
||||
"org.openhab.core.thing.Thing", List.of(new BridgeImplTypeMigrator(), new ThingImplTypeMigrator()));
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(JsonStorageService.class);
|
||||
|
||||
|
@ -0,0 +1,43 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2022 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.storage.json.internal.migration;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
|
||||
/**
|
||||
* The {@link BridgeImplTypeMigrator} implements a {@link TypeMigrator} for stored bridges
|
||||
*
|
||||
* @author Jan N. Klug - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class BridgeImplTypeMigrator extends ThingImplTypeMigrator {
|
||||
|
||||
@Override
|
||||
public String getOldType() {
|
||||
return "org.openhab.core.thing.internal.BridgeImpl";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getNewType() {
|
||||
return "org.openhab.core.thing.internal.ThingStorageEntity";
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonElement migrate(JsonElement oldValue) throws TypeMigrationException {
|
||||
JsonElement newValue = super.migrate(oldValue);
|
||||
newValue.getAsJsonObject().addProperty("isBridge", true);
|
||||
return newValue;
|
||||
}
|
||||
}
|
@ -0,0 +1,77 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2022 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.storage.json.internal.migration;
|
||||
|
||||
import java.util.Spliterator;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.StreamSupport;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
/**
|
||||
* The {@link ThingImplTypeMigrator} implements a {@link TypeMigrator} for stored things
|
||||
*
|
||||
* @author Jan N. Klug - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class ThingImplTypeMigrator implements TypeMigrator {
|
||||
|
||||
@Override
|
||||
public String getOldType() {
|
||||
return "org.openhab.core.thing.internal.ThingImpl";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getNewType() {
|
||||
return "org.openhab.core.thing.internal.ThingStorageEntity";
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonElement migrate(JsonElement oldValue) throws TypeMigrationException {
|
||||
JsonObject newValue = oldValue.deepCopy().getAsJsonObject();
|
||||
segmentUidToStringUid(newValue, "uid", "UID");
|
||||
segmentUidToStringUid(newValue, "bridgeUID");
|
||||
segmentUidToStringUid(newValue, "thingTypeUID");
|
||||
|
||||
for (JsonElement jsonElement : newValue.get("channels").getAsJsonArray()) {
|
||||
JsonObject channel = jsonElement.getAsJsonObject();
|
||||
channel.add("itemType", channel.remove("acceptedItemType"));
|
||||
channel.add("configuration", channel.remove("configuration").getAsJsonObject().get("properties"));
|
||||
segmentUidToStringUid(channel, "uid");
|
||||
segmentUidToStringUid(channel, "channelTypeUID");
|
||||
}
|
||||
|
||||
newValue.add("configuration", newValue.remove("configuration").getAsJsonObject().get("properties"));
|
||||
newValue.addProperty("isBridge", false);
|
||||
|
||||
return newValue;
|
||||
}
|
||||
|
||||
private void segmentUidToStringUid(JsonObject object, String name) {
|
||||
segmentUidToStringUid(object, name, name);
|
||||
}
|
||||
|
||||
private void segmentUidToStringUid(JsonObject object, String oldName, String newName) {
|
||||
JsonElement element = object.remove(oldName);
|
||||
if (element != null) {
|
||||
Spliterator<JsonElement> segments = element.getAsJsonObject().get("segments").getAsJsonArray()
|
||||
.spliterator();
|
||||
String uid = StreamSupport.stream(segments, false).map(JsonElement::getAsString)
|
||||
.collect(Collectors.joining(":"));
|
||||
object.addProperty(newName, uid);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,105 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2022 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.storage.json.internal;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.nullValue;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileReader;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.Arguments;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
import org.openhab.core.config.core.OrderingMapSerializer;
|
||||
import org.openhab.core.config.core.OrderingSetSerializer;
|
||||
import org.openhab.core.storage.json.internal.migration.BridgeImplTypeMigrator;
|
||||
import org.openhab.core.storage.json.internal.migration.ThingImplTypeMigrator;
|
||||
import org.openhab.core.storage.json.internal.migration.TypeMigrationException;
|
||||
import org.openhab.core.storage.json.internal.migration.TypeMigrator;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.JsonElement;
|
||||
|
||||
/**
|
||||
* The {@link ThingStorageEntityMigratorTest} contains tests for the ThingImpl and BridgeImpl migrators
|
||||
*
|
||||
* @author Jan N. Klug - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class ThingStorageEntityMigratorTest {
|
||||
|
||||
private final Gson internalMapper = new GsonBuilder() //
|
||||
.registerTypeHierarchyAdapter(Map.class, new OrderingMapSerializer())//
|
||||
.registerTypeHierarchyAdapter(Set.class, new OrderingSetSerializer())//
|
||||
.registerTypeHierarchyAdapter(Map.class, new StorageEntryMapDeserializer()) //
|
||||
.setPrettyPrinting() //
|
||||
.create();
|
||||
|
||||
private @NonNullByDefault({}) Map<String, StorageEntry> inputMap;
|
||||
private @NonNullByDefault({}) Map<String, StorageEntry> resultMap;
|
||||
|
||||
@BeforeEach
|
||||
public void setup() throws FileNotFoundException {
|
||||
inputMap = readDatabase(Path.of("src/test/resources/thingMigration-input.json"));
|
||||
resultMap = readDatabase(Path.of("src/test/resources/thingMigration-result.json"));
|
||||
|
||||
assertThat(inputMap.size(), is(2));
|
||||
assertThat(resultMap.size(), is(2));
|
||||
}
|
||||
|
||||
private static Stream<Arguments> typeMigrationsSource() {
|
||||
return Stream.of(Arguments.of("deconz:deconz:00313E041ED0", new BridgeImplTypeMigrator(), true),
|
||||
Arguments.of("http:url:0a500ec3d8", new ThingImplTypeMigrator(), false));
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("typeMigrationsSource")
|
||||
public void typeMigration(String thingUid, TypeMigrator migrator, boolean isBridge) throws TypeMigrationException {
|
||||
StorageEntry inputEntry = inputMap.get(thingUid);
|
||||
StorageEntry resultEntry = resultMap.get(thingUid);
|
||||
|
||||
assertThat(inputEntry.getEntityClassName(), is(migrator.getOldType()));
|
||||
|
||||
JsonElement entityValue = (JsonElement) inputEntry.getValue();
|
||||
assertThat(entityValue.getAsJsonObject().get("isBridge"), nullValue());
|
||||
|
||||
JsonElement newEntityValue = migrator.migrate(entityValue);
|
||||
assertThat(newEntityValue.getAsJsonObject().get("isBridge").getAsBoolean(), is(isBridge));
|
||||
|
||||
assertThat(newEntityValue, is(resultEntry.getValue()));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private Map<String, StorageEntry> readDatabase(Path path) throws FileNotFoundException {
|
||||
final Map<String, StorageEntry> map = new ConcurrentHashMap<>();
|
||||
|
||||
FileReader reader = new FileReader(path.toFile());
|
||||
Map<String, StorageEntry> loadedMap = internalMapper.fromJson(reader, map.getClass());
|
||||
|
||||
if (loadedMap != null && !loadedMap.isEmpty()) {
|
||||
map.putAll(loadedMap);
|
||||
}
|
||||
|
||||
return map;
|
||||
}
|
||||
}
|
@ -0,0 +1,130 @@
|
||||
{
|
||||
"deconz:deconz:00313E041ED0": {
|
||||
"class": "org.openhab.core.thing.internal.BridgeImpl",
|
||||
"value": {
|
||||
"label": "Phoscon (192.168.1.100:80)",
|
||||
"channels": [],
|
||||
"configuration": {
|
||||
"properties": {
|
||||
"host": "192.168.1.100",
|
||||
"httpPort": 80,
|
||||
"timeout": 2000,
|
||||
"websocketTimeout": 120
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
"UDN": "56071c34-1111-4b08-bba8-d3f29e6d43d8"
|
||||
},
|
||||
"uid": {
|
||||
"segments": [
|
||||
"deconz",
|
||||
"deconz",
|
||||
"00313E041ED0"
|
||||
],
|
||||
"uid": "deconz:deconz:00313E041ED0"
|
||||
},
|
||||
"thingTypeUID": {
|
||||
"segments": [
|
||||
"deconz",
|
||||
"deconz"
|
||||
],
|
||||
"uid": ""
|
||||
}
|
||||
}
|
||||
},
|
||||
"http:url:0a500ec3d8": {
|
||||
"class": "org.openhab.core.thing.internal.ThingImpl",
|
||||
"value": {
|
||||
"label": "HTTP URL Thing",
|
||||
"channels": [
|
||||
{
|
||||
"acceptedItemType": "DateTime",
|
||||
"kind": "STATE",
|
||||
"uid": {
|
||||
"segments": [
|
||||
"http",
|
||||
"url",
|
||||
"0a500ec3d8",
|
||||
"lastFailure"
|
||||
],
|
||||
"uid": "http:url:0a500ec3d8:lastFailure"
|
||||
},
|
||||
"channelTypeUID": {
|
||||
"segments": [
|
||||
"http",
|
||||
"requestDateTime"
|
||||
],
|
||||
"uid": "http:requestDateTime"
|
||||
},
|
||||
"label": "Last Failure",
|
||||
"configuration": {
|
||||
"properties": {
|
||||
"stateTransformation": "abcd"
|
||||
}
|
||||
},
|
||||
"properties": {},
|
||||
"defaultTags": [],
|
||||
"autoUpdatePolicy": "DEFAULT"
|
||||
},
|
||||
{
|
||||
"acceptedItemType": "DateTime",
|
||||
"kind": "STATE",
|
||||
"uid": {
|
||||
"segments": [
|
||||
"http",
|
||||
"url",
|
||||
"0a500ec3d8",
|
||||
"lastSuccess"
|
||||
],
|
||||
"uid": "http:url:0a500ec3d8:lastSuccess"
|
||||
},
|
||||
"channelTypeUID": {
|
||||
"segments": [
|
||||
"http",
|
||||
"requestDateTime"
|
||||
],
|
||||
"uid": "http:requestDateTime"
|
||||
},
|
||||
"label": "Last Success",
|
||||
"configuration": {
|
||||
"properties": {}
|
||||
},
|
||||
"properties": {},
|
||||
"defaultTags": [],
|
||||
"autoUpdatePolicy": "DEFAULT"
|
||||
}
|
||||
],
|
||||
"configuration": {
|
||||
"properties": {
|
||||
"authMode": "BASIC",
|
||||
"baseURL": "https://localhost:8443",
|
||||
"bufferSize": 2048,
|
||||
"commandMethod": "GET",
|
||||
"delay": 0,
|
||||
"ignoreSSLErrors": true,
|
||||
"refresh": 30,
|
||||
"stateMethod": "GET",
|
||||
"timeout": 3000
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
"thingTypeVersion": "1"
|
||||
},
|
||||
"uid": {
|
||||
"segments": [
|
||||
"http",
|
||||
"url",
|
||||
"0a500ec3d8"
|
||||
],
|
||||
"uid": "http:url:0a500ec3d8"
|
||||
},
|
||||
"thingTypeUID": {
|
||||
"segments": [
|
||||
"http",
|
||||
"url"
|
||||
],
|
||||
"uid": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,70 @@
|
||||
{
|
||||
"deconz:deconz:00313E041ED0": {
|
||||
"class": "org.openhab.core.thing.internal.ThingStorageEntity",
|
||||
"value": {
|
||||
"label": "Phoscon (192.168.1.100:80)",
|
||||
"channels": [],
|
||||
"properties": {
|
||||
"UDN": "56071c34-1111-4b08-bba8-d3f29e6d43d8"
|
||||
},
|
||||
"UID": "deconz:deconz:00313E041ED0",
|
||||
"thingTypeUID": "deconz:deconz",
|
||||
"configuration": {
|
||||
"host": "192.168.1.100",
|
||||
"httpPort": 80,
|
||||
"timeout": 2000,
|
||||
"websocketTimeout": 120
|
||||
},
|
||||
"isBridge": true
|
||||
}
|
||||
},
|
||||
"http:url:0a500ec3d8": {
|
||||
"class": "org.openhab.core.thing.internal.ThingStorageEntity",
|
||||
"value": {
|
||||
"label": "HTTP URL Thing",
|
||||
"channels": [
|
||||
{
|
||||
"kind": "STATE",
|
||||
"label": "Last Failure",
|
||||
"configuration": {
|
||||
"stateTransformation": "abcd"
|
||||
},
|
||||
"properties": {},
|
||||
"defaultTags": [],
|
||||
"autoUpdatePolicy": "DEFAULT",
|
||||
"itemType": "DateTime",
|
||||
"uid": "http:url:0a500ec3d8:lastFailure",
|
||||
"channelTypeUID": "http:requestDateTime"
|
||||
},
|
||||
{
|
||||
"kind": "STATE",
|
||||
"label": "Last Success",
|
||||
"configuration": {},
|
||||
"properties": {},
|
||||
"defaultTags": [],
|
||||
"autoUpdatePolicy": "DEFAULT",
|
||||
"itemType": "DateTime",
|
||||
"uid": "http:url:0a500ec3d8:lastSuccess",
|
||||
"channelTypeUID": "http:requestDateTime"
|
||||
}
|
||||
],
|
||||
"configuration": {
|
||||
"authMode": "BASIC",
|
||||
"baseURL": "https://localhost:8443",
|
||||
"bufferSize": 2048,
|
||||
"commandMethod": "GET",
|
||||
"delay": 0,
|
||||
"ignoreSSLErrors": true,
|
||||
"refresh": 30,
|
||||
"stateMethod": "GET",
|
||||
"timeout": 3000
|
||||
},
|
||||
"properties": {
|
||||
"thingTypeVersion": "1"
|
||||
},
|
||||
"UID": "http:url:0a500ec3d8",
|
||||
"thingTypeUID": "http:url",
|
||||
"isBridge": false
|
||||
}
|
||||
}
|
||||
}
|
@ -13,8 +13,12 @@
|
||||
package org.openhab.core.thing;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.core.common.registry.DefaultAbstractManagedProvider;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.core.common.registry.AbstractManagedProvider;
|
||||
import org.openhab.core.storage.StorageService;
|
||||
import org.openhab.core.thing.dto.ThingDTOMapper;
|
||||
import org.openhab.core.thing.internal.BridgeImpl;
|
||||
import org.openhab.core.thing.internal.ThingStorageEntity;
|
||||
import org.osgi.service.component.annotations.Activate;
|
||||
import org.osgi.service.component.annotations.Component;
|
||||
import org.osgi.service.component.annotations.Reference;
|
||||
@ -31,7 +35,8 @@ import org.osgi.service.component.annotations.Reference;
|
||||
*/
|
||||
@NonNullByDefault
|
||||
@Component(immediate = true, service = { ThingProvider.class, ManagedThingProvider.class })
|
||||
public class ManagedThingProvider extends DefaultAbstractManagedProvider<Thing, ThingUID> implements ThingProvider {
|
||||
public class ManagedThingProvider extends AbstractManagedProvider<Thing, ThingUID, ThingStorageEntity>
|
||||
implements ThingProvider {
|
||||
|
||||
@Activate
|
||||
public ManagedThingProvider(final @Reference StorageService storageService) {
|
||||
@ -47,4 +52,14 @@ public class ManagedThingProvider extends DefaultAbstractManagedProvider<Thing,
|
||||
protected String keyToString(ThingUID key) {
|
||||
return key.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @Nullable Thing toElement(String key, ThingStorageEntity persistableElement) {
|
||||
return ThingDTOMapper.map(persistableElement, persistableElement.isBridge);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ThingStorageEntity toPersistableElement(Thing element) {
|
||||
return new ThingStorageEntity(ThingDTOMapper.map(element), element instanceof BridgeImpl);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,34 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2022 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.thing.internal;
|
||||
|
||||
import org.openhab.core.thing.dto.ThingDTO;
|
||||
|
||||
/**
|
||||
* The {@link ThingStorageEntity} is an entity for Thing storage
|
||||
*
|
||||
* @author Jan N. Klug - Initial contribution
|
||||
*/
|
||||
public class ThingStorageEntity extends ThingDTO {
|
||||
public boolean isBridge = false;
|
||||
|
||||
ThingStorageEntity() {
|
||||
// do not remove, needed by GSON for deserialization
|
||||
}
|
||||
|
||||
public ThingStorageEntity(ThingDTO thingDTO, boolean isBridge) {
|
||||
super(thingDTO.thingTypeUID, thingDTO.UID, thingDTO.label, thingDTO.bridgeUID, thingDTO.channels,
|
||||
thingDTO.configuration, thingDTO.properties, thingDTO.location);
|
||||
this.isBridge = isBridge;
|
||||
}
|
||||
}
|
@ -0,0 +1,76 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2022 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.thing;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import org.mockito.junit.jupiter.MockitoSettings;
|
||||
import org.mockito.quality.Strictness;
|
||||
import org.openhab.core.library.CoreItemFactory;
|
||||
import org.openhab.core.storage.StorageService;
|
||||
import org.openhab.core.thing.binding.builder.BridgeBuilder;
|
||||
import org.openhab.core.thing.binding.builder.ChannelBuilder;
|
||||
import org.openhab.core.thing.binding.builder.ThingBuilder;
|
||||
import org.openhab.core.thing.internal.ThingStorageEntity;
|
||||
|
||||
/**
|
||||
* The {@link ManagedThingProviderTest} contains tests for the {@link ManagedThingProvider}
|
||||
*
|
||||
* @author Jan N. Klug - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
@MockitoSettings(strictness = Strictness.LENIENT)
|
||||
public class ManagedThingProviderTest {
|
||||
|
||||
private static final ThingTypeUID THING_TYPE_UID = new ThingTypeUID("test", "test");
|
||||
private static final ThingUID THING_UID = new ThingUID(THING_TYPE_UID, "test");
|
||||
private static final String FIRST_CHANNEL_ID = "firstgroup#channel1";
|
||||
private static final ChannelUID FIRST_CHANNEL_UID = new ChannelUID(THING_UID, FIRST_CHANNEL_ID);
|
||||
|
||||
private @Mock @NonNullByDefault({}) StorageService storageService;
|
||||
|
||||
@Test
|
||||
public void testThingImplConversion() {
|
||||
Thing thing = ThingBuilder.create(THING_TYPE_UID, THING_UID)
|
||||
.withChannel(ChannelBuilder.create(FIRST_CHANNEL_UID, CoreItemFactory.STRING).build()).build();
|
||||
|
||||
ManagedThingProvider managedThingProvider = new ManagedThingProvider(storageService);
|
||||
ThingStorageEntity persistableElement = managedThingProvider.toPersistableElement(thing);
|
||||
|
||||
assertThat(persistableElement.isBridge, is(false));
|
||||
|
||||
Thing thing1 = managedThingProvider.toElement("", persistableElement);
|
||||
assertThat(thing1, is(thing));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBridgeImplConversion() {
|
||||
Bridge thing = BridgeBuilder.create(THING_TYPE_UID, THING_UID)
|
||||
.withChannel(ChannelBuilder.create(FIRST_CHANNEL_UID, CoreItemFactory.STRING).build()).build();
|
||||
|
||||
ManagedThingProvider managedThingProvider = new ManagedThingProvider(storageService);
|
||||
ThingStorageEntity persistableElement = managedThingProvider.toPersistableElement(thing);
|
||||
|
||||
assertThat(persistableElement.isBridge, is(true));
|
||||
|
||||
Thing thing1 = managedThingProvider.toElement("", persistableElement);
|
||||
assertThat(thing1, is(thing));
|
||||
}
|
||||
}
|
@ -51,4 +51,6 @@ Fragment-Host: org.openhab.core.storage.json
|
||||
org.ops4j.pax.logging.pax-logging-api;version='[2.0.16,2.0.17)',\
|
||||
ch.qos.logback.classic;version='[1.2.11,1.2.12)',\
|
||||
ch.qos.logback.core;version='[1.2.11,1.2.12)',\
|
||||
biz.aQute.tester.junit-platform;version='[6.3.0,6.3.1)'
|
||||
org.openhab.core.io.console;version='[3.3.0,3.3.1)',\
|
||||
org.openhab.core.thing;version='[3.3.0,3.3.1)',\
|
||||
biz.aQute.tester.junit-platform;version='[6.3.0,6.3.1)
|
@ -0,0 +1,73 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2022 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.storage.json.internal;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.hasItems;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.notNullValue;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Collection;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.openhab.core.OpenHAB;
|
||||
import org.openhab.core.storage.Storage;
|
||||
import org.openhab.core.storage.StorageService;
|
||||
import org.openhab.core.test.java.JavaOSGiTest;
|
||||
import org.openhab.core.thing.ManagedThingProvider;
|
||||
import org.openhab.core.thing.Thing;
|
||||
|
||||
/**
|
||||
* The {@link ThingMigrationOSGiTest} is a test for thing migrations
|
||||
*
|
||||
* @author Jan N. Klug - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class ThingMigrationOSGiTest extends JavaOSGiTest {
|
||||
private static final Path DB_DIR = Path.of(OpenHAB.getUserDataFolder(), "jsondb");
|
||||
private static final String DB_NAME = "org.openhab.core.thing.Thing";
|
||||
private static final String DB_OLD_NAME = "org.openhab.core.thing.Thing-old";
|
||||
|
||||
@Test
|
||||
public void migrationParsable() throws IOException {
|
||||
Files.createDirectories(DB_DIR);
|
||||
|
||||
StorageService storageService = getService(StorageService.class);
|
||||
assertThat(storageService, is(notNullValue()));
|
||||
|
||||
// prepare storage
|
||||
Files.copy(bundleContext.getBundle().getResource(DB_NAME + ".json").openStream(),
|
||||
DB_DIR.resolve(DB_NAME + ".json"));
|
||||
|
||||
// we need to go over a ManagedThingProvider because the ThingStorageEntity is an internal package
|
||||
ManagedThingProvider managedThingProvider = new ManagedThingProvider(storageService);
|
||||
Collection<Thing> things = managedThingProvider.getAll();
|
||||
assertThat(things.size(), is(2));
|
||||
|
||||
// remove this block when ThingImpl/BridgeImpl changes
|
||||
Files.copy(bundleContext.getBundle().getResource(DB_NAME + ".json").openStream(),
|
||||
DB_DIR.resolve(DB_OLD_NAME + ".json"));
|
||||
Storage<Thing> oldStorage = storageService.getStorage(DB_OLD_NAME, Thing.class.getClassLoader());
|
||||
Collection<@Nullable Thing> oldThings = oldStorage.getValues();
|
||||
assertThat(oldThings.size(), is(things.size()));
|
||||
|
||||
assertThat(things, hasItems(oldThings.toArray(Thing[]::new)));
|
||||
|
||||
unregisterService(storageService);
|
||||
}
|
||||
}
|
@ -0,0 +1,130 @@
|
||||
{
|
||||
"deconz:deconz:00313E041ED0": {
|
||||
"class": "org.openhab.core.thing.internal.BridgeImpl",
|
||||
"value": {
|
||||
"label": "Phoscon (192.168.1.100:80)",
|
||||
"channels": [],
|
||||
"configuration": {
|
||||
"properties": {
|
||||
"host": "192.168.1.100",
|
||||
"httpPort": 80,
|
||||
"timeout": 2000,
|
||||
"websocketTimeout": 120
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
"UDN": "56071c34-1111-4b08-bba8-d3f29e6d43d8"
|
||||
},
|
||||
"uid": {
|
||||
"segments": [
|
||||
"deconz",
|
||||
"deconz",
|
||||
"00313E041ED0"
|
||||
],
|
||||
"uid": "deconz:deconz:00313E041ED0"
|
||||
},
|
||||
"thingTypeUID": {
|
||||
"segments": [
|
||||
"deconz",
|
||||
"deconz"
|
||||
],
|
||||
"uid": ""
|
||||
}
|
||||
}
|
||||
},
|
||||
"http:url:0a500ec3d8": {
|
||||
"class": "org.openhab.core.thing.internal.ThingImpl",
|
||||
"value": {
|
||||
"label": "HTTP URL Thing",
|
||||
"channels": [
|
||||
{
|
||||
"acceptedItemType": "DateTime",
|
||||
"kind": "STATE",
|
||||
"uid": {
|
||||
"segments": [
|
||||
"http",
|
||||
"url",
|
||||
"0a500ec3d8",
|
||||
"lastFailure"
|
||||
],
|
||||
"uid": "http:url:0a500ec3d8:lastFailure"
|
||||
},
|
||||
"channelTypeUID": {
|
||||
"segments": [
|
||||
"http",
|
||||
"requestDateTime"
|
||||
],
|
||||
"uid": "http:requestDateTime"
|
||||
},
|
||||
"label": "Last Failure",
|
||||
"configuration": {
|
||||
"properties": {
|
||||
"stateTransformation": "abcd"
|
||||
}
|
||||
},
|
||||
"properties": {},
|
||||
"defaultTags": [],
|
||||
"autoUpdatePolicy": "DEFAULT"
|
||||
},
|
||||
{
|
||||
"acceptedItemType": "DateTime",
|
||||
"kind": "STATE",
|
||||
"uid": {
|
||||
"segments": [
|
||||
"http",
|
||||
"url",
|
||||
"0a500ec3d8",
|
||||
"lastSuccess"
|
||||
],
|
||||
"uid": "http:url:0a500ec3d8:lastSuccess"
|
||||
},
|
||||
"channelTypeUID": {
|
||||
"segments": [
|
||||
"http",
|
||||
"requestDateTime"
|
||||
],
|
||||
"uid": "http:requestDateTime"
|
||||
},
|
||||
"label": "Last Success",
|
||||
"configuration": {
|
||||
"properties": {}
|
||||
},
|
||||
"properties": {},
|
||||
"defaultTags": [],
|
||||
"autoUpdatePolicy": "DEFAULT"
|
||||
}
|
||||
],
|
||||
"configuration": {
|
||||
"properties": {
|
||||
"authMode": "BASIC",
|
||||
"baseURL": "https://localhost:8443",
|
||||
"bufferSize": 2048,
|
||||
"commandMethod": "GET",
|
||||
"delay": 0,
|
||||
"ignoreSSLErrors": true,
|
||||
"refresh": 30,
|
||||
"stateMethod": "GET",
|
||||
"timeout": 3000
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
"thingTypeVersion": "1"
|
||||
},
|
||||
"uid": {
|
||||
"segments": [
|
||||
"http",
|
||||
"url",
|
||||
"0a500ec3d8"
|
||||
],
|
||||
"uid": "http:url:0a500ec3d8"
|
||||
},
|
||||
"thingTypeUID": {
|
||||
"segments": [
|
||||
"http",
|
||||
"url"
|
||||
],
|
||||
"uid": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -24,6 +24,7 @@ import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
@ -44,9 +45,12 @@ import org.openhab.core.test.java.JavaOSGiTest;
|
||||
import org.openhab.core.thing.ChannelUID;
|
||||
import org.openhab.core.thing.ManagedThingProvider;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.thing.ThingRegistry;
|
||||
import org.openhab.core.thing.ThingStatus;
|
||||
import org.openhab.core.thing.ThingTypeUID;
|
||||
import org.openhab.core.thing.ThingUID;
|
||||
import org.openhab.core.thing.dto.ThingDTOMapper;
|
||||
import org.openhab.core.thing.internal.ThingStorageEntity;
|
||||
import org.openhab.core.thing.link.ItemChannelLink;
|
||||
import org.openhab.core.thing.link.ManagedItemChannelLinkProvider;
|
||||
import org.openhab.core.thing.type.ChannelDefinition;
|
||||
@ -104,6 +108,7 @@ public class ChangeThingTypeOSGiTest extends JavaOSGiTest {
|
||||
private @NonNullByDefault({}) ManagedThingProvider managedThingProvider;
|
||||
private @NonNullByDefault({}) ManagedItemProvider managedItemProvider;
|
||||
private @NonNullByDefault({}) SampleThingHandlerFactory thingHandlerFactory;
|
||||
private @NonNullByDefault({}) ThingRegistry thingRegistry;
|
||||
|
||||
private @NonNullByDefault({}) ThingType thingTypeGeneric;
|
||||
private @NonNullByDefault({}) ThingType thingTypeSpecific;
|
||||
@ -116,6 +121,9 @@ public class ChangeThingTypeOSGiTest extends JavaOSGiTest {
|
||||
|
||||
@BeforeEach
|
||||
public void setup() throws URISyntaxException {
|
||||
thingRegistry = getService(ThingRegistry.class);
|
||||
assertThat(thingRegistry, is(notNullValue()));
|
||||
|
||||
registerVolatileStorageService();
|
||||
managedThingProvider = getService(ManagedThingProvider.class);
|
||||
assertThat(managedThingProvider, is(notNullValue()));
|
||||
@ -324,7 +332,8 @@ public class ChangeThingTypeOSGiTest extends JavaOSGiTest {
|
||||
Thing persistedThing = ThingFactory.createThing(thingTypeSpecific,
|
||||
new ThingUID("testBinding", "persistedThing"), new Configuration(properties), null, null);
|
||||
persistedThing.setProperty("universal", "survives");
|
||||
storage.getStorage(Thing.class.getName()).put("testBinding::persistedThing", persistedThing);
|
||||
storage.getStorage(Thing.class.getName()).put("testBinding::persistedThing",
|
||||
new ThingStorageEntity(ThingDTOMapper.map(persistedThing), false));
|
||||
selfChanging = true;
|
||||
|
||||
unregisterService(storage);
|
||||
@ -335,7 +344,7 @@ public class ChangeThingTypeOSGiTest extends JavaOSGiTest {
|
||||
managedThingProvider = getService(ManagedThingProvider.class);
|
||||
assertThat(managedThingProvider, is(notNullValue()));
|
||||
|
||||
Collection<Thing> res = managedThingProvider.getAll();
|
||||
Collection<Thing> res = thingRegistry.getAll();
|
||||
assertThat(res.size(), is(1));
|
||||
|
||||
Thing thing = res.iterator().next();
|
||||
@ -400,8 +409,8 @@ public class ChangeThingTypeOSGiTest extends JavaOSGiTest {
|
||||
assertThat(thing.getStatus(), is(ThingStatus.ONLINE));
|
||||
|
||||
// Ensure the new thing type has been persisted into the database
|
||||
Storage<Thing> storage = getService(StorageService.class).getStorage(Thing.class.getName());
|
||||
Thing persistedThing = storage.get("testBinding::testThing");
|
||||
Storage<ThingStorageEntity> storage = getService(StorageService.class).getStorage(Thing.class.getName());
|
||||
Thing persistedThing = ThingDTOMapper.map(Objects.requireNonNull(storage.get("testBinding::testThing")), false);
|
||||
assertThat(persistedThing.getThingTypeUID().getAsString(), is("testBinding:specific"));
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user