Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
c1a12f8
Cleaning up for new test cases
chrdebru Mar 18, 2025
fa32636
Loaded latest versions of test cases
chrdebru Mar 18, 2025
ae17d56
Create fetch-test-cases.bat
chrdebru Mar 18, 2025
93c1e0a
Tests for CC work!
chrdebru Mar 18, 2025
74f2c05
Create TestRMLCore.java
chrdebru Mar 18, 2025
ad6c9dc
Fixed test 26a
chrdebru Mar 18, 2025
43b0883
Support for baseIRI
chrdebru Mar 18, 2025
b9583f4
Update core.ttl
chrdebru Mar 19, 2025
91ee4ad
RML-CC tests are updated
chrdebru Sep 15, 2025
3691eaa
Updated all test cases
chrdebru Sep 26, 2025
266ebda
Cleaned up code for new test cases
chrdebru Sep 26, 2025
a90376c
Starting on RML-LV
chrdebru Sep 29, 2025
6bc9544
Preparation for new shapes files
chrdebru Oct 6, 2025
96d25ca
First series of tests pass.
chrdebru Oct 19, 2025
8b15307
13 of the 19 LV tests pass
chrdebru Oct 19, 2025
c9c2669
Prep for nested calls
chrdebru Oct 19, 2025
f4acc52
Temp
chrdebru Oct 20, 2025
a3a54d7
We pass 21 of 32 tests
chrdebru Oct 20, 2025
8d92d8e
25 of 32 tests passed
chrdebru Oct 20, 2025
829fba4
Merge branch 'kgc-2025-conformance' of https://github.com/kg-construc…
chrdebru Oct 23, 2025
0ef6ec6
Solution for detecting cycles in shapes
chrdebru Oct 23, 2025
f121daf
Fixed shapes to include rml:innerJoin
chrdebru Oct 24, 2025
30a0593
Prepared parsing of joins
chrdebru Oct 24, 2025
c5e59ff
Prepare parse
chrdebru Oct 26, 2025
14b05dc
31/32 of the LV tests pass
chrdebru Oct 29, 2025
e8696ae
Support for new test cases. 34/35 test cases of LV pass
chrdebru Oct 31, 2025
b0049b2
All LV tests pass.
chrdebru Oct 31, 2025
ab9fc5c
Delete TestLV.java
chrdebru Nov 7, 2025
5b68450
Updated test cases
chrdebru Nov 7, 2025
17bddb9
Merge branch 'refs/heads/main' into kgc-2025-conformance
jduchateau Jun 17, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
8 changes: 8 additions & 0 deletions .idea/inspectionProfiles/Project_Default.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

61 changes: 61 additions & 0 deletions fetch-test-cases.bat
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
@echo off

set "targetDir=target"

echo Creating target directory...
if not exist "%targetDir%" mkdir "%targetDir%"
if errorlevel 1 goto error

cd "%targetDir%"
if errorlevel 1 goto error

echo Cloning https://github.com/kg-construct/rml-core
git clone https://github.com/kg-construct/rml-core
if errorlevel 1 goto error

echo Cloning rhttps://github.com/kg-construct/rml-cc
git clone https://github.com/kg-construct/rml-cc
if errorlevel 1 goto error

echo Cloning https://github.com/kg-construct/rml-io
git clone https://github.com/kg-construct/rml-io
if errorlevel 1 goto error

echo Cloning rhttps://github.com/kg-construct/rml-fnml
git clone https://github.com/kg-construct/rml-fnml
if errorlevel 1 goto error

echo Cloning https://github.com/kg-construct/rml-lv
git clone https://github.com/kg-construct/rml-lv
if errorlevel 1 goto error

echo Cloning rhttps://github.com/kg-construct/rml-star
git clone https://github.com/kg-construct/rml-star
if errorlevel 1 goto error

echo All repositories cloned successfully into the target directory!

echo Copying test-case directories to ..\src\test\resources
xcopy .\rml-core\test-cases ..\src\test\resources\rml-core /E /I /Y
xcopy .\rml-cc\test-cases ..\src\test\resources\rml-cc /E /I /Y
xcopy .\target\rml-io\test-cases ..\src\test\resources\rml-io /E /I /Y
xcopy .\rml-lv\test-cases ..\src\test\resources\rml-lv /E /I /Y
xcopy .\rml-fnml\test-cases ..\src\test\resources\rml-fnml /E /I /Y
xcopy .\rml-star\test-cases ..\src\test\resources\rml-star /E /I /Y

rmdir /S /Q .\rml-core
rmdir /S /Q .\rml-cc
rmdir /S /Q .\rml-io
rmdir /S /Q .\rml-lv
rmdir /S /Q .\rml-fnml
rmdir /S /Q .\rml-star

goto end

:error
echo Error occurred.
echo Check the repository URLs and your internet connection.
echo or verify that you have permissions to create and write to the target directory.

