1 package net.pterodactylus.sone.core;
3 import static com.google.common.base.Optional.absent;
4 import static com.google.common.base.Optional.of;
5 import static com.google.common.base.Ticker.systemTicker;
6 import static java.util.concurrent.TimeUnit.NANOSECONDS;
8 import java.util.concurrent.atomic.AtomicInteger;
10 import net.pterodactylus.sone.data.Sone;
12 import com.google.common.annotations.VisibleForTesting;
13 import com.google.common.base.Objects;
14 import com.google.common.base.Optional;
15 import com.google.common.base.Ticker;
18 * Class that detects {@link Sone} modifications (as per their {@link
19 * Sone#getFingerprint() fingerprints} and determines when a modified Sone may
22 * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
24 class SoneModificationDetector {
26 private final Ticker ticker;
27 private final LockableFingerprintProvider lockableFingerprintProvider;
28 private final AtomicInteger insertionDelay;
29 private Optional<Long> lastModificationTime;
30 private String lastInsertFingerprint;
31 private String lastCheckFingerprint;
33 SoneModificationDetector(LockableFingerprintProvider lockableFingerprintProvider, AtomicInteger insertionDelay) {
34 this(systemTicker(), lockableFingerprintProvider, insertionDelay);
38 SoneModificationDetector(Ticker ticker, LockableFingerprintProvider lockableFingerprintProvider, AtomicInteger insertionDelay) {
40 this.lockableFingerprintProvider = lockableFingerprintProvider;
41 this.insertionDelay = insertionDelay;
42 lastCheckFingerprint = lastInsertFingerprint;
45 public boolean isEligibleForInsert() {
46 if (lockableFingerprintProvider.isLocked()) {
47 lastModificationTime = absent();
48 lastCheckFingerprint = "";
51 String fingerprint = lockableFingerprintProvider.getFingerprint();
52 if (fingerprint.equals(lastInsertFingerprint)) {
53 lastModificationTime = absent();
54 lastCheckFingerprint = fingerprint;
57 if (!Objects.equal(lastCheckFingerprint, fingerprint)) {
58 lastModificationTime = of(ticker.read());
59 lastCheckFingerprint = fingerprint;
62 return insertionDelayHasPassed();
65 public String getLastInsertFingerprint() {
66 return lastInsertFingerprint;
69 public void setFingerprint(String fingerprint) {
70 lastInsertFingerprint = fingerprint;
71 lastCheckFingerprint = lastInsertFingerprint;
72 lastModificationTime = absent();
75 private boolean insertionDelayHasPassed() {
76 return NANOSECONDS.toSeconds(ticker.read() - lastModificationTime.get()) >= insertionDelay.get();
79 public boolean isModified() {
80 return !Objects.equal(lockableFingerprintProvider.getFingerprint(), lastInsertFingerprint);
84 * Provider for a fingerprint and the information if a {@link Sone} is locked. This
85 * prevents us from having to lug a Sone object around.
87 * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
89 static interface LockableFingerprintProvider {
92 String getFingerprint();