Search in sources :

Example 1 with MCRSetCondition

use of org.mycore.parsers.bool.MCRSetCondition in project mycore by MyCoRe-Org.

the class MCRQueryParser method normalizeCondition.

/**
 * Normalizes a parsed query condition. AND/OR conditions that just have one
 * child will be replaced with that child. NOT(NOT(X)) will be normalized to X.
 * (A AND (b AND c)) will be normalized to (A AND B AND C), same for nested ORs.
 * AND/OR/NOT conditions with no child conditions will be removed.
 * Conditions that use the operator "contains" will be splitted into multiple
 * simpler conditions if the condition value contains phrases surrounded
 * by '...' or wildcard search with * or ?.
 */
public static MCRCondition<Void> normalizeCondition(MCRCondition<Void> cond) {
    if (cond == null) {
        return null;
    } else if (cond instanceof MCRSetCondition) {
        MCRSetCondition<Void> sc = (MCRSetCondition<Void>) cond;
        List<MCRCondition<Void>> children = sc.getChildren();
        sc = sc instanceof MCRAndCondition ? new MCRAndCondition<>() : new MCROrCondition<>();
        for (MCRCondition<Void> child : children) {
            child = normalizeCondition(child);
            if (child == null) {
            } else if (child instanceof MCRSetCondition && sc.getOperator().equals(((MCRSetCondition) child).getOperator())) {
                // Replace (a AND (b AND c)) with (a AND b AND c), same for OR
                sc.addAll(((MCRSetCondition<Void>) child).getChildren());
            } else {
                sc.addChild(child);
            }
        }
        children = sc.getChildren();
        if (children.size() == 0) {
            // Completely remove empty AND condition
            return null;
        } else if (children.size() == 1) {
            // Replace AND with just one child
            return children.get(0);
        } else {
            return sc;
        }
    } else if (cond instanceof MCRNotCondition) {
        MCRNotCondition<Void> nc = (MCRNotCondition<Void>) cond;
        MCRCondition<Void> child = normalizeCondition(nc.getChild());
        if (child == null) {
            // Remove empty NOT
            return null;
        } else if (child instanceof MCRNotCondition) {
            return normalizeCondition(((MCRNotCondition<Void>) child).getChild());
        } else {
            return new MCRNotCondition<>(child);
        }
    } else if (cond instanceof MCRQueryCondition) {
        MCRQueryCondition qc = (MCRQueryCondition) cond;
        if (!qc.getOperator().equals("contains")) {
            return qc;
        }
        // Normalize value when contains operator is used
        List<String> values = new ArrayList<>();
        StringBuilder phrase = null;
        StringTokenizer st = new StringTokenizer(qc.getValue(), " ");
        while (st.hasMoreTokens()) {
            String value = st.nextToken();
            if (// we are within phrase
            phrase != null) {
                if (// end of phrase
                value.endsWith("'")) {
                    value = phrase + " " + value;
                    values.add(value);
                    phrase = null;
                } else // in middle of phrase
                {
                    phrase.append(' ').append(value);
                }
            } else if (// begin of phrase
            value.startsWith("'")) {
                if (// one-word phrase
                value.endsWith("'")) {
                    values.add(value.substring(1, value.length() - 1));
                } else {
                    phrase = new StringBuilder(value);
                }
            } else if (// begin of NOT phrase
            value.startsWith("-'")) {
                if (// one-word phrase
                value.endsWith("'")) {
                    values.add("-" + value.substring(2, value.length() - 1));
                } else {
                    phrase = new StringBuilder(value);
                }
            } else {
                values.add(value);
            }
        }
        MCRAndCondition<Void> ac = new MCRAndCondition<>();
        for (String value : values) {
            if (value.startsWith("'")) {
                ac.addChild(new MCRQueryCondition(qc.getFieldName(), "phrase", value.substring(1, value.length() - 1)));
            } else if (value.startsWith("-'")) {
                ac.addChild(new MCRNotCondition<>(new MCRQueryCondition(qc.getFieldName(), "phrase", value.substring(2, value.length() - 1))));
            } else if (value.contains("*") || value.contains("?")) {
                ac.addChild(new MCRQueryCondition(qc.getFieldName(), "like", value));
            } else if (// -word means "NOT word"
            value.startsWith("-")) {
                MCRCondition<Void> subCond = new MCRQueryCondition(qc.getFieldName(), "contains", value.substring(1));
                ac.addChild(new MCRNotCondition<>(subCond));
            } else {
                ac.addChild(new MCRQueryCondition(qc.getFieldName(), "contains", value));
            }
        }
        if (values.size() == 1) {
            return ac.getChildren().get(0);
        } else {
            return ac;
        }
    } else {
        return cond;
    }
}
Also used : MCRNotCondition(org.mycore.parsers.bool.MCRNotCondition) MCRSetCondition(org.mycore.parsers.bool.MCRSetCondition) MCRAndCondition(org.mycore.parsers.bool.MCRAndCondition) StringTokenizer(java.util.StringTokenizer) MCRCondition(org.mycore.parsers.bool.MCRCondition) ArrayList(java.util.ArrayList) List(java.util.List)

