/* * Copyright (C) 2013 lichtflut Forschungs- und Entwicklungsgesellschaft mbH * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.arastreju.sge.index; import de.lichtflut.infra.exceptions.NotYetSupportedException; import org.arastreju.sge.query.QueryBuilder; import org.arastreju.sge.query.QueryException; import org.arastreju.sge.query.QueryExpression; import org.arastreju.sge.query.QueryOperator; import org.arastreju.sge.query.QueryParam; import org.arastreju.sge.query.QueryResult; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.regex.Matcher; /** * <p> * Lucene specific query builder. * </p> * * <p> * Created 01.02.13 * </p> * * @author Oliver Tigges */ public class LuceneQueryBuilder extends QueryBuilder { private static final Logger LOGGER = LoggerFactory.getLogger(LuceneQueryBuilder.class); private final IndexSearcher searcher; private final QNResolver resolver; // ----------------------------------------------------- /** * Constructor. * @param searcher The index searcher. * @param resolver The resolver for qualified names. */ public LuceneQueryBuilder(IndexSearcher searcher, QNResolver resolver) { this.searcher = searcher; this.resolver = resolver; } // ----------------------------------------------------- @Override public QueryResult getResult() { final IndexSearchResult hits = searcher.search(toQueryString()); return new LuceneQueryResult(hits, resolver); } // ----------------------------------------------------- /** * Return the Lucence query. * @return The query. */ protected String toQueryString() { final StringBuilder sb = new StringBuilder(); append(getRoot(), sb); return sb.toString(); } @Override protected QueryExpression getRoot() { return super.getRoot(); } // ----------------------------------------------------- private void append(final QueryExpression exp, final StringBuilder sb) { if (exp.isLeaf()) { appendLeaf(exp.getQueryParam(), sb); } else { if (QueryOperator.NOT.equals(exp.getOperator())) { sb.append(" ").append(exp.getOperator().name()).append(" "); } sb.append("("); boolean first = true; for (QueryExpression child : exp.getChildren()) { if (first) { first = false; } else if (!QueryOperator.NOT.equals(exp.getOperator())) { sb.append(" ").append(exp.getOperator().name()).append(" "); } append(child, sb); } sb.append(")"); } } private void appendLeaf(final QueryParam param, final StringBuilder sb) { String value = normalizeValue(param.getValue()); if (value == null || value.length() == 0) { throw new QueryException("Invalid query value: " + param); } switch(param.getOperator()) { case EQUALS: sb.append(normalizeKey(param.getName())).append(":"); break; case HAS_URI: sb.append(IndexFields.QUALIFIED_NAME + ":"); break; case HAS_VALUE: sb.append(IndexFields.RESOURCE_VALUE + ":"); break; case HAS_RELATION: sb.append(IndexFields.RESOURCE_RELATION + ":"); break; case SUB_QUERY: sb.append(param.getValue()); // abort here! return; default: throw new NotYetSupportedException(param.getOperator()); } sb.append(value); } private String normalizeKey(final String key) { return key.replaceAll(":", Matcher.quoteReplacement("\\:")); } private String normalizeValue(final Object value) { if (value == null) { return null; } String normalized = value.toString().trim().toLowerCase(); if (normalized.contains(" ")) { normalized = "\"" + normalized + "\""; } return normalized.replaceAll(":", Matcher.quoteReplacement("\\:")); } }