Skip to content

Commit 412262b

Browse files
Merge pull request #9 from DavidTheExplorer/1.4.0
v1.4.0 - Breaking Changes, JavaDocs, and critical bug fixes.
2 parents d69e0db + 2177e13 commit 412262b

8 files changed

Lines changed: 66 additions & 22 deletions

File tree

README.md

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,26 @@
11
# Tzeva Adom API
2-
Async Java API that listens to `Pikud Ha'oref API` and notifies registered listeners as soon as a Tzeva Adom happens.
2+
Async Java API that listens to `Pikud Ha'oref` and notifies registered listeners as soon as a Tzeva Adom happens.
33

44

55
## How to use
66
Let's create a notifier that logs a message when it's Tzeva Adom:
77
```java
88
TzevaAdomNotifier
9-
.requestFromPikudHaoref()
9+
.basedOnPikudHaoref()
1010
.every(Duration.ofSeconds(3)) //amount of delay between requests
1111
.onFailedRequest(exception -> LOGGER.error("Failed to request the last alert from Pikud Ha'oref", exception))
1212
.onTzevaAdom(alert -> LOGGER.info("Tzeva Adom at: " + alert.getCity()))
1313
.listen(); //async
1414
```
1515

16-
You can save the notifier object by calling `build()` instead of `listen()`, in order to add functionality or get data from it:
16+
You can save the notifier object by calling `build()` instead of `listen()` in order to add functionality or get data:
1717
```java
18-
TzevaAdomNotifier notifier = TzevaAdomNotifier
19-
// builder pattern goes here
18+
TzevaAdomNotifier notifier = new TzevaAdomNotifier.Builder()
19+
// the rest of the builder pattern
2020
.build();
21-
22-
notifier.listen();
21+
22+
// later
23+
Alert lastAlert = notifier.getLastAlert();
2324
```
2425

2526
Add more listeners anytime:
@@ -30,13 +31,12 @@ notifier.addListener(alert -> ...);
3031
Retrieve the Tzeva Adom alerts encountered while running:
3132
```java
3233
//run the notifier async and sleep for a day
33-
notifier.run();
34+
notifier.listen();
3435
TimeUnit.DAYS.sleep(1);
3536

3637
LOGGER.info("There were {} alerts in the last 24 hours:", notifier.getHistory().size());
3738

38-
//Pro Tip: TzevaAdomNotifier implements Iterable!
39-
for(Alert alert : notifier)
39+
for(Alert alert : notifier.getHistory())
4040
{
4141
LOGGER.info("Alert in {} at {}", alert.getCity(), alert.getDate());
4242
}
@@ -55,7 +55,7 @@ Maven Repository:
5555
<dependency>
5656
<groupId>com.github.DavidTheExplorer</groupId>
5757
<artifactId>Tzeva-Adom-API</artifactId>
58-
<version>1.1.0</version>
58+
<version>1.4.0</version>
5959
</dependency>
6060
```
6161

