TwitterCacheFile.java
package org.ferris.tweial.console.twitter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import javax.inject.Inject;
import org.apache.log4j.Logger;
import org.ferris.tweial.console.data.DataDirectory;
import twitter4j.Status;
/**
* This is a hard coded {@link File} object to
* "{@link DataDirectory}/tweets-cache.ser". This file is used
* to store a history of tweets already seen by Tweial. This is how the
* application can then only send new tweets every time it runs. Serialized
* Java objects are written to the file.
*
* @author Michael Remijan mjremijan@yahoo.com @mjremijan
*/
public class TwitterCacheFile extends File {
private static final long serialVersionUID = 4326757809880954L;
@Inject
protected Logger log;
/**
* To file "{@link DataDirectory}/tweets-cache.ser"
*
* @param datadir An {@link DataDirectory} representing the data directory
*/
@Inject
public TwitterCacheFile(DataDirectory datadir) {
super(datadir, "tweets-cache.ser");
}
/**
* This method will de-serialize the data file and return a
* {@link List}<{@link Status}>. The list returned by
* this method is modifiable.
*
* @return
* A {@link List}<{@link Status}> is always returned. {@code null} is
* never returned. If de-serialization fails for any reason, the exception
* is logged and empty list is returned.
*
*/
protected List<Status> getModifiableCache() {
log.debug("Read serialized object from file");
List<Status> retval = null;
try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(this));) {
retval = (List<Status>) ois.readObject();
} catch (IOException|ClassNotFoundException e) {
log.warn("Failure getting cache of stored tweets", e);
retval = new LinkedList<>();
}
return retval;
}
/**
* A getter method which returns an unmodifiable list. This is a
* wrapper over {@link #getModifiableCache() }
*
* @see #getModifiableCache()
*
* @return
* The same as {@link #getModifiableCache() } only unmodifiable
*/
protected List<Status> get() {
log.info("Get cache data");
List<Status> cache = getModifiableCache();
return Collections.unmodifiableList(cache);
}
/**
* Serializes the {@code stored} parameter to the data file. If anything
* goes wrong during serialization the exception is logged and then the
* exception is wrapped in a {@link RuntimeException} and re-thrown;
*
* @param stored The objects to be serialized. No validation of it's value.
*
* @throws RuntimeException
* If anything goes wrong, it's wrapped in a {@link RuntimeException}
* and re-thrown.
*/
protected void set(List<Status> stored) {
log.debug("Set cache data");
try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(this));) {
oos.writeObject(stored);
oos.flush();
} catch (IOException e) {
String msg = "Failure writing cache of stored tweets";
log.fatal(msg, e);
throw new RuntimeException(msg, e);
}
}
/**
* Adds all objects in the {@code addToCache} parameter to cache then
* re-writes the data file. This method is a wrapper around
* {@link #getModifiableCache()} and {@link #set(java.util.List)}.
*
* @param addToCache
* The objects to added to the cache. No validation of it's value.
*
* @throws RuntimeException
* Same as {@link #set(java.util.List) }
*/
protected void addAll(List<Status> addToCache) {
List<Status> cache = getModifiableCache();
cache.addAll(addToCache);
set(cache);
}
/**
* Removes all objects from the cache which are older than
* {@code daysOld}. This method is a wrapper around
* {@link #getModifiableCache()} and {@link #set(java.util.List)}.
*
* @param daysOld Remove data that is older than {@code daysOld}
* @throws RuntimeException
* Same as {@link #set(java.util.List) }
*/
protected void vacuum(int daysOld) {
// Last week
LocalDateTime lastWeek
= LocalDateTime.now().minusDays(daysOld);
// Date ts = ...;
// Instant instant = Instant.ofEpochMilli(ts.getTime());
// LocalDateTime res = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
// Remove if the Status createdAt date is more than a week old.
List<Status> cache = getModifiableCache();
cache.removeIf(s -> LocalDateTime.ofInstant(s.getCreatedAt().toInstant(), ZoneId.systemDefault()).isBefore(lastWeek) );
// Save the cache again
set(cache);
}
}