package ca.ualberta.cs.cmput301t03app.datamanagers;
import java.util.ArrayList;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Type;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import android.util.Log;
import ca.ualberta.cs.cmput301t03app.interfaces.IDataManager;
import ca.ualberta.cs.cmput301t03app.models.Answer;
import ca.ualberta.cs.cmput301t03app.models.Comment;
import ca.ualberta.cs.cmput301t03app.models.Hits;
//import ca.ualberta.cs.cmput301t03app.models.Post;
import ca.ualberta.cs.cmput301t03app.models.Question;
import ca.ualberta.cs.cmput301t03app.models.SearchHit;
import ca.ualberta.cs.cmput301t03app.models.SearchResponse;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;
/**
* Manages the saving and loading of gson files to elastic search server.
* <p>
* All questions will be saved to server.
*
*/
public class ServerDataManager implements IDataManager{
private static final String SEARCH_URL = "http://cmput301.softwareprocess.es:8080/cmput301f14t03/question/_search?size=1000000";
private static final String RESOURCE_URL = "http://cmput301.softwareprocess.es:8080/cmput301f14t03/question/";
private static final String TAG = "QuestionSearch";
private Gson gson;
private GsonBuilder builder;
public ServerDataManager() {
builder = new GsonBuilder();
gson = builder.setDateFormat("yyyy-MM-dd HH:mm:ss.SSS")
.create();
builder.serializeNulls(); // Show fields with null values
}
/**
* Get a question with the specified id
*/
@Override
public ArrayList<Question> loadQuestions() {
// TODO Auto-generated method stub
return null;
}
public void saveAnswers(ArrayList<Answer> list) {
// TODO Auto-generated method stub
}
@Override
public void saveToQuestionBank(ArrayList<Question> list) {
// TODO Auto-generated method stub
}
/**
* Updates the number of upvotes for a question on the server.
* @param questionId - The question that is being updated
* @param amount - The number of upvotes to be added to the question upvotes
*/
public void pushQuestionUpvote(String questionId, Integer amount) {
try {
Question q = getQuestion(questionId);
for (int i = 0; i < amount; i++) {
q.upRating();
}
updateQuestion(q);
} catch (Exception e) {
}
}
/**
* Updates the number of upvotes for an answer on the server.
* @param answerId - the answer that is being updated
* @param questionId - the question that the answer is pertaining to
* @param amount - the number of upvotes to be added to the answer upvotes
*/
public void pushAnswerUpvote(String answerId, String questionId, Integer amount) {
try {
Question q = getQuestion(questionId);
ArrayList<Answer> answers = q.getAnswers();
for (int i = 0; i < answers.size(); i++) {
if (answers.get(i).getId().equals(answerId)) {
for (int j = 0; j < amount; j++) {
answers.get(i).upRating();
}
}
}
q.setAnswers(answers);
updateQuestion(q);
} catch (Exception e) {
}
}
/**
* Gets the question from server using the questionId
* @param questionId - the id of the question to be returned
* @return - the question
*/
public Question getQuestion(String questionId) {
HttpClient httpClient = new DefaultHttpClient();
HttpGet httpGet = new HttpGet(RESOURCE_URL + questionId);
HttpResponse response;
try {
response = httpClient.execute(httpGet);
String status = response.getStatusLine().toString();
Log.i(TAG, status);
SearchHit<Question> sr = parseQuestionHit(response);
return sr.getSource();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* Get questions with the specified search string. If the search does not
* specify fields, it searches on all the fields.
*/
public ArrayList<Question> searchQuestions(String searchString, String field) {
ArrayList<Question> result = new ArrayList<Question>();
if (searchString.equals(null) || searchString.equals("")) {
searchString = "*";
}
HttpClient httpClient = new DefaultHttpClient();
try
{
HttpPost searchRequest = createSearchRequest(searchString, field);
HttpResponse response = httpClient.execute(searchRequest);
String status = response.getStatusLine().toString();
Log.i(TAG, status);
SearchResponse<Question> esResponse = parseSearchResponse(response);
Hits<Question> hits = esResponse.getHits();
if (hits != null) {
if (hits.getHits() != null) {
for (int i = 0; i < hits.getHits().size(); i++) {
SearchHit<Question> sesr = hits.getHits().get(i);
Question q = sesr.getSource();
q.setId(sesr.get_id()); // for some reason q.getId() was returning null
// so I added this.
result.add(q);
}
}
}
} catch (UnsupportedEncodingException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClientProtocolException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
return result;
}
/**
* adds a question to server
* @param question - the question to be added to the server
*/
public void addQuestion(Question question) {
HttpClient httpClient = new DefaultHttpClient();
try {
Log.d("push", question.getId());
HttpPost addRequest = new HttpPost(RESOURCE_URL + question.getId());
StringEntity stringEntity = new StringEntity(gson.toJson(question));
addRequest.setEntity(stringEntity);
addRequest.setHeader("Accept", "application/json");
HttpResponse response = httpClient.execute(addRequest);
String status = response.getStatusLine().toString();
Log.d("push", status);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* Updates a question in server
* @param question - the question to be updated
*/
public void updateQuestion(Question question) {
deleteQuestion(question.getId());
addQuestion(question);
}
/**
* Deletes the question with the specified id
* @param questionId - the id of the question to be deleted
*/
public void deleteQuestion(String questionId) {
HttpClient httpClient = new DefaultHttpClient();
try {
HttpDelete deleteRequest = new HttpDelete(RESOURCE_URL + questionId);
deleteRequest.setHeader("Accept", "application/json");
HttpResponse response = httpClient.execute(deleteRequest);
String status = response.getStatusLine().toString();
Log.i(TAG, status);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* creates a searchRequest that will be used by elastic search to return the results of the search
* @param searchString - the word that will be used to search through the server
* @param field - the field that the word will be searched through
* @return HttpPost - an httpPost that will be needed to be parsed
* @throws UnsupportedEncodingException
*/
private HttpPost createSearchRequest(String searchString, String field) throws UnsupportedEncodingException {
HttpPost searchRequest = new HttpPost(SEARCH_URL);
String[] fields = null;
if (field != null) {
fields = new String[1];
fields[0] = field;
}
SimpleSearchCommand command = new SimpleSearchCommand(searchString, fields);
String query = command.getJsonCommand();
Log.i(TAG, "Json command: " + query);
StringEntity stringEntity;
stringEntity = new StringEntity(query);
searchRequest.setHeader("Accept", "application/json");
searchRequest.setEntity(stringEntity);
return searchRequest;
}
/**
* Returns the search hit from elastic search server
* @param response -the httpResponse that is returned when connected to server
* @return the search hit from elastic search server
*/
private SearchHit<Question> parseQuestionHit(HttpResponse response) {
try {
String json = getEntityContent(response);
Type searchHitType = new TypeToken<SearchHit<Question>>() {}.getType();
SearchHit<Question> sr = gson.fromJson(json, searchHitType);
return sr;
}
catch (IOException e) {
e.printStackTrace();
}
return null;
}
/**
* Returns a SearchResponse after being parsed
* @param response - the httpResponse that is returned when connected to server
* @return a search response
* @throws IOException
*/
private SearchResponse<Question> parseSearchResponse(HttpResponse response) throws IOException {
String json;
json = getEntityContent(response);
Type searchResponseType = new TypeToken<SearchResponse<Question>>() {
}.getType();
SearchResponse<Question> esResponse = gson.fromJson(json, searchResponseType);
return esResponse;
}
/**
* Returns the content of a http response
* @param response - the http response to be parsed
* @return a string that pertains to the content of the http response
* @throws IOException
*/
public String getEntityContent(HttpResponse response) throws IOException {
BufferedReader rd = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
StringBuffer result = new StringBuffer();
String line = "";
while ((line = rd.readLine()) != null) {
result.append(line);
}
return result.toString();
}
}