blob: 970efddec7daa834f102dafa62a86dda0a20d281 [file] [log] [blame]
package de.ids_mannheim.korap.rewrite;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
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.Attributes;
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.rewrite.KoralNode.RewriteIdentifier;
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;
/**
* CollectionRewrite 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 CollectionRewrite implements RewriteTask.RewriteQuery {
public static Logger jlog = LogManager.getLogger(CollectionRewrite.class);
public static boolean DEBUG = false;
public CollectionRewrite () {
super();
}
private List<String> checkAvailability (JsonNode node,
List<String> originalAvailabilities,
List<String> updatedAvailabilities, boolean isOperationOr) {
if (DEBUG) {
try {
jlog.debug(JsonUtils.toJSON(node));
}
catch (KustvaktException e) {
e.printStackTrace();
}
}
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++) {
updatedAvailabilities = checkAvailability(operands.get(i),
originalAvailabilities, updatedAvailabilities,
false);
if (updatedAvailabilities.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());
updatedAvailabilities.clear();
updatedAvailabilities.addAll(originalAvailabilities);
break;
}
else {
updatedAvailabilities = checkAvailability(
operands.get(i), originalAvailabilities,
updatedAvailabilities, 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 (originalAvailabilities.contains(queryAvailability)
&& matchOp.equals(KoralMatchOperator.EQUALS.toString())) {
if (DEBUG) {
jlog.debug("REMOVE " + queryAvailability);
}
updatedAvailabilities.remove(queryAvailability);
}
else if (isOperationOr) {
if (DEBUG) {
jlog.debug("RESET availabilities 2");
}
updatedAvailabilities.clear();
updatedAvailabilities.addAll(originalAvailabilities);
return updatedAvailabilities;
}
}
return updatedAvailabilities;
}
@Override
public KoralNode rewriteQuery (KoralNode node, KustvaktConfiguration config,
User user) throws KustvaktException {
JsonNode jsonNode = node.rawNode();
FullConfiguration fullConfig = (FullConfiguration) config;
List<String> userAvailabilities = new ArrayList<String>();
switch (user.getCorpusAccess()) {
case PUB:
userAvailabilities.addAll(fullConfig.getFreeRegexList());
userAvailabilities.addAll(fullConfig.getPublicRegexList());
break;
case ALL:
userAvailabilities.addAll(fullConfig.getFreeRegexList());
userAvailabilities.addAll(fullConfig.getPublicRegexList());
userAvailabilities.addAll(fullConfig.getAllRegexList());
break;
case FREE:
userAvailabilities.addAll(fullConfig.getFreeRegexList());
break;
}
KoralCollectionQueryBuilder builder = new KoralCollectionQueryBuilder();
RewriteIdentifier identifier = new KoralNode.RewriteIdentifier(
Attributes.AVAILABILITY, user.getCorpusAccess().name());
JsonNode rewrittenNode;
if (jsonNode.has("collection")) {
List<String> avalabilityCopy = new ArrayList<String>(
userAvailabilities.size());
avalabilityCopy.addAll(userAvailabilities);
if (DEBUG) {
jlog.debug("Availabilities: "
+ Arrays.toString(userAvailabilities.toArray()));
}
userAvailabilities = checkAvailability(jsonNode.at("/collection"),
avalabilityCopy, userAvailabilities, false);
if (!userAvailabilities.isEmpty()) {
builder.with(buildAvailability(avalabilityCopy));
if (DEBUG) {
jlog.debug("corpus query: " + builder.toString());
}
builder.setBaseQuery(builder.toJSON());
rewrittenNode = builder.mergeWith(jsonNode).at("/collection");
node.set("collection", rewrittenNode, identifier);
}
}
else {
builder.with(buildAvailability(userAvailabilities));
if (DEBUG) {
jlog.debug("corpus query: " + builder.toString());
}
rewrittenNode = JsonUtils.readTree(builder.toJSON())
.at("/collection");
node.set("collection", rewrittenNode, identifier);
}
node = node.at("/collection");
if (DEBUG) {
jlog.debug("REWRITES: " + node.toString());
}
return node;
}
private String buildAvailability (List<String> userAvailabilities) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < userAvailabilities.size(); i++) {
parseAvailability(sb, userAvailabilities.get(i), "|");
}
String availabilities = sb.toString();
return availabilities.substring(0, availabilities.length() - 3);
}
private void parseAvailability (StringBuilder sb, String availability,
String operator) {
String uaArr[] = null;
if (availability.contains("|")) {
uaArr = availability.split("\\|");
for (int j = 0; j < uaArr.length; j++) {
parseAvailability(sb, uaArr[j].trim(), "|");
}
}
// EM: not supported
// else if (availability.contains("&")){
// uaArr = availability.split("&");
// for (int j=0; j < uaArr.length -1; j++){
// parseAvailability(sb, uaArr[j], "&");
// }
// parseAvailability(sb, uaArr[uaArr.length-1], "|");
// }
else {
sb.append("availability=/");
sb.append(availability);
sb.append("/ ");
sb.append(operator);
sb.append(" ");
}
}
}