Skip to content

Commit

Permalink
Exchange old hydra models with new one
Browse files Browse the repository at this point in the history
  • Loading branch information
yngwi committed May 13, 2021
1 parent 3f72108 commit f6f5529
Show file tree
Hide file tree
Showing 22 changed files with 324 additions and 654 deletions.
Original file line number Diff line number Diff line change
@@ -1,60 +1,57 @@
package eu.nampi.backend.model.hydra;

import org.apache.jena.arq.querybuilder.ConstructBuilder;
import java.util.Optional;
import org.apache.jena.arq.querybuilder.ExprFactory;
import org.apache.jena.arq.querybuilder.WhereBuilder;
import org.apache.jena.graph.Node;
import org.apache.jena.graph.NodeFactory;
import org.apache.jena.query.QuerySolution;
import org.apache.jena.rdf.model.Model;
import org.apache.jena.rdf.model.ModelFactory;
import org.apache.jena.rdf.model.RDFNode;
import org.apache.jena.rdf.model.Resource;
import org.apache.jena.rdf.model.ResourceFactory;
import org.apache.jena.vocabulary.RDF;
import org.apache.jena.vocabulary.RDFS;
import org.apache.jena.vocabulary.XSD;
import eu.nampi.backend.service.JenaService;
import eu.nampi.backend.vocabulary.Api;
import eu.nampi.backend.vocabulary.Core;
import eu.nampi.backend.vocabulary.Hydra;
import eu.nampi.backend.vocabulary.SchemaOrg;

