diff --git a/qendpoint-backend/pom.xml b/qendpoint-backend/pom.xml
index 6b75e331..2686d2fb 100644
--- a/qendpoint-backend/pom.xml
+++ b/qendpoint-backend/pom.xml
@@ -46,7 +46,7 @@
5.0.2
3.4.0
1.5.6
-
+ 2.11.0
UTF-8
UTF-8
@@ -112,6 +112,11 @@
+
+ com.google.code.gson
+ gson
+ ${gson.version}
+
commons-codec
diff --git a/qendpoint-backend/src/main/java/com/the_qa_company/qendpoint/controller/Sparql.java b/qendpoint-backend/src/main/java/com/the_qa_company/qendpoint/controller/Sparql.java
index 7b25ce0c..ed9223ee 100644
--- a/qendpoint-backend/src/main/java/com/the_qa_company/qendpoint/controller/Sparql.java
+++ b/qendpoint-backend/src/main/java/com/the_qa_company/qendpoint/controller/Sparql.java
@@ -12,6 +12,8 @@
import com.the_qa_company.qendpoint.store.EndpointStoreUtils;
import com.the_qa_company.qendpoint.utils.FileUtils;
import com.the_qa_company.qendpoint.utils.RDFStreamUtils;
+import jakarta.annotation.PostConstruct;
+import jakarta.annotation.PreDestroy;
import org.eclipse.rdf4j.model.Statement;
import org.eclipse.rdf4j.model.util.Values;
import org.eclipse.rdf4j.repository.RepositoryConnection;
@@ -34,8 +36,6 @@
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebInputException;
-import javax.annotation.PostConstruct;
-import javax.annotation.PreDestroy;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
diff --git a/qendpoint-core/pom.xml b/qendpoint-core/pom.xml
index d0522ca2..46dde950 100644
--- a/qendpoint-core/pom.xml
+++ b/qendpoint-core/pom.xml
@@ -48,7 +48,7 @@
1.5.6
0.9.44
- 4.3.2
+ 4.9.0
1.7.30
UTF-8
@@ -75,7 +75,7 @@
org.apache.commons
commons-compress
- 1.21
+ 1.26.0
org.apache.jena
diff --git a/qendpoint-core/src/main/java/com/the_qa_company/qendpoint/core/iterator/utils/GraphFilteringTripleId.java b/qendpoint-core/src/main/java/com/the_qa_company/qendpoint/core/iterator/utils/GraphFilteringTripleId.java
index a1b597c0..3894787a 100644
--- a/qendpoint-core/src/main/java/com/the_qa_company/qendpoint/core/iterator/utils/GraphFilteringTripleId.java
+++ b/qendpoint-core/src/main/java/com/the_qa_company/qendpoint/core/iterator/utils/GraphFilteringTripleId.java
@@ -16,7 +16,6 @@ public GraphFilteringTripleId(IteratorTripleID iterator, long[] graphIds) {
this.graphIds = graphIds;
}
-
@Override
public void goToStart() {
throw new NotImplementedException();
diff --git a/qendpoint-core/src/main/java/com/the_qa_company/qendpoint/core/triples/IteratorTripleID.java b/qendpoint-core/src/main/java/com/the_qa_company/qendpoint/core/triples/IteratorTripleID.java
index 0c57074d..0fe04b12 100644
--- a/qendpoint-core/src/main/java/com/the_qa_company/qendpoint/core/triples/IteratorTripleID.java
+++ b/qendpoint-core/src/main/java/com/the_qa_company/qendpoint/core/triples/IteratorTripleID.java
@@ -92,9 +92,11 @@ default boolean isLastTriplePositionBoundToOrder() {
/**
* goto the next subject >= id
+ *
* @param id id
* @return true if the next subject == id
- * @see #canGoToSubject() if can goto returns false, this function is not available
+ * @see #canGoToSubject() if can goto returns false, this function is not
+ * available
*/
default boolean gotoSubject(long id) {
return false;
@@ -102,9 +104,11 @@ default boolean gotoSubject(long id) {
/**
* goto the next predicate >= id
+ *
* @param id id
* @return true if the next predicate == id
- * @see #canGoToPredicate() if can goto returns false, this function is not available
+ * @see #canGoToPredicate() if can goto returns false, this function is not
+ * available
*/
default boolean gotoPredicate(long id) {
return false;
@@ -112,9 +116,11 @@ default boolean gotoPredicate(long id) {
/**
* goto the next object >= id
+ *
* @param id id
* @return true if the next object == id
- * @see #canGoToObject() if can goto returns false, this function is not available
+ * @see #canGoToObject() if can goto returns false, this function is not
+ * available
*/
default boolean gotoObject(long id) {
return false;
@@ -126,12 +132,14 @@ default boolean gotoObject(long id) {
default boolean canGoToSubject() {
return false;
}
+
/**
* @return true if {@link #gotoPredicate(long)} can be used, false otherwise
*/
default boolean canGoToPredicate() {
return false;
}
+
/**
* @return true if {@link #gotoObject(long)} can be used, false otherwise
*/
diff --git a/qendpoint-core/src/main/java/com/the_qa_company/qendpoint/core/triples/impl/BitmapTriplesIterator.java b/qendpoint-core/src/main/java/com/the_qa_company/qendpoint/core/triples/impl/BitmapTriplesIterator.java
index e62df132..d5b465d1 100644
--- a/qendpoint-core/src/main/java/com/the_qa_company/qendpoint/core/triples/impl/BitmapTriplesIterator.java
+++ b/qendpoint-core/src/main/java/com/the_qa_company/qendpoint/core/triples/impl/BitmapTriplesIterator.java
@@ -272,39 +272,50 @@ public boolean isLastTriplePositionBoundToOrder() {
private boolean gotoOrder(long id, TripleComponentRole role) {
switch (role) {
- case SUBJECT -> {
- if (patX != 0) {
- return id == patX; // can't jump or already on the right element
- }
-
- patX = id;
- findRange();
- patX = 0;
+ case SUBJECT -> {
+ if (patX != 0) {
+ return id == patX; // can't jump or already on the right element
+ }
- return true; // we know x exists because we are using
+ if (x >= id) {
+ return id == x;
}
- case PREDICATE -> {
- if (patY != 0) {
- return id == patY; // can't jump or already on the right element
- }
- if (posY == nextY) {
- return false; // no next element
- }
+ x = id;
+ posY = adjY.find(x - 1);
+ posZ = adjZ.find(posY);
+ y = adjY.get(posY);
+ nextY = adjY.last(x - 1) + 1;
+ nextZ = adjZ.find(posY + 1);
- long curr = this.adjY.get(posY);
+ return true; // we know x exists
+ }
+ case PREDICATE -> {
+ if (patY != 0) {
+ return id == patY; // can't jump or already on the right element
+ }
- if (curr >= id) {
- return curr == id;
- }
- if (posY + 1 == nextY) {
- return false; // no next element
- }
+ if (posY == nextY) {
+ return false; // no next element
+ }
- long last = this.adjY.get(nextY - 1);
+ long curr = this.adjY.get(posY);
+ if (curr >= id) {
+ return curr == id;
+ }
- boolean res;
+ boolean res;
+ if (posY + 1 == nextY) {
+ // no next element, go next X
+ x++;
+ posY = nextY;
+ nextY = adjY.findNext(posY) + 1;
+ y = adjY.get(posY);
+
+ res = false;
+ } else {
+ long last = this.adjY.get(nextY - 1);
if (last > id) {
// binary search between curr <-> last id
@@ -319,77 +330,79 @@ private boolean gotoOrder(long id, TripleComponentRole role) {
posY = -loc - 1;
y = adjY.get(posY);
}
- } else if (last != id) {
- // last < id - GOTO end + 1
- posY = nextY;
- res = false;
} else {
- // last == id - GOTO last
- posY = nextY - 1;
- y = adjY.get(posY);
- res = true;
+ if (last != id) {
+ // last < id - GOTO end + 1
+ posY = nextY;
+ res = false;
+ } else {
+ // last == id - GOTO last
+ posY = nextY - 1;
+ y = adjY.get(posY);
+ res = true;
+ }
+ nextY = adjY.findNext(posY) + 1;
}
+ }
- nextY = adjY.findNext(posY) + 1;
-
- // down to z/posZ/nextZ?
- posZ = adjZ.find(posY, patZ);
- nextZ = adjZ.findNext(posZ) + 1;
+ // down to z/posZ/nextZ?
+ posZ = adjZ.find(posY); // assert patZ != 0
+ nextZ = adjZ.findNext(posZ) + 1;
- return res;
+ return res;
+ }
+ case OBJECT -> {
+ if (patZ != 0) {
+ return id == patZ; // can't jump or already on the right element
}
- case OBJECT -> {
- if (patZ != 0) {
- return id == patZ; // can't jump or already on the right element
- }
- if (posZ == nextZ) {
- return false; // no next element
- }
-
- long curr = this.adjZ.get(posZ);
+ if (posZ == nextZ) {
+ return false; // no next element
+ }
- if (curr >= id) {
- return curr == id;
- }
- if (posZ + 1 == nextZ) {
- return false; // no next element
- }
+ long curr = this.adjZ.get(posZ);
- long last = this.adjZ.get(nextZ - 1);
+ if (curr >= id) {
+ return curr == id;
+ }
+ if (posZ + 1 == nextZ) {
+ return false; // no next element
+ }
+ long last = this.adjZ.get(nextZ - 1);
- boolean res;
+ boolean res;
- if (last > id) {
- // binary search between curr <-> last id
- long loc = this.adjZ.searchLoc(id, posZ + 1, nextZ - 2);
+ if (last > id) {
+ // binary search between curr <-> last id
+ long loc = this.adjZ.searchLoc(id, posZ + 1, nextZ - 2);
- if (loc >= 0) { //match
- res = true;
- posZ = loc;
- //z = id; // no need to compute the z, it is only used in next()
- } else {
- res = false;
- posZ = -loc - 1;
- //z = adjZ.get(posZ);
- }
- } else if (last != id) {
- // last < id - GOTO end
- posZ = nextZ;
- res = false;
- } else {
- // last == id - GOTO last
- posZ = nextZ - 1;
- //z = adjZ.get(posZ);
+ if (loc >= 0) { // match
res = true;
+ posZ = loc;
+ // z = id; // no need to compute the z, it is only used in
+ // next()
+ } else {
+ res = false;
+ posZ = -loc - 1;
+ // z = adjZ.get(posZ);
}
+ } else if (last != id) {
+ // last < id - GOTO end
+ posZ = nextZ;
+ res = false;
+ } else {
+ // last == id - GOTO last
+ posZ = nextZ - 1;
+ // z = adjZ.get(posZ);
+ res = true;
+ }
- nextZ = adjZ.findNext(posZ) + 1;
+ nextZ = adjZ.findNext(posZ) + 1;
- return res;
- }
- default -> throw new NotImplementedException("goto " + role);
+ return res;
+ }
+ default -> throw new NotImplementedException("goto " + role);
}
}
@@ -402,6 +415,7 @@ public boolean gotoSubject(long id) {
public boolean gotoPredicate(long id) {
return gotoOrder(id, idx.getOrder().getPredicateMapping());
}
+
@Override
public boolean gotoObject(long id) {
return gotoOrder(id, idx.getOrder().getObjectMapping());
@@ -411,10 +425,12 @@ public boolean gotoObject(long id) {
public boolean canGoToSubject() {
return true;
}
+
@Override
public boolean canGoToPredicate() {
return true;
}
+
@Override
public boolean canGoToObject() {
return true;
diff --git a/qendpoint-core/src/main/java/com/the_qa_company/qendpoint/core/triples/impl/TriplesList.java b/qendpoint-core/src/main/java/com/the_qa_company/qendpoint/core/triples/impl/TriplesList.java
index bc0c7f2e..4b6f522e 100644
--- a/qendpoint-core/src/main/java/com/the_qa_company/qendpoint/core/triples/impl/TriplesList.java
+++ b/qendpoint-core/src/main/java/com/the_qa_company/qendpoint/core/triples/impl/TriplesList.java
@@ -448,7 +448,6 @@ public TripleID next() {
return triplesList.arrayOfTriples.get(pos++).asTripleID();
}
-
/*
* (non-Javadoc)
* @see hdt.iterator.IteratorTripleID#goToStart()
diff --git a/qendpoint-core/src/test/java/com/the_qa_company/qendpoint/core/triples/impl/BitmapQuadTriplesTest.java b/qendpoint-core/src/test/java/com/the_qa_company/qendpoint/core/triples/impl/BitmapQuadTriplesTest.java
index 09344fdf..6d18a20a 100644
--- a/qendpoint-core/src/test/java/com/the_qa_company/qendpoint/core/triples/impl/BitmapQuadTriplesTest.java
+++ b/qendpoint-core/src/test/java/com/the_qa_company/qendpoint/core/triples/impl/BitmapQuadTriplesTest.java
@@ -34,7 +34,6 @@ private static IteratorTripleID fromList(List lst) {
private int current;
private int lastLoc;
-
@Override
public void goToStart() {
current = 0;
diff --git a/qendpoint-core/src/test/java/com/the_qa_company/qendpoint/core/triples/impl/BitmapTriplesIteratorTest.java b/qendpoint-core/src/test/java/com/the_qa_company/qendpoint/core/triples/impl/BitmapTriplesIteratorTest.java
index 4842866c..53c412b3 100644
--- a/qendpoint-core/src/test/java/com/the_qa_company/qendpoint/core/triples/impl/BitmapTriplesIteratorTest.java
+++ b/qendpoint-core/src/test/java/com/the_qa_company/qendpoint/core/triples/impl/BitmapTriplesIteratorTest.java
@@ -1,27 +1,34 @@
package com.the_qa_company.qendpoint.core.triples.impl;
-import java.io.IOException;
-import java.nio.file.Path;
-
-import com.the_qa_company.qendpoint.core.exceptions.NotFoundException;
+import com.the_qa_company.qendpoint.core.enums.RDFNotation;
+import com.the_qa_company.qendpoint.core.enums.TripleComponentOrder;
import com.the_qa_company.qendpoint.core.exceptions.ParserException;
import com.the_qa_company.qendpoint.core.hdt.HDT;
import com.the_qa_company.qendpoint.core.hdt.HDTManager;
+import com.the_qa_company.qendpoint.core.listener.ProgressListener;
import com.the_qa_company.qendpoint.core.options.HDTOptions;
+import com.the_qa_company.qendpoint.core.options.HDTOptionsKeys;
import com.the_qa_company.qendpoint.core.triples.IteratorTripleID;
-import com.the_qa_company.qendpoint.core.triples.IteratorTripleString;
import com.the_qa_company.qendpoint.core.triples.TripleID;
import com.the_qa_company.qendpoint.core.util.LargeFakeDataSetStreamSupplier;
import org.apache.commons.io.file.PathUtils;
-import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Path;
+import java.util.Random;
+
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
public class BitmapTriplesIteratorTest {
@@ -32,18 +39,6 @@ public class BitmapTriplesIteratorTest {
public void setUp() throws Exception {
}
- @Test
- public void test() throws IOException {
-// HDT hdt = HDTManager.mapHDT("/Users/mck/hdt/swdf.hdt", null);
-//
-// int t = (int) hdt.getTriples().getNumberOfElements();
-// BitmapTriplesIterator it = new BitmapTriplesIterator((BitmapTriples) hdt.getTriples(), t-10, t);
-//
-// while(it.hasNext()) {
-// System.out.println(it.next());
-// }
- }
-
@Test
public void jumpTest() throws IOException, ParserException {
Path root = tempDir.newFolder().toPath();
@@ -60,13 +55,11 @@ public void jumpTest() throws IOException, ParserException {
TripleID start = it.next().clone();
-
for (int i = 0; i < 458; i++) {
assertTrue(it.hasNext());
it.next();
}
-
TripleID lastTest = it.next().clone();
assertNotEquals(start, lastTest);
@@ -88,7 +81,274 @@ public void jumpTest() throws IOException, ParserException {
PathUtils.deleteDirectory(root);
}
+ }
+
+ private static final String JUMP_XYZ_DATASET = """
+ @prefix ex: .
+
+ ex:s1 ex:p1 ex:o0000, ex:o0001, ex:o0002, ex:o0003, ex:o0004, ex:o0005 ;
+ ex:p2 ex:o0000, ex:o0002, ex:o0003, ex:o0004, ex:o0005 ;
+ ex:p3 ex:o0000, ex:o0001, ex:o0002, ex:o0003, ex:o0004, ex:o0005 ;
+ ex:p4 ex:o0000, ex:o0001, ex:o0002, ex:o0004, ex:o0005 ;
+ ex:p5 ex:o0000, ex:o0001, ex:o0002, ex:o0003, ex:o0004, ex:o0005 .
+
+
+ ex:s2 ex:p1 ex:o0006, ex:o0007, ex:o0008, ex:o0009, ex:o0010, ex:o0011 ;
+ ex:p2 ex:o0008, ex:o0009, ex:o0010, ex:o0011 ;
+ ex:p3 ex:o0007, ex:o0008, ex:o0009, ex:o0010, ex:o0011 ;
+ ex:p4 ex:o0006, ex:o0007, ex:o0008, ex:o0009, ex:o0010, ex:o0011 .
+
+
+ ex:s3 ex:p1 ex:o0003, ex:o0005, ex:o0007, ex:o0009, ex:o0011, ex:o0015 ;
+ ex:p2 ex:o0003, ex:o0005, ex:o0007, ex:o0009, ex:o0011, ex:o0015 ;
+ ex:p3 ex:o0003, ex:o0005, ex:o0007, ex:o0009, ex:o0011, ex:o0015 ;
+ ex:p4 ex:o0003, ex:o0005, ex:o0007 ;
+ ex:p5 ex:o0003, ex:o0005, ex:o0007, ex:o0009, ex:o0011, ex:o0015 ;
+ ex:p6 ex:o0003, ex:o0007, ex:o0009, ex:o0011, ex:o0015 ;
+ ex:p7 ex:o0003, ex:o0005, ex:o0009, ex:o0011, ex:o0015 .
+
+
+ ex:s4 ex:p1 ex:o0003, ex:o0005, ex:o0007, ex:o0009, ex:o0011, ex:o0015 ;
+ ex:p2 ex:o0005, ex:o0007, ex:o0009, ex:o0011, ex:o0015 ;
+ ex:p3 ex:o0003, ex:o0005, ex:o0009, ex:o0011, ex:o0015 ;
+ ex:p4 ex:o0003, ex:o0005, ex:o0007, ex:o0009, ex:o0011, ex:o0015 ;
+ ex:p5 ex:o0003, ex:o0005, ex:o0007, ex:o0009 .
+
+ """;
+ private static final long JUMP_XYZ_DATASET_X = 4;
+ private static final long JUMP_XYZ_DATASET_Y = 4;
+
+ @Test
+ public void jumpXTest() throws IOException, ParserException {
+ Path root = tempDir.newFolder().toPath();
+
+ try {
+
+ Path hdtPath = root.resolve("test.hdt");
+
+ HDTOptions spec = HDTOptions.of(HDTOptionsKeys.BITMAPTRIPLES_INDEX_OTHERS, "spo,sop,pos,pso,ops,osp",
+ HDTOptionsKeys.BITMAPTRIPLES_INDEX_NO_FOQ, true);
+
+ try (HDT hdt = HDTManager.generateHDT(
+ new ByteArrayInputStream(JUMP_XYZ_DATASET.getBytes(StandardCharsets.UTF_8)),
+ LargeFakeDataSetStreamSupplier.BASE_URI, RDFNotation.TURTLE, spec, ProgressListener.ignore())) {
+ hdt.saveToHDT(hdtPath);
+ }
+
+ try (HDT hdt = HDTManager.mapIndexedHDT(hdtPath, spec, ProgressListener.ignore())) {
+
+ IteratorTripleID ittt = hdt.getTriples().searchAll();
+ assertTrue("bad class: " + ittt.getClass(), ittt instanceof BitmapTriplesIterator);
+
+ for (int sid = 1; sid <= JUMP_XYZ_DATASET_X; sid++) {
+ IteratorTripleID it = hdt.getTriples().searchAll();
+ IteratorTripleID itex = hdt.getTriples().searchAll();
+
+ assertTrue(it.gotoSubject(sid));
+
+ assertEquals(sid, it.next().getSubject());
+
+ long s;
+ do {
+ assertTrue(itex.hasNext());
+ s = itex.next().getSubject();
+ } while (s < sid);
+ assertEquals(sid, s);
+
+ assertTrue(it.hasNext());
+ do {
+ TripleID ac = it.next();
+ assertTrue(itex.hasNext());
+ TripleID ex = itex.next();
+ assertEquals(itex.getLastTriplePosition(), it.getLastTriplePosition());
+
+ assertEquals(ex, ac);
+ } while (it.hasNext());
+
+ assertFalse(itex.hasNext());
+ }
+ }
+ } finally {
+ PathUtils.deleteDirectory(root);
+ }
+ }
+
+ @Test
+ public void jumpYTest() throws IOException, ParserException {
+ Path root = tempDir.newFolder().toPath();
+
+ try {
+
+ Path hdtPath = root.resolve("test.hdt");
+
+ HDTOptions spec = HDTOptions.of(HDTOptionsKeys.BITMAPTRIPLES_INDEX_OTHERS, "spo,sop,pos,pso,ops,osp",
+ HDTOptionsKeys.BITMAPTRIPLES_INDEX_NO_FOQ, true);
+
+ try (HDT hdt = HDTManager.generateHDT(
+ new ByteArrayInputStream(JUMP_XYZ_DATASET.getBytes(StandardCharsets.UTF_8)),
+ LargeFakeDataSetStreamSupplier.BASE_URI, RDFNotation.TURTLE, spec, ProgressListener.ignore())) {
+ hdt.saveToHDT(hdtPath);
+ }
+
+ try (HDT hdt = HDTManager.mapIndexedHDT(hdtPath, spec, ProgressListener.ignore())) {
+
+ IteratorTripleID ittt = hdt.getTriples().searchAll();
+ assertTrue("bad class: " + ittt.getClass(), ittt instanceof BitmapTriplesIterator);
+
+ String lastPosData;
+
+ for (int sid = 1; sid <= JUMP_XYZ_DATASET_X; sid++) {
+ for (int pid = 1; pid <= JUMP_XYZ_DATASET_Y; pid++) {
+ IteratorTripleID it = hdt.getTriples().searchAll();
+ IteratorTripleID itex = hdt.getTriples().searchAll();
+
+ assertTrue(it.gotoSubject(sid));
+ assertTrue(it.gotoPredicate(pid));
+
+ TripleID next = it.next();
+ lastPosData = "[sid:" + sid + "/pid:" + pid + "][ac:" + it.getLastTriplePosition() + "/ex"
+ + itex.getLastTriplePosition() + "]" + next;
+ assertEquals("invalid pos: " + lastPosData, sid, next.getSubject());
+ assertEquals("invalid pos: " + lastPosData, pid, next.getPredicate());
+
+ long s;
+ long p;
+ do {
+ assertTrue(itex.hasNext());
+ TripleID next1 = itex.next();
+ s = next1.getSubject();
+ p = next1.getPredicate();
+ lastPosData = "[sid:" + sid + "/pid:" + pid + "][ac:" + it.getLastTriplePosition() + "/ex"
+ + itex.getLastTriplePosition() + "]" + next1;
+ } while (s < sid || p < pid);
+ assertEquals(lastPosData, sid, s);
+ assertEquals(lastPosData, pid, p);
+
+ assertTrue(it.hasNext());
+ do {
+ TripleID ac = it.next();
+ assertTrue(itex.hasNext());
+ TripleID ex = itex.next();
+ lastPosData = "[sid:" + sid + "/pid:" + pid + "][ac:" + it.getLastTriplePosition() + "/ex"
+ + itex.getLastTriplePosition() + "]" + ac + "/" + ex;
+ assertEquals(lastPosData, itex.getLastTriplePosition(), it.getLastTriplePosition());
+
+ assertEquals(lastPosData, ex, ac);
+ } while (it.hasNext());
+
+ assertFalse(itex.hasNext());
+ }
+ }
+ }
+ } finally {
+ PathUtils.deleteDirectory(root);
+ }
}
+ @Test
+ public void jumpXYZTest() throws IOException, ParserException {
+ Path root = tempDir.newFolder().toPath();
+
+ try {
+ Path hdtPath = root.resolve("test.hdt");
+
+ HDTOptions spec = HDTOptions.of(HDTOptionsKeys.BITMAPTRIPLES_INDEX_OTHERS, "spo,sop,pos,pso,ops,osp",
+ HDTOptionsKeys.BITMAPTRIPLES_INDEX_NO_FOQ, true);
+ final int count = 100_000;
+ LargeFakeDataSetStreamSupplier supplier = LargeFakeDataSetStreamSupplier
+ .createSupplierWithMaxTriples(count, 567890987).withMaxElementSplit(50).withMaxLiteralSize(20);
+
+ supplier.createAndSaveFakeHDT(spec, hdtPath);
+
+ Random rnd = new Random(34567);
+
+ try (HDT hdt = HDTManager.mapIndexedHDT(hdtPath, spec, ProgressListener.ignore())) {
+ int elements = (int) hdt.getTriples().getNumberOfElements();
+
+ for (int i = 0; i < count; i++) {
+ int idx = rnd.nextInt(elements);
+
+ IteratorTripleID it = hdt.getTriples().searchAll();
+
+ assertTrue(it.canGoTo());
+
+ it.goTo(idx);
+
+ TripleID current = it.next().clone();
+ assertEquals(idx, it.getLastTriplePosition());
+
+ for (int member = 0; member < 3; member++) {
+ IteratorTripleID itac = hdt.getTriples().searchAll(TripleComponentOrder.SPO.mask);
+ assertSame("invalid order (" + member + "/" + i + ")", itac.getOrder(),
+ TripleComponentOrder.SPO);
+
+ // test subject
+ assertTrue("Can't jump to subject " + current + " (" + member + "/" + i + ")",
+ itac.canGoToSubject() && itac.gotoSubject(current.getSubject()));
+
+ if (member >= 1) {
+ // test predicate
+ assertTrue("Can't jump to predicate " + current + " (" + member + "/" + i + ")",
+ itac.canGoToPredicate() && itac.gotoPredicate(current.getPredicate()));
+
+ if (member >= 2) {
+ // test object
+ assertTrue("Can't jump to object " + current + " (" + member + "/" + i + ")",
+ itac.canGoToObject() && itac.gotoObject(current.getObject()));
+ }
+ }
+
+ assertTrue("for " + current + " (" + member + "/" + i + ")", itac.hasNext());
+ TripleID next = itac.next();
+ String err = "invalid next " + next + " != " + current + " (" + member + "/" + i + ")";
+ switch (member) {
+ case 2: // object
+ assertEquals("object err " + err, current.getObject(), next.getObject());
+ case 1: // predicate
+ assertEquals("predicate err " + err, current.getPredicate(), next.getPredicate());
+ case 0: // subject only
+ assertEquals("subject err " + err, current.getSubject(), next.getSubject());
+ break;
+ default:
+ fail("bad member: " + member);
+ break;
+ }
+ if (member == 2) {
+ assertEquals("idx err " + err, idx, itac.getLastTriplePosition());
+ TripleID newCurrent = itac.next();
+ assertTrue("idx err " + err, idx < itac.getLastTriplePosition());
+
+ if (current.getSubject() == newCurrent.getSubject()) {
+ // no jump on X, we should have the sam
+ assertTrue("Can't jump to subject " + current + " (" + member + "/" + i + ")",
+ itac.gotoSubject(current.getSubject()));
+
+ if (current.getPredicate() == newCurrent.getPredicate()) {
+ // no jump on Y, we should have the same
+ assertTrue("Can't jump to subject " + current + " (" + member + "/" + i + ")",
+ itac.gotoPredicate(current.getPredicate()));
+
+ assertFalse("Can't jump to subject " + current + " (" + member + "/" + i + ")",
+ itac.gotoObject(current.getObject()));
+ } else {
+ assertFalse("Can't jump to subject " + current + " (" + member + "/" + i + ")",
+ itac.gotoPredicate(current.getPredicate()));
+ }
+
+ } else {
+ assertFalse("Can't jump to subject " + current + " (" + member + "/" + i + ")",
+ itac.gotoSubject(current.getSubject()));
+ }
+
+ } else {
+ assertTrue("idx err " + err, idx >= itac.getLastTriplePosition());
+ }
+ }
+ }
+ }
+ } finally {
+ PathUtils.deleteDirectory(root);
+ }
+ }
}