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.Optional;
14 import com.google.common.base.Ticker;
17 * Class that detects {@link Sone} modifications (as per their {@link
18 * Sone#getFingerprint() fingerprints} and determines when a modified Sone may
21 * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
23 class SoneModificationDetector {
25 private final Ticker ticker;
26 private final LockableFingerprintProvider lockableFingerprintProvider;
27 private final AtomicInteger insertionDelay;
28 private Optional<Long> lastModificationTime;
29 private String originalFingerprint;
30 private String lastFingerprint;
32 SoneModificationDetector(LockableFingerprintProvider lockableFingerprintProvider, AtomicInteger insertionDelay) {
33 this(systemTicker(), lockableFingerprintProvider, insertionDelay);
37 SoneModificationDetector(Ticker ticker, LockableFingerprintProvider lockableFingerprintProvider, AtomicInteger insertionDelay) {
39 this.lockableFingerprintProvider = lockableFingerprintProvider;
40 this.insertionDelay = insertionDelay;
41 originalFingerprint = lockableFingerprintProvider.getFingerprint();
42 lastFingerprint = originalFingerprint;
45 public boolean isEligibleForInsert() {
46 if (lockableFingerprintProvider.isLocked()) {
47 lastModificationTime = absent();
51 String fingerprint = lockableFingerprintProvider.getFingerprint();
52 if (originalFingerprint.equals(fingerprint)) {
53 lastModificationTime = absent();
54 lastFingerprint = fingerprint;
57 if (!lastFingerprint.equals(fingerprint)) {
58 lastModificationTime = of(ticker.read());
59 lastFingerprint = fingerprint;
62 return insertionDelayHasPassed();
65 public String getOriginalFingerprint() {
66 return originalFingerprint;
69 public void setFingerprint(String fingerprint) {
70 originalFingerprint = fingerprint;
71 lastFingerprint = originalFingerprint;
72 lastModificationTime = absent();
75 private boolean insertionDelayHasPassed() {
76 return NANOSECONDS.toSeconds(ticker.read() - lastModificationTime.get()) >= insertionDelay.get();
79 public boolean isModified() {
80 return !lockableFingerprintProvider.getFingerprint().equals(originalFingerprint);
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();