package de.tud.kom.socom.web.server.database.content;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Blob;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import de.tud.kom.socom.web.client.sharedmodels.GameContent;
import de.tud.kom.socom.web.client.sharedmodels.GameContentComment;
import de.tud.kom.socom.web.client.sharedmodels.GlobalConfig;
import de.tud.kom.socom.web.server.database.HSQLAccess;
import de.tud.kom.socom.web.server.database.user.HSQLUserDatabaseAccess;
import de.tud.kom.socom.web.server.util.Logger;
import de.tud.kom.socom.web.server.util.LoggerFactory;
public class HSQLContentDatabaseAccess implements ContentDatabaseAccess, GlobalConfig {
private static ContentDatabaseAccess instance = new HSQLContentDatabaseAccess();
private Logger logger = LoggerFactory.getLogger();
private static HSQLAccess db;
private HSQLContentDatabaseAccess() {
db = HSQLAccess.getInstance();
}
public static ContentDatabaseAccess getInstance() {
return instance;
}
@Override
public GameContent getGameContent(long uid, long cid) {
String query = "SELECT " +
"gamecontent.id, " +
"gamecontent.visibility, " +
"gamecontent.title, " +
"gamecontent.description, " +
"gamecontexts.name AS contextname, " +
"contenttypes.name AS contenttype, " +
"gamecontent.owner, " +
"users.name AS ownername, " +
"gamecontent.time, " +
"AVG(contentratings.value) AS ratingavg, " +
"COUNT(contentratings.value) AS ratingcount, " +
"COUNT(contentcomments.id) AS commentcount, " +
"gamecontent.hits " +
"FROM " +
"(((((gamecontent LEFT JOIN users ON gamecontent.owner = users.uid) " +
"LEFT JOIN gamecontexts ON gamecontexts.id = gamecontent.contextid) " +
"LEFT JOIN contentratings ON contentratings.contentid = gamecontent.id) " +
"LEFT JOIN contentcomments ON contentcomments.contentid = gamecontent.id) " +
"LEFT JOIN contenttypes ON contenttypes.id = gamecontent.type) " +
"WHERE " +
"gamecontent.id = " + cid +
(userIsAdmin(uid) ? " " :
" AND (gamecontent.visibility = 2 OR gamecontent.owner = " + uid +
"OR (gamecontent.visibility = 1 AND " +
"gamecontent.owner = (SELECT uid FROM usersnfriends WHERE uid = gamecontent.owner AND friendid = " + uid + "))) ") +
"GROUP BY " +
"gamecontent.id, " +
"gamecontent.visibility, " +
"gamecontent.title, " +
"gamecontent.description, " +
"gamecontexts.name, " +
"gamecontent.type, " +
"gamecontent.owner, " +
"contenttypes.name, " +
"users.name, " +
"gamecontent.time, " +
"gamecontent.hits " +
"ORDER BY " +
"gamecontexts.name ASC " +
";";
try {
ResultSet rs = db.execQueryWithResult(query);
if(!rs.next())
return null;
GameContent content = new GameContent(rs.getLong("id"), rs.getInt("visibility"), rs.getString("title"),
rs.getString("description"), rs.getString("contextname"), rs.getString("contenttype"), rs.getLong("owner"),
rs.getString("ownername"), rs.getTimestamp("time"), rs.getDouble("ratingavg"), rs.getInt("ratingcount"),
rs.getInt("commentcount"), rs.getInt("hits"), getLastComment(rs.getLong("id")));
return content;
} catch (SQLException e) {
logger.Error(e);
}
return null;
}
@Override
public int getGameContentsPages(long userId, long contextId) {
String query ="SELECT COUNT(DISTINCT gamecontent.id) AS contentcount " +
"FROM " +
"gamecontent LEFT JOIN gamecontexts ON gamecontexts.id = gamecontent.contextid " +
"WHERE " +
"gamecontexts.id = " + contextId +
(userIsAdmin(userId) ? " " : " AND (gamecontent.visibility = 2 OR gamecontent.owner = " + userId + "" +
"OR (gamecontent.visibility = 1 AND " +
"gamecontent.owner = (SELECT uid FROM usersnfriends WHERE uid = gamecontent.owner AND friendid = " + userId + "))) ");
try {
ResultSet rs = db.execQueryWithResult(query);
if(!rs.next()){
return -1;
}
return (int) Math.ceil(((double) rs.getInt("contentcount")) / EntriesPerPage_ContentContexts);
} catch (SQLException e) {
logger.Error(e);
}
return -1;
}
@Override
public GameContent getGameContentNames(long cid) {
GameContent result = null;
try {
String query = "SELECT " +
"gamecontent.id, " +
"gamecontent.title, " +
"gamecontent.description, " +
"gamecontent.time, " +
"gamecontent.visibility, " +
"gamecontent.hits, " +
"gamecontexts.id AS contextid, " +
"gamecontexts.name AS contextname, " +
"gameinstances.id AS gameid, " +
"gameinstances.version, " +
"games.name AS gamename " +
"FROM " +
"((gamecontent INNER JOIN gamecontexts ON gamecontent.contextid = gamecontexts.id) " +
"INNER JOIN gameinstances ON gamecontexts.gameinstid = gameinstances.gameid) " +
"INNER JOIN games ON gameinstances.gameid = games.gameid " +
"WHERE " +
"gamecontent.id = " + cid;
ResultSet queryResult = db.execQueryWithResult(query);
if (!queryResult.next())
return null;
result = new GameContent(queryResult.getLong("id"), queryResult.getInt("visibility"), queryResult.getString("title"),
queryResult.getString("description"), queryResult.getLong("contextid"), queryResult.getString("contextname"), queryResult.getLong("gameid"),
queryResult.getString("gamename") + " " + queryResult.getString("version"), queryResult.getTimestamp("time"), queryResult.getInt("hits"));
} catch (Exception e) {
logger.Error(e);
}
return result;
}
@Override
public List<GameContent> getGameContents(long uid, long contextid, int page) {
List<GameContent> result = new ArrayList<GameContent>();
String query = "SELECT " +
"gamecontent.id, " +
"gamecontent.visibility, " +
"gamecontent.title, " +
"gamecontent.description, " +
"gamecontexts.name AS contextname, " +
"contenttypes.name AS contenttype, " +
"gamecontent.owner, " +
"users.name AS ownername, " +
"gamecontent.time, " +
"AVG(contentratings.value) AS ratingavg, " +
"COUNT(contentratings.value) AS ratingcount, " +
"COUNT(contentcomments.id) AS commentcount, " +
"gamecontent.hits " +
"FROM " +
"(((((gamecontent LEFT JOIN users ON gamecontent.owner = users.uid) " +
"LEFT JOIN gamecontexts ON gamecontexts.id = gamecontent.contextid) " +
"LEFT JOIN contentratings ON contentratings.contentid = gamecontent.id) " +
"LEFT JOIN contentcomments ON contentcomments.contentid = gamecontent.id) " +
"LEFT JOIN contenttypes ON contenttypes.id = gamecontent.type) " +
"WHERE " +
"gamecontent.contextid = " + contextid +
(userIsAdmin(uid) ? " " :
" AND (gamecontent.visibility = 2 OR gamecontent.owner = " + uid + "" +
"OR (gamecontent.visibility = 1 AND " +
"gamecontent.owner = (SELECT uid FROM usersnfriends WHERE uid = gamecontent.owner AND friendid = " + uid + "))) ") +
"GROUP BY " +
"gamecontent.id, " +
"gamecontent.visibility, " +
"gamecontent.title, " +
"gamecontent.description, " +
"gamecontexts.name, " +
"contenttypes.name, " +
"gamecontent.type, " +
"gamecontent.owner, " +
"users.name, " +
"gamecontent.time, " +
"gamecontent.hits " +
"ORDER BY " +
"gamecontexts.name ASC " +
"LIMIT " +
((page - 1) * EntriesPerPage_ContentContexts) + ", " +
EntriesPerPage_ContentContexts + ";";
try {
ResultSet rs = db.execQueryWithResult(query);
while(rs.next()){
GameContent content = new GameContent(rs.getLong("id"), rs.getInt("visibility"), rs.getString("title"),
rs.getString("description"), rs.getString("contextname"), rs.getString("contenttype"), rs.getLong("owner"),
rs.getString("ownername"), rs.getTimestamp("time"), rs.getDouble("ratingavg"), rs.getInt("ratingcount"),
rs.getInt("commentcount"), rs.getInt("hits"), getLastComment(rs.getLong("id")));
result.add(content);
}
} catch (SQLException e) {
logger.Error(e);
}
return result;
}
@Override
public List<GameContentComment> getGameContentComments(long contentId, int page) {
List<GameContentComment> result = new ArrayList<GameContentComment>();
try {
String query = "SELECT " +
"contentcomments.id, " +
"contentcomments.text, " +
"contentcomments.time, " +
"users.uid AS ownerid, " +
"users.name AS ownername " +
"FROM " +
"contentcomments INNER JOIN users ON contentcomments.uid = users.uid " +
"WHERE " +
"contentcomments.contentid = " + contentId + " " +
"ORDER BY " +
"time ASC " +
"LIMIT " +
((page - 1) * EntriesPerPage_ContentComments) + ", " +
EntriesPerPage_ContentComments;
ResultSet queryResult = db.execQueryWithResult(query);
while (queryResult.next()) {
result.add(new GameContentComment(queryResult.getLong("id"), queryResult.getLong("ownerid"), queryResult.getString("ownername"), queryResult
.getString("text"), queryResult.getTimestamp("time")));
}
} catch (Exception e) {
logger.Error(e);
}
return result;
}
@Override
public int getGameCommentsPages(long contentId) {
int result = 0;
try {
String query = "SELECT " +
"COUNT(DISTINCT id) AS gamecontentcommentscount " +
"FROM " +
"contentcomments " +
"WHERE " +
"contentid = " + contentId
+ ";";
ResultSet queryResult = db.execQueryWithResult(query);
if (!queryResult.next())
return -1;
result = (int) Math.ceil(((double) queryResult.getInt("gamecontentcommentscount")) / EntriesPerPage_ContentComments);
} catch (Exception e) {
logger.Error(e);
}
return result;
}
@Override
public boolean setGameContentRating(long userId, long contentId, double rating) {
try {
// Already rated?
String query = "SELECT " + "uid " + "FROM " + "contentratings " + "WHERE " + "uid = " + userId + " " + "AND contentid = " + contentId + ";";
ResultSet queryResult = db.execQueryWithResult(query);
if (!queryResult.next()) {
// Insert new entry
query = "INSERT INTO " + "contentratings " + "VALUES (" + userId + ", " + contentId + ", " + rating + ", " + "NOW());";
db.execQuery(query);
} else {
// Update old entry
query = "UPDATE " + "contentratings " + "SET " + "value = " + rating + ", " + "time = NOW() " + "WHERE " + "uid = " + userId + " "
+ "AND contentid = " + contentId + ";";
db.execQuery(query);
}
} catch (Exception e) {
logger.Error(e);
return false;
}
return true;
}
@Override
public boolean setGameContentComment(long userId, long contentId, String text) {
try {
String query = "INSERT INTO contentcomments(uid, contentid, text, time) VALUES (" + userId + ", " + contentId
+ ", '" + text + "', " + "NOW());";
db.execQuery(query);
} catch (Exception e) {
logger.Error(e);
return false;
}
return true;
}
@Override
public boolean setContentVisibility(long userId, long contentId, int selectedIndex) {
try {
String query = "UPDATE " + "gamecontent " + "SET " + "visibility = " + selectedIndex + " " + "WHERE " + "id = " + contentId + " " + "AND owner = "
+ userId + ";";
db.execQuery(query);
} catch (Exception e) {
logger.Error(e);
return false;
}
return true;
}
@Override
public boolean removeContent(long userId, long contentId) {
try {
if (userIsAdmin(userId) || userOwnsContent(userId, contentId)) {
String query = "DELETE FROM " + "gamecontent " + "WHERE " + "id = " + contentId;
db.execQuery(query);
query = "DELETE FROM " + "contentcomments " + "WHERE " + "contentid = " + contentId;
db.execQuery(query);
query = "DELETE FROM " + "contentratings " + "WHERE " + "contentid = " + contentId;
db.execQuery(query);
} else
return false;
} catch (Exception e) {
logger.Error(e);
return false;
}
return true;
}
@Override
public boolean removeContentComment(long userId, long commentId) {
try {
if (userIsAdmin(userId) || userOwnsComment(userId, commentId)) {
String query = "DELETE FROM " + "contentcomments " + "WHERE " + "id = " + commentId;
db.execQuery(query);
} else
return false;
} catch (Exception e) {
logger.Error(e);
return false;
}
return true;
}
private GameContentComment getLastComment(long cid) {
GameContentComment result = null;
try {
String query = "SELECT " +
"contentcomments.id, " +
"contentcomments.text, " +
"contentcomments.time, " +
"users.uid AS ownerid, " +
"users.name AS ownername " +
"FROM " +
"contentcomments INNER JOIN users ON contentcomments.uid = users.uid " +
"WHERE " +
"contentcomments.contentid = " + cid + " " +
"ORDER BY " +
"time DESC " +
"LIMIT 0, 1";
ResultSet queryResult = db.execQueryWithResult(query);
if (queryResult.next())
result = new GameContentComment(queryResult.getLong("id"), queryResult.getLong("ownerid"), queryResult.getString("ownername"),
queryResult.getString("text"), queryResult.getTimestamp("time"));
} catch (Exception e) {
logger.Error(e);
}
return result;
}
private boolean userOwnsContent(long userId, long contentId) {
boolean result = false;
try {
String query = "SELECT owner FROM gamecontent WHERE id = " + contentId + ";";
ResultSet queryResult = db.execQueryWithResult(query);
if (!queryResult.next())
return false;
result = (queryResult.getLong("owner") == userId);
} catch (Exception e) {
logger.Error(e);
return false;
}
return result;
}
private boolean userOwnsComment(long userId, long commentId) {
boolean result = false;
try {
String query = "SELECT uid FROM contentcomments WHERE id = " + commentId + ";";
ResultSet queryResult = db.execQueryWithResult(query);
if (!queryResult.next())
return false;
result = (queryResult.getLong("uid") == userId);
} catch (Exception e) {
logger.Error(e);
return false;
}
return result;
}
@Override
public boolean registerContentHit(long cid) {
try {
String query = "UPDATE gamecontent SET hits = hits + 1 WHERE id = '" + cid + "'";
return db.execQuery(query) == 1;
} catch (SQLException e) {
logger.Error(e);
return false;
}
}
private boolean userIsAdmin(long userId) {
return HSQLUserDatabaseAccess.getInstance().userIsAdmin(userId);
}
@Override
public byte[] getContentBytes(long contentid) {
try{
String query = "SELECT content FROM gamecontent WHERE id = " + contentid;
ResultSet rs = db.execQueryWithResult(query);
if(!rs.next())
return null;
Blob b = rs.getBlob("content");
if(b == null)
return null;
InputStream input = b.getBinaryStream();
if (input == null)
return null;
ByteArrayOutputStream byteout = new ByteArrayOutputStream();
while (input.available() > 0)
byteout.write(input.read());
byte[] contentBytes = byteout.toByteArray();
return contentBytes;
}catch(IOException e){
logger.Error(e);
} catch (SQLException e) {
logger.Error(e);
}
return null;
}
@Deprecated
public GameContent getGameContent1(long uid, long cid) {
logger.Error("DEPRECATED METHOD USED (getGameContent1)");
GameContent result = null;
try {
// Blobs do not work with AVG, so two queries are necessary
String query =
"SELECT " +
"gamecontent.content " +
"FROM " +
"(gamecontent INNER JOIN gamecontexts ON gamecontent.contextid = gamecontexts.id) " +
"INNER JOIN userprogress ON gamecontent.contextid = userprogress.scnid " +
"WHERE " +
"gamecontent.id = " + cid + " " +
"AND userprogress.uid = " + uid + ";";
ResultSet queryResult = db.execQueryWithResult(query);
if (!queryResult.next())
return null;
Blob b = queryResult.getBlob("content");
if(b == null)
return null;
InputStream input = b.getBinaryStream();
if (input == null)
return null;
ByteArrayOutputStream byteout = new ByteArrayOutputStream();
while (input.available() > 0)
byteout.write(input.read());
@SuppressWarnings("unused")
byte[] content = byteout.toByteArray();
query = "SELECT " +
"gamecontent.id, " +
"gamecontent.title, " +
"gamecontent.description, " +
"gamecontent.time, " +
"gamecontent.visibility, " +
"gamecontent.hits, " +
"contenttypes.name AS typename, " +
"users.uid AS ownerid, " +
"users.name AS ownername, " +
"gamecontexts.name AS context, " +
"ratingsown.value AS ratingown, " +
"fim.friendid IS NOT NULL AS isfriend, " +
"COUNT(DISTINCT contentcomments.id) as comments, " +
"COUNT(ratingsavg.value) as ratingscount, " +
"AVG(ratingsavg.value) AS ratingavg " +
"FROM " +
"((((((gamecontent INNER JOIN contenttypes ON gamecontent.type = contenttypes.id) " +
"INNER JOIN users ON gamecontent.owner = users.uid) " +
"INNER JOIN gamecontexts ON gamecontent.contextid = gamecontexts.id) " +
"INNER JOIN userprogress ON gamecontent.contextid = userprogress.scnid) " +
"LEFT JOIN (SELECT contentid, value FROM contentratings WHERE uid = " + uid + ") " +
"AS ratingsown ON gamecontent.id = ratingsown.contentid) " +
"LEFT JOIN (" +
"SELECT " +
"uid, " +
"friendid " +
"FROM " +
"usersnfriends " +
"WHERE " +
"friendid = " + uid + ") " +
"AS fim ON gamecontent.owner = fim.uid " +
"LEFT JOIN contentratings AS ratingsavg ON gamecontent.id = ratingsavg.contentid) " +
"LEFT JOIN contentcomments ON gamecontent.id = contentcomments.contentid " +
"WHERE " +
"gamecontent.id = " + cid + " " +
"AND userprogress.uid = " + uid + " " +
"GROUP BY " +
"gamecontent.id, " +
"gamecontent.title, " +
"gamecontent.description, " +
"gamecontent.time, " +
"gamecontent.visibility, " +
"gamecontent.hits, " +
"contenttypes.name, " +
"users.uid, " +
"users.name, " +
"gamecontexts.name, " +
"ratingsown.value, " +
"fim.friendid";
queryResult = db.execQueryWithResult(query);
if (!queryResult.next())
return null;
if (queryResult.getInt("visibility") == 2 || (queryResult.getInt("visibility") == 1 && queryResult.getBoolean("isfriend")) || userIsAdmin(uid)
|| uid == queryResult.getInt("ownerid"))
result = new GameContent(queryResult.getLong("id"), queryResult.getInt("visibility"), queryResult.getString("title"),
queryResult.getString("description"), queryResult.getString("context"), queryResult.getString("typename"), queryResult.getInt("ownerid"),
queryResult.getString("ownername"), queryResult.getTimestamp("time"), queryResult.getDouble("ratingavg"),
queryResult.getInt("ratingscount"), queryResult.getInt("comments"),
queryResult.getInt("hits"), getLastComment(cid));
else
result = new GameContent(queryResult.getLong("id"), -1, null, null, null, null, -1, null, null, -1, -1, -1, -1, null);
} catch (Exception e) {
logger.Error(e);
}
return result;
}
@Deprecated
public List<GameContent> getGameContents1(long uid, long gid, int page) {
logger.Error("DEPRECATED METHOD USED (getGameContents1)");
List<GameContent> result = new ArrayList<GameContent>();
try {
String query = "SELECT " +
"gamecontent.id, " +
"gamecontent.title, " +
"gamecontent.description, " +
"gamecontent.time, " +
"gamecontent.visibility, " +
"gamecontent.hits, " +
"contenttypes.name AS typename, " +
"users.uid AS ownerid, " +
"users.name AS ownername, " +
"gamecontexts.name AS context, " +
"ratingsown.value AS ratingown, " +
"COUNT(DISTINCT contentcomments.id) as comments, " +
"COUNT(ratingsavg.value) as ratingscount, " +
"AVG(ratingsavg.value) AS ratingavg " +
"FROM " +
"(((((((gamecontent INNER JOIN contenttypes ON gamecontent.type = contenttypes.id) " +
"INNER JOIN users ON gamecontent.owner = users.uid) " +
"INNER JOIN gamecontexts ON gamecontent.contextid = gamecontexts.id) " +
"INNER JOIN userprogress ON gamecontent.contextid = userprogress.scnid) " +
"LEFT JOIN (" +
"SELECT contentid, value FROM contentratings WHERE uid = " + uid + ") " +
"AS ratingsown ON gamecontent.id = ratingsown.contentid) " +
"LEFT JOIN (" +
"SELECT " +
"uid, " +
"friendid " +
"FROM " +
"usersnfriends " +
"WHERE " +
"friendid = " + uid + ") " +
"AS fim ON gamecontent.owner = fim.uid) " +
"LEFT JOIN contentratings AS ratingsavg ON gamecontent.id = ratingsavg.contentid) " +
"LEFT JOIN contentcomments ON gamecontent.id = contentcomments.contentid " +
"WHERE " +
"gamecontexts.gameinstid = " + gid + " " +
"AND userprogress.uid = " + uid + " " +
(!userIsAdmin(uid) ?
"AND (gamecontent.visibility = 2 OR (gamecontent.visibility = 1 AND fim.friendid IS NOT NULL))" : "") +
"GROUP BY " +
"gamecontent.id, " +
"gamecontent.title, " +
"gamecontent.time, " +
"gamecontent.description, " +
"gamecontent.visibility, " +
"gamecontent.hits, " +
"contenttypes.name, " +
"users.uid, " +
"users.name, " +
"gamecontexts.name, " +
"ratingsown.value " +
"ORDER BY " +
"gamecontexts.name ASC " +
"LIMIT " +
((page - 1) * EntriesPerPage_ContentContexts) + ", " +
EntriesPerPage_ContentContexts + ";";
ResultSet queryResult = db.execQueryWithResult(query);
while (queryResult.next()) {
result.add(new GameContent(queryResult.getLong("id"), queryResult.getInt("visibility"), queryResult.getString("title"), queryResult
.getString("description"), queryResult.getString("context"), queryResult.getString("typename"), queryResult.getInt("ownerid"),
queryResult.getString("ownername"), queryResult.getTimestamp("time"), queryResult.getDouble("ratingavg"),
queryResult.getInt("ratingscount"), queryResult.getInt("comments"), queryResult.getInt("hits"),
getLastComment(queryResult.getLong("id"))));
}
} catch (Exception e) {
logger.Error(e);
}
return result;
}
@Deprecated
public int getGameContentsPages1(long userId, long gameId) {
logger.Error("DEPRECATED METHOD USED (getGameContentsPages1)");
int result = 0;
try {
String query = "SELECT " +
"COUNT(DISTINCT gamecontent.id) AS gamecontentscount " +
"FROM " +
"((gamecontent INNER JOIN gamecontexts ON gamecontent.contextid = gamecontexts.id) " +
"INNER JOIN userprogress ON gamecontent.contextid = userprogress.scnid) " +
"LEFT JOIN (" +
"SELECT " +
"uid, " +
"friendid " +
"FROM " +
"usersnfriends " +
"WHERE " +
"friendid = " + userId + ") AS fim ON gamecontent.owner = fim.uid " +
"WHERE " +
"gamecontexts.gameinstid = " + gameId + " " +
"AND userprogress.uid = " + userId +
(!userIsAdmin(userId) ?
"AND (gamecontent.visibility = 2 " +
"OR (gamecontent.visibility = 1 AND fim.friendid IS NOT NULL))" : "");
ResultSet queryResult = db.execQueryWithResult(query);
if (!queryResult.next())
return -1;
result = (int) Math.ceil(((double) queryResult.getInt("gamecontentscount")) / EntriesPerPage_ContentContexts);
} catch (Exception e) {
logger.Error(e);
}
return result;
}
}