/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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.apache.sling.mailarchiveserver.impl; import static org.apache.sling.mailarchiveserver.impl.SearchQueryParserImpl.MESSAGE_FIELDS; import static org.apache.sling.mailarchiveserver.impl.SearchQueryParserImpl.SEARCH_PARAMETER_TO_MESSAGE_FIELD_MAP; import java.util.List; import java.util.Map; import org.apache.felix.scr.annotations.Component; import org.apache.felix.scr.annotations.Service; import org.apache.sling.mailarchiveserver.api.QueryBuilder; import org.apache.sling.mailarchiveserver.impl.SearchQueryParserImpl.SearchParameter; @Component @Service(QueryBuilder.class) public class QueryBuilderImpl implements QueryBuilder { static final String BASE = "SELECT * FROM [nt:unstructured] WHERE [sling:resourceType] = 'mailarchiveserver/message'"; static final String DUMMY = "SELECT * FROM [nt:frozenNode] WHERE [42] = 0"; private static final String AND = " AND "; private static final String OR = " OR "; public static final String SQL2 = "SQL2"; private String buildSQL2Query(Map<String, List<String>> tokens) { if (tokens == null) { return BASE; } else if (tokens.size() == 0) { return DUMMY; } String constraints = ""; // tokens constraints for (String tokenClass : tokens.keySet()) { if (tokenClass.equals(SearchParameter.NONE)) { continue; } String fieldConstraint = buildFieldConstraints(tokenClass, tokens); constraints += "("+ fieldConstraint +")" + AND; } // global constraints String globalConstraint = ""; List<String> ls = tokens.get(SearchParameter.NONE); if (ls != null) { for (String msgField : MESSAGE_FIELDS) { for (String value : ls) { if (!value.trim().equals("")) { globalConstraint += sqlLikeConstraint(sqlLower(msgField), value.toLowerCase()) + OR; } } } globalConstraint = globalConstraint.substring(0, globalConstraint.length()-OR.length()); } if (!globalConstraint.equals("")) { constraints += "("+ globalConstraint +")" + AND; } if (constraints.equals("")) { return BASE; } else { return BASE + " AND " + constraints.substring(0, constraints.length()-AND.length()); } } private static String buildFieldConstraints(String tokenClass, Map<String, List<String>> tokens) { List<String> ls = tokens.get(tokenClass); String messageField = SEARCH_PARAMETER_TO_MESSAGE_FIELD_MAP.get(tokenClass); String fieldConstraint = ""; for (String value : ls) { if (!value.trim().equals("")) { fieldConstraint += sqlLikeConstraint(sqlLower(messageField), value.toLowerCase()) + OR; } } return fieldConstraint.substring(0, fieldConstraint.length()-OR.length()); } private static String sqlLikeConstraint(String messageField, String value) { return messageField + " LIKE '%" + value + "%'"; } private static String sqlLower(String messageField) { return "LOWER("+ messageField + ")"; } @Override public String buildQuery(Map<String, List<String>> tokens, String lang) { if (lang.trim().equalsIgnoreCase(SQL2)) { return buildSQL2Query(tokens); } else { throw new IllegalArgumentException("Invalid lang argument!"); } } }