Added Blackboard Course Cache
This commit is contained in:
@@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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!")));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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();
|
||||||
|
|
||||||
Reference in New Issue
Block a user