-
Notifications
You must be signed in to change notification settings - Fork 6
Expand file tree
/
Copy pathLocationService.java
More file actions
100 lines (83 loc) · 3.51 KB
/
LocationService.java
File metadata and controls
100 lines (83 loc) · 3.51 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
package org.acme.functions;
import io.quarkus.arc.Arc;
import io.quarkus.arc.Unremovable;
import io.agroal.api.AgroalDataSource;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Logger;
@Unremovable
@ApplicationScoped
public class LocationService {
private static final Logger LOG = Logger.getLogger(LocationService.class.getName());
private static final Set<String> ALLOWED_COLUMNS = Set.of(
"zipCode", "countyName", "countyFips", "stateAbbreviation"
);
@Inject
AgroalDataSource dataSource;
Connection getDbConnection() throws SQLException {
return dataSource.getConnection();
}
/**
* Like {@link #lookup}, but matches filter values as case-insensitive prefix patterns.
* Trailing periods are stripped so abbreviations like "Mont." match "Montgomery".
*/
public static List<String> lookupFuzzy(String column, Map<String, Object> filters) {
Map<String, Object> patterns = new LinkedHashMap<>();
for (Map.Entry<String, Object> entry : filters.entrySet()) {
String raw = entry.getValue().toString().trim();
String pattern = raw.endsWith(".") ? raw.substring(0, raw.length() - 1) + "%" : raw + "%";
patterns.put(entry.getKey(), pattern);
}
return query(column, patterns, "LIKE");
}
public static List<String> lookup(String column, Map<String, Object> filters) {
return query(column, filters, "=");
}
private static List<String> query(String column, Map<String, Object> filters, String operator) {
if (!ALLOWED_COLUMNS.contains(column)) {
throw new IllegalArgumentException("Invalid column: " + column);
}
if (filters.isEmpty()) {
throw new IllegalArgumentException("filters must not be empty");
}
for (String key : filters.keySet()) {
if (!ALLOWED_COLUMNS.contains(key)) {
throw new IllegalArgumentException("Invalid filter key: " + key);
}
}
List<String> results = new ArrayList<>();
StringBuilder sql = new StringBuilder("SELECT DISTINCT ").append(column).append(" FROM locations WHERE ");
boolean first = true;
for (String key : filters.keySet()) {
if (!first) sql.append(" AND ");
sql.append(key).append(" ").append(operator).append(" ? COLLATE NOCASE");
first = false;
}
LocationService service = Arc.container().instance(LocationService.class).get();
try (Connection connection = service.getDbConnection();
PreparedStatement pstmt = connection.prepareStatement(sql.toString())) {
int index = 1;
for (Object value : filters.values()) {
pstmt.setString(index++, value.toString().trim());
}
try (ResultSet rs = pstmt.executeQuery()) {
while (rs.next()) {
results.add(rs.getString(column));
}
}
} catch (SQLException e) {
LOG.severe("Location lookup failed for column=" + column + " filters=" + filters + ": " + e.getMessage());
throw new RuntimeException("Location lookup failed", e);
}
return results;
}
}