blob: 934efd0dbcde7b3b8e800e8968a9ba0494289cb5 [file] [log] [blame]
margaretha56e8e552017-12-05 16:31:21 +01001package de.ids_mannheim.korap.rewrite;
margarethadc731922017-05-22 17:20:42 +02002
margaretha416e7872017-06-20 15:05:17 +02003import java.util.ArrayList;
4import java.util.List;
margaretha416e7872017-06-20 15:05:17 +02005
margaretha8489f862025-02-05 11:32:16 +01006import org.apache.commons.text.CaseUtils;
margaretha49cb6882018-07-04 04:19:54 +02007import org.apache.logging.log4j.LogManager;
8import org.apache.logging.log4j.Logger;
margarethadc731922017-05-22 17:20:42 +02009
10import com.fasterxml.jackson.databind.JsonNode;
margaretha416e7872017-06-20 15:05:17 +020011import com.google.common.collect.Lists;
margarethadc731922017-05-22 17:20:42 +020012
margaretha56e8e552017-12-05 16:31:21 +010013import de.ids_mannheim.korap.config.FullConfiguration;
margaretha1bc9cca2018-12-11 15:09:44 +010014import de.ids_mannheim.korap.config.KustvaktConfiguration;
margarethadc731922017-05-22 17:20:42 +020015import de.ids_mannheim.korap.exceptions.KustvaktException;
margaretha416e7872017-06-20 15:05:17 +020016import de.ids_mannheim.korap.query.object.KoralMatchOperator;
margarethaed7bc7a2017-11-12 21:39:41 +010017import de.ids_mannheim.korap.query.object.KoralOperation;
margarethadc731922017-05-22 17:20:42 +020018import de.ids_mannheim.korap.user.User;
margarethabb486302017-11-21 13:47:22 +010019import de.ids_mannheim.korap.user.User.CorpusAccess;
margarethadc731922017-05-22 17:20:42 +020020import de.ids_mannheim.korap.utils.JsonUtils;
21import de.ids_mannheim.korap.utils.KoralCollectionQueryBuilder;
22
margaretha35e1ca22023-11-16 22:00:01 +010023/**
margarethac105e2f2024-12-19 09:55:46 +010024 * AvailabilityRewrite determines which availability field values are
margaretha9d820462024-11-25 16:11:57 +010025 * possible for a user with respect to login and location of access.
margaretha35e1ca22023-11-16 22:00:01 +010026 *
27 * <br/><br/>
28 * KorAP differentiates 3 kinds of access:
29 * <ul>
30 * <li>FREE: without login</li>
31 * <li>PUB: login outside IDS network</li>
32 * <li>ALL: login within IDS network</li>
33 * </ul>
34 *
35 * Each of these accesses corresponds to a regular expression of
margaretha9d820462024-11-25 16:11:57 +010036 * license formats defined in kustvakt.conf. For a given access, only those
margaretha35e1ca22023-11-16 22:00:01 +010037 * resources whose availability field matches its regular expression
38 * are allowed to be retrieved.
39 *
40 *
margarethadc731922017-05-22 17:20:42 +020041 * @author margaretha
margarethabb486302017-11-21 13:47:22 +010042 * @see CorpusAccess
margarethadc731922017-05-22 17:20:42 +020043 */
margarethac105e2f2024-12-19 09:55:46 +010044public class AvailabilityRewrite implements RewriteTask.RewriteQuery {
margarethadc731922017-05-22 17:20:42 +020045
margarethac105e2f2024-12-19 09:55:46 +010046 public static Logger jlog = LogManager.getLogger(AvailabilityRewrite.class);
margarethadc731922017-05-22 17:20:42 +020047
margarethac105e2f2024-12-19 09:55:46 +010048 public AvailabilityRewrite () {
margarethaa89c3f92017-05-30 19:02:08 +020049 super();
50 }
margarethadc731922017-05-22 17:20:42 +020051
margarethabb486302017-11-21 13:47:22 +010052 private List<String> checkAvailability (JsonNode node,
margarethad9e43ec2024-12-20 12:11:43 +010053 List<String> availabilityRules,
54 List<String> actualAvailabilities, boolean isOperationOr) {
margarethabb486302017-11-21 13:47:22 +010055
56 if (node.has("operands")) {
margaretha35e1ca22023-11-16 22:00:01 +010057 ArrayList<JsonNode> operands = Lists
58 .newArrayList(node.at("/operands").elements());
margarethabb486302017-11-21 13:47:22 +010059
60 if (node.at("/operation").asText()
61 .equals(KoralOperation.AND.toString())) {
62 for (int i = 0; i < operands.size(); i++) {
margarethad9e43ec2024-12-20 12:11:43 +010063 actualAvailabilities = checkAvailability(operands.get(i),
64 availabilityRules, actualAvailabilities,
margarethabb486302017-11-21 13:47:22 +010065 false);
margarethad9e43ec2024-12-20 12:11:43 +010066 if (actualAvailabilities.isEmpty())
margaretha35e1ca22023-11-16 22:00:01 +010067 break;
margarethabb486302017-11-21 13:47:22 +010068 }
69 }
70 else {
71 for (int i = 0; i < operands.size(); i++) {
margarethade92c202018-02-20 14:38:40 +010072 node = operands.get(i);
73 if (node.has("key") && !node.at("/key").asText()
74 .equals("availability")) {
75 jlog.debug("RESET availabilities 1, key="
76 + node.at("/key").asText());
margarethad9e43ec2024-12-20 12:11:43 +010077 actualAvailabilities.clear();
78 actualAvailabilities.addAll(availabilityRules);
margarethade92c202018-02-20 14:38:40 +010079 break;
80 }
81 else {
margarethad9e43ec2024-12-20 12:11:43 +010082 actualAvailabilities = checkAvailability(
83 operands.get(i), availabilityRules,
84 actualAvailabilities, true);
margarethade92c202018-02-20 14:38:40 +010085 }
margarethabb486302017-11-21 13:47:22 +010086 }
margaretha416e7872017-06-20 15:05:17 +020087 }
88 }
89 else if (node.has("key")
90 && node.at("/key").asText().equals("availability")) {
91 String queryAvailability = node.at("/value").asText();
92 String matchOp = node.at("/match").asText();
margarethade92c202018-02-20 14:38:40 +010093
margarethad9e43ec2024-12-20 12:11:43 +010094 if (availabilityRules.contains(queryAvailability)
margarethabb486302017-11-21 13:47:22 +010095 && matchOp.equals(KoralMatchOperator.EQUALS.toString())) {
margarethad9e43ec2024-12-20 12:11:43 +010096 actualAvailabilities.remove(queryAvailability);
margarethabb486302017-11-21 13:47:22 +010097 }
98 else if (isOperationOr) {
margarethad9e43ec2024-12-20 12:11:43 +010099 actualAvailabilities.clear();
100 actualAvailabilities.addAll(availabilityRules);
101 return actualAvailabilities;
margaretha416e7872017-06-20 15:05:17 +0200102 }
103 }
margarethad9e43ec2024-12-20 12:11:43 +0100104 return actualAvailabilities;
margaretha416e7872017-06-20 15:05:17 +0200105 }
margarethadc731922017-05-22 17:20:42 +0200106
margarethaa89c3f92017-05-30 19:02:08 +0200107 @Override
margarethad9e43ec2024-12-20 12:11:43 +0100108 public KoralNode rewriteQuery (KoralNode koralNode, KustvaktConfiguration config,
margarethaa89c3f92017-05-30 19:02:08 +0200109 User user) throws KustvaktException {
margarethad9e43ec2024-12-20 12:11:43 +0100110 JsonNode jsonNode = koralNode.rawNode();
margarethade92c202018-02-20 14:38:40 +0100111
margaretha56e8e552017-12-05 16:31:21 +0100112 FullConfiguration fullConfig = (FullConfiguration) config;
margarethad9e43ec2024-12-20 12:11:43 +0100113 CorpusAccess corpusAccess = user.getCorpusAccess();
margaretha8489f862025-02-05 11:32:16 +0100114 String corpusAccessName = user.accesstoString();
margarethad9e43ec2024-12-20 12:11:43 +0100115 List<String> availabilityRules = getAvailabilityRules(corpusAccess,
116 fullConfig);
margarethabb486302017-11-21 13:47:22 +0100117
margarethad9e43ec2024-12-20 12:11:43 +0100118 String availabilityQuery = getCorpusQuery(corpusAccess, fullConfig);
119
margarethaa89c3f92017-05-30 19:02:08 +0200120 if (jsonNode.has("collection")) {
margarethad9e43ec2024-12-20 12:11:43 +0100121 if (jsonNode.toString().contains("availability")) {
122 List<String> actualAvalability = new ArrayList<>();
123 actualAvalability.addAll(availabilityRules);
margarethabb486302017-11-21 13:47:22 +0100124
margarethad9e43ec2024-12-20 12:11:43 +0100125 actualAvalability = checkAvailability(jsonNode.at("/collection"),
126 availabilityRules, actualAvalability, false);
127 if (!actualAvalability.isEmpty()) {
128 createOperationAnd(availabilityQuery, jsonNode,
margaretha8489f862025-02-05 11:32:16 +0100129 corpusAccessName, koralNode);
margarethad9e43ec2024-12-20 12:11:43 +0100130
131// builder.with(availabilityQuery);
132// builder.setBaseQuery(builder.toJSON());
133// rewrittenNode = builder.mergeWith(jsonNode).at("/collection");
134// koralNode.set("collection", rewrittenNode, identifier);
margarethad6f39d52018-12-06 14:21:39 +0100135 }
margarethad9e43ec2024-12-20 12:11:43 +0100136 }
137 else {
138 createOperationAnd(availabilityQuery, jsonNode,
margaretha8489f862025-02-05 11:32:16 +0100139 corpusAccessName, koralNode);
margarethad9e43ec2024-12-20 12:11:43 +0100140 }
margarethaa89c3f92017-05-30 19:02:08 +0200141 }
margarethad9e43ec2024-12-20 12:11:43 +0100142 else {
143 KoralCollectionQueryBuilder builder =
144 new KoralCollectionQueryBuilder();
145 builder.with(availabilityQuery);
146 JsonNode rewrittenNode = JsonUtils.readTree(builder.toJSON())
147 .at("/collection");
margaretha8489f862025-02-05 11:32:16 +0100148
149 RewriteIdentifier identifier = new RewriteIdentifier(null, null,
150 corpusAccessName + " corpus access policy has been added.");
margarethad9e43ec2024-12-20 12:11:43 +0100151 koralNode.set("collection", rewrittenNode, identifier);
152 }
margarethaa89c3f92017-05-30 19:02:08 +0200153
margarethad9e43ec2024-12-20 12:11:43 +0100154 koralNode = koralNode.at("/collection");
155 return koralNode;
margarethaa89c3f92017-05-30 19:02:08 +0200156 }
margarethad9e43ec2024-12-20 12:11:43 +0100157
158 private void createOperationAnd (String availabilityQuery,
margaretha8489f862025-02-05 11:32:16 +0100159 JsonNode jsonNode, String corpusAccessName, KoralNode node)
margarethad9e43ec2024-12-20 12:11:43 +0100160 throws KustvaktException {
margarethabb486302017-11-21 13:47:22 +0100161
margarethad9e43ec2024-12-20 12:11:43 +0100162 KoralCollectionQueryBuilder availabilityBuilder =
163 new KoralCollectionQueryBuilder();
164 availabilityBuilder.with(availabilityQuery);
165 JsonNode availabilityNode = JsonUtils
166 .readTree(availabilityBuilder.toJSON());
margarethade92c202018-02-20 14:38:40 +0100167
margarethad9e43ec2024-12-20 12:11:43 +0100168 String source = jsonNode.at("/collection").toString();
169 JsonNode sourceNode = JsonUtils.readTree(source);
margarethaad618d22017-12-11 19:58:49 +0100170
margarethad9e43ec2024-12-20 12:11:43 +0100171 KoralCollectionQueryBuilder builder = new KoralCollectionQueryBuilder();
172 // Base query must contains collection
173 builder.setBaseQuery(availabilityNode);
174 JsonNode rewrittenNode = builder.mergeWith(jsonNode).at("/collection");
margaretha8489f862025-02-05 11:32:16 +0100175 RewriteIdentifier identifier = new RewriteIdentifier(null, sourceNode,
176 corpusAccessName + " corpus access policy has been added.");
margarethad9e43ec2024-12-20 12:11:43 +0100177 node.replace("collection", rewrittenNode, identifier);
178 }
179
180 private List<String> getAvailabilityRules (CorpusAccess access,
181 FullConfiguration fullConfig) {
182 switch (access) {
183 case PUB:
184 return fullConfig.getPublicRegexList();
185 case ALL:
186 return fullConfig.getAllRegexList();
187 default: // free
188 return fullConfig.getFreeRegexList();
189 }
190 }
margarethade92c202018-02-20 14:38:40 +0100191
margarethad9e43ec2024-12-20 12:11:43 +0100192 private String getCorpusQuery (CorpusAccess access,
193 FullConfiguration fullConfig) {
194 switch (access) {
195 case PUB:
196 return fullConfig.getPublicAvailabilityQuery();
197 case ALL:
198 return fullConfig.getAllAvailabilityQuery();
199 default: // free
200 return fullConfig.getFreeAvailabilityQuery();
201 }
202
203 }
margarethadc731922017-05-22 17:20:42 +0200204}