Skip to content

Commit

Permalink
Allow managing persistence configurations and enable filters (openhab…
Browse files Browse the repository at this point in the history
…#2871)

* Allow managing persistence configurations

Signed-off-by: Jan N. Klug <[email protected]>
  • Loading branch information
J-N-K authored May 7, 2023
1 parent 28ec419 commit 2e00efc
Show file tree
Hide file tree
Showing 36 changed files with 2,152 additions and 759 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import java.util.Locale;

import javax.annotation.security.RolesAllowed;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.HeaderParam;
Expand All @@ -33,6 +34,7 @@
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import javax.ws.rs.core.UriInfo;

import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
Expand All @@ -57,7 +59,12 @@
import org.openhab.core.persistence.PersistenceServiceRegistry;
import org.openhab.core.persistence.QueryablePersistenceService;
import org.openhab.core.persistence.dto.ItemHistoryDTO;
import org.openhab.core.persistence.dto.PersistenceServiceConfigurationDTO;
import org.openhab.core.persistence.dto.PersistenceServiceDTO;
import org.openhab.core.persistence.registry.ManagedPersistenceServiceConfigurationProvider;
import org.openhab.core.persistence.registry.PersistenceServiceConfiguration;
import org.openhab.core.persistence.registry.PersistenceServiceConfigurationDTOMapper;
import org.openhab.core.persistence.registry.PersistenceServiceConfigurationRegistry;
import org.openhab.core.types.State;
import org.openhab.core.types.TypeParser;
import org.osgi.service.component.annotations.Activate;
Expand Down Expand Up @@ -114,17 +121,23 @@ public class PersistenceResource implements RESTResource {
private final ItemRegistry itemRegistry;
private final LocaleService localeService;
private final PersistenceServiceRegistry persistenceServiceRegistry;
private final PersistenceServiceConfigurationRegistry persistenceServiceConfigurationRegistry;
private final ManagedPersistenceServiceConfigurationProvider managedPersistenceServiceConfigurationProvider;
private final TimeZoneProvider timeZoneProvider;

@Activate
public PersistenceResource( //
final @Reference ItemRegistry itemRegistry, //
final @Reference LocaleService localeService,
final @Reference PersistenceServiceRegistry persistenceServiceRegistry,
final @Reference PersistenceServiceConfigurationRegistry persistenceServiceConfigurationRegistry,
final @Reference ManagedPersistenceServiceConfigurationProvider managedPersistenceServiceConfigurationProvider,
final @Reference TimeZoneProvider timeZoneProvider) {
this.itemRegistry = itemRegistry;
this.localeService = localeService;
this.persistenceServiceRegistry = persistenceServiceRegistry;
this.persistenceServiceConfigurationRegistry = persistenceServiceConfigurationRegistry;
this.managedPersistenceServiceConfigurationProvider = managedPersistenceServiceConfigurationProvider;
this.timeZoneProvider = timeZoneProvider;
}

Expand All @@ -142,6 +155,96 @@ public Response httpGetPersistenceServices(@Context HttpHeaders headers,
return Response.ok(responseObject).build();
}

@GET
@RolesAllowed({ Role.ADMIN })
@Produces({ MediaType.APPLICATION_JSON })
@Path("{serviceId: [a-zA-Z0-9]+}")
@Operation(operationId = "getPersistenceServiceConfiguration", summary = "Gets a persistence service configuration.", security = {
@SecurityRequirement(name = "oauth2", scopes = { "admin" }) }, responses = {
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = PersistenceServiceConfigurationDTO.class))),
@ApiResponse(responseCode = "404", description = "Service configuration not found.") })
public Response httpGetPersistenceServiceConfiguration(@Context HttpHeaders headers,
@Parameter(description = "Id of the persistence service.") @PathParam("serviceId") String serviceId) {
PersistenceServiceConfiguration configuration = persistenceServiceConfigurationRegistry.get(serviceId);

if (configuration != null) {
PersistenceServiceConfigurationDTO configurationDTO = PersistenceServiceConfigurationDTOMapper
.map(configuration);
configurationDTO.editable = managedPersistenceServiceConfigurationProvider.get(serviceId) != null;
return JSONResponse.createResponse(Status.OK, configurationDTO, null);
} else {
return Response.status(Status.NOT_FOUND).build();
}
}