@@ -67,4 +67,3 @@ Either implement `AlertSource` or extend `JSONAlertSource` for JSON APIs, and th
6767
```java
6868
new TzevaAdomNotifier.Builder()
6969
.requestFrom(new YourAlertSource())
70-
.listen();

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<modelVersion>4.0.0</modelVersion>
55
<groupId>dte</groupId>
66
<artifactId>tzevaadomapi</artifactId>
7-
<version>1.3.1</version>
7+
<version>1.4.0</version>
88

99
<build>
1010
<plugins>

src/main/java/dte/tzevaadomapi/alert/Alert.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
import java.time.LocalDateTime;
44
import java.util.Objects;
55

6+
/**
7+
* Represents a <b>Tzeva Adom</b> alert and contains information about where/when it happened.
8+
*/
69
public class Alert
710
{
811
private final String city;

src/main/java/dte/tzevaadomapi/alertsource/AlertSource.java

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,26 @@
22

33
import dte.tzevaadomapi.alert.Alert;
44

5+
/**
6+
* Responsible of gathering information about the most recent {@link Alert Tzeva Adom} in Israel.
7+
*/
58
@FunctionalInterface
69
public interface AlertSource
710
{
11+
/**
12+
* Returns an updated {@link Alert} that describes the last <b>Tzeva Adom</b> in Israel.
13+
*
14+
* @return The last alert that happened in Israel.
15+
* @throws Exception If the information gathering process encountered an exception(typically {@code IOException})
16+
* @apiNote This should never return a cached value, don't make a joke.
17+
*/
818
Alert getMostRecentAlert() throws Exception;
919

1020

11-
public static final Alert EMPTY_RESPONSE = null;
21+
/**
22+
* This object signals that no Exception occurred while {@link #getMostRecentAlert()}, but no alert was returned.
23+
* <p>
24+
* Example: <i>Pikud Ha'oref</i> usually returns an empty JSON if no Tzeva Adom happened in the last 24 hours.
25+
*/
26+
Alert NO_RESPONSE = null;
1227
}

src/main/java/dte/tzevaadomapi/alertsource/json/JSONAlertSource.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ public Alert getMostRecentAlert() throws Exception
3131
JSONArray alertsJsonArray = requestAlertsJSON();
3232

3333
if(alertsJsonArray == null || alertsJsonArray.isEmpty())
34-
return EMPTY_RESPONSE;
34+
return NO_RESPONSE;
3535

3636
return fromJSON((JSONObject) alertsJsonArray.get(0));
3737
}

src/main/java/dte/tzevaadomapi/notifier/TzevaAdomListener.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22

33
import dte.tzevaadomapi.alert.Alert;
44

5+
/**
6+
* Represents an action that should be done <b>immediately</b> when a Tzeva Adom takes place.
7+
*/
58
@FunctionalInterface
69
public interface TzevaAdomListener
710
{

src/main/java/dte/tzevaadomapi/notifier/TzevaAdomNotifier.java

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,14 @@
1616
import dte.tzevaadomapi.alertsource.PHOAlertSource;
1717

1818
/**
19-
* Notifies registered listeners once a Tzeva Adom takes place.
19+
* Notifies registered listeners once a <b>Tzeva Adom</b> takes place.
2020
* <p>
21-
* A request for the most recent alert is sent every constant duration, and the result is then compared to the previous one.
22-
* If the 2 alerts don't equal - It's <b>Tzeva Adom</b> and the registered listeners are notified.
21+
* The workflow of the notifier is:
22+
* <ol>
23+
* <li> Request the most recent alert sent every constant duration(typically ~2 seconds)
24+
* <li> Compare it to the previous one, or store the first result:
25+
* <li> If the 2 alerts are not identical, It's <b>Tzeva Adom</b> - and the listeners are notified immediately.
26+
* </ol>
2327
*/
2428
public class TzevaAdomNotifier
2529
{
@@ -36,12 +40,18 @@ private TzevaAdomNotifier(AlertSource alertSource, Duration requestDelay, Consum
3640
this.requestFailureHandler = requestFailureHandler;
3741
}
3842

39-
public static Builder requestFromPikudHaoref()
43+
public static Builder basedOnPikudHaoref()
4044
{
4145
return new Builder()
4246
.requestFrom(new PHOAlertSource());
4347
}
4448

49+
/**
50+
* Starts listening and reacting to <b>Tzeva Adom</b> on a separate Thread,
51+
* and returns the the corresponding {@link CompletableFuture} object for further control.
52+
*
53+
* @return The {@link CompletableFuture} responsible of reacting to <b>Tzeva Adoms</b>.
54+
*/
4555
public CompletableFuture<Void> listen()
4656
{
4757
return CompletableFuture.runAsync(() ->
@@ -54,11 +64,11 @@ public CompletableFuture<Void> listen()
5464
Alert alert = getMostRecentAlert();
5565

5666
//ignore empty responses
57-
if(alert == AlertSource.EMPTY_RESPONSE)
67+
if(alert == AlertSource.NO_RESPONSE)
5868
continue;
5969

6070
//if the last alert in history equals the the last requested - it's not Tzeva Adom
61-
if(lastTzevaAdom.equals(alert))
71+
if(alert.equals(lastTzevaAdom))
6272
continue;
6373

6474
lastTzevaAdom = alert;

src/test/java/dte/tzevaadomapi/notifier/TzevaAdomNotifierTest.java

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import java.time.Duration;
77
import java.time.LocalDateTime;
88

9+
import org.junit.jupiter.api.DisplayName;
910
import org.junit.jupiter.api.Test;
1011
import org.junit.jupiter.api.TestInstance;
1112
import org.junit.jupiter.api.TestInstance.Lifecycle;
@@ -53,6 +54,20 @@ public void testConsecutiveTzevaAdom() throws Exception
5354
assertEquals(3, simulateNotifier(4).getHistory().size());
5455
}
5556

57+
@Test
58+
@DisplayName("The usual request flow where 99% are no responses")
59+
public void testUsualRoutine() throws Exception
60+
{
61+
when(this.alertSource.getMostRecentAlert()).thenReturn(
62+
AlertSource.NO_RESPONSE,
63+
AlertSource.NO_RESPONSE,
64+
AlertSource.NO_RESPONSE,
65+
AlertSource.NO_RESPONSE,
66+
createAlert("Tel Aviv"));
67+
68+
assertEquals(1, simulateNotifier(5).getHistory().size());
69+
}
70+
5671
private static Alert createAlert(String city)
5772
{
5873
return new Alert(city, "חדירת מחבלים", LocalDateTime.now());
@@ -69,7 +84,6 @@ private TzevaAdomNotifier simulateNotifier(int alertsAmount) throws InterruptedE
6984
TzevaAdomNotifier notifier = new TzevaAdomNotifier.Builder()
7085
.every(Duration.ofMillis(5))
7186
.requestFrom(this.alertSource)
72-
.onFailedRequest(Exception::printStackTrace)
7387
.build();
7488

7589
notifier.listen();

0 commit comments

Comments
 (0)