updated decoder to use regex, added dead letter queue, and added more decoder testing

This commit is contained in:
Christopher Moyer 2023-01-03 21:47:17 -05:00
parent f108cecd86
commit 8cfbf2756b
6 changed files with 89 additions and 7 deletions

View file

@ -25,6 +25,10 @@ public class CamelConfiguration extends RouteBuilder {
@Override
public void configure() {
errorHandler(deadLetterChannel(appProperties.deadLetterRoute())
.log("Failed to process message. Sending to dead letter queue")
.useOriginalMessage());
from(appProperties.jsoCadUpdateRouteIn())
.filter(exchange -> StringUtils.isNotBlank(exchange.getIn().getBody(String.class)))
.process((exchange -> {

View file

@ -17,6 +17,8 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@ApplicationScoped
public class JsoCallDecoder {
@ -32,16 +34,23 @@ public class JsoCallDecoder {
.map(String::trim)
.toList();
String pattern = "(\\d+)\\s+(\\d{1,2}-\\d{1,2} \\d{1,2}:\\d{1,2})\\s+(.+)\\s+( \\d+\\s?[\\w\\d]*)\\s+(\\D+)";
Pattern p = Pattern.compile(pattern);
List<JsoCall> jsoCalls = new ArrayList<>();
for (String call : newCalls) {
Matcher m = p.matcher(call);
if (!m.matches() && m.groupCount() != 5) {
Log.warnf("Failed to parse call\n%s", call);
continue;
}
JsoCall jsoCall = new JsoCall();
String[] workingString = call.split(" ", 5);
workingString[4] = workingString[4].trim();
jsoCall.setIncidentNumber(workingString[0]);
jsoCall.setDispatchedTime(parseTimeWithoutYear(workingString[2] + " " + workingString[3].trim()));
jsoCall.setAddress(workingString[4].substring(0, 61).trim());
jsoCall.setSignal(workingString[4].substring(61, 69).trim());
jsoCall.setCallDescription(workingString[4].substring(69).trim());
jsoCall.setIncidentNumber(m.group(1).trim());
jsoCall.setDispatchedTime(parseTimeWithoutYear(m.group(2).trim()));
jsoCall.setAddress(m.group(3).trim());
jsoCall.setSignal(m.group(4).trim());
jsoCall.setCallDescription(m.group(5).trim());
if (!jsoCall.getAddress().contains("I95")
&& !jsoCall.getAddress().contains("I295") && !jsoCall.getAddress().contains("I10")) {
jsoCall.setPoint(geoCodeAddress(jsoCall.getAddress()));

View file

@ -7,6 +7,7 @@ public interface AppProperties {
String jsoCadUpdateRouteIn();
String jsoCadUpdateRouteOut();
String deadLetterRoute();
String telegramRoute();
String googleApiKey();
double myLat();

View file

@ -1,5 +1,6 @@
app.jso-cad-update-route-in=rabbitmq:${RABBITMQ_IP}/jso.cad.updates.to.postgres?queue=jso.cad.update.received&declare=false&vhost=jso&username=${RABBITMQ_USER}&password=${RABBITMQ_PASSWORD}&autoDelete=false
app.jso-cad-update-route-out=sql:INSERT INTO calls(incident_number, dispatched_time, address, signal, call_description, point) VALUES (:#incident_number, :#dispatched_time, :#address, :#signal, :#call_description, point(:#x, :#y))
app.dead-letter-route=rabbitmq:${RABBITMQ_IP}/failed.updates?declare=false&vhost=jso&username=${RABBITMQ_USER}&password=${RABBITMQ_PASSWORD}&autoDelete=false
app.telegram-route=telegram:bots?authorizationToken=${TELEGRAM_BOT_ID}&chatId=${CHAT_ID}
app.google-api-key=${GOOGLE_API_KEY}

View file

@ -8,6 +8,7 @@ import java.nio.file.Paths;
import java.util.List;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
class JsoCallDecoderTest {
@ -19,4 +20,48 @@ class JsoCallDecoderTest {
List<JsoCall> calls = decoder.decodeJsoCallUpdates(data);
assertEquals(52, calls.size());
}
@Test
void testEdgeCaseSignals() throws IOException {
String data = Files.readString(Paths.get("src/test/resources/edge-cases.txt"));
JsoCallDecoder decoder = new JsoCallDecoder();
List<JsoCall> calls = decoder.decodeJsoCallUpdates(data);
assertEquals(5, calls.size());
JsoCall firstCall = calls.get(0);
assertEquals("202200769492", firstCall.getIncidentNumber());
assertNotNull(firstCall.getDispatchedTime());
assertEquals("5200 RAMONA BLVD", firstCall.getAddress());
assertEquals("13", firstCall.getSignal());
assertEquals("SUSPICIOUS PERSON", firstCall.getCallDescription());
JsoCall secondCall = calls.get(1);
assertEquals("202200769474", secondCall.getIncidentNumber());
assertNotNull(secondCall.getDispatchedTime());
assertEquals("9100 MERRILL RD", secondCall.getAddress());
assertEquals("4", secondCall.getSignal());
assertEquals("AUTO CRASH", secondCall.getCallDescription());
JsoCall thirdCall = calls.get(2);
assertEquals("202200769409", thirdCall.getIncidentNumber());
assertNotNull(thirdCall.getDispatchedTime());
assertEquals("1000 ST CLAIR ST", thirdCall.getAddress());
assertEquals("21CT", thirdCall.getSignal());
assertEquals("BURGLARY CONVEYANCE TELESERVE", thirdCall.getCallDescription());
JsoCall fourthCall = calls.get(3);
assertEquals("202300004101", fourthCall.getIncidentNumber());
assertNotNull(fourthCall.getDispatchedTime());
assertEquals("12000 ATLANTIC BLVD", fourthCall.getAddress());
assertEquals("1050", fourthCall.getSignal());
assertEquals("TRAFFIC STOP", fourthCall.getCallDescription());
JsoCall fifthCall = calls.get(4);
assertEquals("202300004011", fifthCall.getIncidentNumber());
assertNotNull(fifthCall.getDispatchedTime());
assertEquals("BULLS BAY HWY / BEAVER ST W", fifthCall.getAddress());
assertEquals("0 13", fifthCall.getSignal());
assertEquals("ARMED SUSPICIOUS PERSON", fifthCall.getCallDescription());
}
}

View file

@ -0,0 +1,22 @@
JSO CAD
JACKSONVILLE SHERIFF'S OFFICE
JSO Calls for Service
COMPLETED DISPATCHED CALLS FOR SERVICE
Welcome to the Jacksonville Sheriffs Office Completed Dispatched Calls for Service webpage. This page displays calls for service made to the Jacksonville Sheriff's Office that have recently been completed. The data on this page is refreshed automatically.
This information is not intended to be used as official crime data. This program does not provide information about all crimes, and excludes specific incidents such as sexual assaults and child abuse.
Disclaimer: The Jacksonville Sheriff's Office makes every effort to produce and publish current and accurate information. No warranties, expressed or implied, are provided for the data herein, its use, or its interpretation. The services provided are for informational purposes only and should not be relied on for any type of legal action.
(changed) Last refreshed 12/31 12:49:22
(into ) Last refreshed 12/31 13:45:54
Incident # Dispatched Block Address Signal Call Description
(added ) 202200769492 12-31 12:26 5200 RAMONA BLVD 13 SUSPICIOUS PERSON
(added ) 202200769474 12-31 12:19 9100 MERRILL RD 4 AUTO CRASH
(added ) 202200769409 12-31 11:18 1000 ST CLAIR ST 21CT BURGLARY CONVEYANCE TELESERVE
(added ) 202300004101 1-3 08:29 12000 ATLANTIC BLVD 1050 TRAFFIC STOP
(added ) 202300004011 1-3 07:37 BULLS BAY HWY / BEAVER ST W 0 13 ARMED SUSPICIOUS PERSON