package com.opticalcobra.storybear.db;
import java.awt.Point;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import org.hsqldb.server.Server;
import org.hsqldb.types.Types;
import com.opticalcobra.storybear.editor.Story;
import com.opticalcobra.storybear.editor.StoryInfo;
import com.opticalcobra.storybear.main.User;
import com.opticalcobra.storybear.res.Ressources;
/**
*
* @author Tobias
*
*/
public class Database {
private static Server DBinstance;
private static Connection conn;
public static int requestnum;
/**
* @author Tobias
*/
public Database() {
if(DBinstance == null){
DBinstance = Server.start(new String[0]);
}
if(conn == null){
try {
Class.forName("org.hsqldb.jdbcDriver");
conn = DriverManager.getConnection("jdbc:hsqldb:hsql://localhost/", "sa","");
} catch (SQLException e) {
System.err.println("Could not establish database connection");
} catch (ClassNotFoundException e) {
System.err.println("Could not load jdbc driver");
e.printStackTrace();
}
}
}
/**
* @author Tobias
* @throws SQLException
*/
public void shutdown() throws SQLException{
Statement st = conn.createStatement();
st.execute("SHUTDOWN");
conn.close();
}
/**
* @author Tobias & Martika
* @param ba
* @param tableName
* @throws SQLException
*/
private void insertBlob(byte[] ba, String tableName) throws SQLException{
java.sql.Blob obj = conn.createBlob();
obj.setBytes(1, ba);
PreparedStatement pstmt = conn.prepareStatement("INSERT INTO " + tableName + " (OBJECT, LENGTH) VALUES(?,"+ba.length+")");
pstmt.setBlob(1, obj);
pstmt.execute();
}
/**
* @author Tobias & Martika
* @param id
* @param tableName
* @return
* @throws SQLException
*/
private byte[] getBlob(int id, String tableName) throws SQLException{
ResultSet rs = query("SELECT OBJECT, LENGTH FROM " + tableName + " WHERE ID = "+id+";");
rs.next();
java.sql.Blob obj = rs.getBlob("OBJECT");
return obj.getBytes(1, rs.getInt("LENGTH"));
}
/**
* @Martika
* @param currentStory
*/
public void insertStoryToDatabase(Story currentStory){
byte[] ba = Blob.create(currentStory);
try {
insertBlob(ba, "STORY");
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* @author Martika
* @param id
* @return
*/
public Story getStoryFromDatabase(int id){
byte[] currentBlob = null;
try {
currentBlob = getBlob(id, "STORY");
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return ((Story)Blob.read(currentBlob));
}
public void updateStory(Story currentStory) {
try {
conn.createStatement().execute("DELETE FROM story WHERE id=" + currentStory.getId() + ";");
insertStoryToDatabase(currentStory);
} catch (SQLException e) {
e.printStackTrace();
}
}
public ArrayList<StoryInfo> getAllLevelssFromDatabase(){
ArrayList<StoryInfo> result = new ArrayList<StoryInfo>();
try {
ResultSet rs = query("Select Object, length, ID from levels");
while(rs.next()){
java.sql.Blob obj = rs.getBlob("OBJECT");
byte[] ba = obj.getBytes(1, rs.getInt("LENGTH"));
StoryInfo si = (StoryInfo)(Blob.read(ba));
si.setId(rs.getInt("ID"));
result.add(si);
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return result;
}
public ArrayList<Story> getAllStoriesFromDatabase(){
ArrayList<Story> result = new ArrayList<Story>();
try {
ResultSet rs = query("Select Object, length, ID from story");
while(rs.next()){
java.sql.Blob obj = rs.getBlob("OBJECT");
byte[] ba = obj.getBytes(1, rs.getInt("LENGTH"));
Story si = (Story)(Blob.read(ba));
si.setId(rs.getInt("ID"));
result.add(si);
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return result;
}
public ArrayList<StoryInfo> getAllStorysFromDatabaseWithIds(){
ArrayList<StoryInfo> result = new ArrayList<StoryInfo>();
try {
ResultSet rs = query("Select * from levels");
while(rs.next()){
java.sql.Blob obj = rs.getBlob("OBJECT");
byte[] ba = obj.getBytes(1, rs.getInt("LENGTH"));
StoryInfo si = (StoryInfo)(Blob.read(ba));
si.setId(rs.getInt("ID"));
result.add(si);
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return result;
}
/**
* @Martika
* @param currentStory
*/
public void insertStoryInfoToDatabase(StoryInfo currentStoryInfo){
byte[] ba = Blob.create(currentStoryInfo);
try {
insertBlob(ba, "LEVELS");
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* @author Martika
* @param id
* @return
*/
public StoryInfo getStoryInfoFromDatabase(int id){
byte[] currentBlob = null;
try {
currentBlob = getBlob(id, "LEVELS");
} catch (SQLException e) {
}
return ((StoryInfo)Blob.read(currentBlob));
}
/**
* @author Martika
* @return
*/
public TileResult getTileInfo(int tileType){
ResultSet rs;
int height = 0;
boolean walkable = false;
try {
rs = query("SELECT height_level, walkable from foreground_type where id = '" + tileType + "';");
rs.next();
height = (int) (rs.getObject("HEIGHT_LEVEL"));
height = (int) (height / Ressources.SCALE);
walkable = rs.getBoolean("WALKABLE");
rs.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return new TileResult(tileType, height, walkable, null);
}
/**
* @author Martika
* @param tileTypeId
* @param containerTypeId
* @return
*/
public Point getObjectPosForeground(int tileTypeId, int containerTypeId){
ResultSet rs;
Point position = new Point(0, 0);
try {
rs = query("SELECT x, y FROM foreground_container WHERE type_id = " +tileTypeId+ " AND "
+ "container_type = " + containerTypeId + ";");
rs.next();
position.x = (int) rs.getObject("X");
position.y = (int) rs.getObject("Y");
position.x = (int) (position.x / Ressources.SCALE);
position.y = (int) (position.y / Ressources.SCALE);
rs.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return position;
}
/**
* @author Martika
* @param tileTypeId
* @param containerTypeId
* @return
*/
public int getRandomCollectableNumber(){
ResultSet rs;
ResultSet rsCounter;
int range=0;
int returnImageID = 0;
try {
rsCounter = query("SELECT COUNT(*) FROM collectable_object");
rsCounter.next();
range = (int) rsCounter.getInt(1);
range = (int) (Math.random()*range);
rsCounter.close();
rs = query("SELECT image_id FROM collectable_object where id = "+range+";");
rs.next();
returnImageID = range = (int) rs.getObject(1);
rs.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return returnImageID;
}
public Point getObjectPosMiddleground(int tileTypeId, int containerTypeId){
ResultSet rs;
Point position = new Point(0, 0);
try {
rs = query("SELECT x, y FROM middleground_container WHERE type_id = " +tileTypeId+ " AND "
+ "container_id = " + containerTypeId + ";");
while(rs.next()){
position.x = (int) rs.getObject("X");
position.y = (int) rs.getObject("Y");
position.x = (int) (position.x / Ressources.SCALE);
position.y = (int) (position.y / Ressources.SCALE);
}
rs.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return position;
}
public synchronized ResultSet query(String expression) throws SQLException {
requestnum++;
Statement st = null;
ResultSet rs = null;
st = conn.createStatement();
rs = st.executeQuery(expression);
st.close();
return rs;
}
/**
* Returns current Server status
* DBConstants.SERVER_SHUTDOWN
* DBConstants.SERVER_OPENING
* DBConstants.SERVER_RUNNING
* DBConstants.SERVER_CLOSEING
* @return Constant for Server Status
* @author Tobias
*/
public int getState(){
return DBinstance.getState();
}
/**
* Starts the Database for Development purpose
*/
public static void main(String[] args){
Database DB = new Database();
try {
DB.query("SELECT * FROM category;");
DB.shutdown();
} catch (SQLException e) {
System.err.println("SQL Error");
}
}
@SuppressWarnings({ "unchecked", "rawtypes" })
private ArrayList[] toArrayList(ResultSet rs){
int colmax = 0;
ResultSetMetaData meta = null;
ArrayList[] result = null;
//Array initialisieren
try {
meta = rs.getMetaData();
colmax = meta.getColumnCount();
result = new ArrayList[colmax];
for (int i = 0; i < colmax; i++) {
switch (meta.getColumnType(i + 1)) {
case Types.INTEGER:
result[i] = new ArrayList<Integer>();
break;
case Types.BOOLEAN:
result[i] = new ArrayList<Boolean>();
break;
default:
result[i] = new ArrayList<String>(); //to String is working always
break;
}
}
} catch (SQLException e) {
System.err.println("Error identifying metadata from query result");
}
//Daten in ArrayList laden
Object o;
try {
while (rs.next()) {
for (int i = 0; i < colmax; ++i) {
o = rs.getObject(i + 1);
result[i].add(o);
}
}
} catch (SQLException e) {
System.err.println("Error while reading SQL results data");
}
return result;
}
/**
* Returns all information about an Image stored in the DB
* @param query
* @return
* @throws SQLException
*/
public ImageResult queryImagedata(int id) throws SQLException{
String query = "SELECT * FROM IMAGES WHERE ID = "+id;
ResultSet rs = query(query);
int x;
int y;
int width;
int height;
String url;
rs.next();
url =(String) rs.getObject("URL");
x =(Integer) rs.getObject("X");
y =(Integer) rs.getObject("Y");
height =(Integer) rs.getObject("HEIGHT");
width =(Integer) rs.getObject("WIDTH");
rs.close();
return new ImageResult(id, x, y, height, width, url);
}
public Integer[] queryNumberResultOnly(String query) throws SQLException{
ResultSet rs = query(query);
ResultSetMetaData meta = rs.getMetaData();
ArrayList<Integer> result = new ArrayList<Integer>();
while(rs.next()){
result.add((int) rs.getObject(1));
}
rs.close();
return (Integer[])result.toArray(new Integer[0]);
}
/**
* Returns an 0,1,2 or -1 weather we'ye got an image for the word as a collectable, character or landscape
*
* @author Martika
*
* @param word
* @return int 0,1,2 or -1 as Constants
* @throws SQLException
*/
public WordResult queryWordType(String word) throws SQLException{
WordResult result = null;
int typeId = DBConstants.WORD_OBJECT_TYPE_NO_IMAGE;
ResultSet rsCollectable;
ResultSet rsIllustrationBig;
ResultSet rsIllustrationSmall;
ResultSet rsCharacter;
ResultSet rsMiddleground;
ArrayList<String>[] arrayRS; //needed for the ArrayList of the ResultSet rsFexione
String query = "SELECT DISTINCT t2.word FROM term t "
+ "LEFT JOIN synset s ON t.synset_id =s.id "
+ "LEFT JOIN term t2 ON t2.synset_id = s.id "
+ "LEFT JOIN category_link cl ON t2.synset_id = cl.synset_id "
+ "LEFT JOIN category c ON c.id = cl.category_id "
+ "LEFT JOIN term_level tl ON t2.level_id = tl.id "
+ "WHERE t.word in (SELECT basic FROM morph where reflexive= '" +word+ "' ) "
+ "OR t.word like '" +word+ "' OR t.normalized_word like '" +word+ "' "
+ "OR t.normalized_word in (SELECT basic FROM morph where reflexive= '" +word+ "' )";
arrayRS = this.toArrayList(query(query));
arrayRS[0].add(0, word);
for(String flexiom:arrayRS[0]){
rsCollectable = query("SELECT DISTINCT IMAGE_ID FROM Collectable_Object WHERE word = '"+word+"';");
rsIllustrationBig = query("SELECT DISTINCT IMAGE_ID FROM Illustration_Object WHERE word = '"+word+"' AND big = 'true';");
rsIllustrationSmall = query("SELECT DISTINCT IMAGE_ID FROM Illustration_Object WHERE word = '"+word+"' AND big = 'false';");
rsCharacter = query("SELECT DISTINCT IMAGE_ID FROM Character_Object WHERE word = '"+word+"';");
rsMiddleground= query("SELECT DISTINCT IMAGE_ID FROM Middleground_Object WHERE word = '"+word+"';");
if (rsCharacter.next()){
result = new WordResult(DBConstants.WORD_OBJECT_TYPE_CHARACTER,rsCharacter.getInt("IMAGE_ID"),arrayRS);
}
else if (rsCollectable.next()){
result = new WordResult(DBConstants.WORD_OBJECT_TYPE_COLLECTABLE, rsCollectable.getInt("IMAGE_ID"),arrayRS);
}
else if (rsMiddleground.next()){
result = new WordResult(DBConstants.WORD_OBJECT_TYPE_MIDDLEGROUND, rsMiddleground.getInt("IMAGE_ID"),arrayRS);
}
else if (rsIllustrationBig.next()){
result = new WordResult(DBConstants.WORD_OBJECT_TYPE_ILLUSTRATION_BIG, rsIllustrationBig.getInt("IMAGE_ID"),arrayRS);
}
else if (rsIllustrationSmall.next()){
result = new WordResult(DBConstants.WORD_OBJECT_TYPE_ILLUSTRATION_SMALL, rsIllustrationSmall.getInt("IMAGE_ID"),arrayRS);
} else{
result = new WordResult(DBConstants.WORD_OBJECT_TYPE_NO_IMAGE, getRandomCollectableNumber(),arrayRS);
}
rsCollectable.close();
rsIllustrationBig.close();
rsIllustrationSmall.close();
rsCharacter.close();
rsMiddleground.close();
if(result.getType() != DBConstants.WORD_OBJECT_TYPE_NO_IMAGE){
return result;
}
}
return result;
}
/**
* Returns list of all users
* @return list of users
* @throws SQLException
*/
public List<User> queryUserList() throws SQLException {
List<User> resultList = new ArrayList<User>();
ResultSet rs = query("SELECT * FROM user;");
while(rs.next())
resultList.add(new User((Integer) rs.getObject("ID"), (String) rs.getObject("NAME")));
rs.close();
return resultList;
}
/**
* Delete user
* @param id UserId
* @return true if user was deleted successfully
* @throws SQLException
*/
public boolean deleteUserById(int id) throws SQLException {
return conn.createStatement().execute("DELETE FROM user WHERE id=" + id + ";");
}
/**
* Add new User to DB
* @param user User-Object
* @return true if insert was successful
* @throws SQLException
*/
public boolean addUser(User user) throws SQLException {
return conn.createStatement().execute("INSERT INTO user(name) VALUES ('" + user.getName() + "')");
}
/*
* @author Miriam
*/
public String getUserName(int id) throws SQLException{
ResultSet rs = query("SELECT NAME FROM user WHERE id = " + id + ";");
String result = "";
while(rs.next())
result = rs.getString("NAME");
rs.close();
//return rs.getString("NAME");
return result;
}
/*
* @author Miriam
* inserts the highscore data in the highscore table
*/
public void addHighscore(int user_id, int level_id, int score) throws SQLException{
ResultSet rs = query("INSERT INTO highscore (user_id,level_id,score) values ("+ user_id +", "+ level_id +", " + score +");");
}
public ArrayList<HighscoreResult> getHighscoreForLevel(int level) throws SQLException{
ArrayList<HighscoreResult> hr = new ArrayList();
ResultSet rs = query("SELECT * FROM highscore WHERE level_id = " + level + ";");
while(rs.next()){
hr.add(new HighscoreResult((int)(rs.getObject("user_id")), level, (int)(rs.getObject("score"))));
}
rs.close();
return hr;
}
public List<SuggestionWord> getRandomSuggestioWord(int numberOfWords) {
ArrayList<SuggestionWord> words = new ArrayList<SuggestionWord>();
try {
ResultSet res = query("SELECT IMAGE_ID, WORD, BIG FROM Illustration_Object ORDER BY RAND() LIMIT "+numberOfWords+";");
while(res.next()) {
SuggestionWord s = new SuggestionWord();
s.setImageId((Integer) res.getObject("IMAGE_ID"));
s.setWord((String) res.getObject("WORD"));
s.setBig((Boolean) res.getObject("BIG"));
words.add(s);
}
return words;
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
/*
* @author Miriam
* gets the points of a chosen collectable with the mentioned id from the input
*/
public int getPointsOfCollectable(int id) throws SQLException{
int result = 0;
ResultSet rs = query("SELECT POINTS FROM collectable_object WHERE id = " + id + ";");
while(rs.next()){
result = rs.getInt("POINTS");
}
rs.close();
return result;
}
public void dump(ResultSet rs) throws SQLException {
// ResultSetMetaData meta = rs.getMetaData(); // TODO print metadata
// int colmax = meta.getColumnCount();
// Object o = null;
//
// while(rs.next() ) {
// for (int i = 0; i < colmax; ++i) {
// o = rs.getObject(i + 1);
// System.out.print(o + " ");
// }
//
// System.out.println(" ");
// }
System.out.println(toArrayList(rs));
}
}