/*
* This file is part of anycook. The new internet cookbook
* Copyright (C) 2014 Jan Graßegger
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see [http://www.gnu.org/licenses/].
*/
package de.anycook.db.mysql;
import de.anycook.recipe.Recipe;
import de.anycook.recipe.Time;
import de.anycook.recipe.ingredient.Ingredient;
import de.anycook.recipe.tag.Tag;
import de.anycook.user.User;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.*;
/**
* Von DBHandler abgeleitet. Enthaelt alle Funktionen, die fuer die Gerichte zustaendig sind.
*
* @author Jan Grassegger
* @see de.anycook.db.mysql.DBHandler
*/
public class DBRecipe extends DBHandler {
public DBRecipe() throws SQLException {
super();
}
/**
* Ueberprueft Gericht auf Existenz. Nutzt zur Ueberpruefung {@link de.anycook.db.mysql.DBRecipe#getName(String)}.
*
* @param q {@link String} mit zu uberpruefendem Gericht.
* @return {@link Boolean} mit true, wenn vorhanden, sonst false.
*/
public boolean check(String q) throws SQLException {
try {
getName(q);
return true;
} catch (RecipeNotFoundException e) {
return false;
}
}
/**
* Gibt ein gegebenes Gericht q in der Schreibweise der Datenbank zurueck. Ist das Gericht nicht vorhanden wird null zurueckgegeben.
*
* @param q String mit dem gesuchten Gericht.
* @return String mit dem Kategorienamen aus der Datenbank oder null.
*/
public String getName(String q) throws SQLException, RecipeNotFoundException {
PreparedStatement pStatement = connection.prepareStatement("SELECT name from gerichte WHERE name = ?");
pStatement.setString(1, q);
ResultSet data = pStatement.executeQuery();
if (data.next()) return data.getString("name");
throw new RecipeNotFoundException(q);
}
public int getTasteNum(String recipeName) throws SQLException {
int count = 0;
PreparedStatement pStatement =
connection.prepareStatement("SELECT name, COUNT(users_id) AS counter FROM gerichte " +
"LEFT JOIN schmeckt ON name = gerichte_name WHERE name = ? GROUP BY name");
pStatement.setString(1, recipeName);
ResultSet data = pStatement.executeQuery();
if (data.next())
count = data.getInt("counter");
return count;
}
//tags
/**
* Entfernt Tag von einem Gericht. Hat kein weiteres Gericht dieses Tag, wird der Tag komplett geloescht.
*
* @param recipeName Name des Gerichts
* @param tag Name des Tags
* @return wenn mysql-anfragen erfolgreich, true
* @throws java.sql.SQLException
*/
public boolean removeTagFromRecipe(String recipeName, String tag) throws SQLException {
PreparedStatement pStatement = connection.prepareStatement("DELETE FROM gerichte_has_tags " +
"WHERE gerichte_name = ? AND tags_name = ?");
pStatement.setString(1, recipeName);
pStatement.setString(2, tag);
pStatement.executeUpdate();
return true;
}
public boolean hasTag(String tag) throws SQLException {
PreparedStatement pStatement = connection.prepareStatement("SELECT * FROM gerichte_has_tags WHERE tags_name = ?");
pStatement.setString(1, tag);
ResultSet data = pStatement.executeQuery();
return data.next();
}
public boolean hasTag(String recipe, String tag) throws SQLException {
PreparedStatement pStatement = connection.prepareStatement("SELECT * FROM gerichte_has_tags " +
"WHERE gerichte_name = ? AND tags_name = ?");
pStatement.setString(1, recipe);
pStatement.setString(2, tag);
ResultSet data = pStatement.executeQuery();
return data.next();
}
/**
* Gibt die am meisten benutzten tags als map mit ihrer Anzahl zurueck.
*
* @param numTags Anzahl der Tags, die man bekommen moechte.
* @return {@link java.util.Map} mit Tags und Anzahl ihres auftretens.
*/
public List<Tag> getPopularTags(int numTags) throws SQLException {
List<Tag> tags = new LinkedList<>();
PreparedStatement pStatement = connection.prepareStatement("SELECT tags_name AS tag, COUNT(gerichte_name) " +
"AS count FROM gerichte_has_tags " +
"WHERE active = 1 GROUP BY tag ORDER BY count DESC LIMIT ?");
pStatement.setInt(1, numTags);
ResultSet data = pStatement.executeQuery();
while (data.next()) {
String tagName = data.getString("tag");
int count = data.getInt("count");
tags.add(new Tag(tagName, count));
}
return tags;
}
public List<Tag> getPopularTagsNotInRecipe(int numTags, String recipe) throws SQLException {
List<Tag> tags = new LinkedList<>();
PreparedStatement pStatement = connection.prepareStatement("SELECT tags_name, COUNT(gerichte_name) AS count FROM gerichte_has_tags " +
"WHERE active = 1 AND " +
"tags_name NOT IN (SELECT tags_name FROM gerichte_has_tags WHERE gerichte_name = ? GROUP BY tags_name) " +
"GROUP BY tags_name ORDER BY count DESC LIMIT ?");
pStatement.setString(1, recipe);
pStatement.setInt(2, numTags);
ResultSet data = pStatement.executeQuery();
while (data.next()) {
String tagName = data.getString("tags_name");
int count = data.getInt("count");
tags.add(new Tag(tagName, count));
}
return tags;
}
//ingredients
public Ingredient getIngredientForStem(String stem) throws SQLException, DBIngredient.IngredientNotFoundException {
PreparedStatement pStatement = connection.prepareStatement("SELECT name from zutaten WHERE stem = ?");
pStatement.setString(1, stem);
ResultSet data = pStatement.executeQuery();
if (data.next())
return new Ingredient(data.getString("name"));
throw new DBIngredient.IngredientNotFoundException(stem);
}
/**
* ueberprueft ob ein filename bereits bei einem Gericht existiert
*
* @param filename zu checkender Filename
* @return wenn bereits vorhanden false, sonst true
*/
public boolean checkFilename(String filename) throws SQLException {
PreparedStatement pStatement = connection.prepareStatement("SELECT * from versions WHERE imagename = ?");
pStatement.setString(1, filename);
ResultSet data = pStatement.executeQuery();
return !data.next();
}
/**
* increased den viewed eintrag eines bestimmten Gerichts um 1
*
* @param recipeName Gerichtename
*/
public void viewRecipe(String recipeName) throws SQLException {
PreparedStatement pStatement = connection.prepareStatement("UPDATE gerichte " +
"SET viewed = viewed + 1 WHERE name = ?");
pStatement.setString(1, recipeName);
pStatement.executeUpdate();
}
public int getActiveVersion(String recipeName) throws SQLException {
PreparedStatement pStatement = connection.prepareStatement("SELECT active_id FROM gerichte WHERE name = ?");
pStatement.setString(1, recipeName);
ResultSet data = pStatement.executeQuery();
if (data.next())
return data.getInt("active_id");
return -1;
}
protected List<Recipe> getRecipes(ResultSet data) throws SQLException {
List<Recipe> recipes = new ArrayList<>();
while (data.next()) {
recipes.add(getRecipe(data));
}
return recipes;
}
protected Recipe getRecipe(ResultSet data) throws SQLException {
String description = data.getString("beschreibung");
Date created = data.getDate("created");
Timestamp lastChange = data.getTimestamp("last_change");
Time time = new Time(data.getInt("std"), data.getInt("min"));
int skill = data.getInt("skill");
int calorie = data.getInt("kalorien");
int person = data.getInt("personen");
int id = data.getInt("id");
int activeId = data.getInt("active_id");
String name = data.getString("name");
String image = data.getString("image");
int userId = data.getInt("users_id");
String username = data.getString("nickname");
String userImage = data.getString("users.image");
User user = new User(userId, username, userImage);
String category = data.getString("kategorien_name");
int views = data.getInt("viewed");
boolean tasty = data.getBoolean("tastes");
return new Recipe(id, name, description, image, person, created, lastChange, category,
skill, calorie, time, activeId, views, user, tasty);
}
public static class RecipeNotFoundException extends Exception {
public RecipeNotFoundException(String queryRecipe) {
super("recipe does not exist: " + queryRecipe);
}
public RecipeNotFoundException(String recipeName, int versionId) {
super(String.format("recipe: \"%s\" versionId: %d does not exist", recipeName, versionId));
}
}
}