@PUT
@RolesAllowed({ Role.ADMIN })
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
@Path("{serviceId: [a-zA-Z0-9]+}")
@Operation(operationId = "putPersistenceServiceConfiguration", summary = "Sets a persistence service configuration.", security = {
@SecurityRequirement(name = "oauth2", scopes = { "admin" }) }, responses = {
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = PersistenceServiceConfigurationDTO.class))),
@ApiResponse(responseCode = "201", description = "PersistenceServiceConfiguration created."),
@ApiResponse(responseCode = "400", description = "Payload invalid."),
@ApiResponse(responseCode = "405", description = "PersistenceServiceConfiguration not editable.") })
public Response httpPutPersistenceServiceConfiguration(@Context UriInfo uriInfo, @Context HttpHeaders headers,
@Parameter(description = "Id of the persistence service.") @PathParam("serviceId") String serviceId,
@Parameter(description = "service configuration", required = true) @Nullable PersistenceServiceConfigurationDTO serviceConfigurationDTO) {
if (serviceConfigurationDTO == null) {
return JSONResponse.createErrorResponse(Status.BAD_REQUEST, "Payload must not be null.");
}
if (!serviceId.equals(serviceConfigurationDTO.serviceId)) {
return JSONResponse.createErrorResponse(Status.BAD_REQUEST, "serviceId in payload '"
+ serviceConfigurationDTO.serviceId + "' differs from serviceId in URL '" + serviceId + "'");
}

PersistenceServiceConfiguration persistenceServiceConfiguration;
try {
persistenceServiceConfiguration = PersistenceServiceConfigurationDTOMapper.map(serviceConfigurationDTO);
} catch (IllegalArgumentException e) {
logger.warn("Received HTTP PUT request at '{}' with an invalid payload: '{}'.", uriInfo.getPath(),
e.getMessage());
return JSONResponse.createErrorResponse(Status.BAD_REQUEST, e.getMessage());
}

if (persistenceServiceConfigurationRegistry.get(serviceId) == null) {
managedPersistenceServiceConfigurationProvider.add(persistenceServiceConfiguration);
return JSONResponse.createResponse(Status.CREATED, serviceConfigurationDTO, null);
} else if (managedPersistenceServiceConfigurationProvider.get(serviceId) != null) {
// item already exists as a managed item, update it
managedPersistenceServiceConfigurationProvider.update(persistenceServiceConfiguration);
return JSONResponse.createResponse(Status.OK, serviceConfigurationDTO, null);
} else {
// Configuration exists but cannot be updated
logger.warn("Cannot update existing persistence service configuration '{}', because is not managed.",
serviceId);
return JSONResponse.createErrorResponse(Status.METHOD_NOT_ALLOWED,
"Cannot update non-managed persistence service configuration " + serviceId);
}
}

@DELETE
@RolesAllowed({ Role.ADMIN })
@Path("{serviceId: [a-zA-Z0-9]+}")
@Operation(operationId = "deletePersistenceServiceConfiguration", summary = "Deletes a persistence service configuration.", security = {
@SecurityRequirement(name = "oauth2", scopes = { "admin" }) }, responses = {
@ApiResponse(responseCode = "200", description = "OK"),
@ApiResponse(responseCode = "404", description = "Persistence service configuration not found."),
@ApiResponse(responseCode = "405", description = "Persistence service configuration not editable.") })
public Response httpDeletePersistenceServiceConfiguration(@Context UriInfo uriInfo, @Context HttpHeaders headers,
@Parameter(description = "Id of the persistence service.") @PathParam("serviceId") String serviceId) {
if (persistenceServiceConfigurationRegistry.get(serviceId) == null) {
return Response.status(Status.NOT_FOUND).build();
}

if (managedPersistenceServiceConfigurationProvider.remove(serviceId) == null) {
return Response.status(Status.METHOD_NOT_ALLOWED).build();
} else {
return Response.ok().build();
}
}

