package de.anycook.recipe.ingredient;
import de.anycook.db.mysql.DBGetRecipe;
import de.anycook.db.mysql.DBIngredient;
import de.anycook.db.mysql.DBRecipe;
import de.anycook.drafts.IngredientDraft;
import org.apache.logging.log4j.LogManager;
import org.tartarus.snowball.SnowballProgram;
import org.tartarus.snowball.ext.GermanStemmer;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.StringTokenizer;
/**
* @author Jan Graßegger<jan@anycook.de>
*/
public final class Ingredients {
private Ingredients() {
}
public static int getTotal() throws SQLException {
try (DBGetRecipe db = new DBGetRecipe()) {
return db.getTotalIngredients();
}
}
private static Set<Ingredient> searchNGram(List<String> terms, int n, DBRecipe dbRecipe) throws SQLException {
SnowballProgram stemmer = new GermanStemmer();
Set<Ingredient> ingredients = new LinkedHashSet<>();
StringBuffer sb;
List<Integer> indexToDelete = new LinkedList<>();
for (int i = 0; i <= terms.size() - n; ++i) {
sb = new StringBuffer();
try {
sb.append(terms.get(i));
} catch (IndexOutOfBoundsException e) {
LogManager.getLogger(Ingredient.class)
.error("terms: " + terms + " n:" + n + " i:" + i, e);
}
int j;
for (j = i + 1; j < i + n; ++j)
sb.append(' ').append(terms.get(j));
String nGram = sb.toString();
stemmer.setCurrent(nGram);
stemmer.stem();
String stem = stemmer.getCurrent();
try {
Ingredient ingredient = dbRecipe.getIngredientForStem(stem);
ingredients.add(ingredient);
for (int k = i; k < j; ++k)
indexToDelete.add(k);
} catch (DBIngredient.IngredientNotFoundException e) {
//nothing to do
}
}
List<String> restTerms = new ArrayList<>();
for (int i = 0; i < terms.size(); ++i) {
if (!indexToDelete.contains(i))
restTerms.add(terms.get(i));
}
if (restTerms.size() > 0 && n > 1) {
ingredients.addAll(searchNGram(restTerms, Math.min(--n, restTerms.size() - 1), dbRecipe));
}
return ingredients;
}
public static Set<Ingredient> searchNGram(String q, int n) throws SQLException {
StringTokenizer tokenizer = new StringTokenizer(q.toLowerCase(), " ,.;/-!?+(){}*^[]");
List<String> terms = new ArrayList<>();
while (tokenizer.hasMoreElements()) {
terms.add(tokenizer.nextToken());
}
if (terms.size() == 0) return new HashSet<>();
try(DBRecipe dbRecipe = new DBRecipe()){
return searchNGram(terms, Math.min(n, terms.size()), dbRecipe);
}
}
public static List<IngredientDraft> convertToDrafts(List<Ingredient> ingredients) {
List<IngredientDraft> ingredientDrafts = new LinkedList<>();
ingredients.forEach(ingredient -> ingredientDrafts.add(new IngredientDraft(ingredient)));
return ingredientDrafts;
}
public static List<Ingredient> loadParents() throws SQLException {
try (DBIngredient db = new DBIngredient()) {
return db.getParent();
}
}
public static List<Ingredient> loadParentswithData() throws SQLException {
List<Ingredient> parents = new LinkedList<>();
for (Ingredient in : loadParents())
try {
parents.add(Ingredient.init(in.getName()));
} catch (DBIngredient.IngredientNotFoundException e) {
//nope
}
return parents;
}
public static List<Ingredient> getAll() throws SQLException {
try (DBIngredient db = new DBIngredient()) {
return db.getAllIngredients();
}
}
public static List<Ingredient> loadByRecipe(String recipeName) throws SQLException {
try (DBIngredient db = new DBIngredient()) {
return db.getRecipeIngredients(recipeName);
}
}
public static List<Ingredient> loadByRecipe(String recipeName, int versionId) throws SQLException {
try (DBIngredient db = new DBIngredient()) {
return db.getRecipeIngredients(recipeName, versionId);
}
}
public static List<IngredientDraft> loadIngredientDrafts(String recipeName) throws SQLException {
return convertToDrafts(loadByRecipe(recipeName));
}
public static List<IngredientDraft> loadIngredientDrafts(String recipeName, int versionId) throws SQLException {
return convertToDrafts(loadByRecipe(recipeName, versionId));
}
}