package ca.ualberta.cs.cmput301f14t14.questionapp.data; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.ObjectInput; import java.io.ObjectInputStream; import java.io.ObjectOutput; import java.io.ObjectOutputStream; import java.io.OutputStream; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.UUID; import android.content.Context; import android.util.Log; import ca.ualberta.cs.cmput301f14t14.questionapp.model.Answer; import ca.ualberta.cs.cmput301f14t14.questionapp.model.Comment; import ca.ualberta.cs.cmput301f14t14.questionapp.model.Question; public class LocalDataStore implements IDataStore { private static final String QUESTION_SAVE_FILE = "local_data_question.sav"; private static final String ANSWER_SAVE_FILE = "local_data_answers.sav"; private static final String QCOMMENT_SAVE_FILE = "local_data_qcomments.sav"; private static final String ACOMMENT_SAVE_FILE = "local_data_acomments.sav"; private Context context; private Map<UUID, Question> questions; private Map<UUID, Answer> answers; private Map<UUID, Comment<Question>> qcomments; private Map<UUID, Comment<Answer>> acomments; public LocalDataStore(Context context) { this.context = context; load(); } public List<Question> getQuestionList(){ return new ArrayList<Question>(questions.values()); } /** * {@inheritDoc} * * This implementation will return all answers available locally. * If they are not available locally, they will not be included. */ public List<Answer> getAnswerList(Question question) { List<Answer> list = new ArrayList<Answer>(); for (UUID aId: question.getAnswerList()) { Answer a = getAnswer(aId); if (a != null) { list.add(a); } } return list; } /** * {@inheritDoc} * * This implementation will return all comments available locally. * If they are not available locally, they will not be included. */ public List<Comment<Question>> getCommentList(Question question) { List<Comment<Question>> list = new ArrayList<Comment<Question>>(); for (UUID cId: question.getCommentList()) { Comment<Question> c = getQComment(cId); if (c != null) { list.add(c); } } return list; } /** * {@inheritDoc} * * This implementation will return all comments available locally. * If they are not available locally, they will not be included. */ public List<Comment<Answer>> getCommentList(Answer answer) { List<Comment<Answer>> list = new ArrayList<Comment<Answer>>(); for (UUID cId: answer.getCommentList()) { Comment<Answer> c = getAComment(cId); if (c != null) { list.add(c); } } return list; } public void save() { saveObject(questions, QUESTION_SAVE_FILE); saveObject(answers, ANSWER_SAVE_FILE); saveObject(qcomments, QCOMMENT_SAVE_FILE); saveObject(acomments, ACOMMENT_SAVE_FILE); } private void saveObject(Object data, String saveFile) { OutputStream os; ObjectOutput oo; try { os = new BufferedOutputStream(context.openFileOutput(saveFile, Context.MODE_PRIVATE)); oo = new ObjectOutputStream(os); try { oo.writeObject(data); Log.d("save", "Saved data to file " + saveFile); } finally { oo.close(); } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } /** * Load serialized files. * * This is horrible code. */ @SuppressWarnings("unchecked") private void load() { questions = (HashMap<UUID, Question>) loadObject(QUESTION_SAVE_FILE); answers = (HashMap<UUID, Answer>) loadObject(ANSWER_SAVE_FILE); qcomments = (HashMap<UUID, Comment<Question>>) loadObject(QCOMMENT_SAVE_FILE); acomments = (HashMap<UUID, Comment<Answer>>) loadObject(ACOMMENT_SAVE_FILE); if (questions == null) questions = new HashMap<UUID, Question>(); if (answers == null) answers = new HashMap<UUID, Answer>(); if (qcomments == null) qcomments = new HashMap<UUID, Comment<Question>>(); if (acomments == null) acomments = new HashMap<UUID, Comment<Answer>>(); } private Object loadObject(String saveFile) { InputStream is; ObjectInput oi; Object o; try { try { is = new BufferedInputStream(context.openFileInput(saveFile)); } catch (FileNotFoundException e) { Log.d("load", "Serialized file " + saveFile + " not found."); return null; } oi = new ObjectInputStream(is); try { o = oi.readObject(); if (o == null) { Log.e("load", "Loaded data was null."); } else { Log.d("load", "Successfully loaded data from " + saveFile); } return o; } catch (ClassNotFoundException e) { e.printStackTrace(); } finally { oi.close(); } } catch (IOException e) { e.printStackTrace(); } Log.e("load", "Error loading."); return null; } public void putQuestion(Question question) { questions.put(question.getId(), question); } public Question getQuestion(UUID id) { return questions.get(id); } public void putAnswer(Answer answer) { answers.put(answer.getId(), answer); } public Answer getAnswer(UUID id) { return answers.get(id); } public void putQComment(Comment<Question> comment) { qcomments.put(comment.getId(), comment); } public Comment<Question> getQComment(UUID id) { return qcomments.get(id); } public void putAComment(Comment<Answer> comment) { acomments.put(comment.getId(), comment); } public Comment<Answer> getAComment(UUID id) { return acomments.get(id); } /** * Clear the internal data structures. * * To persist this, you should call save() after. */ public void clear() { questions.clear(); answers.clear(); qcomments.clear(); acomments.clear(); } @Override public boolean equals(Object o) { if (!(o instanceof LocalDataStore)) { Log.e("equals", "Object is of incorrect type."); return false; } LocalDataStore lds = (LocalDataStore) o; return this.questions.equals(lds.questions) && this.answers.equals(lds.answers) && this.qcomments.equals(lds.qcomments) && this.acomments.equals(lds.acomments); } }