Example 2 with MCRSetCondition

use of org.mycore.parsers.bool.MCRSetCondition in project mycore by MyCoRe-Org.

the class MCRConditionTransformer method getIndex.

/**
 * Returns the ID of the index of all fields referenced in this condition.
 * If the fields come from multiple indexes, the constant mixed is returned.
 */
@SuppressWarnings("rawtypes")
private static String getIndex(MCRCondition cond) {
    if (cond instanceof MCRQueryCondition) {
        MCRQueryCondition queryCondition = ((MCRQueryCondition) cond);
        String fieldName = queryCondition.getFieldName();
        return getIndex(fieldName);
    } else if (cond instanceof MCRNotCondition) {
        return getIndex(((MCRNotCondition) cond).getChild());
    }
    @SuppressWarnings("unchecked") List<MCRCondition> children = ((MCRSetCondition) cond).getChildren();
    // mixed indexes here!
    return children.stream().map(MCRConditionTransformer::getIndex).reduce((l, r) -> l.equals(r) ? l : mixed).get();
}
Also used : MCRCondition(org.mycore.parsers.bool.MCRCondition) Iterator(java.util.Iterator) MCRAndCondition(org.mycore.parsers.bool.MCRAndCondition) Set(java.util.Set) HashMap(java.util.HashMap) MCRConfiguration(org.mycore.common.config.MCRConfiguration) Collectors(java.util.stream.Collectors) MCRException(org.mycore.common.MCRException) MCRQueryCondition(org.mycore.services.fieldquery.MCRQueryCondition) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) List(java.util.List) MCRSetCondition(org.mycore.parsers.bool.MCRSetCondition) Logger(org.apache.logging.log4j.Logger) MCRSortBy(org.mycore.services.fieldquery.MCRSortBy) MCRSolrConstants(org.mycore.solr.MCRSolrConstants) Map(java.util.Map) SolrQuery(org.apache.solr.client.solrj.SolrQuery) MCRSolrUtils(org.mycore.solr.MCRSolrUtils) ORDER(org.apache.solr.client.solrj.SolrQuery.ORDER) LogManager(org.apache.logging.log4j.LogManager) MCROrCondition(org.mycore.parsers.bool.MCROrCondition) SortClause(org.apache.solr.client.solrj.SolrQuery.SortClause) MCRNotCondition(org.mycore.parsers.bool.MCRNotCondition) MCRQueryCondition(org.mycore.services.fieldquery.MCRQueryCondition) MCRCondition(org.mycore.parsers.bool.MCRCondition) MCRNotCondition(org.mycore.parsers.bool.MCRNotCondition) MCRSetCondition(org.mycore.parsers.bool.MCRSetCondition)

Example 3 with MCRSetCondition

use of org.mycore.parsers.bool.MCRSetCondition in project mycore by MyCoRe-Org.

the class MCRQLSearchUtils method buildNameValueQuery.

/**
 * Search using name=value pairs from HTTP request
 */
@SuppressWarnings({ "rawtypes", "unchecked" })
public static MCRQuery buildNameValueQuery(HttpServletRequest req) {
    MCRAndCondition condition = new MCRAndCondition();
    for (Enumeration<String> names = req.getParameterNames(); names.hasMoreElements(); ) {
        String name = names.nextElement();
        if (name.endsWith(".operator")) {
            continue;
        }
        if (name.contains(".sortField")) {
            continue;
        }
        if (SEARCH_PARAMETER.contains(name)) {
            continue;
        }
        if (name.startsWith("XSL.")) {
            continue;
        }
        String[] values = req.getParameterValues(name);
        MCRSetCondition parent = condition;
        if ((values.length > 1) || name.contains(",")) {
            // Multiple fields with same name, combine with OR
            parent = new MCROrCondition();
            condition.addChild(parent);
        }
        for (String fieldName : name.split(",")) {
            String operator = getReqParameter(req, fieldName + ".operator", "=");
            for (String value : values) {
                parent.addChild(new MCRQueryCondition(fieldName, operator, value));
            }
        }
    }
    if (condition.getChildren().isEmpty()) {
        throw new MCRUsageException("Missing query condition");
    }
    return new MCRQuery(MCRQueryParser.normalizeCondition(condition));
}
Also used : MCRUsageException(org.mycore.common.MCRUsageException) MCRQueryCondition(org.mycore.services.fieldquery.MCRQueryCondition) MCROrCondition(org.mycore.parsers.bool.MCROrCondition) MCRQuery(org.mycore.services.fieldquery.MCRQuery) MCRSetCondition(org.mycore.parsers.bool.MCRSetCondition) MCRAndCondition(org.mycore.parsers.bool.MCRAndCondition)

Example 4 with MCRSetCondition

use of org.mycore.parsers.bool.MCRSetCondition in project mycore by MyCoRe-Org.

the class MCRConditionTransformer method groupConditionsByIndex.

/**
 * Build a table from index ID to a List of conditions referencing this
 * index
 */
