Search in sources :

Example 1 with MCRNotCondition

use of org.mycore.parsers.bool.MCRNotCondition 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 MCRNotCondition

use of org.mycore.parsers.bool.MCRNotCondition 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 MCRNotCondition

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

the class MCRConditionTransformerTest method testToSolrQueryString.

@Test
public final void testToSolrQueryString() {
    HashSet<String> usedFields = new HashSet<>();
    MCRQueryCondition inner1 = new MCRQueryCondition("objectType", "=", "mods");
    assertEquals("+objectType:\"mods\"", MCRConditionTransformer.toSolrQueryString(inner1, usedFields));
    assertTrue("usedFields did not contain 'objectType'", usedFields.contains("objectType"));
    MCRQueryCondition inner2 = new MCRQueryCondition("objectType", "=", "cbu");
    MCROrCondition<Void> orCond = new MCROrCondition<>(inner1, inner2);
    usedFields.clear();
    // MCR-973 check for surrounding brackets on single OR query
    assertEquals("+(objectType:\"mods\" objectType:\"cbu\")", MCRConditionTransformer.toSolrQueryString(orCond, usedFields));
    assertTrue("usedFields did not contain 'objectType'", usedFields.contains("objectType"));
    MCRQueryCondition inner3 = new MCRQueryCondition("derCount", ">", "0");
    MCRAndCondition<Void> andCondition = new MCRAndCondition<>(orCond, inner3);
    usedFields.clear();
    assertEquals("+(objectType:\"mods\" objectType:\"cbu\") +derCount:{0 TO *]", MCRConditionTransformer.toSolrQueryString(andCondition, usedFields));
    assertTrue("usedFields did not contain 'objectType'", usedFields.contains("objectType"));
    assertTrue("usedFields did not contain 'derCount'", usedFields.contains("derCount"));
    inner3.setOperator(">=");
    assertEquals("+(objectType:\"mods\" objectType:\"cbu\") +derCount:[0 TO *]", MCRConditionTransformer.toSolrQueryString(andCondition, usedFields));
    inner3.setOperator("<");
    assertEquals("+(objectType:\"mods\" objectType:\"cbu\") +derCount:[* TO 0}", MCRConditionTransformer.toSolrQueryString(andCondition, usedFields));
    inner3.setOperator("<=");
    assertEquals("+(objectType:\"mods\" objectType:\"cbu\") +derCount:[* TO 0]", MCRConditionTransformer.toSolrQueryString(andCondition, usedFields));
    MCRNotCondition<Void> notCond = new MCRNotCondition<>(orCond);
    andCondition.getChildren().remove(0);
    andCondition.getChildren().add(0, notCond);
    assertEquals("-(objectType:\"mods\" objectType:\"cbu\") +derCount:[* TO 0]", MCRConditionTransformer.toSolrQueryString(andCondition, usedFields));
}
Also used : MCRQueryCondition(org.mycore.services.fieldquery.MCRQueryCondition) MCROrCondition(org.mycore.parsers.bool.MCROrCondition) MCRNotCondition(org.mycore.parsers.bool.MCRNotCondition) MCRAndCondition(org.mycore.parsers.bool.MCRAndCondition) HashSet(java.util.HashSet) Test(org.junit.Test)

Aggregations

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