public abstract class AbstractHydraBuilder extends ConstructBuilder
implements InterfaceHydraBuilder {

public abstract class AbstractHydraBuilder implements InterfaceHydraBuilder {
protected JenaService jenaService;
protected Resource mainType;
protected String baseUri;
public ExprFactory ef;
public Model model = ModelFactory.createDefaultModel();
public Resource root;
public WhereBuilder coreData = new WhereBuilder();
public static final Node VAR_MAIN = NodeFactory.createVariable("main");
public static final Node VAR_MAIN_LABEL = NodeFactory.createVariable("label");
public static final Node VAR_MAIN_COMMENT = NodeFactory.createVariable("comment");
public static final Node VAR_COMMENT = NodeFactory.createVariable("comment");
public static final Node VAR_LABEL = NodeFactory.createVariable("label");

public final ExprFactory ef;
public final Node baseNode;
public final Resource mainType;

public AbstractHydraBuilder(Node baseNode, Resource mainType) {
super();
// @formatter:off
this
.addPrefix("api", Api.getURI())
.addPrefix("core", Core.getURI())
.addPrefix("hydra", Hydra.getURI())
.addPrefix("rdf", RDF.getURI())
.addPrefix("rdfs", RDFS.getURI())
.addPrefix("schema", SchemaOrg.getURI())
.addPrefix("xsd", XSD.getURI())
.addConstruct(VAR_MAIN, RDF.type, mainType)
.addConstruct(VAR_MAIN, RDFS.label, VAR_MAIN_LABEL)
.addConstruct(VAR_MAIN, RDFS.comment, VAR_MAIN_COMMENT);
// @formatter:on
this.baseNode = baseNode;
this.ef = this.getExprFactory();
protected AbstractHydraBuilder(JenaService jenaService, String baseUri, Resource mainType) {
this.jenaService = jenaService;
this.baseUri = baseUri;
this.mainType = mainType;
this.root = ResourceFactory.createResource(baseUri);
coreData.addWhere(VAR_MAIN, RDF.type, mainType);
model
.setNsPrefix("api", Api.getURI())
.setNsPrefix("core", Core.getURI())
.setNsPrefix("hydra", Hydra.getURI())
.setNsPrefix("rdf", RDF.getURI())
.setNsPrefix("rdfs", RDFS.getURI())
.setNsPrefix("schema", SchemaOrg.getURI())
.setNsPrefix("xsd", XSD.getURI());
this.ef = coreData.getExprFactory();
}

public WhereBuilder mainWhere() {
return new WhereBuilder().addWhere(VAR_MAIN, RDF.type, mainType);
}

public WhereBuilder labelWhere() {
return new WhereBuilder().addWhere(VAR_MAIN, RDFS.label, VAR_MAIN_LABEL);
}

public WhereBuilder commentWhere() {
return new WhereBuilder().addOptional(VAR_MAIN, RDFS.comment, VAR_MAIN_COMMENT);
protected Optional<RDFNode> get(QuerySolution row, Node variable) {
return Optional.ofNullable(row.get(variable.getName()));
}

}
204 changes: 87 additions & 117 deletions src/main/java/eu/nampi/backend/model/hydra/HydraCollectionBuilder.java
Original file line number Diff line number Diff line change
@@ -1,143 +1,113 @@
package eu.nampi.backend.model.hydra;

import java.util.Optional;
import java.util.function.BiFunction;
import org.apache.jena.arq.querybuilder.SelectBuilder;
import org.apache.jena.arq.querybuilder.WhereBuilder;
import org.apache.jena.graph.Node;
import org.apache.jena.graph.NodeFactory;
import org.apache.jena.query.QuerySolution;
import org.apache.jena.rdf.model.Model;
import org.apache.jena.rdf.model.RDFNode;
import org.apache.jena.rdf.model.Resource;
import org.apache.jena.rdf.model.ResourceFactory;
import org.apache.jena.sparql.expr.Expr;
import org.apache.jena.sparql.lang.sparql_11.ParseException;
import org.apache.jena.vocabulary.RDF;
import org.apache.jena.vocabulary.RDFS;
import eu.nampi.backend.model.QueryParameters;
import eu.nampi.backend.service.JenaService;
import eu.nampi.backend.vocabulary.Api;
import eu.nampi.backend.vocabulary.Hydra;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class HydraCollectionBuilder extends AbstractHydraBuilder {
private Resource orderByVar;
protected QueryParameters params;
public ParameterMapper mapper;
public WhereBuilder extendedData = new WhereBuilder();

public static final Node VAR_FIRST = NodeFactory.createVariable("first");
public static final Node VAR_LAST = NodeFactory.createVariable("last");
public static final Node VAR_MANAGES = NodeFactory.createVariable("manages");
public static final Node VAR_NEXT = NodeFactory.createVariable("next");
public static final Node VAR_PREVIOUS = NodeFactory.createVariable("previous");
public static final Node VAR_SEARCH = NodeFactory.createVariable("search");
public static final Node VAR_TOTAL_ITEMS = NodeFactory.createVariable("totalItems");

public final ParameterMapper mapper;
public final WhereBuilder countWhere;
public final WhereBuilder dataWhere;

private final Resource orderByVar;
private final QueryParameters params;
private final SelectBuilder bindSelect = new SelectBuilder();
private final WhereBuilder bindWhere = new WhereBuilder();

public HydraCollectionBuilder(String baseUri, Resource mainType, Resource orderByVar,
QueryParameters params) {
this(baseUri, mainType, orderByVar, params, true, false);
}

public HydraCollectionBuilder(String baseUri, Resource mainType, Resource orderByVar,
QueryParameters params, boolean includeTextFilter, boolean optionalLabel) {
super(NodeFactory.createURI(baseUri), mainType);
this.countWhere = mainWhere();
this.dataWhere = mainWhere();
this.mapper = new ParameterMapper(baseUri, VAR_SEARCH, this, bindSelect);
public HydraCollectionBuilder(JenaService jenaService, String baseUri, Resource mainType,
Resource orderByVar, QueryParameters params, boolean includeTextFilter) {
super(jenaService, baseUri, mainType);
this.mapper = new ParameterMapper(baseUri, root, model);
this.orderByVar = orderByVar;
this.params = params;

// Add text filter
if (optionalLabel) {
dataWhere.addOptional(labelWhere());
} else {
dataWhere.addWhere(labelWhere());
// Set up manages node
Resource manages = ResourceFactory.createResource();
this.model
.add(root, Hydra.manages, manages)
.add(manages, Hydra.object, mainType);

boolean orderByLabel = this.params.getOrderByClauses().containsKey("label");
if (orderByLabel) {
coreData.addWhere(VAR_MAIN, RDFS.label, VAR_LABEL);
}
if (includeTextFilter && params.getText().isPresent()) {
Expr regex = ef.regex(VAR_MAIN_LABEL, params.getText().get(), "i");
dataWhere.addFilter(regex);
if (optionalLabel) {
countWhere.addOptional(labelWhere()).addFilter(regex);
} else {
countWhere.addWhere(labelWhere()).addFilter(regex);

// Add default data
extendedData
.addOptional(VAR_MAIN, RDFS.label, VAR_LABEL)
.addOptional(VAR_MAIN, RDFS.comment, VAR_COMMENT);

// Add default text filter
params.getText().filter(text -> includeTextFilter).ifPresent(text -> {
if (!orderByLabel) {
coreData.addWhere(VAR_MAIN, RDFS.label, VAR_LABEL);
}
}
Expr matchText = ef.regex(VAR_LABEL, text, "i");
coreData.addFilter(matchText);
});

// Add type filter
if (params.getType().isPresent()) {
Resource typeResource = ResourceFactory.createResource(params.getType().get());
dataWhere.addWhere(VAR_MAIN, RDF.type, typeResource);
countWhere.addWhere(VAR_MAIN, RDF.type, typeResource);
}
params.getType().map(ResourceFactory::createResource).ifPresent(res -> {
coreData.addWhere(VAR_MAIN, RDF.type, res);
});
}

public HydraCollectionBuilder(JenaService jenaService, String baseUri, Resource mainType,
Resource orderByVar, QueryParameters params) {
this(jenaService, baseUri, mainType, orderByVar, params, true);
}

@Override
public String buildHydra() {
// @formatter:off
try {

// Construct the result
this
// Add general hydra data
.addConstruct(baseNode, RDF.type, Hydra.Collection)
.addConstruct(baseNode, Hydra.totalItems, VAR_TOTAL_ITEMS)
.addConstruct(baseNode, Hydra.manages, VAR_MANAGES)
.addConstruct(VAR_MANAGES, Hydra.object, mainType)
.addConstruct(baseNode, Hydra.search, VAR_SEARCH )
.addConstruct(VAR_SEARCH, RDF.type, Hydra.IriTemplate)
.addConstruct(VAR_SEARCH, Hydra.variableRepresentation, Hydra.BasicRepresentation)
.addConstruct(baseNode, Hydra.member, VAR_MAIN);

// Add all variable bindings
bindWhere
.addBind(ef.bnode(), VAR_SEARCH)
.addBind(ef.bnode(), VAR_MANAGES);

// Set up selects
SelectBuilder dataSelect = new SelectBuilder()
.addVar("*")
.addWhere(dataWhere);
params.getOrderByClauses().appendAllTo(dataSelect);
dataSelect.addOrderBy(VAR_MAIN)
.setOffset(params.getOffset())
.setLimit(params.getLimit());
SelectBuilder countSelect = new SelectBuilder()
.addVar("count(*)", VAR_TOTAL_ITEMS)
.addWhere(countWhere);
SelectBuilder contentSelect = new SelectBuilder()
.addVar("*")
.addUnion(dataSelect)
.addUnion(countSelect);
bindSelect
.addVar("*")
.addWhere(bindWhere);

Node view = mapper
.add("limit", Hydra.limit, params.getLimit())
.add("offset", Hydra.offset, params.getOffset())
.add("orderBy", orderByVar, params.getOrderByClauses().toQueryString())
.add("pageIndex", Hydra.pageIndex, null)
.add("text", Api.textVar, params.getText().orElse(""))
.add("type", RDF.type, params.getType().orElse(""))
.addTemplate(baseNode);

this
.addConstruct(view, Hydra.first, VAR_FIRST)
.addConstruct(view, Hydra.previous, VAR_PREVIOUS)
.addConstruct(view, Hydra.next, VAR_NEXT)
.addConstruct(view, Hydra.last, VAR_LAST)
.addWhere(new WhereBuilder()
.addUnion(contentSelect)
.addUnion(bindSelect))
.addBind("if(contains('" + view + "', 'offset=0'), 1+'', replace('" + view + "', 'offset=\\\\d*', 'offset=0'))", VAR_FIRST)
.addBind("if(" + params.getOffset() + " >= floor(" + VAR_TOTAL_ITEMS + " / " + params.getLimit() + ") * " + params.getLimit() + " , 1+'', replace('" + view + "', 'offset=\\\\d*', concat('offset=', str(xsd:integer(floor(" + VAR_TOTAL_ITEMS + " / " + params.getLimit() + ") * " + params.getLimit() + ")))))", VAR_LAST)
.addBind("if(" + (params.getOffset() - params.getLimit()) + " >= 0, replace('" + view + "', 'offset=\\\\d*', concat('offset=', str(" + (params.getOffset() - params.getLimit()) + "))), 1+'')", VAR_PREVIOUS)
.addBind("if(" + (params.getOffset() + params.getLimit()) + " < " + VAR_TOTAL_ITEMS + ", replace('" + view + "', 'offset=\\\\d*', concat('offset=', str(" + (params.getOffset() + params.getLimit()) + "))), 1+'')", VAR_NEXT);
} catch (ParseException e) {
log.error(e.getMessage());
}
// @formatter:on
return buildString();
public void build(BiFunction<Model, QuerySolution, RDFNode> rowToNode) {
// Count all possible matches
int totalItems = jenaService.count(coreData, VAR_MAIN);

// Finalize the core select
SelectBuilder coreSelect = new SelectBuilder()
.setDistinct(true)
.addVar(VAR_MAIN)
.addWhere(coreData);

this.params
.getOrderByClauses()
.appendAllTo(coreSelect);
coreSelect
.addOrderBy(VAR_MAIN)
.setOffset(params.getOffset())
.setLimit(params.getLimit());

SelectBuilder finalSelect = new SelectBuilder()
.addSubQuery(coreSelect)
.addWhere(extendedData);

// Setup the root hydra collection
this.model
.add(this.root, RDF.type, Hydra.Collection)
.addLiteral(root, Hydra.totalItems, ResourceFactory.createTypedLiteral(totalItems));

// Query the data using the jena service and add the content provided by the row mapper function
// to the model
jenaService.select(finalSelect, row -> this.model
.add(root, Hydra.member, rowToNode.apply(this.model, row)));

// Set up the search and view nodes with the main query parameters
this.mapper
.add("limit", Hydra.limit, params.getLimit())
.add("offset", Hydra.offset, params.getOffset())
.add("orderBy", orderByVar, params.getOrderByClauses().toQueryString())
.add("pageIndex", Hydra.pageIndex, Optional.empty())
.add("text", Api.textVar, params.getText())
.add("type", RDF.type, params.getType())
.insertTemplate()
.insertView(totalItems);
}
}
32 changes: 22 additions & 10 deletions src/main/java/eu/nampi/backend/model/hydra/HydraSingleBuilder.java
Original file line number Diff line number Diff line change
@@ -1,22 +1,34 @@
package eu.nampi.backend.model.hydra;

import org.apache.jena.graph.NodeFactory;
import java.util.function.BiFunction;
import org.apache.jena.arq.querybuilder.SelectBuilder;
import org.apache.jena.query.QuerySolution;
import org.apache.jena.rdf.model.Model;
import org.apache.jena.rdf.model.RDFNode;
import org.apache.jena.rdf.model.Resource;
import org.apache.jena.vocabulary.RDFS;
import eu.nampi.backend.service.JenaService;

public class HydraSingleBuilder extends AbstractHydraBuilder {

public final String iri;
public HydraSingleBuilder(JenaService jenaService, String baseUri, Resource mainType,
boolean optionalLabel) {
super(jenaService, baseUri, mainType);
// Add default data
coreData
.addFilter(ef.sameTerm(VAR_MAIN, root))
.addOptional(VAR_MAIN, RDFS.label, VAR_LABEL)
.addOptional(VAR_MAIN, RDFS.comment, VAR_COMMENT);
}

public HydraSingleBuilder(String iri, Resource type) {
super(NodeFactory.createURI(iri), type);
this.iri = iri;
addWhere(mainWhere());
addFilter(ef.sameTerm(VAR_MAIN, baseNode));
addWhere(labelWhere());
public HydraSingleBuilder(JenaService jenaService, String baseUri, Resource mainType) {
this(jenaService, baseUri, mainType, false);
}

public String buildHydra() {
return buildString();
@Override
public void build(BiFunction<Model, QuerySolution, RDFNode> rowToNode) {
SelectBuilder core = new SelectBuilder().addVar("*").addWhere(coreData);
jenaService.select(core, row -> rowToNode.apply(this.model, row));
}

}
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
package eu.nampi.backend.model.hydra;

import java.util.function.BiFunction;
import org.apache.jena.query.QuerySolution;
import org.apache.jena.rdf.model.Model;
import org.apache.jena.rdf.model.RDFNode;

public interface InterfaceHydraBuilder {

public String buildHydra();
public void build(BiFunction<Model, QuerySolution, RDFNode> rowToNode);

}
Loading

0 comments on commit f6f5529

Please sign in to comment.