| package de.ids_mannheim.korap.rewrite; |
| |
| import java.util.ArrayList; |
| import java.util.List; |
| |
| import org.apache.commons.text.CaseUtils; |
| import org.apache.logging.log4j.LogManager; |
| import org.apache.logging.log4j.Logger; |
| |
| import com.fasterxml.jackson.databind.JsonNode; |
| import com.google.common.collect.Lists; |
| |
| import de.ids_mannheim.korap.config.FullConfiguration; |
| import de.ids_mannheim.korap.config.KustvaktConfiguration; |
| import de.ids_mannheim.korap.exceptions.KustvaktException; |
| import de.ids_mannheim.korap.query.object.KoralMatchOperator; |
| import de.ids_mannheim.korap.query.object.KoralOperation; |
| import de.ids_mannheim.korap.user.User; |
| import de.ids_mannheim.korap.user.User.CorpusAccess; |
| import de.ids_mannheim.korap.utils.JsonUtils; |
| import de.ids_mannheim.korap.utils.KoralCollectionQueryBuilder; |
| |
| /** |
| * AvailabilityRewrite determines which availability field values are |
| * possible for a user with respect to login and location of access. |
| * |
| * <br/><br/> |
| * KorAP differentiates 3 kinds of access: |
| * <ul> |
| * <li>FREE: without login</li> |
| * <li>PUB: login outside IDS network</li> |
| * <li>ALL: login within IDS network</li> |
| * </ul> |
| * |
| * Each of these accesses corresponds to a regular expression of |
| * license formats defined in kustvakt.conf. For a given access, only those |
| * resources whose availability field matches its regular expression |
| * are allowed to be retrieved. |
| * |
| * |
| * @author margaretha |
| * @see CorpusAccess |
| */ |
| public class AvailabilityRewrite implements RewriteTask.RewriteQuery { |
| |
| public static Logger jlog = LogManager.getLogger(AvailabilityRewrite.class); |
| |
| public AvailabilityRewrite () { |
| super(); |
| } |
| |
| private List<String> checkAvailability (JsonNode node, |
| List<String> availabilityRules, |
| List<String> actualAvailabilities, boolean isOperationOr) { |
| |
| if (node.has("operands")) { |
| ArrayList<JsonNode> operands = Lists |
| .newArrayList(node.at("/operands").elements()); |
| |
| if (node.at("/operation").asText() |
| .equals(KoralOperation.AND.toString())) { |
| for (int i = 0; i < operands.size(); i++) { |
| actualAvailabilities = checkAvailability(operands.get(i), |
| availabilityRules, actualAvailabilities, |
| false); |
| if (actualAvailabilities.isEmpty()) |
| break; |
| } |
| } |
| else { |
| for (int i = 0; i < operands.size(); i++) { |
| node = operands.get(i); |
| if (node.has("key") && !node.at("/key").asText() |
| .equals("availability")) { |
| jlog.debug("RESET availabilities 1, key=" |
| + node.at("/key").asText()); |
| actualAvailabilities.clear(); |
| actualAvailabilities.addAll(availabilityRules); |
| break; |
| } |
| else { |
| actualAvailabilities = checkAvailability( |
| operands.get(i), availabilityRules, |
| actualAvailabilities, true); |
| } |
| } |
| } |
| } |
| else if (node.has("key") |
| && node.at("/key").asText().equals("availability")) { |
| String queryAvailability = node.at("/value").asText(); |
| String matchOp = node.at("/match").asText(); |
| |
| if (availabilityRules.contains(queryAvailability) |
| && matchOp.equals(KoralMatchOperator.EQUALS.toString())) { |
| actualAvailabilities.remove(queryAvailability); |
| } |
| else if (isOperationOr) { |
| actualAvailabilities.clear(); |
| actualAvailabilities.addAll(availabilityRules); |
| return actualAvailabilities; |
| } |
| } |
| return actualAvailabilities; |
| } |
| |
| @Override |
| public KoralNode rewriteQuery (KoralNode koralNode, KustvaktConfiguration config, |
| User user) throws KustvaktException { |
| JsonNode jsonNode = koralNode.rawNode(); |
| |
| FullConfiguration fullConfig = (FullConfiguration) config; |
| CorpusAccess corpusAccess = user.getCorpusAccess(); |
| String corpusAccessName = user.accesstoString(); |
| List<String> availabilityRules = getAvailabilityRules(corpusAccess, |
| fullConfig); |
| |
| String availabilityQuery = getCorpusQuery(corpusAccess, fullConfig); |
| |
| if (jsonNode.has("collection")) { |
| if (jsonNode.toString().contains("availability")) { |
| List<String> actualAvalability = new ArrayList<>(); |
| actualAvalability.addAll(availabilityRules); |
| |
| actualAvalability = checkAvailability(jsonNode.at("/collection"), |
| availabilityRules, actualAvalability, false); |
| if (!actualAvalability.isEmpty()) { |
| createOperationAnd(availabilityQuery, jsonNode, |
| corpusAccessName, koralNode); |
| |
| // builder.with(availabilityQuery); |
| // builder.setBaseQuery(builder.toJSON()); |
| // rewrittenNode = builder.mergeWith(jsonNode).at("/collection"); |
| // koralNode.set("collection", rewrittenNode, identifier); |
| } |
| } |
| else { |
| createOperationAnd(availabilityQuery, jsonNode, |
| corpusAccessName, koralNode); |
| } |
| } |
| else { |
| KoralCollectionQueryBuilder builder = |
| new KoralCollectionQueryBuilder(); |
| builder.with(availabilityQuery); |
| JsonNode rewrittenNode = JsonUtils.readTree(builder.toJSON()) |
| .at("/collection"); |
| |
| RewriteIdentifier identifier = new RewriteIdentifier(null, null, |
| corpusAccessName + " corpus access policy has been added."); |
| koralNode.set("collection", rewrittenNode, identifier); |
| } |
| |
| koralNode = koralNode.at("/collection"); |
| return koralNode; |
| } |
| |
| private void createOperationAnd (String availabilityQuery, |
| JsonNode jsonNode, String corpusAccessName, KoralNode node) |
| throws KustvaktException { |
| |
| KoralCollectionQueryBuilder availabilityBuilder = |
| new KoralCollectionQueryBuilder(); |
| availabilityBuilder.with(availabilityQuery); |
| JsonNode availabilityNode = JsonUtils |
| .readTree(availabilityBuilder.toJSON()); |
| |
| String source = jsonNode.at("/collection").toString(); |
| JsonNode sourceNode = JsonUtils.readTree(source); |
| |
| KoralCollectionQueryBuilder builder = new KoralCollectionQueryBuilder(); |
| // Base query must contains collection |
| builder.setBaseQuery(availabilityNode); |
| JsonNode rewrittenNode = builder.mergeWith(jsonNode).at("/collection"); |
| RewriteIdentifier identifier = new RewriteIdentifier(null, sourceNode, |
| corpusAccessName + " corpus access policy has been added."); |
| node.replace("collection", rewrittenNode, identifier); |
| } |
| |
| private List<String> getAvailabilityRules (CorpusAccess access, |
| FullConfiguration fullConfig) { |
| switch (access) { |
| case PUB: |
| return fullConfig.getPublicRegexList(); |
| case ALL: |
| return fullConfig.getAllRegexList(); |
| default: // free |
| return fullConfig.getFreeRegexList(); |
| } |
| } |
| |
| private String getCorpusQuery (CorpusAccess access, |
| FullConfiguration fullConfig) { |
| switch (access) { |
| case PUB: |
| return fullConfig.getPublicAvailabilityQuery(); |
| case ALL: |
| return fullConfig.getAllAvailabilityQuery(); |
| default: // free |
| return fullConfig.getFreeAvailabilityQuery(); |
| } |
| |
| } |
| } |