diff --git a/bundles/org.openhab.persistence.dynamodb/src/main/java/org/openhab/persistence/dynamodb/internal/DynamoDBPersistenceService.java b/bundles/org.openhab.persistence.dynamodb/src/main/java/org/openhab/persistence/dynamodb/internal/DynamoDBPersistenceService.java index 5e58c2e5d..35ad9f4c5 100644 --- a/bundles/org.openhab.persistence.dynamodb/src/main/java/org/openhab/persistence/dynamodb/internal/DynamoDBPersistenceService.java +++ b/bundles/org.openhab.persistence.dynamodb/src/main/java/org/openhab/persistence/dynamodb/internal/DynamoDBPersistenceService.java @@ -36,6 +36,7 @@ import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.openhab.core.common.ThreadPoolManager; import org.openhab.core.config.core.ConfigurableService; +import org.openhab.core.i18n.UnitProvider; import org.openhab.core.items.GenericItem; import org.openhab.core.items.GroupItem; import org.openhab.core.items.Item; @@ -103,7 +104,8 @@ public class DynamoDBPersistenceService implements QueryablePersistenceService { private static final String DYNAMODB_THREADPOOL_NAME = "dynamodbPersistenceService"; - private ItemRegistry itemRegistry; + private final ItemRegistry itemRegistry; + private final UnitProvider unitProvider; private @Nullable DynamoDbEnhancedAsyncClient client; private @Nullable DynamoDbAsyncClient lowLevelClient; private static final Logger logger = LoggerFactory.getLogger(DynamoDBPersistenceService.class); @@ -131,15 +133,19 @@ public class DynamoDBPersistenceService implements QueryablePersistenceService { } @Activate - public DynamoDBPersistenceService(final @Reference ItemRegistry itemRegistry) { + public DynamoDBPersistenceService(final @Reference ItemRegistry itemRegistry, + final @Reference UnitProvider unitProvider) { this.itemRegistry = itemRegistry; + this.unitProvider = unitProvider; } /** * For tests */ - DynamoDBPersistenceService(final ItemRegistry itemRegistry, @Nullable URI endpointOverride) { + DynamoDBPersistenceService(final ItemRegistry itemRegistry, final UnitProvider unitProvider, + @Nullable URI endpointOverride) { this.itemRegistry = itemRegistry; + this.unitProvider = unitProvider; this.endpointOverride = endpointOverride; } @@ -414,7 +420,7 @@ public class DynamoDBPersistenceService implements QueryablePersistenceService { item.getClass().getSimpleName(), dtoClass.getSimpleName(), tableName); QueryEnhancedRequest queryExpression = DynamoDBQueryUtils.createQueryExpression(dtoClass, - localTableNameResolver.getTableSchema(), item, filter); + localTableNameResolver.getTableSchema(), item, filter, unitProvider); CompletableFuture>> itemsFuture = new CompletableFuture<>(); final SdkPublisher> itemPublisher = table.query(queryExpression).items(); @@ -523,7 +529,7 @@ public class DynamoDBPersistenceService implements QueryablePersistenceService { // We do not want to rely item.state since async context below can execute much later. // We 'copy' the item for local use. copyItem also normalizes the unit with NumberItems. - final GenericItem copiedItem = copyItem(itemTemplate, item, effectiveName, null); + final GenericItem copiedItem = copyItem(itemTemplate, item, effectiveName, null, unitProvider); resolveTableSchema().thenAcceptAsync(resolved -> { if (!resolved) { @@ -613,15 +619,18 @@ public class DynamoDBPersistenceService implements QueryablePersistenceService { * @param item item that is used to acquire name and state * @param nameOverride name override for the resulting copy * @param stateOverride state override for the resulting copy + * @param unitProvider the unit provider for number with dimension * @throws IllegalArgumentException when state is QuantityType and not compatible with item */ static GenericItem copyItem(Item itemTemplate, Item item, @Nullable String nameOverride, - @Nullable State stateOverride) { + @Nullable State stateOverride, UnitProvider unitProvider) { final GenericItem copiedItem; try { if (itemTemplate instanceof NumberItem) { - copiedItem = (GenericItem) itemTemplate.getClass().getDeclaredConstructor(String.class, String.class) - .newInstance(itemTemplate.getType(), nameOverride == null ? item.getName() : nameOverride); + copiedItem = (GenericItem) itemTemplate.getClass() + .getDeclaredConstructor(String.class, String.class, UnitProvider.class) + .newInstance(itemTemplate.getType(), nameOverride == null ? item.getName() : nameOverride, + unitProvider); } else { copiedItem = (GenericItem) itemTemplate.getClass().getDeclaredConstructor(String.class) .newInstance(nameOverride == null ? item.getName() : nameOverride); diff --git a/bundles/org.openhab.persistence.dynamodb/src/main/java/org/openhab/persistence/dynamodb/internal/DynamoDBQueryUtils.java b/bundles/org.openhab.persistence.dynamodb/src/main/java/org/openhab/persistence/dynamodb/internal/DynamoDBQueryUtils.java index fa86f9a09..58a0d5cd5 100644 --- a/bundles/org.openhab.persistence.dynamodb/src/main/java/org/openhab/persistence/dynamodb/internal/DynamoDBQueryUtils.java +++ b/bundles/org.openhab.persistence.dynamodb/src/main/java/org/openhab/persistence/dynamodb/internal/DynamoDBQueryUtils.java @@ -17,6 +17,7 @@ import java.time.ZonedDateTime; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; +import org.openhab.core.i18n.UnitProvider; import org.openhab.core.items.GenericItem; import org.openhab.core.items.Item; import org.openhab.core.persistence.FilterCriteria; @@ -45,10 +46,11 @@ public class DynamoDBQueryUtils { * @param item item corresponding to filter * @param filter filter for the query * @return DynamoDBQueryExpression corresponding to the given FilterCriteria + * @param unitProvider the unit provider for number with dimension * @throws IllegalArgumentException when schema is not fully resolved */ public static QueryEnhancedRequest createQueryExpression(Class> dtoClass, - ExpectedTableSchema expectedTableSchema, Item item, FilterCriteria filter) { + ExpectedTableSchema expectedTableSchema, Item item, FilterCriteria filter, UnitProvider unitProvider) { if (!expectedTableSchema.isFullyResolved()) { throw new IllegalArgumentException("Schema not resolved"); } @@ -59,7 +61,7 @@ public class DynamoDBQueryUtils { throw new IllegalArgumentException("Item name not set"); } addFilterbyItemAndTimeFilter(queryBuilder, expectedTableSchema, itemName, filter); - addStateFilter(queryBuilder, expectedTableSchema, item, dtoClass, filter); + addStateFilter(queryBuilder, expectedTableSchema, item, dtoClass, filter, unitProvider); addProjection(dtoClass, expectedTableSchema, queryBuilder); return queryBuilder.build(); } @@ -94,7 +96,7 @@ public class DynamoDBQueryUtils { private static void addStateFilter(QueryEnhancedRequest.Builder queryBuilder, ExpectedTableSchema expectedTableSchema, Item item, Class> dtoClass, - FilterCriteria filter) { + FilterCriteria filter, UnitProvider unitProvider) { final Expression expression; Builder itemStateTypeExpressionBuilder = Expression.builder() .expression(String.format("attribute_exists(#attr)")); @@ -123,7 +125,7 @@ public class DynamoDBQueryUtils { // Following will throw IllegalArgumentException when filter state is not compatible with // item. This is acceptable. GenericItem stateToFind = DynamoDBPersistenceService.copyItem(item, item, filter.getItemName(), - filter.getState()); + filter.getState(), unitProvider); acceptAsDTO(stateToFind, legacy, new DynamoDBItemVisitor<@Nullable Void>() { @Override public @Nullable Void visit(DynamoDBStringItem serialized) { diff --git a/bundles/org.openhab.persistence.dynamodb/src/test/java/org/openhab/persistence/dynamodb/internal/BaseIntegrationTest.java b/bundles/org.openhab.persistence.dynamodb/src/test/java/org/openhab/persistence/dynamodb/internal/BaseIntegrationTest.java index f3e5d38bd..f975a3864 100644 --- a/bundles/org.openhab.persistence.dynamodb/src/test/java/org/openhab/persistence/dynamodb/internal/BaseIntegrationTest.java +++ b/bundles/org.openhab.persistence.dynamodb/src/test/java/org/openhab/persistence/dynamodb/internal/BaseIntegrationTest.java @@ -39,7 +39,6 @@ import org.mockito.Mockito; import org.openhab.core.common.registry.RegistryChangeListener; import org.openhab.core.i18n.UnitProvider; import org.openhab.core.internal.i18n.I18nProviderImpl; -import org.openhab.core.items.GenericItem; import org.openhab.core.items.GroupItem; import org.openhab.core.items.Item; import org.openhab.core.items.ItemNotFoundException; @@ -147,12 +146,12 @@ public class BaseIntegrationTest extends JavaTest { ITEMS.put("dimmer", new DimmerItem("dimmer")); ITEMS.put("number", new NumberItem("number")); - NumberItem temperatureItem = new NumberItem("Number:Temperature", "numberTemperature"); + NumberItem temperatureItem = new NumberItem("Number:Temperature", "numberTemperature", UNIT_PROVIDER); ITEMS.put("numberTemperature", temperatureItem); GroupItem groupTemperature = new GroupItem("groupNumberTemperature", temperatureItem); ITEMS.put("groupNumberTemperature", groupTemperature); - NumberItem dimensionlessItem = new NumberItem("Number:Dimensionless", "numberDimensionless"); + NumberItem dimensionlessItem = new NumberItem("Number:Dimensionless", "numberDimensionless", UNIT_PROVIDER); ITEMS.put("numberDimensionless", dimensionlessItem); GroupItem groupDimensionless = new GroupItem("groupNumberDimensionless", dimensionlessItem); ITEMS.put("groupNumberDimensionless", groupDimensionless); @@ -170,8 +169,6 @@ public class BaseIntegrationTest extends JavaTest { ITEMS.put("location", new LocationItem("location")); ITEMS.put("player_playpause", new PlayerItem("player_playpause")); ITEMS.put("player_rewindfastforward", new PlayerItem("player_rewindfastforward")); - - injectItemServices(); } @BeforeAll @@ -248,7 +245,6 @@ public class BaseIntegrationTest extends JavaTest { if (item == null) { throw new ItemNotFoundException(name); } - injectItemServices(item); return item; } @@ -326,23 +322,12 @@ public class BaseIntegrationTest extends JavaTest { public void removeRegistryHook(RegistryHook hook) { throw new UnsupportedOperationException(); } - }, localEndpointOverride); + }, UNIT_PROVIDER, localEndpointOverride); service.activate(null, config); return service; } - protected static void injectItemServices() { - ITEMS.values().forEach(BaseIntegrationTest::injectItemServices); - } - - protected static void injectItemServices(Item item) { - if (item instanceof GenericItem) { - GenericItem genericItem = (GenericItem) item; - genericItem.setUnitProvider(UNIT_PROVIDER); - } - } - private static Map getConfig(@Nullable Boolean legacy, @Nullable String table, @Nullable String tablePrefix) { Map config = new HashMap<>();