Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 19 additions & 6 deletions elda-lda/src/main/java/com/epimorphics/lda/core/View.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import org.apache.jena.query.Query;
import org.apache.jena.rdf.model.*;
import org.apache.jena.shared.PrefixMapping;
import org.apache.jena.sparql.util.Closure;
import org.apache.jena.vocabulary.RDF;
import org.apache.jena.vocabulary.RDFS;
import org.slf4j.Logger;
Expand Down Expand Up @@ -293,19 +294,19 @@ void endGraph(StringBuilder sb) {
}
}

public String fetchDescriptions(Controls c, State s) {
public String fetchDescriptions(Controls c, State s, boolean encloseDescribe) {
Times t = c.times;
switch (type) {
case T_DESCRIBE: {
String detailsQuery = fetchByGivenPropertyChains(s, chains);
String describeQuery = describeBySelectedItems(s, s.roots);
String describeQuery = describeBySelectedItems(s, s.roots, encloseDescribe);
t.addToViewQuerySize(detailsQuery);
t.addToViewQuerySize(describeQuery);
return describeQuery;
}

case T_ALL: {
String detailsQuery = describeBySelectedItems(s, s.roots);
String detailsQuery = describeBySelectedItems(s, s.roots, encloseDescribe);
String chainsQuery = fetchByGivenPropertyChains(s, chains);
addAllObjectLabels(s);
t.addToViewQuerySize(detailsQuery);
Expand Down Expand Up @@ -360,10 +361,22 @@ public String fetchByGivenPropertyChains(State st, List<PropertyChain> chains) {
return queryString;
}

private String describeBySelectedItems(State s, List<Resource> allRoots) {
private String describeBySelectedItems(State s, List<Resource> allRoots, boolean encloseDescribe) {
String query = createDescribeQueryForItems(s, allRoots);
Query describeQuery = QueryUtil.create(query);
for (Source x : s.sources) s.m.add(x.executeDescribe(describeQuery));
for (Source x : s.sources) {
Model m = s.m;
Model description = x.executeDescribe(describeQuery);
if (encloseDescribe) {
for (Resource root : allRoots) {
Resource res = root.inModel(description);
Model closure = Closure.closure(res, false);
m.add(closure);
}
} else {
m.add(description);
}
}
return query.toString();
}

Expand Down Expand Up @@ -449,7 +462,7 @@ public static String buildFetchLabelsQuery(State s, List<String> properties) {
List<Source> sources = spec.getDescribeSources();
return this.isTemplateView()
? this.viewByTemplate(roots, m, spec, sources, graphName)
: this.fetchDescriptions(c, new View.State(roots, m, sources, vars, graphName));
: this.fetchDescriptions(c, new View.State(roots, m, sources, vars, graphName), spec.getEncloseDescribe());
}

public String viewByTemplate(List<Resource> roots, Model m, APISpec spec, List<Source> sources, String graphName) {
Expand Down
7 changes: 7 additions & 0 deletions elda-lda/src/main/java/com/epimorphics/lda/specs/APISpec.java
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,8 @@ public class APISpec extends SpecCommon {

protected final boolean purging;

protected final boolean encloseDescribe;

protected final Boolean enableForwardHeaders;

protected final MetaConfig metaConfig;
Expand Down Expand Up @@ -150,6 +152,7 @@ public APISpec(MetaConfig mc, String prefixPath, String appName, FileManager fm,
this.enableCounting = RDFUtils.getOptionalBooleanValue(root, ELDA_API.enableCounting, Boolean.FALSE);
this.propertyExpiryTimes = PropertyExpiryTimes.assemble(root.getModel());
this.enableForwardHeaders = RDFUtils.getBooleanValue(root, ELDA_API.enableForwardHeaders, true);
this.encloseDescribe = RDFUtils.getBooleanValue(root, ELDA_API.encloseDescribe, false);
//
this.metaConfig = new MetaConfig(root, mc);
//
Expand Down Expand Up @@ -396,4 +399,8 @@ public String getGraphTemplate() {
public Boolean getEnableForwardHeaders() {
return enableForwardHeaders;
}

public Boolean getEncloseDescribe() {
return encloseDescribe;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,9 @@ public class ELDA_API extends API {

/** <p></p> */
public static final Property enableForwardHeaders = M_MODEL.createProperty( "http://www.epimorphics.com/vocabularies/lda#enableForwardHeaders" );


public static final Property encloseDescribe = M_MODEL.createProperty( "http://www.epimorphics.com/vocabularies/lda#encloseDescribe" );

/** <p></p> */
public static final Property enhanceViewWith = M_MODEL.createProperty( "http://www.epimorphics.com/vocabularies/lda#enhanceViewWith" );

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package com.epimorphics.lda.core;

import com.epimorphics.lda.specs.APISpec;
import org.apache.jena.rdf.model.Model;
import org.apache.jena.rdf.model.Resource;
import org.apache.jena.util.FileManager;
import org.junit.Test;

import java.io.IOException;
import java.io.InputStream;

import static org.apache.jena.rdf.model.ModelFactory.createDefaultModel;
import static org.junit.Assert.*;
import static org.mockito.Mockito.mock;

public class EncloseDescribeApiTest {

private Model readFromResource(String path) {
Model model = createDefaultModel();
try {
try (InputStream input = this.getClass().getResource(path).openStream()) {
model.read(input, "", "TTL");
}
} catch (IOException ioe) {
fail(ioe.getMessage());
}

return model;
}

@Test
public void apiSpec_withEncloseDescribe() {
Model model = readFromResource("/view/api.ttl");
Resource api = model.getResource("http://www.epimorphics.com/tools/example#encloseDescribe");
APISpec spec = new APISpec(mock(FileManager.class), api, mock(ModelLoader.class));
assertTrue(spec.getEncloseDescribe());
}

@Test
public void apiSpec_withoutEncloseDescribe() {
Model model = readFromResource("/view/api.ttl");
Resource api = model.getResource("http://www.epimorphics.com/tools/example#default");
APISpec spec = new APISpec(mock(FileManager.class), api, mock(ModelLoader.class));
assertFalse(spec.getEncloseDescribe());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package com.epimorphics.lda.core;

import com.epimorphics.lda.sources.Source;
import com.epimorphics.lda.support.Controls;
import com.epimorphics.lda.support.Times;
import org.apache.jena.rdf.model.Model;
import org.apache.jena.rdf.model.Resource;
import org.junit.Test;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;

import static org.apache.jena.rdf.model.ModelFactory.createDefaultModel;
import static org.apache.jena.rdf.model.ResourceFactory.createResource;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

public class EncloseDescribeTest {
private final Controls c = new Controls(false, mock(Times.class));
private final Source s = mock(Source.class);

private Model readFromResource(String path) {
Model model = createDefaultModel();
try {
try (InputStream input = this.getClass().getResource(path).openStream()) {
model.read(input, "", "TTL");
}
} catch (IOException ioe) {
fail(ioe.getMessage());
}

return model;
}

private void assertIsomorphic(Model expected, Model actual) {
if (!expected.isIsomorphicWith(actual)) {
assertEquals(expected, actual);
}
}

@Test
public void describeView_fetchDescriptions_withReverseClosure_returnsForwardClosure() {
Model describe = readFromResource("/view/bw_reverse_closure.ttl");
when(s.executeDescribe(any())).thenReturn(describe);

View v = new View("test", View.Type.T_DESCRIBE);

List<Resource> roots = List.of(createResource("http://environment.data.gov.uk/id/bathing-water/"));
Model result = createDefaultModel();
List<Source> sources = List.of(s);
VarSupply vs = mock(VarSupply.class);

View.State state = new View.State(roots, result, sources, vs, "#graph");


v.fetchDescriptions(c, state, true);

Model expected = readFromResource("/view/bw_closure.ttl");
assertIsomorphic(expected, result);
}

@Test
public void allView_fetchDescriptions_withReverseClosure_returnsForwardClosure() {
Model describe = readFromResource("/view/bw_reverse_closure.ttl");
when(s.executeDescribe(any())).thenReturn(describe);
when(s.executeConstruct(any())).thenReturn(createDefaultModel());

View v = new View("test", View.Type.T_ALL);

List<Resource> roots = List.of(createResource("http://environment.data.gov.uk/id/bathing-water/"));
Model result = createDefaultModel();
List<Source> sources = List.of(s);
VarSupply vs = mock(VarSupply.class);

View.State state = new View.State(roots, result, sources, vs, "#graph");


v.fetchDescriptions(c, state, true);

Model expected = readFromResource("/view/bw_closure.ttl");
assertIsomorphic(expected, result);
}
}
51 changes: 51 additions & 0 deletions elda-lda/src/test/resources/view/api.ttl
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
## Common prefixes.
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix owl: <http://www.w3.org/2002/07/owl#> .
@prefix foaf: <http://xmlns.com/foaf/0.1/> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix api: <http://purl.org/linked-data/api/vocab#> .
@prefix skos: <http://www.w3.org/2004/02/skos/core#> .
@prefix geo: <http://www.w3.org/2003/01/geo/wgs84_pos#> .
@prefix spatialrelations: <http://data.ordnancesurvey.co.uk/ontology/spatialrelations/> .
@prefix admingeo: <http://statistics.data.gov.uk/def/administrative-geography/> .
@prefix qb: <http://purl.org/linked-data/cube#> .
@prefix time: <http://www.w3.org/2006/time#> .
@prefix interval: <http://reference.data.gov.uk/def/intervals/> .
@prefix dgu: <http://reference.data.gov.uk/def/reference/> .
@prefix bw: <http://environment.data.gov.uk/id/bathing-water/> .
@prefix bwsp: <http://location.data.gov.uk/so/ef/SamplingPoint/bwsp.eaew/> .
@prefix bwq: <http://environment.data.gov.uk/def/bathing-water-quality/> .
@prefix bwq-iss: <http://environment.data.gov.uk/data/bathing-water-quality/in-season/slice/> .
@prefix bw-def: <http://environment.data.gov.uk/def/bathing-water/> .
@prefix ef-def: <http://location.data.gov.uk/def/ef/SamplingPoint/> .
@prefix dct: <http://purl.org/dc/terms/> .
@prefix t: <http://environment.data.gov.uk/api#> .
@prefix dgu: <http://reference.data.gov.uk/def/reference/> .
@prefix void: <http://rdfs.org/ns/void#> .
@prefix elda: <http://www.epimorphics.com/vocabularies/lda#> .
@prefix : <http://www.epimorphics.com/tools/example#> .

:encloseDescribe
a api:API ;
api:sparqlEndpoint <local:CURRENT-TEST>;
api:endpoint t:bathingWaters ;
elda:encloseDescribe true ;
.

:default
a api:API ;
api:sparqlEndpoint <local:CURRENT-TEST>;
api:endpoint t:bathingWaters ;
.

t:bathingWaters
a api:ListEndpoint ;
api:uriTemplate "/doc/bathing-water" ;
api:exampleRequestPath "/doc/bathing-water" ;
api:viewer api:describeViewer;
api:defaultViewer api:describeViewer;
api:selector [
api:filter "type=BathingWater" ;
# api:sort "samplingPoint.samplePointNotation";
] .
28 changes: 28 additions & 0 deletions elda-lda/src/test/resources/view/bw_closure.ttl
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
@prefix void: <http://rdfs.org/ns/void#> .
@prefix onsadmingeo: <http://statistics.data.gov.uk/def/administrative-geography/> .
@prefix def-geom: <http://location.data.gov.uk/def/common/Geometry/> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix spatialrelations: <http://data.ordnancesurvey.co.uk/ontology/spatialrelations/> .
@prefix def-ef: <http://location.data.gov.uk/def/ef/SamplingPoint/> .
@prefix dgu: <http://reference.data.gov.uk/def/reference/> .
@prefix osadmingeo: <http://data.ordnancesurvey.co.uk/ontology/admingeo/> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix bw: <http://environment.data.gov.uk/id/bathing-water/> .
@prefix dcterms: <http://purl.org/dc/terms/> .
@prefix geometry: <http://data.ordnancesurvey.co.uk/ontology/geometry/> .
@prefix api: <http://purl.org/linked-data/api/vocab#> .
@prefix foaf: <http://xmlns.com/foaf/0.1/> .
@prefix def-bw: <http://environment.data.gov.uk/def/bathing-water/> .

bw: a void:Dataset , dgu:URIset ;
rdfs:label "Bathing waters monitored by the Environment Agency for England and Wales."@en ;
dcterms:description "URI Set of Bathing Waters in England and Wales monitored by the Environment Agency for compliance with the EU Bathing Water Directive"@en ;
dcterms:license <http://reference.data.gov.uk/id/open-government-licence> ;
dcterms:modified "2025-11-25T09:05:57.727Z"^^xsd:dateTime , "2014-06-30T15:53:44.397Z"^^xsd:dateTime ;
dcterms:source <http://environment.data.gov.uk/sources/bwq/eaew/input/2025_ea_site_reference.csv> , <http://environment.data.gov.uk/sources/bwq/eaew/input/reference-EngWal_bw_site_140630v3-20140630-155343-40.csv> ;
void:dataDump <http://environment.data.gov.uk/sources/bwq/eaew/output/reference.ttl> ;
void:uriRegexPattern "http://environment.data.gov.uk/id/bathing-water/.*" ;
void:vocabulary <http://www.w3.org/2004/02/skos/core> , geometry: , osadmingeo: , def-bw: , spatialrelations: , dgu: , onsadmingeo: , def-ef: , <http://www.w3.org/ns/org> , <http://www.w3.org/2003/01/geo/wgs84_pos> , def-geom: ;
dgu:itemType def-bw:BathingWater ;
dgu:status <http://reference.data.gov.uk/def/status/draft> .
Loading
Loading