package de.tud.kom.socom.components.influence;
import java.io.IOException;
import java.sql.SQLException;
import org.apache.commons.fileupload.FileUploadException;
import org.json.JSONException;
import org.json.JSONObject;
import de.tud.kom.socom.SocomComponent;
import de.tud.kom.socom.components.social.SocialNetworkManager;
import de.tud.kom.socom.database.influence.HSQLInfluenceDatabase;
import de.tud.kom.socom.database.influence.InfluenceDatabase;
import de.tud.kom.socom.util.SocomRequest;
import de.tud.kom.socom.util.JSONUtils;
import de.tud.kom.socom.util.LoggerFactory;
import de.tud.kom.socom.util.datatypes.InfluenceConfiguration;
import de.tud.kom.socom.util.datatypes.InfluenceResult;
import de.tud.kom.socom.util.exceptions.CurrentGameInstanceNotIncludedException;
import de.tud.kom.socom.util.exceptions.SocomException;
import de.tud.kom.socom.util.exceptions.IllegalAccessException;
import de.tud.kom.socom.util.exceptions.IllegalParameterException;
import de.tud.kom.socom.util.exceptions.InfluenceNotAvailableException;
import de.tud.kom.socom.util.exceptions.InfluenceTemplateException;
import de.tud.kom.socom.util.exceptions.ParseException;
import de.tud.kom.socom.util.exceptions.UIDNotIncludedException;
/**
*
* @author rhaban
*
*/
public class InfluenceManager extends SocomComponent {
private static final String URL_PATTERN = "influence";
private static final InfluenceManager instance = new InfluenceManager();
private static InfluenceDatabase db;
private InfluenceManager() {
db = HSQLInfluenceDatabase.getInstance();
if (!InfluenceUploadHandler.DATA_DIR.exists() || !InfluenceUploadHandler.DATA_DIR.isDirectory()) {
InfluenceUploadHandler.DATA_DIR.mkdir();
}
}
public static InfluenceManager getInstance() {
return instance;
}
@Override
public String getUrlPattern() {
return URL_PATTERN;
}
/**
* Prepares a template for polls, which can later be used in createInfluence inheriting
* settings of the template
*
* @param see createInfluence
* @return Influence-ID
* @throws JSONException
* @throws SQLException
* @throws SocomException
* @throws IOException
*/
public int createInfluenceTemplate(SocomRequest req) throws JSONException, SQLException, SocomException, IOException {
try {
int vis = Integer.valueOf(req.getParam("visibility"));
return createInfluence(req, vis, true);
} catch (NumberFormatException e) {
throw new IllegalParameterException("visibility must be of type integer.");
}
}
/**
* Prepares a poll which can be shown in the webapplication. Answeres with
* the id of the created Poll.
*
* @param visibility
* @param question
* @param type
* @param allowfreeanswers (boolean)
* @param freeanswersvotable (boolean)
* @param Optional
* : publish (boolean if the influence should be published in the
* SN's)
* @param Optional
* : message If the influence should be published via SNs this is
* the message for the post
* @param Optional
* : time If the influence should be published the influence must
* be started directly. This is the time when it should end
*
* @return Influence-ID and Post-Ids if published
* @throws JSONException
* @throws SQLException
* @throws IOException
*/
public int createInfluence(SocomRequest req) throws JSONException, SQLException, SocomException, IOException {
try {
if(req.containsParam("templateid")) {
String templateid = req.getParam("templateid");
return createInfluenceFromTemplate(req, templateid);
}
int vis = Integer.valueOf(req.getParam("visibility"));
return createInfluence(req, vis, false);
} catch (NumberFormatException e) {
throw new IllegalParameterException("visibility must be of type integer.");
}
}
private int createInfluenceFromTemplate(SocomRequest req, String templateid) throws JSONException, UIDNotIncludedException, SQLException, CurrentGameInstanceNotIncludedException, InfluenceNotAvailableException, InfluenceTemplateException {
long uid = req.getUid();
long gid = req.getCurrentGameInst();
String externalId = db.copyInfluenceTemplate(uid, gid, templateid);
JSONObject json = new JSONObject();
json.put("id", externalId);
req.addOutput(JSONUtils.JSONToString(json));
return 0;
}
private int createInfluence(SocomRequest req, int visibility, boolean template) throws JSONException, SQLException, SocomException, IOException {
try {
long uid = req.getUid();
long gid = req.getCurrentGameInst();
String question = req.getParam("question");
String type = req.getParam("type");
String externalId = InfluenceFactory.createInfluence(uid, gid, question, type, visibility, req, template);
if (externalId == null)
return 1; // unknown error
JSONObject json = new JSONObject();
json.put("id", externalId);
if (req.containsParam("publish") && !template) {
boolean publish = Boolean.parseBoolean(req.getParam("publish"));
if (publish) {
String message = req.getParam("message");
boolean publishOnPage = req.getParam("publishonpage", false);
int time = Integer.parseInt(req.getParam("time"));
db.startInfluence(uid, externalId, time);
json.put("postids", SocialNetworkManager.getInstance().publishInfluence(publishOnPage, uid, gid, message, externalId));
}
}
req.addOutput(JSONUtils.JSONToString(json));
} catch (NumberFormatException e) {
throw new IllegalParameterException("time must be of type long");
}
return 0;
}
/**
* Creates a predefined answer for a text-influence.
*
* @param id
* @param answer
*
* @return success boolean
* @throws JSONException
* @throws SQLException
*/
public int addPredefinedAnswer(SocomRequest req) throws JSONException, SQLException, SocomException {
long uid = req.getUid();
String externalid = req.getParam("id");
String answer = req.getParam("answer");
long id = db.addPredefinedAnswer(uid, externalid, answer);
req.addOutput(JSONUtils.JSONToString(new JSONObject().put("answerid", id)));
return 0;
}
/**
* HTTP-POST-Method
* Creates a predefined answer with binary content
*
* All Parameters are expected as cookies. Furthermore the stream should contain the content
*
* @param id Influence-ID
* @param answer
* @param fileextension
* @return success boolean
* @throws IOException
* @throws SQLException
* @throws JSONException
*/
public int addPredefinedAnswerWithData(SocomRequest req) throws IOException, SQLException, JSONException {
return InfluenceUploadHandler.addPredefinedData(req);
}
/**
* (Hard-)Removes a predefined answer with the given id in the given influence
* if the current user id administrator or the owner
* @param influenceid external-id of the influence
* @param answerid id of the answer
* @return success boolean
* @throws NumberFormatException
* @throws SocomException
* @throws SQLException
*/
public int removePredefinedAnswer(SocomRequest req) throws NumberFormatException, SocomException, SQLException {
long uid = req.getUid();
String externalid = req.getParam("influenceid");
long answerid = Long.parseLong(req.getParam("answerid"));
boolean success = db.removePredefinedAnswer(uid, externalid, answerid);
req.addOutput(JSONUtils.getSuccessJsonString(success));
return 0;
}
/**
* Starts an influence with the given timeout.
*
* @param id of the Influence
* @param time in s ('permanent' or negative value for unlimited time)
*
* @return success boolean
* @throws JSONException
* @throws SQLException
*/
public int startInfluence(SocomRequest req) throws JSONException, SQLException, SocomException {
long uid = req.getUid();
String externalid = req.getParam("id");
String timeParam = req.getParam("time");
if(timeParam.equalsIgnoreCase("permanent"))
timeParam = "-1";
int time = Integer.parseInt(timeParam);
db.startInfluence(uid, externalid, time);
req.addOutput(JSONUtils.getSuccessJsonString());
return 0;
}
/**
* Stops an influence.
*
* @param id Influence-ID
* @return success boolean
*
* @throws JSONException
* @throws SQLException
*/
public int stopInfluence(SocomRequest req) throws JSONException, SQLException, SocomException {
long uid = req.getUid();
String externalid = req.getParam("id");
db.stopInfluence(uid, externalid);
req.addOutput(JSONUtils.getSuccessJsonString());
return 0;
}
/**
* Shows the current results of a voting or inquiry.
*
* @param id Influence-Id
*
* @return error code
*/
public int fetchResult(SocomRequest req) throws SQLException, SocomException {
long uid = req.getUid();
String externalid = req.getParam("id");
InfluenceResult result = db.fetchResult(uid, externalid);
req.addOutput(result.toJSONString());
return 0;
}
/**
* shows the configuration of the correspoding influence
*
* @param id externalid of influence to see
* @return configuration (de.tud.kom.socom.util.datatypes.InfluenceConfiguration)
* @throws SocomException
* @throws SQLException
*/
public int getInfluence(SocomRequest req) throws SocomException, SQLException {
long uid = req.getUid();
String externalid = req.getParam("id");
InfluenceResult result = db.fetchResult(uid, externalid);
InfluenceConfiguration config = db.readConfiguration(uid, externalid);
JSONObject infl = config.getJSON();
try {
infl.put("result", result.getJSON());
} catch (JSONException e) {
LoggerFactory.getLogger().Error(e);
}
req.addOutput(JSONUtils.JSONToString(infl));
return 0;
}
/**
* change the configuration of an influence or an influence template using the given parameter
*
* all parameter (except externalid) are optional and only the specified are overwritten
*
* @param externalid
* @param question
* @param type
* @param minchoices
* @param maxchoices
* @param maxdigits
* @param maxlines
* @param maxbyes
* @param visibility
* @param allowfreeanswers
* @param freeanswersvotable
*
* @return success boolean
* @throws ParseException
* @throws IllegalParameterException
* @throws UIDNotIncludedException
* @throws SQLException
* @throws IllegalAccessException
* @throws InfluenceNotAvailableException
*/
public int changeInfluence(SocomRequest req) throws SocomException, SQLException {
String externalid = req.getParam("id");
long uid = req.getUid();
String question = req.containsParam("question") ? req.getParam("question") : null;
String type = req.containsParam("type") ? req.getParam("type") : null;
boolean success = false;
try{
int minchoices = req.containsParam("minchoices") ? Integer.parseInt(req.getParam("minchoices")) : -1;
int maxchoices = req.containsParam("maxchoices") ? Integer.parseInt(req.getParam("maxchoices")) : -1;
int maxdigits = req.containsParam("maxdigits") ? Integer.parseInt(req.getParam("maxdigits")) : -1;
int maxlines = req.containsParam("maxlines") ? Integer.parseInt(req.getParam("maxlines")) : -1;
int maxBytes = req.containsParam("maxbytes") ? Integer.parseInt(req.getParam("maxbytes")) : -1;
int visibility = req.containsParam("visibility") ? Integer.parseInt(req.getParam("visibility")) : -1;
boolean containsAllowFree = req.containsParam("allowfreeanswers");
boolean containsFreeVotable = req.containsParam("freeanswersvotable");
boolean allowFree = containsAllowFree ? Boolean.parseBoolean(req.getParam("allowfreeanswers")) : false;
boolean freeVotable = containsFreeVotable? Boolean.parseBoolean(req.getParam("freeanswersvotable")) : false;
success = db.changeConfiguration(uid, externalid, question, type, minchoices, maxchoices, maxdigits, maxlines,
maxBytes, visibility, containsAllowFree, allowFree, containsFreeVotable, freeVotable);
}catch(NumberFormatException e) {
throw new IllegalParameterException(e.getMessage());
}
req.addOutput(JSONUtils.getSuccessJsonString(success));
return 0;
}
/**
* Only used from Web-Application to upload an Influence Image
*/
public int uploadInfluenceData(SocomRequest req) throws FileUploadException, IOException, SQLException, JSONException {
if (!req.isMultipartContent()) return 19;
return InfluenceUploadHandler.addFreeData(req);
}
}