:end
pause
72 changes: 72 additions & 0 deletions fetch-test-cases.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
#!/usr/bin/env bash
set -Eeuo pipefail

# --- config ---
target_dir="target"
resources_dir="src/test/resources"
shapes_resources_dir="src/main/resources/shapes"
repos=(
"rml-core"
"rml-cc"
"rml-io"
"rml-fnml"
"rml-lv"
"rml-star"
)

trap 'echo; echo "Error occurred."; echo "• Check the repository URLs and your internet connection."; echo "• Verify you have permissions to create/write to \"$target_dir\"."; exit 1' ERR

# Check prerequisites
command -v git >/dev/null 2>&1 || { echo "git is required but not found in PATH."; exit 1; }

echo "Creating $target_dir directory..."
mkdir -p "$target_dir"

echo "Entering $target_dir..."
cd "$target_dir"

# Clone all repositories
for repo in "${repos[@]}"; do
echo "Cloning https://github.com/kg-construct/$repo ..."
git clone "https://github.com/kg-construct/$repo"
done

echo "All repositories cloned successfully into $target_dir"

# Copy test-cases into ../src/test/resources/<repo>
echo "Copying test-case directories to ../$resources_dir ..."
for repo in "${repos[@]}"; do
src="$repo/test-cases"
dest="../$resources_dir/$repo"
if [[ -d "$src" ]]; then
mkdir -p "$dest"
# -a to preserve attrs; -r for recursive; --no-target-directory not needed here
cp -a "$src/." "$dest/"
echo "• Copied $src -> $dest"
else
echo "• Skipped $repo (no test-cases directory found)"
fi
done

# Copy shapes into ../src/main/resources/<repo>
echo "Copying shapes directories to ../$shapes_resources_dir ..."
for repo in "${repos[@]}"; do
src="$repo/shapes"
dest="../$shapes_resources_dir/$repo"
if [[ -d "$src" ]]; then
mkdir -p "$dest"
# -a to preserve attrs; -r for recursive; --no-target-directory not needed here
cp -a "$src/." "$dest/"
echo "• Copied $src -> $dest"
else
echo "• Skipped $repo (no shapes directory found)"
fi
done

# Remove cloned repositories
echo "Cleaning up cloned repositories..."
for repo in "${repos[@]}"; do
rm -rf "./$repo"
done

echo "Done."
8 changes: 7 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.github.kg-construct</groupId>
<groupId>io.github.kg-construct</groupId>
<artifactId>BURP</artifactId>
<version>0.1.2</version>
<name>Basic and Unassuming RML Processor</name>
Expand Down Expand Up @@ -220,6 +220,12 @@
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-params</artifactId>
<version>5.10.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>junit-jupiter</artifactId>
<version>1.19.5</version>
Expand Down
4 changes: 3 additions & 1 deletion src/main/java/burp/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -68,11 +68,13 @@ public static int doMain(String[] args) {
}
}

