Cache KVV courses
This commit is contained in:
@@ -16,6 +16,7 @@ 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.CacheBBCourse;
|
||||||
|
import de.sebse.fuplanner.services.kvv.types.CacheKVVCourse;
|
||||||
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;
|
||||||
@@ -35,6 +36,7 @@ public class ModulesList extends HTTPService {
|
|||||||
private ModulesListLecturer mLecturer;
|
private ModulesListLecturer mLecturer;
|
||||||
private CacheBBCourse mBBCache;
|
private CacheBBCourse mBBCache;
|
||||||
private final NewAsyncQueue mQueue = new NewAsyncQueue();
|
private final NewAsyncQueue mQueue = new NewAsyncQueue();
|
||||||
|
private CacheKVVCourse mKVVCache;
|
||||||
|
|
||||||
ModulesList(Login login, KVVListener listener, Context context) {
|
ModulesList(Login login, KVVListener listener, Context context) {
|
||||||
super(context);
|
super(context);
|
||||||
@@ -167,69 +169,109 @@ public class ModulesList extends HTTPService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void upgradeKVV(final NetworkCallback<Modules> callback, final NetworkErrorCallback errorCallback) {
|
private void upgradeKVV(final NetworkCallback<Modules> callback, final NetworkErrorCallback errorCallback) {
|
||||||
|
NetworkCallback<Modules> successCallback = (modules -> {
|
||||||
|
try {
|
||||||
|
cacheKVVCourse().save(getContext());
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
callback.onResponse(modules);
|
||||||
|
});
|
||||||
|
|
||||||
if (!mLogin.isInOnlineMode() || mLogin.getLoginTokenKVV() == null) {
|
if (!mLogin.isInOnlineMode() || mLogin.getLoginTokenKVV() == null) {
|
||||||
errorCallback.onError(new NetworkError(101110, 500, "Currently running in offline mode!"));
|
errorCallback.onError(new NetworkError(101110, 500, "Currently running in offline mode!"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
Modules modules = new Modules(mLogin.getLoginTokenKVV().getUsername());
|
||||||
if (!mLogin.getLoginTokenKVV().isAvailable()) {
|
if (!mLogin.getLoginTokenKVV().isAvailable()) {
|
||||||
callback.onResponse(new Modules(mLogin.getLoginTokenKVV().getUsername()));
|
callback.onResponse(modules);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
get("https://kvv.imp.fu-berlin.de/direct/site.json?_validateSession=", mLogin.getLoginTokenKVV().getCookies(), response -> {
|
get("https://kvv.imp.fu-berlin.de/direct/membership.json?_validateSession=", mLogin.getLoginTokenKVV().getCookies(), response -> {
|
||||||
String body = response.getParsed();
|
String body = response.getParsed();
|
||||||
if (body == null) {
|
if (body == null) {
|
||||||
errorCallback.onError(new NetworkError(101111, 403, "No module list retrieved!"));
|
errorCallback.onError(new NetworkError(101111, 403, "No membership list retrieved!"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Modules modules = new Modules(mLogin.getLoginTokenKVV().getUsername());
|
JSONArray memberships;
|
||||||
JSONArray sites;
|
|
||||||
try {
|
try {
|
||||||
JSONObject json = new JSONObject(body);
|
JSONObject json = new JSONObject(body);
|
||||||
sites = json.getJSONArray("site_collection");
|
memberships = json.getJSONArray("membership_collection");
|
||||||
} catch (JSONException e) {
|
} catch (JSONException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
errorCallback.onError(new NetworkError(101112, 403, "Cannot parse module list!"));
|
errorCallback.onError(new NetworkError(101112, 403, "Cannot parse membership list!"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (int i = 0; i < sites.length(); i++) {
|
final int[] latch = {memberships.length()};
|
||||||
|
for (int i = 0; i < memberships.length(); i++) {
|
||||||
try {
|
try {
|
||||||
JSONObject site = sites.getJSONObject(i);
|
JSONObject membership = memberships.getJSONObject(i);
|
||||||
String semester_string = site.getJSONObject("props").optString("term_eid", null);
|
String locationReference = membership.getString("locationReference");
|
||||||
Semester semester;
|
String courseId = Regex.regex("/site/([0-9a-f-]+)", locationReference);
|
||||||
if (semester_string == null)
|
Modules.Module kvvCourse = cacheKVVCourse().getKVVCourse(courseId);
|
||||||
semester = null;
|
if (kvvCourse != null) {
|
||||||
else
|
kvvCourse = kvvCourse.clone();
|
||||||
semester = new Semester(semester_string);
|
modules.addModule(kvvCourse);
|
||||||
HashSet<String> lvNumbers = new HashSet<>();
|
if (--latch[0] == 0) successCallback.onResponse(modules);
|
||||||
String kvv_lvnumbers = site.getJSONObject("props").optString("kvv_lvnumbers", null);
|
continue;
|
||||||
if (kvv_lvnumbers != null)
|
|
||||||
for (MatchResult matchResult : Regex.allMatches("[0-9]+", kvv_lvnumbers)) {
|
|
||||||
lvNumbers.add(matchResult.group());
|
|
||||||
}
|
|
||||||
String title = site.getString("entityTitle");
|
|
||||||
LinkedHashSet<Lecturer> lecturers = new LinkedHashSet<>();
|
|
||||||
String kvv_lecturers = site.getJSONObject("props").optString("kvv_lecturers", null);
|
|
||||||
if (kvv_lecturers != null) for (String lecturer : kvv_lecturers.split("#")) {
|
|
||||||
if (lecturer.length() > 2)
|
|
||||||
lecturers.add(new Lecturer(lecturer));
|
|
||||||
}
|
}
|
||||||
String type = site.getJSONObject("props").optString("kvv_coursetype", "Projekt");
|
get(String.format("https://kvv.imp.fu-berlin.de/direct/site/%s.json?_validateSession=", courseId), mLogin.getLoginTokenKVV().getCookies(), response1 -> {
|
||||||
String description = site.optString("description", "");
|
String body1 = response1.getParsed();
|
||||||
description = String.valueOf(PartModules.fromHtml(description));
|
if (body1 == null) {
|
||||||
String id = site.getString("id");
|
errorCallback.onError(new NetworkError(101113, 403, "No site retrieved!"));
|
||||||
modules.addModule(semester, lvNumbers, title, lecturers, type, description, id, Modules.TYPE_KVV);
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
JSONObject site = new JSONObject(body1);
|
||||||
|
|
||||||
|
String semester_string = site.getJSONObject("props").optString("term_eid", null);
|
||||||
|
Semester semester;
|
||||||
|
if (semester_string == null)
|
||||||
|
semester = null;
|
||||||
|
else
|
||||||
|
semester = new Semester(semester_string);
|
||||||
|
HashSet<String> lvNumbers = new HashSet<>();
|
||||||
|
String kvv_lvnumbers = site.getJSONObject("props").optString("kvv_lvnumbers", null);
|
||||||
|
if (kvv_lvnumbers != null)
|
||||||
|
for (MatchResult matchResult : Regex.allMatches("[0-9]+", kvv_lvnumbers)) {
|
||||||
|
lvNumbers.add(matchResult.group());
|
||||||
|
}
|
||||||
|
String title = site.getString("entityTitle");
|
||||||
|
LinkedHashSet<Lecturer> lecturers = new LinkedHashSet<>();
|
||||||
|
String kvv_lecturers = site.getJSONObject("props").optString("kvv_lecturers", null);
|
||||||
|
if (kvv_lecturers != null) for (String lecturer : kvv_lecturers.split("#")) {
|
||||||
|
if (lecturer.length() > 2)
|
||||||
|
lecturers.add(new Lecturer(lecturer));
|
||||||
|
}
|
||||||
|
String type = site.getJSONObject("props").optString("kvv_coursetype", "Projekt");
|
||||||
|
String description = site.optString("description", "");
|
||||||
|
description = String.valueOf(PartModules.fromHtml(description));
|
||||||
|
String id = site.getString("id");
|
||||||
|
Modules.Module module = modules.addModule(semester, lvNumbers, title, lecturers, type, description, id, Modules.TYPE_KVV);
|
||||||
|
cacheKVVCourse().setKVVCourse(courseId, module.clone());
|
||||||
|
if (--latch[0] == 0) successCallback.onResponse(modules);
|
||||||
|
} catch (JSONException e) {
|
||||||
|
log.e(new NetworkError(101114, 403, "Cannot parse site!"));
|
||||||
|
log.e("JSON:", body1);
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (NoSuchFieldException e) {
|
||||||
|
log.e(new NetworkError(101115, 403, "Cannot parse site!"));
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}, error -> errorCallback.onError(new NetworkError(101116, error.networkResponse.statusCode, "Cannot get membership list!")));
|
||||||
} catch (JSONException e) {
|
} catch (JSONException e) {
|
||||||
log.e(new NetworkError(101113, 403, "Cannot parse module list!"));
|
log.e("ID:", i, "JSON:", memberships);
|
||||||
log.e("ID:", i, "JSON:", sites);
|
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
errorCallback.onError(new NetworkError(101117, 403, "Cannot parse membership list!"));
|
||||||
|
return;
|
||||||
} catch (NoSuchFieldException e) {
|
} catch (NoSuchFieldException e) {
|
||||||
log.e(new NetworkError(101114, 403, "Cannot parse module list!"));
|
log.e("ID:", i, "JSON:", memberships);
|
||||||
log.e("ID:", i, "JSON:", sites);
|
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
errorCallback.onError(new NetworkError(101118, 403, "Cannot parse membership list!"));
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
callback.onResponse(modules);
|
}, error -> errorCallback.onError(new NetworkError(101119, error.networkResponse.statusCode, "Cannot get membership list!")));
|
||||||
}, error -> errorCallback.onError(new NetworkError(101115, error.networkResponse.statusCode, "Cannot get module list!")));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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) {
|
||||||
@@ -363,4 +405,19 @@ public class ModulesList extends HTTPService {
|
|||||||
mBBCache = new CacheBBCourse();
|
mBBCache = new CacheBBCourse();
|
||||||
return mBBCache;
|
return mBBCache;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private CacheKVVCourse cacheKVVCourse() {
|
||||||
|
if (mKVVCache == null) {
|
||||||
|
try {
|
||||||
|
mKVVCache = CacheKVVCourse.load(getContext());
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (ClassNotFoundException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (mKVVCache == null)
|
||||||
|
mKVVCache = new CacheKVVCourse();
|
||||||
|
return mKVVCache;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,79 @@
|
|||||||
|
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.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
|
||||||
|
public class CacheKVVCourse implements Serializable {
|
||||||
|
private transient static final long RESAVE_TIMER = 1000L * 60 * 60 * 24 * 30;
|
||||||
|
private static final String FILE_NAME = "KVVCourseStorageSaving";
|
||||||
|
private static final String FILE_NAME_TIMESTAMP = "KVVCourseStorageSavingTimestamp";
|
||||||
|
private transient long mLastTimestamp = 0;
|
||||||
|
|
||||||
|
private HashMap<String, Modules.Module> mKVVCourseList = new HashMap<>();
|
||||||
|
private HashMap<String, Long> mKVVCourseListRefresh = new HashMap<>();
|
||||||
|
|
||||||
|
public static CacheKVVCourse load(Context context) throws IOException, ClassNotFoundException {
|
||||||
|
FileInputStream fis = context.openFileInput(FILE_NAME);
|
||||||
|
ObjectInputStream is = new ObjectInputStream(fis);
|
||||||
|
Object readObject = is.readObject();
|
||||||
|
if (!(readObject instanceof CacheKVVCourse))
|
||||||
|
return null;
|
||||||
|
CacheKVVCourse storage = (CacheKVVCourse) 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 setKVVCourse(String courseID, Modules.Module lecturer) {
|
||||||
|
mKVVCourseList.put(courseID, lecturer);
|
||||||
|
mKVVCourseListRefresh.put(courseID, System.currentTimeMillis());
|
||||||
|
}
|
||||||
|
|
||||||
|
public Modules.Module getKVVCourse(String courseID) {
|
||||||
|
if (!mKVVCourseListRefresh.containsKey(courseID))
|
||||||
|
return null;
|
||||||
|
//noinspection ConstantConditions
|
||||||
|
if (mKVVCourseListRefresh.get(courseID) + RESAVE_TIMER < System.currentTimeMillis())
|
||||||
|
return null;
|
||||||
|
return mKVVCourseList.get(courseID);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user