@GET
@RolesAllowed({ Role.ADMIN })
@Path("/items")
Expand Down Expand Up @@ -238,7 +341,7 @@ private Response getItemHistoryDTO(@Nullable String serviceId, String itemName,
protected @Nullable ItemHistoryDTO createDTO(@Nullable String serviceId, String itemName,
@Nullable String timeBegin, @Nullable String timeEnd, int pageNumber, int pageLength, boolean boundary) {
// If serviceId is null, then use the default service
PersistenceService service = null;
PersistenceService service;
String effectiveServiceId = serviceId != null ? serviceId : persistenceServiceRegistry.getDefaultId();
service = persistenceServiceRegistry.get(effectiveServiceId);

Expand Down Expand Up @@ -283,9 +386,9 @@ private Response getItemHistoryDTO(@Nullable String serviceId, String itemName,
}

Iterable<HistoricItem> result;
State state = null;
State state;

Long quantity = 0l;
long quantity = 0L;

ItemHistoryDTO dto = new ItemHistoryDTO();
dto.name = itemName;
Expand Down Expand Up @@ -363,7 +466,7 @@ private Response getItemHistoryDTO(@Nullable String serviceId, String itemName,
/**
* Gets a list of persistence services currently configured in the system
*
* @return list of persistence services as {@link ServiceBean}
* @return list of persistence services
*/
private List<PersistenceServiceDTO> getPersistenceServiceList(Locale locale) {
List<PersistenceServiceDTO> dtoList = new ArrayList<>();
Expand All @@ -389,7 +492,7 @@ private List<PersistenceServiceDTO> getPersistenceServiceList(Locale locale) {

private Response getServiceItemList(@Nullable String serviceId) {
// If serviceId is null, then use the default service
PersistenceService service = null;
PersistenceService service;
if (serviceId == null) {
service = persistenceServiceRegistry.getDefault();
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@
import org.openhab.core.persistence.QueryablePersistenceService;
import org.openhab.core.persistence.dto.ItemHistoryDTO;
import org.openhab.core.persistence.dto.ItemHistoryDTO.HistoryDataBean;
import org.openhab.core.persistence.registry.ManagedPersistenceServiceConfigurationProvider;
import org.openhab.core.persistence.registry.PersistenceServiceConfigurationRegistry;
import org.openhab.core.types.State;

/**
Expand All @@ -58,11 +60,14 @@ public class PersistenceResourceTest {
private @Mock @NonNullByDefault({}) ItemRegistry itemRegistryMock;
private @Mock @NonNullByDefault({}) LocaleService localeServiceMock;
private @Mock @NonNullByDefault({}) PersistenceServiceRegistry persistenceServiceRegistryMock;
private @Mock @NonNullByDefault({}) PersistenceServiceConfigurationRegistry persistenceServiceConfigurationRegistryMock;
private @Mock @NonNullByDefault({}) ManagedPersistenceServiceConfigurationProvider managedPersistenceServiceConfigurationProviderMock;
private @Mock @NonNullByDefault({}) TimeZoneProvider timeZoneProviderMock;

@BeforeEach
public void beforeEach() {
pResource = new PersistenceResource(itemRegistryMock, localeServiceMock, persistenceServiceRegistryMock,
persistenceServiceConfigurationRegistryMock, managedPersistenceServiceConfigurationProviderMock,
timeZoneProviderMock);

int startValue = 2016;
Expand Down
2 changes: 2 additions & 0 deletions bundles/org.openhab.core.model.persistence/bnd.bnd
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ Import-Package: \
org.openhab.core.persistence,\
org.openhab.core.persistence.config,\
org.openhab.core.persistence.strategy,\
org.openhab.core.persistence.filter,\
org.openhab.core.persistence.registry,\
org.openhab.core.types,\
org.openhab.core.model.core,\
com.google.common.*;version="14",\
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ FilterDetails:
;

ThresholdFilter:
'>' value=DECIMAL percent?='%'
'>' value=DECIMAL unit=STRING
;

TimeFilter:
Expand Down
Loading

0 comments on commit 2e00efc

Please sign in to comment.