split to poststats-api/api-site
This commit is contained in:
179
pom.xml
179
pom.xml
@@ -1,54 +1,37 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.poststats</groupId>
|
||||
<groupId>com.poststats.golf</groupId>
|
||||
<artifactId>golf-api</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<packaging>war</packaging>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>1.8</maven.compiler.source>
|
||||
<maven.compiler.target>1.8</maven.compiler.target>
|
||||
<project.build.sourceEncoding>utf-8</project.build.sourceEncoding>
|
||||
<maven.compiler.source>11</maven.compiler.source>
|
||||
<maven.compiler.target>11</maven.compiler.target>
|
||||
<maven.compiler.release>11</maven.compiler.release>
|
||||
<maven.compiler.debug>true</maven.compiler.debug>
|
||||
<maven.compiler.debuglevel>lines,vars,source</maven.compiler.debuglevel>
|
||||
|
||||
<server.hostname>poststats.com</server.hostname>
|
||||
<server.path.tomcat>/var/local/tomcat7-${env}</server.path.tomcat>
|
||||
<server.path.configs>${server.path.tomcat}/shared/classes</server.path.configs>
|
||||
<server.path.webapps>${server.path.tomcat}/webapps/golf.api.poststats.com</server.path.webapps>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.glassfish.jersey.bundles</groupId>
|
||||
<artifactId>jaxrs-ri</artifactId>
|
||||
<version>2.26</version>
|
||||
<groupId>com.poststats</groupId>
|
||||
<artifactId>poststats-api</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.poststats.golf</groupId>
|
||||
<artifactId>golf-core</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-csv</artifactId>
|
||||
<version>1.5</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.poststats.golf</groupId>
|
||||
<artifactId>db</artifactId>
|
||||
<version>4.3-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.poststats</groupId>
|
||||
<artifactId>db</artifactId>
|
||||
<version>4.3-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.poststats</groupId>
|
||||
<artifactId>commons-api</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
<version>2.8.7</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
@@ -58,137 +41,19 @@
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<extensions>
|
||||
<extension>
|
||||
<groupId>org.apache.maven.wagon</groupId>
|
||||
<artifactId>wagon-ssh</artifactId>
|
||||
<version>2.10</version>
|
||||
</extension>
|
||||
</extensions>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-maven-plugin</artifactId>
|
||||
<version>9.4.8.v20171121</version>
|
||||
<groupId>io.repaint.maven</groupId>
|
||||
<artifactId>tiles-maven-plugin</artifactId>
|
||||
<version>2.33</version>
|
||||
<extensions>true</extensions>
|
||||
<configuration>
|
||||
<scanIntervalSeconds>10</scanIntervalSeconds>
|
||||
<connectors>
|
||||
<connector implementation="org.mortbay.jetty.nio.SelectChannelConnector">
|
||||
<port>8080</port>
|
||||
<maxIdleTime>60000</maxIdleTime>
|
||||
</connector>
|
||||
</connectors>
|
||||
<webApp>
|
||||
<contextPath>/</contextPath>
|
||||
<resourceBases>
|
||||
<resourceBase>${project.build.directory}/${project.artifactId}-${project.version}</resourceBase>
|
||||
</resourceBases>
|
||||
<extraClasspath>${basedir}/../../poststats-db/db/src/${env},${basedir}/../../golf-db/db/src/${env},${basedir}/src/${env}/resources</extraClasspath>
|
||||
</webApp>
|
||||
<contextXml>${basedir}/src/${env}/jetty.xml</contextXml>
|
||||
<useTestScope>true</useTestScope>
|
||||
<tiles>
|
||||
<tile>com.poststats:source-format-tile:[1.0.0,1.1.0)</tile>
|
||||
</tiles>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>com.webcohesion.enunciate</groupId>
|
||||
<artifactId>enunciate-maven-plugin</artifactId>
|
||||
<version>2.9.1</version>
|
||||
<configuration>
|
||||
<docsDir>${project.build.directory}/${project.build.finalName}</docsDir>
|
||||
<configFile>${basedir}/enunciate.xml</configFile>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>compile</phase>
|
||||
<goals>
|
||||
<goal>docs</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>digitalocean-env</id>
|
||||
<activation>
|
||||
<property>
|
||||
<name>env</name>
|
||||
</property>
|
||||
</activation>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>wagon-maven-plugin</artifactId>
|
||||
<version>1.0</version>
|
||||
<configuration>
|
||||
<serverId>digitalocean-poststats</serverId>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>upload-config-to-server</id>
|
||||
<phase>install</phase>
|
||||
<goals>
|
||||
<goal>upload</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<fromDir>${basedir}/src/${env}/resources</fromDir>
|
||||
<url>scp://${server.hostname}${server.path.configs}</url>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
<profile>
|
||||
<id>digitalocean-deploy</id>
|
||||
<activation>
|
||||
<property>
|
||||
<name>env</name>
|
||||
</property>
|
||||
</activation>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>wagon-maven-plugin</artifactId>
|
||||
<version>1.0</version>
|
||||
<configuration>
|
||||
<serverId>digitalocean-poststats</serverId>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>upload-war-to-server</id>
|
||||
<phase>install</phase>
|
||||
<goals>
|
||||
<goal>upload-single</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<fromFile>${project.build.directory}/${project.build.finalName}.war</fromFile>
|
||||
<url>scp://${server.hostname}/tmp</url>
|
||||
</configuration>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>deploy-war-in-server</id>
|
||||
<phase>install</phase>
|
||||
<goals>
|
||||
<goal>sshexec</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<url>scp://${server.hostname}</url>
|
||||
<commands>
|
||||
<command>mv /tmp/${project.build.finalName}.war ${server.path.webapps}/ROOT.war</command>
|
||||
</commands>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
</profiles>
|
||||
|
||||
</project>
|
||||
|
@@ -1,4 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
|
||||
<Configure id="golf-api" class="org.eclipse.jetty.webapp.WebAppContext">
|
||||
</Configure>
|
@@ -1,8 +0,0 @@
|
||||
package com.poststats.api.golf;
|
||||
|
||||
import javax.ws.rs.ApplicationPath;
|
||||
|
||||
@ApplicationPath("golf")
|
||||
public class Application extends javax.ws.rs.core.Application {
|
||||
|
||||
}
|
@@ -1,7 +0,0 @@
|
||||
package com.poststats.api.golf.service;
|
||||
|
||||
public interface EventService {
|
||||
|
||||
int getSeriesId(long eventId);
|
||||
|
||||
}
|
@@ -1,89 +0,0 @@
|
||||
package com.poststats.api.golf.service.impl;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.ws.rs.WebApplicationException;
|
||||
import javax.ws.rs.core.Response.Status;
|
||||
|
||||
import com.brianlong.sql.DataSet;
|
||||
import com.brianlong.sql.FlexPreparedStatement;
|
||||
import com.poststats.api.golf.service.EventPersonService;
|
||||
import com.poststats.sql.PostStatsDataSource;
|
||||
|
||||
public class DatabaseEventPersonService implements EventPersonService {
|
||||
|
||||
@Override
|
||||
public List<DataSet> getPeople(long eventId) {
|
||||
Connection dbcon = PostStatsDataSource.getInstance().acquire(true);
|
||||
try {
|
||||
return this.queryPersons(dbcon, eventId);
|
||||
} catch (SQLException se) {
|
||||
throw new WebApplicationException("Database call failure", se, Status.INTERNAL_SERVER_ERROR);
|
||||
} finally {
|
||||
PostStatsDataSource.getInstance().release(dbcon);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DataSet> getParticipants(long eventId) {
|
||||
Connection dbcon = PostStatsDataSource.getInstance().acquire(true);
|
||||
try {
|
||||
return this.queryParticipants(dbcon, eventId);
|
||||
} catch (SQLException se) {
|
||||
throw new WebApplicationException("Database call failure", se, Status.INTERNAL_SERVER_ERROR);
|
||||
} finally {
|
||||
PostStatsDataSource.getInstance().release(dbcon);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Long> getSeriesEventIdsAsParticipant(int seriesId, long personId) {
|
||||
Connection dbcon = PostStatsDataSource.getInstance().acquire(true);
|
||||
try {
|
||||
return this.querySeriesEventIdsAsParticipant(dbcon, seriesId, personId);
|
||||
} catch (SQLException se) {
|
||||
throw new WebApplicationException("Database call failure", se, Status.INTERNAL_SERVER_ERROR);
|
||||
} finally {
|
||||
PostStatsDataSource.getInstance().release(dbcon);
|
||||
}
|
||||
}
|
||||
|
||||
private List<DataSet> queryPersons(Connection dbcon, long eventId) throws SQLException {
|
||||
FlexPreparedStatement fps = new FlexPreparedStatement(dbcon, SQL_SELECT_PERSONS);
|
||||
try {
|
||||
fps.setIntegerU(1, eventId);
|
||||
return fps.executeQuery().getAllRows();
|
||||
} finally {
|
||||
fps.close();
|
||||
}
|
||||
}
|
||||
|
||||
private List<DataSet> queryParticipants(Connection dbcon, long eventId) throws SQLException {
|
||||
FlexPreparedStatement fps = new FlexPreparedStatement(dbcon, SQL_SELECT_PARTICIPANTS);
|
||||
try {
|
||||
fps.setIntegerU(1, eventId);
|
||||
return fps.executeQuery().getAllRows();
|
||||
} finally {
|
||||
fps.close();
|
||||
}
|
||||
}
|
||||
|
||||
private Set<Long> querySeriesEventIdsAsParticipant(Connection dbcon, int seriesId, long personId) throws SQLException {
|
||||
FlexPreparedStatement fps = new FlexPreparedStatement(dbcon, SQL_SELECT_PARTICIPANTS);
|
||||
try {
|
||||
fps.setSmallintU(1, seriesId);
|
||||
fps.setIntegerU(2, personId);
|
||||
|
||||
Set<Long> eventIds = new HashSet<>();
|
||||
fps.executeQuery().getFirstColumn(Long.class, eventIds);
|
||||
return eventIds;
|
||||
} finally {
|
||||
fps.close();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -1,38 +0,0 @@
|
||||
package com.poststats.api.golf.service.impl;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
|
||||
import javax.ws.rs.WebApplicationException;
|
||||
import javax.ws.rs.core.Response.Status;
|
||||
|
||||
import com.brianlong.sql.FlexPreparedStatement;
|
||||
import com.poststats.api.golf.service.EventService;
|
||||
import com.poststats.golf.sql.GolfSQL;
|
||||
import com.poststats.sql.PostStatsDataSource;
|
||||
|
||||
public class DatabaseEventService implements EventService {
|
||||
|
||||
@Override
|
||||
public int getSeriesId(long eventId) {
|
||||
Connection dbcon = PostStatsDataSource.getInstance().acquire(true);
|
||||
try {
|
||||
return this.querySeriesId(dbcon, eventId);
|
||||
} catch (SQLException se) {
|
||||
throw new WebApplicationException("Database call failure", se, Status.INTERNAL_SERVER_ERROR);
|
||||
} finally {
|
||||
PostStatsDataSource.getInstance().release(dbcon);
|
||||
}
|
||||
}
|
||||
|
||||
private int querySeriesId(Connection dbcon, long eventId) throws SQLException {
|
||||
FlexPreparedStatement fps = new FlexPreparedStatement(dbcon, GolfSQL.changeSchema("SELECT seriesId FROM ~g~.Event WHERE eventID=?"));
|
||||
try {
|
||||
fps.setIntegerU(1, eventId);
|
||||
return fps.executeQuery().getOne(Integer.class);
|
||||
} finally {
|
||||
fps.close();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
76
src/main/java/com/poststats/golf/api/EventApi.java
Normal file
76
src/main/java/com/poststats/golf/api/EventApi.java
Normal file
@@ -0,0 +1,76 @@
|
||||
package com.poststats.golf.api;
|
||||
|
||||
import com.brianlong.sql.DataSet;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.poststats.golf.api.model.Event;
|
||||
import com.poststats.golf.api.model.EventDetail;
|
||||
import com.poststats.golf.service.EventService;
|
||||
import com.poststats.golf.transformer.EventTransformer;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import jakarta.enterprise.context.RequestScoped;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.ws.rs.GET;
|
||||
import jakarta.ws.rs.Path;
|
||||
import jakarta.ws.rs.PathParam;
|
||||
import jakarta.ws.rs.Produces;
|
||||
import jakarta.ws.rs.WebApplicationException;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import jakarta.ws.rs.core.Response.Status;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* This API provides access to PostStats Golf Event meta-data and features.
|
||||
*
|
||||
* @author brian.long@poststats.com
|
||||
*/
|
||||
@RequestScoped
|
||||
@Path("/event/{eventId}")
|
||||
public class EventApi {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||
|
||||
@PathParam("eventId")
|
||||
private long eventId;
|
||||
|
||||
@Inject
|
||||
private EventService eventService;
|
||||
|
||||
@Inject
|
||||
private EventTransformer eventTransformer;
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
this.logger.debug("EventApi init: {}", this.eventId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return An event model object.
|
||||
* @throws JsonProcessingException A JSON parsing issue occurred.
|
||||
* @throws http-404 The specified event was not found.
|
||||
*/
|
||||
@GET
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public Event get() throws JsonProcessingException {
|
||||
DataSet row = this.eventService.get(this.eventId);
|
||||
if (row == null) throw new WebApplicationException("Event not found", Status.NOT_FOUND);
|
||||
|
||||
return this.eventTransformer.toModel(row);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return An event model object.
|
||||
* @throws JsonProcessingException A JSON parsing issue occurred.
|
||||
* @throws http-404 The specified event was not found.
|
||||
*/
|
||||
@GET
|
||||
@Path("/detail")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public EventDetail getDetail() throws JsonProcessingException {
|
||||
DataSet row = this.eventService.getDetail(this.eventId);
|
||||
if (row == null) throw new WebApplicationException("Event not found", Status.NOT_FOUND);
|
||||
|
||||
return (EventDetail) this.eventTransformer.toModel(row, new EventDetail());
|
||||
}
|
||||
|
||||
}
|
@@ -1,47 +1,48 @@
|
||||
package com.poststats.api.golf;
|
||||
package com.poststats.golf.api;
|
||||
|
||||
import com.brianlong.sql.DataSet;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.poststats.golf.service.EventFinanceService;
|
||||
import jakarta.annotation.security.RolesAllowed;
|
||||
import jakarta.enterprise.context.RequestScoped;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.ws.rs.GET;
|
||||
import jakarta.ws.rs.Path;
|
||||
import jakarta.ws.rs.PathParam;
|
||||
import jakarta.ws.rs.Produces;
|
||||
import jakarta.ws.rs.core.Context;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import jakarta.ws.rs.core.SecurityContext;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.ServiceLoader;
|
||||
|
||||
import javax.annotation.security.RolesAllowed;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.PathParam;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.core.Context;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.SecurityContext;
|
||||
|
||||
import org.apache.commons.csv.CSVFormat;
|
||||
import org.apache.commons.csv.CSVPrinter;
|
||||
|
||||
import com.brianlong.sql.DataSet;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.poststats.api.golf.service.EventFinanceService;
|
||||
|
||||
@RequestScoped
|
||||
@Path("/event/{eventId}/finance")
|
||||
public class EventFinanceApi {
|
||||
|
||||
|
||||
private final ObjectMapper mapper = new ObjectMapper();
|
||||
|
||||
|
||||
@PathParam("eventId")
|
||||
private long eventId;
|
||||
|
||||
|
||||
@Inject
|
||||
private EventFinanceService eventFinanceService;
|
||||
|
||||
@GET
|
||||
@Path("/balance/persons")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@RolesAllowed("member")
|
||||
public String getBalanceByPersonsAsJson(@Context SecurityContext securityContext) throws JsonProcessingException {
|
||||
if (!securityContext.isUserInRole(this.eventId + "~finance"))
|
||||
throw new SecurityException("Not permitted");
|
||||
|
||||
List<DataSet> personsBalances = this.getEventFinanceService().getPersonsBalances(this.eventId);
|
||||
|
||||
if (!securityContext.isUserInRole(this.eventId + "~finance")) throw new SecurityException("Not permitted");
|
||||
|
||||
List<DataSet> personsBalances = this.eventFinanceService.getPersonsBalances(this.eventId);
|
||||
|
||||
List<Map<String, Object>> personsBalancesJson = new ArrayList<>(personsBalances.size());
|
||||
for (DataSet personBalance : personsBalances) {
|
||||
Map<String, Object> personBalanceJson = new HashMap<>(5);
|
||||
@@ -51,53 +52,36 @@ public class EventFinanceApi {
|
||||
personBalanceJson.put("balance", personBalance.getFloat("balance"));
|
||||
personsBalancesJson.add(personBalanceJson);
|
||||
}
|
||||
|
||||
|
||||
return this.mapper.writeValueAsString(personsBalancesJson);
|
||||
}
|
||||
|
||||
|
||||
@GET
|
||||
@Path("/balance/persons/csv")
|
||||
@Produces("text/csv")
|
||||
@RolesAllowed("member")
|
||||
public String getBalanceByPersonsAsCsv(@Context SecurityContext securityContext) throws IOException {
|
||||
if (!securityContext.isUserInRole(this.eventId + "~finance"))
|
||||
throw new SecurityException("Not permitted");
|
||||
|
||||
List<DataSet> personsBalances = this.getEventFinanceService().getPersonsBalances(this.eventId);
|
||||
|
||||
if (!securityContext.isUserInRole(this.eventId + "~finance")) throw new SecurityException("Not permitted");
|
||||
|
||||
List<DataSet> personsBalances = this.eventFinanceService.getPersonsBalances(this.eventId);
|
||||
|
||||
StringBuilder personsBalancesCsvBuilder = new StringBuilder();
|
||||
CSVPrinter personsBalancesCsvPrinter = new CSVPrinter(personsBalancesCsvBuilder, CSVFormat.DEFAULT);
|
||||
try {
|
||||
personsBalancesCsvPrinter.printRecord(
|
||||
"personID",
|
||||
"lname",
|
||||
"fname",
|
||||
"suffix",
|
||||
"expense",
|
||||
"paid",
|
||||
"balance");
|
||||
|
||||
personsBalancesCsvPrinter.printRecord("personID", "lname", "fname", "suffix", "expense", "paid", "balance");
|
||||
|
||||
for (DataSet personBalance : personsBalances) {
|
||||
personsBalancesCsvPrinter.printRecord(
|
||||
personBalance.getLong("personID"),
|
||||
personBalance.getString("lname"),
|
||||
personBalance.getString("fname"),
|
||||
personBalance.getString("suffix"),
|
||||
personBalance.getFloat("expense"),
|
||||
personBalance.getFloat("paid"),
|
||||
personsBalancesCsvPrinter.printRecord(personBalance.getLong("personID"), personBalance.getString("lname"), personBalance.getString("fname"),
|
||||
personBalance.getString("suffix"), personBalance.getFloat("expense"), personBalance.getFloat("paid"),
|
||||
personBalance.getFloat("balance"));
|
||||
}
|
||||
|
||||
|
||||
personsBalancesCsvPrinter.flush();
|
||||
} finally {
|
||||
personsBalancesCsvPrinter.close();
|
||||
}
|
||||
|
||||
|
||||
return personsBalancesCsvBuilder.toString();
|
||||
}
|
||||
|
||||
private EventFinanceService getEventFinanceService() {
|
||||
return ServiceLoader.load(EventFinanceService.class).iterator().next();
|
||||
}
|
||||
|
||||
}
|
@@ -1,5 +1,22 @@
|
||||
package com.poststats.api.golf;
|
||||
package com.poststats.golf.api;
|
||||
|
||||
import com.brianlong.sql.DataSet;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.poststats.golf.service.EventPersonService;
|
||||
import com.poststats.golf.service.EventService;
|
||||
import com.poststats.security.Person;
|
||||
import jakarta.annotation.security.RolesAllowed;
|
||||
import jakarta.enterprise.context.RequestScoped;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.ws.rs.GET;
|
||||
import jakarta.ws.rs.Path;
|
||||
import jakarta.ws.rs.PathParam;
|
||||
import jakarta.ws.rs.Produces;
|
||||
import jakarta.ws.rs.QueryParam;
|
||||
import jakarta.ws.rs.core.Context;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import jakarta.ws.rs.core.SecurityContext;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
@@ -7,100 +24,86 @@ import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.ServiceLoader;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.annotation.security.RolesAllowed;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.PathParam;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.QueryParam;
|
||||
import javax.ws.rs.core.Context;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.SecurityContext;
|
||||
|
||||
import org.apache.commons.csv.CSVFormat;
|
||||
import org.apache.commons.csv.CSVPrinter;
|
||||
|
||||
import com.brianlong.sql.DataSet;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.poststats.api.golf.service.EventPersonService;
|
||||
import com.poststats.api.golf.service.EventService;
|
||||
import com.poststats.api.model.Person;
|
||||
|
||||
@RequestScoped
|
||||
@Path("/event/{eventId}")
|
||||
public class EventPersonApi {
|
||||
|
||||
|
||||
private final ObjectMapper mapper = new ObjectMapper();
|
||||
|
||||
|
||||
@PathParam("eventId")
|
||||
private long eventId;
|
||||
|
||||
|
||||
@Inject
|
||||
private EventService eventService;
|
||||
|
||||
@Inject
|
||||
private EventPersonService eventPersonService;
|
||||
|
||||
@GET
|
||||
@Path("/people")
|
||||
@Produces({MediaType.APPLICATION_JSON, "text/csv"})
|
||||
@Produces({ MediaType.APPLICATION_JSON, "text/csv" })
|
||||
@RolesAllowed("member")
|
||||
public String get(@Context SecurityContext securityContext, @QueryParam("format") String format) throws JsonProcessingException, IOException {
|
||||
if (!securityContext.isUserInRole(this.eventId + "~member"))
|
||||
throw new SecurityException("Not permitted");
|
||||
|
||||
List<DataSet> persons = this.getEventPersonService().getPeople(this.eventId);
|
||||
|
||||
if ("csv".equals(format)) {
|
||||
return this.toAddressBookAsCsv(persons);
|
||||
} else {
|
||||
return this.toAddressBookAsJson(persons);
|
||||
}
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("/participants")
|
||||
@Produces({MediaType.APPLICATION_JSON, "text/csv"})
|
||||
@RolesAllowed("member")
|
||||
public String getParticipants(@Context SecurityContext securityContext, @QueryParam("format") String format) throws JsonProcessingException, IOException {
|
||||
if (!securityContext.isUserInRole(this.eventId + "~member"))
|
||||
throw new SecurityException("Not permitted");
|
||||
|
||||
List<DataSet> persons = this.getEventPersonService().getParticipants(this.eventId);
|
||||
|
||||
if ("csv".equals(format)) {
|
||||
return this.toAddressBookAsCsv(persons);
|
||||
} else {
|
||||
return this.toAddressBookAsJson(persons);
|
||||
}
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("/participants")
|
||||
@Produces({MediaType.APPLICATION_JSON, "text/csv"})
|
||||
@RolesAllowed("member")
|
||||
public String getSeriesParticipants(@Context SecurityContext securityContext, @QueryParam("format") String format) throws JsonProcessingException, IOException {
|
||||
if (!securityContext.isUserInRole(this.eventId + "~member"))
|
||||
throw new SecurityException("Not permitted");
|
||||
|
||||
int seriesId = this.getEventService().getSeriesId(this.eventId);
|
||||
if (!securityContext.isUserInRole(this.eventId + "~member")) throw new SecurityException("Not permitted");
|
||||
|
||||
List<DataSet> persons = this.eventPersonService.getPeople(this.eventId);
|
||||
|
||||
if ("csv".equals(format)) {
|
||||
return this.toAddressBookAsCsv(persons);
|
||||
} else {
|
||||
return this.toAddressBookAsJson(persons);
|
||||
}
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("/participants")
|
||||
@Produces({ MediaType.APPLICATION_JSON, "text/csv" })
|
||||
@RolesAllowed("member")
|
||||
public String getParticipants(@Context SecurityContext securityContext, @Context @QueryParam("format") String format)
|
||||
throws JsonProcessingException, IOException {
|
||||
if (!securityContext.isUserInRole(this.eventId + "~member")) throw new SecurityException("Not permitted");
|
||||
|
||||
List<DataSet> persons = this.eventPersonService.getParticipants(this.eventId);
|
||||
|
||||
if ("csv".equals(format)) {
|
||||
return this.toAddressBookAsCsv(persons);
|
||||
} else {
|
||||
return this.toAddressBookAsJson(persons);
|
||||
}
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("/participants")
|
||||
@Produces({ MediaType.APPLICATION_JSON, "text/csv" })
|
||||
@RolesAllowed("member")
|
||||
public String getSeriesParticipants(@Context SecurityContext securityContext, @QueryParam("format") String format)
|
||||
throws JsonProcessingException, IOException {
|
||||
if (!securityContext.isUserInRole(this.eventId + "~member")) throw new SecurityException("Not permitted");
|
||||
|
||||
int seriesId = this.eventService.getSeriesId(this.eventId);
|
||||
|
||||
Person principal = (Person) securityContext.getUserPrincipal();
|
||||
Set<Long> eventIds = this.eventPersonService.getSeriesEventIdsAsParticipant(seriesId, principal.getId());
|
||||
|
||||
Person principal = (Person)securityContext.getUserPrincipal();
|
||||
Set<Long> eventIds = this.getEventPersonService().getSeriesEventIdsAsParticipant(seriesId, principal.getId());
|
||||
|
||||
Set<Long> personIds = new HashSet<>();
|
||||
List<DataSet> persons = new LinkedList<>();
|
||||
for (long eventId : eventIds) {
|
||||
List<DataSet> tmpPersons = this.getEventPersonService().getParticipants(eventId);
|
||||
List<DataSet> tmpPersons = this.eventPersonService.getParticipants(eventId);
|
||||
for (DataSet person : tmpPersons)
|
||||
if (personIds.add(person.getLong("personID")))
|
||||
persons.add(person);
|
||||
if (personIds.add(person.getLong("personID"))) persons.add(person);
|
||||
}
|
||||
|
||||
|
||||
if ("csv".equals(format)) {
|
||||
return this.toAddressBookAsCsv(persons);
|
||||
} else {
|
||||
return this.toAddressBookAsJson(persons);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private String toAddressBookAsJson(List<DataSet> persons) throws JsonProcessingException {
|
||||
List<Map<String, Object>> personsJson = new ArrayList<>(persons.size());
|
||||
for (DataSet person : persons) {
|
||||
@@ -113,46 +116,27 @@ public class EventPersonApi {
|
||||
personJson.put("emailAddress", person.getString("email"));
|
||||
personsJson.add(personJson);
|
||||
}
|
||||
|
||||
|
||||
return this.mapper.writeValueAsString(personsJson);
|
||||
}
|
||||
|
||||
|
||||
private String toAddressBookAsCsv(List<DataSet> persons) throws IOException {
|
||||
StringBuilder personsCsvBuilder = new StringBuilder();
|
||||
CSVPrinter personsCsvPrinter = new CSVPrinter(personsCsvBuilder, CSVFormat.DEFAULT);
|
||||
try {
|
||||
personsCsvPrinter.printRecord(
|
||||
"ID",
|
||||
"Prefix",
|
||||
"Last Name",
|
||||
"First Name",
|
||||
"Suffix",
|
||||
"Email Address");
|
||||
|
||||
personsCsvPrinter.printRecord("ID", "Prefix", "Last Name", "First Name", "Suffix", "Email Address");
|
||||
|
||||
for (DataSet person : persons) {
|
||||
personsCsvPrinter.printRecord(
|
||||
person.getLong("personID"),
|
||||
person.getString("prefix"),
|
||||
person.getString("lname"),
|
||||
person.getString("fname"),
|
||||
person.getString("suffix"),
|
||||
person.getString("email"));
|
||||
personsCsvPrinter.printRecord(person.getLong("personID"), person.getString("prefix"), person.getString("lname"), person.getString("fname"),
|
||||
person.getString("suffix"), person.getString("email"));
|
||||
}
|
||||
|
||||
|
||||
personsCsvPrinter.flush();
|
||||
} finally {
|
||||
personsCsvPrinter.close();
|
||||
}
|
||||
|
||||
|
||||
return personsCsvBuilder.toString();
|
||||
}
|
||||
|
||||
private EventService getEventService() {
|
||||
return ServiceLoader.load(EventService.class).iterator().next();
|
||||
}
|
||||
|
||||
private EventPersonService getEventPersonService() {
|
||||
return ServiceLoader.load(EventPersonService.class).iterator().next();
|
||||
}
|
||||
|
||||
}
|
60
src/main/java/com/poststats/golf/api/GolferApi.java
Normal file
60
src/main/java/com/poststats/golf/api/GolferApi.java
Normal file
@@ -0,0 +1,60 @@
|
||||
package com.poststats.golf.api;
|
||||
|
||||
import com.brianlong.sql.DataSet;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.poststats.api.model.Person;
|
||||
import com.poststats.golf.transformer.GolferTransformer;
|
||||
import com.poststats.service.PersonService;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import jakarta.enterprise.context.RequestScoped;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.ws.rs.GET;
|
||||
import jakarta.ws.rs.Path;
|
||||
import jakarta.ws.rs.PathParam;
|
||||
import jakarta.ws.rs.Produces;
|
||||
import jakarta.ws.rs.WebApplicationException;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import jakarta.ws.rs.core.Response.Status;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* This API provides access to PostStats Golfer meta-data and features.
|
||||
*
|
||||
* @author brian.long@poststats.com
|
||||
*/
|
||||
@RequestScoped
|
||||
@Path("/golfer/{personId}")
|
||||
public class GolferApi {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||
|
||||
@PathParam("personId")
|
||||
private long personId;
|
||||
|
||||
@Inject
|
||||
private PersonService personService;
|
||||
|
||||
@Inject
|
||||
private GolferTransformer golferTransformer;
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
this.logger.debug("GolferApi init: {}", this.personId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return An person model object.
|
||||
* @throws JsonProcessingException A JSON parsing issue occurred.
|
||||
* @throws http-404 The specified event was not found.
|
||||
*/
|
||||
@GET
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public Person get() throws JsonProcessingException {
|
||||
DataSet row = this.personService.get(this.personId);
|
||||
if (row == null) throw new WebApplicationException("Event not found", Status.NOT_FOUND);
|
||||
|
||||
return this.golferTransformer.toModel(row);
|
||||
}
|
||||
|
||||
}
|
113
src/main/java/com/poststats/golf/api/SeriesApi.java
Normal file
113
src/main/java/com/poststats/golf/api/SeriesApi.java
Normal file
@@ -0,0 +1,113 @@
|
||||
package com.poststats.golf.api;
|
||||
|
||||
import com.brianlong.sql.DataSet;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.poststats.golf.api.model.Event;
|
||||
import com.poststats.golf.api.model.Series;
|
||||
import com.poststats.golf.service.EventService;
|
||||
import com.poststats.golf.service.SeriesService;
|
||||
import com.poststats.golf.transformer.EventTransformer;
|
||||
import com.poststats.golf.transformer.SeriesTransformer;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import jakarta.enterprise.context.RequestScoped;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.ws.rs.GET;
|
||||
import jakarta.ws.rs.Path;
|
||||
import jakarta.ws.rs.PathParam;
|
||||
import jakarta.ws.rs.Produces;
|
||||
import jakarta.ws.rs.QueryParam;
|
||||
import jakarta.ws.rs.WebApplicationException;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import jakarta.ws.rs.core.Response.Status;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* This API provides access to PostStats Golf Event Series meta-data and
|
||||
* features.
|
||||
*
|
||||
* @author brian.long@poststats.com
|
||||
*/
|
||||
@RequestScoped
|
||||
@Path("/series/{seriesId}")
|
||||
public class SeriesApi {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||
|
||||
@PathParam("seriesId")
|
||||
private int seriesId;
|
||||
|
||||
@Inject
|
||||
private SeriesService seriesService;
|
||||
|
||||
@Inject
|
||||
private EventService eventService;
|
||||
|
||||
@Inject
|
||||
private SeriesTransformer seriesTransformer;
|
||||
|
||||
@Inject
|
||||
private EventTransformer eventTransformer;
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
this.logger.debug("SeriesApi init: {}", this.seriesId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return An event series model object.
|
||||
* @throws JsonProcessingException A JSON parsing issue occurred.
|
||||
* @throws http-404 The specified series was not found.
|
||||
*/
|
||||
@GET
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public Series get() throws JsonProcessingException {
|
||||
DataSet row = this.seriesService.get(this.seriesId);
|
||||
if (row == null) throw new WebApplicationException("Series not found", Status.NOT_FOUND);
|
||||
|
||||
return this.seriesTransformer.toModel(row);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return An event series model object.
|
||||
* @throws JsonProcessingException A JSON parsing issue occurred.
|
||||
* @throws http-404 The specified series was not found or it had
|
||||
* no associated events.
|
||||
*/
|
||||
@GET
|
||||
@Path("/eventIds")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public Set<Long> getEventIds() throws JsonProcessingException {
|
||||
Set<Long> eventIds = this.eventService.getIds(this.seriesId);
|
||||
if (eventIds.isEmpty()) throw new WebApplicationException("Series or events not found", Status.NOT_FOUND);
|
||||
return eventIds;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param reverse `true` to sort events in reverse chronological order; `false`
|
||||
* (default) otherwise.
|
||||
* @return A list of event model objects.
|
||||
* @throws JsonProcessingException A JSON parsing issue occurred.
|
||||
* @throws http-404 The specified series was not found or it had
|
||||
* no associated events.
|
||||
*/
|
||||
@GET
|
||||
@Path("/events")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public List<Event> getEvents(@QueryParam("reverse") Boolean reverse) throws JsonProcessingException {
|
||||
Map<Long, DataSet> rows = this.eventService.get(this.seriesId, !Boolean.TRUE.equals(reverse));
|
||||
if (rows.isEmpty()) throw new WebApplicationException("Series or events not found", Status.NOT_FOUND);
|
||||
|
||||
List<Event> events = new LinkedList<Event>();
|
||||
for (DataSet row : rows.values()) {
|
||||
events.add(this.eventTransformer.toModel(row));
|
||||
}
|
||||
|
||||
return events;
|
||||
}
|
||||
|
||||
}
|
@@ -1,26 +1,27 @@
|
||||
package com.poststats.api.golf;
|
||||
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
package com.poststats.golf.api;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.node.TextNode;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.ws.rs.GET;
|
||||
import jakarta.ws.rs.Path;
|
||||
import jakarta.ws.rs.Produces;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
|
||||
@ApplicationScoped
|
||||
@Path("/version")
|
||||
public class VersionApi {
|
||||
|
||||
|
||||
private ObjectMapper mapper = new ObjectMapper();
|
||||
|
||||
|
||||
@GET
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public String get() throws JsonProcessingException {
|
||||
// FIXME make dynamic
|
||||
return this.mapper.writeValueAsString(new TextNode("1.0"));
|
||||
}
|
||||
|
||||
|
||||
@GET
|
||||
@Path("/pattern")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
126
src/main/java/com/poststats/golf/api/model/Event.java
Normal file
126
src/main/java/com/poststats/golf/api/model/Event.java
Normal file
@@ -0,0 +1,126 @@
|
||||
package com.poststats.golf.api.model;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import jakarta.annotation.Generated;
|
||||
import java.time.LocalDate;
|
||||
|
||||
/**
|
||||
* @author brian.long@poststats.com
|
||||
*/
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class Event {
|
||||
|
||||
@JsonProperty(required = true)
|
||||
private long id;
|
||||
@JsonProperty(required = true)
|
||||
private String name;
|
||||
@JsonProperty
|
||||
private String location;
|
||||
@JsonProperty
|
||||
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "YYYY-MM-dd")
|
||||
private LocalDate liveline;
|
||||
@JsonProperty
|
||||
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "YYYY-MM-dd")
|
||||
private LocalDate deadline;
|
||||
@JsonProperty
|
||||
private int seriesId;
|
||||
|
||||
@Generated("Eclipse")
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Generated("Eclipse")
|
||||
public void setId(long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@Generated("Eclipse")
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Generated("Eclipse")
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Generated("Eclipse")
|
||||
public String getLocation() {
|
||||
return location;
|
||||
}
|
||||
|
||||
@Generated("Eclipse")
|
||||
public void setLocation(String location) {
|
||||
this.location = location;
|
||||
}
|
||||
|
||||
@Generated("Eclipse")
|
||||
public LocalDate getLiveline() {
|
||||
return liveline;
|
||||
}
|
||||
|
||||
@Generated("Eclipse")
|
||||
public void setLiveline(LocalDate liveline) {
|
||||
this.liveline = liveline;
|
||||
}
|
||||
|
||||
@Generated("Eclipse")
|
||||
public LocalDate getDeadline() {
|
||||
return deadline;
|
||||
}
|
||||
|
||||
@Generated("Eclipse")
|
||||
public void setDeadline(LocalDate deadline) {
|
||||
this.deadline = deadline;
|
||||
}
|
||||
|
||||
@Generated("Eclipse")
|
||||
public int getSeriesId() {
|
||||
return seriesId;
|
||||
}
|
||||
|
||||
@Generated("Eclipse")
|
||||
public void setSeriesId(int seriesId) {
|
||||
this.seriesId = seriesId;
|
||||
}
|
||||
|
||||
@Generated("Spark")
|
||||
public Event withId(long id) {
|
||||
this.id = id;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Generated("Spark")
|
||||
public Event withName(String name) {
|
||||
this.name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Generated("Spark")
|
||||
public Event withLocation(String location) {
|
||||
this.location = location;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Generated("Spark")
|
||||
public Event withLiveline(LocalDate liveline) {
|
||||
this.liveline = liveline;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Generated("Spark")
|
||||
public Event withDeadline(LocalDate deadline) {
|
||||
this.deadline = deadline;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Generated("Spark")
|
||||
public Event withSeriesId(int seriesId) {
|
||||
this.seriesId = seriesId;
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
11
src/main/java/com/poststats/golf/api/model/EventDetail.java
Normal file
11
src/main/java/com/poststats/golf/api/model/EventDetail.java
Normal file
@@ -0,0 +1,11 @@
|
||||
package com.poststats.golf.api.model;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
|
||||
/**
|
||||
* @author brian.long@poststats.com
|
||||
*/
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class EventDetail extends Event {
|
||||
|
||||
}
|
50
src/main/java/com/poststats/golf/api/model/Series.java
Normal file
50
src/main/java/com/poststats/golf/api/model/Series.java
Normal file
@@ -0,0 +1,50 @@
|
||||
package com.poststats.golf.api.model;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import jakarta.annotation.Generated;
|
||||
|
||||
/**
|
||||
* @author brian.long@poststats.com
|
||||
*/
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class Series {
|
||||
|
||||
@JsonProperty(required = true)
|
||||
private long id;
|
||||
@JsonProperty(required = true)
|
||||
private String name;
|
||||
|
||||
@Generated("Eclipse")
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Generated("Eclipse")
|
||||
public void setId(long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@Generated("Eclipse")
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Generated("Eclipse")
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Generated("Spark")
|
||||
public Series withId(long id) {
|
||||
this.id = id;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Generated("Spark")
|
||||
public Series withName(String name) {
|
||||
this.name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
4
src/main/java/com/poststats/golf/package-info.java
Normal file
4
src/main/java/com/poststats/golf/package-info.java
Normal file
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* Here is a description.
|
||||
*/
|
||||
package com.poststats.golf;
|
@@ -0,0 +1,38 @@
|
||||
package com.poststats.golf.security;
|
||||
|
||||
import com.poststats.security.Person;
|
||||
import jakarta.ws.rs.core.SecurityContext;
|
||||
import java.security.Principal;
|
||||
|
||||
public class EventPersonSecurityContext implements SecurityContext {
|
||||
|
||||
private final SecurityContext securityContext;
|
||||
private final long eventId;
|
||||
|
||||
public EventPersonSecurityContext(SecurityContext securityContext, long eventId) {
|
||||
this.securityContext = securityContext;
|
||||
this.eventId = eventId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Principal getUserPrincipal() {
|
||||
return this.securityContext.getUserPrincipal();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUserInRole(String role) {
|
||||
Person person = (Person) this.securityContext.getUserPrincipal();
|
||||
return person.hasAccessControl(role, this.eventId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAuthenticationScheme() {
|
||||
return this.securityContext.getAuthenticationScheme();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSecure() {
|
||||
return this.securityContext.isSecure();
|
||||
}
|
||||
|
||||
}
|
@@ -1,11 +1,10 @@
|
||||
package com.poststats.api.golf.service;
|
||||
|
||||
import java.util.List;
|
||||
package com.poststats.golf.service;
|
||||
|
||||
import com.brianlong.sql.DataSet;
|
||||
import java.util.List;
|
||||
|
||||
public interface EventFinanceService {
|
||||
|
||||
|
||||
List<DataSet> getPersonsBalances(long eventId);
|
||||
|
||||
}
|
@@ -1,16 +1,15 @@
|
||||
package com.poststats.api.golf.service;
|
||||
package com.poststats.golf.service;
|
||||
|
||||
import com.brianlong.sql.DataSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import com.brianlong.sql.DataSet;
|
||||
|
||||
public interface EventPersonService {
|
||||
|
||||
|
||||
List<DataSet> getPeople(long eventId);
|
||||
|
||||
|
||||
List<DataSet> getParticipants(long eventId);
|
||||
|
||||
|
||||
Set<Long> getSeriesEventIdsAsParticipant(int seriesId, long personId);
|
||||
|
||||
}
|
19
src/main/java/com/poststats/golf/service/EventService.java
Normal file
19
src/main/java/com/poststats/golf/service/EventService.java
Normal file
@@ -0,0 +1,19 @@
|
||||
package com.poststats.golf.service;
|
||||
|
||||
import com.brianlong.sql.DataSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public interface EventService {
|
||||
|
||||
DataSet get(long eventId);
|
||||
|
||||
DataSet getDetail(long eventId);
|
||||
|
||||
Map<Long, DataSet> get(int seriesId, boolean chronological);
|
||||
|
||||
Set<Long> getIds(int seriesId);
|
||||
|
||||
int getSeriesId(long eventId);
|
||||
|
||||
}
|
@@ -1,13 +1,12 @@
|
||||
package com.poststats.api.golf.service;
|
||||
|
||||
import java.util.List;
|
||||
package com.poststats.golf.service;
|
||||
|
||||
import com.brianlong.sql.DataSet;
|
||||
import java.util.List;
|
||||
|
||||
public interface SeriesPersonService {
|
||||
|
||||
List<DataSet> getSeriesPeople(int seriesId);
|
||||
|
||||
|
||||
List<DataSet> getSeriesParticipants(int seriesId);
|
||||
|
||||
}
|
11
src/main/java/com/poststats/golf/service/SeriesService.java
Normal file
11
src/main/java/com/poststats/golf/service/SeriesService.java
Normal file
@@ -0,0 +1,11 @@
|
||||
package com.poststats.golf.service;
|
||||
|
||||
import com.brianlong.sql.DataSet;
|
||||
|
||||
public interface SeriesService {
|
||||
|
||||
DataSet get(int seriesId);
|
||||
|
||||
DataSet getByEventId(long eventId);
|
||||
|
||||
}
|
@@ -1,45 +1,54 @@
|
||||
package com.poststats.api.golf.service.impl;
|
||||
package com.poststats.golf.service.db;
|
||||
|
||||
import com.brianlong.sql.DataSet;
|
||||
import com.brianlong.sql.FlexPreparedStatement;
|
||||
import com.poststats.golf.service.EventFinanceService;
|
||||
import com.poststats.golf.sql.GolfSQL;
|
||||
import com.poststats.sql.PostStatsDataSource;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.ws.rs.WebApplicationException;
|
||||
import jakarta.ws.rs.core.Response.Status;
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
|
||||
import javax.ws.rs.WebApplicationException;
|
||||
import javax.ws.rs.core.Response.Status;
|
||||
@ApplicationScoped
|
||||
public class EventFinanceServiceDAO implements EventFinanceService {
|
||||
|
||||
import com.brianlong.sql.DataSet;
|
||||
import com.brianlong.sql.FlexPreparedStatement;
|
||||
import com.poststats.api.golf.service.EventFinanceService;
|
||||
import com.poststats.golf.sql.GolfSQL;
|
||||
import com.poststats.sql.PostStatsDataSource;
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
System.out.println("EventFinanceServiceDAO init");
|
||||
}
|
||||
|
||||
public class DatabaseEventFinanceService implements EventFinanceService {
|
||||
|
||||
@Override
|
||||
public List<DataSet> getPersonsBalances(long eventId) {
|
||||
Connection dbcon = PostStatsDataSource.getInstance().acquire(true);
|
||||
Connection dbcon = PostStatsDataSource.getInstance()
|
||||
.acquire(true);
|
||||
try {
|
||||
return this.queryPersonsBalances(dbcon, eventId);
|
||||
} catch (SQLException se) {
|
||||
throw new WebApplicationException("Database call failure", se, Status.INTERNAL_SERVER_ERROR);
|
||||
} finally {
|
||||
PostStatsDataSource.getInstance().release(dbcon);
|
||||
PostStatsDataSource.getInstance()
|
||||
.release(dbcon);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private List<DataSet> queryPersonsBalances(Connection dbcon, long eventId) throws SQLException {
|
||||
FlexPreparedStatement fps = new FlexPreparedStatement(dbcon, SQL_SELECT_BALANCES);
|
||||
try {
|
||||
for (int i = 1; i <= 5; i++)
|
||||
fps.setIntegerU(1, eventId);
|
||||
return fps.executeQuery().getAllRows();
|
||||
return fps.executeQuery()
|
||||
.getAllRows();
|
||||
} finally {
|
||||
fps.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
private static final String SQL_SELECT_BALANCES = GolfSQL.changeSchema(new StringBuilder()
|
||||
.append("SELECT P.personID, P.prefix, P.fname, P.lname, P.suffix, ")
|
||||
.append("TT.epersonID, SUM(TT.expenses) expenses, SUM(TT.paid) paid, (SUM(TT.paid)-SUM(TT.expenses)) balance ")
|
@@ -0,0 +1,96 @@
|
||||
package com.poststats.golf.service.db;
|
||||
|
||||
import com.brianlong.sql.DataSet;
|
||||
import com.poststats.golf.service.EventPersonService;
|
||||
import com.poststats.sql.PostStatsDataSource;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.ws.rs.WebApplicationException;
|
||||
import jakarta.ws.rs.core.Response.Status;
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
@ApplicationScoped
|
||||
public class EventPersonServiceDAO implements EventPersonService {
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
System.out.println("EventFinanceServiceDAO init");
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DataSet> getPeople(long eventId) {
|
||||
Connection dbcon = PostStatsDataSource.getInstance()
|
||||
.acquire(true);
|
||||
try {
|
||||
return this.queryPersons(dbcon, eventId);
|
||||
} catch (SQLException se) {
|
||||
throw new WebApplicationException("Database call failure", se, Status.INTERNAL_SERVER_ERROR);
|
||||
} finally {
|
||||
PostStatsDataSource.getInstance()
|
||||
.release(dbcon);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DataSet> getParticipants(long eventId) {
|
||||
Connection dbcon = PostStatsDataSource.getInstance()
|
||||
.acquire(true);
|
||||
try {
|
||||
return this.queryParticipants(dbcon, eventId);
|
||||
} catch (SQLException se) {
|
||||
throw new WebApplicationException("Database call failure", se, Status.INTERNAL_SERVER_ERROR);
|
||||
} finally {
|
||||
PostStatsDataSource.getInstance()
|
||||
.release(dbcon);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Long> getSeriesEventIdsAsParticipant(int seriesId, long personId) {
|
||||
Connection dbcon = PostStatsDataSource.getInstance()
|
||||
.acquire(true);
|
||||
try {
|
||||
return this.querySeriesEventIdsAsParticipant(dbcon, seriesId, personId);
|
||||
} catch (SQLException se) {
|
||||
throw new WebApplicationException("Database call failure", se, Status.INTERNAL_SERVER_ERROR);
|
||||
} finally {
|
||||
PostStatsDataSource.getInstance()
|
||||
.release(dbcon);
|
||||
}
|
||||
}
|
||||
|
||||
private List<DataSet> queryPersons(Connection dbcon, long eventId) throws SQLException {
|
||||
throw new WebApplicationException(Status.NOT_IMPLEMENTED);
|
||||
/*
|
||||
* FlexPreparedStatement fps = new FlexPreparedStatement(dbcon,
|
||||
* SQL_SELECT_PERSONS); try { fps.setIntegerU(1, eventId); return
|
||||
* fps.executeQuery().getAllRows(); } finally { fps.close(); }
|
||||
*/
|
||||
}
|
||||
|
||||
private List<DataSet> queryParticipants(Connection dbcon, long eventId) throws SQLException {
|
||||
throw new WebApplicationException(Status.NOT_IMPLEMENTED);
|
||||
/*
|
||||
* FlexPreparedStatement fps = new FlexPreparedStatement(dbcon,
|
||||
* SQL_SELECT_PARTICIPANTS); try { fps.setIntegerU(1, eventId); return
|
||||
* fps.executeQuery().getAllRows(); } finally { fps.close(); }
|
||||
*/
|
||||
}
|
||||
|
||||
private Set<Long> querySeriesEventIdsAsParticipant(Connection dbcon, int seriesId, long personId) throws SQLException {
|
||||
throw new WebApplicationException(Status.NOT_IMPLEMENTED);
|
||||
/*
|
||||
* FlexPreparedStatement fps = new FlexPreparedStatement(dbcon,
|
||||
* SQL_SELECT_PARTICIPANTS); try { fps.setSmallintU(1, seriesId);
|
||||
* fps.setIntegerU(2, personId);
|
||||
*
|
||||
* Set<Long> eventIds = new HashSet<>();
|
||||
* fps.executeQuery().getFirstColumn(Long.class, eventIds); return eventIds; }
|
||||
* finally { fps.close(); }
|
||||
*/
|
||||
}
|
||||
|
||||
}
|
170
src/main/java/com/poststats/golf/service/db/EventServiceDAO.java
Normal file
170
src/main/java/com/poststats/golf/service/db/EventServiceDAO.java
Normal file
@@ -0,0 +1,170 @@
|
||||
package com.poststats.golf.service.db;
|
||||
|
||||
import com.brianlong.sql.DataSet;
|
||||
import com.brianlong.sql.FlexPreparedStatement;
|
||||
import com.poststats.golf.service.EventService;
|
||||
import com.poststats.golf.sql.GolfDataSource;
|
||||
import com.poststats.golf.sql.GolfSQL;
|
||||
import com.poststats.service.ServiceException;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@ApplicationScoped
|
||||
public class EventServiceDAO implements EventService {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
this.logger.debug("EventFinanceServiceDAO init");
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataSet get(long eventId) {
|
||||
Connection dbcon = GolfDataSource.getInstance()
|
||||
.acquire(true);
|
||||
try {
|
||||
return this.queryEvent(dbcon, eventId, false);
|
||||
} catch (SQLException se) {
|
||||
throw new ServiceException(se);
|
||||
} finally {
|
||||
GolfDataSource.getInstance()
|
||||
.release(dbcon);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataSet getDetail(long eventId) {
|
||||
Connection dbcon = GolfDataSource.getInstance()
|
||||
.acquire(true);
|
||||
try {
|
||||
return this.queryEvent(dbcon, eventId, true);
|
||||
} catch (SQLException se) {
|
||||
throw new ServiceException(se);
|
||||
} finally {
|
||||
GolfDataSource.getInstance()
|
||||
.release(dbcon);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<Long, DataSet> get(int seriesId, boolean chronological) {
|
||||
Connection dbcon = GolfDataSource.getInstance()
|
||||
.acquire(true);
|
||||
try {
|
||||
return this.queryEvents(dbcon, seriesId, chronological);
|
||||
} catch (SQLException se) {
|
||||
throw new ServiceException(se);
|
||||
} finally {
|
||||
GolfDataSource.getInstance()
|
||||
.release(dbcon);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Long> getIds(int seriesId) {
|
||||
Connection dbcon = GolfDataSource.getInstance()
|
||||
.acquire(true);
|
||||
try {
|
||||
return this.queryEventIds(dbcon, seriesId);
|
||||
} catch (SQLException se) {
|
||||
throw new ServiceException(se);
|
||||
} finally {
|
||||
GolfDataSource.getInstance()
|
||||
.release(dbcon);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSeriesId(long eventId) {
|
||||
Connection dbcon = GolfDataSource.getInstance()
|
||||
.acquire(true);
|
||||
try {
|
||||
return this.querySeriesId(dbcon, eventId);
|
||||
} catch (SQLException se) {
|
||||
throw new ServiceException(se);
|
||||
} finally {
|
||||
GolfDataSource.getInstance()
|
||||
.release(dbcon);
|
||||
}
|
||||
}
|
||||
|
||||
private static final String SQL_SELECT_EVENT_BRIEF = GolfSQL.changeSchema(
|
||||
"SELECT E.* "
|
||||
+ "FROM ~g~.Event E "
|
||||
+ "WHERE E.eventID=? ");
|
||||
private static final String SQL_SELECT_EVENT_DETAIL = GolfSQL.changeSchema(
|
||||
"SELECT E.*, EF.* "
|
||||
+ "FROM ~g~.Event E "
|
||||
+ " INNER JOIN ~g~.EventFeature EF ON (E.eventID=EF.eventID) "
|
||||
+ "WHERE E.eventID=? ");
|
||||
|
||||
private DataSet queryEvent(Connection dbcon, long eventId, boolean includeExtraDetail) throws SQLException {
|
||||
FlexPreparedStatement fps = new FlexPreparedStatement(dbcon, includeExtraDetail ? SQL_SELECT_EVENT_DETAIL : SQL_SELECT_EVENT_BRIEF);
|
||||
try {
|
||||
fps.setIntegerU(1, eventId);
|
||||
return fps.executeQuery()
|
||||
.getNextRow();
|
||||
} finally {
|
||||
fps.close();
|
||||
}
|
||||
}
|
||||
|
||||
private static final String SQL_SELECT_EVENTS = GolfSQL.changeSchema(
|
||||
"SELECT E.* "
|
||||
+ "FROM ~g~.Event E "
|
||||
+ "WHERE E.seriesID=? ");
|
||||
private static final String SQL_ORDER_EVENTS_ASC = "ORDER BY E.liveline ASC";
|
||||
private static final String SQL_ORDER_EVENTS_DESC = "ORDER BY E.liveline DESC";
|
||||
|
||||
private Map<Long, DataSet> queryEvents(Connection dbcon, int seriesId, boolean chronological) throws SQLException {
|
||||
FlexPreparedStatement fps = new FlexPreparedStatement(dbcon, SQL_SELECT_EVENTS + (chronological ? SQL_ORDER_EVENTS_ASC : SQL_ORDER_EVENTS_DESC));
|
||||
try {
|
||||
fps.setSmallintU(1, seriesId);
|
||||
return fps.executeQuery()
|
||||
.getAllRows("eventID", Long.class);
|
||||
} finally {
|
||||
fps.close();
|
||||
}
|
||||
}
|
||||
|
||||
private static final String SQL_SELECT_EVENT_IDS = GolfSQL.changeSchema(
|
||||
"SELECT eventID FROM ~g~.Event WHERE seriesID=? ");
|
||||
|
||||
private Set<Long> queryEventIds(Connection dbcon, int seriesId) throws SQLException {
|
||||
Set<Long> eventIds = new HashSet<>(32);
|
||||
|
||||
FlexPreparedStatement fps = new FlexPreparedStatement(dbcon, SQL_SELECT_EVENT_IDS);
|
||||
try {
|
||||
fps.setSmallintU(1, seriesId);
|
||||
fps.executeQuery()
|
||||
.getFirstColumn(Long.class, eventIds);
|
||||
} finally {
|
||||
fps.close();
|
||||
}
|
||||
|
||||
return eventIds;
|
||||
}
|
||||
|
||||
private static final String SQL_SELECT_SERIES_REF = GolfSQL.changeSchema(
|
||||
"SELECT seriesID FROM ~g~.Event WHERE eventID=?");
|
||||
|
||||
private int querySeriesId(Connection dbcon, long eventId) throws SQLException {
|
||||
FlexPreparedStatement fps = new FlexPreparedStatement(dbcon, SQL_SELECT_SERIES_REF);
|
||||
try {
|
||||
fps.setIntegerU(1, eventId);
|
||||
return fps.executeQuery()
|
||||
.getOne(Integer.class);
|
||||
} finally {
|
||||
fps.close();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,82 @@
|
||||
package com.poststats.golf.service.db;
|
||||
|
||||
import com.brianlong.sql.DataSet;
|
||||
import com.brianlong.sql.FlexPreparedStatement;
|
||||
import com.poststats.golf.service.SeriesService;
|
||||
import com.poststats.golf.sql.GolfDataSource;
|
||||
import com.poststats.golf.sql.GolfSQL;
|
||||
import com.poststats.service.ServiceException;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@ApplicationScoped
|
||||
public class SeriesServiceDAO implements SeriesService {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
this.logger.debug("SeriesServiceDAO init");
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataSet get(int seriesId) {
|
||||
Connection dbcon = GolfDataSource.getInstance()
|
||||
.acquire(true);
|
||||
try {
|
||||
return this.querySeries(dbcon, seriesId);
|
||||
} catch (SQLException se) {
|
||||
throw new ServiceException(se);
|
||||
} finally {
|
||||
GolfDataSource.getInstance()
|
||||
.release(dbcon);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataSet getByEventId(long eventId) {
|
||||
Connection dbcon = GolfDataSource.getInstance()
|
||||
.acquire(true);
|
||||
try {
|
||||
return this.querySeries(dbcon, eventId);
|
||||
} catch (SQLException se) {
|
||||
throw new ServiceException(se);
|
||||
} finally {
|
||||
GolfDataSource.getInstance()
|
||||
.release(dbcon);
|
||||
}
|
||||
}
|
||||
|
||||
private static final String SQL_SELECT_SERIES = GolfSQL.changeSchema(
|
||||
"SELECT * FROM ~g~.Series WHERE seriesID=? ");
|
||||
|
||||
private DataSet querySeries(Connection dbcon, int seriesId) throws SQLException {
|
||||
FlexPreparedStatement fps = new FlexPreparedStatement(dbcon, SQL_SELECT_SERIES);
|
||||
try {
|
||||
fps.setSmallintU(1, seriesId);
|
||||
return fps.executeQuery()
|
||||
.getNextRow();
|
||||
} finally {
|
||||
fps.close();
|
||||
}
|
||||
}
|
||||
|
||||
private static final String SQL_SELECT_SERIES_BY_EVENT_ID = GolfSQL.changeSchema(
|
||||
"SELECT * FROM ~g~.Series WHERE eventID=? ");
|
||||
|
||||
private DataSet querySeries(Connection dbcon, long eventId) throws SQLException {
|
||||
FlexPreparedStatement fps = new FlexPreparedStatement(dbcon, SQL_SELECT_SERIES_BY_EVENT_ID);
|
||||
try {
|
||||
fps.setIntegerU(1, eventId);
|
||||
return fps.executeQuery()
|
||||
.getNextRow();
|
||||
} finally {
|
||||
fps.close();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
57
src/main/java/com/poststats/golf/servlet/EventFilter.java
Normal file
57
src/main/java/com/poststats/golf/servlet/EventFilter.java
Normal file
@@ -0,0 +1,57 @@
|
||||
package com.poststats.golf.servlet;
|
||||
|
||||
import com.brianlong.util.StringUtil;
|
||||
import com.poststats.golf.Constants;
|
||||
import com.poststats.golf.security.EventPersonSecurityContext;
|
||||
import jakarta.annotation.Priority;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.ws.rs.Priorities;
|
||||
import jakarta.ws.rs.container.ContainerRequestContext;
|
||||
import jakarta.ws.rs.container.ContainerRequestFilter;
|
||||
import jakarta.ws.rs.container.PreMatching;
|
||||
import jakarta.ws.rs.core.SecurityContext;
|
||||
import jakarta.ws.rs.ext.Provider;
|
||||
import java.io.IOException;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@ApplicationScoped
|
||||
@Provider
|
||||
@PreMatching
|
||||
@Priority(Priorities.AUTHORIZATION + 10)
|
||||
public class EventFilter implements ContainerRequestFilter {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||
|
||||
@Override
|
||||
public void filter(ContainerRequestContext requestContext) throws IOException {
|
||||
String eventIdStr = requestContext.getUriInfo()
|
||||
.getPathParameters()
|
||||
.getFirst(Constants.EVENT_ID);
|
||||
eventIdStr = StringUtil.getInstance()
|
||||
.trim(eventIdStr);
|
||||
|
||||
if (eventIdStr == null) {
|
||||
eventIdStr = requestContext.getUriInfo()
|
||||
.getQueryParameters()
|
||||
.getFirst(Constants.EVENT_ID);
|
||||
eventIdStr = StringUtil.getInstance()
|
||||
.trim(eventIdStr);
|
||||
}
|
||||
|
||||
if (eventIdStr == null) return;
|
||||
|
||||
this.logger.debug("Entering event context: {}", eventIdStr);
|
||||
|
||||
long eventId = Long.valueOf(eventIdStr);
|
||||
requestContext.setProperty(Constants.EVENT_ID, eventId);
|
||||
|
||||
SecurityContext scontext = requestContext.getSecurityContext();
|
||||
if (scontext != null) {
|
||||
this.logger.debug("Authorized for Event: {} => {}", scontext.getUserPrincipal()
|
||||
.getName(), eventId);
|
||||
requestContext.setSecurityContext(new EventPersonSecurityContext(scontext, eventId));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
48
src/main/java/com/poststats/golf/servlet/SeriesFilter.java
Normal file
48
src/main/java/com/poststats/golf/servlet/SeriesFilter.java
Normal file
@@ -0,0 +1,48 @@
|
||||
package com.poststats.golf.servlet;
|
||||
|
||||
import com.brianlong.util.StringUtil;
|
||||
import com.poststats.golf.Constants;
|
||||
import jakarta.annotation.Priority;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.ws.rs.Priorities;
|
||||
import jakarta.ws.rs.container.ContainerRequestContext;
|
||||
import jakarta.ws.rs.container.ContainerRequestFilter;
|
||||
import jakarta.ws.rs.container.PreMatching;
|
||||
import jakarta.ws.rs.ext.Provider;
|
||||
import java.io.IOException;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@ApplicationScoped
|
||||
@Provider
|
||||
@PreMatching
|
||||
@Priority(Priorities.AUTHORIZATION + 5)
|
||||
public class SeriesFilter implements ContainerRequestFilter {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||
|
||||
@Override
|
||||
public void filter(ContainerRequestContext requestContext) throws IOException {
|
||||
String seriesIdStr = requestContext.getUriInfo()
|
||||
.getPathParameters()
|
||||
.getFirst(Constants.EVENT_SERIES_ID);
|
||||
seriesIdStr = StringUtil.getInstance()
|
||||
.trim(seriesIdStr);
|
||||
|
||||
if (seriesIdStr == null) {
|
||||
seriesIdStr = requestContext.getUriInfo()
|
||||
.getQueryParameters()
|
||||
.getFirst(Constants.EVENT_SERIES_ID);
|
||||
seriesIdStr = StringUtil.getInstance()
|
||||
.trim(seriesIdStr);
|
||||
}
|
||||
|
||||
if (seriesIdStr == null) return;
|
||||
|
||||
this.logger.debug("Entering series context: {}", seriesIdStr);
|
||||
|
||||
int seriesId = Integer.valueOf(seriesIdStr);
|
||||
requestContext.setProperty(Constants.EVENT_SERIES_ID, seriesId);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,41 @@
|
||||
package com.poststats.golf.transformer;
|
||||
|
||||
import com.brianlong.sql.DataSet;
|
||||
import com.poststats.golf.api.model.Event;
|
||||
import com.poststats.transformer.Transformer;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@ApplicationScoped
|
||||
public class EventTransformer implements Transformer<Event> {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||
|
||||
@Override
|
||||
public Event toModel(DataSet row) {
|
||||
return this.toModel(row, new Event());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Event toModel(DataSet row, Event event) {
|
||||
event.withId(row.getLong("eventID"))
|
||||
.withName(row.getString("event"))
|
||||
.withLiveline(row.getDate("liveline"))
|
||||
.withDeadline(row.getDate("deadline"))
|
||||
.withSeriesId(row.getInteger("seriesID"));
|
||||
|
||||
StringBuilder location = new StringBuilder();
|
||||
if (row.isNotEmpty("addrcountry")) location.append(' ')
|
||||
.append(row.getString("addrcountry"));
|
||||
if (row.isNotEmpty("addrstate")) location.insert(0, ' ')
|
||||
.insert(1, row.getString("addrstate"));
|
||||
if (row.isNotEmpty("addrcity")) location.insert(0, ',')
|
||||
.insert(0, row.getString("addrcity"));
|
||||
this.logger.debug("Formulated event {} location: {}", row.getLong("eventID"), location);
|
||||
event.setLocation(location.toString());
|
||||
|
||||
return event;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,29 @@
|
||||
package com.poststats.golf.transformer;
|
||||
|
||||
import com.brianlong.sql.DataSet;
|
||||
import com.poststats.api.model.Person;
|
||||
import com.poststats.transformer.Transformer;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@ApplicationScoped
|
||||
public class GolferTransformer implements Transformer<Person> {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||
|
||||
@Override
|
||||
public Person toModel(DataSet row) {
|
||||
return this.toModel(row, new Person());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Person toModel(DataSet row, Person person) {
|
||||
person.withId(row.getLong("personID"))
|
||||
.withFirstName(row.getString("fname"))
|
||||
.withLastName(row.getString("lname"));
|
||||
|
||||
return person;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,28 @@
|
||||
package com.poststats.golf.transformer;
|
||||
|
||||
import com.brianlong.sql.DataSet;
|
||||
import com.poststats.golf.api.model.Series;
|
||||
import com.poststats.transformer.Transformer;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@ApplicationScoped
|
||||
public class SeriesTransformer implements Transformer<Series> {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||
|
||||
@Override
|
||||
public Series toModel(DataSet row) {
|
||||
return this.toModel(row, new Series());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Series toModel(DataSet row, Series series) {
|
||||
series.withId(row.getInteger("seriesID"))
|
||||
.withName(row.getString("series"));
|
||||
|
||||
return series;
|
||||
}
|
||||
|
||||
}
|
5
src/main/resources/META-INF/beans.xml
Normal file
5
src/main/resources/META-INF/beans.xml
Normal file
@@ -0,0 +1,5 @@
|
||||
<beans version="4.0"
|
||||
xmlns="https://jakarta.ee/xml/ns/jakartaee"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/beans_4_0.xsd">
|
||||
</beans>
|
@@ -1 +0,0 @@
|
||||
com.poststats.api.golf.service.impl.DatabaseEventFinanceService
|
@@ -1 +0,0 @@
|
||||
com.poststats.api.golf.service.impl.DatabaseEventPersonService
|
@@ -1 +0,0 @@
|
||||
com.poststats.api.golf.service.impl.DatabaseEventService
|
@@ -1,24 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
|
||||
|
||||
<display-name>PostStats Golf API</display-name>
|
||||
|
||||
<context-param>
|
||||
<param-name>envConfig</param-name>
|
||||
<param-value>/env-config.golf-api.properties</param-value>
|
||||
</context-param>
|
||||
<!--
|
||||
<login-config>
|
||||
<auth-method>BASIC</auth-method>
|
||||
<realm-name>default</realm-name>
|
||||
</login-config>
|
||||
-->
|
||||
<session-config>
|
||||
<session-timeout>300</session-timeout>
|
||||
</session-config>
|
||||
|
||||
<welcome-file-list>
|
||||
<welcome-file>index.jsp</welcome-file>
|
||||
</welcome-file-list>
|
||||
|
||||
</web-app>
|
@@ -1,44 +1,45 @@
|
||||
package com.poststats.api.golf;
|
||||
package com.poststats.golf.api;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import java.io.IOException;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.poststats.api.golf.VersionApi;
|
||||
|
||||
public class VersionApiUnitTest {
|
||||
|
||||
|
||||
private static ObjectMapper om = new ObjectMapper();
|
||||
private static VersionApi api;
|
||||
|
||||
|
||||
@BeforeClass
|
||||
public static void init() {
|
||||
api = new VersionApi();
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void get() throws IOException {
|
||||
String current = api.get();
|
||||
Assert.assertNotNull(current);
|
||||
Assert.assertTrue(current.length() > 0);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void getPattern() throws IOException {
|
||||
String pattern = api.getRegexPattern();
|
||||
Assert.assertNotNull(pattern);
|
||||
Assert.assertTrue(pattern.length() > 0);
|
||||
|
||||
Pattern.compile(pattern);
|
||||
Pattern.compile(om.readValue(pattern, String.class));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void isValidFormat() throws IOException {
|
||||
String pattern = api.getRegexPattern();
|
||||
String current = api.get();
|
||||
Assert.assertTrue(Pattern.compile(pattern).matcher(current).matches());
|
||||
String pattern = om.readValue(api.getRegexPattern(), String.class);
|
||||
String current = om.readValue(api.get(), String.class);
|
||||
Assert.assertTrue(Pattern.compile(pattern)
|
||||
.matcher(current)
|
||||
.matches());
|
||||
}
|
||||
|
||||
}
|
19
src/test/resources/log4j2.properties
Normal file
19
src/test/resources/log4j2.properties
Normal file
@@ -0,0 +1,19 @@
|
||||
rootLogger.level = debug
|
||||
rootLogger.appenderRef.stdout.ref = api
|
||||
|
||||
appender.rolling.type = RollingFile
|
||||
appender.rolling.name = api
|
||||
appender.rolling.fileName = ${catalina.base}/logs/api.log
|
||||
appender.rolling.filePattern = ${catalina.base}/logs/api-%d{MM-dd-yyyy}.log.gz
|
||||
appender.rolling.layout.type = PatternLayout
|
||||
appender.rolling.layout.pattern = %d %p %C{1.} [%t] %m%n
|
||||
appender.rolling.policies.type = Policies
|
||||
appender.rolling.policies.time.type = TimeBasedTriggeringPolicy
|
||||
appender.rolling.strategy.type = DefaultRolloverStrategy
|
||||
appender.rolling.strategy.max = 10
|
||||
|
||||
logger.brianlong.name = com.brianlong
|
||||
logger.brianlong.level = debug
|
||||
|
||||
logger.poststats.name = com.poststats
|
||||
logger.poststats.level = debug
|
Reference in New Issue
Block a user