forked from folio-org/mod-circulation-storage
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathPatronActionSessionAPI.java
More file actions
183 lines (153 loc) · 7.69 KB
/
Copy pathPatronActionSessionAPI.java
File metadata and controls
183 lines (153 loc) · 7.69 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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
package org.folio.rest.impl;
import static io.vertx.core.Future.succeededFuture;
import static javax.ws.rs.core.HttpHeaders.CONTENT_TYPE;
import static javax.ws.rs.core.MediaType.TEXT_PLAIN;
import static org.folio.rest.persist.PostgresClient.convertToPsqlStandard;
import static org.folio.support.DbUtil.rowSetToStream;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import javax.ws.rs.core.Response;
import org.apache.commons.lang3.StringUtils;
import org.folio.rest.RestVerticle;
import org.folio.rest.annotations.Validate;
import org.folio.rest.jaxrs.model.Errors;
import org.folio.rest.jaxrs.model.ExpiredSession;
import org.folio.rest.jaxrs.model.PatronActionExpiredIdsResponse;
import org.folio.rest.jaxrs.model.PatronActionSession;
import org.folio.rest.jaxrs.model.PatronActionSessions;
import org.folio.rest.jaxrs.resource.PatronActionSessionStorage;
import org.folio.rest.persist.PgUtil;
import org.folio.rest.tools.utils.ValidationHelper;
import org.folio.support.PgClientFutureAdapter;
import org.joda.time.DateTime;
import org.joda.time.format.ISODateTimeFormat;
import io.vertx.core.AsyncResult;
import io.vertx.core.Context;
import io.vertx.core.Handler;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;
import io.vertx.sqlclient.Row;
import io.vertx.sqlclient.RowSet;
public class PatronActionSessionAPI implements PatronActionSessionStorage {
private static final String PATRON_ACTION_SESSION_TABLE = "patron_action_session";
private static final String INTERNAL_SERVER_ERROR = "Internal Server Error";
private static final Logger LOGGER = LogManager.getLogger();
private static final String PATRON_ID = "patronId";
private static final String ACTION_TYPE = "actionType";
@Validate
@Override
public void getPatronActionSessionStoragePatronActionSessions(String totalRecords, int offset,
int limit, String query, Map<String, String> okapiHeaders,
Handler<AsyncResult<Response>> asyncResultHandler, Context vertxContext) {
PgUtil.get(PATRON_ACTION_SESSION_TABLE, PatronActionSession.class, PatronActionSessions.class,
query, offset, limit, okapiHeaders, vertxContext,
GetPatronActionSessionStoragePatronActionSessionsResponse.class, asyncResultHandler);
}
@Validate
@Override
public void postPatronActionSessionStoragePatronActionSessions(PatronActionSession entity,
Map<String, String> okapiHeaders, Handler<AsyncResult<Response>> asyncResultHandler,
Context vertxContext) {
PgUtil.post(PATRON_ACTION_SESSION_TABLE, entity, okapiHeaders, vertxContext,
PostPatronActionSessionStoragePatronActionSessionsResponse.class, asyncResultHandler);
}
@Validate
@Override
public void getPatronActionSessionStoragePatronActionSessionsByPatronSessionId(
String patronSessionId, Map<String, String> okapiHeaders,
Handler<AsyncResult<Response>> asyncResultHandler, Context vertxContext) {
PgUtil.getById(PATRON_ACTION_SESSION_TABLE, PatronActionSession.class, patronSessionId,
okapiHeaders, vertxContext, GetPatronActionSessionStoragePatronActionSessionsByPatronSessionIdResponse.class,
asyncResultHandler);
}
@Validate
@Override
public void deletePatronActionSessionStoragePatronActionSessionsByPatronSessionId(
String patronSessionId, Map<String, String> okapiHeaders,
Handler<AsyncResult<Response>> asyncResultHandler, Context vertxContext) {
PgUtil.deleteById(PATRON_ACTION_SESSION_TABLE, patronSessionId, okapiHeaders, vertxContext,
DeletePatronActionSessionStoragePatronActionSessionsByPatronSessionIdResponse.class, asyncResultHandler);
}
@Validate
@Override
public void getPatronActionSessionStorageExpiredSessionPatronIds(
String actionType, String sessionInactivityTimeLimit, int limit, Map<String, String> okapiHeaders,
Handler<AsyncResult<Response>> asyncResultHandler, Context vertxContext) {
String tenantId = okapiHeaders.get(RestVerticle.OKAPI_HEADER_TENANT);
PgClientFutureAdapter pgClient = PgClientFutureAdapter.create(vertxContext, okapiHeaders);
DateTime dateTimeLimit;
try {
dateTimeLimit = DateTime.parse(sessionInactivityTimeLimit);
} catch (Exception e) {
Errors errors = ValidationHelper.createValidationErrorMessage("session_inactivity_time_limit",
sessionInactivityTimeLimit, "Date cannot be parsed");
asyncResultHandler.handle(succeededFuture(
PatronActionSessionStorage.PutPatronActionSessionStoragePatronActionSessionsByPatronSessionIdResponse
.respond422WithApplicationJson(errors)));
return;
}
PatronActionSession.ActionType mappedActionType = null;
if (!StringUtils.isBlank(actionType)) {
try {
mappedActionType = PatronActionSession.ActionType.fromValue(actionType);
} catch (IllegalArgumentException e) {
Errors errors = ValidationHelper.createValidationErrorMessage("action_type",
sessionInactivityTimeLimit, "Invalid action type value");
asyncResultHandler.handle(succeededFuture(
PatronActionSessionStorage.PutPatronActionSessionStoragePatronActionSessionsByPatronSessionIdResponse
.respond422WithApplicationJson(errors)));
return;
}
}
String sql = toSelectExpiredSessionsQuery(tenantId, mappedActionType,
limit, dateTimeLimit);
pgClient.select(sql)
.map(this::mapPatronIdResponse)
.map(GetPatronActionSessionStorageExpiredSessionPatronIdsResponse::respond200WithApplicationJson)
.map(Response.class::cast)
.otherwise(this::mapExceptionToResponse)
.onComplete(asyncResultHandler);
}
private PatronActionExpiredIdsResponse mapPatronIdResponse(RowSet<Row> rowSet) {
List<ExpiredSession> expiredSessions = rowSetToStream(rowSet)
.map(this::mapToExpiredSession)
.collect(Collectors.toList());
return new PatronActionExpiredIdsResponse().withExpiredSessions(expiredSessions);
}
private ExpiredSession mapToExpiredSession(Row row){
return new ExpiredSession()
.withPatronId(row.getString(PATRON_ID))
.withActionType(ExpiredSession.ActionType.fromValue(row.getString(ACTION_TYPE)));
}
@Validate
@Override
public void putPatronActionSessionStoragePatronActionSessionsByPatronSessionId(
String patronSessionId, PatronActionSession entity, Map<String, String> okapiHeaders,
Handler<AsyncResult<Response>> asyncResultHandler, Context vertxContext) {
PgUtil.put(PATRON_ACTION_SESSION_TABLE, entity, patronSessionId, okapiHeaders, vertxContext,
PutPatronActionSessionStoragePatronActionSessionsByPatronSessionIdResponse.class, asyncResultHandler);
}
private String toSelectExpiredSessionsQuery(String tenant, PatronActionSession.ActionType actionType,
int limit, DateTime lastActionDateLimit){
String actionTypeFilter = actionType != null
? String.format("WHERE jsonb ->> 'actionType' = '%s'", actionType)
: "";
String tableName = String.format("%s.%s", convertToPsqlStandard(tenant), PATRON_ACTION_SESSION_TABLE);
String limitDate = lastActionDateLimit.toString(ISODateTimeFormat.dateTime());
return String.format("SELECT jsonb ->> 'patronId' AS \"%s\", " +
"jsonb ->> 'actionType' AS \"%s\" " +
"FROM %s %s " +
"GROUP BY jsonb ->> 'patronId', jsonb ->> 'actionType' " +
"HAVING max(jsonb #>> '{metadata,createdDate}') < '%s' " +
"ORDER BY max(jsonb #>> '{metadata,createdDate}') ASC " +
"LIMIT '%d'", PATRON_ID, ACTION_TYPE, tableName, actionTypeFilter, limitDate, limit);
}
private Response mapExceptionToResponse(Throwable t) {
LOGGER.error(t.getMessage(), t);
return Response.status(500)
.header(CONTENT_TYPE, TEXT_PLAIN)
.entity(INTERNAL_SERVER_ERROR)
.build();
}
}