mirror of
https://github.com/danieldemus/openhab-core.git
synced 2025-01-10 21:31:53 +01:00
Enhance transformation configuration (#3036)
* Enhance transformation configuration This is needed to give the users the best experience when editing transformations in UI. Signed-off-by: Jan N. Klug <github@klug.nrw>
This commit is contained in:
parent
2909945998
commit
0b7fc242d4
@ -29,9 +29,9 @@ import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.core.common.ThreadPoolManager;
|
||||
import org.openhab.core.common.registry.RegistryChangeListener;
|
||||
import org.openhab.core.transform.TransformationConfiguration;
|
||||
import org.openhab.core.transform.TransformationConfigurationRegistry;
|
||||
import org.openhab.core.transform.Transformation;
|
||||
import org.openhab.core.transform.TransformationException;
|
||||
import org.openhab.core.transform.TransformationRegistry;
|
||||
import org.openhab.core.transform.TransformationService;
|
||||
import org.osgi.service.component.annotations.Activate;
|
||||
import org.osgi.service.component.annotations.Component;
|
||||
@ -48,8 +48,7 @@ import org.slf4j.LoggerFactory;
|
||||
*/
|
||||
@Component(service = TransformationService.class, property = { "openhab.transform=SCRIPT" })
|
||||
@NonNullByDefault
|
||||
public class ScriptTransformationService
|
||||
implements TransformationService, RegistryChangeListener<TransformationConfiguration> {
|
||||
public class ScriptTransformationService implements TransformationService, RegistryChangeListener<Transformation> {
|
||||
public static final String OPENHAB_TRANSFORMATION_SCRIPT = "openhab-transformation-script-";
|
||||
public static final String SUPPORTED_CONFIGURATION_TYPE = "script";
|
||||
|
||||
@ -65,21 +64,20 @@ public class ScriptTransformationService
|
||||
private final Map<String, CompiledScript> compiledScripts = new HashMap<>();
|
||||
private final Map<String, String> scriptCache = new HashMap<>();
|
||||
|
||||
private final TransformationConfigurationRegistry transformationConfigurationRegistry;
|
||||
private final TransformationRegistry transformationRegistry;
|
||||
private final ScriptEngineManager scriptEngineManager;
|
||||
|
||||
@Activate
|
||||
public ScriptTransformationService(
|
||||
@Reference TransformationConfigurationRegistry transformationConfigurationRegistry,
|
||||
public ScriptTransformationService(@Reference TransformationRegistry transformationRegistry,
|
||||
@Reference ScriptEngineManager scriptEngineManager) {
|
||||
this.transformationConfigurationRegistry = transformationConfigurationRegistry;
|
||||
this.transformationRegistry = transformationRegistry;
|
||||
this.scriptEngineManager = scriptEngineManager;
|
||||
transformationConfigurationRegistry.addRegistryChangeListener(this);
|
||||
transformationRegistry.addRegistryChangeListener(this);
|
||||
}
|
||||
|
||||
@Deactivate
|
||||
public void deactivate() {
|
||||
transformationConfigurationRegistry.removeRegistryChangeListener(this);
|
||||
transformationRegistry.removeRegistryChangeListener(this);
|
||||
|
||||
// cleanup script engines
|
||||
scriptEngineContainers.values().stream().map(ScriptEngineContainer::getScriptEngine)
|
||||
@ -98,14 +96,13 @@ public class ScriptTransformationService
|
||||
|
||||
String script = scriptCache.get(scriptUid);
|
||||
if (script == null) {
|
||||
TransformationConfiguration transformationConfiguration = transformationConfigurationRegistry
|
||||
.get(scriptUid);
|
||||
if (transformationConfiguration != null) {
|
||||
if (!SUPPORTED_CONFIGURATION_TYPE.equals(transformationConfiguration.getType())) {
|
||||
Transformation transformation = transformationRegistry.get(scriptUid);
|
||||
if (transformation != null) {
|
||||
if (!SUPPORTED_CONFIGURATION_TYPE.equals(transformation.getType())) {
|
||||
throw new TransformationException("Configuration does not have correct type 'script' but '"
|
||||
+ transformationConfiguration.getType() + "'.");
|
||||
+ transformation.getType() + "'.");
|
||||
}
|
||||
script = transformationConfiguration.getContent();
|
||||
script = transformation.getConfiguration().get(Transformation.FUNCTION);
|
||||
}
|
||||
if (script == null) {
|
||||
throw new TransformationException("Could not get script for UID '" + scriptUid + "'.");
|
||||
@ -164,17 +161,17 @@ public class ScriptTransformationService
|
||||
}
|
||||
|
||||
@Override
|
||||
public void added(TransformationConfiguration element) {
|
||||
public void added(Transformation element) {
|
||||
clearCache(element.getUID());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removed(TransformationConfiguration element) {
|
||||
public void removed(Transformation element) {
|
||||
clearCache(element.getUID());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updated(TransformationConfiguration oldElement, TransformationConfiguration element) {
|
||||
public void updated(Transformation oldElement, Transformation element) {
|
||||
clearCache(element.getUID());
|
||||
}
|
||||
|
||||
|
@ -19,6 +19,7 @@ import static org.mockito.ArgumentMatchers.*;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
import javax.script.ScriptContext;
|
||||
@ -33,9 +34,9 @@ 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.transform.TransformationConfiguration;
|
||||
import org.openhab.core.transform.TransformationConfigurationRegistry;
|
||||
import org.openhab.core.transform.Transformation;
|
||||
import org.openhab.core.transform.TransformationException;
|
||||
import org.openhab.core.transform.TransformationRegistry;
|
||||
|
||||
/**
|
||||
* The {@link ScriptTransformationServiceTest} holds tests for the {@link ScriptTransformationService}
|
||||
@ -53,12 +54,12 @@ public class ScriptTransformationServiceTest {
|
||||
private static final String SCRIPT = "script";
|
||||
private static final String SCRIPT_OUTPUT = "output";
|
||||
|
||||
private static final TransformationConfiguration TRANSFORMATION_CONFIGURATION = new TransformationConfiguration(
|
||||
SCRIPT_UID, "label", ScriptTransformationService.SUPPORTED_CONFIGURATION_TYPE, null, SCRIPT);
|
||||
private static final TransformationConfiguration INVALID_TRANSFORMATION_CONFIGURATION = new TransformationConfiguration(
|
||||
INVALID_SCRIPT_UID, "label", "invalid", null, SCRIPT);
|
||||
private static final Transformation TRANSFORMATION_CONFIGURATION = new Transformation(SCRIPT_UID, "label",
|
||||
ScriptTransformationService.SUPPORTED_CONFIGURATION_TYPE, Map.of(Transformation.FUNCTION, SCRIPT));
|
||||
private static final Transformation INVALID_TRANSFORMATION_CONFIGURATION = new Transformation(INVALID_SCRIPT_UID,
|
||||
"label", "invalid", Map.of(Transformation.FUNCTION, SCRIPT));
|
||||
|
||||
private @Mock @NonNullByDefault({}) TransformationConfigurationRegistry transformationConfigurationRegistry;
|
||||
private @Mock @NonNullByDefault({}) TransformationRegistry transformationRegistry;
|
||||
private @Mock @NonNullByDefault({}) ScriptEngineManager scriptEngineManager;
|
||||
private @Mock @NonNullByDefault({}) ScriptEngineContainer scriptEngineContainer;
|
||||
private @Mock @NonNullByDefault({}) ScriptEngine scriptEngine;
|
||||
@ -68,7 +69,7 @@ public class ScriptTransformationServiceTest {
|
||||
|
||||
@BeforeEach
|
||||
public void setUp() throws ScriptException {
|
||||
service = new ScriptTransformationService(transformationConfigurationRegistry, scriptEngineManager);
|
||||
service = new ScriptTransformationService(transformationRegistry, scriptEngineManager);
|
||||
|
||||
when(scriptEngineManager.createScriptEngine(eq(SCRIPT_LANGUAGE), any())).thenReturn(scriptEngineContainer);
|
||||
when(scriptEngineManager.isSupported(anyString()))
|
||||
@ -77,7 +78,7 @@ public class ScriptTransformationServiceTest {
|
||||
when(scriptEngine.eval(SCRIPT)).thenReturn("output");
|
||||
when(scriptEngine.getContext()).thenReturn(scriptContext);
|
||||
|
||||
when(transformationConfigurationRegistry.get(anyString())).thenAnswer(arguments -> {
|
||||
when(transformationRegistry.get(anyString())).thenAnswer(arguments -> {
|
||||
String scriptUid = arguments.getArgument(0);
|
||||
if (SCRIPT_UID.equals(scriptUid)) {
|
||||
return TRANSFORMATION_CONFIGURATION;
|
||||
@ -120,7 +121,7 @@ public class ScriptTransformationServiceTest {
|
||||
service.transform(SCRIPT_LANGUAGE + ":" + SCRIPT_UID, "input");
|
||||
service.transform(SCRIPT_LANGUAGE + ":" + SCRIPT_UID, "input");
|
||||
|
||||
verify(transformationConfigurationRegistry).get(SCRIPT_UID);
|
||||
verify(transformationRegistry).get(SCRIPT_UID);
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -129,7 +130,7 @@ public class ScriptTransformationServiceTest {
|
||||
service.updated(TRANSFORMATION_CONFIGURATION, TRANSFORMATION_CONFIGURATION);
|
||||
service.transform(SCRIPT_LANGUAGE + ":" + SCRIPT_UID, "input");
|
||||
|
||||
verify(transformationConfigurationRegistry, times(2)).get(SCRIPT_UID);
|
||||
verify(transformationRegistry, times(2)).get(SCRIPT_UID);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -1,40 +0,0 @@
|
||||
/**
|
||||
* 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.io.rest.transform;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.core.transform.TransformationConfiguration;
|
||||
|
||||
/**
|
||||
* The {@link TransformationConfigurationDTO} wraps a {@link TransformationConfiguration}
|
||||
*
|
||||
* @author Jan N. Klug - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class TransformationConfigurationDTO {
|
||||
public String uid;
|
||||
public String label;
|
||||
public String type;
|
||||
public @Nullable String language;
|
||||
public String content;
|
||||
public boolean editable = false;
|
||||
|
||||
public TransformationConfigurationDTO(TransformationConfiguration transformationConfiguration) {
|
||||
this.uid = transformationConfiguration.getUID();
|
||||
this.label = transformationConfiguration.getLabel();
|
||||
this.type = transformationConfiguration.getType();
|
||||
this.content = transformationConfiguration.getContent();
|
||||
this.language = transformationConfiguration.getLanguage();
|
||||
}
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
/**
|
||||
* 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.io.rest.transform;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.core.transform.Transformation;
|
||||
|
||||
/**
|
||||
* The {@link TransformationDTO} wraps a {@link Transformation}
|
||||
*
|
||||
* @author Jan N. Klug - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class TransformationDTO {
|
||||
public String uid;
|
||||
public String label;
|
||||
public String type;
|
||||
public Map<String, String> configuration;
|
||||
public boolean editable = false;
|
||||
|
||||
public TransformationDTO(Transformation transformation) {
|
||||
this.uid = transformation.getUID();
|
||||
this.label = transformation.getLabel();
|
||||
this.type = transformation.getType();
|
||||
this.configuration = transformation.getConfiguration();
|
||||
}
|
||||
}
|
@ -34,10 +34,10 @@ import org.openhab.core.auth.Role;
|
||||
import org.openhab.core.io.rest.RESTConstants;
|
||||
import org.openhab.core.io.rest.RESTResource;
|
||||
import org.openhab.core.io.rest.Stream2JSONInputStream;
|
||||
import org.openhab.core.io.rest.transform.TransformationConfigurationDTO;
|
||||
import org.openhab.core.transform.ManagedTransformationConfigurationProvider;
|
||||
import org.openhab.core.transform.TransformationConfiguration;
|
||||
import org.openhab.core.transform.TransformationConfigurationRegistry;
|
||||
import org.openhab.core.io.rest.transform.TransformationDTO;
|
||||
import org.openhab.core.transform.ManagedTransformationProvider;
|
||||
import org.openhab.core.transform.Transformation;
|
||||
import org.openhab.core.transform.TransformationRegistry;
|
||||
import org.osgi.service.component.annotations.Activate;
|
||||
import org.osgi.service.component.annotations.Component;
|
||||
import org.osgi.service.component.annotations.Reference;
|
||||
@ -59,99 +59,97 @@ import io.swagger.v3.oas.annotations.security.SecurityRequirement;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
|
||||
/**
|
||||
* The {@link TransformationConfigurationResource} is a REST resource for handling transformation configurations
|
||||
* The {@link TransformationResource} is a REST resource for handling transformations
|
||||
*
|
||||
* @author Jan N. Klug - Initial contribution
|
||||
*/
|
||||
@Component(immediate = true)
|
||||
@JaxrsResource
|
||||
@JaxrsName(TransformationConfigurationResource.PATH_TRANSFORMATIONS)
|
||||
@JaxrsName(TransformationResource.PATH_TRANSFORMATIONS)
|
||||
@JaxrsApplicationSelect("(" + JaxrsWhiteboardConstants.JAX_RS_NAME + "=" + RESTConstants.JAX_RS_NAME + ")")
|
||||
@JSONRequired
|
||||
@Path(TransformationConfigurationResource.PATH_TRANSFORMATIONS)
|
||||
@Path(TransformationResource.PATH_TRANSFORMATIONS)
|
||||
@RolesAllowed({ Role.ADMIN })
|
||||
@SecurityRequirement(name = "oauth2", scopes = { "admin" })
|
||||
@Tag(name = TransformationConfigurationResource.PATH_TRANSFORMATIONS)
|
||||
@Tag(name = TransformationResource.PATH_TRANSFORMATIONS)
|
||||
@NonNullByDefault
|
||||
public class TransformationConfigurationResource implements RESTResource {
|
||||
public class TransformationResource implements RESTResource {
|
||||
public static final String PATH_TRANSFORMATIONS = "transformations";
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(TransformationConfigurationResource.class);
|
||||
private final TransformationConfigurationRegistry transformationConfigurationRegistry;
|
||||
private final ManagedTransformationConfigurationProvider managedTransformationConfigurationProvider;
|
||||
private final Logger logger = LoggerFactory.getLogger(TransformationResource.class);
|
||||
private final TransformationRegistry transformationRegistry;
|
||||
private final ManagedTransformationProvider managedTransformationProvider;
|
||||
private @Context @NonNullByDefault({}) UriInfo uriInfo;
|
||||
|
||||
@Activate
|
||||
public TransformationConfigurationResource(
|
||||
final @Reference TransformationConfigurationRegistry transformationConfigurationRegistry,
|
||||
final @Reference ManagedTransformationConfigurationProvider managedTransformationConfigurationProvider) {
|
||||
this.transformationConfigurationRegistry = transformationConfigurationRegistry;
|
||||
this.managedTransformationConfigurationProvider = managedTransformationConfigurationProvider;
|
||||
public TransformationResource(final @Reference TransformationRegistry transformationRegistry,
|
||||
final @Reference ManagedTransformationProvider managedTransformationProvider) {
|
||||
this.transformationRegistry = transformationRegistry;
|
||||
this.managedTransformationProvider = managedTransformationProvider;
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("configurations")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Operation(operationId = "getTransformationConfigurations", summary = "Get a list of all transformation configurations", responses = {
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(array = @ArraySchema(schema = @Schema(implementation = TransformationConfigurationDTO.class)))) })
|
||||
public Response getTransformationConfigurations() {
|
||||
@Operation(operationId = "getTransformations", summary = "Get a list of all transformations", responses = {
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(array = @ArraySchema(schema = @Schema(implementation = TransformationDTO.class)))) })
|
||||
public Response getTransformations() {
|
||||
logger.debug("Received HTTP GET request at '{}'", uriInfo.getPath());
|
||||
Stream<TransformationConfigurationDTO> stream = transformationConfigurationRegistry.stream()
|
||||
.map(TransformationConfigurationDTO::new).peek(c -> c.editable = isEditable(c.uid));
|
||||
Stream<TransformationDTO> stream = transformationRegistry.stream().map(TransformationDTO::new)
|
||||
.peek(c -> c.editable = isEditable(c.uid));
|
||||
return Response.ok(new Stream2JSONInputStream(stream)).build();
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("configurations/{uid}")
|
||||
@Path("{uid}")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Operation(operationId = "getTransformationConfiguration", summary = "Get a single transformation configuration", responses = {
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = TransformationConfiguration.class))),
|
||||
@Operation(operationId = "getTransformation", summary = "Get a single transformation", responses = {
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = Transformation.class))),
|
||||
@ApiResponse(responseCode = "404", description = "Not found") })
|
||||
public Response getTransformationConfiguration(
|
||||
@PathParam("uid") @Parameter(description = "Configuration UID") String uid) {
|
||||
public Response getTransformation(@PathParam("uid") @Parameter(description = "Transformation UID") String uid) {
|
||||
logger.debug("Received HTTP GET request at '{}'", uriInfo.getPath());
|
||||
|
||||
TransformationConfiguration configuration = transformationConfigurationRegistry.get(uid);
|
||||
if (configuration == null) {
|
||||
Transformation transformation = transformationRegistry.get(uid);
|
||||
if (transformation == null) {
|
||||
return Response.status(Response.Status.NOT_FOUND).build();
|
||||
}
|
||||
return Response.ok(configuration).build();
|
||||
TransformationDTO dto = new TransformationDTO(transformation);
|
||||
dto.editable = isEditable(uid);
|
||||
return Response.ok(dto).build();
|
||||
}
|
||||
|
||||
@PUT
|
||||
@Path("configurations/{uid}")
|
||||
@Path("{uid}")
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@Produces(MediaType.TEXT_PLAIN)
|
||||
@Operation(operationId = "putTransformationConfiguration", summary = "Get a single transformation configuration", responses = {
|
||||
@Operation(operationId = "putTransformation", summary = "Put a single transformation", responses = {
|
||||
@ApiResponse(responseCode = "200", description = "OK"),
|
||||
@ApiResponse(responseCode = "400", description = "Bad Request (content missing or invalid)"),
|
||||
@ApiResponse(responseCode = "405", description = "Configuration not editable") })
|
||||
public Response putTransformationConfiguration(
|
||||
@PathParam("uid") @Parameter(description = "Configuration UID") String uid,
|
||||
@Parameter(description = "configuration", required = true) @Nullable TransformationConfigurationDTO newConfiguration) {
|
||||
@ApiResponse(responseCode = "405", description = "Transformation not editable") })
|
||||
public Response putTransformation(@PathParam("uid") @Parameter(description = "Transformation UID") String uid,
|
||||
@Parameter(description = "transformation", required = true) @Nullable TransformationDTO newTransformation) {
|
||||
logger.debug("Received HTTP PUT request at '{}'", uriInfo.getPath());
|
||||
|
||||
TransformationConfiguration oldConfiguration = transformationConfigurationRegistry.get(uid);
|
||||
if (oldConfiguration != null && !isEditable(uid)) {
|
||||
Transformation oldTransformation = transformationRegistry.get(uid);
|
||||
if (oldTransformation != null && !isEditable(uid)) {
|
||||
return Response.status(Response.Status.METHOD_NOT_ALLOWED).build();
|
||||
}
|
||||
|
||||
if (newConfiguration == null) {
|
||||
if (newTransformation == null) {
|
||||
return Response.status(Response.Status.BAD_REQUEST).entity("Content missing.").build();
|
||||
}
|
||||
|
||||
if (!uid.equals(newConfiguration.uid)) {
|
||||
return Response.status(Response.Status.BAD_REQUEST).entity("UID of configuration and path not matching.")
|
||||
if (!uid.equals(newTransformation.uid)) {
|
||||
return Response.status(Response.Status.BAD_REQUEST).entity("UID of transformation and path not matching.")
|
||||
.build();
|
||||
}
|
||||
|
||||
TransformationConfiguration transformationConfiguration = new TransformationConfiguration(newConfiguration.uid,
|
||||
newConfiguration.label, newConfiguration.type, newConfiguration.language, newConfiguration.content);
|
||||
Transformation transformation = new Transformation(newTransformation.uid, newTransformation.label,
|
||||
newTransformation.type, newTransformation.configuration);
|
||||
try {
|
||||
if (oldConfiguration != null) {
|
||||
managedTransformationConfigurationProvider.update(transformationConfiguration);
|
||||
if (oldTransformation != null) {
|
||||
managedTransformationProvider.update(transformation);
|
||||
} else {
|
||||
managedTransformationConfigurationProvider.add(transformationConfiguration);
|
||||
managedTransformationProvider.add(transformation);
|
||||
}
|
||||
} catch (IllegalArgumentException e) {
|
||||
return Response.status(Response.Status.BAD_REQUEST).entity(Objects.requireNonNullElse(e.getMessage(), ""))
|
||||
@ -162,18 +160,17 @@ public class TransformationConfigurationResource implements RESTResource {
|
||||
}
|
||||
|
||||
@DELETE
|
||||
@Path("configurations/{uid}")
|
||||
@Path("{uid}")
|
||||
@Produces(MediaType.TEXT_PLAIN)
|
||||
@Operation(operationId = "deleteTransformationConfiguration", summary = "Get a single transformation configuration", responses = {
|
||||
@Operation(operationId = "deleteTransformation", summary = "Get a single transformation", responses = {
|
||||
@ApiResponse(responseCode = "200", description = "OK"),
|
||||
@ApiResponse(responseCode = "404", description = "UID not found"),
|
||||
@ApiResponse(responseCode = "405", description = "Configuration not editable") })
|
||||
public Response deleteTransformationConfiguration(
|
||||
@PathParam("uid") @Parameter(description = "Configuration UID") String uid) {
|
||||
@ApiResponse(responseCode = "405", description = "Transformation not editable") })
|
||||
public Response deleteTransformation(@PathParam("uid") @Parameter(description = "Transformation UID") String uid) {
|
||||
logger.debug("Received HTTP DELETE request at '{}'", uriInfo.getPath());
|
||||
|
||||
TransformationConfiguration oldConfiguration = transformationConfigurationRegistry.get(uid);
|
||||
if (oldConfiguration == null) {
|
||||
Transformation oldTransformation = transformationRegistry.get(uid);
|
||||
if (oldTransformation == null) {
|
||||
return Response.status(Response.Status.NOT_FOUND).build();
|
||||
}
|
||||
|
||||
@ -181,12 +178,12 @@ public class TransformationConfigurationResource implements RESTResource {
|
||||
return Response.status(Response.Status.METHOD_NOT_ALLOWED).build();
|
||||
}
|
||||
|
||||
managedTransformationConfigurationProvider.remove(uid);
|
||||
managedTransformationProvider.remove(uid);
|
||||
|
||||
return Response.ok().build();
|
||||
}
|
||||
|
||||
private boolean isEditable(String uid) {
|
||||
return managedTransformationConfigurationProvider.get(uid) != null;
|
||||
return managedTransformationProvider.get(uid) != null;
|
||||
}
|
||||
}
|
@ -26,6 +26,7 @@ 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.PersistedTransformationTypeMigrator;
|
||||
import org.openhab.core.storage.json.internal.migration.ThingImplTypeMigrator;
|
||||
import org.openhab.core.storage.json.internal.migration.TypeMigrator;
|
||||
import org.osgi.framework.Constants;
|
||||
@ -54,7 +55,9 @@ 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( //
|
||||
"org.openhab.core.thing.Thing", List.of(new BridgeImplTypeMigrator(), new ThingImplTypeMigrator()));
|
||||
"org.openhab.core.thing.Thing", List.of(new BridgeImplTypeMigrator(), new ThingImplTypeMigrator()), //
|
||||
"org.openhab.core.transform.TransformationConfiguration",
|
||||
List.of(new PersistedTransformationTypeMigrator()));
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(JsonStorageService.class);
|
||||
|
||||
|
@ -0,0 +1,49 @@
|
||||
/**
|
||||
* 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;
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
/**
|
||||
* The {@link PersistedTransformationTypeMigrator} implements a {@link TypeMigrator} for stored things
|
||||
*
|
||||
* @author Jan N. Klug - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class PersistedTransformationTypeMigrator implements TypeMigrator {
|
||||
|
||||
@Override
|
||||
public String getOldType() {
|
||||
return "org.openhab.core.transform.ManagedTransformationConfigurationProvider$PersistedTransformationConfiguration";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getNewType() {
|
||||
return "org.openhab.core.transform.ManagedTransformationProvider$PersistedTransformation";
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonElement migrate(JsonElement oldValue) throws TypeMigrationException {
|
||||
JsonObject newValue = oldValue.deepCopy().getAsJsonObject();
|
||||
|
||||
JsonObject configuration = new JsonObject();
|
||||
configuration.addProperty("function", newValue.remove("content").getAsString());
|
||||
newValue.remove("language");
|
||||
newValue.add("configuration", configuration);
|
||||
|
||||
return newValue;
|
||||
}
|
||||
}
|
@ -0,0 +1,100 @@
|
||||
/**
|
||||
* 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 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.PersistedTransformationTypeMigrator;
|
||||
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 PersistedTransformationMigratorTest} contains tests for the ThingImpl and BridgeImpl migrators
|
||||
*
|
||||
* @author Jan N. Klug - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class PersistedTransformationMigratorTest {
|
||||
|
||||
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/transformMigration-input.json"));
|
||||
resultMap = readDatabase(Path.of("src/test/resources/transformMigration-result.json"));
|
||||
|
||||
assertThat(inputMap.size(), is(2));
|
||||
assertThat(resultMap.size(), is(2));
|
||||
}
|
||||
|
||||
private static Stream<Arguments> typeMigrationsSource() {
|
||||
return Stream.of(Arguments.of("config:map:2480cdc5d0:de", new PersistedTransformationTypeMigrator()),
|
||||
Arguments.of("config:script:testTransCfg", new PersistedTransformationTypeMigrator()));
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("typeMigrationsSource")
|
||||
public void typeMigration(String thingUid, TypeMigrator migrator) throws TypeMigrationException {
|
||||
StorageEntry inputEntry = inputMap.get(thingUid);
|
||||
StorageEntry resultEntry = resultMap.get(thingUid);
|
||||
|
||||
assertThat(inputEntry.getEntityClassName(), is(migrator.getOldType()));
|
||||
|
||||
JsonElement entityValue = (JsonElement) inputEntry.getValue();
|
||||
JsonElement newEntityValue = migrator.migrate(entityValue);
|
||||
|
||||
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,21 @@
|
||||
{
|
||||
"config:map:2480cdc5d0:de": {
|
||||
"class": "org.openhab.core.transform.ManagedTransformationConfigurationProvider$PersistedTransformationConfiguration",
|
||||
"value": {
|
||||
"uid": "config:map:2480cdc5d0:de",
|
||||
"label": "MAP DE 2",
|
||||
"type": "map",
|
||||
"language": "de",
|
||||
"content": "dcyxc"
|
||||
}
|
||||
},
|
||||
"config:script:testTransCfg": {
|
||||
"class": "org.openhab.core.transform.ManagedTransformationConfigurationProvider$PersistedTransformationConfiguration",
|
||||
"value": {
|
||||
"uid": "config:script:testTransCfg",
|
||||
"label": "Test Transformation X",
|
||||
"type": "script",
|
||||
"content": "if (input \u003d\u003d \u0027test\u0027) {\n console.log(\"Test!\")\n}"
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
{
|
||||
"config:map:2480cdc5d0:de": {
|
||||
"class": "org.openhab.core.transform.ManagedTransformationProvider$PersistedTransformation",
|
||||
"value": {
|
||||
"uid": "config:map:2480cdc5d0:de",
|
||||
"label": "MAP DE 2",
|
||||
"type": "map",
|
||||
"configuration": { "function": "dcyxc" }
|
||||
}
|
||||
},
|
||||
"config:script:testTransCfg": {
|
||||
"class": "org.openhab.core.transform.ManagedTransformationProvider$PersistedTransformation",
|
||||
"value": {
|
||||
"uid": "config:script:testTransCfg",
|
||||
"label": "Test Transformation X",
|
||||
"type": "script",
|
||||
"configuration": { "function": "if (input \u003d\u003d \u0027test\u0027) {\n console.log(\"Test!\")\n}" }
|
||||
}
|
||||
}
|
||||
}
|
@ -49,7 +49,7 @@ import org.slf4j.LoggerFactory;
|
||||
* under the 'transform' folder within the configuration path. To organize the various
|
||||
* transformations one might use subfolders.
|
||||
*
|
||||
* @deprecated use the {@link TransformationConfigurationRegistry} instead
|
||||
* @deprecated use the {@link TransformationRegistry} instead
|
||||
*
|
||||
* @author Gaël L'hopital - Initial contribution
|
||||
* @author Kai Kreuzer - File caching mechanism
|
||||
|
@ -12,6 +12,8 @@
|
||||
*/
|
||||
package org.openhab.core.transform;
|
||||
|
||||
import static org.openhab.core.transform.Transformation.FUNCTION;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.FileVisitOption;
|
||||
import java.nio.file.Files;
|
||||
@ -35,15 +37,14 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link FileTransformationConfigurationProvider} implements a {@link TransformationConfigurationProvider} for
|
||||
* supporting configurations stored in configuration files
|
||||
* The {@link FileTransformationProvider} implements a {@link TransformationProvider} for
|
||||
* supporting transformations stored in configuration files
|
||||
*
|
||||
* @author Jan N. Klug - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
@Component(service = TransformationConfigurationProvider.class, immediate = true)
|
||||
public class FileTransformationConfigurationProvider extends AbstractWatchService
|
||||
implements TransformationConfigurationProvider {
|
||||
@Component(service = TransformationProvider.class, immediate = true)
|
||||
public class FileTransformationProvider extends AbstractWatchService implements TransformationProvider {
|
||||
private static final WatchEvent.Kind<?>[] WATCH_EVENTS = { StandardWatchEventKinds.ENTRY_CREATE,
|
||||
StandardWatchEventKinds.ENTRY_DELETE, StandardWatchEventKinds.ENTRY_MODIFY };
|
||||
private static final Set<String> IGNORED_EXTENSIONS = Set.of("txt");
|
||||
@ -52,18 +53,18 @@ public class FileTransformationConfigurationProvider extends AbstractWatchServic
|
||||
private static final Path TRANSFORMATION_PATH = Path.of(OpenHAB.getConfigFolder(),
|
||||
TransformationService.TRANSFORM_FOLDER_NAME);
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(FileTransformationConfigurationProvider.class);
|
||||
private final Logger logger = LoggerFactory.getLogger(FileTransformationProvider.class);
|
||||
|
||||
private final Set<ProviderChangeListener<TransformationConfiguration>> listeners = ConcurrentHashMap.newKeySet();
|
||||
private final Map<Path, TransformationConfiguration> transformationConfigurations = new ConcurrentHashMap<>();
|
||||
private final Set<ProviderChangeListener<Transformation>> listeners = ConcurrentHashMap.newKeySet();
|
||||
private final Map<Path, Transformation> transformationConfigurations = new ConcurrentHashMap<>();
|
||||
private final Path transformationPath;
|
||||
|
||||
public FileTransformationConfigurationProvider() {
|
||||
public FileTransformationProvider() {
|
||||
this(TRANSFORMATION_PATH);
|
||||
}
|
||||
|
||||
// constructor package private used for testing
|
||||
FileTransformationConfigurationProvider(Path transformationPath) {
|
||||
FileTransformationProvider(Path transformationPath) {
|
||||
super(transformationPath.toString());
|
||||
this.transformationPath = transformationPath;
|
||||
|
||||
@ -78,17 +79,17 @@ public class FileTransformationConfigurationProvider extends AbstractWatchServic
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addProviderChangeListener(ProviderChangeListener<TransformationConfiguration> listener) {
|
||||
public void addProviderChangeListener(ProviderChangeListener<Transformation> listener) {
|
||||
listeners.add(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeProviderChangeListener(ProviderChangeListener<TransformationConfiguration> listener) {
|
||||
public void removeProviderChangeListener(ProviderChangeListener<Transformation> listener) {
|
||||
listeners.remove(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<TransformationConfiguration> getAll() {
|
||||
public Collection<Transformation> getAll() {
|
||||
return transformationConfigurations.values();
|
||||
}
|
||||
|
||||
@ -109,7 +110,7 @@ public class FileTransformationConfigurationProvider extends AbstractWatchServic
|
||||
|
||||
private void processPath(WatchEvent.Kind<?> kind, Path path) {
|
||||
if (StandardWatchEventKinds.ENTRY_DELETE.equals(kind)) {
|
||||
TransformationConfiguration oldElement = transformationConfigurations.remove(path);
|
||||
Transformation oldElement = transformationConfigurations.remove(path);
|
||||
if (oldElement != null) {
|
||||
logger.trace("Removed configuration from file '{}", path);
|
||||
listeners.forEach(listener -> listener.removed(this, oldElement));
|
||||
@ -135,9 +136,8 @@ public class FileTransformationConfigurationProvider extends AbstractWatchServic
|
||||
String content = new String(Files.readAllBytes(path));
|
||||
String uid = transformationPath.relativize(path).toString();
|
||||
|
||||
TransformationConfiguration newElement = new TransformationConfiguration(uid, uid, fileExtension,
|
||||
m.group("language"), content);
|
||||
TransformationConfiguration oldElement = transformationConfigurations.put(path, newElement);
|
||||
Transformation newElement = new Transformation(uid, uid, fileExtension, Map.of(FUNCTION, content));
|
||||
Transformation oldElement = transformationConfigurations.put(path, newElement);
|
||||
if (oldElement == null) {
|
||||
logger.trace("Added new configuration from file '{}'", path);
|
||||
listeners.forEach(listener -> listener.added(this, newElement));
|
@ -1,114 +0,0 @@
|
||||
/**
|
||||
* 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.transform;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.regex.Matcher;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.core.common.registry.AbstractManagedProvider;
|
||||
import org.openhab.core.storage.StorageService;
|
||||
import org.openhab.core.transform.ManagedTransformationConfigurationProvider.PersistedTransformationConfiguration;
|
||||
import org.osgi.service.component.annotations.Activate;
|
||||
import org.osgi.service.component.annotations.Component;
|
||||
import org.osgi.service.component.annotations.Reference;
|
||||
|
||||
/**
|
||||
* The {@link ManagedTransformationConfigurationProvider} implements a {@link TransformationConfigurationProvider} for
|
||||
* managed configurations stored in a JSON database
|
||||
*
|
||||
* @author Jan N. Klug - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
@Component(service = { TransformationConfigurationProvider.class,
|
||||
ManagedTransformationConfigurationProvider.class }, immediate = true)
|
||||
public class ManagedTransformationConfigurationProvider
|
||||
extends AbstractManagedProvider<TransformationConfiguration, String, PersistedTransformationConfiguration>
|
||||
implements TransformationConfigurationProvider {
|
||||
|
||||
@Activate
|
||||
public ManagedTransformationConfigurationProvider(final @Reference StorageService storageService) {
|
||||
super(storageService);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getStorageName() {
|
||||
return TransformationConfiguration.class.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String keyToString(String key) {
|
||||
return key;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @Nullable TransformationConfiguration toElement(String key,
|
||||
PersistedTransformationConfiguration persistableElement) {
|
||||
return new TransformationConfiguration(persistableElement.uid, persistableElement.label,
|
||||
persistableElement.type, persistableElement.language, persistableElement.content);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PersistedTransformationConfiguration toPersistableElement(TransformationConfiguration element) {
|
||||
return new PersistedTransformationConfiguration(element);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(TransformationConfiguration element) {
|
||||
checkConfiguration(element);
|
||||
super.add(element);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable TransformationConfiguration update(TransformationConfiguration element) {
|
||||
checkConfiguration(element);
|
||||
return super.update(element);
|
||||
}
|
||||
|
||||
private static void checkConfiguration(TransformationConfiguration element) {
|
||||
Matcher matcher = TransformationConfigurationRegistry.CONFIG_UID_PATTERN.matcher(element.getUID());
|
||||
if (!matcher.matches()) {
|
||||
throw new IllegalArgumentException(
|
||||
"The transformation configuration UID '" + element.getUID() + "' is invalid.");
|
||||
}
|
||||
if (!Objects.equals(element.getLanguage(), matcher.group("language"))) {
|
||||
throw new IllegalArgumentException("The transformation configuration UID '" + element.getUID()
|
||||
+ "' contains(misses) a language, but it is not set (set).");
|
||||
}
|
||||
if (!Objects.equals(element.getType(), matcher.group("type"))) {
|
||||
throw new IllegalArgumentException("The transformation configuration UID '" + element.getUID()
|
||||
+ "' is not matching the type '" + element.getType() + "'.");
|
||||
}
|
||||
}
|
||||
|
||||
public static class PersistedTransformationConfiguration {
|
||||
public @NonNullByDefault({}) String uid;
|
||||
public @NonNullByDefault({}) String label;
|
||||
public @NonNullByDefault({}) String type;
|
||||
public @Nullable String language;
|
||||
public @NonNullByDefault({}) String content;
|
||||
|
||||
protected PersistedTransformationConfiguration() {
|
||||
// default constructor for deserialization
|
||||
}
|
||||
|
||||
public PersistedTransformationConfiguration(TransformationConfiguration configuration) {
|
||||
this.uid = configuration.getUID();
|
||||
this.label = configuration.getLabel();
|
||||
this.type = configuration.getType();
|
||||
this.language = configuration.getLanguage();
|
||||
this.content = configuration.getContent();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,106 @@
|
||||
/**
|
||||
* 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.transform;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.regex.Matcher;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.core.common.registry.AbstractManagedProvider;
|
||||
import org.openhab.core.storage.StorageService;
|
||||
import org.openhab.core.transform.ManagedTransformationProvider.PersistedTransformation;
|
||||
import org.osgi.service.component.annotations.Activate;
|
||||
import org.osgi.service.component.annotations.Component;
|
||||
import org.osgi.service.component.annotations.Reference;
|
||||
|
||||
/**
|
||||
* The {@link ManagedTransformationProvider} implements a {@link TransformationProvider} for
|
||||
* managed transformations stored in a JSON database
|
||||
*
|
||||
* @author Jan N. Klug - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
@Component(service = { TransformationProvider.class, ManagedTransformationProvider.class }, immediate = true)
|
||||
public class ManagedTransformationProvider extends
|
||||
AbstractManagedProvider<Transformation, String, PersistedTransformation> implements TransformationProvider {
|
||||
|
||||
@Activate
|
||||
public ManagedTransformationProvider(final @Reference StorageService storageService) {
|
||||
super(storageService);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getStorageName() {
|
||||
return Transformation.class.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String keyToString(String key) {
|
||||
return key;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @Nullable Transformation toElement(String key, PersistedTransformation persistableElement) {
|
||||
return new Transformation(persistableElement.uid, persistableElement.label, persistableElement.type,
|
||||
persistableElement.configuration);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PersistedTransformation toPersistableElement(Transformation element) {
|
||||
return new PersistedTransformation(element);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(Transformation element) {
|
||||
checkConfiguration(element);
|
||||
super.add(element);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Transformation update(Transformation element) {
|
||||
checkConfiguration(element);
|
||||
return super.update(element);
|
||||
}
|
||||
|
||||
private static void checkConfiguration(Transformation element) {
|
||||
Matcher matcher = TransformationRegistry.CONFIG_UID_PATTERN.matcher(element.getUID());
|
||||
if (!matcher.matches()) {
|
||||
throw new IllegalArgumentException(
|
||||
"The transformation configuration UID '" + element.getUID() + "' is invalid.");
|
||||
}
|
||||
if (!Objects.equals(element.getType(), matcher.group("type"))) {
|
||||
throw new IllegalArgumentException("The transformation configuration UID '" + element.getUID()
|
||||
+ "' is not matching the type '" + element.getType() + "'.");
|
||||
}
|
||||
}
|
||||
|
||||
public static class PersistedTransformation {
|
||||
public @NonNullByDefault({}) String uid;
|
||||
public @NonNullByDefault({}) String label;
|
||||
public @NonNullByDefault({}) String type;
|
||||
public @NonNullByDefault({}) Map<String, String> configuration;
|
||||
|
||||
protected PersistedTransformation() {
|
||||
// default constructor for deserialization
|
||||
}
|
||||
|
||||
public PersistedTransformation(Transformation configuration) {
|
||||
this.uid = configuration.getUID();
|
||||
this.label = configuration.getLabel();
|
||||
this.type = configuration.getType();
|
||||
this.configuration = configuration.getConfiguration();
|
||||
}
|
||||
}
|
||||
}
|
@ -12,6 +12,7 @@
|
||||
*/
|
||||
package org.openhab.core.transform;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
@ -19,32 +20,30 @@ import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.core.common.registry.Identifiable;
|
||||
|
||||
/**
|
||||
* The {@link TransformationConfiguration} encapsulates a transformation configuration
|
||||
* The {@link Transformation} encapsulates a transformation configuration
|
||||
*
|
||||
* @author Jan N. Klug - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class TransformationConfiguration implements Identifiable<String> {
|
||||
public class Transformation implements Identifiable<String> {
|
||||
public static final String FUNCTION = "function";
|
||||
|
||||
private final String uid;
|
||||
private final String label;
|
||||
private final String type;
|
||||
private final @Nullable String language;
|
||||
private final String content;
|
||||
private final Map<String, String> configuration;
|
||||
|
||||
/**
|
||||
* @param uid the configuration UID. The format is config:<type>:<name>[:<locale>]. For backward
|
||||
* compatibility also filenames are allowed.
|
||||
* @param type the type of the configuration (file extension for file-based providers)
|
||||
* @param language the language of this configuration (<code>null</code> if not set)
|
||||
* @param content the content of this configuration
|
||||
* @param configuration the configuration (containing e.g. the transformation function)
|
||||
*/
|
||||
public TransformationConfiguration(String uid, String label, String type, @Nullable String language,
|
||||
String content) {
|
||||
public Transformation(String uid, String label, String type, Map<String, String> configuration) {
|
||||
this.uid = uid;
|
||||
this.label = label;
|
||||
this.type = type;
|
||||
this.content = content;
|
||||
this.language = language;
|
||||
this.configuration = configuration;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -60,12 +59,8 @@ public class TransformationConfiguration implements Identifiable<String> {
|
||||
return type;
|
||||
}
|
||||
|
||||
public @Nullable String getLanguage() {
|
||||
return language;
|
||||
}
|
||||
|
||||
public String getContent() {
|
||||
return content;
|
||||
public Map<String, String> getConfiguration() {
|
||||
return configuration;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -76,19 +71,19 @@ public class TransformationConfiguration implements Identifiable<String> {
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
TransformationConfiguration that = (TransformationConfiguration) o;
|
||||
Transformation that = (Transformation) o;
|
||||
return uid.equals(that.uid) && label.equals(that.label) && type.equals(that.type)
|
||||
&& Objects.equals(language, that.language) && content.equals(that.content);
|
||||
&& configuration.equals(that.configuration);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(uid, label, type, language, content);
|
||||
return Objects.hash(uid, label, type, configuration);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "TransformationConfiguration{uid='" + uid + "', label='" + label + "', type='" + type + "', language='"
|
||||
+ language + "', content='" + content + "'}";
|
||||
return "TransformationConfiguration{uid='" + uid + "', label='" + label + "', type='" + type
|
||||
+ "', configuration='" + configuration + "'}";
|
||||
}
|
||||
}
|
@ -16,11 +16,11 @@ import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.core.common.registry.Provider;
|
||||
|
||||
/**
|
||||
* The {@link TransformationConfigurationProvider} is implemented by providers for transformation configurations
|
||||
* The {@link TransformationProvider} is implemented by providers for transformations
|
||||
*
|
||||
* @author Jan N. Klug - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public interface TransformationConfigurationProvider extends Provider<TransformationConfiguration> {
|
||||
public interface TransformationProvider extends Provider<Transformation> {
|
||||
|
||||
}
|
@ -21,29 +21,29 @@ import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.core.common.registry.Registry;
|
||||
|
||||
/**
|
||||
* The {@link TransformationConfigurationRegistry} is the interface for the transformation configuration registry
|
||||
* The {@link TransformationRegistry} is the interface for the transformation registry
|
||||
*
|
||||
* @author Jan N. Klug - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public interface TransformationConfigurationRegistry extends Registry<TransformationConfiguration, String> {
|
||||
public interface TransformationRegistry extends Registry<Transformation, String> {
|
||||
Pattern CONFIG_UID_PATTERN = Pattern.compile("config:(?<type>\\w+):(?<name>\\w+)(:(?<language>\\w+))?");
|
||||
|
||||
/**
|
||||
* Get a localized version of the configuration for a given UID
|
||||
* Get a localized version of the transformation for a given UID
|
||||
*
|
||||
* @param uid the configuration UID
|
||||
* @param locale a locale (system locale is used if <code>null</code>)
|
||||
* @return the requested {@link TransformationConfiguration} (or <code>null</code> if not found).
|
||||
* @return the requested {@link Transformation} (or <code>null</code> if not found).
|
||||
*/
|
||||
@Nullable
|
||||
TransformationConfiguration get(String uid, @Nullable Locale locale);
|
||||
Transformation get(String uid, @Nullable Locale locale);
|
||||
|
||||
/**
|
||||
* Get all configurations which match the given types
|
||||
* Get all transformations which match the given types
|
||||
*
|
||||
* @param types a {@link Collection} of configuration types
|
||||
* @return a {@link Collection} of {@link TransformationConfiguration}s
|
||||
* @return a {@link Collection} of {@link Transformation}s
|
||||
*/
|
||||
Collection<TransformationConfiguration> getConfigurations(Collection<String> types);
|
||||
Collection<Transformation> getTransformations(Collection<String> types);
|
||||
}
|
@ -24,10 +24,10 @@ import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.core.common.registry.AbstractRegistry;
|
||||
import org.openhab.core.common.registry.Provider;
|
||||
import org.openhab.core.i18n.LocaleProvider;
|
||||
import org.openhab.core.transform.ManagedTransformationConfigurationProvider;
|
||||
import org.openhab.core.transform.TransformationConfiguration;
|
||||
import org.openhab.core.transform.TransformationConfigurationProvider;
|
||||
import org.openhab.core.transform.TransformationConfigurationRegistry;
|
||||
import org.openhab.core.transform.ManagedTransformationProvider;
|
||||
import org.openhab.core.transform.Transformation;
|
||||
import org.openhab.core.transform.TransformationProvider;
|
||||
import org.openhab.core.transform.TransformationRegistry;
|
||||
import org.osgi.service.component.annotations.Activate;
|
||||
import org.osgi.service.component.annotations.Component;
|
||||
import org.osgi.service.component.annotations.Reference;
|
||||
@ -35,30 +35,29 @@ import org.osgi.service.component.annotations.ReferenceCardinality;
|
||||
import org.osgi.service.component.annotations.ReferencePolicy;
|
||||
|
||||
/**
|
||||
* The {@link TransformationConfigurationRegistryImpl} implements the {@link TransformationConfigurationRegistry}
|
||||
* The {@link TransformationRegistryImpl} implements the {@link TransformationRegistry}
|
||||
*
|
||||
* @author Jan N. Klug - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
@Component(immediate = true)
|
||||
public class TransformationConfigurationRegistryImpl
|
||||
extends AbstractRegistry<TransformationConfiguration, String, TransformationConfigurationProvider>
|
||||
implements TransformationConfigurationRegistry {
|
||||
public class TransformationRegistryImpl extends AbstractRegistry<Transformation, String, TransformationProvider>
|
||||
implements TransformationRegistry {
|
||||
private static final Pattern FILENAME_PATTERN = Pattern
|
||||
.compile("(?<filename>.+)(_(?<language>[a-z]{2}))?\\.(?<extension>[^.]*)$");
|
||||
|
||||
private final LocaleProvider localeProvider;
|
||||
|
||||
@Activate
|
||||
public TransformationConfigurationRegistryImpl(@Reference LocaleProvider localeProvider) {
|
||||
super(TransformationConfigurationProvider.class);
|
||||
public TransformationRegistryImpl(@Reference LocaleProvider localeProvider) {
|
||||
super(TransformationProvider.class);
|
||||
|
||||
this.localeProvider = localeProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable TransformationConfiguration get(String uid, @Nullable Locale locale) {
|
||||
TransformationConfiguration configuration = null;
|
||||
public @Nullable Transformation get(String uid, @Nullable Locale locale) {
|
||||
Transformation configuration = null;
|
||||
|
||||
String language = Objects.requireNonNullElse(locale, localeProvider.getLocale()).getLanguage();
|
||||
Matcher uidMatcher = CONFIG_UID_PATTERN.matcher(uid);
|
||||
@ -82,21 +81,21 @@ public class TransformationConfigurationRegistryImpl
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<TransformationConfiguration> getConfigurations(Collection<String> types) {
|
||||
public Collection<Transformation> getTransformations(Collection<String> types) {
|
||||
return getAll().stream().filter(e -> types.contains(e.getType())).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.OPTIONAL, policy = ReferencePolicy.DYNAMIC)
|
||||
protected void setManagedProvider(ManagedTransformationConfigurationProvider provider) {
|
||||
protected void setManagedProvider(ManagedTransformationProvider provider) {
|
||||
super.setManagedProvider(provider);
|
||||
}
|
||||
|
||||
protected void unsetManagedProvider(ManagedTransformationConfigurationProvider provider) {
|
||||
protected void unsetManagedProvider(ManagedTransformationProvider provider) {
|
||||
super.unsetManagedProvider(provider);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addProvider(Provider<TransformationConfiguration> provider) {
|
||||
protected void addProvider(Provider<Transformation> provider) {
|
||||
// overridden to make method available for testing
|
||||
super.addProvider(provider);
|
||||
}
|
@ -18,6 +18,7 @@ import static org.hamcrest.Matchers.hasItem;
|
||||
import static org.hamcrest.Matchers.not;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.openhab.core.transform.Transformation.FUNCTION;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
@ -26,6 +27,7 @@ import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.StandardWatchEventKinds;
|
||||
import java.nio.file.WatchEvent;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNull;
|
||||
@ -42,27 +44,27 @@ import org.mockito.quality.Strictness;
|
||||
import org.openhab.core.common.registry.ProviderChangeListener;
|
||||
|
||||
/**
|
||||
* The {@link FileTransformationConfigurationProviderTest} includes tests for the
|
||||
* {@link FileTransformationConfigurationProvider}
|
||||
* The {@link FileTransformationProviderTest} includes tests for the
|
||||
* {@link FileTransformationProvider}
|
||||
*
|
||||
* @author Jan N. Klug - Initial contribution
|
||||
*/
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
@MockitoSettings(strictness = Strictness.LENIENT)
|
||||
@NonNullByDefault
|
||||
public class FileTransformationConfigurationProviderTest {
|
||||
public class FileTransformationProviderTest {
|
||||
private static final String FOO_TYPE = "foo";
|
||||
private static final String INITIAL_CONTENT = "initial";
|
||||
private static final String INITIAL_FILENAME = INITIAL_CONTENT + "." + FOO_TYPE;
|
||||
private static final TransformationConfiguration INITIAL_CONFIGURATION = new TransformationConfiguration(
|
||||
INITIAL_FILENAME, INITIAL_FILENAME, FOO_TYPE, null, INITIAL_CONTENT);
|
||||
private static final Transformation INITIAL_CONFIGURATION = new Transformation(INITIAL_FILENAME, INITIAL_FILENAME,
|
||||
FOO_TYPE, Map.of(FUNCTION, INITIAL_CONTENT));
|
||||
private static final String ADDED_CONTENT = "added";
|
||||
private static final String ADDED_FILENAME = ADDED_CONTENT + "." + FOO_TYPE;
|
||||
|
||||
private @Mock @NonNullByDefault({}) WatchEvent<String> watchEventMock;
|
||||
private @Mock @NonNullByDefault({}) ProviderChangeListener<@NonNull TransformationConfiguration> listenerMock;
|
||||
private @Mock @NonNullByDefault({}) ProviderChangeListener<@NonNull Transformation> listenerMock;
|
||||
|
||||
private @NonNullByDefault({}) FileTransformationConfigurationProvider provider;
|
||||
private @NonNullByDefault({}) FileTransformationProvider provider;
|
||||
private @NonNullByDefault({}) Path targetPath;
|
||||
|
||||
@BeforeEach
|
||||
@ -72,7 +74,7 @@ public class FileTransformationConfigurationProviderTest {
|
||||
// set initial content
|
||||
Files.write(targetPath.resolve(INITIAL_FILENAME), INITIAL_CONTENT.getBytes(StandardCharsets.UTF_8));
|
||||
|
||||
provider = new FileTransformationConfigurationProvider(targetPath);
|
||||
provider = new FileTransformationProvider(targetPath);
|
||||
provider.addProviderChangeListener(listenerMock);
|
||||
}
|
||||
|
||||
@ -95,8 +97,8 @@ public class FileTransformationConfigurationProviderTest {
|
||||
Path path = targetPath.resolve(ADDED_FILENAME);
|
||||
|
||||
Files.write(path, ADDED_CONTENT.getBytes(StandardCharsets.UTF_8));
|
||||
TransformationConfiguration addedConfiguration = new TransformationConfiguration(ADDED_FILENAME, ADDED_FILENAME,
|
||||
FOO_TYPE, null, ADDED_CONTENT);
|
||||
Transformation addedConfiguration = new Transformation(ADDED_FILENAME, ADDED_FILENAME, FOO_TYPE,
|
||||
Map.of(FUNCTION, ADDED_CONTENT));
|
||||
|
||||
provider.processWatchEvent(watchEventMock, StandardWatchEventKinds.ENTRY_CREATE, path);
|
||||
|
||||
@ -109,8 +111,8 @@ public class FileTransformationConfigurationProviderTest {
|
||||
public void testUpdatingConfigurationIsPropagated() throws IOException {
|
||||
Path path = targetPath.resolve(INITIAL_FILENAME);
|
||||
Files.write(path, "updated".getBytes(StandardCharsets.UTF_8));
|
||||
TransformationConfiguration updatedConfiguration = new TransformationConfiguration(INITIAL_FILENAME,
|
||||
INITIAL_FILENAME, FOO_TYPE, null, "updated");
|
||||
Transformation updatedConfiguration = new Transformation(INITIAL_FILENAME, INITIAL_FILENAME, FOO_TYPE,
|
||||
Map.of(FUNCTION, "updated"));
|
||||
|
||||
provider.processWatchEvent(watchEventMock, StandardWatchEventKinds.ENTRY_MODIFY, path);
|
||||
|
||||
@ -136,8 +138,7 @@ public class FileTransformationConfigurationProviderTest {
|
||||
|
||||
Files.write(path, INITIAL_CONTENT.getBytes(StandardCharsets.UTF_8));
|
||||
|
||||
TransformationConfiguration expected = new TransformationConfiguration(fileName, fileName, FOO_TYPE, "de",
|
||||
INITIAL_CONTENT);
|
||||
Transformation expected = new Transformation(fileName, fileName, FOO_TYPE, Map.of(FUNCTION, INITIAL_CONTENT));
|
||||
|
||||
provider.processWatchEvent(watchEventMock, StandardWatchEventKinds.ENTRY_CREATE, path);
|
||||
assertThat(provider.getAll(), hasItem(expected));
|
@ -15,6 +15,9 @@ package org.openhab.core.transform;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.openhab.core.transform.Transformation.FUNCTION;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNull;
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
@ -30,35 +33,35 @@ import org.openhab.core.common.registry.ProviderChangeListener;
|
||||
import org.openhab.core.test.storage.VolatileStorageService;
|
||||
|
||||
/**
|
||||
* The {@link ManagedTransformationConfigurationProviderTest} includes tests for the
|
||||
* {@link org.openhab.core.transform.ManagedTransformationConfigurationProvider}
|
||||
* The {@link ManagedTransformationProviderTest} includes tests for the
|
||||
* {@link ManagedTransformationProvider}
|
||||
*
|
||||
* @author Jan N. Klug - Initial contribution
|
||||
*/
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
@MockitoSettings(strictness = Strictness.LENIENT)
|
||||
@NonNullByDefault
|
||||
public class ManagedTransformationConfigurationProviderTest {
|
||||
public class ManagedTransformationProviderTest {
|
||||
|
||||
private @Mock @NonNullByDefault({}) ProviderChangeListener<@NonNull TransformationConfiguration> listenerMock;
|
||||
private @Mock @NonNullByDefault({}) ProviderChangeListener<@NonNull Transformation> listenerMock;
|
||||
|
||||
private @NonNullByDefault({}) ManagedTransformationConfigurationProvider provider;
|
||||
private @NonNullByDefault({}) ManagedTransformationProvider provider;
|
||||
|
||||
@BeforeEach
|
||||
public void setup() {
|
||||
VolatileStorageService storageService = new VolatileStorageService();
|
||||
provider = new ManagedTransformationConfigurationProvider(storageService);
|
||||
provider = new ManagedTransformationProvider(storageService);
|
||||
provider.addProviderChangeListener(listenerMock);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidConfigurationsAreAdded() {
|
||||
TransformationConfiguration withoutLanguage = new TransformationConfiguration("config:foo:identifier", "",
|
||||
"foo", null, "content");
|
||||
Transformation withoutLanguage = new Transformation("config:foo:identifier", "", "foo",
|
||||
Map.of(FUNCTION, "content"));
|
||||
provider.add(withoutLanguage);
|
||||
|
||||
TransformationConfiguration withLanguage = new TransformationConfiguration("config:foo:identifier:de", "",
|
||||
"foo", "de", "content");
|
||||
Transformation withLanguage = new Transformation("config:foo:identifier:de", "", "foo",
|
||||
Map.of(FUNCTION, "content"));
|
||||
provider.add(withLanguage);
|
||||
|
||||
Mockito.verify(listenerMock).added(provider, withoutLanguage);
|
||||
@ -67,10 +70,10 @@ public class ManagedTransformationConfigurationProviderTest {
|
||||
|
||||
@Test
|
||||
public void testValidConfigurationsIsUpdated() {
|
||||
TransformationConfiguration configuration = new TransformationConfiguration("config:foo:identifier", "", "foo",
|
||||
null, "content");
|
||||
TransformationConfiguration updatedConfiguration = new TransformationConfiguration("config:foo:identifier", "",
|
||||
"foo", null, "updated");
|
||||
Transformation configuration = new Transformation("config:foo:identifier", "", "foo",
|
||||
Map.of(FUNCTION, "content"));
|
||||
Transformation updatedConfiguration = new Transformation("config:foo:identifier", "", "foo",
|
||||
Map.of(FUNCTION, "updated"));
|
||||
|
||||
provider.add(configuration);
|
||||
provider.update(updatedConfiguration);
|
||||
@ -81,45 +84,27 @@ public class ManagedTransformationConfigurationProviderTest {
|
||||
|
||||
@Test
|
||||
public void testUidFormatValidation() {
|
||||
TransformationConfiguration inValidUid = new TransformationConfiguration("invalid:foo:identifier", "", "foo",
|
||||
null, "content");
|
||||
Transformation inValidUid = new Transformation("invalid:foo:identifier", "", "foo",
|
||||
Map.of(FUNCTION, "content"));
|
||||
|
||||
assertThrows(IllegalArgumentException.class, () -> provider.add(inValidUid));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLanguageValidations() {
|
||||
TransformationConfiguration languageMissingInUid = new TransformationConfiguration("config:foo:identifier", "",
|
||||
"foo", "de", "content");
|
||||
|
||||
assertThrows(IllegalArgumentException.class, () -> provider.add(languageMissingInUid));
|
||||
|
||||
TransformationConfiguration languageMissingInConfiguration = new TransformationConfiguration(
|
||||
"config:foo:identifier:de", "", "foo", null, "content");
|
||||
|
||||
assertThrows(IllegalArgumentException.class, () -> provider.add(languageMissingInConfiguration));
|
||||
|
||||
TransformationConfiguration languageNotMatching = new TransformationConfiguration("config:foo:identifier:en",
|
||||
"", "foo", "de", "content");
|
||||
|
||||
assertThrows(IllegalArgumentException.class, () -> provider.add(languageNotMatching));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTypeValidation() {
|
||||
TransformationConfiguration typeNotMatching = new TransformationConfiguration("config:foo:identifier", "",
|
||||
"bar", null, "content");
|
||||
Transformation typeNotMatching = new Transformation("config:foo:identifier", "", "bar",
|
||||
Map.of(FUNCTION, "content"));
|
||||
|
||||
assertThrows(IllegalArgumentException.class, () -> provider.add(typeNotMatching));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSerializationDeserializationResultsInSameConfiguration() {
|
||||
TransformationConfiguration configuration = new TransformationConfiguration("config:foo:identifier", "", "foo",
|
||||
null, "content");
|
||||
Transformation configuration = new Transformation("config:foo:identifier", "", "foo",
|
||||
Map.of(FUNCTION, "content"));
|
||||
provider.add(configuration);
|
||||
|
||||
TransformationConfiguration configuration1 = provider.get("config:foo:identifier");
|
||||
Transformation configuration1 = provider.get("config:foo:identifier");
|
||||
|
||||
assertThat(configuration, is(configuration1));
|
||||
}
|
@ -14,8 +14,10 @@ package org.openhab.core.transform.internal;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.openhab.core.transform.Transformation.FUNCTION;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
@ -27,54 +29,54 @@ import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import org.mockito.junit.jupiter.MockitoSettings;
|
||||
import org.mockito.quality.Strictness;
|
||||
import org.openhab.core.i18n.LocaleProvider;
|
||||
import org.openhab.core.transform.ManagedTransformationConfigurationProvider;
|
||||
import org.openhab.core.transform.TransformationConfiguration;
|
||||
import org.openhab.core.transform.ManagedTransformationProvider;
|
||||
import org.openhab.core.transform.Transformation;
|
||||
|
||||
/**
|
||||
* The {@link TransformationConfigurationRegistryImplTest} includes tests for the
|
||||
* {@link TransformationConfigurationRegistryImpl}
|
||||
* The {@link TransformationRegistryImplTest} includes tests for the
|
||||
* {@link TransformationRegistryImpl}
|
||||
*
|
||||
* @author Jan N. Klug - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
@MockitoSettings(strictness = Strictness.LENIENT)
|
||||
public class TransformationConfigurationRegistryImplTest {
|
||||
public class TransformationRegistryImplTest {
|
||||
private static final String SERVICE = "foo";
|
||||
|
||||
private static final String MANAGED_WITHOUT_LANGUAGE_UID = "config:" + SERVICE + ":managed";
|
||||
private static final String MANAGED_WITH_EN_LANGUAGE_UID = "config:" + SERVICE + ":managed:en";
|
||||
private static final String MANAGED_WITH_DE_LANGUAGE_UID = "config:" + SERVICE + ":managed:de";
|
||||
|
||||
private static final TransformationConfiguration MANAGED_WITHOUT_LANGUAGE = new TransformationConfiguration(
|
||||
MANAGED_WITHOUT_LANGUAGE_UID, "", SERVICE, null, MANAGED_WITHOUT_LANGUAGE_UID);
|
||||
private static final TransformationConfiguration MANAGED_WITH_EN_LANGUAGE = new TransformationConfiguration(
|
||||
MANAGED_WITH_EN_LANGUAGE_UID, "", SERVICE, "en", MANAGED_WITH_EN_LANGUAGE_UID);
|
||||
private static final TransformationConfiguration MANAGED_WITH_DE_LANGUAGE = new TransformationConfiguration(
|
||||
MANAGED_WITH_DE_LANGUAGE_UID, "", SERVICE, "de", MANAGED_WITH_DE_LANGUAGE_UID);
|
||||
private static final Transformation MANAGED_WITHOUT_LANGUAGE = new Transformation(MANAGED_WITHOUT_LANGUAGE_UID, "",
|
||||
SERVICE, Map.of(FUNCTION, MANAGED_WITHOUT_LANGUAGE_UID));
|
||||
private static final Transformation MANAGED_WITH_EN_LANGUAGE = new Transformation(MANAGED_WITH_EN_LANGUAGE_UID, "",
|
||||
SERVICE, Map.of(FUNCTION, MANAGED_WITH_EN_LANGUAGE_UID));
|
||||
private static final Transformation MANAGED_WITH_DE_LANGUAGE = new Transformation(MANAGED_WITH_DE_LANGUAGE_UID, "",
|
||||
SERVICE, Map.of(FUNCTION, MANAGED_WITH_DE_LANGUAGE_UID));
|
||||
|
||||
private static final String FILE_WITHOUT_LANGUAGE_UID = "foo/FILE." + SERVICE;
|
||||
private static final String FILE_WITH_EN_LANGUAGE_UID = "foo/FILE_en." + SERVICE;
|
||||
private static final String FILE_WITH_DE_LANGUAGE_UID = "foo/FILE_de." + SERVICE;
|
||||
|
||||
private static final TransformationConfiguration FILE_WITHOUT_LANGUAGE = new TransformationConfiguration(
|
||||
FILE_WITHOUT_LANGUAGE_UID, "", SERVICE, null, FILE_WITHOUT_LANGUAGE_UID);
|
||||
private static final TransformationConfiguration FILE_WITH_EN_LANGUAGE = new TransformationConfiguration(
|
||||
FILE_WITH_EN_LANGUAGE_UID, "", SERVICE, "en", FILE_WITH_EN_LANGUAGE_UID);
|
||||
private static final TransformationConfiguration FILE_WITH_DE_LANGUAGE = new TransformationConfiguration(
|
||||
FILE_WITH_DE_LANGUAGE_UID, "", SERVICE, "de", FILE_WITH_DE_LANGUAGE_UID);
|
||||
private static final Transformation FILE_WITHOUT_LANGUAGE = new Transformation(FILE_WITHOUT_LANGUAGE_UID, "",
|
||||
SERVICE, Map.of(FUNCTION, FILE_WITHOUT_LANGUAGE_UID));
|
||||
private static final Transformation FILE_WITH_EN_LANGUAGE = new Transformation(FILE_WITH_EN_LANGUAGE_UID, "",
|
||||
SERVICE, Map.of(FUNCTION, FILE_WITH_EN_LANGUAGE_UID));
|
||||
private static final Transformation FILE_WITH_DE_LANGUAGE = new Transformation(FILE_WITH_DE_LANGUAGE_UID, "",
|
||||
SERVICE, Map.of(FUNCTION, FILE_WITH_DE_LANGUAGE_UID));
|
||||
|
||||
private @Mock @NonNullByDefault({}) LocaleProvider localeProviderMock;
|
||||
|
||||
private @Mock @NonNullByDefault({}) ManagedTransformationConfigurationProvider providerMock;
|
||||
private @Mock @NonNullByDefault({}) ManagedTransformationProvider providerMock;
|
||||
|
||||
private @NonNullByDefault({}) TransformationConfigurationRegistryImpl registry;
|
||||
private @NonNullByDefault({}) TransformationRegistryImpl registry;
|
||||
|
||||
@BeforeEach
|
||||
public void setup() {
|
||||
Mockito.when(localeProviderMock.getLocale()).thenReturn(Locale.US);
|
||||
|
||||
registry = new TransformationConfigurationRegistryImpl(localeProviderMock);
|
||||
registry = new TransformationRegistryImpl(localeProviderMock);
|
||||
registry.addProvider(providerMock);
|
||||
registry.added(providerMock, MANAGED_WITHOUT_LANGUAGE);
|
||||
registry.added(providerMock, MANAGED_WITH_EN_LANGUAGE);
|
Loading…
Reference in New Issue
Block a user