Skip to content

Commit

Permalink
[New] Fetch possible values module
Browse files Browse the repository at this point in the history
  • Loading branch information
blcham committed Sep 18, 2022
1 parent f34d922 commit ee84a52
Show file tree
Hide file tree
Showing 2 changed files with 182 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
package cz.cvut.spipes.modules;


import cz.cvut.sforms.SFormsVocabularyJena;
import cz.cvut.spipes.constants.KBSS_MODULE;
import cz.cvut.spipes.constants.SML;
import cz.cvut.spipes.engine.ExecutionContext;
import cz.cvut.spipes.engine.ExecutionContextFactory;
import cz.cvut.spipes.form.JenaFormUtils;
import org.apache.jena.rdf.model.Model;
import org.apache.jena.rdf.model.ModelFactory;
import org.apache.jena.rdf.model.Resource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashMap;
import java.util.Map;

/**
* Inputs are forms using Q&A model. Possible values of questions are added to questions that does not have
* any value attached and contains possible value query.
*/
public class FetchPossibleValuesModule extends AnnotatedAbstractModule {

private static final Logger LOG = LoggerFactory.getLogger(FetchPossibleValuesModule.class);
private static final String TYPE_URI = KBSS_MODULE.uri + "fetch-possible-values";

@Parameter(urlPrefix = SML.uri, name = "replace")
private boolean isReplace = false;


@Override
ExecutionContext executeSelf() {

Model inpModel = this.getExecutionContext().getDefaultModel();

Model constructedModel = ModelFactory.createDefaultModel();

Map<String, PossibleValuesQueryProcessor> query2possibleValue = new HashMap<>();

JenaFormUtils.getQuestions(inpModel)
.filterKeep(q -> q.hasProperty(SFormsVocabularyJena.s_p_has_possible_values_query))
.filterKeep(q -> !q.hasProperty(SFormsVocabularyJena.s_p_has_possible_value))
.forEachRemaining(
q -> {

String possibleValuesQuery = getPossibleValuesQuery(q);
PossibleValuesQueryProcessor qProcessor = query2possibleValue.get(possibleValuesQuery);
if (qProcessor == null) {
qProcessor = new PossibleValuesQueryProcessor(possibleValuesQuery);
LOG.debug("Retrieved {} new possible values for question {}.",
qProcessor.getPossibleValuesCount(), q.getURI());
query2possibleValue.put(possibleValuesQuery, qProcessor);
} else {
LOG.debug("Using cache of {} possible values for question {}.",
qProcessor.getPossibleValuesCount(), q.getURI());
}
qProcessor.addQuestion(q);
}
);

query2possibleValue.values().forEach(
qP -> {
constructedModel.add(qP.getPossibleValuesModel());
qP.getRelatedQuestions().forEach(
q -> qP.getPossibleValueResources().forEach(
v -> constructedModel.add(q, SFormsVocabularyJena.s_p_has_possible_value, v)
)
);
}
);

if (isReplace) {
return ExecutionContextFactory.createContext(constructedModel);
} else {
return ExecutionContextFactory.createContext(ModelFactory.createUnion(constructedModel, inpModel));
}
}

public String getPossibleValuesQuery(Resource question) {
return question
.getRequiredProperty(SFormsVocabularyJena.s_p_has_possible_values_query)
.getObject()
.asLiteral()
.toString();
}

public boolean isReplace() {
return isReplace;
}

public void setReplace(boolean replace) {
isReplace = replace;
}

@Override
public String getTypeURI() {
return TYPE_URI;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package cz.cvut.spipes.modules;

import org.apache.jena.rdf.model.Model;
import org.apache.jena.rdf.model.ModelFactory;
import org.apache.jena.rdf.model.Resource;
import org.apache.jena.util.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.net.URI;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;

class PossibleValuesQueryProcessor {

private static final Logger LOG = LoggerFactory.getLogger(PossibleValuesQueryProcessor.class);
String possibleValuesQuery;
String retrievedPossibleValues;
Model possibleValuesModel;
List<Resource> possibleValueResources;

List<Resource> questions = new LinkedList<>();

PossibleValuesQueryProcessor(String possibleValuesQuery) {
this.possibleValuesQuery = possibleValuesQuery;
this.retrievedPossibleValues = fetchPossibleValues(possibleValuesQuery);
if (this.retrievedPossibleValues != null) {
this.possibleValuesModel = convertRetrievedValuesToModel(this.retrievedPossibleValues);
possibleValueResources = possibleValuesModel.listSubjects().toList();
}
}

private String fetchPossibleValues(String possibleValueQuery) {
final HttpHeaders headers = new HttpHeaders();
headers.set(HttpHeaders.ACCEPT, "text/turtle");
final HttpEntity<Object> entity = new HttpEntity<>(null, headers);
final URI urlWithQuery = URI.create(possibleValueQuery);
RestTemplate restTemplate = new RestTemplate();
try {
final ResponseEntity<String> result = restTemplate.exchange(urlWithQuery, HttpMethod.GET, entity,
String.class);
return result.getBody();
} catch (Exception e) {
LOG.error("Error when requesting remote data, url: {}.", urlWithQuery, e);
}
return null;
}

private Model convertRetrievedValuesToModel(String possibleValues) {
InputStream pvIS = new ByteArrayInputStream(possibleValues.getBytes());
return ModelFactory.createDefaultModel().read(pvIS, null, FileUtils.langTurtle);
}

public void addQuestion(Resource question) {
questions.add(question);
}

public int getPossibleValuesCount() {
return possibleValueResources.size();
}

public List<Resource> getPossibleValueResources() {
return Collections.unmodifiableList(possibleValueResources);
}

public List<Resource> getRelatedQuestions() {
return Collections.unmodifiableList(questions);
}

public Model getPossibleValuesModel() {
return possibleValuesModel;
}
}

0 comments on commit ee84a52

Please sign in to comment.