aboutsummaryrefslogtreecommitdiff
path: root/src/uk/ac/ox/cs/pagoda/query
diff options
context:
space:
mode:
Diffstat (limited to 'src/uk/ac/ox/cs/pagoda/query')
-rw-r--r--src/uk/ac/ox/cs/pagoda/query/AnswerTuple.java30
-rw-r--r--src/uk/ac/ox/cs/pagoda/query/QueryRecord.java141
2 files changed, 92 insertions, 79 deletions
diff --git a/src/uk/ac/ox/cs/pagoda/query/AnswerTuple.java b/src/uk/ac/ox/cs/pagoda/query/AnswerTuple.java
index 78aced1..9a9d0de 100644
--- a/src/uk/ac/ox/cs/pagoda/query/AnswerTuple.java
+++ b/src/uk/ac/ox/cs/pagoda/query/AnswerTuple.java
@@ -16,14 +16,10 @@ import java.lang.reflect.Type;
16import java.util.HashMap; 16import java.util.HashMap;
17import java.util.Map; 17import java.util.Map;
18import java.util.StringTokenizer; 18import java.util.StringTokenizer;
19import java.util.regex.Matcher;
20import java.util.regex.Pattern;
21 19
22public class AnswerTuple { 20public class AnswerTuple {
23 21
24 public static final String SEPARATOR = "\t"; 22 public static final String SEPARATOR = "\t";
25 static final Pattern owlLiteralRegex =
26 Pattern.compile("^\"(?<lexicalForm>[^@]+(@(?<langTag>.+))?)\"(^^<(?<dataType>.+)>)?$");
27 String m_str = null; 23 String m_str = null;
28 GroundTerm[] m_tuple; 24 GroundTerm[] m_tuple;
29 25
@@ -158,32 +154,36 @@ public class AnswerTuple {
158 String tuplesString = json.getAsJsonPrimitive().getAsString(); 154 String tuplesString = json.getAsJsonPrimitive().getAsString();
159// StringTokenizer tokenizer = new StringTokenizer(tuplesString, SEPARATOR); 155// StringTokenizer tokenizer = new StringTokenizer(tuplesString, SEPARATOR);
160 StringTokenizer tokenizer = new StringTokenizer(tuplesString); 156 StringTokenizer tokenizer = new StringTokenizer(tuplesString);
161 GroundTerm[] terms = new GroundTerm[tokenizer.countTokens()]; 157 int tokensCount = tokenizer.countTokens();
158 GroundTerm[] terms = new GroundTerm[tokensCount];
162 159
163 // TODO test parsing 160 // TODO test parsing
164 for (int i = 0; i < tokenizer.countTokens(); i++) { 161 for(int i = 0; i < tokensCount; i++) {
165 String token = tokenizer.nextToken(); 162 String token = tokenizer.nextToken();
166 if (token.charAt(0) == '<') { 163 if (token.charAt(0) == '<') {
167 terms[i] = uk.ac.ox.cs.JRDFox.model.Individual.create(token.substring(1,token.length()-1)); 164 terms[i] = uk.ac.ox.cs.JRDFox.model.Individual.create(token.substring(1,token.length()-1));
168 } 165 }
169 else if (token.charAt(0) == '"') { 166 else if (token.charAt(0) == '"') {
170 Matcher matcher = owlLiteralRegex.matcher(token); 167 Datatype datatype;
171 if(matcher.matches()) { 168 String lexicalForm;
172 String lexicalForm = matcher.group("lexicalForm"); 169 if(token.contains("^^")) {
173 String dataTypeIRI = matcher.group("dataType"); 170 String[] lexicalFormAndType = token.split("^^");
174 Datatype dataType; 171 lexicalForm = lexicalFormAndType[0];
175 if(dataTypeIRI == null || dataTypeIRI.isEmpty()) dataType = Datatype.RDF_PLAIN_LITERAL; 172 datatype = Datatype.value(lexicalFormAndType[1]);
176 else dataType = uk.ac.ox.cs.JRDFox.model.Datatype.value(dataTypeIRI);
177 terms[i] = uk.ac.ox.cs.JRDFox.model.Literal.create(lexicalForm, dataType);
178 } 173 }
179 else { 174 else {
180 throw new IllegalArgumentException("The given json does not represent a valid AnswerTuple"); 175 lexicalForm = token.substring(1, token.length() - 1);
176 // TODO check
177// datatype = token.contains("@") ? Datatype.RDF_PLAIN_LITERAL : Datatype.XSD_STRING;
178 datatype = Datatype.XSD_STRING;
181 } 179 }
180 terms[i] = uk.ac.ox.cs.JRDFox.model.Literal.create(lexicalForm, datatype);
182 } 181 }
183 else { 182 else {
184 terms[i] = uk.ac.ox.cs.JRDFox.model.BlankNode.create(token); 183 terms[i] = uk.ac.ox.cs.JRDFox.model.BlankNode.create(token);
185 } 184 }
186 } 185 }
186
187 return new AnswerTuple(terms); 187 return new AnswerTuple(terms);
188 } 188 }
189 } 189 }
diff --git a/src/uk/ac/ox/cs/pagoda/query/QueryRecord.java b/src/uk/ac/ox/cs/pagoda/query/QueryRecord.java
index 742b7da..516a461 100644
--- a/src/uk/ac/ox/cs/pagoda/query/QueryRecord.java
+++ b/src/uk/ac/ox/cs/pagoda/query/QueryRecord.java
@@ -135,74 +135,16 @@ public class QueryRecord extends Disposable {
135 return updateUpperBoundAnswers(answerTuples, false); 135 return updateUpperBoundAnswers(answerTuples, false);
136 } 136 }
137 137
138 public boolean updateUpperBoundAnswers(AnswerTuples answerTuples, boolean toCheckAux) { 138 public boolean checkUpperBoundAnswers(AnswerTuples answerTuples) {
139 if(isDisposed()) throw new DisposedException(); 139 if(isDisposed()) throw new DisposedException();
140 140
141 if(!(answerTuples instanceof RDFoxAnswerTuples)) { 141 return updateUpperBoundAnswers(answerTuples, true, false);
142 String msg = "The upper bound must be computed by RDFox!"; 142 }
143 Utility.logError(msg);
144 throw new IllegalArgumentException(msg);
145 }
146
147 RDFoxAnswerTuples rdfoxAnswerTuples = (RDFoxAnswerTuples) answerTuples;
148
149 Set<AnswerTuple> candidateGapAnswerTuples = new HashSet<AnswerTuple>();
150 AnswerTuple tuple;
151 for(; rdfoxAnswerTuples.isValid(); rdfoxAnswerTuples.moveNext()) {
152 tuple = rdfoxAnswerTuples.getTuple();
153 if(isBottom() || !tuple.hasAnonymousIndividual())
154 if((!toCheckAux || !tuple.hasAuxPredicate()) && !soundAnswerTuples.contains(tuple))
155 candidateGapAnswerTuples.add(tuple);
156 }
157
158 /*** START: debugging ***/
159 if(PagodaProperties.isDebuggingMode()) {
160 if(rdfoxAnswerTuples.getArity() != getAnswerVariables().length)
161 throw new IllegalArgumentException(
162 "The arity of answers (" + rdfoxAnswerTuples.getArity() + ") " +
163 "is different from the number of answer variables (" +
164 getAnswerVariables().length + ")");
165
166 Set<AnswerTuple> namedAnswerTuples = new HashSet<>();
167 rdfoxAnswerTuples.reset();
168 for(; rdfoxAnswerTuples.isValid(); rdfoxAnswerTuples.moveNext()) {
169 tuple = rdfoxAnswerTuples.getTuple();
170// if(isBottom() || !tuple.hasAnonymousIndividual()) {
171 namedAnswerTuples.add(tuple);
172// }
173 }
174 HashSet<AnswerTuple> difference = new HashSet<>(soundAnswerTuples);
175 difference.removeAll(namedAnswerTuples);
176 if(!difference.isEmpty())
177 throw new IllegalArgumentException("The upper bound does not contain the lower bound! Missing answers: " + difference
178 .size());
179 }
180 /*** END: debugging ***/
181
182 boolean update;
183 if(gapAnswerTuples == null) {
184 gapAnswerTuples = candidateGapAnswerTuples;
185 update = true;
186 }
187 else {
188 update = gapAnswerTuples.retainAll(candidateGapAnswerTuples);
189 }
190
191 if(update)
192 Utility.logInfo("Upper bound answers updated: " + getNumberOfAnswers());
193 else
194 Utility.logInfo("Upper bound answers unchanged");
195 143
196 return update; 144 public boolean updateUpperBoundAnswers(AnswerTuples answerTuples, boolean toCheckAux) {
145 if(isDisposed()) throw new DisposedException();
197 146
198// boolean update = false; 147 return updateUpperBoundAnswers(answerTuples, toCheckAux, true);
199// for(Iterator<AnswerTuple> iter = gapAnswerTuples.iterator(); iter.hasNext(); ) {
200// tuple = iter.next();
201// if(!candidateGapAnswerTuples.contains(tuple)) {
202// iter.remove();
203// update = true;
204// }
205// }
206 } 148 }
207 149
208 public int getNumberOfAnswers() { 150 public int getNumberOfAnswers() {
@@ -713,6 +655,77 @@ public class QueryRecord extends Disposable {
713 return Objects.hash(queryText, soundAnswerTuples); 655 return Objects.hash(queryText, soundAnswerTuples);
714 } 656 }
715 657
658 private boolean updateUpperBoundAnswers(AnswerTuples answerTuples, boolean toCheckAux, boolean _check_containment) {
659 if(!(answerTuples instanceof RDFoxAnswerTuples)) {
660 String msg = "The upper bound must be computed by RDFox!";
661 Utility.logError(msg);
662 throw new IllegalArgumentException(msg);
663 }
664
665 RDFoxAnswerTuples rdfoxAnswerTuples = (RDFoxAnswerTuples) answerTuples;
666
667 Set<AnswerTuple> candidateGapAnswerTuples = new HashSet<AnswerTuple>();
668 AnswerTuple tuple;
669 for(; rdfoxAnswerTuples.isValid(); rdfoxAnswerTuples.moveNext()) {
670 tuple = rdfoxAnswerTuples.getTuple();
671 if(isBottom() || !tuple.hasAnonymousIndividual())
672 if((!toCheckAux || !tuple.hasAuxPredicate()) && !soundAnswerTuples.contains(tuple))
673 candidateGapAnswerTuples.add(tuple);
674 }
675
676 /*** START: debugging ***/
677 if(PagodaProperties.isDebuggingMode() && _check_containment) {
678 if(rdfoxAnswerTuples.getArity() != getAnswerVariables().length)
679 throw new IllegalArgumentException(
680 "The arity of answers (" + rdfoxAnswerTuples.getArity() + ") " +
681 "is different from the number of answer variables (" +
682 getAnswerVariables().length + ")");
683
684 Set<AnswerTuple> namedAnswerTuples = new HashSet<>();
685 rdfoxAnswerTuples.reset();
686 int numberOfAnswers = 0;
687 for(; rdfoxAnswerTuples.isValid(); rdfoxAnswerTuples.moveNext()) {
688 tuple = rdfoxAnswerTuples.getTuple();
689// if(isBottom() || !tuple.hasAnonymousIndividual()) {
690 namedAnswerTuples.add(tuple);
691// }
692 numberOfAnswers++;
693 }
694 Utility.logDebug("The number of answers returned by an upper bound: " + numberOfAnswers);
695 HashSet<AnswerTuple> difference = new HashSet<>(soundAnswerTuples);
696 difference.removeAll(namedAnswerTuples);
697 if(!difference.isEmpty())
698 throw new IllegalArgumentException("The upper bound does not contain the lower bound! Missing answers: " + difference
699 .size());
700 }
701 /*** END: debugging ***/
702
703 boolean update;
704 if(gapAnswerTuples == null) {
705 gapAnswerTuples = candidateGapAnswerTuples;
706 update = true;
707 }
708 else {
709 update = gapAnswerTuples.retainAll(candidateGapAnswerTuples);
710 }
711
712 if(update)
713 Utility.logInfo("Upper bound answers updated: " + getNumberOfAnswers());
714 else
715 Utility.logInfo("Upper bound answers unchanged");
716
717 return update;
718
719// boolean update = false;
720// for(Iterator<AnswerTuple> iter = gapAnswerTuples.iterator(); iter.hasNext(); ) {
721// tuple = iter.next();
722// if(!candidateGapAnswerTuples.contains(tuple)) {
723// iter.remove();
724// update = true;
725// }
726// }
727 }
728
716 public enum Step { 729 public enum Step {
717 LOWER_BOUND, 730 LOWER_BOUND,
718 UPPER_BOUND, 731 UPPER_BOUND,