You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@marmotta.apache.org by wi...@apache.org on 2013/02/19 13:52:00 UTC
[36/52] [partial] code contribution,
initial import of relevant modules of LMF-3.0.0-SNAPSHOT based on
revision 4bf944319368 of the default branch at https://code.google.com/p/lmf/
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/c32963d5/kiwi/kiwi-versioning/src/test/java/org/apache/marmotta/kiwi/versioning/test/VersioningPersistenceTest.java
----------------------------------------------------------------------
diff --git a/kiwi/kiwi-versioning/src/test/java/org/apache/marmotta/kiwi/versioning/test/VersioningPersistenceTest.java b/kiwi/kiwi-versioning/src/test/java/org/apache/marmotta/kiwi/versioning/test/VersioningPersistenceTest.java
new file mode 100644
index 0000000..6005697
--- /dev/null
+++ b/kiwi/kiwi-versioning/src/test/java/org/apache/marmotta/kiwi/versioning/test/VersioningPersistenceTest.java
@@ -0,0 +1,354 @@
+/*
+ * Copyright (c) 2013 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.marmotta.kiwi.versioning.test;
+
+import org.apache.commons.lang.RandomStringUtils;
+import org.apache.marmotta.kiwi.model.rdf.KiWiStringLiteral;
+import org.apache.marmotta.kiwi.model.rdf.KiWiTriple;
+import org.apache.marmotta.kiwi.model.rdf.KiWiUriResource;
+import org.apache.marmotta.kiwi.persistence.KiWiConnection;
+import org.apache.marmotta.kiwi.persistence.KiWiDialect;
+import org.apache.marmotta.kiwi.persistence.KiWiPersistence;
+import org.apache.marmotta.kiwi.persistence.h2.H2Dialect;
+import org.apache.marmotta.kiwi.persistence.mysql.MySQLDialect;
+import org.apache.marmotta.kiwi.persistence.pgsql.PostgreSQLDialect;
+import org.apache.marmotta.kiwi.test.helper.DBConnectionChecker;
+import org.apache.marmotta.kiwi.versioning.model.Version;
+import org.apache.marmotta.kiwi.versioning.persistence.KiWiVersioningConnection;
+import org.apache.marmotta.kiwi.versioning.persistence.KiWiVersioningPersistence;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+import static org.hamcrest.Matchers.hasItems;
+
+/**
+ * This test checks if the database persistence for the versioning functionality works properly.
+ * It will try running over all available databases. Except for in-memory databases like
+ * H2 or Derby, database URLs must be passed as system property, or otherwise the test is skipped for this database.
+ * Available system properties:
+ * <ul>
+ * <li>PostgreSQL:
+ * <ul>
+ * <li>postgresql.url, e.g. jdbc:postgresql://localhost:5433/kiwitest?prepareThreshold=3</li>
+ * <li>postgresql.user (default: lmf)</li>
+ * <li>postgresql.pass (default: lmf)</li>
+ * </ul>
+ * </li>
+ * <li>MySQL:
+ * <ul>
+ * <li>mysql.url, e.g. jdbc:mysql://localhost:3306/kiwitest?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull</li>
+ * <li>mysql.user (default: lmf)</li>
+ * <li>mysql.pass (default: lmf</li>
+ * </ul>
+ * </li>
+ * <li>H2:
+ * <ul>
+ * <li>h2.url, e.g. jdbc:h2:mem;MVCC=true;DB_CLOSE_ON_EXIT=FALSE;DB_CLOSE_DELAY=10</li>
+ * <li>h2.user (default: lmf)</li>
+ * <li>h2.pass (default: lmf</li>
+ * </ul>
+ * </li>
+ * </ul>
+ *
+ * <p/>
+ * Author: Sebastian Schaffert
+ */
+@RunWith(Parameterized.class)
+public class VersioningPersistenceTest {
+
+
+ /**
+ * Return database configurations if the appropriate parameters have been set.
+ *
+ * @return an array (database name, url, user, password)
+ */
+ @Parameterized.Parameters(name="Database Test {index}: {0} at {1}")
+ public static Iterable<Object[]> databases() {
+ String[] databases = {"H2", "PostgreSQL", "MySQL"};
+
+ List<Object[]> result = new ArrayList<Object[]>(databases.length);
+ for(String database : databases) {
+ if(System.getProperty(database.toLowerCase()+".url") != null) {
+ result.add(new Object[] {
+ database,
+ System.getProperty(database.toLowerCase()+".url"),
+ System.getProperty(database.toLowerCase()+".user","lmf"),
+ System.getProperty(database.toLowerCase()+".pass","lmf")
+ });
+ }
+ }
+ return result;
+ }
+
+
+ private KiWiDialect dialect;
+
+ private String jdbcUrl;
+
+ private String jdbcUser;
+
+ private String jdbcPass;
+
+ private KiWiPersistence persistence;
+ private KiWiVersioningPersistence vpersistence;
+
+ public VersioningPersistenceTest(String database, String jdbcUrl, String jdbcUser, String jdbcPass) {
+ this.jdbcPass = jdbcPass;
+ this.jdbcUrl = jdbcUrl;
+ this.jdbcUser = jdbcUser;
+
+ if("H2".equals(database)) {
+ this.dialect = new H2Dialect();
+ } else if("MySQL".equals(database)) {
+ this.dialect = new MySQLDialect();
+ } else if("PostgreSQL".equals(database)) {
+ this.dialect = new PostgreSQLDialect();
+ }
+
+ DBConnectionChecker.checkDatabaseAvailability(jdbcUrl, jdbcUser, jdbcPass, dialect);
+ }
+
+
+ @Before
+ public void initDatabase() throws SQLException {
+ persistence = new KiWiPersistence("test",jdbcUrl,jdbcUser,jdbcPass,dialect);
+ persistence.initDatabase();
+
+ vpersistence = new KiWiVersioningPersistence(persistence);
+ vpersistence.initDatabase();
+ }
+
+ @After
+ public void dropDatabase() throws SQLException {
+ vpersistence.dropDatabase();
+
+ persistence.dropDatabase();
+ persistence.shutdown();
+ }
+
+
+ @Test
+ public void testTablesCreateDrop() throws Exception {
+ // test if database exists and has a version
+ KiWiConnection connection = vpersistence.getConnection();
+ try {
+ Assert.assertThat(connection.getDatabaseTables(), hasItems("versions", "versions_added", "versions_removed"));
+ Assert.assertEquals(1, connection.getDatabaseVersion());
+
+ connection.commit();
+ } finally {
+ connection.close();
+ }
+ }
+
+ @Test
+ public void testCreateListVersions() throws Exception {
+ KiWiVersioningConnection connection = vpersistence.getConnection();
+ try {
+ KiWiUriResource subject1 = new KiWiUriResource("http://localhost/resource/"+ RandomStringUtils.randomAlphanumeric(8));
+ KiWiUriResource subject2 = new KiWiUriResource("http://localhost/resource/"+ RandomStringUtils.randomAlphanumeric(8));
+ KiWiUriResource pred_1 = new KiWiUriResource("http://localhost/predicate/P1");
+ KiWiUriResource pred_2 = new KiWiUriResource("http://localhost/predicate/P2");
+ KiWiUriResource object_1 = new KiWiUriResource("http://localhost/resource/"+RandomStringUtils.randomAlphanumeric(8));
+ KiWiStringLiteral object_2 = new KiWiStringLiteral(RandomStringUtils.randomAlphanumeric(32));
+ KiWiUriResource context = new KiWiUriResource("http://localhost/context/"+RandomStringUtils.randomAlphanumeric(8));
+
+ connection.storeNode(subject1);
+ connection.storeNode(subject2);
+ connection.storeNode(pred_1);
+ connection.storeNode(pred_2);
+ connection.storeNode(object_1);
+ connection.storeNode(object_2);
+ connection.storeNode(context);
+
+ KiWiTriple triple1 = new KiWiTriple(subject1,pred_1,object_1,context);
+ KiWiTriple triple2 = new KiWiTriple(subject2,pred_2,object_2,context);
+
+ connection.storeTriple(triple1);
+ connection.storeTriple(triple2);
+ connection.commit();
+
+ Version version1 = new Version();
+ version1.setCommitTime(new Date());
+ version1.addTriple(triple1);
+ connection.storeVersion(version1);
+ connection.commit();
+
+ // check if listVersions now gives exactly one version
+ List<Version> list1 = connection.listVersions().asList();
+ Assert.assertEquals("there should be exactly one version",1,list1.size());
+ Assert.assertEquals("contents of version differ", version1, list1.get(0));
+ Assert.assertEquals("version id is not 1", 1L, (long)list1.get(0).getId());
+
+ // check if listVersions with subject1 now gives exactly one version
+ List<Version> listr1 = connection.listVersions(subject1).asList();
+ Assert.assertEquals("there should be exactly one version", 1, listr1.size());
+ Assert.assertEquals("contents of version differ", version1, listr1.get(0));
+ Assert.assertEquals("version id is not 1", 1L, (long)listr1.get(0).getId());
+
+
+ Version version2 = new Version();
+ version2.setCommitTime(new Date());
+ version2.addTriple(triple2);
+ version2.removeTriple(triple1);
+ connection.storeVersion(version2);
+ connection.commit();
+
+ // check if listVersions now gives exactly two versions
+ List<Version> list2 = connection.listVersions().asList();
+ Assert.assertEquals("there should be exactly two version",2,list2.size());
+ Assert.assertEquals("contents of version differ", version2, list2.get(1));
+
+
+ // check if listVersions with subject1 still gives exactly one version
+ List<Version> listr2 = connection.listVersions(subject1).asList();
+ Assert.assertEquals("there should be exactly one version", 2, listr2.size());
+ Assert.assertEquals("contents of version differ", version1, listr2.get(0));
+ Assert.assertEquals("version id is not 1", 1L, (long)listr2.get(0).getId());
+
+ connection.commit();
+ } finally {
+ connection.close();
+ }
+
+ }
+
+ /**
+ * Test listing versions between two dates
+ *
+ * @throws Exception
+ */
+ @Test
+ public void testCreateListVersionsBetween() throws Exception {
+ KiWiVersioningConnection connection = vpersistence.getConnection();
+ try {
+ KiWiUriResource subject = new KiWiUriResource("http://localhost/resource/"+ RandomStringUtils.randomAlphanumeric(8));
+ KiWiUriResource pred_1 = new KiWiUriResource("http://localhost/predicate/P1");
+ KiWiUriResource pred_2 = new KiWiUriResource("http://localhost/predicate/P2");
+ KiWiUriResource object_1 = new KiWiUriResource("http://localhost/resource/"+RandomStringUtils.randomAlphanumeric(8));
+ KiWiStringLiteral object_2 = new KiWiStringLiteral(RandomStringUtils.randomAlphanumeric(32));
+ KiWiUriResource context = new KiWiUriResource("http://localhost/context/"+RandomStringUtils.randomAlphanumeric(8));
+
+ connection.storeNode(subject);
+ connection.storeNode(pred_1);
+ connection.storeNode(pred_2);
+ connection.storeNode(object_1);
+ connection.storeNode(object_2);
+ connection.storeNode(context);
+
+ KiWiTriple triple1 = new KiWiTriple(subject,pred_1,object_1,context);
+ KiWiTriple triple2 = new KiWiTriple(subject,pred_2,object_2,context);
+
+ connection.storeTriple(triple1);
+ connection.storeTriple(triple2);
+ connection.commit();
+
+ Date date1 = new Date();
+
+ // wait for one second to be sure to capture MySQL cutting milliseconds
+ mysqlSleep();
+
+
+ Version version1 = new Version();
+ version1.setCommitTime(new Date());
+ version1.addTriple(triple1);
+ connection.storeVersion(version1);
+ connection.commit();
+
+ // wait for one second to be sure to capture MySQL cutting milliseconds
+ mysqlSleep();
+
+ Date date2 = new Date();
+
+ // wait for one second to be sure to capture MySQL cutting milliseconds
+ mysqlSleep();
+
+
+ Version version2 = new Version();
+ version2.setCommitTime(new Date());
+ version2.addTriple(triple2);
+ version2.removeTriple(triple1);
+ connection.storeVersion(version2);
+ connection.commit();
+
+ // wait for one second to be sure to capture MySQL cutting milliseconds
+ mysqlSleep();
+
+ Date date3 = new Date();
+
+
+ // now we test different ways of listing versions between dates
+ List<Version> list1 = connection.listVersions(date1,date2).asList();
+ Assert.assertEquals("there should be exactly one version from "+date1+" to "+date2,1,list1.size());
+ Assert.assertEquals("contents of version differ", version1, list1.get(0));
+ Assert.assertEquals("version id is not 1", 1L, (long)list1.get(0).getId());
+
+ // check if getLatestVersion at date2 works
+ Version latest2 = connection.getLatestVersion(subject,date2);
+ Assert.assertNotNull("latest version for subject was not found",latest2);
+ Assert.assertEquals("latest version is not the expected version", version1,latest2);
+
+ // check if listVersions with subject1 now gives exactly one version
+ List<Version> listr1 = connection.listVersions(subject,date1,date2).asList();
+ Assert.assertEquals("there should be exactly one version", 1, listr1.size());
+ Assert.assertEquals("contents of version differ", version1, listr1.get(0));
+ Assert.assertEquals("version id is not 1", 1L, (long)listr1.get(0).getId());
+
+
+ List<Version> list2 = connection.listVersions(date2,date3).asList();
+ Assert.assertEquals("there should be exactly one version from "+date2+" to "+date3,1,list2.size());
+ Assert.assertEquals("contents of version differ", version2, list2.get(0));
+ Assert.assertEquals("version id is not 2", 2L, (long)list2.get(0).getId());
+
+ List<Version> list3 = connection.listVersions(date3,new Date()).asList();
+ Assert.assertEquals("there should be no version from "+date3+" to now",0,list3.size());
+
+ List<Version> list4 = connection.listVersions(date1,date3).asList();
+ Assert.assertEquals("there should be exactly two versions from "+date1+" to "+date3,2,list4.size());
+ Assert.assertEquals("contents of version1 differ", version1, list4.get(0));
+ Assert.assertEquals("contents of version2 differ", version2, list4.get(1));
+
+
+ connection.commit();
+ } finally {
+ connection.close();
+ }
+
+
+ }
+
+ /**
+ * MYSQL rounds timestamps to the second, so it is sometimes necessary to sleep before doing a test
+ */
+ private void mysqlSleep() {
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException e) {
+ }
+ }
+
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/c32963d5/kiwi/kiwi-versioning/src/test/java/org/apache/marmotta/kiwi/versioning/test/VersioningRepositoryTest.java
----------------------------------------------------------------------
diff --git a/kiwi/kiwi-versioning/src/test/java/org/apache/marmotta/kiwi/versioning/test/VersioningRepositoryTest.java b/kiwi/kiwi-versioning/src/test/java/org/apache/marmotta/kiwi/versioning/test/VersioningRepositoryTest.java
new file mode 100644
index 0000000..a6531d4
--- /dev/null
+++ b/kiwi/kiwi-versioning/src/test/java/org/apache/marmotta/kiwi/versioning/test/VersioningRepositoryTest.java
@@ -0,0 +1,261 @@
+/*
+ * Copyright (c) 2013 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.marmotta.kiwi.versioning.test;
+
+import org.apache.marmotta.kiwi.persistence.KiWiDialect;
+import org.apache.marmotta.kiwi.persistence.h2.H2Dialect;
+import org.apache.marmotta.kiwi.persistence.mysql.MySQLDialect;
+import org.apache.marmotta.kiwi.persistence.pgsql.PostgreSQLDialect;
+import org.apache.marmotta.kiwi.sail.KiWiStore;
+import org.apache.marmotta.kiwi.test.helper.DBConnectionChecker;
+import org.apache.marmotta.kiwi.transactions.sail.KiWiTransactionalSail;
+import org.apache.marmotta.kiwi.versioning.model.Version;
+import org.apache.marmotta.kiwi.versioning.sail.KiWiVersioningSail;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.openrdf.repository.Repository;
+import org.openrdf.repository.RepositoryConnection;
+import org.openrdf.repository.RepositoryException;
+import org.openrdf.repository.RepositoryResult;
+import org.openrdf.repository.sail.SailRepository;
+import org.openrdf.rio.RDFFormat;
+
+import java.io.InputStream;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+import static org.hamcrest.CoreMatchers.notNullValue;
+import static org.junit.Assume.assumeThat;
+
+/**
+ * This test checks if the versioning functionality itself works, i.e. the system properly creates versions on
+ * transaction commits. It will try running over all available databases. Except for in-memory databases like
+ * H2 or Derby, database URLs must be passed as system property, or otherwise the test is skipped for this database.
+ * Available system properties:
+ * <ul>
+ * <li>PostgreSQL:
+ * <ul>
+ * <li>postgresql.url, e.g. jdbc:postgresql://localhost:5433/kiwitest?prepareThreshold=3</li>
+ * <li>postgresql.user (default: lmf)</li>
+ * <li>postgresql.pass (default: lmf)</li>
+ * </ul>
+ * </li>
+ * <li>MySQL:
+ * <ul>
+ * <li>mysql.url, e.g. jdbc:mysql://localhost:3306/kiwitest?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull</li>
+ * <li>mysql.user (default: lmf)</li>
+ * <li>mysql.pass (default: lmf</li>
+ * </ul>
+ * </li>
+ * <li>H2:
+ * <ul>
+ * <li>h2.url, e.g. jdbc:h2:mem;MVCC=true;DB_CLOSE_ON_EXIT=FALSE;DB_CLOSE_DELAY=10</li>
+ * <li>h2.user (default: lmf)</li>
+ * <li>h2.pass (default: lmf</li>
+ * </ul>
+ * </li>
+ * </ul>
+ *
+ * <p/>
+ * Author: Sebastian Schaffert
+ */
+@RunWith(Parameterized.class)
+public class VersioningRepositoryTest {
+
+ /**
+ * Return database configurations if the appropriate parameters have been set.
+ *
+ * @return an array (database name, url, user, password)
+ */
+ @Parameterized.Parameters(name="Database Test {index}: {0} at {1}")
+ public static Iterable<Object[]> databases() {
+ String[] databases = {"H2", "PostgreSQL", "MySQL"};
+
+ List<Object[]> result = new ArrayList<Object[]>(databases.length);
+ for(String database : databases) {
+ if(System.getProperty(database.toLowerCase()+".url") != null) {
+ result.add(new Object[] {
+ database,
+ System.getProperty(database.toLowerCase()+".url"),
+ System.getProperty(database.toLowerCase()+".user","lmf"),
+ System.getProperty(database.toLowerCase()+".pass","lmf")
+ });
+ }
+ }
+ return result;
+ }
+
+
+ private KiWiDialect dialect;
+
+ private String jdbcUrl;
+
+ private String jdbcUser;
+
+ private String jdbcPass;
+
+ private KiWiStore store;
+
+ private KiWiTransactionalSail tsail;
+
+ private KiWiVersioningSail vsail;
+
+ private Repository repository;
+
+ public VersioningRepositoryTest(String database, String jdbcUrl, String jdbcUser, String jdbcPass) {
+ this.jdbcPass = jdbcPass;
+ this.jdbcUrl = jdbcUrl;
+ this.jdbcUser = jdbcUser;
+
+ if("H2".equals(database)) {
+ this.dialect = new H2Dialect();
+ } else if("MySQL".equals(database)) {
+ this.dialect = new MySQLDialect();
+ } else if("PostgreSQL".equals(database)) {
+ this.dialect = new PostgreSQLDialect();
+ }
+
+ DBConnectionChecker.checkDatabaseAvailability(jdbcUrl, jdbcUser, jdbcPass, dialect);
+ }
+
+
+ @Before
+ public void initDatabase() throws RepositoryException {
+ store = new KiWiStore("test",jdbcUrl,jdbcUser,jdbcPass,dialect, "http://localhost/context/default", "http://localhost/context/inferred");
+ tsail = new KiWiTransactionalSail(store);
+ vsail = new KiWiVersioningSail(tsail);
+ repository = new SailRepository(vsail);
+ repository.initialize();
+ }
+
+ @After
+ public void dropDatabase() throws RepositoryException, SQLException {
+ vsail.getPersistence().dropDatabase();
+ store.getPersistence().dropDatabase();
+ repository.shutDown();
+ }
+
+ /**
+ * This test imports three small RDF files in sequence and checks afterwards that the number of versions
+ * is correct and they contain the correct information
+ * @throws Exception
+ */
+ @Test
+ public void testCreateVersions() throws Exception {
+ // import three files in sequence and check if the versions are created properly
+
+ Date date1 = new Date();
+
+ mysqlSleep();
+
+ // base data
+ InputStream baseData = this.getClass().getResourceAsStream("version-base.rdf");
+ assumeThat("Could not load test-data: version-base.rdf", baseData, notNullValue(InputStream.class));
+
+ RepositoryConnection connectionBase = repository.getConnection();
+ try {
+ connectionBase.add(baseData, "http://marmotta.incubator.apache.org/testing/ns1/", RDFFormat.RDFXML);
+ connectionBase.commit();
+ } finally {
+ connectionBase.close();
+ }
+
+ mysqlSleep();
+
+ Date date2 = new Date();
+
+ mysqlSleep();
+
+ // update 1
+ InputStream update1Data = this.getClass().getResourceAsStream("version-update1.rdf");
+ assumeThat("Could not load test-data: version-update1.rdf", update1Data, notNullValue(InputStream.class));
+
+ RepositoryConnection connectionUpdate1 = repository.getConnection();
+ try {
+ connectionUpdate1.add(update1Data, "http://marmotta.incubator.apache.org/testing/ns1/", RDFFormat.RDFXML);
+ connectionUpdate1.commit();
+ } finally {
+ connectionUpdate1.close();
+ }
+
+ // update 2
+ InputStream update2Data = this.getClass().getResourceAsStream("version-update2.rdf");
+ assumeThat("Could not load test-data: version-update2.rdf", update2Data, notNullValue(InputStream.class));
+
+ RepositoryConnection connectionUpdate2 = repository.getConnection();
+ try {
+ connectionUpdate2.add(update2Data, "http://marmotta.incubator.apache.org/testing/ns1/", RDFFormat.RDFXML);
+ connectionUpdate2.commit();
+ } finally {
+ connectionUpdate2.close();
+ }
+
+ // list all versions
+ List<Version> versions = asList(vsail.listVersions());
+ Assert.assertEquals("expected 3 versions!", 3, versions.size());
+ Assert.assertEquals(1, (long)versions.get(0).getId());
+ Assert.assertEquals(2, (long)versions.get(1).getId());
+ Assert.assertEquals(3, (long)versions.get(2).getId());
+ Assert.assertEquals(3, (long)versions.get(0).getAddedTriples().size());
+ Assert.assertEquals(3, (long)versions.get(1).getAddedTriples().size());
+ Assert.assertEquals(1, (long)versions.get(2).getAddedTriples().size());
+
+ List<Version> versions1 = asList(vsail.listVersions(date1,date2));
+ Assert.assertEquals("expected 1 version!", 1, versions1.size());
+ Assert.assertEquals(1, (long)versions1.get(0).getId());
+ Assert.assertEquals(3, (long)versions1.get(0).getAddedTriples().size());
+ }
+
+
+ /**
+ * MYSQL rounds timestamps to the second, so it is sometimes necessary to sleep before doing a test
+ */
+ private void mysqlSleep() {
+ if(this.dialect instanceof MySQLDialect) {
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException e) {
+ }
+ }
+ }
+
+
+ /**
+ * Workaround for https://openrdf.atlassian.net/browse/SES-1702 in Sesame 2.7.0-beta1
+ * @param <E>
+ * @return
+ */
+ public static <E> List<E> asList(RepositoryResult<E> result) throws RepositoryException {
+ ArrayList<E> collection = new ArrayList<E>();
+ try {
+ while (result.hasNext()) {
+ collection.add(result.next());
+ }
+
+ return collection;
+ }
+ finally {
+ result.close();
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/c32963d5/kiwi/kiwi-versioning/src/test/resources/logback.xml
----------------------------------------------------------------------
diff --git a/kiwi/kiwi-versioning/src/test/resources/logback.xml b/kiwi/kiwi-versioning/src/test/resources/logback.xml
new file mode 100644
index 0000000..08c9e0a
--- /dev/null
+++ b/kiwi/kiwi-versioning/src/test/resources/logback.xml
@@ -0,0 +1,35 @@
+<!--
+ ~ Copyright (c) 2013 Salzburg Research.
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<configuration>
+
+ <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+ <!-- encoders are assigned the type
+ ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
+ <encoder>
+<!-- <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern> -->
+ <pattern>%d{HH:mm:ss.SSS} %-5level - %msg%n</pattern>
+<!-- <pattern>%d{HH:mm:ss.SSS} %-5level %logger{36} - %msg%n</pattern> -->
+ </encoder>
+ </appender>
+
+ <logger name="com.mchange" level="INFO" />
+
+
+ <root level="debug">
+ <appender-ref ref="STDOUT" />
+ </root>
+</configuration>
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/c32963d5/kiwi/kiwi-versioning/src/test/resources/org/apache/marmotta/kiwi/versioning/test/version-base.rdf
----------------------------------------------------------------------
diff --git a/kiwi/kiwi-versioning/src/test/resources/org/apache/marmotta/kiwi/versioning/test/version-base.rdf b/kiwi/kiwi-versioning/src/test/resources/org/apache/marmotta/kiwi/versioning/test/version-base.rdf
new file mode 100644
index 0000000..f15e108
--- /dev/null
+++ b/kiwi/kiwi-versioning/src/test/resources/org/apache/marmotta/kiwi/versioning/test/version-base.rdf
@@ -0,0 +1,25 @@
+<!--
+ ~ Copyright (c) 2013 Salzburg Research.
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<rdf:RDF
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:ns1="http://marmotta.incubator.apache.org/testing/ns1/">
+ <ns1:C rdf:about="http://marmotta.incubator.apache.org/testing/ns1/R1">
+ <ns1:P1>property 1 value 1</ns1:P1>
+ <ns1:P2>property 2 value 1</ns1:P2>
+ </ns1:C>
+
+</rdf:RDF>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/c32963d5/kiwi/kiwi-versioning/src/test/resources/org/apache/marmotta/kiwi/versioning/test/version-update1.rdf
----------------------------------------------------------------------
diff --git a/kiwi/kiwi-versioning/src/test/resources/org/apache/marmotta/kiwi/versioning/test/version-update1.rdf b/kiwi/kiwi-versioning/src/test/resources/org/apache/marmotta/kiwi/versioning/test/version-update1.rdf
new file mode 100644
index 0000000..1f94210
--- /dev/null
+++ b/kiwi/kiwi-versioning/src/test/resources/org/apache/marmotta/kiwi/versioning/test/version-update1.rdf
@@ -0,0 +1,25 @@
+<!--
+ ~ Copyright (c) 2013 Salzburg Research.
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<rdf:RDF
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:ns1="http://marmotta.incubator.apache.org/testing/ns1/">
+ <ns1:C rdf:about="http://marmotta.incubator.apache.org/testing/ns1/R2">
+ <ns1:P1>property 1 value 2</ns1:P1>
+ <ns1:P3>property 3 value 2</ns1:P3>
+ </ns1:C>
+
+</rdf:RDF>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/c32963d5/kiwi/kiwi-versioning/src/test/resources/org/apache/marmotta/kiwi/versioning/test/version-update2.rdf
----------------------------------------------------------------------
diff --git a/kiwi/kiwi-versioning/src/test/resources/org/apache/marmotta/kiwi/versioning/test/version-update2.rdf b/kiwi/kiwi-versioning/src/test/resources/org/apache/marmotta/kiwi/versioning/test/version-update2.rdf
new file mode 100644
index 0000000..ab083fb
--- /dev/null
+++ b/kiwi/kiwi-versioning/src/test/resources/org/apache/marmotta/kiwi/versioning/test/version-update2.rdf
@@ -0,0 +1,24 @@
+<!--
+ ~ Copyright (c) 2013 Salzburg Research.
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<rdf:RDF
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:ns1="http://marmotta.incubator.apache.org/testing/ns1/">
+ <ns1:C rdf:about="http://marmotta.incubator.apache.org/testing/ns1/R1">
+ <ns1:P3>property 3 value 1</ns1:P3>
+ </ns1:C>
+
+</rdf:RDF>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/c32963d5/kiwi/pom.xml
----------------------------------------------------------------------
diff --git a/kiwi/pom.xml b/kiwi/pom.xml
new file mode 100644
index 0000000..2c2baca
--- /dev/null
+++ b/kiwi/pom.xml
@@ -0,0 +1,179 @@
+<!--
+ ~ Copyright (c) 2013 The Apache Software Foundation
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>at.newmedialab.lmf</groupId>
+ <artifactId>lmf-parent</artifactId>
+ <version>3.0.0-SNAPSHOT</version>
+ <relativePath>../</relativePath>
+ </parent>
+
+ <artifactId>kiwi-parent</artifactId>
+ <packaging>pom</packaging>
+
+ <name>KiWi Triplestore: Parent</name>
+ <description>A Sesame Triple Store based on a relational database. Supports reasoning and versioning.</description>
+ <url>https://code.google.com/p/ldpath/</url>
+
+ <inceptionYear>2008</inceptionYear>
+ <licenses>
+ <license>
+ <name>Apache Software License, Version 2.0</name>
+ <url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
+ <distribution>repo</distribution>
+ <comments>A business-friendly OSS license</comments>
+ </license>
+ </licenses>
+
+ <developers>
+ <developer>
+ <name>Sebastian Schaffert</name>
+ <email>sebastian.schaffert@salzburgresearch.at</email>
+ <organization>Salzburg Research</organization>
+ </developer>
+ </developers>
+
+ <organization>
+ <name>Salzburg Research</name>
+ <url>http://www.salzburgresearch.at</url>
+ </organization>
+
+ <properties>
+ <sesameVersion>2.6.10</sesameVersion>
+ <sl4jVersion>1.7.2</sl4jVersion>
+ <logbackVersion>1.0.7</logbackVersion>
+ </properties>
+
+
+
+ <build>
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <version>2.13</version>
+ <configuration>
+ <systemPropertyVariables>
+ <h2.url>jdbc:h2:mem:test;MVCC=true;DB_CLOSE_ON_EXIT=TRUE</h2.url>
+ <h2.user>sa</h2.user>
+ <h2.pass />
+
+ <!-- enable or pass on command line for testing local PostgreSQL -->
+ <postgresql.url>jdbc:postgresql://localhost:5433/kiwitest?prepareThreshold=3</postgresql.url>
+ <postgresql.user>lmf</postgresql.user>
+ <postgresql.pass>lmf</postgresql.pass>
+
+ <!-- enable or pass on command line for testing local MySQL -->
+ <mysql.url>jdbc:mysql://localhost:3306/kiwitest</mysql.url>
+ <mysql.user>lmf</mysql.user>
+ <mysql.pass>lmf</mysql.pass>
+ </systemPropertyVariables>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>surefire-booter</artifactId>
+ <version>2.13</version>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-gpg-plugin</artifactId>
+ <version>1.4</version>
+ <!-- uncomment for release deployment -->
+ <executions>
+ <execution>
+ <id>sign-artifacts</id>
+ <phase>verify</phase>
+ <goals>
+ <goal>sign</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <version>2.3.7</version>
+ <inherited>true</inherited>
+ <configuration>
+ <instructions>
+ <Bundle-DocURL>http://code.google.com/p/ldpath/</Bundle-DocURL>
+ <Bundle-Vendor>Salzburg Research</Bundle-Vendor>
+ <Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
+ <_versionpolicy>$${version;===;${@}}</_versionpolicy>
+ </instructions>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-scr-plugin</artifactId>
+ <version>1.7.4</version>
+ <executions>
+ <execution>
+ <id>generate-scr-scrdescriptor</id>
+ <goals>
+ <goal>scr</goal>
+ </goals>
+ <configuration>
+ <properties>
+ <service.vendor>Salzburg Research</service.vendor>
+ </properties>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin> <!-- generate JRebel Configuration -->
+ <groupId>org.zeroturnaround</groupId>
+ <artifactId>jrebel-maven-plugin</artifactId>
+ <configuration>
+ <relativePath>../../</relativePath>
+ </configuration>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>at.newmedialab.lmf</groupId>
+ <artifactId>kiwi-triplestore</artifactId>
+ <version>${project.version}</version>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+
+ <modules>
+ <module>kiwi-contextaware</module>
+ <module>kiwi-triplestore</module>
+ <module>kiwi-transactions</module>
+ <module>kiwi-tripletable</module>
+ <module>kiwi-versioning</module>
+ <module>kiwi-reasoner</module>
+ </modules>
+
+</project>
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/c32963d5/ldcache/.project
----------------------------------------------------------------------
diff --git a/ldcache/.project b/ldcache/.project
new file mode 100644
index 0000000..6de81ee
--- /dev/null
+++ b/ldcache/.project
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>ldcache-parent</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.m2e.core.maven2Builder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.m2e.core.maven2Nature</nature>
+ </natures>
+</projectDescription>
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/c32963d5/ldcache/.settings/org.eclipse.m2e.core.prefs
----------------------------------------------------------------------
diff --git a/ldcache/.settings/org.eclipse.m2e.core.prefs b/ldcache/.settings/org.eclipse.m2e.core.prefs
new file mode 100644
index 0000000..f897a7f
--- /dev/null
+++ b/ldcache/.settings/org.eclipse.m2e.core.prefs
@@ -0,0 +1,4 @@
+activeProfiles=
+eclipse.preferences.version=1
+resolveWorkspaceProjects=true
+version=1
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/c32963d5/ldcache/README.txt
----------------------------------------------------------------------
diff --git a/ldcache/README.txt b/ldcache/README.txt
new file mode 100644
index 0000000..a593d58
--- /dev/null
+++ b/ldcache/README.txt
@@ -0,0 +1,10 @@
+This components implements Linked Data Caching support in conjunction with the Linked Data Client Library.
+It provides the following modules:
+- ldcache-api: interfaces and data model for Linked Data Caching
+- ldcache-core: core library implementation, manages the caching functionality
+- ldcache-sail: Sesame StackedSail that can be used for transparently retrieving Linked Data Resources when
+ requested through the Sesame API
+- ldcache-backend-kiwi: caching backend based on the KiWi triplestore; allows persisting caching information
+ in the JDBC database used by KiWi
+
+Other backends can be implemented as needed.
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/c32963d5/ldcache/ldcache-api/.classpath
----------------------------------------------------------------------
diff --git a/ldcache/ldcache-api/.classpath b/ldcache/ldcache-api/.classpath
new file mode 100644
index 0000000..90df7da
--- /dev/null
+++ b/ldcache/ldcache-api/.classpath
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
+ <classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER"/>
+ <classpathentry kind="output" path="target/classes"/>
+</classpath>
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/c32963d5/ldcache/ldcache-api/.project
----------------------------------------------------------------------
diff --git a/ldcache/ldcache-api/.project b/ldcache/ldcache-api/.project
new file mode 100644
index 0000000..d5d1332
--- /dev/null
+++ b/ldcache/ldcache-api/.project
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>ldcache-api</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.m2e.core.maven2Builder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.zeroturnaround.eclipse.rebelXmlBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ <nature>org.eclipse.m2e.core.maven2Nature</nature>
+ <nature>org.zeroturnaround.eclipse.jrebelNature</nature>
+ </natures>
+</projectDescription>
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/c32963d5/ldcache/ldcache-api/.settings/org.eclipse.jdt.core.prefs
----------------------------------------------------------------------
diff --git a/ldcache/ldcache-api/.settings/org.eclipse.jdt.core.prefs b/ldcache/ldcache-api/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..60105c1
--- /dev/null
+++ b/ldcache/ldcache-api/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,5 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.source=1.6
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/c32963d5/ldcache/ldcache-api/.settings/org.eclipse.m2e.core.prefs
----------------------------------------------------------------------
diff --git a/ldcache/ldcache-api/.settings/org.eclipse.m2e.core.prefs b/ldcache/ldcache-api/.settings/org.eclipse.m2e.core.prefs
new file mode 100644
index 0000000..f897a7f
--- /dev/null
+++ b/ldcache/ldcache-api/.settings/org.eclipse.m2e.core.prefs
@@ -0,0 +1,4 @@
+activeProfiles=
+eclipse.preferences.version=1
+resolveWorkspaceProjects=true
+version=1
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/c32963d5/ldcache/ldcache-api/pom.xml
----------------------------------------------------------------------
diff --git a/ldcache/ldcache-api/pom.xml b/ldcache/ldcache-api/pom.xml
new file mode 100644
index 0000000..4bf13f8
--- /dev/null
+++ b/ldcache/ldcache-api/pom.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (c) 2013 The Apache Software Foundation
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>at.newmedialab.lmf</groupId>
+ <artifactId>ldcache-parent</artifactId>
+ <version>3.0.0-SNAPSHOT</version>
+ <relativePath>../</relativePath>
+ </parent>
+
+ <artifactId>ldcache-api</artifactId>
+ <name>LDCache: API</name>
+
+ <description>
+ Interfaces and Data Model for the Linked Data Caching component.
+ </description>
+
+ <dependencies>
+
+ <dependency>
+ <groupId>at.newmedialab.lmf</groupId>
+ <artifactId>ldclient-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.openrdf.sesame</groupId>
+ <artifactId>sesame-model</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.openrdf.sesame</groupId>
+ <artifactId>sesame-repository-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.openrdf.sesame</groupId>
+ <artifactId>sesame-query</artifactId>
+ </dependency>
+
+ </dependencies>
+</project>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/c32963d5/ldcache/ldcache-api/src/main/java/org/apache/marmotta/ldcache/api/LDCachingBackend.java
----------------------------------------------------------------------
diff --git a/ldcache/ldcache-api/src/main/java/org/apache/marmotta/ldcache/api/LDCachingBackend.java b/ldcache/ldcache-api/src/main/java/org/apache/marmotta/ldcache/api/LDCachingBackend.java
new file mode 100644
index 0000000..e6fdc90
--- /dev/null
+++ b/ldcache/ldcache-api/src/main/java/org/apache/marmotta/ldcache/api/LDCachingBackend.java
@@ -0,0 +1,69 @@
+/**
+ * Copyright (C) 2013 Salzburg Research.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.marmotta.ldcache.api;
+
+import info.aduna.iteration.CloseableIteration;
+import org.apache.marmotta.ldcache.model.CacheEntry;
+import org.openrdf.repository.RepositoryException;
+
+/**
+ * This interface defines the API for different backends for storing the caching results.
+ * <p/>
+ * Author: Sebastian Schaffert (sschaffert@apache.org)
+ */
+public interface LDCachingBackend {
+
+ /**
+ * Return a repository connection that can be used for caching. The LDCache will first remove all statements for
+ * the newly cached resources and then add retrieved statements as-is to this connection and properly commit and
+ * close it after use.
+ * <p/>
+ * Note that in case the statements should be rewritten this method must take care of providing the proper
+ * connection, e.g. by using a ContextAwareRepositoryConnection to add a context to all statements when adding them.
+ *
+ *
+ * @param resource the resource that will be cached
+ * @return a repository connection that can be used for storing retrieved triples for caching
+ */
+ public LDCachingConnection getCacheConnection(String resource) throws RepositoryException;
+
+
+ /**
+ * Return an iterator over all expired cache entries (can e.g. be used for refreshing).
+ *
+ * @return
+ */
+ public CloseableIteration<CacheEntry,RepositoryException> listExpiredEntries() throws RepositoryException;
+
+
+ /**
+ * Return an iterator over all cache entries (can e.g. be used for refreshing or expiring).
+ *
+ * @return
+ */
+ public CloseableIteration<CacheEntry,RepositoryException> listCacheEntries() throws RepositoryException;
+
+
+ /**
+ * Carry out any initialization tasks that might be necessary
+ */
+ public void initialize();
+
+ /**
+ * Shutdown the backend and free all runtime resources.
+ */
+ public void shutdown();
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/c32963d5/ldcache/ldcache-api/src/main/java/org/apache/marmotta/ldcache/api/LDCachingConnection.java
----------------------------------------------------------------------
diff --git a/ldcache/ldcache-api/src/main/java/org/apache/marmotta/ldcache/api/LDCachingConnection.java b/ldcache/ldcache-api/src/main/java/org/apache/marmotta/ldcache/api/LDCachingConnection.java
new file mode 100644
index 0000000..6a284d0
--- /dev/null
+++ b/ldcache/ldcache-api/src/main/java/org/apache/marmotta/ldcache/api/LDCachingConnection.java
@@ -0,0 +1,57 @@
+/**
+ * Copyright (C) 2013 Salzburg Research.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.marmotta.ldcache.api;
+
+import org.apache.marmotta.ldcache.model.CacheEntry;
+import org.openrdf.model.URI;
+import org.openrdf.repository.RepositoryConnection;
+import org.openrdf.repository.RepositoryException;
+
+/**
+ * Add file description here!
+ * <p/>
+ * Author: Sebastian Schaffert (sschaffert@apache.org)
+ */
+public interface LDCachingConnection extends RepositoryConnection {
+
+
+ /**
+ * Get the cache entry for the passed resource, if any. Returns null in case there is no cache entry.
+ *
+ *
+ * @param resource the resource to look for
+ * @return the cache entry for the resource, or null if the resource has never been cached or is expired
+ */
+ public CacheEntry getCacheEntry(URI resource) throws RepositoryException;
+
+ /**
+ * Store a cache entry for the passed resource in the backend. Depending on the backend, this can be a
+ * persistent storage or an in-memory storage.
+ *
+ * @param resource
+ * @param entry
+ */
+ public void addCacheEntry(URI resource, CacheEntry entry) throws RepositoryException;
+
+
+ /**
+ * Remove the currently stored cache entry for the passed resource from the backend.
+ * @param resource
+ */
+ public void removeCacheEntry(URI resource) throws RepositoryException;
+
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/c32963d5/ldcache/ldcache-api/src/main/java/org/apache/marmotta/ldcache/api/LDCachingService.java
----------------------------------------------------------------------
diff --git a/ldcache/ldcache-api/src/main/java/org/apache/marmotta/ldcache/api/LDCachingService.java b/ldcache/ldcache-api/src/main/java/org/apache/marmotta/ldcache/api/LDCachingService.java
new file mode 100644
index 0000000..54a3f6a
--- /dev/null
+++ b/ldcache/ldcache-api/src/main/java/org/apache/marmotta/ldcache/api/LDCachingService.java
@@ -0,0 +1,101 @@
+/**
+ * Copyright (C) 2013 Salzburg Research.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.marmotta.ldcache.api;
+
+import info.aduna.iteration.CloseableIteration;
+import org.apache.marmotta.ldcache.model.CacheEntry;
+import org.openrdf.model.URI;
+import org.openrdf.repository.RepositoryException;
+
+/**
+ * Add file description here!
+ * <p/>
+ * User: sschaffe
+ */
+public interface LDCachingService {
+
+
+ /**
+ * Refresh the cached resource passed as argument. The method will do nothing for local
+ * resources.
+ * Calling the method will carry out the following tasks:
+ * 1. check whether the resource is a remote resource; if no, returns immediately
+ * 2. check whether the resource has a cache entry; if no, goto 4
+ * 3. check whether the expiry time of the cache entry has passed; if no, returns immediately
+ * 4. retrieve the triples for the resource from the Linked Data Cloud using the methods offered
+ * by the
+ * LinkedDataClientService (registered endpoints etc); returns immediately if the result is null
+ * or
+ * an exception is thrown
+ * 5. remove all old triples for the resource and add all new triples for the resource
+ * 6. create new expiry information of the cache entry and persist it in the transaction
+ *
+ *
+ * @param resource
+ * @param forceRefresh if <code>true</code> the resource will be refreshed despite the
+ */
+ public void refreshResource(URI resource, boolean forceRefresh);
+
+ /**
+ * Refresh all expired resources by listing the cache entries that have expired and calling refreshResource on
+ * them. This method can e.g. be called by a scheduled task to regularly update cache entries to always have
+ * the latest version available in the Search Index and elsewhere.
+ */
+ public void refreshExpired();
+
+ /**
+ * Manually expire the caching information for the given resource. The resource will be
+ * re-retrieved upon the next access.
+ *
+ * @param resource the Resource to expire.
+ */
+ public void expire(URI resource);
+
+ /**
+ * Manually expire all cached resources.
+ *
+ * @see #expire(org.openrdf.model.URI)
+ */
+ public void expireAll();
+
+
+ /**
+ * Shutdown the caching service and free all occupied runtime resources.
+ */
+ public void shutdown();
+
+ /**
+ * Return a repository connection that can be used for accessing cached resources.
+ *
+ * @param resource the resource that will be cached
+ * @return a repository connection that can be used for storing retrieved triples for caching
+ */
+ LDCachingConnection getCacheConnection(String resource) throws RepositoryException;
+
+ /**
+ * Return an iterator over all cache entries (can e.g. be used for refreshing or expiring).
+ *
+ * @return
+ */
+ CloseableIteration<CacheEntry, RepositoryException> listCacheEntries() throws RepositoryException;
+
+ /**
+ * Return an iterator over all expired cache entries (can e.g. be used for refreshing).
+ *
+ * @return
+ */
+ CloseableIteration<CacheEntry, RepositoryException> listExpiredEntries() throws RepositoryException;
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/c32963d5/ldcache/ldcache-api/src/main/java/org/apache/marmotta/ldcache/model/CacheConfiguration.java
----------------------------------------------------------------------
diff --git a/ldcache/ldcache-api/src/main/java/org/apache/marmotta/ldcache/model/CacheConfiguration.java b/ldcache/ldcache-api/src/main/java/org/apache/marmotta/ldcache/model/CacheConfiguration.java
new file mode 100644
index 0000000..4302735
--- /dev/null
+++ b/ldcache/ldcache-api/src/main/java/org/apache/marmotta/ldcache/model/CacheConfiguration.java
@@ -0,0 +1,56 @@
+/**
+ * Copyright (C) 2013 Salzburg Research.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.marmotta.ldcache.model;
+
+import org.apache.marmotta.ldclient.model.ClientConfiguration;
+
+/**
+ * Configuration options for LDCache instances. Can be subclassed by backends as needed.
+ * <p/>
+ * Author: Sebastian Schaffert (sschaffert@apache.org)
+ */
+public class CacheConfiguration {
+
+ /** the LDClient configuration to use for configuring the Linked Data Client */
+ private ClientConfiguration clientConfiguration;
+
+
+ private long defaultExpiry = 86400L;
+
+ public CacheConfiguration() {
+ this(new ClientConfiguration());
+ }
+
+ public CacheConfiguration(ClientConfiguration clientConfiguration) {
+ this.clientConfiguration = clientConfiguration;
+ }
+
+ public ClientConfiguration getClientConfiguration() {
+ return clientConfiguration;
+ }
+
+ public void setClientConfiguration(ClientConfiguration clientConfiguration) {
+ this.clientConfiguration = clientConfiguration;
+ }
+
+ public long getDefaultExpiry() {
+ return defaultExpiry;
+ }
+
+ public void setDefaultExpiry(long defaultExpiry) {
+ this.defaultExpiry = defaultExpiry;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/c32963d5/ldcache/ldcache-api/src/main/java/org/apache/marmotta/ldcache/model/CacheEntry.java
----------------------------------------------------------------------
diff --git a/ldcache/ldcache-api/src/main/java/org/apache/marmotta/ldcache/model/CacheEntry.java b/ldcache/ldcache-api/src/main/java/org/apache/marmotta/ldcache/model/CacheEntry.java
new file mode 100644
index 0000000..72a1775
--- /dev/null
+++ b/ldcache/ldcache-api/src/main/java/org/apache/marmotta/ldcache/model/CacheEntry.java
@@ -0,0 +1,90 @@
+/**
+ * Copyright (C) 2013 Salzburg Research.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.marmotta.ldcache.model;
+
+import org.openrdf.model.URI;
+
+import java.util.Date;
+
+/**
+ * The cache entry for a URI resource managed by the Linked Data Cache. Contains maintenance information about
+ * the resource, i.e. when it has been retrieved last, when to retrieve it next, etc.
+ * <p/>
+ * User: Sebastian Schaffert
+ */
+public class CacheEntry {
+
+ /**
+ * The URI resource managed by this cache entry.
+ */
+ private URI resource;
+
+ /**
+ * The date when this resource has been retrieved the last time.
+ */
+ private Date lastRetrieved;
+
+
+ /**
+ * The date when this resource needs to be retrieved again according to expiry configuration.
+ */
+ private Date expiryDate;
+
+
+ /**
+ * The number of times this resource has already been updated.
+ */
+ private Integer updateCount;
+
+
+
+ public CacheEntry() {
+ }
+
+
+ public URI getResource() {
+ return resource;
+ }
+
+ public void setResource(URI resource) {
+ this.resource = resource;
+ }
+
+ public Date getLastRetrieved() {
+ return lastRetrieved;
+ }
+
+ public void setLastRetrieved(Date lastRetrieved) {
+ this.lastRetrieved = new Date(lastRetrieved.getTime());
+ }
+
+ public Date getExpiryDate() {
+ return expiryDate;
+ }
+
+ public void setExpiryDate(Date expiryDate) {
+ this.expiryDate = new Date(expiryDate.getTime());
+ }
+
+ public Integer getUpdateCount() {
+ return updateCount;
+ }
+
+ public void setUpdateCount(Integer updateCount) {
+ this.updateCount = updateCount;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/c32963d5/ldcache/ldcache-api/src/main/java/org/apache/marmotta/ldcache/sail/LDCachingSail.java
----------------------------------------------------------------------
diff --git a/ldcache/ldcache-api/src/main/java/org/apache/marmotta/ldcache/sail/LDCachingSail.java b/ldcache/ldcache-api/src/main/java/org/apache/marmotta/ldcache/sail/LDCachingSail.java
new file mode 100644
index 0000000..43a1015
--- /dev/null
+++ b/ldcache/ldcache-api/src/main/java/org/apache/marmotta/ldcache/sail/LDCachingSail.java
@@ -0,0 +1,32 @@
+/**
+ * Copyright (C) 2013 Salzburg Research.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.marmotta.ldcache.sail;
+
+import org.openrdf.sail.Sail;
+
+/**
+ * Add file description here!
+ * <p/>
+ * Author: Sebastian Schaffert (sschaffert@apache.org)
+ */
+public interface LDCachingSail extends Sail {
+
+ /**
+ * Return a caching connection.
+ * @return
+ */
+ public LDCachingSailConnection getConnection();
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/c32963d5/ldcache/ldcache-api/src/main/java/org/apache/marmotta/ldcache/sail/LDCachingSailConnection.java
----------------------------------------------------------------------
diff --git a/ldcache/ldcache-api/src/main/java/org/apache/marmotta/ldcache/sail/LDCachingSailConnection.java b/ldcache/ldcache-api/src/main/java/org/apache/marmotta/ldcache/sail/LDCachingSailConnection.java
new file mode 100644
index 0000000..d91d24d
--- /dev/null
+++ b/ldcache/ldcache-api/src/main/java/org/apache/marmotta/ldcache/sail/LDCachingSailConnection.java
@@ -0,0 +1,55 @@
+/**
+ * Copyright (C) 2013 Salzburg Research.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.marmotta.ldcache.sail;
+
+import org.apache.marmotta.ldcache.model.CacheEntry;
+import org.openrdf.model.URI;
+import org.openrdf.sail.SailConnection;
+import org.openrdf.sail.SailException;
+
+/**
+ * Add file description here!
+ * <p/>
+ * Author: Sebastian Schaffert (sschaffert@apache.org)
+ */
+public interface LDCachingSailConnection extends SailConnection {
+
+ /**
+ * Get the cache entry for the passed resource, if any. Returns null in case there is no cache entry.
+ *
+ *
+ * @param resource the resource to look for
+ * @return the cache entry for the resource, or null if the resource has never been cached or is expired
+ */
+ public CacheEntry getCacheEntry(URI resource) throws SailException;
+
+ /**
+ * Store a cache entry for the passed resource in the backend. Depending on the backend, this can be a
+ * persistent storage or an in-memory storage.
+ *
+ * @param resource
+ * @param entry
+ */
+ public void addCacheEntry(URI resource, CacheEntry entry) throws SailException;
+
+
+ /**
+ * Remove the currently stored cache entry for the passed resource from the backend.
+ * @param resource
+ */
+ public void removeCacheEntry(URI resource) throws SailException;
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/c32963d5/ldcache/ldcache-backend-ehcache/pom.xml
----------------------------------------------------------------------
diff --git a/ldcache/ldcache-backend-ehcache/pom.xml b/ldcache/ldcache-backend-ehcache/pom.xml
new file mode 100644
index 0000000..b1b6453
--- /dev/null
+++ b/ldcache/ldcache-backend-ehcache/pom.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (c) 2013 The Apache Software Foundation
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>at.newmedialab.lmf</groupId>
+ <artifactId>ldcache-parent</artifactId>
+ <version>3.0.0-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>ldcache-backend-ehcache</artifactId>
+ <name>LDCache Backend: EHCache</name>
+
+ <description>
+ This module offers a backend that allows storing cache entries in an EHCache instance. The backend class is
+ abstract and needs to be subclassed to provide the repository connection for the triples.
+ </description>
+
+
+ <dependencies>
+
+
+ <dependency>
+ <groupId>at.newmedialab.lmf</groupId>
+ <artifactId>ldcache-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>at.newmedialab.lmf</groupId>
+ <artifactId>kiwi-tripletable</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>net.sf.ehcache</groupId>
+ <artifactId>ehcache-core</artifactId>
+ </dependency>
+ </dependencies>
+
+</project>
\ No newline at end of file