-
Notifications
You must be signed in to change notification settings - Fork 4
/
ApplyConstructModule.java
185 lines (142 loc) · 6.19 KB
/
ApplyConstructModule.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
package cz.cvut.spipes.modules;
import cz.cvut.spipes.config.AuditConfig;
import cz.cvut.spipes.config.Environment;
import cz.cvut.spipes.config.ExecutionConfig;
import cz.cvut.spipes.constants.KBSS_MODULE;
import cz.cvut.spipes.constants.SML;
import cz.cvut.spipes.engine.ExecutionContext;
import cz.cvut.spipes.util.JenaUtils;
import cz.cvut.spipes.util.QueryUtils;
import org.apache.jena.query.Query;
import org.apache.jena.query.QueryFactory;
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.Resource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.topbraid.spin.arq.ARQFactory;
import org.topbraid.spin.model.Construct;
import org.topbraid.spin.system.SPINModuleRegistry;
import org.topbraid.spin.vocabulary.SP;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
/**
* TODO Order of queries is not enforced.
*
**/
public class ApplyConstructModule extends AbstractModule {
private static final Logger LOG = LoggerFactory.getLogger(ApplyConstructModule.class);
//sml:constructQuery
private List<Resource> constructQueries;
//sml:replace
private boolean isReplace;
//kbss:parseText
/**
* Whether the query should be taken from sp:text property instead of from SPIN serialization
*/
private boolean parseText;
//kbss:iterationCount
/**
* Maximal number of iterations of the whole rule set. 0 means 0 iterations. The actual number of iterations can be smaller,
* if no new inferences are generated any more.
*
* iterationCount = 1:
* - the whole rule set is executed only once.
* iterationCount > 1:
* - the whole rule set is executed at most "iterationCount" times.
* - in each iteration, queries are evaluated on the model merged from the default model and the result of previous iteration
*
* Within each iteration, all queries are evaluated on the same model.
*
*/
private int iterationCount;
public ApplyConstructModule() {
// TODO move elsewhere
SPINModuleRegistry.get().init(); //TODO -- downloads spin from the web (should be cached instead)
}
public boolean isParseText() {
return parseText;
}
public void setParseText(boolean parseText) {
this.parseText = parseText;
}
public int getIterationCount() {
return iterationCount;
}
public void setIterationCount(int iterationCount) {
this.iterationCount = iterationCount;
}
public boolean isReplace() {
return isReplace;
}
public void setReplace(boolean replace) {
isReplace = replace;
}
public List<Resource> getConstructQueries() {
return constructQueries;
}
public void setConstructQueries(List<Resource> constructQueries) {
this.constructQueries = constructQueries;
}
public ExecutionContext executeSelf() {
Model defaultModel = executionContext.getDefaultModel();
QuerySolution bindings = executionContext.getVariablesBinding().asQuerySolution();
long nNew = 1;
int count = 0;
Model inferredModel = ModelFactory.createDefaultModel();
List<Construct> constructQueriesSorted = constructQueries
.stream().map(r -> r.as(Construct.class))
.sorted(Comparator.comparing(this::getQueryComment))
.collect(Collectors.toList());
while (nNew > 0 && count++ < iterationCount) {
// set up variable bindings
Model inferredInSingleIterationModel = ModelFactory.createDefaultModel();
Model extendedInferredModel = JenaUtils.createUnion(defaultModel, inferredModel);
for (int i = 0; i < constructQueriesSorted.size(); i++) {
Construct spinConstructRes = constructQueriesSorted.get(i);
if (LOG.isTraceEnabled()) {
String queryComment = getQueryComment(spinConstructRes);
LOG.trace(
"Executing iteration {}/{} with {}/{} query \"{}\" ...",
count, iterationCount, i + 1, constructQueriesSorted.size(), queryComment
);
}
Query query;
if (parseText) {
query = QueryFactory.create(spinConstructRes.getProperty(SP.text).getLiteral().getString());
} else {
query = ARQFactory.get().createQuery(spinConstructRes);
}
Model constructedModel = QueryUtils.execConstruct(query, extendedInferredModel, bindings);
if (LOG.isTraceEnabled()) {
LOG.trace("... the query returned {} triples.", constructedModel.size());
}
if (AuditConfig.isEnabled() || ExecutionConfig.getEnvironment().equals(Environment.development)) {
LOG.debug("... saving module's partially computed output to file {}.", saveModelToTemporaryFile(constructedModel));
}
inferredInSingleIterationModel = ModelFactory.createUnion(inferredInSingleIterationModel, constructedModel);
}
inferredModel = JenaUtils.createUnion(inferredModel, inferredInSingleIterationModel);
nNew = inferredInSingleIterationModel.size();
}
return this.createOutputContext(isReplace, inferredModel);
}
@Override
public String getTypeURI() {
return SML.ApplyConstruct.getURI();
}
@Override
public void loadConfiguration() {
// TODO sparql expressions
// TODO load default values from configuration
// TODO does not work with string query as object is not RDF resource ???
constructQueries = getResourcesByProperty(SML.constructQuery);
LOG.debug("Loaded {} spin construct queries.", constructQueries.size());
//TODO default value must be taken from template definition
isReplace = this.getPropertyValue(SML.replace, false);
parseText = this.getPropertyValue(KBSS_MODULE.is_parse_text, false);
iterationCount = this.getPropertyValue(KBSS_MODULE.has_max_iteration_count, 1);
}
}