Added Blackboard Course Cache

This commit is contained in:
Caesar2011
2019-02-06 16:08:34 +01:00
parent 2ec6a3c08d
commit 94e05ef8ba
4 changed files with 124 additions and 17 deletions

View File

@@ -15,6 +15,7 @@ import java.util.regex.MatchResult;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import androidx.arch.core.util.Function; 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.Lecturer;
import de.sebse.fuplanner.services.kvv.types.Modules; import de.sebse.fuplanner.services.kvv.types.Modules;
import de.sebse.fuplanner.services.kvv.types.Semester; import de.sebse.fuplanner.services.kvv.types.Semester;
@@ -32,6 +33,7 @@ public class ModulesList extends HTTPService {
private final KVVListener mListener; private final KVVListener mListener;
@Nullable private Modules mModules; @Nullable private Modules mModules;
private ModulesListLecturer mLecturer; private ModulesListLecturer mLecturer;
private CacheBBCourse mBBCache;
private final NewAsyncQueue mQueue = new NewAsyncQueue(); private final NewAsyncQueue mQueue = new NewAsyncQueue();
ModulesList(Login login, KVVListener listener, Context context) { ModulesList(Login login, KVVListener listener, Context context) {
@@ -235,6 +237,15 @@ public class ModulesList extends HTTPService {
} }
private void upgradeBB(final Modules modulesKVV, final NetworkCallback<Modules> callback, final NetworkErrorCallback errorCallback) { private void upgradeBB(final Modules modulesKVV, final NetworkCallback<Modules> callback, final NetworkErrorCallback errorCallback) {
NetworkCallback<Modules> successCallback = (modules -> {
try {
cacheBBCourse().save(getContext());
} catch (IOException e) {
e.printStackTrace();
}
callback.onResponse(modules);
});
if (!mLogin.isInOnlineMode() || mLogin.getLoginTokenBB() == null) { if (!mLogin.isInOnlineMode() || mLogin.getLoginTokenBB() == null) {
errorCallback.onError(new NetworkError(101120, 500, "Currently running in offline mode!")); errorCallback.onError(new NetworkError(101120, 500, "Currently running in offline mode!"));
return; return;
@@ -263,7 +274,11 @@ public class ModulesList extends HTTPService {
try { try {
JSONObject site = sites[0].getJSONObject(i); JSONObject site = sites[0].getJSONObject(i);
String courseId = site.getString("courseId"); 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(); String body1 = response1.getParsed();
if (body1 == null) { if (body1 == null) {
errorCallback.onError(new NetworkError(101124, 403, "No module list retrieved!")); errorCallback.onError(new NetworkError(101124, 403, "No module list retrieved!"));
@@ -299,12 +314,15 @@ public class ModulesList extends HTTPService {
String finalType = type; String finalType = type;
lecturer().getBBLecturers(courseId, success -> { lecturer().getBBLecturers(courseId, success -> {
modulesKVV.addModule(finalSemester, lvNumberSet, name, success, finalType, description, courseId, Modules.TYPE_BB); 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 -> { }, error -> {
log.e(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) { } catch (JSONException e) {
e.printStackTrace(); e.printStackTrace();
errorCallback.onError(new NetworkError(101125, 403, "Cannot parse module list!")); errorCallback.onError(new NetworkError(101125, 403, "Cannot parse module list!"));
@@ -326,4 +344,19 @@ public class ModulesList extends HTTPService {
mLecturer = new ModulesListLecturer(getContext(), mLogin); mLecturer = new ModulesListLecturer(getContext(), mLogin);
return mLecturer; 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;
}
} }

View File

@@ -11,7 +11,7 @@ import java.util.ArrayList;
import java.util.LinkedHashSet; import java.util.LinkedHashSet;
import de.sebse.fuplanner.services.kvv.types.Lecturer; 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.HTTPService;
import de.sebse.fuplanner.tools.network.NetworkCallback; import de.sebse.fuplanner.tools.network.NetworkCallback;
import de.sebse.fuplanner.tools.network.NetworkError; import de.sebse.fuplanner.tools.network.NetworkError;
@@ -19,27 +19,27 @@ import de.sebse.fuplanner.tools.network.NetworkErrorCallback;
class ModulesListLecturer extends HTTPService { class ModulesListLecturer extends HTTPService {
private final Login mLogin; 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); super(context);
this.mLogin = login; this.mLogin = login;
LecturerStorage storage = null; CacheLecturer storage = null;
try { try {
storage = LecturerStorage.load(context); storage = CacheLecturer.load(context);
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
} catch (ClassNotFoundException e) { } catch (ClassNotFoundException e) {
e.printStackTrace(); e.printStackTrace();
} }
if (storage == null) { if (storage == null) {
mStorage = new LecturerStorage(); mStorage = new CacheLecturer();
} else { } else {
mStorage = storage; mStorage = storage;
} }
} }
public void getBBLecturers(String moduleID, NetworkCallback<LinkedHashSet<Lecturer>> callback, NetworkErrorCallback errorCallback) { void getBBLecturers(String moduleID, NetworkCallback<LinkedHashSet<Lecturer>> callback, NetworkErrorCallback errorCallback) {
ArrayList<String> lecturerString = mStorage.getLecturersPerCourse(moduleID); ArrayList<String> lecturerString = mStorage.getLecturersPerCourse(moduleID);
if (lecturerString != null) { if (lecturerString != null) {
final int[] latch = {lecturerString.size()}; 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!"))); }, error -> errorCallback.onError(new NetworkError(102104, error.networkResponse.statusCode, "Error retrieving lecturers!")));
} }
public void getBBLecturer(String lecturerID, NetworkCallback<Lecturer> callback, NetworkErrorCallback errorCallback) { private void getBBLecturer(String lecturerID, NetworkCallback<Lecturer> callback, NetworkErrorCallback errorCallback) {
Lecturer lecturerStore = mStorage.getLecturer(lecturerID); Lecturer lecturerStore = mStorage.getLecturer(lecturerID);
if (lecturerStore != null) { if (lecturerStore != null) {
callback.onResponse(lecturerStore); callback.onResponse(lecturerStore);
@@ -149,7 +149,6 @@ class ModulesListLecturer extends HTTPService {
} catch (JSONException e) { } catch (JSONException e) {
e.printStackTrace(); e.printStackTrace();
errorCallback.onError(new NetworkError(102112, 403, "Cannot parse lecturer!")); errorCallback.onError(new NetworkError(102112, 403, "Cannot parse lecturer!"));
return;
} }
}, error -> errorCallback.onError(new NetworkError(102113, error.networkResponse.statusCode, "Error retrieving lecturer!"))); }, error -> errorCallback.onError(new NetworkError(102113, error.networkResponse.statusCode, "Error retrieving lecturer!")));
} }

View File

@@ -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<String> 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);
}
}

View File

@@ -11,7 +11,7 @@ import java.io.Serializable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; 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 transient static final long RESAVE_TIMER = 1000L * 60 * 60 * 24 * 30;
private static final String FILE_NAME = "LecturerStorageSaving"; private static final String FILE_NAME = "LecturerStorageSaving";
private static final String FILE_NAME_TIMESTAMP = "LecturerStorageSavingTimestamp"; private static final String FILE_NAME_TIMESTAMP = "LecturerStorageSavingTimestamp";
@@ -22,13 +22,13 @@ public class LecturerStorage implements Serializable {
private HashMap<String, Lecturer> mLecturers = new HashMap<>(); private HashMap<String, Lecturer> mLecturers = new HashMap<>();
private HashMap<String, Long> mLecturersRefresh = new HashMap<>(); private HashMap<String, Long> 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); FileInputStream fis = context.openFileInput(FILE_NAME);
ObjectInputStream is = new ObjectInputStream(fis); ObjectInputStream is = new ObjectInputStream(fis);
Object readObject = is.readObject(); Object readObject = is.readObject();
if (!(readObject instanceof LecturerStorage)) if (!(readObject instanceof CacheLecturer))
return null; return null;
LecturerStorage storage = (LecturerStorage) readObject; CacheLecturer storage = (CacheLecturer) readObject;
is.close(); is.close();
fis.close(); fis.close();