> handlers) {
+ return new StoreUpdateRunnable<>(store, changeProvider, lastUpdate, message, handlers);
+ }
+}
diff --git a/src/store-sync/src/main/java/org/eclipse/lyo/store/sync/StoreUpdateRunnable.java b/src/store-sync/src/main/java/org/eclipse/lyo/store/sync/StoreUpdateRunnable.java
new file mode 100644
index 0000000..c91e279
--- /dev/null
+++ b/src/store-sync/src/main/java/org/eclipse/lyo/store/sync/StoreUpdateRunnable.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v. 1.0 which accompanies this distribution.
+ *
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: EPL-1.0 OR BSD-3-Clause
+ */
+package org.eclipse.lyo.store.sync;
+
+import java.time.ZoneId;
+import java.time.ZonedDateTime;
+import java.util.Collection;
+import java.util.Date;
+import java.util.List;
+import org.eclipse.lyo.store.Store;
+import org.eclipse.lyo.store.sync.change.Change;
+import org.eclipse.lyo.store.sync.change.ChangeProvider;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Requests latest {@link Change} collection from {@link ChangeProvider} and triggers each
+ * handler afterwards. Stores the timestamp of the newest change to request new updates starting
+ * from that point in time.
+ *
+ *
Handlers will be notified with different message per service provider as accessible via
+ * {@link OSLCMessage#getServiceProviderId()}.
+ *
+ * @author Andrew Berezovskyi (andriib@kth.se)
+ * @version $version-stub$
+ * @since 0.18.0
+ */
+class StoreUpdateRunnable implements Runnable {
+
+ private static final ZonedDateTime LAST_UPDATE_DEFAULT = ZonedDateTime.of(1971, 1, 1, 1, 1, 1,
+ 1, ZoneId.of("UTC"));
+ private final Logger log = LoggerFactory.getLogger(StoreUpdateRunnable.class);
+ private final ChangeProvider changeProvider;
+ private final M message;
+ private final Store store;
+ private final List> handlers;
+ private ZonedDateTime lastUpdate;
+
+ /**
+ * @param store Initialised Store
+ * @param changeProvider Change provider
+ * @param lastUpdate Initial timestamp. If null, will be set to {@link
+ * StoreUpdateRunnable#LAST_UPDATE_DEFAULT}
+ * @param message Initial message to the {@link ChangeProvider}
+ * @param handlers List of handlers to be notified.
+ */
+ StoreUpdateRunnable(final Store store, final ChangeProvider changeProvider,
+ final ZonedDateTime lastUpdate, final M message, final List> handlers) {
+ this.store = store;
+ this.changeProvider = changeProvider;
+ this.message = message;
+ this.handlers = handlers;
+ if (lastUpdate != null) {
+ this.lastUpdate = lastUpdate;
+ } else {
+ this.lastUpdate = StoreUpdateRunnable.LAST_UPDATE_DEFAULT;
+ }
+ }
+
+ @Override
+ public void run() {
+ try {
+ log.trace("Running background update");
+ Collection> changes = null;
+ try {
+ changes = changeProvider.getChangesSince(lastUpdate, message);
+ } catch (final Exception e) {
+ log.error("ChangeProvider threw an exception", e);
+ }
+ if (changes != null && !changes.isEmpty()) {
+ for (final Handler handler : handlers) {
+ log.trace("Notifying {}", handler);
+ try {
+ handler.handle(store, changes);
+ } catch (final Exception e) {
+ log.warn("Handler {} threw an exception", handler, e);
+ }
+ }
+ for (final Change> change : changes) {
+ if (change != null) {
+ final Date date = change.getHistoryResource().getTimestamp();
+ final ZonedDateTime dateTime = date.toInstant()
+ .atZone(ZoneId.systemDefault());
+ if (lastUpdate.isBefore(dateTime)) {
+ lastUpdate = dateTime;
+ }
+ }
+ }
+ log.trace("Setting previous revision to {}", lastUpdate);
+ }
+ } catch (final Exception e) {
+ // ExecutorService will terminate the whole schedule if a Runnable throws an exception
+ log.error("A handler threw an exception!", e);
+ }
+ }
+}
diff --git a/src/store-sync/src/main/java/org/eclipse/lyo/store/sync/change/Change.java b/src/store-sync/src/main/java/org/eclipse/lyo/store/sync/change/Change.java
new file mode 100644
index 0000000..d26d93c
--- /dev/null
+++ b/src/store-sync/src/main/java/org/eclipse/lyo/store/sync/change/Change.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v. 1.0 which accompanies this distribution.
+ *
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: EPL-1.0 OR BSD-3-Clause
+ */
+package org.eclipse.lyo.store.sync.change;
+
+import org.eclipse.lyo.oslc4j.core.model.AbstractResource;
+
+/**
+ * Change is .
+ *
+ * @version $version-stub$
+ * @since 4.0.0
+ */
+public class Change {
+ /**
+ * Not IExtendedResource due to the use of AbstractResource throughout Lyo generated code.
+ */
+ private final AbstractResource resource;
+ private final HistoryResource historyResource;
+ private final T message;
+
+ public Change(AbstractResource resource, HistoryResource historyResource, T message) {
+ this.resource = resource;
+ this.historyResource = historyResource;
+ this.message = message;
+ }
+
+ public AbstractResource getResource() {
+ return resource;
+ }
+
+ public HistoryResource getHistoryResource() {
+ return historyResource;
+ }
+
+ public T getMessage() {
+ return message;
+ }
+}
diff --git a/src/store-sync/src/main/java/org/eclipse/lyo/store/sync/change/ChangeHelper.java b/src/store-sync/src/main/java/org/eclipse/lyo/store/sync/change/ChangeHelper.java
new file mode 100644
index 0000000..8f0738c
--- /dev/null
+++ b/src/store-sync/src/main/java/org/eclipse/lyo/store/sync/change/ChangeHelper.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v. 1.0 which accompanies this distribution.
+ *
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: EPL-1.0 OR BSD-3-Clause
+ */
+package org.eclipse.lyo.store.sync.change;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Objects;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+/**
+ * ChangeHelper is .
+ *
+ * @author Andrew Berezovskyi (andriib@kth.se)
+ * @version $version-stub$
+ * @since 4.0.0
+ */
+public class ChangeHelper {
+
+ public static List changesCreated(Collection allChanges) {
+ return allChanges.stream()
+ .filter(change -> Objects.equals(change.getHistoryResource().getChangeKindEnum(), ChangeKind.CREATION))
+ .collect(Collectors.toList());
+ }
+
+ public static List changesModified(Collection allChanges) {
+ return allChanges.stream().filter(
+ change -> Objects.equals(change.getHistoryResource().getChangeKindEnum(), ChangeKind.MODIFICATION))
+ .collect(Collectors.toList());
+ }
+
+ public static List historyFrom(Collection changes) {
+ return ChangeHelper.mapFn(changes, Change::getHistoryResource);
+ }
+
+ public static List mapFn(Collection changes, Function mapper) {
+ return changes.stream().map(mapper).collect(Collectors.toList());
+ }
+}
diff --git a/src/store-sync/src/main/java/org/eclipse/lyo/store/sync/change/ChangeKind.java b/src/store-sync/src/main/java/org/eclipse/lyo/store/sync/change/ChangeKind.java
new file mode 100644
index 0000000..e3a251f
--- /dev/null
+++ b/src/store-sync/src/main/java/org/eclipse/lyo/store/sync/change/ChangeKind.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v. 1.0 which accompanies this distribution.
+ *
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: EPL-1.0 OR BSD-3-Clause
+ */
+package org.eclipse.lyo.store.sync.change;
+
+import org.eclipse.lyo.oslc4j.core.annotation.OslcName;
+import org.eclipse.lyo.oslc4j.core.annotation.OslcNamespace;
+import org.eclipse.lyo.oslc4j.core.annotation.OslcResourceShape;
+
+/**
+ * ChangeKind is .
+ *
+ * @author Andrew Berezovskyi (andriib@kth.se)
+ * @version $version-stub$
+ * @since 4.0.0
+ */
+@OslcNamespace(HistoryResource.NS_TRS)
+@OslcName(ChangeKind.NAME)
+@OslcResourceShape(title = "Change Kind Resource Shape", describes = HistoryResource.NS_TRS + ChangeKind.NAME)
+public enum ChangeKind {
+ // Strings taken from the TRS provider implementation
+ CREATION("Created"),
+ MODIFICATION("Modified"),
+ DELETION("Deleted");
+
+ public static final String NAME = "ChangeKind";
+ private final String created;
+
+ ChangeKind(String created) {
+ this.created = created;
+ }
+
+ public static ChangeKind fromString(String text) {
+ if (text != null) {
+ for (ChangeKind kind : ChangeKind.values()) {
+ if (text.equalsIgnoreCase(kind.created)) {
+ return kind;
+ }
+ }
+ }
+ throw new IllegalArgumentException("No constant with text " + text + " found");
+ }
+
+ @Override
+ public String toString() {
+ return created;
+ }
+}
diff --git a/src/store-sync/src/main/java/org/eclipse/lyo/store/sync/change/ChangeProvider.java b/src/store-sync/src/main/java/org/eclipse/lyo/store/sync/change/ChangeProvider.java
new file mode 100644
index 0000000..70bb0b4
--- /dev/null
+++ b/src/store-sync/src/main/java/org/eclipse/lyo/store/sync/change/ChangeProvider.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v. 1.0 which accompanies this distribution.
+ *
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: EPL-1.0 OR BSD-3-Clause
+ */
+package org.eclipse.lyo.store.sync.change;
+
+import java.time.ZonedDateTime;
+import java.util.Collection;
+
+/**
+ * ChangeProvider is .
+ *
+ * @author Andrew Berezovskyi (andriib@kth.se)
+ * @version $version-stub$
+ * @since 4.0.0
+ */
+public interface ChangeProvider {
+ Collection> getChangesSince(ZonedDateTime lastUpdate, T message);
+}
diff --git a/src/store-sync/src/main/java/org/eclipse/lyo/store/sync/change/HistoryResource.java b/src/store-sync/src/main/java/org/eclipse/lyo/store/sync/change/HistoryResource.java
new file mode 100644
index 0000000..d09b1f1
--- /dev/null
+++ b/src/store-sync/src/main/java/org/eclipse/lyo/store/sync/change/HistoryResource.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v. 1.0 which accompanies this distribution.
+ *
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: EPL-1.0 OR BSD-3-Clause
+ */
+package org.eclipse.lyo.store.sync.change;
+
+import org.eclipse.lyo.oslc4j.core.annotation.OslcName;
+import org.eclipse.lyo.oslc4j.core.annotation.OslcNamespace;
+import org.eclipse.lyo.oslc4j.core.annotation.OslcPropertyDefinition;
+import org.eclipse.lyo.oslc4j.core.annotation.OslcResourceShape;
+import org.eclipse.lyo.oslc4j.core.model.AbstractResource;
+
+import java.net.URI;
+import java.time.ZonedDateTime;
+import java.util.Date;
+
+/**
+ * HistoryResource is a wrapper OSLC Resource around org.eclipse.lyo.oslc4j.trs.provider.HistoryData
.
+ *
+ * @author Andrew Berezovskyi (andriib@kth.se)
+ * @version $version-stub$
+ * @since 4.0.0
+ */
+@OslcNamespace(HistoryResource.NS_TRS)
+@OslcName(HistoryResource.NAME)
+@OslcResourceShape(title = "TRS History Resource Shape", describes = HistoryResource.TYPE)
+public class HistoryResource extends AbstractResource {
+ public static final String NS_TRS = "http://open-services.net/ns/core/trs#";
+ public static final String NAME = "TrsHistoryResource";
+ public static final String TYPE = NS_TRS + NAME;
+ private ChangeKind changeKind;
+ private Date timestamp;
+ private URI resourceURI;
+
+ /**
+ * Shall be used only by the OSLC Jena Model Helper
+ */
+ @Deprecated
+ public HistoryResource() {
+ }
+
+ public HistoryResource(ChangeKind changeKind, Date timestamp, URI resourceURI) {
+ this.changeKind = changeKind;
+ this.timestamp = timestamp;
+ this.resourceURI = resourceURI;
+ }
+
+ public HistoryResource(ChangeKind changeKind, ZonedDateTime timestamp, URI resourceURI) {
+ this.changeKind = changeKind;
+ this.timestamp = Date.from(timestamp.toInstant());
+ this.resourceURI = resourceURI;
+ }
+
+ @OslcName("change_kind")
+ @OslcPropertyDefinition(NS_TRS + "change_kind")
+ public String getChangeKind() {
+ return changeKind.toString();
+ }
+
+ public void setChangeKind(ChangeKind changeKind) {
+ this.changeKind = changeKind;
+ }
+
+ public ChangeKind getChangeKindEnum() {
+ return changeKind;
+ }
+
+ public void setChangeKind(String changeKind) {
+ this.changeKind = ChangeKind.fromString(changeKind);
+ }
+
+ @OslcName("timestamp")
+ @OslcPropertyDefinition(NS_TRS + "timestamp")
+ public Date getTimestamp() {
+ return timestamp;
+ }
+
+ public void setTimestamp(Date timestamp) {
+ this.timestamp = timestamp;
+ }
+
+ @OslcName("uri")
+ @OslcPropertyDefinition(NS_TRS + "uri")
+ public URI getResourceURI() {
+ return resourceURI;
+ }
+
+ public void setResourceURI(URI resourceURI) {
+ this.resourceURI = resourceURI;
+ }
+}
diff --git a/src/store-sync/src/main/java/org/eclipse/lyo/store/sync/change/package-info.java b/src/store-sync/src/main/java/org/eclipse/lyo/store/sync/change/package-info.java
new file mode 100644
index 0000000..6241141
--- /dev/null
+++ b/src/store-sync/src/main/java/org/eclipse/lyo/store/sync/change/package-info.java
@@ -0,0 +1,8 @@
+/**
+ * Classes for defining changes for handlers.
+ * {@link org.eclipse.lyo.store.sync.change.HistoryResource} can be persisted in a
+ * triplestore.
+ * @version $version-stub$
+ * @since 4.0.0
+ */
+package org.eclipse.lyo.store.sync.change;
diff --git a/src/store-sync/src/main/java/org/eclipse/lyo/store/sync/handlers/SimpleStoreHandler.java b/src/store-sync/src/main/java/org/eclipse/lyo/store/sync/handlers/SimpleStoreHandler.java
new file mode 100644
index 0000000..cde1051
--- /dev/null
+++ b/src/store-sync/src/main/java/org/eclipse/lyo/store/sync/handlers/SimpleStoreHandler.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2020 Contributors to the Eclipse Foundation
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v. 1.0 which accompanies this distribution.
+ *
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: EPL-1.0 OR BSD-3-Clause
+ */
+package org.eclipse.lyo.store.sync.handlers;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
+import org.eclipse.lyo.oslc4j.core.model.AbstractResource;
+import org.eclipse.lyo.oslc4j.core.model.ServiceProvider;
+import org.eclipse.lyo.store.Store;
+import org.eclipse.lyo.store.StoreAccessException;
+import org.eclipse.lyo.store.sync.Handler;
+import org.eclipse.lyo.store.sync.ServiceProviderMessage;
+import org.eclipse.lyo.store.sync.change.Change;
+import org.eclipse.lyo.store.sync.change.ChangeKind;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * This is a simple handler that puts resources into named graphs per
+ * {@link ServiceProvider} if the message implements
+ * {@link ServiceProviderMessage}.
+ *
+ * @author Andrew Berezovskyi
+ * @version $version-stub$
+ * @param
+ * @since 2.4.0
+ *
+ */
+public class SimpleStoreHandler implements Handler {
+
+ private final URI defaultGraph;
+
+ private final Logger log = LoggerFactory.getLogger(SimpleStoreHandler.class);
+
+ private final Store store;
+
+ public SimpleStoreHandler(Store store) {
+ this.store = store;
+ try {
+ this.defaultGraph = new URI("urn:x-arq:DefaultGraph");
+ } catch (URISyntaxException e) {
+ // this should never happen - we don't want the exception trail
+ // so we cheat with wrapping this in an unmanaged exception
+ // that will halt the execution.
+ IllegalStateException exception = new IllegalStateException(e);
+ log.error("Failed to generate default graph URI");
+ throw exception;
+ }
+ }
+
+ @Override
+ public Collection> handle(Store store, Collection> changes) {
+ if (changes == null || changes.isEmpty()) {
+ log.warn("Empty change list cannot be handled");
+ return changes;
+ }
+
+ Optional> firstChange = changes.stream().findFirst();
+ if (firstChange.get().getMessage() instanceof ServiceProviderMessage) {
+ Map, List>> map = changes.stream()
+ .collect(Collectors.groupingBy(c -> c.getMessage().getClass()));
+ for (Entry, List>> changeSet : map.entrySet()) {
+ URI spURI = ((ServiceProviderMessage) changeSet.getKey()).getServiceProviderUri();
+ persistChanges(spURI, changeSet.getValue());
+ }
+ } else {
+ persistChanges(defaultGraph, changes);
+ }
+
+ return changes;
+ }
+
+ private void persistChanges(URI spURI, Collection> value) {
+ try {
+ persistUpdates(spURI, value);
+ } catch (StoreAccessException e) {
+ log.error("Failed to persist updates", e);
+ }
+
+ persistDeletions(spURI, value);
+ }
+
+ private void persistDeletions(URI spURI, Collection> value) {
+ Collection deletedResources = value.stream()
+ .filter(c -> c.getHistoryResource().getChangeKindEnum() == ChangeKind.DELETION)
+ .map(c -> c.getResource().getAbout()).collect(Collectors.toList());
+ store.deleteResources(spURI, deletedResources.toArray(new URI[0]));
+ }
+
+ private void persistUpdates(URI spURI, Collection> value) throws StoreAccessException {
+ Collection updatedResources = value.stream()
+ .filter(c -> c.getHistoryResource().getChangeKindEnum() == ChangeKind.CREATION
+ || c.getHistoryResource().getChangeKindEnum() == ChangeKind.MODIFICATION)
+ .map(c -> c.getResource()).collect(Collectors.toList());
+ store.appendResources(spURI, updatedResources);
+ }
+
+}
diff --git a/src/store-sync/src/main/java/org/eclipse/lyo/store/sync/handlers/package-info.java b/src/store-sync/src/main/java/org/eclipse/lyo/store/sync/handlers/package-info.java
new file mode 100644
index 0000000..c27aae5
--- /dev/null
+++ b/src/store-sync/src/main/java/org/eclipse/lyo/store/sync/handlers/package-info.java
@@ -0,0 +1,8 @@
+/**
+ *
+ */
+/**
+ * @author andrew
+ *
+ */
+package org.eclipse.lyo.store.sync.handlers;
diff --git a/src/store-sync/src/main/java/org/eclipse/lyo/store/sync/package-info.java b/src/store-sync/src/main/java/org/eclipse/lyo/store/sync/package-info.java
new file mode 100644
index 0000000..74482ab
--- /dev/null
+++ b/src/store-sync/src/main/java/org/eclipse/lyo/store/sync/package-info.java
@@ -0,0 +1,10 @@
+/**
+ * Common primitives for updating store.
+ * {@link org.eclipse.lyo.store.sync.StoreUpdateRunnable} is scheduled by
+ * {@link org.eclipse.lyo.store.sync.StoreUpdateManager}.
+ *
+ * @author Andrew Berezovskyi (andriib@kth.se)
+ * @version $version-stub$
+ * @since 0.18.0
+ */
+package org.eclipse.lyo.store.sync;
diff --git a/src/store-sync/src/test/java/org/eclipse/lyo/store/sync/TestHistoryResource.java b/src/store-sync/src/test/java/org/eclipse/lyo/store/sync/TestHistoryResource.java
new file mode 100644
index 0000000..2b91965
--- /dev/null
+++ b/src/store-sync/src/test/java/org/eclipse/lyo/store/sync/TestHistoryResource.java
@@ -0,0 +1,86 @@
+package org.eclipse.lyo.store.sync;
+
+import org.apache.jena.rdf.model.Model;
+import java.net.URI;
+import java.time.Instant;
+import java.util.Collections;
+import java.util.Date;
+import java.util.List;
+import static org.assertj.core.api.Assertions.assertThat;
+import org.eclipse.lyo.oslc4j.provider.jena.JenaModelHelper;
+import org.eclipse.lyo.store.Store;
+import org.eclipse.lyo.store.StoreFactory;
+import org.eclipse.lyo.store.sync.change.ChangeKind;
+import org.eclipse.lyo.store.sync.change.HistoryResource;
+import org.junit.Test;
+
+/**
+ * TestTrsHistoryResource is .
+ *
+ * @author Andrew Berezovskyi (andriib@kth.se)
+ * @version $version-stub$
+ * @since 4.0.0
+ */
+public class TestHistoryResource {
+ public static final URI RESOURCE_URI = URI.create("test:test");
+ private final Store store = StoreFactory.inMemory();
+
+ @Test
+ public void testResourceIsMarshalled() throws Exception {
+ HistoryResource resource = new HistoryResource(ChangeKind.CREATION,
+ Date.from(Instant.now()), TestHistoryResource.RESOURCE_URI);
+
+ Model model = JenaModelHelper.createJenaModel(new Object[] { resource });
+ assertThat(model.size()).isGreaterThan(0);
+ }
+
+ @Test
+ public void testResourceContainsStatements() throws Exception {
+ HistoryResource resource = new HistoryResource(ChangeKind.CREATION,
+ Date.from(Instant.now()), TestHistoryResource.RESOURCE_URI);
+ resource.setAbout(TestHistoryResource.RESOURCE_URI);
+
+ Model model = JenaModelHelper.createJenaModel(new Object[] { resource });
+ assertThat(model.size()).isGreaterThan(1);
+ }
+
+ @Test
+ public void testResourceIsPersisted() throws Exception {
+ HistoryResource resource = new HistoryResource(ChangeKind.CREATION,
+ Date.from(Instant.now()), TestHistoryResource.RESOURCE_URI);
+ resource.setAbout(TestHistoryResource.RESOURCE_URI);
+
+ assertThat(store.keySet()).hasSize(0);
+ store.putResources(resource.getAbout(), Collections.singletonList(resource));
+ assertThat(store.keySet()).hasSize(1);
+ }
+
+ @Test
+ public void testResourceIsRestored() throws Exception {
+ HistoryResource resource = new HistoryResource(ChangeKind.CREATION,
+ Date.from(Instant.now()), TestHistoryResource.RESOURCE_URI);
+ resource.setAbout(TestHistoryResource.RESOURCE_URI);
+
+ store.putResources(resource.getAbout(), Collections.singletonList(resource));
+ List resources = store.getResources(TestHistoryResource.RESOURCE_URI, HistoryResource.class);
+ assertThat(resources).hasSize(1);
+ }
+
+ @Test
+ public void testResourceIsRestoredWithProperties() throws Exception {
+ String testResourceURI = "lyo:testtest";
+ Date timestamp = Date.from(Instant.now());
+ HistoryResource resource = new HistoryResource(ChangeKind.CREATION, timestamp,
+ URI.create(testResourceURI));
+ resource.setAbout(TestHistoryResource.RESOURCE_URI);
+
+ store.putResources(resource.getAbout(), Collections.singletonList(resource));
+
+ List resources = store.getResources(TestHistoryResource.RESOURCE_URI, HistoryResource.class);
+ HistoryResource storeResource = resources.get(0);
+
+ assertThat(storeResource.getChangeKind()).isEqualToIgnoringCase(String.valueOf(ChangeKind.CREATION));
+ assertThat(storeResource.getTimestamp()).isEqualTo(timestamp);
+ assertThat(storeResource.getResourceURI().toASCIIString()).isEqualTo(testResourceURI);
+ }
+}
diff --git a/src/store-sync/src/test/resources/log4j.properties b/src/store-sync/src/test/resources/log4j.properties
new file mode 100644
index 0000000..9f4c714
--- /dev/null
+++ b/src/store-sync/src/test/resources/log4j.properties
@@ -0,0 +1,26 @@
+###
+# #%L
+# Contributors:
+# Andrew Berezovskyi - initial template (based on https://logging.apache.org/log4j/1.2/manual.html)
+#
+# NOTICE:
+# Copyright © 2000-2002 The Apache Software Foundation. All rights reserved. This software is published under the terms of the Apache Software License version 2.0, a copy of which has been included in the LICENSE file shipped with the log4j distribution. This document is based on the article "Log4j delivers control over logging" published in November 2000 edition of JavaWorld. However, the present article containsKey more detailed and up to date information. The present short manual also borrows some text from "The complete log4j manual" by the same author (yours truly).
+# %%
+# Copyright (C) 2016 KTH Royal Institute of Technology
+# %%
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+# #L%
+###
+# Set root logger level to DEBUG and its only appender to rootAppender.
+log4j.rootLogger=DEBUG, rootAppender
+
+log4j.appender.rootAppender=org.apache.log4j.ConsoleAppender
+log4j.appender.rootAppender.layout=org.apache.log4j.PatternLayout
+log4j.appender.rootAppender.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n
+
+
+log4j.logger.org.apache.jena=INFO
+log4j.logger.com.hp.hpl.jena=INFO