[persistence] Allow persistence services to define default strategies (#1387)

* Allow persistence services to define default strategies
* Added null annotations

Signed-off-by: Kai Kreuzer <kai@openhab.org>
This commit is contained in:
Kai Kreuzer 2020-03-09 21:57:44 +01:00 committed by GitHub
parent 857679f66b
commit 427e969ef9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 202 additions and 147 deletions

View File

@ -19,14 +19,14 @@ import org.eclipse.emf.ecore.EObject;
import org.openhab.core.persistence.PersistenceManager;
import org.openhab.core.persistence.PersistenceService;
import org.openhab.core.persistence.PersistenceServiceConfiguration;
import org.openhab.core.persistence.SimpleFilter;
import org.openhab.core.persistence.SimpleItemConfiguration;
import org.openhab.core.persistence.config.SimpleAllConfig;
import org.openhab.core.persistence.config.SimpleConfig;
import org.openhab.core.persistence.config.SimpleGroupConfig;
import org.openhab.core.persistence.config.SimpleItemConfig;
import org.openhab.core.persistence.strategy.SimpleCronStrategy;
import org.openhab.core.persistence.strategy.SimpleStrategy;
import org.openhab.core.persistence.PersistenceFilter;
import org.openhab.core.persistence.PersistenceItemConfiguration;
import org.openhab.core.persistence.config.PersistenceAllConfig;
import org.openhab.core.persistence.config.PersistenceConfig;
import org.openhab.core.persistence.config.PersistenceGroupConfig;
import org.openhab.core.persistence.config.PersistenceItemConfig;
import org.openhab.core.persistence.strategy.PersistenceCronStrategy;
import org.openhab.core.persistence.strategy.PersistenceStrategy;
import org.openhab.core.model.core.EventType;
import org.openhab.core.model.core.ModelRepository;
import org.openhab.core.model.core.ModelRepositoryChangeListener;
@ -120,55 +120,55 @@ public class PersistenceModelManager implements ModelRepositoryChangeListener {
return modelName.substring(0, modelName.length() - ".persist".length());
}
private List<SimpleItemConfiguration> mapConfigs(List<PersistenceConfiguration> configs) {
final List<SimpleItemConfiguration> lst = new LinkedList<>();
private List<PersistenceItemConfiguration> mapConfigs(List<PersistenceConfiguration> configs) {
final List<PersistenceItemConfiguration> lst = new LinkedList<>();
for (final PersistenceConfiguration config : configs) {
lst.add(mapConfig(config));
}
return lst;
}
private SimpleItemConfiguration mapConfig(PersistenceConfiguration config) {
final List<SimpleConfig> items = new LinkedList<>();
private PersistenceItemConfiguration mapConfig(PersistenceConfiguration config) {
final List<PersistenceConfig> items = new LinkedList<>();
for (final EObject item : config.getItems()) {
if (item instanceof AllConfig) {
items.add(new SimpleAllConfig());
items.add(new PersistenceAllConfig());
} else if (item instanceof GroupConfig) {
items.add(new SimpleGroupConfig(((GroupConfig) item).getGroup()));
items.add(new PersistenceGroupConfig(((GroupConfig) item).getGroup()));
} else if (item instanceof ItemConfig) {
items.add(new SimpleItemConfig(((ItemConfig) item).getItem()));
items.add(new PersistenceItemConfig(((ItemConfig) item).getItem()));
}
}
return new SimpleItemConfiguration(items, config.getAlias(), mapStrategies(config.getStrategies()),
return new PersistenceItemConfiguration(items, config.getAlias(), mapStrategies(config.getStrategies()),
mapFilters(config.getFilters()));
}
private List<SimpleStrategy> mapStrategies(List<Strategy> strategies) {
final List<SimpleStrategy> lst = new LinkedList<>();
private List<PersistenceStrategy> mapStrategies(List<Strategy> strategies) {
final List<PersistenceStrategy> lst = new LinkedList<>();
for (final Strategy strategy : strategies) {
lst.add(mapStrategy(strategy));
}
return lst;
}
private SimpleStrategy mapStrategy(Strategy strategy) {
private PersistenceStrategy mapStrategy(Strategy strategy) {
if (strategy instanceof CronStrategy) {
return new SimpleCronStrategy(strategy.getName(), ((CronStrategy) strategy).getCronExpression());
return new PersistenceCronStrategy(strategy.getName(), ((CronStrategy) strategy).getCronExpression());
} else {
return new SimpleStrategy(strategy.getName());
return new PersistenceStrategy(strategy.getName());
}
}
private List<SimpleFilter> mapFilters(List<Filter> filters) {
final List<SimpleFilter> lst = new LinkedList<>();
private List<PersistenceFilter> mapFilters(List<Filter> filters) {
final List<PersistenceFilter> lst = new LinkedList<>();
for (final Filter filter : filters) {
lst.add(mapFilter(filter));
}
return lst;
}
private SimpleFilter mapFilter(Filter filter) {
return new SimpleFilter();
private PersistenceFilter mapFilter(Filter filter) {
return new PersistenceFilter();
}
}

View File

@ -12,11 +12,14 @@
*/
package org.openhab.core.persistence;
import org.eclipse.jdt.annotation.NonNullByDefault;
/**
*
*
* @author Markus Rathgeb - Initial contribution
*/
public class SimpleFilter {
@NonNullByDefault
public class PersistenceFilter {
}

View File

@ -15,42 +15,45 @@ package org.openhab.core.persistence;
import java.util.Arrays;
import java.util.List;
import org.openhab.core.persistence.config.SimpleConfig;
import org.openhab.core.persistence.strategy.SimpleStrategy;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.core.persistence.config.PersistenceConfig;
import org.openhab.core.persistence.strategy.PersistenceStrategy;
/**
* This class holds the configuration of a persistence strategy for specific items.
*
* @author Markus Rathgeb - Initial contribution
*/
public class SimpleItemConfiguration {
@NonNullByDefault
public class PersistenceItemConfiguration {
private final List<SimpleConfig> items;
private final String alias;
private final List<SimpleStrategy> strategies;
private final List<SimpleFilter> filters;
private final List<PersistenceConfig> items;
private final @Nullable String alias;
private final @Nullable List<PersistenceStrategy> strategies;
private final @Nullable List<PersistenceFilter> filters;
public SimpleItemConfiguration(final List<SimpleConfig> items, final String alias,
final List<SimpleStrategy> strategies, final List<SimpleFilter> filters) {
public PersistenceItemConfiguration(final List<PersistenceConfig> items, @Nullable final String alias,
@Nullable final List<PersistenceStrategy> strategies, @Nullable final List<PersistenceFilter> filters) {
this.items = items;
this.alias = alias;
this.strategies = strategies;
this.filters = filters;
}
public List<SimpleConfig> getItems() {
public List<PersistenceConfig> getItems() {
return items;
}
public String getAlias() {
public @Nullable String getAlias() {
return alias;
}
public List<SimpleStrategy> getStrategies() {
public @Nullable List<PersistenceStrategy> getStrategies() {
return strategies;
}
public List<SimpleFilter> getFilters() {
public @Nullable List<PersistenceFilter> getFilters() {
return filters;
}

View File

@ -12,11 +12,13 @@
*/
package org.openhab.core.persistence;
import java.util.List;
import java.util.Locale;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.core.items.Item;
import org.openhab.core.persistence.strategy.PersistenceStrategy;
/**
* A persistence service which can be used to store data from openHAB.
@ -69,5 +71,12 @@ public interface PersistenceService {
* @param item the item which state should be persisted.
* @param alias the alias under which the item should be persisted.
*/
void store(Item item, String alias);
void store(Item item, @Nullable String alias);
/**
* Provides default persistence strategies that are used for all items if no user defined configuration is found.
*
* @return The default persistence strategies
*/
List<PersistenceStrategy> getDefaultStrategies();
}

View File

@ -12,24 +12,27 @@
*/
package org.openhab.core.persistence;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import org.openhab.core.persistence.strategy.SimpleStrategy;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.core.persistence.strategy.PersistenceStrategy;
/**
* This class represents the configuration for a persistence service.
*
* @author Markus Rathgeb - Initial contribution
*/
@NonNullByDefault
public class PersistenceServiceConfiguration {
private final List<SimpleItemConfiguration> configs;
private final List<SimpleStrategy> defaults;
private final List<SimpleStrategy> strategies;
private final List<PersistenceItemConfiguration> configs;
private final List<PersistenceStrategy> defaults;
private final List<PersistenceStrategy> strategies;
public PersistenceServiceConfiguration(final List<SimpleItemConfiguration> configs,
final List<SimpleStrategy> defaults, final List<SimpleStrategy> strategies) {
public PersistenceServiceConfiguration(final Collection<PersistenceItemConfiguration> configs,
final Collection<PersistenceStrategy> defaults, final Collection<PersistenceStrategy> strategies) {
this.configs = Collections.unmodifiableList(new LinkedList<>(configs));
this.defaults = Collections.unmodifiableList(new LinkedList<>(defaults));
this.strategies = Collections.unmodifiableList(new LinkedList<>(strategies));
@ -40,7 +43,7 @@ public class PersistenceServiceConfiguration {
*
* @return an unmodifiable list of the item configurations
*/
public List<SimpleItemConfiguration> getConfigs() {
public List<PersistenceItemConfiguration> getConfigs() {
return configs;
}
@ -49,7 +52,7 @@ public class PersistenceServiceConfiguration {
*
* @return an unmodifiable list of the default strategies
*/
public List<SimpleStrategy> getDefaults() {
public List<PersistenceStrategy> getDefaults() {
return defaults;
}
@ -58,7 +61,7 @@ public class PersistenceServiceConfiguration {
*
* @return an unmodifiable list of the defined strategies
*/
public List<SimpleStrategy> getStrategies() {
public List<PersistenceStrategy> getStrategies() {
return strategies;
}

View File

@ -12,12 +12,15 @@
*/
package org.openhab.core.persistence.config;
import org.eclipse.jdt.annotation.NonNullByDefault;
/**
* This class represents the configuration that stand for "using all items".
*
* @author Markus Rathgeb - Initial contribution
*/
public class SimpleAllConfig extends SimpleConfig {
@NonNullByDefault
public class PersistenceAllConfig extends PersistenceConfig {
@Override
public String toString() {

View File

@ -12,11 +12,14 @@
*/
package org.openhab.core.persistence.config;
import org.eclipse.jdt.annotation.NonNullByDefault;
/**
* This class is a base class that needs to be used by every item configuration.
*
* @author Markus Rathgeb - Initial contribution
*/
public abstract class SimpleConfig {
@NonNullByDefault
public abstract class PersistenceConfig {
}

View File

@ -12,16 +12,19 @@
*/
package org.openhab.core.persistence.config;
import org.eclipse.jdt.annotation.NonNullByDefault;
/**
* This class represents the configuration that is used for group items.
*
* @author Markus Rathgeb - Initial contribution
*/
public class SimpleGroupConfig extends SimpleConfig {
@NonNullByDefault
public class PersistenceGroupConfig extends PersistenceConfig {
private final String group;
public SimpleGroupConfig(final String group) {
public PersistenceGroupConfig(final String group) {
this.group = group;
}

View File

@ -12,15 +12,18 @@
*/
package org.openhab.core.persistence.config;
import org.eclipse.jdt.annotation.NonNullByDefault;
/**
* This class represents the configuration that identify item(s) by name.
*
* @author Markus Rathgeb - Initial contribution
*/
public class SimpleItemConfig extends SimpleConfig {
@NonNullByDefault
public class PersistenceItemConfig extends PersistenceConfig {
final String item;
public SimpleItemConfig(final String item) {
public PersistenceItemConfig(final String item) {
this.item = item;
}

View File

@ -18,8 +18,8 @@ import java.util.concurrent.TimeUnit;
import org.openhab.core.items.Item;
import org.openhab.core.persistence.PersistenceService;
import org.openhab.core.persistence.PersistenceServiceConfiguration;
import org.openhab.core.persistence.SimpleItemConfiguration;
import org.openhab.core.persistence.strategy.SimpleStrategy;
import org.openhab.core.persistence.PersistenceItemConfiguration;
import org.openhab.core.persistence.strategy.PersistenceStrategy;
import org.openhab.core.scheduler.SchedulerRunnable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -51,7 +51,7 @@ public class PersistItemsJob implements SchedulerRunnable {
final PersistenceServiceConfiguration config = manager.persistenceServiceConfigs.get(dbId);
if (persistenceService != null) {
for (SimpleItemConfiguration itemConfig : config.getConfigs()) {
for (PersistenceItemConfiguration itemConfig : config.getConfigs()) {
if (hasStrategy(config.getDefaults(), itemConfig, strategyName)) {
for (Item item : manager.getAllItems(itemConfig)) {
long startTime = System.nanoTime();
@ -66,9 +66,9 @@ public class PersistItemsJob implements SchedulerRunnable {
}
}
private boolean hasStrategy(List<SimpleStrategy> defaults, SimpleItemConfiguration config, String strategyName) {
private boolean hasStrategy(List<PersistenceStrategy> defaults, PersistenceItemConfiguration config, String strategyName) {
// check if the strategy is directly defined on the config
for (SimpleStrategy strategy : config.getStrategies()) {
for (PersistenceStrategy strategy : config.getStrategies()) {
if (strategyName.equals(strategy.getName())) {
return true;
}
@ -80,8 +80,8 @@ public class PersistItemsJob implements SchedulerRunnable {
return false;
}
private boolean isDefault(List<SimpleStrategy> defaults, String strategyName) {
for (SimpleStrategy strategy : defaults) {
private boolean isDefault(List<PersistenceStrategy> defaults, String strategyName) {
for (PersistenceStrategy strategy : defaults) {
if (strategy.getName().equals(strategyName)) {
return true;
}

View File

@ -24,6 +24,7 @@ import java.util.Map.Entry;
import java.util.Set;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.core.common.SafeCaller;
import org.openhab.core.items.GenericItem;
import org.openhab.core.items.GroupItem;
@ -34,17 +35,17 @@ import org.openhab.core.items.ItemRegistryChangeListener;
import org.openhab.core.items.StateChangeListener;
import org.openhab.core.persistence.FilterCriteria;
import org.openhab.core.persistence.HistoricItem;
import org.openhab.core.persistence.PersistenceItemConfiguration;
import org.openhab.core.persistence.PersistenceManager;
import org.openhab.core.persistence.PersistenceService;
import org.openhab.core.persistence.PersistenceServiceConfiguration;
import org.openhab.core.persistence.QueryablePersistenceService;
import org.openhab.core.persistence.SimpleItemConfiguration;
import org.openhab.core.persistence.config.SimpleAllConfig;
import org.openhab.core.persistence.config.SimpleConfig;
import org.openhab.core.persistence.config.SimpleGroupConfig;
import org.openhab.core.persistence.config.SimpleItemConfig;
import org.openhab.core.persistence.strategy.SimpleCronStrategy;
import org.openhab.core.persistence.strategy.SimpleStrategy;
import org.openhab.core.persistence.config.PersistenceAllConfig;
import org.openhab.core.persistence.config.PersistenceConfig;
import org.openhab.core.persistence.config.PersistenceGroupConfig;
import org.openhab.core.persistence.config.PersistenceItemConfig;
import org.openhab.core.persistence.strategy.PersistenceCronStrategy;
import org.openhab.core.persistence.strategy.PersistenceStrategy;
import org.openhab.core.scheduler.CronScheduler;
import org.openhab.core.scheduler.ScheduledCompletableFuture;
import org.openhab.core.types.State;
@ -77,7 +78,7 @@ public class PersistenceManagerImpl implements ItemRegistryChangeListener, Persi
private volatile boolean started = false;
final Map<String, PersistenceService> persistenceServices = new HashMap<>();
final Map<String, PersistenceServiceConfiguration> persistenceServiceConfigs = new HashMap<>();
final Map<String, @Nullable PersistenceServiceConfiguration> persistenceServiceConfigs = new HashMap<>();
private final Map<String, Set<ScheduledCompletableFuture<?>>> persistenceJobs = new HashMap<>();
@Activate
@ -107,6 +108,7 @@ public class PersistenceManagerImpl implements ItemRegistryChangeListener, Persi
protected void addPersistenceService(PersistenceService persistenceService) {
logger.debug("Initializing {} persistence service.", persistenceService.getId());
persistenceServices.put(persistenceService.getId(), persistenceService);
persistenceServiceConfigs.putIfAbsent(persistenceService.getId(), getDefaultConfig(persistenceService));
if (started) {
stopEventHandling(persistenceService.getId());
startEventHandling(persistenceService.getId());
@ -126,13 +128,14 @@ public class PersistenceManagerImpl implements ItemRegistryChangeListener, Persi
*/
private void handleStateEvent(Item item, boolean onlyChanges) {
synchronized (persistenceServiceConfigs) {
for (Entry<String, PersistenceServiceConfiguration> entry : persistenceServiceConfigs.entrySet()) {
for (Entry<String, @Nullable PersistenceServiceConfiguration> entry : persistenceServiceConfigs
.entrySet()) {
final String serviceName = entry.getKey();
final PersistenceServiceConfiguration config = entry.getValue();
if (persistenceServices.containsKey(serviceName)) {
for (SimpleItemConfiguration itemConfig : config.getConfigs()) {
if (hasStrategy(config, itemConfig,
onlyChanges ? SimpleStrategy.Globals.CHANGE : SimpleStrategy.Globals.UPDATE)) {
if (config != null && persistenceServices.containsKey(serviceName)) {
for (PersistenceItemConfiguration itemConfig : config.getConfigs()) {
if (hasStrategy(config, itemConfig, onlyChanges ? PersistenceStrategy.Globals.CHANGE
: PersistenceStrategy.Globals.UPDATE)) {
if (appliesToItem(itemConfig, item)) {
persistenceServices.get(serviceName).store(item, itemConfig.getAlias());
}
@ -151,12 +154,12 @@ public class PersistenceManagerImpl implements ItemRegistryChangeListener, Persi
* @param strategy the strategy to check for
* @return true, if it has the given strategy
*/
private boolean hasStrategy(PersistenceServiceConfiguration config, SimpleItemConfiguration itemConfig,
SimpleStrategy strategy) {
private boolean hasStrategy(PersistenceServiceConfiguration config, PersistenceItemConfiguration itemConfig,
PersistenceStrategy strategy) {
if (config.getDefaults().contains(strategy) && itemConfig.getStrategies().isEmpty()) {
return true;
} else {
for (SimpleStrategy s : itemConfig.getStrategies()) {
for (PersistenceStrategy s : itemConfig.getStrategies()) {
if (s.equals(strategy)) {
return true;
}
@ -172,19 +175,19 @@ public class PersistenceManagerImpl implements ItemRegistryChangeListener, Persi
* @param item to check if the configuration applies to
* @return true, if the configuration applies to the item
*/
private boolean appliesToItem(SimpleItemConfiguration config, Item item) {
for (SimpleConfig itemCfg : config.getItems()) {
if (itemCfg instanceof SimpleAllConfig) {
private boolean appliesToItem(PersistenceItemConfiguration config, Item item) {
for (PersistenceConfig itemCfg : config.getItems()) {
if (itemCfg instanceof PersistenceAllConfig) {
return true;
}
if (itemCfg instanceof SimpleItemConfig) {
SimpleItemConfig singleItemConfig = (SimpleItemConfig) itemCfg;
if (itemCfg instanceof PersistenceItemConfig) {
PersistenceItemConfig singleItemConfig = (PersistenceItemConfig) itemCfg;
if (item.getName().equals(singleItemConfig.getItem())) {
return true;
}
}
if (itemCfg instanceof SimpleGroupConfig) {
SimpleGroupConfig groupItemConfig = (SimpleGroupConfig) itemCfg;
if (itemCfg instanceof PersistenceGroupConfig) {
PersistenceGroupConfig groupItemConfig = (PersistenceGroupConfig) itemCfg;
try {
Item gItem = itemRegistry.getItem(groupItemConfig.getGroup());
if (gItem instanceof GroupItem) {
@ -207,10 +210,10 @@ public class PersistenceManagerImpl implements ItemRegistryChangeListener, Persi
* @param config the persistence configuration entry
* @return all items that this configuration applies to
*/
Iterable<Item> getAllItems(SimpleItemConfiguration config) {
Iterable<Item> getAllItems(PersistenceItemConfiguration config) {
// first check, if we should return them all
for (Object itemCfg : config.getItems()) {
if (itemCfg instanceof SimpleAllConfig) {
if (itemCfg instanceof PersistenceAllConfig) {
return itemRegistry.getItems();
}
}
@ -218,8 +221,8 @@ public class PersistenceManagerImpl implements ItemRegistryChangeListener, Persi
// otherwise, go through the detailed definitions
Set<Item> items = new HashSet<>();
for (Object itemCfg : config.getItems()) {
if (itemCfg instanceof SimpleItemConfig) {
SimpleItemConfig singleItemConfig = (SimpleItemConfig) itemCfg;
if (itemCfg instanceof PersistenceItemConfig) {
PersistenceItemConfig singleItemConfig = (PersistenceItemConfig) itemCfg;
String itemName = singleItemConfig.getItem();
try {
items.add(itemRegistry.getItem(itemName));
@ -227,8 +230,8 @@ public class PersistenceManagerImpl implements ItemRegistryChangeListener, Persi
logger.debug("Item '{}' does not exist.", itemName);
}
}
if (itemCfg instanceof SimpleGroupConfig) {
SimpleGroupConfig groupItemConfig = (SimpleGroupConfig) itemCfg;
if (itemCfg instanceof PersistenceGroupConfig) {
PersistenceGroupConfig groupItemConfig = (PersistenceGroupConfig) itemCfg;
String groupName = groupItemConfig.getGroup();
try {
Item gItem = itemRegistry.getItem(groupName);
@ -256,46 +259,50 @@ public class PersistenceManagerImpl implements ItemRegistryChangeListener, Persi
private void initialize(Item item) {
// get the last persisted state from the persistence service if no state is yet set
if (item.getState().equals(UnDefType.NULL) && item instanceof GenericItem) {
for (Entry<String, PersistenceServiceConfiguration> entry : persistenceServiceConfigs.entrySet()) {
for (Entry<String, @Nullable PersistenceServiceConfiguration> entry : persistenceServiceConfigs
.entrySet()) {
final String serviceName = entry.getKey();
final PersistenceServiceConfiguration config = entry.getValue();
for (SimpleItemConfiguration itemConfig : config.getConfigs()) {
if (hasStrategy(config, itemConfig, SimpleStrategy.Globals.RESTORE)) {
if (appliesToItem(itemConfig, item)) {
PersistenceService service = persistenceServices.get(serviceName);
if (service instanceof QueryablePersistenceService) {
QueryablePersistenceService queryService = (QueryablePersistenceService) service;
FilterCriteria filter = new FilterCriteria().setItemName(item.getName()).setPageSize(1);
Iterable<HistoricItem> result = safeCaller
.create(queryService, QueryablePersistenceService.class).onTimeout(() -> {
logger.warn("Querying persistence service '{}' takes more than {}ms.",
queryService.getId(), SafeCaller.DEFAULT_TIMEOUT);
}).onException(e -> {
logger.error(
"Exception occurred while querying persistence service '{}': {}",
queryService.getId(), e.getMessage(), e);
}).build().query(filter);
if (result != null) {
Iterator<HistoricItem> it = result.iterator();
if (it.hasNext()) {
HistoricItem historicItem = it.next();
GenericItem genericItem = (GenericItem) item;
genericItem.removeStateChangeListener(this);
genericItem.setState(historicItem.getState());
genericItem.addStateChangeListener(this);
if (logger.isDebugEnabled()) {
logger.debug("Restored item state from '{}' for item '{}' -> '{}'",
DateFormat.getDateTimeInstance()
.format(historicItem.getTimestamp()),
item.getName(), historicItem.getState());
if (config != null) {
for (PersistenceItemConfiguration itemConfig : config.getConfigs()) {
if (hasStrategy(config, itemConfig, PersistenceStrategy.Globals.RESTORE)) {
if (appliesToItem(itemConfig, item)) {
PersistenceService service = persistenceServices.get(serviceName);
if (service instanceof QueryablePersistenceService) {
QueryablePersistenceService queryService = (QueryablePersistenceService) service;
FilterCriteria filter = new FilterCriteria().setItemName(item.getName())
.setPageSize(1);
Iterable<HistoricItem> result = safeCaller
.create(queryService, QueryablePersistenceService.class).onTimeout(() -> {
logger.warn("Querying persistence service '{}' takes more than {}ms.",
queryService.getId(), SafeCaller.DEFAULT_TIMEOUT);
}).onException(e -> {
logger.error(
"Exception occurred while querying persistence service '{}': {}",
queryService.getId(), e.getMessage(), e);
}).build().query(filter);
if (result != null) {
Iterator<HistoricItem> it = result.iterator();
if (it.hasNext()) {
HistoricItem historicItem = it.next();
GenericItem genericItem = (GenericItem) item;
genericItem.removeStateChangeListener(this);
genericItem.setState(historicItem.getState());
genericItem.addStateChangeListener(this);
if (logger.isDebugEnabled()) {
logger.debug("Restored item state from '{}' for item '{}' -> '{}'",
DateFormat.getDateTimeInstance()
.format(historicItem.getTimestamp()),
item.getName(), historicItem.getState());
}
return;
}
return;
}
} else if (service != null) {
logger.warn(
"Failed to restore item states as persistence service '{}' cannot be queried.",
serviceName);
}
} else if (service != null) {
logger.warn(
"Failed to restore item states as persistence service '{}' can not be queried.",
serviceName);
}
}
}
@ -314,15 +321,15 @@ public class PersistenceManagerImpl implements ItemRegistryChangeListener, Persi
/**
* Creates new {@link ScheduledCompletableFuture}s in the group <code>dbId</code> for the given collection of
* {@link SimpleStrategy strategies}.
* {@link PersistenceStrategy strategies}.
*
* @param dbId the database id used by the persistence service
* @param strategies a collection of strategies
*/
private void createTimers(final String dbId, List<SimpleStrategy> strategies) {
for (SimpleStrategy strategy : strategies) {
if (strategy instanceof SimpleCronStrategy) {
SimpleCronStrategy cronStrategy = (SimpleCronStrategy) strategy;
private void createTimers(final String dbId, List<PersistenceStrategy> strategies) {
for (PersistenceStrategy strategy : strategies) {
if (strategy instanceof PersistenceCronStrategy) {
PersistenceCronStrategy cronStrategy = (PersistenceCronStrategy) strategy;
String cronExpression = cronStrategy.getCronExpression();
final PersistItemsJob job = new PersistItemsJob(this, dbId, cronStrategy.getName());
@ -366,6 +373,9 @@ public class PersistenceManagerImpl implements ItemRegistryChangeListener, Persi
@Override
public void addConfig(final String dbId, final PersistenceServiceConfiguration config) {
synchronized (persistenceServiceConfigs) {
if (persistenceServiceConfigs.containsKey(dbId)) {
stopEventHandling(dbId);
}
persistenceServiceConfigs.put(dbId, config);
if (persistenceServices.containsKey(dbId)) {
startEventHandling(dbId);
@ -377,7 +387,12 @@ public class PersistenceManagerImpl implements ItemRegistryChangeListener, Persi
public void removeConfig(final String dbId) {
synchronized (persistenceServiceConfigs) {
stopEventHandling(dbId);
persistenceServiceConfigs.remove(dbId);
if (persistenceServices.containsKey(dbId)) {
persistenceServiceConfigs.put(dbId, getDefaultConfig(persistenceServices.get(dbId)));
startEventHandling(dbId);
} else {
persistenceServiceConfigs.remove(dbId);
}
}
}
@ -385,8 +400,8 @@ public class PersistenceManagerImpl implements ItemRegistryChangeListener, Persi
synchronized (persistenceServiceConfigs) {
final PersistenceServiceConfiguration config = persistenceServiceConfigs.get(serviceName);
if (config != null) {
for (SimpleItemConfiguration itemConfig : config.getConfigs()) {
if (hasStrategy(config, itemConfig, SimpleStrategy.Globals.RESTORE)) {
for (PersistenceItemConfiguration itemConfig : config.getConfigs()) {
if (hasStrategy(config, itemConfig, PersistenceStrategy.Globals.RESTORE)) {
for (Item item : getAllItems(itemConfig)) {
initialize(item);
}
@ -403,6 +418,13 @@ public class PersistenceManagerImpl implements ItemRegistryChangeListener, Persi
}
}
private @Nullable PersistenceServiceConfiguration getDefaultConfig(PersistenceService persistenceService) {
List<PersistenceStrategy> strategies = persistenceService.getDefaultStrategies();
List<PersistenceItemConfiguration> configs = Collections.singletonList(new PersistenceItemConfiguration(
Collections.singletonList(new PersistenceAllConfig()), null, strategies, null));
return new PersistenceServiceConfiguration(configs, strategies, strategies);
}
@Override
public void allItemsChanged(Collection<String> oldItemNames) {
for (Item item : itemRegistry.getItems()) {

View File

@ -17,11 +17,11 @@ package org.openhab.core.persistence.strategy;
*
* @author Markus Rathgeb - Initial contribution
*/
public class SimpleCronStrategy extends SimpleStrategy {
public class PersistenceCronStrategy extends PersistenceStrategy {
private final String cronExpression;
public SimpleCronStrategy(final String name, final String cronExpression) {
public PersistenceCronStrategy(final String name, final String cronExpression) {
super(name);
this.cronExpression = cronExpression;
}

View File

@ -19,16 +19,16 @@ import java.util.Objects;
*
* @author Markus Rathgeb - Initial contribution
*/
public class SimpleStrategy {
public class PersistenceStrategy {
public static class Globals {
public static final SimpleStrategy UPDATE = new SimpleStrategy("everyUpdate");
public static final SimpleStrategy CHANGE = new SimpleStrategy("everyChange");
public static final SimpleStrategy RESTORE = new SimpleStrategy("restoreOnStartup");
public static final PersistenceStrategy UPDATE = new PersistenceStrategy("everyUpdate");
public static final PersistenceStrategy CHANGE = new PersistenceStrategy("everyChange");
public static final PersistenceStrategy RESTORE = new PersistenceStrategy("restoreOnStartup");
}
private final String name;
public SimpleStrategy(final String name) {
public PersistenceStrategy(final String name) {
this.name = name;
}
@ -52,13 +52,10 @@ public class SimpleStrategy {
if (obj == null) {
return false;
}
// if (getClass() != obj.getClass()) {
// return false;
// }
if (!(obj instanceof SimpleStrategy)) {
if (!(obj instanceof PersistenceStrategy)) {
return false;
}
final SimpleStrategy other = (SimpleStrategy) obj;
final PersistenceStrategy other = (PersistenceStrategy) obj;
if (!Objects.equals(name, other.name)) {
return false;
}

View File

@ -28,6 +28,7 @@ import org.openhab.core.persistence.FilterCriteria.Ordering;
import org.openhab.core.persistence.HistoricItem;
import org.openhab.core.persistence.PersistenceItemInfo;
import org.openhab.core.persistence.QueryablePersistenceService;
import org.openhab.core.persistence.strategy.PersistenceStrategy;
import org.openhab.core.types.State;
/**
@ -50,7 +51,7 @@ public class TestPersistenceService implements QueryablePersistenceService {
}
@Override
public void store(Item item, String alias) {
public void store(Item item, @Nullable String alias) {
}
@SuppressWarnings("deprecation")
@ -106,4 +107,9 @@ public class TestPersistenceService implements QueryablePersistenceService {
return "Test Label";
}
@Override
public List<PersistenceStrategy> getDefaultStrategies() {
return Collections.emptyList();
}
}