mirror of
https://github.com/danieldemus/openhab-core.git
synced 2025-01-26 20:21:33 +01:00
Persistence extensions, add lastChange and nextChange (#4259)
* add lastChange and nextChange Signed-off-by: Mark Herwege <mark.herwege@telenet.be>
This commit is contained in:
parent
93b53e7847
commit
cb65e41445
@ -60,6 +60,7 @@ import org.slf4j.LoggerFactory;
|
|||||||
* @author Jan N. Klug - Added interval methods and refactoring
|
* @author Jan N. Klug - Added interval methods and refactoring
|
||||||
* @author Mark Herwege - Changed return types to State for some interval methods to also return unit
|
* @author Mark Herwege - Changed return types to State for some interval methods to also return unit
|
||||||
* @author Mark Herwege - Extended for future dates
|
* @author Mark Herwege - Extended for future dates
|
||||||
|
* @author Mark Herwege - lastChange and nextChange methods
|
||||||
*/
|
*/
|
||||||
@Component(immediate = true)
|
@Component(immediate = true)
|
||||||
@NonNullByDefault
|
@NonNullByDefault
|
||||||
@ -323,9 +324,9 @@ public class PersistenceExtensions {
|
|||||||
* Query the last historic update time of a given <code>item</code>. The default persistence service is used.
|
* Query the last historic update time of a given <code>item</code>. The default persistence service is used.
|
||||||
*
|
*
|
||||||
* @param item the item for which the last historic update time is to be returned
|
* @param item the item for which the last historic update time is to be returned
|
||||||
* @return point in time of the last historic update to <code>item</code>, or <code>null</code> if there are no
|
* @return point in time of the last historic update to <code>item</code>, <code>null</code> if there are no
|
||||||
* historic persisted updates or the default persistence service is not available or not a
|
* historic persisted updates, the state has changed since the last update or the default persistence
|
||||||
* {@link QueryablePersistenceService}
|
* service is not available or not a {@link QueryablePersistenceService}
|
||||||
*/
|
*/
|
||||||
public static @Nullable ZonedDateTime lastUpdate(Item item) {
|
public static @Nullable ZonedDateTime lastUpdate(Item item) {
|
||||||
return internalAdjacentUpdate(item, false, null);
|
return internalAdjacentUpdate(item, false, null);
|
||||||
@ -336,9 +337,9 @@ public class PersistenceExtensions {
|
|||||||
*
|
*
|
||||||
* @param item the item for which the last historic update time is to be returned
|
* @param item the item for which the last historic update time is to be returned
|
||||||
* @param serviceId the name of the {@link PersistenceService} to use
|
* @param serviceId the name of the {@link PersistenceService} to use
|
||||||
* @return point in time of the last historic update to <code>item</code>, or <code>null</code> if there are no
|
* @return point in time of the last historic update to <code>item</code>, <code>null</code> if there are no
|
||||||
* historic persisted updates or if persistence service given by <code>serviceId</code> does not refer to an
|
* historic persisted updates, the state has changed since the last update or if persistence service given
|
||||||
* available {@link QueryablePersistenceService}
|
* by <code>serviceId</code> does not refer to an available {@link QueryablePersistenceService}
|
||||||
*/
|
*/
|
||||||
public static @Nullable ZonedDateTime lastUpdate(Item item, @Nullable String serviceId) {
|
public static @Nullable ZonedDateTime lastUpdate(Item item, @Nullable String serviceId) {
|
||||||
return internalAdjacentUpdate(item, false, serviceId);
|
return internalAdjacentUpdate(item, false, serviceId);
|
||||||
@ -371,6 +372,66 @@ public class PersistenceExtensions {
|
|||||||
|
|
||||||
private static @Nullable ZonedDateTime internalAdjacentUpdate(Item item, boolean forward,
|
private static @Nullable ZonedDateTime internalAdjacentUpdate(Item item, boolean forward,
|
||||||
@Nullable String serviceId) {
|
@Nullable String serviceId) {
|
||||||
|
return internalAdjacent(item, forward, false, serviceId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Query the last historic change time of a given <code>item</code>. The default persistence service is used.
|
||||||
|
*
|
||||||
|
* @param item the item for which the last historic change time is to be returned
|
||||||
|
* @return point in time of the last historic change to <code>item</code>, <code>null</code> if there are no
|
||||||
|
* historic persisted changes, the state has changed since the last update or the default persistence
|
||||||
|
* service is not available or not a {@link QueryablePersistenceService}
|
||||||
|
*/
|
||||||
|
public static @Nullable ZonedDateTime lastChange(Item item) {
|
||||||
|
return internalAdjacentChange(item, false, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Query for the last historic change time of a given <code>item</code>.
|
||||||
|
*
|
||||||
|
* @param item the item for which the last historic change time is to be returned
|
||||||
|
* @param serviceId the name of the {@link PersistenceService} to use
|
||||||
|
* @return point in time of the last historic change to <code>item</code> <code>null</code> if there are no
|
||||||
|
* historic persisted changes, the state has changed since the last update or if persistence service given
|
||||||
|
* by <code>serviceId</code> does not refer to an available {@link QueryablePersistenceService}
|
||||||
|
*/
|
||||||
|
public static @Nullable ZonedDateTime lastChange(Item item, @Nullable String serviceId) {
|
||||||
|
return internalAdjacentChange(item, false, serviceId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Query the first future change time of a given <code>item</code>. The default persistence service is used.
|
||||||
|
*
|
||||||
|
* @param item the item for which the first future change time is to be returned
|
||||||
|
* @return point in time of the first future change to <code>item</code>, or <code>null</code> if there are no
|
||||||
|
* future persisted changes or the default persistence service is not available or not a
|
||||||
|
* {@link QueryablePersistenceService}
|
||||||
|
*/
|
||||||
|
public static @Nullable ZonedDateTime nextChange(Item item) {
|
||||||
|
return internalAdjacentChange(item, true, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Query for the first future change time of a given <code>item</code>.
|
||||||
|
*
|
||||||
|
* @param item the item for which the first future change time is to be returned
|
||||||
|
* @param serviceId the name of the {@link PersistenceService} to use
|
||||||
|
* @return point in time of the first future change to <code>item</code>, or <code>null</code> if there are no
|
||||||
|
* future persisted changes or if persistence service given by <code>serviceId</code> does not refer to an
|
||||||
|
* available {@link QueryablePersistenceService}
|
||||||
|
*/
|
||||||
|
public static @Nullable ZonedDateTime nextChange(Item item, @Nullable String serviceId) {
|
||||||
|
return internalAdjacentChange(item, true, serviceId);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static @Nullable ZonedDateTime internalAdjacentChange(Item item, boolean forward,
|
||||||
|
@Nullable String serviceId) {
|
||||||
|
return internalAdjacent(item, forward, true, serviceId);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static @Nullable ZonedDateTime internalAdjacent(Item item, boolean forward, boolean skipEqual,
|
||||||
|
@Nullable String serviceId) {
|
||||||
String effectiveServiceId = serviceId == null ? getDefaultServiceId() : serviceId;
|
String effectiveServiceId = serviceId == null ? getDefaultServiceId() : serviceId;
|
||||||
if (effectiveServiceId == null) {
|
if (effectiveServiceId == null) {
|
||||||
return null;
|
return null;
|
||||||
@ -385,10 +446,49 @@ public class PersistenceExtensions {
|
|||||||
filter.setEndDate(ZonedDateTime.now());
|
filter.setEndDate(ZonedDateTime.now());
|
||||||
}
|
}
|
||||||
filter.setOrdering(forward ? Ordering.ASCENDING : Ordering.DESCENDING);
|
filter.setOrdering(forward ? Ordering.ASCENDING : Ordering.DESCENDING);
|
||||||
filter.setPageSize(1);
|
|
||||||
Iterable<HistoricItem> result = qService.query(filter);
|
filter.setPageSize(skipEqual ? 1000 : 1);
|
||||||
if (result.iterator().hasNext()) {
|
int startPage = 0;
|
||||||
return result.iterator().next().getTimestamp();
|
filter.setPageNumber(startPage);
|
||||||
|
|
||||||
|
Iterable<HistoricItem> items = qService.query(filter);
|
||||||
|
Iterator<HistoricItem> itemIterator = items.iterator();
|
||||||
|
State state = item.getState();
|
||||||
|
if (itemIterator.hasNext()) {
|
||||||
|
if (!skipEqual) {
|
||||||
|
HistoricItem historicItem = itemIterator.next();
|
||||||
|
if (!forward && !historicItem.getState().equals(state)) {
|
||||||
|
// Last persisted state value different from current state value, so it must have updated since
|
||||||
|
// last persist. We do not know when.
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return historicItem.getTimestamp();
|
||||||
|
} else {
|
||||||
|
HistoricItem historicItem = itemIterator.next();
|
||||||
|
int itemCount = 1;
|
||||||
|
if (!historicItem.getState().equals(state)) {
|
||||||
|
// Persisted state value different from current state value, so it must have changed, but we do
|
||||||
|
// not know when when looking backward.
|
||||||
|
return forward ? historicItem.getTimestamp() : null;
|
||||||
|
}
|
||||||
|
while (items != null) {
|
||||||
|
while (historicItem.getState().equals(state) && itemIterator.hasNext()) {
|
||||||
|
HistoricItem nextHistoricItem = itemIterator.next();
|
||||||
|
itemCount++;
|
||||||
|
if (!nextHistoricItem.getState().equals(state)) {
|
||||||
|
return forward ? nextHistoricItem.getTimestamp() : historicItem.getTimestamp();
|
||||||
|
}
|
||||||
|
historicItem = nextHistoricItem;
|
||||||
|
}
|
||||||
|
if (itemCount == filter.getPageSize()) {
|
||||||
|
filter.setPageNumber(++startPage);
|
||||||
|
items = qService.query(filter);
|
||||||
|
itemCount = 0;
|
||||||
|
} else {
|
||||||
|
items = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
LoggerFactory.getLogger(PersistenceExtensions.class)
|
LoggerFactory.getLogger(PersistenceExtensions.class)
|
||||||
|
@ -1532,6 +1532,28 @@ public class PersistenceExtensionsTest {
|
|||||||
assertNull(nextUpdate);
|
assertNull(nextUpdate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testLastChange() {
|
||||||
|
ZonedDateTime lastChange = PersistenceExtensions.lastChange(numberItem, SERVICE_ID);
|
||||||
|
assertNotNull(lastChange);
|
||||||
|
assertEquals(ZonedDateTime.of(HISTORIC_END, 1, 1, 0, 0, 0, 0, ZoneId.systemDefault()), lastChange);
|
||||||
|
|
||||||
|
// default persistence service
|
||||||
|
lastChange = PersistenceExtensions.lastChange(numberItem);
|
||||||
|
assertNull(lastChange);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testNextChange() {
|
||||||
|
ZonedDateTime nextChange = PersistenceExtensions.nextChange(numberItem, SERVICE_ID);
|
||||||
|
assertNotNull(nextChange);
|
||||||
|
assertEquals(ZonedDateTime.of(FUTURE_START, 1, 1, 0, 0, 0, 0, ZoneId.systemDefault()), nextChange);
|
||||||
|
|
||||||
|
// default persistence service
|
||||||
|
nextChange = PersistenceExtensions.nextChange(numberItem);
|
||||||
|
assertNull(nextChange);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDeltaSince() {
|
public void testDeltaSince() {
|
||||||
State delta = PersistenceExtensions.deltaSince(numberItem,
|
State delta = PersistenceExtensions.deltaSince(numberItem,
|
||||||
|
Loading…
Reference in New Issue
Block a user