private static Dataset generate(List<TriplesMap> triplesmaps, String baseIRI) {
private static Dataset generate(List<TriplesMap> triplesmaps, String givenBaseIRI) {
Dataset ds = DatasetFactory.create();

// Execute the triples maps
for (TriplesMap tm : triplesmaps) {
String baseIRI = tm.baseIRI == null ? givenBaseIRI : tm.baseIRI;

// Let sm be the subject map of the triples map
SubjectMap sm = tm.subjectMap;

Expand Down
45 changes: 25 additions & 20 deletions src/main/java/burp/ls/CSVSource.java
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
package burp.ls;

import java.io.FileReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.io.StringWriter;
import java.util.*;
import java.util.stream.Collectors;

import com.opencsv.CSVParserBuilder;
import com.opencsv.CSVReader;
import com.opencsv.CSVReaderBuilder;

import burp.model.Iteration;
import com.opencsv.CSVWriter;

class CSVSource extends FileBasedLogicalSource {

Expand All @@ -23,7 +21,7 @@ class CSVSource extends FileBasedLogicalSource {
public Iterator<Iteration> iterator() {
try {
if (iterations == null) {
iterations = new ArrayList<Iteration>();
iterations = new ArrayList<>();

FileReader fr = new FileReader(getDecompressedFile(), encoding);

Expand Down Expand Up @@ -64,7 +62,8 @@ public Iterator<Iteration> iterator() {

class CSVIteration extends Iteration {

private Map<String, String> map = new HashMap<String, String>();
// Use a LinkedHashMap to preserve a correspondence between keys and values
private final Map<String, String> map = new LinkedHashMap<>();

protected CSVIteration(String[] header, String[] rec, Set<Object> nulls) {
super(nulls);
Expand All @@ -76,28 +75,34 @@ protected CSVIteration(String[] header, String[] rec, Set<Object> nulls) {

@Override
public List<Object> getValuesFor(String reference) {
List<Object> l = new ArrayList<Object>();
List<Object> l = new ArrayList<>();
if(!map.containsKey(reference))
throw new RuntimeException("Attribute " + reference + " does not exist.");

String o = map.get(reference);
if(!nulls.contains(o))
if(nulls == null || !nulls.contains(o))
l.add(o);

return l;
}

@Override
public List<String> getStringsFor(String reference) {
List<String> l = new ArrayList<String>();
if(!map.containsKey(reference))
throw new RuntimeException("Attribute " + reference + " does not exist.");

String o = map.get(reference);
if(!nulls.contains(o))
l.add(o);

return l;
return getValuesFor(reference).stream().map(Object::toString).collect(Collectors.toList());
}


@Override
public String asString() {
StringWriter stringWriter = new StringWriter();
try (CSVWriter writer = new CSVWriter(stringWriter)) {
String[] header = map.keySet().toArray(new String[0]);
writer.writeNext(header);
String[] rec = map.values().toArray(new String[0]);
writer.writeNext(rec);
} catch(Exception e) {
throw new RuntimeException("Error representing CSV iteration as CSV.");
}
return stringWriter.toString();
}

}
1 change: 0 additions & 1 deletion src/main/java/burp/ls/FileBasedLogicalSource.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ abstract class FileBasedLogicalSource extends LogicalSource {

protected List<Iteration> iterations = null;
public String file;
public String iterator;
public Charset encoding = StandardCharsets.UTF_8;
public Resource compression = RML.none;

Expand Down
47 changes: 20 additions & 27 deletions src/main/java/burp/ls/JSONSource.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,20 @@

class JSONSource extends FileBasedLogicalSource {

private static Configuration c = Configuration.builder().mappingProvider(new JacksonMappingProvider())
.jsonProvider(new JacksonJsonProvider()).build().addOptions(Option.ALWAYS_RETURN_LIST);
public static final Configuration configuration = Configuration.builder()
.mappingProvider(new JacksonMappingProvider())
.jsonProvider(new JacksonJsonProvider())
.build()
.addOptions(Option.ALWAYS_RETURN_LIST);

@Override
public Iterator<Iteration> iterator() {
try {
if (iterations == null) {
iterations = new ArrayList<Iteration>();
iterations = new ArrayList<>();
String contents = Files.readString(Paths.get(getDecompressedFile()), encoding);

List<Map<String, Object>> nodes = JsonPath.using(c).parse(contents).read(iterator);
List<Map<String, Object>> nodes = JsonPath.using(configuration).parse(contents).read(iterator);
for (Map<String, Object> n : nodes) {
iterations.add(new JSONIteration(JSONObject.toJSONString(n), nulls));
}
Expand All @@ -47,34 +50,22 @@ public Iterator<Iteration> iterator() {
class JSONIteration extends Iteration {

private DocumentContext doc = null;

private static Configuration c = Configuration
.builder()
.mappingProvider(new JacksonMappingProvider())
.jsonProvider(new JacksonJsonProvider())
.build()
.addOptions(Option.ALWAYS_RETURN_LIST)
;


protected JSONIteration(String json, Set<Object> nulls) {
super(nulls);

doc = JsonPath.using(c).parse(json);
doc = JsonPath.using(JSONSource.configuration).parse(json);
}

@Override
public List<Object> getValuesFor(String reference) {
// We need to explicitly convert the objects
// to strings because RML has not worked out
// "6.6.1 Automatically deriving datatypes" yet
List<Object> l2 = new ArrayList<Object>();
List<Object> l2 = new ArrayList<>();
try {
List<Object> l = doc.read(reference);
for(Object o : l) {
if (o instanceof List<?>)
throw new RuntimeException("Data error: reference retrieved an array");
if (o != null && !nulls.contains(o))
l2.add(o.toString());
if (o != null && (nulls == null || !nulls.contains(o)))
l2.add(o);
}
} catch (PathNotFoundException e) {
// No data, silently ignore
Expand All @@ -85,16 +76,13 @@ public List<Object> getValuesFor(String reference) {

@Override
public List<String> getStringsFor(String reference) {
// We need to explicitly convert the objects
// to strings (when they are null) because
// this JSONPath library is... difficult.
List<String> l2 = new ArrayList<String>();
List<String> l2 = new ArrayList<>();
try {
List<Object> l = doc.read(reference);
for(Object o : l) {
if (o instanceof List<?>)
throw new RuntimeException("Data error: reference retrieved an array");
if (o != null && !nulls.contains(o))
if (o != null && (nulls == null || !nulls.contains(o)))
l2.add(o.toString());
}
} catch (PathNotFoundException e) {
Expand All @@ -103,5 +91,10 @@ public List<String> getStringsFor(String reference) {
}
return l2;
}


@Override
public String asString() {
return doc.jsonString();
}

}
Loading
Loading