| margaretha | 5b70879 | 2023-05-12 16:55:29 +0200 | [diff] [blame] | 1 | package de.ids_mannheim.korap.core.service; |
| margaretha | 20f3123 | 2018-07-09 17:49:39 +0200 | [diff] [blame] | 2 | |
| margaretha | 0ddaed6 | 2021-01-21 17:10:33 +0100 | [diff] [blame] | 3 | import java.io.BufferedReader; |
| 4 | import java.io.InputStreamReader; |
| 5 | import java.io.OutputStream; |
| 6 | import java.net.HttpURLConnection; |
| 7 | import java.net.URL; |
| margaretha | 20f3123 | 2018-07-09 17:49:39 +0200 | [diff] [blame] | 8 | import java.util.ArrayList; |
| margaretha | a85965d | 2018-12-19 15:58:21 +0100 | [diff] [blame] | 9 | import java.util.List; |
| margaretha | 20f3123 | 2018-07-09 17:49:39 +0200 | [diff] [blame] | 10 | import java.util.Set; |
| 11 | import java.util.regex.Pattern; |
| 12 | |
| margaretha | 137d4ee | 2019-12-13 14:49:15 +0100 | [diff] [blame] | 13 | import org.apache.http.HttpStatus; |
| margaretha | 20f3123 | 2018-07-09 17:49:39 +0200 | [diff] [blame] | 14 | import org.apache.logging.log4j.LogManager; |
| 15 | import org.apache.logging.log4j.Logger; |
| 16 | import org.springframework.beans.factory.annotation.Autowired; |
| 17 | import org.springframework.stereotype.Service; |
| 18 | |
| margaretha | 2544cdf | 2019-07-08 11:39:43 +0200 | [diff] [blame] | 19 | import com.fasterxml.jackson.databind.JsonNode; |
| margaretha | 137d4ee | 2019-12-13 14:49:15 +0100 | [diff] [blame] | 20 | import com.fasterxml.jackson.databind.node.ArrayNode; |
| 21 | import com.fasterxml.jackson.databind.node.ObjectNode; |
| margaretha | 20f3123 | 2018-07-09 17:49:39 +0200 | [diff] [blame] | 22 | |
| margaretha | 5a5b995 | 2023-06-12 12:46:36 +0200 | [diff] [blame] | 23 | import de.ids_mannheim.korap.config.KustvaktCacheable; |
| margaretha | 20f3123 | 2018-07-09 17:49:39 +0200 | [diff] [blame] | 24 | import de.ids_mannheim.korap.config.KustvaktConfiguration; |
| 25 | import de.ids_mannheim.korap.exceptions.KustvaktException; |
| 26 | import de.ids_mannheim.korap.exceptions.StatusCodes; |
| margaretha | 20f3123 | 2018-07-09 17:49:39 +0200 | [diff] [blame] | 27 | import de.ids_mannheim.korap.query.serialize.MetaQueryBuilder; |
| 28 | import de.ids_mannheim.korap.query.serialize.QuerySerializer; |
| margaretha | 137d4ee | 2019-12-13 14:49:15 +0100 | [diff] [blame] | 29 | import de.ids_mannheim.korap.response.Notifications; |
| margaretha | 398f472 | 2019-01-09 19:07:20 +0100 | [diff] [blame] | 30 | import de.ids_mannheim.korap.rewrite.RewriteHandler; |
| margaretha | 20f3123 | 2018-07-09 17:49:39 +0200 | [diff] [blame] | 31 | import de.ids_mannheim.korap.user.User; |
| 32 | import de.ids_mannheim.korap.user.User.CorpusAccess; |
| margaretha | 2544cdf | 2019-07-08 11:39:43 +0200 | [diff] [blame] | 33 | import de.ids_mannheim.korap.utils.JsonUtils; |
| margaretha | 20f3123 | 2018-07-09 17:49:39 +0200 | [diff] [blame] | 34 | import de.ids_mannheim.korap.web.ClientsHandler; |
| margaretha | db5da37 | 2023-09-01 11:02:52 +0200 | [diff] [blame] | 35 | import jakarta.annotation.PostConstruct; |
| margaretha | 96c309d | 2023-08-16 12:24:12 +0200 | [diff] [blame] | 36 | import jakarta.ws.rs.core.HttpHeaders; |
| 37 | import jakarta.ws.rs.core.MultivaluedHashMap; |
| 38 | import jakarta.ws.rs.core.MultivaluedMap; |
| 39 | import jakarta.ws.rs.core.UriBuilder; |
| margaretha | 20f3123 | 2018-07-09 17:49:39 +0200 | [diff] [blame] | 40 | |
| 41 | @Service |
| margaretha | 35e1ca2 | 2023-11-16 22:00:01 +0100 | [diff] [blame] | 42 | public class SearchService extends BasicService { |
| 43 | |
| 44 | public class TotalResultCache extends KustvaktCacheable { |
| 45 | |
| margaretha | 5a5b995 | 2023-06-12 12:46:36 +0200 | [diff] [blame] | 46 | public TotalResultCache () { |
| margaretha | 35e1ca2 | 2023-11-16 22:00:01 +0100 | [diff] [blame] | 47 | super("total_results", "key:hashedKoralQuery"); |
| margaretha | 5a5b995 | 2023-06-12 12:46:36 +0200 | [diff] [blame] | 48 | } |
| 49 | } |
| margaretha | 79d738c | 2018-12-17 16:45:47 +0100 | [diff] [blame] | 50 | private static final boolean DEBUG = false; |
| 51 | |
| margaretha | 20f3123 | 2018-07-09 17:49:39 +0200 | [diff] [blame] | 52 | private static Logger jlog = LogManager.getLogger(SearchService.class); |
| 53 | |
| 54 | @Autowired |
| margaretha | 4dee07a | 2022-05-27 11:45:28 +0200 | [diff] [blame] | 55 | private SearchNetworkEndpoint searchNetwork; |
| margaretha | 20f3123 | 2018-07-09 17:49:39 +0200 | [diff] [blame] | 56 | |
| 57 | private ClientsHandler graphDBhandler; |
| margaretha | 35e1ca2 | 2023-11-16 22:00:01 +0100 | [diff] [blame] | 58 | |
| margaretha | 5a5b995 | 2023-06-12 12:46:36 +0200 | [diff] [blame] | 59 | private TotalResultCache totalResultCache; |
| margaretha | 9b754d7 | 2025-04-01 12:46:18 +0200 | [diff] [blame] | 60 | |
| 61 | @Autowired |
| 62 | protected RewriteHandler rewriteHandler; |
| margaretha | 20f3123 | 2018-07-09 17:49:39 +0200 | [diff] [blame] | 63 | |
| margaretha | 66061bb | 2025-06-23 11:11:18 +0200 | [diff] [blame] | 64 | @Autowired |
| 65 | protected KustvaktConfiguration config; |
| 66 | |
| margaretha | 20f3123 | 2018-07-09 17:49:39 +0200 | [diff] [blame] | 67 | @PostConstruct |
| 68 | private void doPostConstruct () { |
| margaretha | 20f3123 | 2018-07-09 17:49:39 +0200 | [diff] [blame] | 69 | UriBuilder builder = UriBuilder.fromUri("http://10.0.10.13").port(9997); |
| 70 | this.graphDBhandler = new ClientsHandler(builder.build()); |
| margaretha | 35e1ca2 | 2023-11-16 22:00:01 +0100 | [diff] [blame] | 71 | |
| margaretha | 5a5b995 | 2023-06-12 12:46:36 +0200 | [diff] [blame] | 72 | totalResultCache = new TotalResultCache(); |
| margaretha | 20f3123 | 2018-07-09 17:49:39 +0200 | [diff] [blame] | 73 | } |
| 74 | |
| margaretha | e1228ab | 2021-02-22 11:51:38 +0100 | [diff] [blame] | 75 | public String getKrillVersion () { |
| 76 | return searchKrill.getIndex().getVersion(); |
| 77 | |
| 78 | } |
| margaretha | 35e1ca2 | 2023-11-16 22:00:01 +0100 | [diff] [blame] | 79 | |
| margaretha | 7926adc | 2018-08-30 13:45:33 +0200 | [diff] [blame] | 80 | @SuppressWarnings("unchecked") |
| margaretha | 20f3123 | 2018-07-09 17:49:39 +0200 | [diff] [blame] | 81 | public String serializeQuery (String q, String ql, String v, String cq, |
| 82 | Integer pageIndex, Integer startPage, Integer pageLength, |
| margaretha | 279ad6e | 2025-08-14 11:25:48 +0200 | [diff] [blame] | 83 | String context, Boolean cutoff, boolean accessRewriteDisabled, |
| 84 | double apiVersion) |
| margaretha | 2544cdf | 2019-07-08 11:39:43 +0200 | [diff] [blame] | 85 | throws KustvaktException { |
| margaretha | 279ad6e | 2025-08-14 11:25:48 +0200 | [diff] [blame] | 86 | QuerySerializer ss = new QuerySerializer(apiVersion).setQuery(q, ql, v); |
| margaretha | 35e1ca2 | 2023-11-16 22:00:01 +0100 | [diff] [blame] | 87 | if (cq != null) |
| 88 | ss.setCollection(cq); |
| margaretha | 20f3123 | 2018-07-09 17:49:39 +0200 | [diff] [blame] | 89 | |
| 90 | MetaQueryBuilder meta = new MetaQueryBuilder(); |
| margaretha | 35e1ca2 | 2023-11-16 22:00:01 +0100 | [diff] [blame] | 91 | if (pageIndex != null) |
| 92 | meta.addEntry("startIndex", pageIndex); |
| margaretha | 20f3123 | 2018-07-09 17:49:39 +0200 | [diff] [blame] | 93 | if (pageIndex == null && startPage != null) |
| 94 | meta.addEntry("startPage", startPage); |
| margaretha | 35e1ca2 | 2023-11-16 22:00:01 +0100 | [diff] [blame] | 95 | if (pageLength != null) |
| 96 | meta.addEntry("count", pageLength); |
| 97 | if (context != null) |
| 98 | meta.setSpanContext(context); |
| margaretha | 20f3123 | 2018-07-09 17:49:39 +0200 | [diff] [blame] | 99 | meta.addEntry("cutOff", cutoff); |
| 100 | |
| 101 | ss.setMeta(meta.raw()); |
| margaretha | 3495447 | 2018-10-24 20:05:17 +0200 | [diff] [blame] | 102 | // return ss.toJSON(); |
| 103 | |
| 104 | String query = ss.toJSON(); |
| 105 | query = rewriteHandler.processQuery(ss.toJSON(), null); |
| 106 | return query; |
| margaretha | 20f3123 | 2018-07-09 17:49:39 +0200 | [diff] [blame] | 107 | } |
| 108 | |
| margaretha | 2544cdf | 2019-07-08 11:39:43 +0200 | [diff] [blame] | 109 | public String search (String jsonld, String username, HttpHeaders headers) |
| 110 | throws KustvaktException { |
| 111 | |
| 112 | User user = createUser(username, headers); |
| 113 | |
| margaretha | 35e1ca2 | 2023-11-16 22:00:01 +0100 | [diff] [blame] | 114 | JsonNode node = JsonUtils.readTree(jsonld); |
| margaretha | 2544cdf | 2019-07-08 11:39:43 +0200 | [diff] [blame] | 115 | node = node.at("/meta/snippets"); |
| margaretha | 35e1ca2 | 2023-11-16 22:00:01 +0100 | [diff] [blame] | 116 | if (node != null && node.asBoolean()) { |
| margaretha | 2544cdf | 2019-07-08 11:39:43 +0200 | [diff] [blame] | 117 | user.setCorpusAccess(CorpusAccess.ALL); |
| 118 | } |
| margaretha | 35e1ca2 | 2023-11-16 22:00:01 +0100 | [diff] [blame] | 119 | |
| margaretha | 2544cdf | 2019-07-08 11:39:43 +0200 | [diff] [blame] | 120 | String query = this.rewriteHandler.processQuery(jsonld, user); |
| margaretha | 20f3123 | 2018-07-09 17:49:39 +0200 | [diff] [blame] | 121 | // MH: todo: should be possible to add the meta part to |
| 122 | // the query serialization |
| 123 | // User user = controller.getUser(ctx.getUsername()); |
| 124 | // jsonld = this.processor.processQuery(jsonld, user); |
| margaretha | 2544cdf | 2019-07-08 11:39:43 +0200 | [diff] [blame] | 125 | return searchKrill.search(query); |
| margaretha | 20f3123 | 2018-07-09 17:49:39 +0200 | [diff] [blame] | 126 | } |
| 127 | |
| margaretha | 7926adc | 2018-08-30 13:45:33 +0200 | [diff] [blame] | 128 | @SuppressWarnings("unchecked") |
| margaretha | 279ad6e | 2025-08-14 11:25:48 +0200 | [diff] [blame] | 129 | public String search (double requestedVersion, String engine, |
| 130 | String username, HttpHeaders headers, |
| margaretha | 66061bb | 2025-06-23 11:11:18 +0200 | [diff] [blame] | 131 | String q, String ql, String v, List<String> cqList, String fields, |
| 132 | String pipes, String responsePipes, Integer pageIndex, |
| 133 | Integer pageInteger, String ctx, Integer pageLength, Boolean cutoff, |
| 134 | boolean accessRewriteDisabled, boolean showTokens, |
| 135 | boolean showSnippet) throws KustvaktException { |
| margaretha | 20f3123 | 2018-07-09 17:49:39 +0200 | [diff] [blame] | 136 | |
| margaretha | c1db913 | 2019-08-28 11:32:04 +0200 | [diff] [blame] | 137 | if (pageInteger != null && pageInteger < 1) { |
| 138 | throw new KustvaktException(StatusCodes.INVALID_ARGUMENT, |
| 139 | "page must start from 1", "page"); |
| 140 | } |
| margaretha | 35e1ca2 | 2023-11-16 22:00:01 +0100 | [diff] [blame] | 141 | |
| margaretha | 20f3123 | 2018-07-09 17:49:39 +0200 | [diff] [blame] | 142 | User user = createUser(username, headers); |
| margaretha | 79d738c | 2018-12-17 16:45:47 +0100 | [diff] [blame] | 143 | CorpusAccess corpusAccess = user.getCorpusAccess(); |
| margaretha | 35e1ca2 | 2023-11-16 22:00:01 +0100 | [diff] [blame] | 144 | |
| margaretha | 2544cdf | 2019-07-08 11:39:43 +0200 | [diff] [blame] | 145 | // EM: TODO: check if requested fields are public metadata. Currently |
| 146 | // it is not needed because all metadata are public. |
| margaretha | 35e1ca2 | 2023-11-16 22:00:01 +0100 | [diff] [blame] | 147 | if (accessRewriteDisabled) { |
| margaretha | 2544cdf | 2019-07-08 11:39:43 +0200 | [diff] [blame] | 148 | corpusAccess = CorpusAccess.ALL; |
| 149 | user.setCorpusAccess(CorpusAccess.ALL); |
| 150 | } |
| margaretha | 35e1ca2 | 2023-11-16 22:00:01 +0100 | [diff] [blame] | 151 | |
| margaretha | 279ad6e | 2025-08-14 11:25:48 +0200 | [diff] [blame] | 152 | QuerySerializer serializer = new QuerySerializer(requestedVersion); |
| margaretha | 20f3123 | 2018-07-09 17:49:39 +0200 | [diff] [blame] | 153 | serializer.setQuery(q, ql, v); |
| margaretha | ed2ee24 | 2019-12-12 17:34:18 +0100 | [diff] [blame] | 154 | String cq = combineMultipleCorpusQuery(cqList); |
| margaretha | 35e1ca2 | 2023-11-16 22:00:01 +0100 | [diff] [blame] | 155 | if (cq != null) |
| 156 | serializer.setCollection(cq); |
| margaretha | 20f3123 | 2018-07-09 17:49:39 +0200 | [diff] [blame] | 157 | |
| margaretha | 8596764 | 2019-11-13 13:35:33 +0100 | [diff] [blame] | 158 | List<String> fieldList = convertFieldsToList(fields); |
| 159 | handleNonPublicFields(fieldList, accessRewriteDisabled, serializer); |
| margaretha | 35e1ca2 | 2023-11-16 22:00:01 +0100 | [diff] [blame] | 160 | |
| margaretha | 20f3123 | 2018-07-09 17:49:39 +0200 | [diff] [blame] | 161 | MetaQueryBuilder meta = createMetaQuery(pageIndex, pageInteger, ctx, |
| margaretha | 35e1ca2 | 2023-11-16 22:00:01 +0100 | [diff] [blame] | 162 | pageLength, cutoff, corpusAccess, fieldList, |
| 163 | accessRewriteDisabled, showTokens, showSnippet); |
| margaretha | 20f3123 | 2018-07-09 17:49:39 +0200 | [diff] [blame] | 164 | serializer.setMeta(meta.raw()); |
| margaretha | 35e1ca2 | 2023-11-16 22:00:01 +0100 | [diff] [blame] | 165 | |
| margaretha | 20f3123 | 2018-07-09 17:49:39 +0200 | [diff] [blame] | 166 | // There is an error in query processing |
| 167 | // - either query, corpus or meta |
| 168 | if (serializer.hasErrors()) { |
| 169 | throw new KustvaktException(serializer.toJSON()); |
| 170 | } |
| 171 | |
| margaretha | 1d1c73e | 2019-12-03 18:07:28 +0100 | [diff] [blame] | 172 | String query = serializer.toJSON(); |
| margaretha | 35e1ca2 | 2023-11-16 22:00:01 +0100 | [diff] [blame] | 173 | |
| margaretha | 9c6493e | 2022-01-25 11:54:29 +0100 | [diff] [blame] | 174 | if (accessRewriteDisabled && showTokens) { |
| margaretha | d0f3651 | 2025-07-04 11:06:10 +0200 | [diff] [blame] | 175 | query = addWarning(query, StatusCodes.NOT_ALLOWED, |
| margaretha | 9c6493e | 2022-01-25 11:54:29 +0100 | [diff] [blame] | 176 | "Tokens cannot be shown without access."); |
| margaretha | 9c6493e | 2022-01-25 11:54:29 +0100 | [diff] [blame] | 177 | } |
| margaretha | 35e1ca2 | 2023-11-16 22:00:01 +0100 | [diff] [blame] | 178 | |
| margaretha | 66061bb | 2025-06-23 11:11:18 +0200 | [diff] [blame] | 179 | // Query pipe rewrite |
| 180 | query = runPipes(query, pipes); |
| margaretha | 35e1ca2 | 2023-11-16 22:00:01 +0100 | [diff] [blame] | 181 | |
| margaretha | 1d1c73e | 2019-12-03 18:07:28 +0100 | [diff] [blame] | 182 | query = this.rewriteHandler.processQuery(query, user); |
| margaretha | 35e1ca2 | 2023-11-16 22:00:01 +0100 | [diff] [blame] | 183 | if (DEBUG) { |
| margaretha | 79d738c | 2018-12-17 16:45:47 +0100 | [diff] [blame] | 184 | jlog.debug("the serialized query " + query); |
| 185 | } |
| margaretha | 20f3123 | 2018-07-09 17:49:39 +0200 | [diff] [blame] | 186 | |
| margaretha | 5a5b995 | 2023-06-12 12:46:36 +0200 | [diff] [blame] | 187 | int hashedKoralQuery = createTotalResultCacheKey(query); |
| 188 | boolean hasCutOff = hasCutOff(query); |
| margaretha | e6ebfbc | 2024-10-07 08:39:42 +0200 | [diff] [blame] | 189 | if (config.isTotalResultCacheEnabled() && !hasCutOff) { |
| margaretha | 35e1ca2 | 2023-11-16 22:00:01 +0100 | [diff] [blame] | 190 | query = precheckTotalResultCache(hashedKoralQuery, query); |
| margaretha | 5a5b995 | 2023-06-12 12:46:36 +0200 | [diff] [blame] | 191 | } |
| 192 | |
| margaretha | 35e1ca2 | 2023-11-16 22:00:01 +0100 | [diff] [blame] | 193 | KustvaktConfiguration.BACKENDS searchEngine = this.config |
| 194 | .chooseBackend(engine); |
| margaretha | 20f3123 | 2018-07-09 17:49:39 +0200 | [diff] [blame] | 195 | String result; |
| margaretha | 4dee07a | 2022-05-27 11:45:28 +0200 | [diff] [blame] | 196 | if (searchEngine.equals(KustvaktConfiguration.BACKENDS.NEO4J)) { |
| margaretha | 20f3123 | 2018-07-09 17:49:39 +0200 | [diff] [blame] | 197 | result = searchNeo4J(query, pageLength, meta, false); |
| 198 | } |
| margaretha | 4dee07a | 2022-05-27 11:45:28 +0200 | [diff] [blame] | 199 | else if (searchEngine.equals(KustvaktConfiguration.BACKENDS.NETWORK)) { |
| 200 | result = searchNetwork.search(query); |
| 201 | } |
| margaretha | 20f3123 | 2018-07-09 17:49:39 +0200 | [diff] [blame] | 202 | else { |
| 203 | result = searchKrill.search(query); |
| 204 | } |
| margaretha | 3495447 | 2018-10-24 20:05:17 +0200 | [diff] [blame] | 205 | // jlog.debug("Query result: " + result); |
| margaretha | 66061bb | 2025-06-23 11:11:18 +0200 | [diff] [blame] | 206 | |
| margaretha | e6ebfbc | 2024-10-07 08:39:42 +0200 | [diff] [blame] | 207 | if (config.isTotalResultCacheEnabled()) { |
| 208 | result = afterCheckTotalResultCache(hashedKoralQuery, result); |
| 209 | } |
| 210 | |
| margaretha | 5a5b995 | 2023-06-12 12:46:36 +0200 | [diff] [blame] | 211 | if (!hasCutOff) { |
| 212 | result = removeCutOff(result); |
| 213 | } |
| margaretha | 66061bb | 2025-06-23 11:11:18 +0200 | [diff] [blame] | 214 | |
| 215 | // Response pipe rewrite |
| 216 | result = runPipes(result, responsePipes); |
| margaretha | 20f3123 | 2018-07-09 17:49:39 +0200 | [diff] [blame] | 217 | return result; |
| 218 | |
| 219 | } |
| margaretha | 66061bb | 2025-06-23 11:11:18 +0200 | [diff] [blame] | 220 | |
| margaretha | 5a5b995 | 2023-06-12 12:46:36 +0200 | [diff] [blame] | 221 | private String removeCutOff (String result) throws KustvaktException { |
| 222 | ObjectNode resultNode = (ObjectNode) JsonUtils.readTree(result); |
| 223 | ObjectNode meta = (ObjectNode) resultNode.at("/meta"); |
| 224 | meta.remove("cutOff"); |
| 225 | return resultNode.toString(); |
| 226 | } |
| 227 | |
| margaretha | 35e1ca2 | 2023-11-16 22:00:01 +0100 | [diff] [blame] | 228 | public int createTotalResultCacheKey (String query) |
| 229 | throws KustvaktException { |
| margaretha | 5a5b995 | 2023-06-12 12:46:36 +0200 | [diff] [blame] | 230 | ObjectNode queryNode = (ObjectNode) JsonUtils.readTree(query); |
| 231 | queryNode.remove("meta"); |
| margaretha | e6ebfbc | 2024-10-07 08:39:42 +0200 | [diff] [blame] | 232 | return queryNode.toString().hashCode(); |
| margaretha | 5a5b995 | 2023-06-12 12:46:36 +0200 | [diff] [blame] | 233 | } |
| 234 | |
| 235 | private String afterCheckTotalResultCache (int hashedKoralQuery, |
| 236 | String result) throws KustvaktException { |
| margaretha | 35e1ca2 | 2023-11-16 22:00:01 +0100 | [diff] [blame] | 237 | |
| 238 | String totalResults = (String) totalResultCache |
| 239 | .getCacheValue(hashedKoralQuery); |
| margaretha | 5a5b995 | 2023-06-12 12:46:36 +0200 | [diff] [blame] | 240 | if (totalResults != null) { |
| 241 | ObjectNode queryNode = (ObjectNode) JsonUtils.readTree(result); |
| 242 | ObjectNode meta = (ObjectNode) queryNode.at("/meta"); |
| 243 | if (meta.isMissingNode()) { |
| Marc Kupietz | 824f204 | 2023-09-18 14:50:21 +0200 | [diff] [blame] | 244 | queryNode.put("totalResults", Integer.valueOf(totalResults)); |
| margaretha | 5a5b995 | 2023-06-12 12:46:36 +0200 | [diff] [blame] | 245 | } |
| 246 | else { |
| Marc Kupietz | 824f204 | 2023-09-18 14:50:21 +0200 | [diff] [blame] | 247 | meta.put("totalResults", Integer.valueOf(totalResults)); |
| margaretha | 5a5b995 | 2023-06-12 12:46:36 +0200 | [diff] [blame] | 248 | } |
| 249 | result = queryNode.toString(); |
| 250 | } |
| 251 | else { |
| 252 | JsonNode node = JsonUtils.readTree(result); |
| 253 | totalResults = node.at("/meta/totalResults").asText(); |
| margaretha | bf6b058 | 2024-10-24 09:43:49 +0200 | [diff] [blame] | 254 | boolean timeExceeded = node.at("/meta/timeExceeded").asBoolean(); |
| 255 | |
| 256 | if (!timeExceeded && totalResults != null && !totalResults.isEmpty() |
| margaretha | 35e1ca2 | 2023-11-16 22:00:01 +0100 | [diff] [blame] | 257 | && Integer.parseInt(totalResults) > 0) |
| margaretha | 5a5b995 | 2023-06-12 12:46:36 +0200 | [diff] [blame] | 258 | totalResultCache.storeInCache(hashedKoralQuery, totalResults); |
| 259 | } |
| 260 | return result; |
| 261 | } |
| 262 | |
| 263 | public String precheckTotalResultCache (int hashedKoralQuery, String query) |
| 264 | throws KustvaktException { |
| margaretha | 35e1ca2 | 2023-11-16 22:00:01 +0100 | [diff] [blame] | 265 | String totalResults = (String) totalResultCache |
| 266 | .getCacheValue(hashedKoralQuery); |
| margaretha | 5a5b995 | 2023-06-12 12:46:36 +0200 | [diff] [blame] | 267 | if (totalResults != null) { |
| 268 | // add cutoff |
| 269 | ObjectNode queryNode = (ObjectNode) JsonUtils.readTree(query); |
| 270 | ObjectNode meta = (ObjectNode) queryNode.at("/meta"); |
| 271 | meta.put("cutOff", "true"); |
| 272 | query = queryNode.toString(); |
| 273 | } |
| 274 | return query; |
| 275 | } |
| margaretha | 35e1ca2 | 2023-11-16 22:00:01 +0100 | [diff] [blame] | 276 | |
| margaretha | 5a5b995 | 2023-06-12 12:46:36 +0200 | [diff] [blame] | 277 | private boolean hasCutOff (String query) throws KustvaktException { |
| 278 | JsonNode queryNode = JsonUtils.readTree(query); |
| 279 | JsonNode cutOff = queryNode.at("/meta/cutOff"); |
| 280 | if (cutOff.isMissingNode()) { |
| 281 | return false; |
| 282 | } |
| 283 | else { |
| 284 | return true; |
| 285 | } |
| 286 | } |
| margaretha | 20f3123 | 2018-07-09 17:49:39 +0200 | [diff] [blame] | 287 | |
| margaretha | 137d4ee | 2019-12-13 14:49:15 +0100 | [diff] [blame] | 288 | /** |
| 289 | * Pipes are service URLs for modifying KoralQuery. A POST request |
| 290 | * with Content-Type application/json will be sent for each pipe. |
| margaretha | 35e1ca2 | 2023-11-16 22:00:01 +0100 | [diff] [blame] | 291 | * Kustvakt expects a KoralQuery in JSON format as the pipe |
| 292 | * response. |
| margaretha | 137d4ee | 2019-12-13 14:49:15 +0100 | [diff] [blame] | 293 | * |
| margaretha | 35e1ca2 | 2023-11-16 22:00:01 +0100 | [diff] [blame] | 294 | * @param query |
| 295 | * the original koral query |
| margaretha | 66061bb | 2025-06-23 11:11:18 +0200 | [diff] [blame] | 296 | * @param pipes |
| margaretha | 35e1ca2 | 2023-11-16 22:00:01 +0100 | [diff] [blame] | 297 | * the pipe service URLs |
| 298 | * @param serializer |
| 299 | * the query serializer |
| margaretha | 137d4ee | 2019-12-13 14:49:15 +0100 | [diff] [blame] | 300 | * @return a modified koral query |
| margaretha | 35e1ca2 | 2023-11-16 22:00:01 +0100 | [diff] [blame] | 301 | * @throws KustvaktException |
| margaretha | 137d4ee | 2019-12-13 14:49:15 +0100 | [diff] [blame] | 302 | */ |
| margaretha | 66061bb | 2025-06-23 11:11:18 +0200 | [diff] [blame] | 303 | private String runPipes (String query, String pipes) |
| margaretha | 35e1ca2 | 2023-11-16 22:00:01 +0100 | [diff] [blame] | 304 | throws KustvaktException { |
| margaretha | d0f3651 | 2025-07-04 11:06:10 +0200 | [diff] [blame] | 305 | if (config.getPipeHost().isEmpty()) { |
| 306 | addWarning(query, StatusCodes.NOT_SUPPORTED, |
| 307 | "Pipe is not supported."); |
| 308 | return query; |
| 309 | } |
| 310 | |
| margaretha | 66061bb | 2025-06-23 11:11:18 +0200 | [diff] [blame] | 311 | if (pipes != null && !pipes.isEmpty()) { |
| 312 | String[] pipeArray = pipes.split(","); |
| 313 | |
| margaretha | 35e1ca2 | 2023-11-16 22:00:01 +0100 | [diff] [blame] | 314 | for (int i = 0; i < pipeArray.length; i++) { |
| margaretha | 137d4ee | 2019-12-13 14:49:15 +0100 | [diff] [blame] | 315 | String pipeURL = pipeArray[i]; |
| margaretha | 66061bb | 2025-06-23 11:11:18 +0200 | [diff] [blame] | 316 | if (pipeURL.startsWith(config.getPipeHost())) { |
| 317 | try { |
| 318 | URL url = new URL(pipeURL); |
| 319 | HttpURLConnection connection = (HttpURLConnection) url |
| 320 | .openConnection(); |
| 321 | connection.setRequestMethod("POST"); |
| 322 | connection.setRequestProperty("Content-Type", |
| 323 | "application/json; charset=UTF-8"); |
| 324 | connection.setRequestProperty("Accept", "application/json"); |
| 325 | connection.setDoOutput(true); |
| 326 | OutputStream os = connection.getOutputStream(); |
| 327 | byte[] input = query.getBytes("utf-8"); |
| 328 | os.write(input, 0, input.length); |
| 329 | |
| 330 | String entity = null; |
| 331 | if (connection.getResponseCode() == HttpStatus.SC_OK) { |
| 332 | BufferedReader br = new BufferedReader( |
| 333 | new InputStreamReader( |
| 334 | connection.getInputStream(), "utf-8")); |
| 335 | StringBuilder response = new StringBuilder(); |
| 336 | String responseLine = null; |
| 337 | while ((responseLine = br.readLine()) != null) { |
| 338 | response.append(responseLine.trim()); |
| 339 | } |
| 340 | entity = response.toString(); |
| margaretha | 137d4ee | 2019-12-13 14:49:15 +0100 | [diff] [blame] | 341 | } |
| margaretha | 66061bb | 2025-06-23 11:11:18 +0200 | [diff] [blame] | 342 | |
| 343 | if (entity != null && !entity.isEmpty()) { |
| 344 | query = entity; |
| 345 | } |
| 346 | else { |
| 347 | query = handlePipeError(query, pipeURL, |
| 348 | connection.getResponseCode() + " " |
| 349 | + connection.getResponseMessage()); |
| 350 | } |
| margaretha | 0ddaed6 | 2021-01-21 17:10:33 +0100 | [diff] [blame] | 351 | } |
| margaretha | 66061bb | 2025-06-23 11:11:18 +0200 | [diff] [blame] | 352 | catch (Exception e) { |
| 353 | query = handlePipeError(query, pipeURL, e.getMessage()); |
| margaretha | 137d4ee | 2019-12-13 14:49:15 +0100 | [diff] [blame] | 354 | } |
| 355 | } |
| margaretha | 66061bb | 2025-06-23 11:11:18 +0200 | [diff] [blame] | 356 | else { |
| 357 | query = handlePipeError(query, pipeURL, |
| 358 | "Unrecognized pipe URL"); |
| margaretha | 137d4ee | 2019-12-13 14:49:15 +0100 | [diff] [blame] | 359 | } |
| margaretha | 1d1c73e | 2019-12-03 18:07:28 +0100 | [diff] [blame] | 360 | } |
| margaretha | 66061bb | 2025-06-23 11:11:18 +0200 | [diff] [blame] | 361 | } |
| margaretha | 1d1c73e | 2019-12-03 18:07:28 +0100 | [diff] [blame] | 362 | return query; |
| 363 | } |
| margaretha | 35e1ca2 | 2023-11-16 22:00:01 +0100 | [diff] [blame] | 364 | |
| 365 | private String handlePipeError (String query, String url, String message) |
| 366 | throws KustvaktException { |
| margaretha | 35e1ca2 | 2023-11-16 22:00:01 +0100 | [diff] [blame] | 367 | |
| margaretha | d0f3651 | 2025-07-04 11:06:10 +0200 | [diff] [blame] | 368 | query = addWarning(query, StatusCodes.PIPE_FAILED, "Pipe failed", url, message); |
| margaretha | 35e1ca2 | 2023-11-16 22:00:01 +0100 | [diff] [blame] | 369 | return query; |
| margaretha | 9c6493e | 2022-01-25 11:54:29 +0100 | [diff] [blame] | 370 | } |
| margaretha | 9c6493e | 2022-01-25 11:54:29 +0100 | [diff] [blame] | 371 | |
| margaretha | d0f3651 | 2025-07-04 11:06:10 +0200 | [diff] [blame] | 372 | private String addWarning (String query, int statusCode, |
| 373 | String warningMessage, String ... terms) throws KustvaktException { |
| 374 | Notifications n = new Notifications(); |
| 375 | n.addWarning(statusCode, warningMessage, terms); |
| 376 | JsonNode warning = n.toJsonNode(); |
| 377 | |
| margaretha | 66061bb | 2025-06-23 11:11:18 +0200 | [diff] [blame] | 378 | ObjectNode node = null; |
| 379 | try { |
| 380 | node = (ObjectNode) JsonUtils.readTree(query); |
| 381 | } |
| 382 | catch (Exception e) { |
| 383 | throw new KustvaktException(StatusCodes.DESERIALIZATION_FAILED, |
| 384 | "Invalid JSON format"); |
| 385 | } |
| margaretha | 35e1ca2 | 2023-11-16 22:00:01 +0100 | [diff] [blame] | 386 | if (node.has("warnings")) { |
| margaretha | 137d4ee | 2019-12-13 14:49:15 +0100 | [diff] [blame] | 387 | warning = warning.at("/warnings/0"); |
| 388 | ArrayNode arrayNode = (ArrayNode) node.get("warnings"); |
| 389 | arrayNode.add(warning); |
| 390 | node.set("warnings", arrayNode); |
| 391 | } |
| margaretha | 35e1ca2 | 2023-11-16 22:00:01 +0100 | [diff] [blame] | 392 | else { |
| margaretha | 137d4ee | 2019-12-13 14:49:15 +0100 | [diff] [blame] | 393 | node.setAll((ObjectNode) warning); |
| 394 | } |
| margaretha | 9c6493e | 2022-01-25 11:54:29 +0100 | [diff] [blame] | 395 | return node.toString(); |
| margaretha | 137d4ee | 2019-12-13 14:49:15 +0100 | [diff] [blame] | 396 | } |
| margaretha | 1d1c73e | 2019-12-03 18:07:28 +0100 | [diff] [blame] | 397 | |
| margaretha | 8596764 | 2019-11-13 13:35:33 +0100 | [diff] [blame] | 398 | private void handleNonPublicFields (List<String> fieldList, |
| 399 | boolean accessRewriteDisabled, QuerySerializer serializer) { |
| margaretha | 35e1ca2 | 2023-11-16 22:00:01 +0100 | [diff] [blame] | 400 | List<String> nonPublicFields = new ArrayList<>(); |
| margaretha | 8596764 | 2019-11-13 13:35:33 +0100 | [diff] [blame] | 401 | nonPublicFields.add("snippet"); |
| margaretha | 35e1ca2 | 2023-11-16 22:00:01 +0100 | [diff] [blame] | 402 | |
| margaretha | 8596764 | 2019-11-13 13:35:33 +0100 | [diff] [blame] | 403 | List<String> ignoredFields = new ArrayList<>(); |
| 404 | if (accessRewriteDisabled && !fieldList.isEmpty()) { |
| 405 | for (String field : fieldList) { |
| 406 | if (nonPublicFields.contains(field)) { |
| 407 | ignoredFields.add(field); |
| 408 | } |
| 409 | } |
| 410 | if (!ignoredFields.isEmpty()) { |
| 411 | serializer.addWarning(StatusCodes.NON_PUBLIC_FIELD_IGNORED, |
| 412 | "The requested non public fields are ignored", |
| 413 | ignoredFields); |
| 414 | } |
| 415 | } |
| 416 | } |
| margaretha | 35e1ca2 | 2023-11-16 22:00:01 +0100 | [diff] [blame] | 417 | |
| margaretha | 20f3123 | 2018-07-09 17:49:39 +0200 | [diff] [blame] | 418 | private MetaQueryBuilder createMetaQuery (Integer pageIndex, |
| margaretha | 35e1ca2 | 2023-11-16 22:00:01 +0100 | [diff] [blame] | 419 | Integer pageInteger, String ctx, Integer pageLength, Boolean cutoff, |
| 420 | CorpusAccess corpusAccess, List<String> fieldList, |
| 421 | boolean accessRewriteDisabled, boolean showTokens, |
| 422 | boolean showSnippet) { |
| margaretha | 20f3123 | 2018-07-09 17:49:39 +0200 | [diff] [blame] | 423 | MetaQueryBuilder meta = new MetaQueryBuilder(); |
| 424 | meta.addEntry("startIndex", pageIndex); |
| 425 | meta.addEntry("startPage", pageInteger); |
| 426 | meta.setSpanContext(ctx); |
| 427 | meta.addEntry("count", pageLength); |
| 428 | // todo: what happened to cutoff? |
| 429 | meta.addEntry("cutOff", cutoff); |
| margaretha | ac85ae1 | 2023-05-08 11:09:13 +0200 | [diff] [blame] | 430 | meta.addEntry("snippets", (showSnippet && !accessRewriteDisabled)); |
| margaretha | 9c6493e | 2022-01-25 11:54:29 +0100 | [diff] [blame] | 431 | if (!accessRewriteDisabled) { |
| 432 | meta.addEntry("tokens", showTokens); |
| 433 | } |
| margaretha | 35e1ca2 | 2023-11-16 22:00:01 +0100 | [diff] [blame] | 434 | |
| margaretha | 20f3123 | 2018-07-09 17:49:39 +0200 | [diff] [blame] | 435 | // meta.addMeta(pageIndex, pageInteger, pageLength, ctx, |
| 436 | // cutoff); |
| 437 | // fixme: should only apply to CQL queries per default! |
| 438 | // meta.addEntry("itemsPerResource", 1); |
| margaretha | 35e1ca2 | 2023-11-16 22:00:01 +0100 | [diff] [blame] | 439 | |
| 440 | if (corpusAccess.equals(CorpusAccess.FREE)) { |
| margaretha | 245198d | 2025-06-18 12:19:59 +0200 | [diff] [blame] | 441 | meta.addEntry("timeout", config.getGuestTimeout()); |
| margaretha | 79d738c | 2018-12-17 16:45:47 +0100 | [diff] [blame] | 442 | } |
| margaretha | 35e1ca2 | 2023-11-16 22:00:01 +0100 | [diff] [blame] | 443 | else { |
| margaretha | 245198d | 2025-06-18 12:19:59 +0200 | [diff] [blame] | 444 | meta.addEntry("timeout", config.getLoginTimeout()); |
| margaretha | 79d738c | 2018-12-17 16:45:47 +0100 | [diff] [blame] | 445 | } |
| margaretha | 35e1ca2 | 2023-11-16 22:00:01 +0100 | [diff] [blame] | 446 | |
| 447 | if (fieldList != null && !fieldList.isEmpty()) { |
| margaretha | a85965d | 2018-12-19 15:58:21 +0100 | [diff] [blame] | 448 | meta.addEntry("fields", fieldList); |
| 449 | } |
| margaretha | 20f3123 | 2018-07-09 17:49:39 +0200 | [diff] [blame] | 450 | return meta; |
| 451 | } |
| 452 | |
| margaretha | 852a0f6 | 2019-02-19 12:14:30 +0100 | [diff] [blame] | 453 | private List<String> convertFieldsToList (String fields) { |
| margaretha | 8596764 | 2019-11-13 13:35:33 +0100 | [diff] [blame] | 454 | if (fields != null && !fields.isEmpty()) { |
| 455 | String[] fieldArray = fields.split(","); |
| 456 | List<String> fieldList = new ArrayList<>(fieldArray.length); |
| 457 | for (String field : fieldArray) { |
| 458 | fieldList.add(field.trim()); |
| 459 | } |
| 460 | return fieldList; |
| margaretha | 852a0f6 | 2019-02-19 12:14:30 +0100 | [diff] [blame] | 461 | } |
| margaretha | 8596764 | 2019-11-13 13:35:33 +0100 | [diff] [blame] | 462 | else { |
| 463 | return new ArrayList<>(); |
| 464 | } |
| margaretha | 852a0f6 | 2019-02-19 12:14:30 +0100 | [diff] [blame] | 465 | } |
| margaretha | 35e1ca2 | 2023-11-16 22:00:01 +0100 | [diff] [blame] | 466 | |
| margaretha | 20f3123 | 2018-07-09 17:49:39 +0200 | [diff] [blame] | 467 | private String searchNeo4J (String query, int pageLength, |
| 468 | MetaQueryBuilder meta, boolean raw) throws KustvaktException { |
| 469 | |
| 470 | if (raw) { |
| 471 | throw new KustvaktException(StatusCodes.ILLEGAL_ARGUMENT, |
| 472 | "raw not supported!"); |
| 473 | } |
| 474 | |
| abcpro1 | d912a2c | 2022-11-07 17:10:50 +0000 | [diff] [blame] | 475 | MultivaluedMap<String, String> map = new MultivaluedHashMap<String, String>(); |
| margaretha | 20f3123 | 2018-07-09 17:49:39 +0200 | [diff] [blame] | 476 | map.add("q", query); |
| 477 | map.add("count", String.valueOf(pageLength)); |
| 478 | map.add("lctxs", String.valueOf(meta.getSpanContext().getLeftSize())); |
| 479 | map.add("rctxs", String.valueOf(meta.getSpanContext().getRightSize())); |
| 480 | return this.graphDBhandler.getResponse(map, "distKwic"); |
| 481 | |
| 482 | } |
| 483 | |
| margaretha | 351f769 | 2019-02-06 19:36:52 +0100 | [diff] [blame] | 484 | private Pattern determineAvailabilityPattern (User user) { |
| margaretha | 3495447 | 2018-10-24 20:05:17 +0200 | [diff] [blame] | 485 | Pattern p = null; |
| 486 | if (user != null) { |
| 487 | CorpusAccess corpusAccess = user.getCorpusAccess(); |
| 488 | switch (corpusAccess) { |
| 489 | case PUB: |
| 490 | p = config.getPublicLicensePattern(); |
| 491 | break; |
| 492 | case ALL: |
| 493 | p = config.getAllLicensePattern(); |
| 494 | break; |
| 495 | default: // FREE |
| 496 | p = config.getFreeLicensePattern(); |
| 497 | break; |
| 498 | } |
| margaretha | 20f3123 | 2018-07-09 17:49:39 +0200 | [diff] [blame] | 499 | } |
| margaretha | 351f769 | 2019-02-06 19:36:52 +0100 | [diff] [blame] | 500 | return p; |
| 501 | } |
| margaretha | 35e1ca2 | 2023-11-16 22:00:01 +0100 | [diff] [blame] | 502 | |
| 503 | public String retrieveMatchInfo (String corpusId, String docId, |
| 504 | String textId, String matchId, boolean info, Set<String> foundries, |
| 505 | String username, HttpHeaders headers, Set<String> layers, |
| 506 | boolean spans, boolean snippet, boolean tokens, |
| margaretha | c7f8f80 | 2024-06-05 12:52:45 +0200 | [diff] [blame] | 507 | boolean sentenceExpansion, boolean highlights, boolean isDeprecated) |
| margaretha | 35e1ca2 | 2023-11-16 22:00:01 +0100 | [diff] [blame] | 508 | throws KustvaktException { |
| 509 | String matchid = searchKrill.getMatchId(corpusId, docId, textId, |
| 510 | matchId); |
| margaretha | 351f769 | 2019-02-06 19:36:52 +0100 | [diff] [blame] | 511 | |
| 512 | User user = createUser(username, headers); |
| 513 | Pattern p = determineAvailabilityPattern(user); |
| Akron | 70e28ca | 2020-04-01 09:24:46 +0200 | [diff] [blame] | 514 | |
| margaretha | 35e1ca2 | 2023-11-16 22:00:01 +0100 | [diff] [blame] | 515 | // boolean match_only = foundries == null || foundries.isEmpty(); |
| margaretha | 20f3123 | 2018-07-09 17:49:39 +0200 | [diff] [blame] | 516 | String results; |
| margaretha | 35e1ca2 | 2023-11-16 22:00:01 +0100 | [diff] [blame] | 517 | // try { |
| margaretha | 20f3123 | 2018-07-09 17:49:39 +0200 | [diff] [blame] | 518 | |
| Akron | 17fbad7 | 2023-04-05 15:46:21 +0200 | [diff] [blame] | 519 | ArrayList<String> foundryList = null; |
| 520 | ArrayList<String> layerList = null; |
| margaretha | 20f3123 | 2018-07-09 17:49:39 +0200 | [diff] [blame] | 521 | |
| Akron | 17fbad7 | 2023-04-05 15:46:21 +0200 | [diff] [blame] | 522 | if (foundries != null && !foundries.isEmpty()) { |
| 523 | foundryList = new ArrayList<String>(); |
| 524 | layerList = new ArrayList<String>(); |
| 525 | // EM: now without user, just list all foundries and |
| 526 | // layers |
| 527 | if (foundries.contains("*")) { |
| 528 | foundryList = config.getFoundries(); |
| 529 | layerList = config.getLayers(); |
| margaretha | 20f3123 | 2018-07-09 17:49:39 +0200 | [diff] [blame] | 530 | } |
| 531 | else { |
| Akron | 17fbad7 | 2023-04-05 15:46:21 +0200 | [diff] [blame] | 532 | foundryList.addAll(foundries); |
| 533 | layerList.addAll(layers); |
| margaretha | 20f3123 | 2018-07-09 17:49:39 +0200 | [diff] [blame] | 534 | } |
| margaretha | 35e1ca2 | 2023-11-16 22:00:01 +0100 | [diff] [blame] | 535 | } |
| 536 | else { |
| Akron | 17fbad7 | 2023-04-05 15:46:21 +0200 | [diff] [blame] | 537 | sentenceExpansion = false; |
| 538 | spans = false; |
| 539 | info = false; |
| 540 | highlights = true; |
| 541 | }; |
| margaretha | 35e1ca2 | 2023-11-16 22:00:01 +0100 | [diff] [blame] | 542 | |
| 543 | results = searchKrill.getMatch(matchid, info, foundryList, layerList, |
| margaretha | c7f8f80 | 2024-06-05 12:52:45 +0200 | [diff] [blame] | 544 | spans, snippet, tokens, highlights, sentenceExpansion, p, isDeprecated); |
| margaretha | 35e1ca2 | 2023-11-16 22:00:01 +0100 | [diff] [blame] | 545 | // } |
| 546 | // catch (Exception e) { |
| 547 | // jlog.error("Exception in the MatchInfo service encountered!", e); |
| 548 | // throw new KustvaktException(StatusCodes.ILLEGAL_ARGUMENT, |
| 549 | // e.getMessage()); |
| 550 | // } |
| 551 | if (DEBUG) { |
| margaretha | a85965d | 2018-12-19 15:58:21 +0100 | [diff] [blame] | 552 | jlog.debug("MatchInfo results: " + results); |
| 553 | } |
| margaretha | 20f3123 | 2018-07-09 17:49:39 +0200 | [diff] [blame] | 554 | return results; |
| 555 | } |
| 556 | |
| 557 | public String retrieveDocMetadata (String corpusId, String docId, |
| margaretha | 852a0f6 | 2019-02-19 12:14:30 +0100 | [diff] [blame] | 558 | String textId, String fields, String username, HttpHeaders headers) |
| margaretha | 351f769 | 2019-02-06 19:36:52 +0100 | [diff] [blame] | 559 | throws KustvaktException { |
| margaretha | 852a0f6 | 2019-02-19 12:14:30 +0100 | [diff] [blame] | 560 | List<String> fieldList = null; |
| margaretha | 35e1ca2 | 2023-11-16 22:00:01 +0100 | [diff] [blame] | 561 | if (fields != null && !fields.isEmpty()) { |
| margaretha | 852a0f6 | 2019-02-19 12:14:30 +0100 | [diff] [blame] | 562 | fieldList = convertFieldsToList(fields); |
| 563 | } |
| 564 | Pattern p = null; |
| margaretha | 35e1ca2 | 2023-11-16 22:00:01 +0100 | [diff] [blame] | 565 | if (config.isMetadataRestricted()) { |
| margaretha | 852a0f6 | 2019-02-19 12:14:30 +0100 | [diff] [blame] | 566 | User user = createUser(username, headers); |
| 567 | p = determineAvailabilityPattern(user); |
| 568 | } |
| margaretha | 20f3123 | 2018-07-09 17:49:39 +0200 | [diff] [blame] | 569 | String textSigle = searchKrill.getTextSigle(corpusId, docId, textId); |
| margaretha | 852a0f6 | 2019-02-19 12:14:30 +0100 | [diff] [blame] | 570 | return searchKrill.getFields(textSigle, fieldList, p); |
| margaretha | 20f3123 | 2018-07-09 17:49:39 +0200 | [diff] [blame] | 571 | } |
| margaretha | 35e1ca2 | 2023-11-16 22:00:01 +0100 | [diff] [blame] | 572 | |
| margaretha | 20f3123 | 2018-07-09 17:49:39 +0200 | [diff] [blame] | 573 | public String getCollocationBase (String query) throws KustvaktException { |
| 574 | return graphDBhandler.getResponse("distCollo", "q", query); |
| 575 | } |
| margaretha | 35e1ca2 | 2023-11-16 22:00:01 +0100 | [diff] [blame] | 576 | |
| margaretha | 78f9080 | 2022-03-28 08:23:20 +0200 | [diff] [blame] | 577 | public void closeIndexReader () throws KustvaktException { |
| 578 | searchKrill.closeIndexReader(); |
| margaretha | 3d55b00 | 2019-03-19 12:00:44 +0100 | [diff] [blame] | 579 | } |
| Akron | 48e51b9 | 2020-06-02 14:50:27 +0200 | [diff] [blame] | 580 | |
| 581 | /** |
| 582 | * Return the fingerprint of the latest index revision. |
| 583 | */ |
| 584 | public String getIndexFingerprint () { |
| 585 | return searchKrill.getIndexFingerprint(); |
| 586 | } |
| margaretha | 35e1ca2 | 2023-11-16 22:00:01 +0100 | [diff] [blame] | 587 | |
| margaretha | 5a5b995 | 2023-06-12 12:46:36 +0200 | [diff] [blame] | 588 | public TotalResultCache getTotalResultCache () { |
| 589 | return totalResultCache; |
| 590 | } |
| margaretha | 20f3123 | 2018-07-09 17:49:39 +0200 | [diff] [blame] | 591 | } |