From 94e05ef8baebd529352d6a339bf1c124f70f37a8 Mon Sep 17 00:00:00 2001 From: Caesar2011 Date: Wed, 6 Feb 2019 16:08:34 +0100 Subject: [PATCH] Added Blackboard Course Cache --- .../fuplanner/services/kvv/ModulesList.java | 41 +++++++++- .../services/kvv/ModulesListLecturer.java | 17 ++--- .../services/kvv/types/CacheBBCourse.java | 75 +++++++++++++++++++ ...ecturerStorage.java => CacheLecturer.java} | 8 +- 4 files changed, 124 insertions(+), 17 deletions(-) create mode 100644 app/src/main/java/de/sebse/fuplanner/services/kvv/types/CacheBBCourse.java rename app/src/main/java/de/sebse/fuplanner/services/kvv/types/{LecturerStorage.java => CacheLecturer.java} (92%) diff --git a/app/src/main/java/de/sebse/fuplanner/services/kvv/ModulesList.java b/app/src/main/java/de/sebse/fuplanner/services/kvv/ModulesList.java index 8b826b7..67526bd 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/kvv/ModulesList.java +++ b/app/src/main/java/de/sebse/fuplanner/services/kvv/ModulesList.java @@ -15,6 +15,7 @@ import java.util.regex.MatchResult; import java.util.regex.Matcher; import androidx.arch.core.util.Function; +import de.sebse.fuplanner.services.kvv.types.CacheBBCourse; import de.sebse.fuplanner.services.kvv.types.Lecturer; import de.sebse.fuplanner.services.kvv.types.Modules; import de.sebse.fuplanner.services.kvv.types.Semester; @@ -32,6 +33,7 @@ public class ModulesList extends HTTPService { private final KVVListener mListener; @Nullable private Modules mModules; private ModulesListLecturer mLecturer; + private CacheBBCourse mBBCache; private final NewAsyncQueue mQueue = new NewAsyncQueue(); ModulesList(Login login, KVVListener listener, Context context) { @@ -235,6 +237,15 @@ public class ModulesList extends HTTPService { } private void upgradeBB(final Modules modulesKVV, final NetworkCallback callback, final NetworkErrorCallback errorCallback) { + NetworkCallback successCallback = (modules -> { + try { + cacheBBCourse().save(getContext()); + } catch (IOException e) { + e.printStackTrace(); + } + callback.onResponse(modules); + }); + if (!mLogin.isInOnlineMode() || mLogin.getLoginTokenBB() == null) { errorCallback.onError(new NetworkError(101120, 500, "Currently running in offline mode!")); return; @@ -263,7 +274,11 @@ public class ModulesList extends HTTPService { try { JSONObject site = sites[0].getJSONObject(i); String courseId = site.getString("courseId"); - get(String.format("https://lms.fu-berlin.de/learn/api/v1/courses/%s?fields=name,courseId", courseId), mLogin.getLoginTokenBB().getCookies(), response1 -> { + if (cacheBBCourse().hasKVVCourseID(courseId)) { + if (--latch[0] == 0) successCallback.onResponse(modulesKVV); + continue; + } + get(String.format("https://lms.fu-berlin.de/learn/api/v1/courses/%s?fields=name,courseId,description", courseId), mLogin.getLoginTokenBB().getCookies(), response1 -> { String body1 = response1.getParsed(); if (body1 == null) { errorCallback.onError(new NetworkError(101124, 403, "No module list retrieved!")); @@ -299,12 +314,15 @@ public class ModulesList extends HTTPService { String finalType = type; lecturer().getBBLecturers(courseId, success -> { modulesKVV.addModule(finalSemester, lvNumberSet, name, success, finalType, description, courseId, Modules.TYPE_BB); - if (--latch[0] == 0) callback.onResponse(modulesKVV); + if (--latch[0] == 0) successCallback.onResponse(modulesKVV); }, error -> { log.e(error); - if (--latch[0] == 0) callback.onResponse(modulesKVV); + if (--latch[0] == 0) successCallback.onResponse(modulesKVV); }); - } else if (--latch[0] == 0) callback.onResponse(modulesKVV); + } else { + cacheBBCourse().addKVVCourseID(courseId); + if (--latch[0] == 0) successCallback.onResponse(modulesKVV); + } } catch (JSONException e) { e.printStackTrace(); errorCallback.onError(new NetworkError(101125, 403, "Cannot parse module list!")); @@ -326,4 +344,19 @@ public class ModulesList extends HTTPService { mLecturer = new ModulesListLecturer(getContext(), mLogin); return mLecturer; } + + private CacheBBCourse cacheBBCourse() { + if (mBBCache == null) { + try { + mBBCache = CacheBBCourse.load(getContext()); + } catch (IOException e) { + e.printStackTrace(); + } catch (ClassNotFoundException e) { + e.printStackTrace(); + } + } + if (mBBCache == null) + mBBCache = new CacheBBCourse(); + return mBBCache; + } } diff --git a/app/src/main/java/de/sebse/fuplanner/services/kvv/ModulesListLecturer.java b/app/src/main/java/de/sebse/fuplanner/services/kvv/ModulesListLecturer.java index 131d731..5d9ae64 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/kvv/ModulesListLecturer.java +++ b/app/src/main/java/de/sebse/fuplanner/services/kvv/ModulesListLecturer.java @@ -11,7 +11,7 @@ import java.util.ArrayList; import java.util.LinkedHashSet; import de.sebse.fuplanner.services.kvv.types.Lecturer; -import de.sebse.fuplanner.services.kvv.types.LecturerStorage; +import de.sebse.fuplanner.services.kvv.types.CacheLecturer; import de.sebse.fuplanner.tools.network.HTTPService; import de.sebse.fuplanner.tools.network.NetworkCallback; import de.sebse.fuplanner.tools.network.NetworkError; @@ -19,27 +19,27 @@ import de.sebse.fuplanner.tools.network.NetworkErrorCallback; class ModulesListLecturer extends HTTPService { private final Login mLogin; - private final LecturerStorage mStorage; + private final CacheLecturer mStorage; - public ModulesListLecturer(Context context, Login login) { + ModulesListLecturer(Context context, Login login) { super(context); this.mLogin = login; - LecturerStorage storage = null; + CacheLecturer storage = null; try { - storage = LecturerStorage.load(context); + storage = CacheLecturer.load(context); } catch (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } if (storage == null) { - mStorage = new LecturerStorage(); + mStorage = new CacheLecturer(); } else { mStorage = storage; } } - public void getBBLecturers(String moduleID, NetworkCallback> callback, NetworkErrorCallback errorCallback) { + void getBBLecturers(String moduleID, NetworkCallback> callback, NetworkErrorCallback errorCallback) { ArrayList lecturerString = mStorage.getLecturersPerCourse(moduleID); if (lecturerString != null) { final int[] latch = {lecturerString.size()}; @@ -116,7 +116,7 @@ class ModulesListLecturer extends HTTPService { }, error -> errorCallback.onError(new NetworkError(102104, error.networkResponse.statusCode, "Error retrieving lecturers!"))); } - public void getBBLecturer(String lecturerID, NetworkCallback callback, NetworkErrorCallback errorCallback) { + private void getBBLecturer(String lecturerID, NetworkCallback callback, NetworkErrorCallback errorCallback) { Lecturer lecturerStore = mStorage.getLecturer(lecturerID); if (lecturerStore != null) { callback.onResponse(lecturerStore); @@ -149,7 +149,6 @@ class ModulesListLecturer extends HTTPService { } catch (JSONException e) { e.printStackTrace(); errorCallback.onError(new NetworkError(102112, 403, "Cannot parse lecturer!")); - return; } }, error -> errorCallback.onError(new NetworkError(102113, error.networkResponse.statusCode, "Error retrieving lecturer!"))); } diff --git a/app/src/main/java/de/sebse/fuplanner/services/kvv/types/CacheBBCourse.java b/app/src/main/java/de/sebse/fuplanner/services/kvv/types/CacheBBCourse.java new file mode 100644 index 0000000..0101348 --- /dev/null +++ b/app/src/main/java/de/sebse/fuplanner/services/kvv/types/CacheBBCourse.java @@ -0,0 +1,75 @@ +package de.sebse.fuplanner.services.kvv.types; + +import android.content.Context; + +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.util.HashSet; + +public class CacheBBCourse implements Serializable { + private transient static final long RESAVE_TIMER = 1000L * 60 * 60 * 24 * 30; + private static final String FILE_NAME = "BBCourseStorageSaving"; + private static final String FILE_NAME_TIMESTAMP = "BBCourseStorageSavingTimestamp"; + private transient long mLastTimestamp = 0; + + private HashSet mKVVCourseList = new HashSet<>(); + private long mKVVCourseListRefresh = 0; + + public static CacheBBCourse load(Context context) throws IOException, ClassNotFoundException { + FileInputStream fis = context.openFileInput(FILE_NAME); + ObjectInputStream is = new ObjectInputStream(fis); + Object readObject = is.readObject(); + if (!(readObject instanceof CacheBBCourse)) + return null; + CacheBBCourse storage = (CacheBBCourse) readObject; + is.close(); + fis.close(); + + fis = context.openFileInput(FILE_NAME_TIMESTAMP); + is = new ObjectInputStream(fis); + storage.mLastTimestamp = is.readLong(); + is.close(); + fis.close(); + + return storage; + } + + public boolean isNewerVersionInStorage(Context context) throws IOException { + FileInputStream fis = context.openFileInput(FILE_NAME_TIMESTAMP); + ObjectInputStream is = new ObjectInputStream(fis); + boolean result = this.mLastTimestamp < is.readLong(); + is.close(); + fis.close(); + return result; + } + + public void save(Context context) throws IOException { + FileOutputStream fos = context.openFileOutput(FILE_NAME, Context.MODE_PRIVATE); + ObjectOutputStream os = new ObjectOutputStream(fos); + os.writeObject(this); + os.close(); + fos.close(); + + fos = context.openFileOutput(FILE_NAME_TIMESTAMP, Context.MODE_PRIVATE); + os = new ObjectOutputStream(fos); + this.mLastTimestamp = System.currentTimeMillis(); + os.writeLong(this.mLastTimestamp); + os.close(); + fos.close(); + } + + public void addKVVCourseID(String courseID) { + mKVVCourseList.add(courseID); + mKVVCourseListRefresh = System.currentTimeMillis(); + } + + public boolean hasKVVCourseID(String courseID) { + if (mKVVCourseListRefresh + RESAVE_TIMER < System.currentTimeMillis()) + return false; + return mKVVCourseList.contains(courseID); + } +} diff --git a/app/src/main/java/de/sebse/fuplanner/services/kvv/types/LecturerStorage.java b/app/src/main/java/de/sebse/fuplanner/services/kvv/types/CacheLecturer.java similarity index 92% rename from app/src/main/java/de/sebse/fuplanner/services/kvv/types/LecturerStorage.java rename to app/src/main/java/de/sebse/fuplanner/services/kvv/types/CacheLecturer.java index 3f913c4..c079574 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/kvv/types/LecturerStorage.java +++ b/app/src/main/java/de/sebse/fuplanner/services/kvv/types/CacheLecturer.java @@ -11,7 +11,7 @@ import java.io.Serializable; import java.util.ArrayList; import java.util.HashMap; -public class LecturerStorage implements Serializable { +public class CacheLecturer implements Serializable { private transient static final long RESAVE_TIMER = 1000L * 60 * 60 * 24 * 30; private static final String FILE_NAME = "LecturerStorageSaving"; private static final String FILE_NAME_TIMESTAMP = "LecturerStorageSavingTimestamp"; @@ -22,13 +22,13 @@ public class LecturerStorage implements Serializable { private HashMap mLecturers = new HashMap<>(); private HashMap mLecturersRefresh = new HashMap<>(); - public static LecturerStorage load(Context context) throws IOException, ClassNotFoundException { + public static CacheLecturer load(Context context) throws IOException, ClassNotFoundException { FileInputStream fis = context.openFileInput(FILE_NAME); ObjectInputStream is = new ObjectInputStream(fis); Object readObject = is.readObject(); - if (!(readObject instanceof LecturerStorage)) + if (!(readObject instanceof CacheLecturer)) return null; - LecturerStorage storage = (LecturerStorage) readObject; + CacheLecturer storage = (CacheLecturer) readObject; is.close(); fis.close();