From 8b80d3ce9af8906a53f69ccaa8f5ff35037cd5f1 Mon Sep 17 00:00:00 2001 From: Brian Long Date: Sat, 11 Feb 2023 12:04:50 -0500 Subject: [PATCH] moved cache merge into the JAXRS layer --- .../com/poststats/golf/api/CourseApi.java | 5 ++ .../java/com/poststats/golf/api/EventApi.java | 6 ++ .../com/poststats/golf/api/EventRoundApi.java | 35 ++++++--- .../com/poststats/golf/api/GolferApi.java | 4 + .../poststats/golf/api/model/BaseCourse.java | 2 +- .../poststats/golf/service/CourseService.java | 4 + .../golf/service/EventRoundService.java | 12 ++- .../golf/service/db/CourseServiceDAO.java | 74 ++++++++----------- .../golf/service/db/EventRoundServiceDAO.java | 31 +++----- .../golf/service/db/EventServiceDAO.java | 22 ------ .../golf/service/db/PersonServiceDAO.java | 18 ----- 11 files changed, 94 insertions(+), 119 deletions(-) diff --git a/src/main/java/com/poststats/golf/api/CourseApi.java b/src/main/java/com/poststats/golf/api/CourseApi.java index 5955211..21a03d1 100644 --- a/src/main/java/com/poststats/golf/api/CourseApi.java +++ b/src/main/java/com/poststats/golf/api/CourseApi.java @@ -3,6 +3,7 @@ package com.poststats.golf.api; import com.brianlong.util.FlexMap; import com.poststats.golf.api.model.Course; import com.poststats.golf.service.CourseService; +import com.poststats.service.FacilityService; import com.poststats.transformer.impl.DaoConverter; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; @@ -39,6 +40,9 @@ public class CourseApi { @Inject private CourseService courseService; + @Inject + private FacilityService facilityService; + @Inject private DaoConverter converter; @@ -59,6 +63,7 @@ public class CourseApi { throw new WebApplicationException("Course not found", Status.NOT_FOUND); this.logger.trace("found: {}", this.courseId); + this.facilityService.inject("facilityID", row, "facility"); return this.converter.convertValue(row, Course.class); } diff --git a/src/main/java/com/poststats/golf/api/EventApi.java b/src/main/java/com/poststats/golf/api/EventApi.java index 39fead5..f27c1ad 100644 --- a/src/main/java/com/poststats/golf/api/EventApi.java +++ b/src/main/java/com/poststats/golf/api/EventApi.java @@ -5,6 +5,7 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.poststats.api.Constants; import com.poststats.golf.api.model.Event; import com.poststats.golf.service.EventService; +import com.poststats.golf.service.SeriesService; import com.poststats.transformer.impl.DaoConverter; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.responses.ApiResponse; @@ -38,6 +39,9 @@ public class EventApi { @Inject private EventService eventService; + @Inject + private SeriesService seriesService; + @Inject private DaoConverter converter; @@ -61,6 +65,7 @@ public class EventApi { if (row == null) throw new WebApplicationException("Event not found", Status.NOT_FOUND); + this.seriesService.inject("seriesID", row, "series"); return this.converter.convertValue(row, Event.class); } @@ -80,6 +85,7 @@ public class EventApi { if (row == null) throw new WebApplicationException("Event not found", Status.NOT_FOUND); + this.seriesService.inject("seriesID", row, "series"); return this.converter.convertValue(row, Event.class); } diff --git a/src/main/java/com/poststats/golf/api/EventRoundApi.java b/src/main/java/com/poststats/golf/api/EventRoundApi.java index 629668a..c2a11e8 100644 --- a/src/main/java/com/poststats/golf/api/EventRoundApi.java +++ b/src/main/java/com/poststats/golf/api/EventRoundApi.java @@ -3,6 +3,7 @@ package com.poststats.golf.api; import com.brianlong.util.FlexMap; import com.poststats.api.Constants; import com.poststats.golf.api.model.EventRound; +import com.poststats.golf.service.CourseService; import com.poststats.golf.service.EventRoundService; import com.poststats.transformer.impl.DaoConverter; import io.swagger.v3.oas.annotations.Operation; @@ -39,6 +40,9 @@ public class EventRoundApi { @Inject private EventRoundService roundService; + @Inject + private CourseService courseService; + @Inject private DaoConverter converter; @@ -48,7 +52,7 @@ public class EventRoundApi { } @GET - @Path("/r{number}") + @Path("/rounds/next") @Produces(Constants.V1_JSON) @Operation( summary = "Retrieves limited meta-data about an event.", @@ -56,18 +60,22 @@ public class EventRoundApi { ) @ApiResponses({ @ApiResponse(responseCode = "200", description = "Success"), - @ApiResponse(responseCode = "404", description = "An event with the specified ID could not be found") + @ApiResponse( + responseCode = "404", + description = "An event with the specified ID or upcoming event rounds could not be found" + ) }) - public EventRound getOne(@PathParam("number") short roundNumber) { - FlexMap row = this.roundService.get(this.eventId, roundNumber); - if (row == null) - throw new WebApplicationException("Event round not found", Status.NOT_FOUND); + public List getNext() { + List rows = this.roundService.getUpcoming(this.eventId); + if (rows == null || rows.isEmpty()) + throw new WebApplicationException("No event round was found", Status.NOT_FOUND); - return this.converter.convertValue(row, EventRound.class); + this.courseService.injectDeep("courseID", rows, "course"); + return this.converter.convertValue(rows, EventRound.class); } @GET - @Path("/round/{eroundId}") + @Path("/round/{eroundId:[0-9]+}") @Produces(Constants.V1_JSON) @Operation( summary = "Retrieves limited meta-data about an event.", @@ -75,7 +83,10 @@ public class EventRoundApi { ) @ApiResponses({ @ApiResponse(responseCode = "200", description = "Success"), - @ApiResponse(responseCode = "404", description = "An event with the specified ID could not be found") + @ApiResponse( + responseCode = "404", + description = "An event or event round with the specified ID could not be found" + ) }) public EventRound getOne(@PathParam("eroundId") long eroundId) { FlexMap row = this.roundService.get(eroundId); @@ -87,6 +98,7 @@ public class EventRoundApi { throw new WebApplicationException("Event round not found", Status.NOT_FOUND); } + this.courseService.injectDeep("courseID", row, "course"); return this.converter.convertValue(row, EventRound.class); } @@ -99,7 +111,10 @@ public class EventRoundApi { ) @ApiResponses({ @ApiResponse(responseCode = "200", description = "Success"), - @ApiResponse(responseCode = "404", description = "An event with the specified ID could not be found") + @ApiResponse( + responseCode = "404", + description = "An event with the specified ID or any event rounds could not be found" + ) }) public List getAll() { Map rows = this.roundService.getByEventId(this.eventId); diff --git a/src/main/java/com/poststats/golf/api/GolferApi.java b/src/main/java/com/poststats/golf/api/GolferApi.java index f57194d..eda3baf 100644 --- a/src/main/java/com/poststats/golf/api/GolferApi.java +++ b/src/main/java/com/poststats/golf/api/GolferApi.java @@ -38,6 +38,9 @@ public class GolferApi { @Inject private PersonService personService; + @Inject + private com.poststats.service.PersonService poststatsPersonService; + @Inject private DaoConverter converter; @@ -61,6 +64,7 @@ public class GolferApi { if (row == null) throw new WebApplicationException("Event not found", Status.NOT_FOUND); + this.poststatsPersonService.inject("personID", row, "person"); return this.converter.convertValue(row, Golfer.class); } diff --git a/src/main/java/com/poststats/golf/api/model/BaseCourse.java b/src/main/java/com/poststats/golf/api/model/BaseCourse.java index 7959180..90698e2 100644 --- a/src/main/java/com/poststats/golf/api/model/BaseCourse.java +++ b/src/main/java/com/poststats/golf/api/model/BaseCourse.java @@ -26,7 +26,7 @@ public abstract class BaseCourse> extend private String name; @JsonProperty - @MapEntry("coursePrefix") + @MapEntry("prefix") private String namePrefix; @JsonProperty diff --git a/src/main/java/com/poststats/golf/service/CourseService.java b/src/main/java/com/poststats/golf/service/CourseService.java index 6100197..30580d1 100644 --- a/src/main/java/com/poststats/golf/service/CourseService.java +++ b/src/main/java/com/poststats/golf/service/CourseService.java @@ -28,6 +28,10 @@ public interface CourseService extends CacheableService { */ Map get(Collection courseIds); + FlexMap injectDeep(String idKey, FlexMap parentMap, String mapKey); + + Collection injectDeep(String idKey, Collection parentMaps, String mapKey); + default SubList findByName(String name) { return this.findByName(name, 1, 10); } diff --git a/src/main/java/com/poststats/golf/service/EventRoundService.java b/src/main/java/com/poststats/golf/service/EventRoundService.java index a9f5874..877ac71 100644 --- a/src/main/java/com/poststats/golf/service/EventRoundService.java +++ b/src/main/java/com/poststats/golf/service/EventRoundService.java @@ -1,6 +1,7 @@ package com.poststats.golf.service; import com.brianlong.util.FlexMap; +import java.util.List; import java.util.Map; public interface EventRoundService { @@ -14,13 +15,16 @@ public interface EventRoundService { FlexMap get(long eroundId); /** - * This method retrieves meta-data about the specified event round. + * This method retrieves meta-data about the next event round in the specified + * event. + * + * It will only return more than one event round if the next date has more than + * one round. It will return today's round(s) until 6p EST. * * @param eventId A unique identifier for the event. - * @param number A sequential number for the event round, starting with 1. - * @return A map of meta-data specific to the event round. + * @return A list of meta-data about each event round. */ - FlexMap get(long eventId, short number); + List getUpcoming(long eventId); /** * This method retrieves meta-data about the specified event rounds. diff --git a/src/main/java/com/poststats/golf/service/db/CourseServiceDAO.java b/src/main/java/com/poststats/golf/service/db/CourseServiceDAO.java index e8efaba..061b773 100644 --- a/src/main/java/com/poststats/golf/service/db/CourseServiceDAO.java +++ b/src/main/java/com/poststats/golf/service/db/CourseServiceDAO.java @@ -1,6 +1,7 @@ package com.poststats.golf.service.db; import com.brianlong.sql.DataSet; +import com.brianlong.sql.FlexManyToOneDef; import com.brianlong.sql.FlexPreparedStatement; import com.brianlong.sql.ResultSubSetFeature; import com.brianlong.util.FlexMap; @@ -24,6 +25,7 @@ import java.util.Map; public class CourseServiceDAO extends CacheableServiceDAO implements CourseService { private final int defaultCacheExpirationInSeconds = 600; + private final FlexManyToOneDef facilityManyToOneDef = new FlexManyToOneDef("facilityID", "facility"); @Inject private FacilityService facilityService; @@ -34,27 +36,20 @@ public class CourseServiceDAO extends CacheableServiceDAO implements Co } @Override - public FlexMap get(Integer courseId) { - FlexMap row = super.get(Integer.valueOf(courseId)); - if (row == null) - return null; - - this.injectCache(row, this.facilityService, "facilityID", "facility"); - return row; + public FlexMap injectDeep(String idKey, FlexMap parentMap, String mapKey) { + FlexMap map = this.inject(idKey, parentMap, mapKey); + return this.facilityService.inject("facilityID", map, "facility"); } @Override - public Map get(Collection courseIds) { - Map rows = super.get(courseIds); - - this.injectCache(rows.values(), this.facilityService, "facilityID", "facility"); - return rows; + public Collection injectDeep(String idKey, Collection parentMaps, + String mapKey) { + Collection maps = this.inject(idKey, parentMaps, mapKey); + return this.facilityService.inject("facilityID", maps, "facility"); } @Override public SubList findByName(String name, int page, int perPage) { - SubList rows; - try { FlexPreparedStatement fps = this.sqlSelectByName.buildPreparedStatement(); try { @@ -62,34 +57,32 @@ public class CourseServiceDAO extends CacheableServiceDAO implements Co fps.setVarchar(2, "%" + name + "%"); fps.setSmallintU(3, (page - 1) * perPage); fps.setSmallintU(4, perPage); - rows = (SubList) fps.executeQuery().getAllRows(); + return (SubList) fps.executeQuery().getAllRows(this.facilityManyToOneDef); } finally { fps.close(); } } catch (SQLException se) { throw new ServiceException(se); } - - this.injectCache(rows, this.facilityService, "facilityID", "facility"); - return rows; } @Inject @Named(Constants.STATEMENT_PROVIDER_GOLF) @Statement( feature = ResultSubSetFeature.class, - sql = "SELECT CP.*, C.* " + sql = "SELECT C.courseID, C.course, C.access, CP.prefix, " + + " F.*, FP.prefix, FS.suffix, FS.suffixAbbrev " + "FROM ~g~.Course C " + " LEFT JOIN ~g~.CoursePrefix CP ON (C.prefixID=CP.prefixID) " + " INNER JOIN ~p~.Facility F ON (C.facilityID=F.facilityID) " - + "WHERE course LIKE ? OR facility LIKE ? " + + " LEFT JOIN ~p~.FacilityPrefix FP ON (F.prefixID=FP.prefixID) " + + " LEFT JOIN ~p~.FacilitySuffix FS ON (F.suffixID=FS.suffixID) " + + "WHERE C.course LIKE ? OR F.facility LIKE ? " ) private StatementProvider sqlSelectByName; @Override public SubList findByJurisdiction(String country, String state, int page, int perPage) { - SubList rows; - try { FlexPreparedStatement fps = this.sqlSelectByJurisdiction.buildPreparedStatement(); try { @@ -97,26 +90,26 @@ public class CourseServiceDAO extends CacheableServiceDAO implements Co fps.setVarchar(2, state); fps.setSmallintU(3, (page - 1) * perPage); fps.setSmallintU(4, perPage); - rows = (SubList) fps.executeQuery().getAllRows(); + return (SubList) fps.executeQuery().getAllRows(this.facilityManyToOneDef); } finally { fps.close(); } } catch (SQLException se) { throw new ServiceException(se); } - - this.injectCache(rows, this.facilityService, "facilityID", "facility"); - return rows; } @Inject @Named(Constants.STATEMENT_PROVIDER_GOLF) @Statement( feature = ResultSubSetFeature.class, - sql = "SELECT CP.*, C.* " + sql = "SELECT C.courseID, C.course, C.access, CP.prefix, " + + " F.*, FP.prefix, FS.suffix, FS.suffixAbbrev " + "FROM ~g~.Course C " + " LEFT JOIN ~g~.CoursePrefix CP ON (C.prefixID=CP.prefixID) " + " INNER JOIN ~p~.Facility F ON (C.facilityID=F.facilityID) " + + " LEFT JOIN ~p~.FacilityPrefix FP ON (F.prefixID=FP.prefixID) " + + " LEFT JOIN ~p~.FacilitySuffix FS ON (F.suffixID=FS.suffixID) " + "WHERE F.addrcountry=? AND F.addrstate=? " + " AND C.deadline IS NULL " ) @@ -126,7 +119,6 @@ public class CourseServiceDAO extends CacheableServiceDAO implements Co public SubList findByLocation(double latitude, double longitude, int radiusInMiles, int page, int perPage) { double degrees = PostStatsSQL.miles2degrees(radiusInMiles); - SubList rows; try { FlexPreparedStatement fps = this.sqlSelectByGeolocation.buildPreparedStatement(); @@ -137,26 +129,26 @@ public class CourseServiceDAO extends CacheableServiceDAO implements Co fps.setDouble(4, longitude + degrees); fps.setSmallintU(5, (page - 1) * perPage); fps.setSmallintU(6, perPage); - rows = (SubList) fps.executeQuery().getAllRows(); + return (SubList) fps.executeQuery().getAllRows(this.facilityManyToOneDef); } finally { fps.close(); } } catch (SQLException se) { throw new ServiceException(se); } - - this.injectCache(rows, this.facilityService, "facilityID", "facility"); - return rows; } @Inject @Named(Constants.STATEMENT_PROVIDER_GOLF) @Statement( feature = ResultSubSetFeature.class, - sql = "SELECT CP.*, C.* " + sql = "SELECT C.courseID, C.course, C.access, CP.prefix, " + + " F.*, FP.prefix, FS.suffix, FS.suffixAbbrev " + "FROM ~g~.Course C " + " LEFT JOIN ~g~.CoursePrefix CP ON (C.prefixID=CP.prefixID) " + " INNER JOIN ~p~.Facility F ON (C.facilityID=F.facilityID) " + + " LEFT JOIN ~p~.FacilityPrefix FP ON (F.prefixID=FP.prefixID) " + + " LEFT JOIN ~p~.FacilitySuffix FS ON (F.suffixID=FS.suffixID) " + "WHERE F.latitude>=? AND F.latitude<=? AND F.longitude>=? AND F.longitude<=? " + " AND C.deadline IS NULL " ) @@ -181,13 +173,10 @@ public class CourseServiceDAO extends CacheableServiceDAO implements Co @Inject @Named(Constants.STATEMENT_PROVIDER_GOLF) @Statement( - sql = "SELECT FP.*, FS.*, F.*, CP.prefix coursePrefix, C.* " + sql = "SELECT CP.*, C.* " + "FROM ~g~.Course C " + " LEFT JOIN ~g~.CoursePrefix CP ON (C.prefixID=CP.prefixID) " - + " INNER JOIN ~p~.Facility F ON (C.facilityID=F.facilityID) " - + " LEFT JOIN ~p~.FacilityPrefix FP ON (F.prefixID=FP.prefixID) " - + " LEFT JOIN ~p~.FacilitySuffix FS ON (F.suffixID=FS.suffixID) " - + "WHERE courseID=? " + + "WHERE C.courseID=? " ) private StatementProvider sqlSelectCourse; @@ -202,15 +191,12 @@ public class CourseServiceDAO extends CacheableServiceDAO implements Co } @Inject - @Named(Constants.STATEMENT_PROVIDER_POSTSTATS) + @Named(Constants.STATEMENT_PROVIDER_GOLF) @Statement( - sql = "SELECT FP.*, FS.*, F.*, CP.prefix coursePrefix, C.* " + sql = "SELECT CP.*, C.* " + "FROM ~g~.Course C " + " LEFT JOIN ~g~.CoursePrefix CP ON (C.prefixID=CP.prefixID) " - + " INNER JOIN ~p~.Facility F ON (C.facilityID=F.facilityID) " - + " LEFT JOIN ~p~.FacilityPrefix FP ON (F.prefixID=FP.prefixID) " - + " LEFT JOIN ~p~.FacilitySuffix FS ON (F.suffixID=FS.suffixID) " - + "WHERE courseID IN (??) " + + "WHERE C.courseID IN (??) " ) private StatementProvider sqlSelectCourses; diff --git a/src/main/java/com/poststats/golf/service/db/EventRoundServiceDAO.java b/src/main/java/com/poststats/golf/service/db/EventRoundServiceDAO.java index 28d15ee..18d3c8a 100644 --- a/src/main/java/com/poststats/golf/service/db/EventRoundServiceDAO.java +++ b/src/main/java/com/poststats/golf/service/db/EventRoundServiceDAO.java @@ -4,7 +4,6 @@ import com.brianlong.sql.DataSet; import com.brianlong.sql.FlexPreparedStatement; import com.brianlong.util.FlexMap; import com.poststats.golf.api.Constants; -import com.poststats.golf.service.CourseService; import com.poststats.golf.service.EventRoundService; import com.poststats.provider.Statement; import com.poststats.provider.StatementProvider; @@ -14,7 +13,9 @@ import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; import jakarta.inject.Named; import java.sql.SQLException; +import java.time.LocalDateTime; import java.util.Collection; +import java.util.List; import java.util.Map; @ApplicationScoped @@ -22,33 +23,23 @@ public class EventRoundServiceDAO extends CacheableServiceDAO implements E private final long defaultCacheExpirationInSeconds = 3600; - @Inject - private CourseService courseService; - @Override public FlexMap get(long eroundId) { return this.get(Long.valueOf(eroundId)); } @Override - public FlexMap get(Long eventId) { - FlexMap row = super.get(Long.valueOf(eventId)); - if (row == null) - return null; + public List getUpcoming(long eventId) { + LocalDateTime now = LocalDateTime.now(); + if (now.getHour() > 17) + now.plusDays(1); - this.injectCache(row, this.courseService, "courseID", "course"); - row.put("course", this.courseService.get(row.getInteger("courseID"))); - return row; - } - - @Override - public FlexMap get(long eventId, short number) { try { - FlexPreparedStatement fps = this.sqlSelectByNumber.buildPreparedStatement(); + FlexPreparedStatement fps = this.sqlSelectUpcoming.buildPreparedStatement(); try { fps.setIntegerU(1, eventId); - fps.setTinyintU(2, number); - return fps.executeQuery().getNextRow(); + fps.setDate(2, now.toLocalDate()); + return fps.executeQuery().getAllRows(); } finally { fps.close(); } @@ -63,9 +54,9 @@ public class EventRoundServiceDAO extends CacheableServiceDAO implements E sql = "SELECT TF.*, ER.* " + "FROM ~g~.EventRound ER " + " LEFT JOIN ~g~.TeeFormat TF ON (ER.teeFormatID=TF.teeFormatID) " - + "WHERE ER.eventID=? AND ER.round=? " + + "WHERE ER.eventID=? AND ER.date>=? AND MIN(ER.date)=ER.date " ) - private StatementProvider sqlSelectByNumber; + private StatementProvider sqlSelectUpcoming; @Override public Map getByEventId(long eventId) { diff --git a/src/main/java/com/poststats/golf/service/db/EventServiceDAO.java b/src/main/java/com/poststats/golf/service/db/EventServiceDAO.java index a8278b6..2d2ae98 100644 --- a/src/main/java/com/poststats/golf/service/db/EventServiceDAO.java +++ b/src/main/java/com/poststats/golf/service/db/EventServiceDAO.java @@ -5,7 +5,6 @@ import com.brianlong.sql.FlexPreparedStatement; import com.brianlong.util.FlexMap; import com.poststats.golf.api.Constants; import com.poststats.golf.service.EventService; -import com.poststats.golf.service.SeriesService; import com.poststats.provider.Statement; import com.poststats.provider.StatementProvider; import com.poststats.service.ServiceException; @@ -24,32 +23,11 @@ public class EventServiceDAO extends CacheableServiceDAO implements EventS private final long defaultCacheExpirationInSeconds = 3600; - @Inject - private SeriesService seriesService; - @Override public FlexMap get(long eventId) { return this.get(Long.valueOf(eventId)); } - @Override - public FlexMap get(Long eventId) { - FlexMap row = super.get(Long.valueOf(eventId)); - if (row == null) - return null; - - this.injectCache(row, this.seriesService, "seriesID", "series"); - return row; - } - - @Override - public Map get(Collection eventIds) { - Map rows = super.get(eventIds); - - this.injectCache(rows.values(), this.seriesService, "seriesID", "series"); - return rows; - } - @Override public Set getIdsBySeriesId(int seriesId) { try { diff --git a/src/main/java/com/poststats/golf/service/db/PersonServiceDAO.java b/src/main/java/com/poststats/golf/service/db/PersonServiceDAO.java index 20364e9..4e9067e 100644 --- a/src/main/java/com/poststats/golf/service/db/PersonServiceDAO.java +++ b/src/main/java/com/poststats/golf/service/db/PersonServiceDAO.java @@ -68,24 +68,6 @@ public class PersonServiceDAO extends CacheableServiceDAO implements Perso return this.get(Long.valueOf(personId)); } - @Override - public FlexMap get(Long personId) { - FlexMap row = this.get(Long.valueOf(personId)); - if (row == null) - return null; - - this.injectCache(row, this.poststatsPersonService, "personID", "person"); - return row; - } - - @Override - public Map get(Collection ids) { - Map rows = super.get(ids); - - this.injectCache(rows.values(), this.poststatsPersonService, "personID", "person"); - return rows; - } - private abstract class PrincipalCacheableFetcher implements CacheableFetcher { public abstract com.poststats.security.AuthenticatedPerson getPerson();