FilterQueryParser { static SolrQuery getQuery(Filter filter, QueryIndex.IndexPlan plan, OakSolrConfiguration configuration) { SolrQuery solrQuery = new SolrQuery(); setDefaults(solrQuery, configuration); StringBuilder queryBuilder = new StringBuilder(); FullTextExpression ft = filter.getFullTextConstraint(); if (ft != null) { queryBuilder.append(parseFullTextExpression(ft, configuration)); queryBuilder.append(' '); } else if (filter.getFulltextConditions() != null) { Collection<String> fulltextConditions = filter.getFulltextConditions(); for (String fulltextCondition : fulltextConditions) { queryBuilder.append(fulltextCondition).append(" "); } } if (plan != null && plan.getSortOrder() != null) { List<QueryIndex.OrderEntry> sortOrder = plan.getSortOrder(); for (QueryIndex.OrderEntry orderEntry : sortOrder) { SolrQuery.ORDER order; if (QueryIndex.OrderEntry.Order.ASCENDING.equals(orderEntry.getOrder())) { order = SolrQuery.ORDER.asc; } else { order = SolrQuery.ORDER.desc; } String sortingField; if (JcrConstants.JCR_PATH.equals(orderEntry.getPropertyName())) { sortingField = partialEscape(configuration.getPathField()).toString(); } else if (JcrConstants.JCR_SCORE.equals(orderEntry.getPropertyName())) { sortingField = "score"; } else { if (orderEntry.getPropertyName().indexOf('/') >= 0) { log.warn("cannot sort on relative properties, ignoring {} clause", orderEntry); continue; } sortingField = partialEscape(getSortingField(orderEntry.getPropertyType().tag(), orderEntry.getPropertyName())).toString(); } solrQuery.addOrUpdateSort(sortingField, order); } } Collection<Filter.PropertyRestriction> propertyRestrictions = filter.getPropertyRestrictions(); if (propertyRestrictions != null && !propertyRestrictions.isEmpty()) { for (Filter.PropertyRestriction pr : propertyRestrictions) { if (pr.isNullRestriction()) { continue; } if (QueryConstants.REP_FACET.equals(pr.propertyName)) { solrQuery.setFacetMinCount(1); solrQuery.setFacet(true); String value = pr.first.getValue(Type.STRING); solrQuery.addFacetField(value.substring(QueryConstants.REP_FACET.length() + 1, value.length() - 1) + "_facet"); } if (SolrQueryIndex.NATIVE_SOLR_QUERY.equals(pr.propertyName) || SolrQueryIndex.NATIVE_LUCENE_QUERY.equals(pr.propertyName)) { String nativeQueryString = String.valueOf(pr.first.getValue(pr.first.getType())); if (isSupportedHttpRequest(nativeQueryString)) { String requestHandlerString = nativeQueryString.substring(0, nativeQueryString.indexOf('?')); if (!"select".equals(requestHandlerString)) { if (requestHandlerString.charAt(0) != '/') { requestHandlerString = "/" + requestHandlerString; } solrQuery.setRequestHandler(requestHandlerString); } String parameterString = nativeQueryString.substring(nativeQueryString.indexOf('?') + 1); for (String param : parameterString.split("&")) { String[] kv = param.split("="); if (kv.length != 2) { throw new RuntimeException("Unparsable native HTTP Solr query"); } else { if ("/mlt".equals(requestHandlerString)) { if ("stream.body".equals(kv[0])) { kv[0] = "q"; String mltFlString = "mlt.fl="; int mltFlIndex = parameterString.indexOf(mltFlString); if (mltFlIndex > -1) { int beginIndex = mltFlIndex + mltFlString.length(); int endIndex = parameterString.indexOf('&', beginIndex); String fields; if (endIndex > beginIndex) { fields = parameterString.substring(beginIndex, endIndex); } else { fields = parameterString.substring(beginIndex); } kv[1] = "_query_:\"{!dismax qf=" + fields + " q.op=OR}" + kv[1] + "\""; } } if ("mlt.fl".equals(kv[0]) && ":path".equals(kv[1])) { kv[1] = configuration.getCatchAllField(); } } if ("/spellcheck".equals(requestHandlerString)) { if ("term".equals(kv[0])) { kv[0] = "spellcheck.q"; } solrQuery.setParam("spellcheck", true); } if ("/suggest".equals(requestHandlerString)) { if ("term".equals(kv[0])) { kv[0] = "suggest.q"; } solrQuery.setParam("suggest", true); } solrQuery.setParam(kv[0], kv[1]); } } return solrQuery; } else { queryBuilder.append(nativeQueryString); } } else { if (SolrQueryIndex.isIgnoredProperty(pr, configuration)) { continue; } String first = null; if (pr.first != null) { first = partialEscape(String.valueOf(pr.first.getValue(pr.first.getType()))).toString(); } String last = null; if (pr.last != null) { last = partialEscape(String.valueOf(pr.last.getValue(pr.last.getType()))).toString(); } String prField = configuration.getFieldForPropertyRestriction(pr); CharSequence fieldName = partialEscape(prField != null ? prField : pr.propertyName); if ("jcr\\:path".equals(fieldName.toString())) { queryBuilder.append(configuration.getPathField()); queryBuilder.append(':'); queryBuilder.append(first); } else { if (pr.first != null && pr.last != null && pr.first.equals(pr.last)) { queryBuilder.append(fieldName).append(':'); queryBuilder.append(first); } else if (pr.first == null && pr.last == null) { if (!queryBuilder.toString().contains(fieldName + ":")) { queryBuilder.append(fieldName).append(':'); queryBuilder.append('*'); } } else if ((pr.first != null && pr.last == null) || (pr.last != null && pr.first == null) || (!pr.first.equals(pr.last))) { queryBuilder.append(fieldName).append(':'); queryBuilder.append(createRangeQuery(first, last, pr.firstIncluding, pr.lastIncluding)); } else if (pr.isLike) { queryBuilder.append(fieldName).append(':'); queryBuilder.append(partialEscape(String.valueOf(pr.first.getValue(pr.first.getType())).replace('%', '*').replace('_', '?'))); } else { throw new RuntimeException("[unexpected!] not handled case"); } } } queryBuilder.append(" "); } } if (configuration.useForPrimaryTypes()) { String[] pts = filter.getPrimaryTypes().toArray(new String[filter.getPrimaryTypes().size()]); StringBuilder ptQueryBuilder = new StringBuilder(); for (int i = 0; i < pts.length; i++) { String pt = pts[i]; if (i == 0) { ptQueryBuilder.append("("); } if (i > 0 && i < pts.length) { ptQueryBuilder.append("OR "); } ptQueryBuilder.append("jcr\\:primaryType").append(':').append(partialEscape(pt)).append(" "); if (i == pts.length - 1) { ptQueryBuilder.append(")"); ptQueryBuilder.append(' '); } } solrQuery.addFilterQuery(ptQueryBuilder.toString()); } if (filter.getQueryStatement() != null && filter.getQueryStatement().contains(QueryConstants.REP_EXCERPT)) { if (!solrQuery.getHighlight()) { solrQuery.setHighlight(true); solrQuery.set("hl.fl", "*"); solrQuery.set("hl.encoder", "html"); solrQuery.set("hl.mergeContiguous", true); solrQuery.setHighlightSimplePre("<strong>"); solrQuery.setHighlightSimplePost("</strong>"); } } if (configuration.useForPathRestrictions()) { Filter.PathRestriction pathRestriction = filter.getPathRestriction(); if (pathRestriction != null) { String path = purgePath(filter, plan.getPathPrefix()); String fieldName = configuration.getFieldForPathRestriction(pathRestriction); if (fieldName != null) { if (pathRestriction.equals(Filter.PathRestriction.ALL_CHILDREN)) { solrQuery.addFilterQuery(fieldName + ':' + path); } else { queryBuilder.append(fieldName); queryBuilder.append(':'); queryBuilder.append(path); } } } } if (configuration.collapseJcrContentNodes()) { solrQuery.addFilterQuery("{!collapse field=" + configuration.getCollapsedPathField() + " min=" + configuration.getPathDepthField() + " hint=top_fc nullPolicy=expand}"); } if (queryBuilder.length() == 0) { queryBuilder.append("*:*"); } String escapedQuery = queryBuilder.toString(); solrQuery.setQuery(escapedQuery); if (log.isDebugEnabled()) { log.debug("JCR query {} has been converted to Solr query {}", filter.getQueryStatement(), solrQuery.toString()); } return solrQuery; }    }
@Test public void testMatchAllConversionWithNoConstraints() throws Exception { Filter filter = mock(Filter.class); OakSolrConfiguration configuration = mock(OakSolrConfiguration.class); QueryIndex.IndexPlan plan = mock(QueryIndex.IndexPlan.class); SolrQuery solrQuery = FilterQueryParser.getQuery(filter, plan, configuration); assertNotNull(solrQuery); assertEquals("*:*", solrQuery.getQuery()); }
@Test public void testAllChildrenQueryParsing() throws Exception { String query = "select [jcr:path], [jcr:score], * from [nt:hierarchy] as a where isdescendantnode(a, '/')"; Filter filter = mock(Filter.class); OakSolrConfiguration configuration = new DefaultSolrConfiguration(){ @Override public boolean useForPathRestrictions() { return true; } }; when(filter.getQueryStatement()).thenReturn(query); Filter.PathRestriction pathRestriction = Filter.PathRestriction.ALL_CHILDREN; when(filter.getPathRestriction()).thenReturn(pathRestriction); when(filter.getPath()).thenReturn("/"); QueryIndex.IndexPlan plan = mock(QueryIndex.IndexPlan.class); SolrQuery solrQuery = FilterQueryParser.getQuery(filter, plan, configuration); assertNotNull(solrQuery); String[] filterQueries = solrQuery.getFilterQueries(); assertTrue(Arrays.asList(filterQueries).contains(configuration.getFieldForPathRestriction(pathRestriction) + ":\\/")); assertEquals("*:*", solrQuery.get("q")); }
@Test public void testCollapseJcrContentNodes() throws Exception { String query = "select [jcr:path], [jcr:score], * from [nt:hierarchy] as a where isdescendantnode(a, '/')"; Filter filter = mock(Filter.class); OakSolrConfiguration configuration = new DefaultSolrConfiguration(){ @Override public boolean collapseJcrContentNodes() { return true; } }; when(filter.getQueryStatement()).thenReturn(query); QueryIndex.IndexPlan plan = mock(QueryIndex.IndexPlan.class); SolrQuery solrQuery = FilterQueryParser.getQuery(filter, plan, configuration); assertNotNull(solrQuery); String[] filterQueries = solrQuery.getFilterQueries(); assertTrue(Arrays.asList(filterQueries).contains("{!collapse field=" + configuration.getCollapsedPathField() + " min=" + configuration.getPathDepthField() + " hint=top_fc nullPolicy=expand}")); assertEquals("*:*", solrQuery.get("q")); }