1/*
  2 * Copyright (c) 2018, Daniel Gultsch All rights reserved.
  3 *
  4 * Redistribution and use in source and binary forms, with or without modification,
  5 * are permitted provided that the following conditions are met:
  6 *
  7 * 1. Redistributions of source code must retain the above copyright notice, this
  8 * list of conditions and the following disclaimer.
  9 *
 10 * 2. Redistributions in binary form must reproduce the above copyright notice,
 11 * this list of conditions and the following disclaimer in the documentation and/or
 12 * other materials provided with the distribution.
 13 *
 14 * 3. Neither the name of the copyright holder nor the names of its contributors
 15 * may be used to endorse or promote products derived from this software without
 16 * specific prior written permission.
 17 *
 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 21 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
 22 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 25 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 28 */
 29
 30package eu.siacs.conversations.utils;
 31
 32import java.util.ArrayList;
 33import java.util.Arrays;
 34import java.util.List;
 35import java.util.Locale;
 36
 37
 38public class FtsUtils {
 39
 40	private static final List<String> KEYWORDS = Arrays.asList("OR", "AND");
 41
 42	public static List<String> parse(String input) {
 43		List<String> term = new ArrayList<>();
 44		for (String part : input.replace('"',' ').split("\\s+")) {
 45			if (part.isEmpty()) {
 46				continue;
 47			}
 48			final String cleaned = clean(part);
 49			if (isKeyword(cleaned) || cleaned.contains("*")) {
 50				term.add(part);
 51			} else if (!cleaned.isEmpty()) {
 52				term.add(cleaned);
 53			}
 54		}
 55		return term;
 56	}
 57
 58	public static String toMatchString(List<String> terms) {
 59		StringBuilder builder = new StringBuilder();
 60		for (String term : terms) {
 61			if (builder.length() != 0) {
 62				builder.append(' ');
 63			}
 64			if (isKeyword(term)) {
 65				builder.append(term.toUpperCase(Locale.ENGLISH));
 66			} else if (term.contains("*") || term.startsWith("-")) {
 67				builder.append(term);
 68			} else {
 69				builder.append(term).append('*');
 70			}
 71		}
 72		return builder.toString();
 73	}
 74
 75	static boolean isKeyword(String term) {
 76		return KEYWORDS.contains(term.toUpperCase(Locale.ENGLISH));
 77	}
 78
 79	private static int getStartIndex(String term) {
 80		int length = term.length();
 81		int index = 0;
 82		while (term.charAt(index) == '*') {
 83			++index;
 84			if (index >= length) {
 85				break;
 86			}
 87		}
 88		return index;
 89	}
 90
 91	private static int getEndIndex(String term) {
 92		int index = term.length() - 1;
 93		while (term.charAt(index) == '*') {
 94			--index;
 95			if (index < 0) {
 96				break;
 97			}
 98		}
 99		return index;
100	}
101
102	private static String clean(String input) {
103		int begin = getStartIndex(input);
104		int end = getEndIndex(input);
105		if (begin > end) {
106			return "";
107		} else {
108			return input.substring(begin, end + 1);
109		}
110	}
111
112	public static String toUserEnteredString(List<String> term) {
113		final StringBuilder builder = new StringBuilder();
114		for(String part : term) {
115			if (builder.length() != 0) {
116				builder.append(' ');
117			}
118			builder.append(part);
119		}
120		return builder.toString();
121	}
122}