@SuppressWarnings("rawtypes")
public static HashMap<String, List<MCRCondition>> groupConditionsByIndex(MCRSetCondition cond) {
    HashMap<String, List<MCRCondition>> table = new HashMap<>();
    @SuppressWarnings("unchecked") List<MCRCondition> children = cond.getChildren();
    for (MCRCondition child : children) {
        String index = getIndex(child);
        table.computeIfAbsent(index, k -> new ArrayList<>()).add(child);
    }
    return table;
}
Also used : MCRCondition(org.mycore.parsers.bool.MCRCondition) Iterator(java.util.Iterator) MCRAndCondition(org.mycore.parsers.bool.MCRAndCondition) Set(java.util.Set) HashMap(java.util.HashMap) MCRConfiguration(org.mycore.common.config.MCRConfiguration) Collectors(java.util.stream.Collectors) MCRException(org.mycore.common.MCRException) MCRQueryCondition(org.mycore.services.fieldquery.MCRQueryCondition) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) List(java.util.List) MCRSetCondition(org.mycore.parsers.bool.MCRSetCondition) Logger(org.apache.logging.log4j.Logger) MCRSortBy(org.mycore.services.fieldquery.MCRSortBy) MCRSolrConstants(org.mycore.solr.MCRSolrConstants) Map(java.util.Map) SolrQuery(org.apache.solr.client.solrj.SolrQuery) MCRSolrUtils(org.mycore.solr.MCRSolrUtils) ORDER(org.apache.solr.client.solrj.SolrQuery.ORDER) LogManager(org.apache.logging.log4j.LogManager) MCROrCondition(org.mycore.parsers.bool.MCROrCondition) SortClause(org.apache.solr.client.solrj.SolrQuery.SortClause) MCRNotCondition(org.mycore.parsers.bool.MCRNotCondition) MCRCondition(org.mycore.parsers.bool.MCRCondition) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) ArrayList(java.util.ArrayList) List(java.util.List)

Example 5 with MCRSetCondition

use of org.mycore.parsers.bool.MCRSetCondition in project mycore by MyCoRe-Org.

the class MCRQLSearchUtils method getSolrQuery.

@SuppressWarnings("rawtypes")
public static SolrQuery getSolrQuery(MCRQuery query, Document input, HttpServletRequest request) {
    int rows = Integer.parseInt(input.getRootElement().getAttributeValue("numPerPage", "10"));
    List<String> returnFields = query.getReturnFields();
    MCRCondition condition = query.getCondition();
    HashMap<String, List<MCRCondition>> table;
    if (condition instanceof MCRSetCondition) {
        table = MCRConditionTransformer.groupConditionsByIndex((MCRSetCondition) condition);
    } else {
        // if there is only one condition its no set condition. we don't need to group
        LOGGER.warn("Condition is not SetCondition.");
        table = new HashMap<>();
        ArrayList<MCRCondition> conditionList = new ArrayList<>();
        conditionList.add(condition);
        table.put("metadata", conditionList);
    }
    boolean booleanAnd = !(condition instanceof MCROrCondition<?>);
    SolrQuery mergedSolrQuery = MCRConditionTransformer.buildMergedSolrQuery(query.getSortBy(), false, booleanAnd, table, rows, returnFields);
    String mask = input.getRootElement().getAttributeValue("mask");
    if (mask != null) {
        mergedSolrQuery.setParam("mask", mask);
        mergedSolrQuery.setParam("_session", request.getParameter("_session"));
    }
    return mergedSolrQuery;
}
Also used : ArrayList(java.util.ArrayList) MCRSetCondition(org.mycore.parsers.bool.MCRSetCondition) SolrQuery(org.apache.solr.client.solrj.SolrQuery) MCRCondition(org.mycore.parsers.bool.MCRCondition) MCROrCondition(org.mycore.parsers.bool.MCROrCondition) ArrayList(java.util.ArrayList) List(java.util.List)

Aggregations

MCRSetCondition (org.mycore.parsers.bool.MCRSetCondition)5 ArrayList (java.util.ArrayList)4 List (java.util.List)4 MCRAndCondition (org.mycore.parsers.bool.MCRAndCondition)4 MCRCondition (org.mycore.parsers.bool.MCRCondition)4 MCROrCondition (org.mycore.parsers.bool.MCROrCondition)4 SolrQuery (org.apache.solr.client.solrj.SolrQuery)3 MCRNotCondition (org.mycore.parsers.bool.MCRNotCondition)3 MCRQueryCondition (org.mycore.services.fieldquery.MCRQueryCondition)3 HashMap (java.util.HashMap)2 HashSet (java.util.HashSet)2 Iterator (java.util.Iterator)2 Map (java.util.Map)2 Set (java.util.Set)2 Collectors (java.util.stream.Collectors)2 LogManager (org.apache.logging.log4j.LogManager)2 Logger (org.apache.logging.log4j.Logger)2 ORDER (org.apache.solr.client.solrj.SolrQuery.ORDER)2 SortClause (org.apache.solr.client.solrj.SolrQuery.SortClause)2 MCRException (org.mycore.common.MCRException)2