🔀 Merge branch 'release/v82'
[Sone.git] / core / SoneModificationDetector.java
1 package net.pterodactylus.sone.core;
2
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;
7
8 import java.util.concurrent.atomic.AtomicInteger;
9
10 import net.pterodactylus.sone.data.Sone;
11
12 import com.google.common.annotations.VisibleForTesting;
13 import com.google.common.base.Optional;
14 import com.google.common.base.Ticker;
15
16 /**
17  * Class that detects {@link Sone} modifications (as per their {@link
18  * Sone#getFingerprint() fingerprints} and determines when a modified Sone may
19  * be inserted.
20  *
21  * @author <a href="mailto:bombe@pterodactylus.net">David â€˜Bombe’ Roden</a>
22  */
23 class SoneModificationDetector {
24
25         private final Ticker ticker;
26         private final Core core;
27         private final Sone sone;
28         private final AtomicInteger insertionDelay;
29         private Optional<Long> lastModificationTime;
30         private String originalFingerprint;
31         private String lastFingerprint;
32
33         SoneModificationDetector(Core core, Sone sone, AtomicInteger insertionDelay) {
34                 this(systemTicker(), core, sone, insertionDelay);
35         }
36
37         @VisibleForTesting
38         SoneModificationDetector(Ticker ticker, Core core, Sone sone, AtomicInteger insertionDelay) {
39                 this.ticker = ticker;
40                 this.core = core;
41                 this.sone = sone;
42                 this.insertionDelay = insertionDelay;
43                 originalFingerprint = sone.getFingerprint();
44                 lastFingerprint = originalFingerprint;
45         }
46
47         public boolean isEligibleForInsert() {
48                 if (core.isLocked(sone)) {
49                         lastModificationTime = absent();
50                         lastFingerprint = "";
51                         return false;
52                 }
53                 String fingerprint = sone.getFingerprint();
54                 if (originalFingerprint.equals(fingerprint)) {
55                         lastModificationTime = absent();
56                         lastFingerprint = fingerprint;
57                         return false;
58                 }
59                 if (!lastFingerprint.equals(fingerprint)) {
60                         lastModificationTime = of(ticker.read());
61                         lastFingerprint = fingerprint;
62                         return false;
63                 }
64                 return insertionDelayHasPassed();
65         }
66
67         public String getOriginalFingerprint() {
68                 return originalFingerprint;
69         }
70
71         public void setFingerprint(String fingerprint) {
72                 originalFingerprint = fingerprint;
73                 lastFingerprint = originalFingerprint;
74                 lastModificationTime = absent();
75         }
76
77         private boolean insertionDelayHasPassed() {
78                 return lastModificationTime.isPresent() && (NANOSECONDS.toSeconds(ticker.read() - lastModificationTime.get()) >= insertionDelay.get());
79         }
80
81         public boolean isModified() {
82                 return !sone.getFingerprint().equals(originalFingerprint);
83         }
84
85 }