From 32b0a4025225b8befb905e32d0cc6401cf2c72d6 Mon Sep 17 00:00:00 2001 From: Mark Herwege Date: Thu, 20 Feb 2025 07:53:28 +0100 Subject: [PATCH] Persistence alias support (#18286) Signed-off-by: Mark Herwege --- .../internal/AbstractDynamoDBItem.java | 2 +- .../internal/DynamoDBPersistenceService.java | 7 +- .../dynamodb/internal/DynamoDBQueryUtils.java | 6 +- .../influxdb/InfluxDBPersistenceService.java | 34 +++++---- .../internal/FilterCriteriaQueryCreator.java | 6 +- .../internal/InfluxDBMetadataService.java | 5 +- .../influxdb/internal/InfluxDBRepository.java | 6 +- ...fluxDB1FilterCriteriaQueryCreatorImpl.java | 11 +-- .../influx1/InfluxDB1RepositoryImpl.java | 9 +-- ...fluxDB2FilterCriteriaQueryCreatorImpl.java | 9 +-- .../influx2/InfluxDB2RepositoryImpl.java | 6 +- ...luxFilterCriteriaQueryCreatorImplTest.java | 30 ++++---- .../persistence/jdbc/internal/JdbcMapper.java | 9 +-- .../jdbc/internal/JdbcPersistenceService.java | 37 ++++++---- .../jpa/internal/JpaPersistenceService.java | 7 +- .../internal/MongoDBPersistenceService.java | 15 ++-- .../MongoDBPersistenceServiceTest.java | 72 +++++++++++++++---- .../internal/RRD4jPersistenceService.java | 10 ++- .../internal/charts/RRD4jChartServlet.java | 20 ++++-- .../console/RRD4jCommandExtension.java | 20 +++++- 20 files changed, 218 insertions(+), 103 deletions(-) diff --git a/bundles/org.openhab.persistence.dynamodb/src/main/java/org/openhab/persistence/dynamodb/internal/AbstractDynamoDBItem.java b/bundles/org.openhab.persistence.dynamodb/src/main/java/org/openhab/persistence/dynamodb/internal/AbstractDynamoDBItem.java index b84542f6fd3..550b779fb00 100644 --- a/bundles/org.openhab.persistence.dynamodb/src/main/java/org/openhab/persistence/dynamodb/internal/AbstractDynamoDBItem.java +++ b/bundles/org.openhab.persistence.dynamodb/src/main/java/org/openhab/persistence/dynamodb/internal/AbstractDynamoDBItem.java @@ -449,7 +449,7 @@ public abstract class AbstractDynamoDBItem implements DynamoDBItem { if (deserializedState == null) { return null; } - return new DynamoDBHistoricItem(getName(), deserializedState, getTime().toInstant()); + return new DynamoDBHistoricItem(item.getName(), deserializedState, getTime().toInstant()); } catch (Exception e) { logger.trace("Failed to convert state '{}' to item {} {}: {} {}. Data persisted with incompatible item.", this.state, item.getClass().getSimpleName(), item.getName(), e.getClass().getSimpleName(), 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 cd18ae99036..afc84b2434c 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 @@ -350,6 +350,11 @@ public class DynamoDBPersistenceService implements QueryablePersistenceService { @Override public Iterable query(FilterCriteria filter) { + return query(filter, null); + } + + @Override + public Iterable query(FilterCriteria filter, @Nullable String alias) { logIfManyQueuedTasks(); Instant start = Instant.now(); String filterDescription = filterToString(filter); @@ -419,7 +424,7 @@ public class DynamoDBPersistenceService implements QueryablePersistenceService { item.getClass().getSimpleName(), dtoClass.getSimpleName(), tableName); QueryEnhancedRequest queryExpression = DynamoDBQueryUtils.createQueryExpression(dtoClass, - localTableNameResolver.getTableSchema(), item, filter, unitProvider); + localTableNameResolver.getTableSchema(), item, alias, filter, unitProvider); CompletableFuture>> itemsFuture = new CompletableFuture<>(); final SdkPublisher> itemPublisher = table.query(queryExpression).items(); 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 54e72060a51..3a083fcad7b 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 @@ -44,19 +44,21 @@ public class DynamoDBQueryUtils { * @param dtoClass dto class * @param expectedTableSchema table schema to query against * @param item item corresponding to filter + * @param alias corresponding to item * @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, UnitProvider unitProvider) { + ExpectedTableSchema expectedTableSchema, Item item, @Nullable String alias, FilterCriteria filter, + UnitProvider unitProvider) { if (!expectedTableSchema.isFullyResolved()) { throw new IllegalArgumentException("Schema not resolved"); } QueryEnhancedRequest.Builder queryBuilder = QueryEnhancedRequest.builder() .scanIndexForward(filter.getOrdering() == Ordering.ASCENDING); - String itemName = filter.getItemName(); + String itemName = alias != null ? alias : filter.getItemName(); if (itemName == null) { throw new IllegalArgumentException("Item name not set"); } diff --git a/bundles/org.openhab.persistence.influxdb/src/main/java/org/openhab/persistence/influxdb/InfluxDBPersistenceService.java b/bundles/org.openhab.persistence.influxdb/src/main/java/org/openhab/persistence/influxdb/InfluxDBPersistenceService.java index c00237b9b5d..ee88e03ae17 100644 --- a/bundles/org.openhab.persistence.influxdb/src/main/java/org/openhab/persistence/influxdb/InfluxDBPersistenceService.java +++ b/bundles/org.openhab.persistence.influxdb/src/main/java/org/openhab/persistence/influxdb/InfluxDBPersistenceService.java @@ -204,7 +204,7 @@ public class InfluxDBPersistenceService implements ModifiablePersistenceService logger.warn("InfluxDB service not ready. Storing {} rejected.", item); return; } - convert(item, state, date.toInstant(), null).thenAccept(point -> { + convert(item, state, date.toInstant(), alias).thenAccept(point -> { if (point == null) { logger.trace("Ignoring item {}, conversion to an InfluxDB point failed.", item.getName()); return; @@ -233,27 +233,33 @@ public class InfluxDBPersistenceService implements ModifiablePersistenceService @Override public Iterable query(FilterCriteria filter) { + return query(filter, null); + } + + @Override + public Iterable query(FilterCriteria filter, @Nullable String alias) { + String itemName = filter.getItemName(); + if (itemName == null) { + logger.warn("Item name is missing in filter {} when querying data.", filter); + return List.of(); + } if (serviceActivated && checkConnection()) { logger.trace( "Query-Filter: itemname: {}, ordering: {}, state: {}, operator: {}, getBeginDate: {}, getEndDate: {}, getPageSize: {}, getPageNumber: {}", - filter.getItemName(), filter.getOrdering().toString(), filter.getState(), filter.getOperator(), + itemName, filter.getOrdering().toString(), filter.getState(), filter.getOperator(), filter.getBeginDate(), filter.getEndDate(), filter.getPageSize(), filter.getPageNumber()); - if (filter.getItemName() == null) { - logger.warn("Item name is missing in filter {} when querying data.", filter); - return List.of(); - } List results = influxDBRepository.query(filter, - configuration.getRetentionPolicy()); - return results.stream().map(this::mapRowToHistoricItem).collect(Collectors.toList()); + configuration.getRetentionPolicy(), alias); + return results.stream().map(r -> mapRowToHistoricItem(r, itemName)).collect(Collectors.toList()); } else { logger.debug("Query for persisted data ignored, InfluxDB is not connected"); return List.of(); } } - private HistoricItem mapRowToHistoricItem(InfluxDBRepository.InfluxRow row) { - State state = InfluxDBStateConvertUtils.objectToState(row.value(), row.itemName(), itemRegistry); + private HistoricItem mapRowToHistoricItem(InfluxDBRepository.InfluxRow row, String itemName) { + State state = InfluxDBStateConvertUtils.objectToState(row.value(), itemName, itemRegistry); return new InfluxDBHistoricItem(row.itemName(), state, row.time()); } @@ -314,8 +320,8 @@ public class InfluxDBPersistenceService implements ModifiablePersistenceService } return CompletableFuture.supplyAsync(() -> { - String measurementName = storeAlias != null && !storeAlias.isBlank() ? storeAlias : itemName; - measurementName = influxDBMetadataService.getMeasurementNameOrDefault(itemName, measurementName); + String alias = storeAlias != null && !storeAlias.isBlank() ? storeAlias : itemName; + String measurementName = influxDBMetadataService.getMeasurementNameOrDefault(alias); if (configuration.isReplaceUnderscore()) { measurementName = measurementName.replace('_', '.'); @@ -326,7 +332,7 @@ public class InfluxDBPersistenceService implements ModifiablePersistenceService Object value = InfluxDBStateConvertUtils.stateToObject(storeState); InfluxPoint.Builder pointBuilder = InfluxPoint.newBuilder(measurementName).withTime(timeStamp) - .withValue(value).withTag(TAG_ITEM_NAME, itemName); + .withValue(value).withTag(TAG_ITEM_NAME, alias); if (configuration.isAddCategoryTag()) { String categoryName = Objects.requireNonNullElse(category, "n/a"); @@ -342,7 +348,7 @@ public class InfluxDBPersistenceService implements ModifiablePersistenceService pointBuilder.withTag(TAG_LABEL_NAME, labelName); } - influxDBMetadataService.getMetaData(itemName) + influxDBMetadataService.getMetaData(alias) .ifPresent(metadata -> metadata.getConfiguration().forEach(pointBuilder::withTag)); return pointBuilder.build(); diff --git a/bundles/org.openhab.persistence.influxdb/src/main/java/org/openhab/persistence/influxdb/internal/FilterCriteriaQueryCreator.java b/bundles/org.openhab.persistence.influxdb/src/main/java/org/openhab/persistence/influxdb/internal/FilterCriteriaQueryCreator.java index 8cc6286fa9c..1343c0ad625 100644 --- a/bundles/org.openhab.persistence.influxdb/src/main/java/org/openhab/persistence/influxdb/internal/FilterCriteriaQueryCreator.java +++ b/bundles/org.openhab.persistence.influxdb/src/main/java/org/openhab/persistence/influxdb/internal/FilterCriteriaQueryCreator.java @@ -13,6 +13,7 @@ package org.openhab.persistence.influxdb.internal; import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; import org.openhab.core.persistence.FilterCriteria; /** @@ -24,12 +25,13 @@ import org.openhab.core.persistence.FilterCriteria; public interface FilterCriteriaQueryCreator { /** * Create query from {@link FilterCriteria} - * + * * @param criteria Criteria to create query from * @param retentionPolicy Name of the retentionPolicy/bucket to use in query + * @param alias * @return Created query as a String */ - String createQuery(FilterCriteria criteria, String retentionPolicy); + String createQuery(FilterCriteria criteria, String retentionPolicy, @Nullable String alias); default String getOperationSymbol(FilterCriteria.Operator operator, InfluxDBVersion version) { return switch (operator) { diff --git a/bundles/org.openhab.persistence.influxdb/src/main/java/org/openhab/persistence/influxdb/internal/InfluxDBMetadataService.java b/bundles/org.openhab.persistence.influxdb/src/main/java/org/openhab/persistence/influxdb/internal/InfluxDBMetadataService.java index c5f056fd679..6d243307f25 100644 --- a/bundles/org.openhab.persistence.influxdb/src/main/java/org/openhab/persistence/influxdb/internal/InfluxDBMetadataService.java +++ b/bundles/org.openhab.persistence.influxdb/src/main/java/org/openhab/persistence/influxdb/internal/InfluxDBMetadataService.java @@ -42,10 +42,9 @@ public class InfluxDBMetadataService { * get the measurement name from the item metadata or return the provided default * * @param itemName the item name - * @param defaultName the default measurement name ( * @return the metadata measurement name if present, defaultName otherwise */ - public String getMeasurementNameOrDefault(String itemName, String defaultName) { + public String getMeasurementNameOrDefault(String itemName) { Optional metadata = getMetaData(itemName); if (metadata.isPresent()) { String metaName = metadata.get().getValue(); @@ -54,7 +53,7 @@ public class InfluxDBMetadataService { } } - return defaultName; + return itemName; } /** diff --git a/bundles/org.openhab.persistence.influxdb/src/main/java/org/openhab/persistence/influxdb/internal/InfluxDBRepository.java b/bundles/org.openhab.persistence.influxdb/src/main/java/org/openhab/persistence/influxdb/internal/InfluxDBRepository.java index 8aef35c71b7..1785b1c4a22 100644 --- a/bundles/org.openhab.persistence.influxdb/src/main/java/org/openhab/persistence/influxdb/internal/InfluxDBRepository.java +++ b/bundles/org.openhab.persistence.influxdb/src/main/java/org/openhab/persistence/influxdb/internal/InfluxDBRepository.java @@ -17,6 +17,7 @@ import java.util.List; import java.util.Map; import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; import org.openhab.core.persistence.FilterCriteria; /** @@ -63,10 +64,11 @@ public interface InfluxDBRepository { * Executes Flux query * * @param filter the query filter + * @param alias * @return Query results - * + * */ - List query(FilterCriteria filter, String retentionPolicy); + List query(FilterCriteria filter, String retentionPolicy, @Nullable String alias); /** * Write points to database diff --git a/bundles/org.openhab.persistence.influxdb/src/main/java/org/openhab/persistence/influxdb/internal/influx1/InfluxDB1FilterCriteriaQueryCreatorImpl.java b/bundles/org.openhab.persistence.influxdb/src/main/java/org/openhab/persistence/influxdb/internal/influx1/InfluxDB1FilterCriteriaQueryCreatorImpl.java index 4fce5071dc5..508beaeaddd 100644 --- a/bundles/org.openhab.persistence.influxdb/src/main/java/org/openhab/persistence/influxdb/internal/influx1/InfluxDB1FilterCriteriaQueryCreatorImpl.java +++ b/bundles/org.openhab.persistence.influxdb/src/main/java/org/openhab/persistence/influxdb/internal/influx1/InfluxDB1FilterCriteriaQueryCreatorImpl.java @@ -50,9 +50,10 @@ public class InfluxDB1FilterCriteriaQueryCreatorImpl implements FilterCriteriaQu } @Override - public String createQuery(FilterCriteria criteria, String retentionPolicy) { + public String createQuery(FilterCriteria criteria, String retentionPolicy, @Nullable String alias) { final String itemName = Objects.requireNonNull(criteria.getItemName()); // we checked non-null before - final String tableName = getTableName(itemName); + final String localAlias = alias != null ? alias : itemName; + final String tableName = getTableName(localAlias); final boolean hasCriteriaName = itemName != null; Select select = select().column("\"" + COLUMN_VALUE_NAME_V1 + "\"::field") @@ -61,8 +62,8 @@ public class InfluxDB1FilterCriteriaQueryCreatorImpl implements FilterCriteriaQu Where where = select.where(); - if (itemName != null && !tableName.equals(itemName)) { - where.and(BuiltQuery.QueryBuilder.eq(TAG_ITEM_NAME, itemName)); + if (localAlias != null && !tableName.equals(localAlias)) { + where.and(BuiltQuery.QueryBuilder.eq(TAG_ITEM_NAME, localAlias)); } if (criteria.getBeginDate() != null) { where.and(BuiltQuery.QueryBuilder.gte(COLUMN_TIME_NAME_V1, criteria.getBeginDate().toInstant().toString())); @@ -99,7 +100,7 @@ public class InfluxDB1FilterCriteriaQueryCreatorImpl implements FilterCriteriaQu return "/.*/"; } - String name = influxDBMetadataService.getMeasurementNameOrDefault(itemName, itemName); + String name = influxDBMetadataService.getMeasurementNameOrDefault(itemName); if (configuration.isReplaceUnderscore()) { name = name.replace('_', '.'); diff --git a/bundles/org.openhab.persistence.influxdb/src/main/java/org/openhab/persistence/influxdb/internal/influx1/InfluxDB1RepositoryImpl.java b/bundles/org.openhab.persistence.influxdb/src/main/java/org/openhab/persistence/influxdb/internal/influx1/InfluxDB1RepositoryImpl.java index 1cc0303000d..3228f734d2b 100644 --- a/bundles/org.openhab.persistence.influxdb/src/main/java/org/openhab/persistence/influxdb/internal/influx1/InfluxDB1RepositoryImpl.java +++ b/bundles/org.openhab.persistence.influxdb/src/main/java/org/openhab/persistence/influxdb/internal/influx1/InfluxDB1RepositoryImpl.java @@ -12,10 +12,7 @@ */ package org.openhab.persistence.influxdb.internal.influx1; -import static org.openhab.persistence.influxdb.internal.InfluxDBConstants.COLUMN_TIME_NAME_V1; -import static org.openhab.persistence.influxdb.internal.InfluxDBConstants.COLUMN_VALUE_NAME_V1; -import static org.openhab.persistence.influxdb.internal.InfluxDBConstants.FIELD_VALUE_NAME; -import static org.openhab.persistence.influxdb.internal.InfluxDBConstants.TAG_ITEM_NAME; +import static org.openhab.persistence.influxdb.internal.InfluxDBConstants.*; import java.time.Instant; import java.util.ArrayList; @@ -168,11 +165,11 @@ public class InfluxDB1RepositoryImpl implements InfluxDBRepository { } @Override - public List query(FilterCriteria filter, String retentionPolicy) { + public List query(FilterCriteria filter, String retentionPolicy, @Nullable String alias) { try { final InfluxDB currentClient = client; if (currentClient != null) { - String query = queryCreator.createQuery(filter, retentionPolicy); + String query = queryCreator.createQuery(filter, retentionPolicy, alias); logger.trace("Query {}", query); Query parsedQuery = new Query(query, configuration.getDatabaseName()); List results = currentClient.query(parsedQuery, TimeUnit.MILLISECONDS).getResults(); diff --git a/bundles/org.openhab.persistence.influxdb/src/main/java/org/openhab/persistence/influxdb/internal/influx2/InfluxDB2FilterCriteriaQueryCreatorImpl.java b/bundles/org.openhab.persistence.influxdb/src/main/java/org/openhab/persistence/influxdb/internal/influx2/InfluxDB2FilterCriteriaQueryCreatorImpl.java index e3df00f12c3..e0e1a2aad3e 100644 --- a/bundles/org.openhab.persistence.influxdb/src/main/java/org/openhab/persistence/influxdb/internal/influx2/InfluxDB2FilterCriteriaQueryCreatorImpl.java +++ b/bundles/org.openhab.persistence.influxdb/src/main/java/org/openhab/persistence/influxdb/internal/influx2/InfluxDB2FilterCriteriaQueryCreatorImpl.java @@ -12,8 +12,7 @@ */ package org.openhab.persistence.influxdb.internal.influx2; -import static com.influxdb.query.dsl.functions.restriction.Restrictions.measurement; -import static com.influxdb.query.dsl.functions.restriction.Restrictions.tag; +import static com.influxdb.query.dsl.functions.restriction.Restrictions.*; import static org.openhab.persistence.influxdb.internal.InfluxDBConstants.*; import static org.openhab.persistence.influxdb.internal.InfluxDBStateConvertUtils.stateToObject; @@ -21,6 +20,7 @@ import java.time.temporal.ChronoUnit; import java.util.Objects; import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; import org.openhab.core.persistence.FilterCriteria; import org.openhab.core.types.State; import org.openhab.persistence.influxdb.internal.FilterCriteriaQueryCreator; @@ -49,7 +49,7 @@ public class InfluxDB2FilterCriteriaQueryCreatorImpl implements FilterCriteriaQu } @Override - public String createQuery(FilterCriteria criteria, String retentionPolicy) { + public String createQuery(FilterCriteria criteria, String retentionPolicy, @Nullable String alias) { Flux flux = Flux.from(retentionPolicy); RangeFlux range = flux.range(); @@ -66,7 +66,8 @@ public class InfluxDB2FilterCriteriaQueryCreatorImpl implements FilterCriteriaQu flux = range; String itemName = Objects.requireNonNull(criteria.getItemName()); // we checked non-null before - String name = influxDBMetadataService.getMeasurementNameOrDefault(itemName, itemName); + final String localAlias = alias != null ? alias : itemName; + String name = influxDBMetadataService.getMeasurementNameOrDefault(localAlias); String measurementName = configuration.isReplaceUnderscore() ? name.replace('_', '.') : name; flux = flux.filter(measurement().equal(measurementName)); if (!measurementName.equals(itemName)) { diff --git a/bundles/org.openhab.persistence.influxdb/src/main/java/org/openhab/persistence/influxdb/internal/influx2/InfluxDB2RepositoryImpl.java b/bundles/org.openhab.persistence.influxdb/src/main/java/org/openhab/persistence/influxdb/internal/influx2/InfluxDB2RepositoryImpl.java index 8251634a287..a73e3f5e3a3 100644 --- a/bundles/org.openhab.persistence.influxdb/src/main/java/org/openhab/persistence/influxdb/internal/influx2/InfluxDB2RepositoryImpl.java +++ b/bundles/org.openhab.persistence.influxdb/src/main/java/org/openhab/persistence/influxdb/internal/influx2/InfluxDB2RepositoryImpl.java @@ -176,7 +176,7 @@ public class InfluxDB2RepositoryImpl implements InfluxDBRepository { String predicate = ""; String itemName = filter.getItemName(); if (itemName != null) { - String name = influxDBMetadataService.getMeasurementNameOrDefault(itemName, itemName); + String name = influxDBMetadataService.getMeasurementNameOrDefault(itemName); String measurementName = configuration.isReplaceUnderscore() ? name.replace('_', '.') : name; predicate = "(_measurement=\"" + measurementName + "\")"; } @@ -213,11 +213,11 @@ public class InfluxDB2RepositoryImpl implements InfluxDBRepository { } @Override - public List query(FilterCriteria filter, String retentionPolicy) { + public List query(FilterCriteria filter, String retentionPolicy, @Nullable String alias) { try { final QueryApi currentQueryAPI = queryAPI; if (currentQueryAPI != null) { - String query = queryCreator.createQuery(filter, retentionPolicy); + String query = queryCreator.createQuery(filter, retentionPolicy, alias); logger.trace("Query {}", query); List clientResult = currentQueryAPI.query(query); return clientResult.stream().flatMap(this::mapRawResultToHistoric).toList(); diff --git a/bundles/org.openhab.persistence.influxdb/src/test/java/org/openhab/persistence/influxdb/internal/InfluxFilterCriteriaQueryCreatorImplTest.java b/bundles/org.openhab.persistence.influxdb/src/test/java/org/openhab/persistence/influxdb/internal/InfluxFilterCriteriaQueryCreatorImplTest.java index df96b2a30bd..4d345872351 100644 --- a/bundles/org.openhab.persistence.influxdb/src/test/java/org/openhab/persistence/influxdb/internal/InfluxFilterCriteriaQueryCreatorImplTest.java +++ b/bundles/org.openhab.persistence.influxdb/src/test/java/org/openhab/persistence/influxdb/internal/InfluxFilterCriteriaQueryCreatorImplTest.java @@ -76,11 +76,11 @@ public class InfluxFilterCriteriaQueryCreatorImplTest { public void testSimpleItemQueryWithoutParams() { FilterCriteria criteria = createBaseCriteria(); - String queryV1 = instanceV1.createQuery(criteria, RETENTION_POLICY); + String queryV1 = instanceV1.createQuery(criteria, RETENTION_POLICY, null); assertThat(queryV1, equalTo("SELECT \"value\"::field,\"item\"::tag FROM \"origin\".\"sampleItem\" ORDER BY time DESC;")); - String queryV2 = instanceV2.createQuery(criteria, RETENTION_POLICY); + String queryV2 = instanceV2.createQuery(criteria, RETENTION_POLICY, null); assertThat(queryV2, equalTo(""" from(bucket:"origin") \t|> range(start:-100y, stop:100y) @@ -97,13 +97,13 @@ public class InfluxFilterCriteriaQueryCreatorImplTest { criteria.setBeginDate(now); criteria.setEndDate(tomorrow); - String queryV1 = instanceV1.createQuery(criteria, RETENTION_POLICY); + String queryV1 = instanceV1.createQuery(criteria, RETENTION_POLICY, null); String expectedQueryV1 = String.format( "SELECT \"value\"::field,\"item\"::tag FROM \"origin\".\"sampleItem\" WHERE time >= '%s' AND time <= '%s' ORDER BY time DESC;", now.toInstant(), tomorrow.toInstant()); assertThat(queryV1, equalTo(expectedQueryV1)); - String queryV2 = instanceV2.createQuery(criteria, RETENTION_POLICY); + String queryV2 = instanceV2.createQuery(criteria, RETENTION_POLICY, null); String expectedQueryV2 = String.format(""" from(bucket:"origin") \t|> range(start:%s, stop:%s) @@ -120,11 +120,11 @@ public class InfluxFilterCriteriaQueryCreatorImplTest { criteria.setOperator(FilterCriteria.Operator.LTE); criteria.setState(new PercentType(90)); - String query = instanceV1.createQuery(criteria, RETENTION_POLICY); + String query = instanceV1.createQuery(criteria, RETENTION_POLICY, null); assertThat(query, equalTo( "SELECT \"value\"::field,\"item\"::tag FROM \"origin\".\"sampleItem\" WHERE value <= 90 ORDER BY time DESC;")); - String queryV2 = instanceV2.createQuery(criteria, RETENTION_POLICY); + String queryV2 = instanceV2.createQuery(criteria, RETENTION_POLICY, null); assertThat(queryV2, equalTo(""" from(bucket:"origin") \t|> range(start:-100y, stop:100y) @@ -140,11 +140,11 @@ public class InfluxFilterCriteriaQueryCreatorImplTest { criteria.setPageNumber(2); criteria.setPageSize(10); - String query = instanceV1.createQuery(criteria, RETENTION_POLICY); + String query = instanceV1.createQuery(criteria, RETENTION_POLICY, null); assertThat(query, equalTo( "SELECT \"value\"::field,\"item\"::tag FROM \"origin\".\"sampleItem\" ORDER BY time DESC LIMIT 10 OFFSET 20;")); - String queryV2 = instanceV2.createQuery(criteria, RETENTION_POLICY); + String queryV2 = instanceV2.createQuery(criteria, RETENTION_POLICY, null); assertThat(queryV2, equalTo(""" from(bucket:"origin") \t|> range(start:-100y, stop:100y) @@ -159,11 +159,11 @@ public class InfluxFilterCriteriaQueryCreatorImplTest { FilterCriteria criteria = createBaseCriteria(); criteria.setOrdering(FilterCriteria.Ordering.ASCENDING); - String query = instanceV1.createQuery(criteria, RETENTION_POLICY); + String query = instanceV1.createQuery(criteria, RETENTION_POLICY, null); assertThat(query, equalTo("SELECT \"value\"::field,\"item\"::tag FROM \"origin\".\"sampleItem\" ORDER BY time ASC;")); - String queryV2 = instanceV2.createQuery(criteria, RETENTION_POLICY); + String queryV2 = instanceV2.createQuery(criteria, RETENTION_POLICY, null); assertThat(queryV2, equalTo(""" from(bucket:"origin") \t|> range(start:-100y, stop:100y) @@ -177,7 +177,7 @@ public class InfluxFilterCriteriaQueryCreatorImplTest { FilterCriteria criteria = createBaseCriteria(); criteria.setOrdering(FilterCriteria.Ordering.DESCENDING); criteria.setPageSize(1); - String queryV2 = instanceV2.createQuery(criteria, RETENTION_POLICY); + String queryV2 = instanceV2.createQuery(criteria, RETENTION_POLICY, null); assertThat(queryV2, equalTo(""" from(bucket:"origin") \t|> range(start:-100y, stop:100y) @@ -200,11 +200,11 @@ public class InfluxFilterCriteriaQueryCreatorImplTest { when(metadataRegistry.get(metadataKey)) .thenReturn(new Metadata(metadataKey, "measurementName", Map.of("key1", "val1", "key2", "val2"))); - String queryV1 = instanceV1.createQuery(criteria, RETENTION_POLICY); + String queryV1 = instanceV1.createQuery(criteria, RETENTION_POLICY, null); assertThat(queryV1, equalTo( "SELECT \"value\"::field,\"item\"::tag FROM \"origin\".\"measurementName\" WHERE item = 'sampleItem' ORDER BY time DESC;")); - String queryV2 = instanceV2.createQuery(criteria, RETENTION_POLICY); + String queryV2 = instanceV2.createQuery(criteria, RETENTION_POLICY, null); assertThat(queryV2, equalTo(""" from(bucket:"origin") \t|> range(start:-100y, stop:100y) @@ -215,11 +215,11 @@ public class InfluxFilterCriteriaQueryCreatorImplTest { when(metadataRegistry.get(metadataKey)) .thenReturn(new Metadata(metadataKey, "", Map.of("key1", "val1", "key2", "val2"))); - queryV1 = instanceV1.createQuery(criteria, RETENTION_POLICY); + queryV1 = instanceV1.createQuery(criteria, RETENTION_POLICY, null); assertThat(queryV1, equalTo("SELECT \"value\"::field,\"item\"::tag FROM \"origin\".\"sampleItem\" ORDER BY time DESC;")); - queryV2 = instanceV2.createQuery(criteria, RETENTION_POLICY); + queryV2 = instanceV2.createQuery(criteria, RETENTION_POLICY, null); assertThat(queryV2, equalTo(""" from(bucket:"origin") \t|> range(start:-100y, stop:100y) diff --git a/bundles/org.openhab.persistence.jdbc/src/main/java/org/openhab/persistence/jdbc/internal/JdbcMapper.java b/bundles/org.openhab.persistence.jdbc/src/main/java/org/openhab/persistence/jdbc/internal/JdbcMapper.java index d7594a401b6..37f93c560e2 100644 --- a/bundles/org.openhab.persistence.jdbc/src/main/java/org/openhab/persistence/jdbc/internal/JdbcMapper.java +++ b/bundles/org.openhab.persistence.jdbc/src/main/java/org/openhab/persistence/jdbc/internal/JdbcMapper.java @@ -212,9 +212,10 @@ public class JdbcMapper { logTime("alterTableColumn", timerStart, System.currentTimeMillis()); } - protected void storeItemValue(Item item, State itemState, @Nullable ZonedDateTime date) throws JdbcException { + protected void storeItemValue(Item item, State itemState, @Nullable ZonedDateTime date, @Nullable String alias) + throws JdbcException { logger.debug("JDBC::storeItemValue: item={} state={} date={}", item, itemState, date); - String tableName = getTable(item); + String tableName = getTable(item, alias); long timerStart = System.currentTimeMillis(); if (date == null) { conf.getDBDAO().doStoreItemValue(item, itemState, new ItemVO(tableName, null)); @@ -353,8 +354,8 @@ public class JdbcMapper { } } - protected String getTable(Item item) throws JdbcException { - String itemName = item.getName(); + protected String getTable(Item item, @Nullable String alias) throws JdbcException { + String itemName = alias != null ? alias : item.getName(); if (!initialized) { throw new JdbcException("Not initialized, unable to find table for item " + itemName); } diff --git a/bundles/org.openhab.persistence.jdbc/src/main/java/org/openhab/persistence/jdbc/internal/JdbcPersistenceService.java b/bundles/org.openhab.persistence.jdbc/src/main/java/org/openhab/persistence/jdbc/internal/JdbcPersistenceService.java index 82d51ad4675..86bb3ee79a1 100644 --- a/bundles/org.openhab.persistence.jdbc/src/main/java/org/openhab/persistence/jdbc/internal/JdbcPersistenceService.java +++ b/bundles/org.openhab.persistence.jdbc/src/main/java/org/openhab/persistence/jdbc/internal/JdbcPersistenceService.java @@ -137,27 +137,26 @@ public class JdbcPersistenceService extends JdbcMapper implements ModifiablePers @Override public void store(Item item) { - scheduler.execute(() -> internalStore(item, null, item.getState())); + scheduler.execute(() -> internalStore(item, null, item.getState(), null)); } @Override public void store(Item item, @Nullable String alias) { - // alias is not supported - scheduler.execute(() -> internalStore(item, null, item.getState())); + scheduler.execute(() -> internalStore(item, null, item.getState(), alias)); } @Override public void store(Item item, ZonedDateTime date, State state) { - scheduler.execute(() -> internalStore(item, date, state)); + scheduler.execute(() -> internalStore(item, date, state, null)); } @Override public void store(Item item, ZonedDateTime date, State state, @Nullable String alias) { - // alias is not supported - scheduler.execute(() -> internalStore(item, date, state)); + scheduler.execute(() -> internalStore(item, date, state, alias)); } - private synchronized void internalStore(Item item, @Nullable ZonedDateTime date, State state) { + private synchronized void internalStore(Item item, @Nullable ZonedDateTime date, State state, + @Nullable String alias) { // Do not store undefined/uninitialized data if (state instanceof UnDefType) { logger.debug("JDBC::store: ignore Item '{}' because it is UnDefType", item.getName()); @@ -171,7 +170,7 @@ public class JdbcPersistenceService extends JdbcMapper implements ModifiablePers } try { long timerStart = System.currentTimeMillis(); - storeItemValue(item, state, date); + storeItemValue(item, state, date, alias); if (logger.isDebugEnabled()) { logger.debug("JDBC: Stored item '{}' as '{}' in SQL database at {} in {} ms.", item.getName(), state, new Date(), System.currentTimeMillis() - timerStart); @@ -190,12 +189,24 @@ public class JdbcPersistenceService extends JdbcMapper implements ModifiablePers * Queries the {@link PersistenceService} for data with a given filter * criteria * - * @param filter - * the filter to apply to the query + * @param filter the filter to apply to the query * @return a time series of items */ @Override public Iterable query(FilterCriteria filter) { + return query(filter, null); + } + + /** + * Queries the {@link PersistenceService} for data with a given filter + * criteria + * + * @param filter the filter to apply to the query + * @param alias for the item + * @return a time series of items + */ + @Override + public Iterable query(FilterCriteria filter, @Nullable String alias) { if (!checkDBAccessability()) { logger.warn("JDBC::query: database not connected, query aborted for item '{}'", filter.getItemName()); return List.of(); @@ -231,9 +242,11 @@ public class JdbcPersistenceService extends JdbcMapper implements ModifiablePers } } - String table = itemNameToTableNameMap.get(itemName); + String localAlias = alias != null ? alias : itemName; + String table = itemNameToTableNameMap.get(localAlias); if (table == null) { - logger.debug("JDBC::query: unable to find table for item with name: '{}', no data in database.", itemName); + logger.debug("JDBC::query: unable to find table for item with name or alias: '{}', no data in database.", + localAlias); return List.of(); } diff --git a/bundles/org.openhab.persistence.jpa/src/main/java/org/openhab/persistence/jpa/internal/JpaPersistenceService.java b/bundles/org.openhab.persistence.jpa/src/main/java/org/openhab/persistence/jpa/internal/JpaPersistenceService.java index c9eac1abefb..0b373df182a 100644 --- a/bundles/org.openhab.persistence.jpa/src/main/java/org/openhab/persistence/jpa/internal/JpaPersistenceService.java +++ b/bundles/org.openhab.persistence.jpa/src/main/java/org/openhab/persistence/jpa/internal/JpaPersistenceService.java @@ -187,6 +187,11 @@ public class JpaPersistenceService implements QueryablePersistenceService { @Override public Iterable query(FilterCriteria filter) { + return query(filter, null); + } + + @Override + public Iterable query(FilterCriteria filter, @Nullable String alias) { logger.debug("Querying for historic item: {}", filter.getItemName()); if (!initialized) { @@ -235,7 +240,7 @@ public class JpaPersistenceService implements QueryablePersistenceService { logger.debug("Creating query..."); Query query = em.createQuery(queryString); - query.setParameter("itemName", item.getName()); + query.setParameter("itemName", alias != null ? alias : item.getName()); if (hasBeginDate) { query.setParameter("beginDate", Date.from(filter.getBeginDate().toInstant())); } diff --git a/bundles/org.openhab.persistence.mongodb/src/main/java/org/openhab/persistence/mongodb/internal/MongoDBPersistenceService.java b/bundles/org.openhab.persistence.mongodb/src/main/java/org/openhab/persistence/mongodb/internal/MongoDBPersistenceService.java index 9522bb784a0..224ad5ed47f 100644 --- a/bundles/org.openhab.persistence.mongodb/src/main/java/org/openhab/persistence/mongodb/internal/MongoDBPersistenceService.java +++ b/bundles/org.openhab.persistence.mongodb/src/main/java/org/openhab/persistence/mongodb/internal/MongoDBPersistenceService.java @@ -247,6 +247,15 @@ public class MongoDBPersistenceService implements ModifiablePersistenceService { @Override public Iterable query(FilterCriteria filter) { + return query(filter, null); + } + + @Override + public Iterable query(FilterCriteria filter, @Nullable String alias) { + String realItemName = filter.getItemName(); + if (alias != null) { + filter.setItemName(alias); + } MongoCollection collection = prepareCollection(filter); // If collection creation failed, return nothing. if (collection == null) { @@ -259,8 +268,6 @@ public class MongoDBPersistenceService implements ModifiablePersistenceService { return Collections.emptyList(); } - @Nullable - String realItemName = filter.getItemName(); if (realItemName == null) { logger.warn("Item name is missing in filter {}", filter); return Collections.emptyList(); @@ -354,7 +361,8 @@ public class MongoDBPersistenceService implements ModifiablePersistenceService { } String realItemName = item.getName(); - String collectionName = collectionPerItem ? realItemName : this.collection; + String name = (alias != null) ? alias : realItemName; + String collectionName = collectionPerItem ? name : this.collection; @Nullable MongoCollection collection = connectToCollection(collectionName); @@ -364,7 +372,6 @@ public class MongoDBPersistenceService implements ModifiablePersistenceService { return; } - String name = (alias != null) ? alias : realItemName; Object value = MongoDBTypeConversions.convertValue(state); Document obj = new Document(); diff --git a/bundles/org.openhab.persistence.mongodb/src/test/java/org/openhab/persistence/mongodb/internal/MongoDBPersistenceServiceTest.java b/bundles/org.openhab.persistence.mongodb/src/test/java/org/openhab/persistence/mongodb/internal/MongoDBPersistenceServiceTest.java index 28d75404c6f..45e15dc5314 100644 --- a/bundles/org.openhab.persistence.mongodb/src/test/java/org/openhab/persistence/mongodb/internal/MongoDBPersistenceServiceTest.java +++ b/bundles/org.openhab.persistence.mongodb/src/test/java/org/openhab/persistence/mongodb/internal/MongoDBPersistenceServiceTest.java @@ -12,8 +12,7 @@ */ package org.openhab.persistence.mongodb.internal; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.*; import java.text.DateFormat; import java.time.Instant; @@ -30,6 +29,7 @@ import java.util.stream.Collectors; import org.bson.Document; import org.bson.types.ObjectId; +import org.eclipse.jdt.annotation.NonNull; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; @@ -46,6 +46,7 @@ import org.openhab.core.library.types.DecimalType; import org.openhab.core.library.types.HSBType; import org.openhab.core.library.types.QuantityType; import org.openhab.core.library.types.RawType; +import org.openhab.core.library.types.StringType; import org.openhab.core.persistence.FilterCriteria; import org.openhab.core.persistence.HistoricItem; import org.osgi.framework.BundleContext; @@ -206,7 +207,7 @@ public class MongoDBPersistenceServiceTest { // Verification MongoCollection collection = database.getCollection("testCollection"); - List documents = (ArrayList) collection.find().into(new ArrayList<>()); + List documents = collection.find().into(new ArrayList<>()); assertEquals(1, documents.size()); // Assert that there is only one document @@ -244,7 +245,7 @@ public class MongoDBPersistenceServiceTest { // Verification MongoCollection collection = database.getCollection("testCollection"); - List documents = (ArrayList) collection.find().into(new ArrayList<>()); + List documents = collection.find().into(new ArrayList<>()); assertEquals(1, documents.size()); // Assert that there is only one document @@ -284,7 +285,7 @@ public class MongoDBPersistenceServiceTest { // Verification MongoCollection collection = database.getCollection("testCollection"); - List documents = (ArrayList) collection.find().into(new ArrayList<>()); + List documents = collection.find().into(new ArrayList<>()); assertEquals(2, documents.size()); // Assert that there are two documents @@ -326,7 +327,7 @@ public class MongoDBPersistenceServiceTest { // Verification MongoCollection collection = database.getCollection("testCollection"); - List documents = (ArrayList) collection.find().into(new ArrayList<>()); + List documents = collection.find().into(new ArrayList<>()); assertEquals(2, documents.size()); // Assert that there are two documents @@ -366,7 +367,7 @@ public class MongoDBPersistenceServiceTest { // Verification MongoCollection collection = database.getCollection("testCollection"); - List documents = (ArrayList) collection.find().into(new ArrayList<>()); + List documents = collection.find().into(new ArrayList<>()); assertEquals(1, documents.size()); // Assert that there is only one document @@ -378,6 +379,48 @@ public class MongoDBPersistenceServiceTest { } } + /** + * Tests the reading of String Items stored with an alias + * + * @param dbContainer The container running the MongoDB instance. + */ + @ParameterizedTest + @MethodSource("org.openhab.persistence.mongodb.internal.DataCreationHelper#provideDatabaseBackends") + public void testQueryStringWithAlias(DatabaseTestContainer dbContainer) { + try { + SetupResult setupResult = DataCreationHelper.setupMongoDB("testCollection", dbContainer); + MongoDBPersistenceService service = setupResult.service; + MongoDatabase database = setupResult.database; + + service.activate(setupResult.bundleContext, setupResult.config); + MongoCollection collection = database.getCollection("testCollection"); + + StringItem item = DataCreationHelper.createStringItem("TestItem", "TestValue"); + try { + Mockito.when(setupResult.itemRegistry.getItem("TestItem")).thenReturn(item); + } catch (ItemNotFoundException e) { + } + + String alias = "AliasName"; + + Document obj = new Document(); + obj.put(MongoDBFields.FIELD_ID, new ObjectId()); + obj.put(MongoDBFields.FIELD_ITEM, alias); + obj.put(MongoDBFields.FIELD_REALNAME, "TestItem"); + obj.put(MongoDBFields.FIELD_TIMESTAMP, new Date()); + obj.put(MongoDBFields.FIELD_VALUE, "TestValue"); + collection.insertOne(obj); + + // Execution + FilterCriteria filter = DataCreationHelper.createFilterCriteria("TestItem"); + @NonNull + Iterable<@NonNull HistoricItem> result = service.query(filter, alias); + VerificationHelper.verifyQueryResult(result, new StringType("TestValue")); + } finally { + dbContainer.stop(); + } + } + /** * Tests the query method of MongoDBPersistenceService with NumberItems in a single collection. * @@ -607,7 +650,7 @@ public class MongoDBPersistenceServiceTest { // Verification MongoCollection collection = database.getCollection("testCollection"); - List documents = (ArrayList) collection.find().into(new ArrayList<>()); + List documents = collection.find().into(new ArrayList<>()); assertEquals(1, documents.size()); // Assert that there is only one document @@ -735,7 +778,7 @@ public class MongoDBPersistenceServiceTest { service.store(item, null); // Verification - List documents = (ArrayList) collection.find().into(new ArrayList<>()); + List documents = collection.find().into(new ArrayList<>()); assertEquals(1, documents.size()); // Assert that there is only one document @@ -793,7 +836,6 @@ public class MongoDBPersistenceServiceTest { /** * Tests the toString of a MongoDBItem - * * * @param item The item to store in the database. */ @@ -840,7 +882,7 @@ public class MongoDBPersistenceServiceTest { // Verification MongoCollection collection = database.getCollection("TestItem"); - List documents = (ArrayList) collection.find().into(new ArrayList<>()); + List documents = collection.find().into(new ArrayList<>()); assertEquals(1, documents.size()); // Assert that there is only one document @@ -880,8 +922,8 @@ public class MongoDBPersistenceServiceTest { service.store(item, now, historicState, "AliasName"); // Verification - MongoCollection collection = database.getCollection("TestItem"); - List documents = (ArrayList) collection.find().into(new ArrayList<>()); + MongoCollection collection = database.getCollection("AliasName"); + List documents = collection.find().into(new ArrayList<>()); assertEquals(1, documents.size()); // Assert that there is only one document @@ -919,7 +961,7 @@ public class MongoDBPersistenceServiceTest { // Verification MongoCollection collection = database.getCollection("testcollection"); - List documents = (ArrayList) collection.find().into(new ArrayList<>()); + List documents = collection.find().into(new ArrayList<>()); assertEquals(1, documents.size()); // Assert that there is the other document @@ -959,7 +1001,7 @@ public class MongoDBPersistenceServiceTest { MongoCollection collection = database.getCollection("testcollection"); // Query the database for all data points - List documents = (ArrayList) collection.find().into(new ArrayList<>()); + List documents = collection.find().into(new ArrayList<>()); // Create a set of the returned data points Set returnedData = documents.stream() diff --git a/bundles/org.openhab.persistence.rrd4j/src/main/java/org/openhab/persistence/rrd4j/internal/RRD4jPersistenceService.java b/bundles/org.openhab.persistence.rrd4j/src/main/java/org/openhab/persistence/rrd4j/internal/RRD4jPersistenceService.java index f1b6ffd694c..1c286d42fae 100644 --- a/bundles/org.openhab.persistence.rrd4j/src/main/java/org/openhab/persistence/rrd4j/internal/RRD4jPersistenceService.java +++ b/bundles/org.openhab.persistence.rrd4j/src/main/java/org/openhab/persistence/rrd4j/internal/RRD4jPersistenceService.java @@ -333,7 +333,7 @@ public class RRD4jPersistenceService implements QueryablePersistenceService { if (oldValue != null && !oldValue.equals(value)) { logger.debug( "Discarding value {} for item {} with timestamp {} because a new value ({}) arrived with the same timestamp.", - oldValue, name, now, value); + oldValue, item.getName(), now, value); } } @@ -411,6 +411,11 @@ public class RRD4jPersistenceService implements QueryablePersistenceService { @Override public Iterable query(FilterCriteria filter) { + return query(filter, null); + } + + @Override + public Iterable query(FilterCriteria filter, @Nullable String alias) { ZonedDateTime filterBeginDate = filter.getBeginDate(); ZonedDateTime filterEndDate = filter.getEndDate(); if (filterBeginDate != null && filterEndDate != null && filterBeginDate.isAfter(filterEndDate)) { @@ -424,9 +429,10 @@ public class RRD4jPersistenceService implements QueryablePersistenceService { } logger.trace("Querying rrd4j database for item '{}'", itemName); + String localAlias = alias != null ? alias : itemName; RrdDb db = null; try { - db = getDB(itemName, false); + db = getDB(localAlias, false); } catch (Exception e) { logger.warn("Failed to open rrd4j database '{}' for querying ({})", itemName, e.toString()); return List.of(); diff --git a/bundles/org.openhab.persistence.rrd4j/src/main/java/org/openhab/persistence/rrd4j/internal/charts/RRD4jChartServlet.java b/bundles/org.openhab.persistence.rrd4j/src/main/java/org/openhab/persistence/rrd4j/internal/charts/RRD4jChartServlet.java index 96a028b470a..c0bc1e0caa9 100644 --- a/bundles/org.openhab.persistence.rrd4j/src/main/java/org/openhab/persistence/rrd4j/internal/charts/RRD4jChartServlet.java +++ b/bundles/org.openhab.persistence.rrd4j/src/main/java/org/openhab/persistence/rrd4j/internal/charts/RRD4jChartServlet.java @@ -38,6 +38,8 @@ import org.openhab.core.items.GroupItem; import org.openhab.core.items.Item; import org.openhab.core.items.ItemNotFoundException; import org.openhab.core.library.items.NumberItem; +import org.openhab.core.persistence.registry.PersistenceServiceConfiguration; +import org.openhab.core.persistence.registry.PersistenceServiceConfigurationRegistry; import org.openhab.core.ui.chart.ChartProvider; import org.openhab.core.ui.items.ItemUIRegistry; import org.openhab.persistence.rrd4j.internal.RRD4jPersistenceService; @@ -106,13 +108,16 @@ public class RRD4jChartServlet implements Servlet, ChartProvider { private final HttpService httpService; private final ItemUIRegistry itemUIRegistry; private final TimeZoneProvider timeZoneProvider; + private final PersistenceServiceConfigurationRegistry persistenceServiceConfigurationRegistry; @Activate public RRD4jChartServlet(final @Reference HttpService httpService, final @Reference ItemUIRegistry itemUIRegistry, - final @Reference TimeZoneProvider timeZoneProvider) { + final @Reference TimeZoneProvider timeZoneProvider, + final @Reference PersistenceServiceConfigurationRegistry persistenceServiceConfigurationRegistry) { this.httpService = httpService; this.itemUIRegistry = itemUIRegistry; this.timeZoneProvider = timeZoneProvider; + this.persistenceServiceConfigurationRegistry = persistenceServiceConfigurationRegistry; } @Activate @@ -179,10 +184,10 @@ public class RRD4jChartServlet implements Servlet, ChartProvider { * @param item the item to add a line for * @param counter defines the number of the datasource and is used to determine the line color */ - protected void addLine(RrdGraphDef graphDef, Item item, int counter) { + protected void addLine(RrdGraphDef graphDef, Item item, @Nullable String alias, int counter) { Color color = LINECOLORS[counter % LINECOLORS.length]; String label = itemUIRegistry.getLabel(item.getName()); - String rrdName = RRD4jPersistenceService.getDatabasePath(item.getName()).toString(); + String rrdName = RRD4jPersistenceService.getDatabasePath(alias != null ? alias : item.getName()).toString(); ConsolFun consolFun; if (label != null && label.contains("[") && label.contains("]")) { label = label.substring(0, label.indexOf('[')); @@ -251,14 +256,18 @@ public class RRD4jChartServlet implements Servlet, ChartProvider { graphDef.setFont(FontTag.TITLE, new Font("SansSerif", Font.PLAIN, 15)); graphDef.setFont(FontTag.DEFAULT, new Font("SansSerif", Font.PLAIN, 11)); + PersistenceServiceConfiguration config = persistenceServiceConfigurationRegistry + .get(RRD4jPersistenceService.SERVICE_ID); + int seriesCounter = 0; // Loop through all the items if (items != null) { String[] itemNames = items.split(","); for (String itemName : itemNames) { + String alias = config != null ? config.getAliases().get(itemName) : null; Item item = itemUIRegistry.getItem(itemName); - addLine(graphDef, item, seriesCounter++); + addLine(graphDef, item, alias, seriesCounter++); } } @@ -269,7 +278,8 @@ public class RRD4jChartServlet implements Servlet, ChartProvider { Item item = itemUIRegistry.getItem(groupName); if (item instanceof GroupItem groupItem) { for (Item member : groupItem.getMembers()) { - addLine(graphDef, member, seriesCounter++); + String alias = config != null ? config.getAliases().get(member.getName()) : null; + addLine(graphDef, member, alias, seriesCounter++); } } else { throw new ItemNotFoundException("Item '" + item.getName() + "' defined in groups is not a group."); diff --git a/bundles/org.openhab.persistence.rrd4j/src/main/java/org/openhab/persistence/rrd4j/internal/console/RRD4jCommandExtension.java b/bundles/org.openhab.persistence.rrd4j/src/main/java/org/openhab/persistence/rrd4j/internal/console/RRD4jCommandExtension.java index 941cdc2beb4..21910ad93cb 100644 --- a/bundles/org.openhab.persistence.rrd4j/src/main/java/org/openhab/persistence/rrd4j/internal/console/RRD4jCommandExtension.java +++ b/bundles/org.openhab.persistence.rrd4j/src/main/java/org/openhab/persistence/rrd4j/internal/console/RRD4jCommandExtension.java @@ -17,7 +17,10 @@ import java.nio.file.Path; import java.util.Collections; import java.util.Comparator; import java.util.List; +import java.util.Map.Entry; +import java.util.Objects; import java.util.stream.Collectors; +import java.util.stream.Stream; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; @@ -30,6 +33,8 @@ import org.openhab.core.items.ItemNotFoundException; import org.openhab.core.items.ItemRegistry; import org.openhab.core.persistence.PersistenceService; import org.openhab.core.persistence.PersistenceServiceRegistry; +import org.openhab.core.persistence.registry.PersistenceServiceConfiguration; +import org.openhab.core.persistence.registry.PersistenceServiceConfigurationRegistry; import org.openhab.persistence.rrd4j.internal.RRD4jPersistenceService; import org.osgi.service.component.annotations.Activate; import org.osgi.service.component.annotations.Component; @@ -51,13 +56,16 @@ public class RRD4jCommandExtension extends AbstractConsoleCommandExtension imple false); private final PersistenceServiceRegistry persistenceServiceRegistry; + private final PersistenceServiceConfigurationRegistry persistenceServiceConfigurationRegistry; private final ItemRegistry itemRegistry; @Activate public RRD4jCommandExtension(final @Reference PersistenceServiceRegistry persistenceServiceRegistry, - final @Reference ItemRegistry itemRegistry) { + final @Reference ItemRegistry itemRegistry, + final @Reference PersistenceServiceConfigurationRegistry persistenceServiceConfigurationRegistry) { super(RRD4jPersistenceService.SERVICE_ID, "Interact with the RRD4j persistence service."); this.persistenceServiceRegistry = persistenceServiceRegistry; + this.persistenceServiceConfigurationRegistry = persistenceServiceConfigurationRegistry; this.itemRegistry = itemRegistry; } @@ -104,6 +112,11 @@ public class RRD4jCommandExtension extends AbstractConsoleCommandExtension imple Collections.sort(filenames, Comparator.naturalOrder()); } + PersistenceServiceConfiguration config = persistenceServiceConfigurationRegistry + .get(RRD4jPersistenceService.SERVICE_ID); + Stream> aliases = config != null ? config.getAliases().entrySet().stream() + : Stream.empty(); + console.println((checkOnly ? "Checking" : "Cleaning") + " RRD files..."); int nb = 0; for (String filename : filenames) { @@ -114,7 +127,10 @@ public class RRD4jCommandExtension extends AbstractConsoleCommandExtension imple } else { boolean itemFound; try { - itemRegistry.getItem(name); + // Map alias back to item + String item = Objects.requireNonNull( + aliases.filter(e -> name.equals(e.getValue())).findAny().map(e -> e.getKey()).orElse(name)); + itemRegistry.getItem(item); itemFound = true; } catch (ItemNotFoundException e) { itemFound = false;