diff --git a/engine/src/main/java/nl/inl/blacklab/search/lucene/SpansCaptureRelationsBetweenSpans.java b/engine/src/main/java/nl/inl/blacklab/search/lucene/SpansCaptureRelationsBetweenSpans.java index 2a99be3af..8a7a52bd5 100644 --- a/engine/src/main/java/nl/inl/blacklab/search/lucene/SpansCaptureRelationsBetweenSpans.java +++ b/engine/src/main/java/nl/inl/blacklab/search/lucene/SpansCaptureRelationsBetweenSpans.java @@ -12,13 +12,13 @@ /** * Captures all relations between the hits from two clauses. * - * This is used to capture cross-field relations in a parallel corpus. + * This is used to capture cross-field (alignment) relations in a parallel corpus. * - * @@@ PROBLEM: right now, subsequent spans from the source spans may not overlap! + * FIXME ? right now, subsequent spans from the source spans may not overlap! * If they do overlap, some relations may be skipped over. * We should cache (some) relations from the source span so we can be sure we return all * of them, even if the source spans overlap. Use SpansInBuckets or maybe a rewindable - * Spans view on top of that class? + * Spans view on top of that class? See @@@ comment below for a possible solution. */ class SpansCaptureRelationsBetweenSpans extends BLFilterSpans { @@ -117,6 +117,12 @@ public String toString() { /** List of relations captured for current hit */ private List capturedRelations = new ArrayList<>(); + /** Start of current (source) hit (covers all sources of captured relations) */ + private int adjustedStart; + + /** End of current (source) hit (covers all sources of captured relations) */ + private int adjustedEnd; + /** * Construct a SpansCaptureRelationsWithinSpan. * @@ -128,6 +134,24 @@ public SpansCaptureRelationsBetweenSpans(BLSpans source, List targets) { this.targets = targets; } + @Override + public int startPosition() { + if (atFirstInCurrentDoc) + return -1; + if (startPos == -1 || startPos == NO_MORE_POSITIONS) + return startPos; + return adjustedStart; + } + + @Override + public int endPosition() { + if (atFirstInCurrentDoc) + return -1; + if (startPos == -1 || startPos == NO_MORE_POSITIONS) + return startPos; + return adjustedEnd; + } + @Override protected FilterSpans.AcceptStatus accept(BLSpans candidate) throws IOException { // Prepare matchInfo so we can add captured relations to it @@ -139,11 +163,16 @@ protected FilterSpans.AcceptStatus accept(BLSpans candidate) throws IOException candidate.getMatchInfo(matchInfo); // Find current source span - int sourceStart = startPosition(); - int sourceEnd = endPosition(); + int sourceStart = candidate.startPosition(); + int sourceEnd = candidate.endPosition(); + + // Our final (source) span will cover all captured relations. + adjustedStart = sourceStart; + adjustedEnd = sourceEnd; for (Target target: targets) { - // Capture all relations with source inside this span. + + // Capture all relations with source overlapping this span. capturedRelations.clear(); int targetPosMin = Integer.MAX_VALUE; int targetPosMax = Integer.MIN_VALUE; @@ -151,21 +180,28 @@ protected FilterSpans.AcceptStatus accept(BLSpans candidate) throws IOException if (docId < candidate.docID()) docId = target.relations.advance(candidate.docID()); if (docId == candidate.docID()) { - // @@@ TODO: make rewindable Spans view on top of SpansInBucketsPerDocument for this? + + // @@@ make rewindable Spans view on top of SpansInBucketsPerDocument for this? // (otherwise we might miss relations if the source spans overlap) - // if (target.relations.startPosition() > sourceStart) + // + // // Rewind relations if necessary + // if (target.relations.endPosition() > sourceStart) // target.relations.rewindStartPosition(sourceStart); - if (target.relations.startPosition() < sourceStart) - target.relations.advanceStartPosition(sourceStart); + + // Advance relations such that the relation source end position is after the + // current start position (of the query source), i.e. they may overlap. + while (target.relations.endPosition() <= sourceStart) { + if (target.relations.nextStartPosition() == NO_MORE_POSITIONS) + break; + } while (target.relations.startPosition() < sourceEnd) { - if (target.relations.endPosition() <= sourceEnd) { - // Source of this relation is inside our source hit. - RelationInfo relInfo = target.relations.getRelationInfo().copy(); - capturedRelations.add(relInfo); - // Keep track of the min and max target positions so we can quickly reject targets below. - targetPosMin = Math.min(targetPosMin, relInfo.getTargetStart()); - targetPosMax = Math.max(targetPosMax, relInfo.getTargetEnd()); - } + // Source of this relation overlaps our source hit. + RelationInfo relInfo = target.relations.getRelationInfo().copy(); + capturedRelations.add(relInfo); + // Keep track of the min and max target positions so we can quickly reject targets below. + targetPosMin = Math.min(targetPosMin, relInfo.getTargetStart()); + targetPosMax = Math.max(targetPosMax, relInfo.getTargetEnd()); + target.relations.nextStartPosition(); } } @@ -190,10 +226,11 @@ protected FilterSpans.AcceptStatus accept(BLSpans candidate) throws IOException target.targetField); } + updateSourceStartEndWithCapturedRelations(); // update start/end to cover all captured relations continue; } - // Find the smallest target span that covers the highest number of the relations we just captured. + // Find the smallest target span that overlaps the highest number of the relations we just captured. int targetDocId = target.target.docID(); if (targetDocId < candidate.docID()) { targetDocId = target.target.advance(candidate.docID()); @@ -213,9 +250,9 @@ protected FilterSpans.AcceptStatus accept(BLSpans candidate) throws IOException continue; } // There is some overlap between the target span and the relations we captured. - // Find out which relations are inside this target span, so we can pick the best target span. + // Find out which relations overlap this target span, so we can pick the best target span. int relationsCovered = (int) capturedRelations.stream() - .filter(r -> r.getTargetStart() >= targetStart && r.getTargetEnd() <= targetEnd) + .filter(r -> r.getTargetEnd() > targetStart && r.getTargetStart() < targetEnd) .count(); int length = targetEnd - targetStart; if (relationsCovered > targetRelationsCovered @@ -229,13 +266,15 @@ protected FilterSpans.AcceptStatus accept(BLSpans candidate) throws IOException // A valid hit must have at least one matching relation in each target. return FilterSpans.AcceptStatus.NO; } - // Only keep the relations that match the target span we found. + // Only keep the relations that overlap the target span we found. int finalTargetIndex = targetIndex; - capturedRelations.removeIf(r -> r.getTargetStart() < target.target.startPosition(finalTargetIndex) - || r.getTargetEnd() > target.target.endPosition(finalTargetIndex)); + capturedRelations.removeIf(r -> r.getTargetEnd() <= target.target.startPosition(finalTargetIndex) + || r.getTargetStart() >= target.target.endPosition(finalTargetIndex)); capturedRelations.sort(RelationInfo::compareTo); matchInfo[target.captureAsIndex] = RelationListInfo.create(capturedRelations, getOverriddenField()); target.target.getMatchInfo(finalTargetIndex, matchInfo); // also perform captures on the target + + updateSourceStartEndWithCapturedRelations(); // update start/end to cover all captured relations } else { // Target document has no matches. Reject this hit. return FilterSpans.AcceptStatus.NO; @@ -245,6 +284,17 @@ protected FilterSpans.AcceptStatus accept(BLSpans candidate) throws IOException return FilterSpans.AcceptStatus.YES; } + private void updateSourceStartEndWithCapturedRelations() { + // Our final (source) span will cover all captured relations, so that + // e.g. "the" =sentence-alignment=>nl "de" will have the aligned sentences as hits, not just single words. + capturedRelations.forEach(r -> { + if (r.getSourceStart() < adjustedStart) + adjustedStart = r.getSourceStart(); + if (r.getSourceEnd() > adjustedEnd) + adjustedEnd = r.getSourceEnd(); + }); + } + @Override public String toString() { return "==>(" + in + ", " + targets + ")"; diff --git a/query-parser/src/main/java/nl/inl/blacklab/queryParser/corpusql/GeneratedCorpusQueryLanguageParserTokenManager.java b/query-parser/src/main/java/nl/inl/blacklab/queryParser/corpusql/GeneratedCorpusQueryLanguageParserTokenManager.java index c1dfccd06..aedd5648e 100644 --- a/query-parser/src/main/java/nl/inl/blacklab/queryParser/corpusql/GeneratedCorpusQueryLanguageParserTokenManager.java +++ b/query-parser/src/main/java/nl/inl/blacklab/queryParser/corpusql/GeneratedCorpusQueryLanguageParserTokenManager.java @@ -393,7 +393,7 @@ private int jjMoveNfa_0(int startState, int curPos) catch(java.io.IOException e) { throw new Error("Internal Error"); } curPos = 0; int startsAt = 0; - jjnewStateCnt = 58; + jjnewStateCnt = 61; int i = 1; jjstateSet[0] = startState; int kind = 0x7fffffff; @@ -413,20 +413,20 @@ private int jjMoveNfa_0(int startState, int curPos) { if (kind > 15) kind = 15; - { jjCheckNAdd(39); } + { jjCheckNAdd(42); } } else if (curChar == 39) { jjCheckNAddStates(0, 2); } else if (curChar == 34) { jjCheckNAddStates(3, 5); } else if (curChar == 37) - jjstateSet[jjnewStateCnt++] = 38; + jjstateSet[jjnewStateCnt++] = 41; else if (curChar == 61) - { jjCheckNAddTwoStates(29, 34); } + { jjCheckNAddTwoStates(31, 37); } else if (curChar == 45) - { jjCheckNAddTwoStates(22, 27); } + { jjCheckNAddTwoStates(23, 29); } else if (curChar == 33) - jjstateSet[jjnewStateCnt++] = 21; + jjstateSet[jjnewStateCnt++] = 22; else if (curChar == 47) jjstateSet[jjnewStateCnt++] = 5; else if (curChar == 35) @@ -485,189 +485,201 @@ else if (curChar == 35) break; case 12: if (curChar == 45) - { jjCheckNAddTwoStates(13, 18); } + { jjCheckNAddTwoStates(13, 19); } break; case 13: if ((0xffffdfffffffffffL & l) != 0L) { jjCheckNAddStates(12, 14); } break; case 14: - if (curChar == 45) - jjstateSet[jjnewStateCnt++] = 15; + if ((0xffffdf7affffffffL & l) != 0L) + { jjCheckNAddStates(12, 14); } break; case 15: - if ((0xbfffffffffffffffL & l) != 0L) - { jjCheckNAddStates(12, 14); } + if (curChar == 45) + jjstateSet[jjnewStateCnt++] = 16; break; case 16: + if ((0xbfffff7affffffffL & l) != 0L) + { jjCheckNAddStates(12, 14); } + break; + case 17: if (curChar != 62) break; if (kind > 10) kind = 10; - { jjCheckNAdd(17); } + { jjCheckNAdd(18); } break; - case 17: + case 18: if ((0x3ff200000000000L & l) == 0L) break; if (kind > 10) kind = 10; - { jjCheckNAdd(17); } + { jjCheckNAdd(18); } break; - case 18: + case 19: if (curChar == 45) - jjstateSet[jjnewStateCnt++] = 16; + jjstateSet[jjnewStateCnt++] = 17; break; - case 20: + case 21: if (curChar == 33) - jjstateSet[jjnewStateCnt++] = 21; + jjstateSet[jjnewStateCnt++] = 22; break; - case 21: + case 22: if (curChar == 45) - { jjCheckNAddTwoStates(22, 27); } + { jjCheckNAddTwoStates(23, 29); } break; - case 22: + case 23: if ((0xffffdfffffffffffL & l) != 0L) { jjCheckNAddStates(15, 17); } break; - case 23: - if (curChar == 45) - jjstateSet[jjnewStateCnt++] = 24; - break; case 24: - if ((0xbfffffffffffffffL & l) != 0L) + if ((0xffffdf7affffffffL & l) != 0L) { jjCheckNAddStates(15, 17); } break; case 25: + if (curChar == 45) + jjstateSet[jjnewStateCnt++] = 26; + break; + case 26: + if ((0xbfffff7affffffffL & l) != 0L) + { jjCheckNAddStates(15, 17); } + break; + case 27: if (curChar != 62) break; if (kind > 11) kind = 11; - { jjCheckNAdd(26); } + { jjCheckNAdd(28); } break; - case 26: + case 28: if ((0x3ff200000000000L & l) == 0L) break; if (kind > 11) kind = 11; - { jjCheckNAdd(26); } + { jjCheckNAdd(28); } break; - case 27: + case 29: if (curChar == 45) - jjstateSet[jjnewStateCnt++] = 25; + jjstateSet[jjnewStateCnt++] = 27; break; - case 28: + case 30: if (curChar == 61) - { jjCheckNAddTwoStates(29, 34); } + { jjCheckNAddTwoStates(31, 37); } break; - case 29: + case 31: if ((0xdfffffffffffffffL & l) != 0L) { jjCheckNAddStates(18, 20); } break; - case 30: + case 32: + if ((0xdfffff7affffffffL & l) != 0L) + { jjCheckNAddStates(18, 20); } + break; + case 33: if (curChar == 61) - jjstateSet[jjnewStateCnt++] = 31; + jjstateSet[jjnewStateCnt++] = 34; break; - case 31: - if ((0xbfffffffffffffffL & l) != 0L) + case 34: + if ((0xbfffff7affffffffL & l) != 0L) { jjCheckNAddStates(18, 20); } break; - case 32: + case 35: if (curChar != 62) break; if (kind > 12) kind = 12; - { jjCheckNAdd(33); } + { jjCheckNAdd(36); } break; - case 33: + case 36: if ((0x3ff200000000000L & l) == 0L) break; if (kind > 12) kind = 12; - { jjCheckNAdd(33); } + { jjCheckNAdd(36); } break; - case 34: + case 37: if (curChar == 61) - jjstateSet[jjnewStateCnt++] = 32; + jjstateSet[jjnewStateCnt++] = 35; break; - case 36: + case 39: if ((0x3ff200000000000L & l) == 0L) break; if (kind > 13) kind = 13; - jjstateSet[jjnewStateCnt++] = 36; + jjstateSet[jjnewStateCnt++] = 39; break; - case 37: + case 40: if (curChar == 37) - jjstateSet[jjnewStateCnt++] = 38; + jjstateSet[jjnewStateCnt++] = 41; break; - case 39: + case 42: if ((0x3ff000000000000L & l) == 0L) break; if (kind > 15) kind = 15; - { jjCheckNAdd(39); } + { jjCheckNAdd(42); } break; - case 41: + case 44: if ((0x3ff000000000000L & l) != 0L) { jjAddStates(21, 22); } break; - case 42: + case 45: if (curChar == 61) - { jjCheckNAdd(43); } + { jjCheckNAdd(46); } break; - case 43: + case 46: if ((0x3ff000000000000L & l) == 0L) break; if (kind > 16) kind = 16; - { jjCheckNAddTwoStates(43, 44); } + { jjCheckNAddTwoStates(46, 47); } break; - case 44: + case 47: if (curChar == 44) - { jjCheckNAdd(45); } + { jjCheckNAdd(48); } break; - case 45: + case 48: if ((0x3ff000000000000L & l) != 0L) - { jjCheckNAddTwoStates(45, 46); } + { jjCheckNAddTwoStates(48, 49); } break; - case 46: + case 49: if (curChar == 61) - { jjCheckNAdd(47); } + { jjCheckNAdd(50); } break; - case 47: + case 50: if ((0x3ff000000000000L & l) == 0L) break; if (kind > 16) kind = 16; - { jjCheckNAddTwoStates(44, 47); } + { jjCheckNAddTwoStates(47, 50); } break; - case 48: + case 51: if (curChar == 34) { jjCheckNAddStates(3, 5); } break; - case 49: + case 52: if ((0xfffffffbffffffffL & l) != 0L) { jjCheckNAddStates(3, 5); } break; - case 51: + case 54: { jjCheckNAddStates(3, 5); } break; - case 52: + case 55: if (curChar == 34 && kind > 17) kind = 17; break; - case 53: + case 56: if (curChar == 39) { jjCheckNAddStates(0, 2); } break; - case 54: + case 57: if ((0xffffff7fffffffffL & l) != 0L) { jjCheckNAddStates(0, 2); } break; - case 56: + case 59: { jjCheckNAddStates(0, 2); } break; - case 57: + case 60: if (curChar == 39 && kind > 18) kind = 18; break; @@ -687,10 +699,10 @@ else if (curChar < 128) { if (kind > 13) kind = 13; - { jjCheckNAdd(36); } + { jjCheckNAdd(39); } } else if (curChar == 64) - { jjCheckNAdd(41); } + { jjCheckNAdd(44); } else if (curChar == 94) jjstateSet[jjnewStateCnt++] = 12; break; @@ -704,103 +716,106 @@ else if (curChar == 94) { jjCheckNAddStates(9, 11); } break; case 13: - case 15: + case 14: + case 16: { jjCheckNAddStates(12, 14); } break; - case 17: + case 18: if ((0x7fffffe87fffffeL & l) == 0L) break; if (kind > 10) kind = 10; - jjstateSet[jjnewStateCnt++] = 17; + jjstateSet[jjnewStateCnt++] = 18; break; - case 19: + case 20: if (curChar == 94) jjstateSet[jjnewStateCnt++] = 12; break; - case 22: + case 23: case 24: + case 26: { jjCheckNAddStates(15, 17); } break; - case 26: + case 28: if ((0x7fffffe87fffffeL & l) == 0L) break; if (kind > 11) kind = 11; - jjstateSet[jjnewStateCnt++] = 26; + jjstateSet[jjnewStateCnt++] = 28; break; - case 29: case 31: + case 32: + case 34: { jjCheckNAddStates(18, 20); } break; - case 33: + case 36: if ((0x7fffffe87fffffeL & l) == 0L) break; if (kind > 12) kind = 12; - jjstateSet[jjnewStateCnt++] = 33; + jjstateSet[jjnewStateCnt++] = 36; break; - case 35: - case 36: + case 38: + case 39: if ((0x7fffffe87fffffeL & l) == 0L) break; if (kind > 13) kind = 13; - { jjCheckNAdd(36); } + { jjCheckNAdd(39); } break; - case 38: + case 41: if ((0x101800001018L & l) == 0L) break; if (kind > 14) kind = 14; - jjstateSet[jjnewStateCnt++] = 38; + jjstateSet[jjnewStateCnt++] = 41; break; - case 40: + case 43: if (curChar == 64) - { jjCheckNAdd(41); } + { jjCheckNAdd(44); } break; - case 41: + case 44: if ((0x7fffffe87fffffeL & l) != 0L) - { jjCheckNAddTwoStates(41, 42); } + { jjCheckNAddTwoStates(44, 45); } break; - case 43: + case 46: if ((0x7fffffe87fffffeL & l) == 0L) break; if (kind > 16) kind = 16; - { jjCheckNAddTwoStates(43, 44); } + { jjCheckNAddTwoStates(46, 47); } break; - case 45: + case 48: if ((0x7fffffe87fffffeL & l) != 0L) { jjAddStates(23, 24); } break; - case 47: + case 50: if ((0x7fffffe87fffffeL & l) == 0L) break; if (kind > 16) kind = 16; - { jjCheckNAddTwoStates(44, 47); } + { jjCheckNAddTwoStates(47, 50); } break; - case 49: + case 52: if ((0xffffffffefffffffL & l) != 0L) { jjCheckNAddStates(3, 5); } break; - case 50: + case 53: if (curChar == 92) - jjstateSet[jjnewStateCnt++] = 51; + jjstateSet[jjnewStateCnt++] = 54; break; - case 51: + case 54: { jjCheckNAddStates(3, 5); } break; - case 54: + case 57: if ((0xffffffffefffffffL & l) != 0L) { jjCheckNAddStates(0, 2); } break; - case 55: + case 58: if (curChar == 92) - jjstateSet[jjnewStateCnt++] = 56; + jjstateSet[jjnewStateCnt++] = 59; break; - case 56: + case 59: { jjCheckNAddStates(0, 2); } break; default : break; @@ -831,27 +846,30 @@ else if (curChar == 94) { jjCheckNAddStates(9, 11); } break; case 13: - case 15: + case 14: + case 16: if (jjCanMove_0(hiByte, i1, i2, l1, l2)) { jjCheckNAddStates(12, 14); } break; - case 22: + case 23: case 24: + case 26: if (jjCanMove_0(hiByte, i1, i2, l1, l2)) { jjCheckNAddStates(15, 17); } break; - case 29: case 31: + case 32: + case 34: if (jjCanMove_0(hiByte, i1, i2, l1, l2)) { jjCheckNAddStates(18, 20); } break; - case 49: - case 51: + case 52: + case 54: if (jjCanMove_0(hiByte, i1, i2, l1, l2)) { jjCheckNAddStates(3, 5); } break; - case 54: - case 56: + case 57: + case 59: if (jjCanMove_0(hiByte, i1, i2, l1, l2)) { jjCheckNAddStates(0, 2); } break; @@ -866,7 +884,7 @@ else if (curChar == 94) kind = 0x7fffffff; } ++curPos; - if ((i = jjnewStateCnt) == (startsAt = 58 - (jjnewStateCnt = startsAt))) + if ((i = jjnewStateCnt) == (startsAt = 61 - (jjnewStateCnt = startsAt))) break; try { curChar = input_stream.readChar(); } catch(java.io.IOException e) { break; } @@ -892,8 +910,8 @@ else if (jjmatchedPos == strPos && jjmatchedKind > strKind) return toRet; } static final int[] jjnextStates = { - 54, 55, 57, 49, 50, 52, 1, 2, 4, 6, 7, 10, 13, 14, 18, 22, - 23, 27, 29, 30, 34, 41, 42, 45, 46, + 57, 58, 60, 52, 53, 55, 1, 2, 4, 6, 7, 10, 14, 15, 19, 24, + 25, 29, 32, 33, 37, 44, 45, 48, 49, }; private static final boolean jjCanMove_0(int hiByte, int i1, int i2, long l1, long l2) { @@ -1076,7 +1094,7 @@ private void ReInitRounds() { int i; jjround = 0x80000001; - for (i = 58; i-- > 0;) + for (i = 61; i-- > 0;) jjrounds[i] = 0x80000000; } @@ -1112,8 +1130,8 @@ public void SwitchTo(int lexState) }; protected JavaCharStream input_stream; - private final int[] jjrounds = new int[58]; - private final int[] jjstateSet = new int[2 * 58]; + private final int[] jjrounds = new int[61]; + private final int[] jjstateSet = new int[2 * 61]; protected int curChar; diff --git a/query-parser/src/main/javacc/nl/inl/blacklab/queryParser/corpusql/cql.jj b/query-parser/src/main/javacc/nl/inl/blacklab/queryParser/corpusql/cql.jj index 3124f18a0..6a5bac3a6 100644 --- a/query-parser/src/main/javacc/nl/inl/blacklab/queryParser/corpusql/cql.jj +++ b/query-parser/src/main/javacc/nl/inl/blacklab/queryParser/corpusql/cql.jj @@ -97,9 +97,9 @@ TOKEN [IGNORE_CASE]: | | /* valid are e.g. --> -root-> -.*-> -a-b-> (and same preceded by ^ or !) */ -| "] )* )? "->" (["A"-"Z","a"-"z","_","-","0"-"9"])* > -| "] )* )? "->" (["A"-"Z","a"-"z","_","-","0"-"9"])* > -| "] )* )? "=>" (["A"-"Z","a"-"z","_","-","0"-"9"])* > +| ", " ", "'", "\"", "]"] )* )? "->" (["A"-"Z","a"-"z","_","-","0"-"9"])* > +| ", " ", "'", "\"", "]"] )* )? "->" (["A"-"Z","a"-"z","_","-","0"-"9"])* > +| ", " ", "'", "\"", "]"] )* )? "=>" (["A"-"Z","a"-"z","_","-","0"-"9"])* > | | | diff --git a/query-parser/src/test/java/nl/inl/blacklab/search/TestBcqlParser.java b/query-parser/src/test/java/nl/inl/blacklab/search/TestBcqlParser.java index 0667a4b4b..dfdb05de4 100644 --- a/query-parser/src/test/java/nl/inl/blacklab/search/TestBcqlParser.java +++ b/query-parser/src/test/java/nl/inl/blacklab/search/TestBcqlParser.java @@ -19,4 +19,10 @@ public void testEscapedQuote() throws IOException, InvalidQuery { Assert.assertTrue(tp instanceof TextPatternTerm); Assert.assertEquals("\"", ((TextPatternTerm) tp).getValue()); } + + @Test + public void testParseAlignmentQuery() throws IOException, InvalidQuery { + String pattern = "[word='the'] =verse-alignment=>nl [word='het']"; + TextPattern tp = CorpusQueryLanguageParser.parse(pattern); + } } diff --git a/wslib/src/main/java/nl/inl/blacklab/server/search/SearchManager.java b/wslib/src/main/java/nl/inl/blacklab/server/search/SearchManager.java index f3c000889..2ad9d3258 100644 --- a/wslib/src/main/java/nl/inl/blacklab/server/search/SearchManager.java +++ b/wslib/src/main/java/nl/inl/blacklab/server/search/SearchManager.java @@ -11,10 +11,10 @@ import nl.inl.blacklab.search.BlackLab; import nl.inl.blacklab.search.BlackLabEngine; import nl.inl.blacklab.searches.SearchCache; +import nl.inl.blacklab.server.auth.AuthManager; import nl.inl.blacklab.server.config.BLSConfig; import nl.inl.blacklab.server.exceptions.ConfigurationException; import nl.inl.blacklab.server.index.IndexManager; -import nl.inl.blacklab.server.auth.AuthManager; /** * Manages the lifetime of a number of objects needed for the web service. @@ -45,6 +45,7 @@ public class SearchManager { * @throws ConfigurationException */ public SearchManager(BLSConfig config, boolean forceApplyGlobalConfig) throws ConfigurationException { + assert config != null; this.config = config; // load blacklab's internal config before doing anything @@ -97,6 +98,7 @@ public SearchCache getBlackLabCache() { } public BLSConfig config() { + assert config != null; return config; }