import static java.util.logging.Level.WARNING;
import java.util.Collection;
+import java.util.HashMap;
import java.util.HashSet;
+import java.util.Map;
+import java.util.Map.Entry;
import java.util.Set;
import java.util.logging.Logger;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
import net.pterodactylus.util.config.Configuration;
import net.pterodactylus.util.config.ConfigurationException;
return loadIds("Bookmarks/Post");
}
+ @Nullable
+ public synchronized Long getSoneFollowingTime(@Nonnull String soneId) {
+ return loadSoneFollowingTimes().get(soneId);
+ }
+
+ public synchronized void removeSoneFollowingTime(@Nonnull String soneId) {
+ Map<String, Long> soneFollowingTimes = loadSoneFollowingTimes();
+ soneFollowingTimes.remove(soneId);
+ storeSoneFollowingTimes(soneFollowingTimes);
+ }
+
+ public synchronized void setSoneFollowingTime(@Nonnull String soneId, long time) {
+ Map<String, Long> soneFollowingTimes = loadSoneFollowingTimes();
+ soneFollowingTimes.put(soneId, time);
+ storeSoneFollowingTimes(soneFollowingTimes);
+ }
+
+ private synchronized Map<String, Long> loadSoneFollowingTimes() {
+ Map<String, Long> soneFollowingTimes = new HashMap<>();
+ int soneCounter = 0;
+ while (true) {
+ String soneId = configuration.getStringValue("SoneFollowingTimes/" + soneCounter + "/Sone").getValue(null);
+ if (soneId == null) {
+ break;
+ }
+ soneFollowingTimes.put(soneId, configuration.getLongValue("SoneFollowingTimes/" + soneCounter++ + "/Time").getValue(Long.MAX_VALUE));
+ }
+ return soneFollowingTimes;
+ }
+
+ private synchronized void storeSoneFollowingTimes(Map<String, Long> soneFollowingTimes) {
+ int soneCounter = 0;
+ try {
+ for (Entry<String, Long> soneFollowingTime : soneFollowingTimes.entrySet()) {
+ configuration.getStringValue("SoneFollowingTimes/" + soneCounter + "/Sone").setValue(soneFollowingTime.getKey());
+ configuration.getLongValue("SoneFollowingTimes/" + soneCounter + "/Time").setValue(soneFollowingTime.getValue());
+ ++soneCounter;
+ }
+ configuration.getStringValue("SoneFollowingTimes/" + soneCounter + "/Sone").setValue(null);
+ } catch (ConfigurationException ce1) {
+ logger.log(WARNING, "Could not save Sone following times!", ce1);
+ }
+ }
+
private Set<String> loadIds(String prefix) {
Set<String> ids = new HashSet<String>();
int idCounter = 0;
import net.pterodactylus.util.config.Value
import org.hamcrest.MatcherAssert.assertThat
import org.hamcrest.Matchers.containsInAnyOrder
+import org.hamcrest.Matchers.equalTo
import org.hamcrest.Matchers.nullValue
import org.junit.Test
whenever(configuration.getStringValue(attribute)).thenReturn(this)
}
+ private fun setupLongValue(attribute: String, value: Long? = null): Value<Long?> =
+ from(value).apply {
+ whenever(configuration.getLongValue(attribute)).thenReturn(this)
+ }
+
@Test
fun `loader can load known posts`() {
setupStringValue("KnownPosts/0/ID", "Post2")
assertThat(post3.value, nullValue())
}
+ @Test
+ fun `loader can load Sone following times`() {
+ setupStringValue("SoneFollowingTimes/0/Sone", "Sone1")
+ setupLongValue("SoneFollowingTimes/0/Time", 1000L)
+ setupStringValue("SoneFollowingTimes/1/Sone", "Sone2")
+ setupLongValue("SoneFollowingTimes/1/Time", 2000L)
+ setupStringValue("SoneFollowingTimes/2/Sone")
+ assertThat(configurationLoader.getSoneFollowingTime("Sone1"), equalTo(1000L))
+ assertThat(configurationLoader.getSoneFollowingTime("Sone2"), equalTo(2000L))
+ assertThat(configurationLoader.getSoneFollowingTime("Sone3"), nullValue())
+ }
+
+ @Test
+ fun `loader can overwrite existing Sone following time`() {
+ val sone1Id = setupStringValue("SoneFollowingTimes/0/Sone", "Sone1")
+ val sone1Time = setupLongValue("SoneFollowingTimes/0/Time", 1000L)
+ val sone2Id = setupStringValue("SoneFollowingTimes/1/Sone", "Sone2")
+ val sone2Time = setupLongValue("SoneFollowingTimes/1/Time", 2000L)
+ setupStringValue("SoneFollowingTimes/2/Sone")
+ configurationLoader.setSoneFollowingTime("Sone1", 3000L)
+ assertThat(listOf(sone1Id.value to sone1Time.value, sone2Id.value to sone2Time.value), containsInAnyOrder<Pair<String?, Long?>>(
+ "Sone1" to 3000L,
+ "Sone2" to 2000L
+ ))
+ }
+
+ @Test
+ fun `loader can remove Sone following time`() {
+ val sone1Id = setupStringValue("SoneFollowingTimes/0/Sone", "Sone1")
+ val sone1Time = setupLongValue("SoneFollowingTimes/0/Time", 1000L)
+ val sone2Id = setupStringValue("SoneFollowingTimes/1/Sone", "Sone2")
+ val sone2Time = setupLongValue("SoneFollowingTimes/1/Time", 2000L)
+ setupStringValue("SoneFollowingTimes/2/Sone")
+ configurationLoader.removeSoneFollowingTime("Sone1")
+ assertThat(sone1Id.value, equalTo("Sone2"))
+ assertThat(sone1Time.value, equalTo(2000L))
+ assertThat(sone2Id.value, nullValue())
+ }
+
}