initial checkin
This commit is contained in:
commit
cfdc7d2e36
8
.gitignore
vendored
Normal file
8
.gitignore
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
# Maven
|
||||
target
|
||||
|
||||
# Eclipse
|
||||
.project
|
||||
.classpath
|
||||
.settings
|
||||
|
194
pom.xml
Normal file
194
pom.xml
Normal file
@ -0,0 +1,194 @@
|
||||
<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>
|
||||
<artifactId>golf-api</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<packaging>war</packaging>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>1.8</maven.compiler.source>
|
||||
<maven.compiler.target>1.8</maven.compiler.target>
|
||||
<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>
|
||||
</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>
|
||||
<version>4.12</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</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>
|
||||
<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>
|
||||
</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>
|
4
src/local/jetty.xml
Normal file
4
src/local/jetty.xml
Normal file
@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
|
||||
<Configure id="golf-api" class="org.eclipse.jetty.webapp.WebAppContext">
|
||||
</Configure>
|
8
src/main/java/com/poststats/api/golf/Application.java
Normal file
8
src/main/java/com/poststats/api/golf/Application.java
Normal file
@ -0,0 +1,8 @@
|
||||
package com.poststats.api.golf;
|
||||
|
||||
import javax.ws.rs.ApplicationPath;
|
||||
|
||||
@ApplicationPath("golf")
|
||||
public class Application extends javax.ws.rs.core.Application {
|
||||
|
||||
}
|
103
src/main/java/com/poststats/api/golf/EventFinanceApi.java
Normal file
103
src/main/java/com/poststats/api/golf/EventFinanceApi.java
Normal file
@ -0,0 +1,103 @@
|
||||
package com.poststats.api.golf;
|
||||
|
||||
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;
|
||||
|
||||
@Path("/event/{eventId}/finance")
|
||||
public class EventFinanceApi {
|
||||
|
||||
private final ObjectMapper mapper = new ObjectMapper();
|
||||
|
||||
@PathParam("eventId")
|
||||
private long eventId;
|
||||
|
||||
@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);
|
||||
|
||||
List<Map<String, Object>> personsBalancesJson = new ArrayList<>(personsBalances.size());
|
||||
for (DataSet personBalance : personsBalances) {
|
||||
Map<String, Object> personBalanceJson = new HashMap<>(5);
|
||||
personBalanceJson.put("personId", personBalance.getLong("personID"));
|
||||
personBalanceJson.put("expense", personBalance.getFloat("expense"));
|
||||
personBalanceJson.put("paid", personBalance.getFloat("paid"));
|
||||
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);
|
||||
|
||||
StringBuilder personsBalancesCsvBuilder = new StringBuilder();
|
||||
CSVPrinter personsBalancesCsvPrinter = new CSVPrinter(personsBalancesCsvBuilder, CSVFormat.DEFAULT);
|
||||
try {
|
||||
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"),
|
||||
personBalance.getFloat("balance"));
|
||||
}
|
||||
|
||||
personsBalancesCsvPrinter.flush();
|
||||
} finally {
|
||||
personsBalancesCsvPrinter.close();
|
||||
}
|
||||
|
||||
return personsBalancesCsvBuilder.toString();
|
||||
}
|
||||
|
||||
private EventFinanceService getEventFinanceService() {
|
||||
return ServiceLoader.load(EventFinanceService.class).iterator().next();
|
||||
}
|
||||
|
||||
}
|
158
src/main/java/com/poststats/api/golf/EventPersonApi.java
Normal file
158
src/main/java/com/poststats/api/golf/EventPersonApi.java
Normal file
@ -0,0 +1,158 @@
|
||||
package com.poststats.api.golf;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
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;
|
||||
|
||||
@Path("/event/{eventId}")
|
||||
public class EventPersonApi {
|
||||
|
||||
private final ObjectMapper mapper = new ObjectMapper();
|
||||
|
||||
@PathParam("eventId")
|
||||
private long eventId;
|
||||
|
||||
@GET
|
||||
@Path("/people")
|
||||
@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);
|
||||
|
||||
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);
|
||||
for (DataSet person : tmpPersons)
|
||||
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) {
|
||||
Map<String, Object> personJson = new HashMap<>(5);
|
||||
personJson.put("personId", person.getLong("personID"));
|
||||
personJson.put("prefix", person.getString("prefix"));
|
||||
personJson.put("lastName", person.getString("lname"));
|
||||
personJson.put("firstName", person.getString("fname"));
|
||||
personJson.put("suffix", person.getString("suffix"));
|
||||
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");
|
||||
|
||||
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.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();
|
||||
}
|
||||
|
||||
}
|
31
src/main/java/com/poststats/api/golf/VersionApi.java
Normal file
31
src/main/java/com/poststats/api/golf/VersionApi.java
Normal file
@ -0,0 +1,31 @@
|
||||
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;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.node.TextNode;
|
||||
|
||||
@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)
|
||||
public String getRegexPattern() throws JsonProcessingException {
|
||||
return this.mapper.writeValueAsString(new TextNode("[0-9]+\\.[0-9]+"));
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
package com.poststats.api.golf.service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.brianlong.sql.DataSet;
|
||||
|
||||
public interface EventFinanceService {
|
||||
|
||||
List<DataSet> getPersonsBalances(long eventId);
|
||||
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
package com.poststats.api.golf.service;
|
||||
|
||||
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);
|
||||
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
package com.poststats.api.golf.service;
|
||||
|
||||
public interface EventService {
|
||||
|
||||
int getSeriesId(long eventId);
|
||||
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
package com.poststats.api.golf.service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.brianlong.sql.DataSet;
|
||||
|
||||
public interface SeriesPersonService {
|
||||
|
||||
List<DataSet> getSeriesPeople(int seriesId);
|
||||
|
||||
List<DataSet> getSeriesParticipants(int seriesId);
|
||||
|
||||
}
|
@ -0,0 +1,81 @@
|
||||
package com.poststats.api.golf.service.impl;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
|
||||
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.EventFinanceService;
|
||||
import com.poststats.golf.sql.GolfSQL;
|
||||
import com.poststats.sql.PostStatsDataSource;
|
||||
|
||||
public class DatabaseEventFinanceService implements EventFinanceService {
|
||||
|
||||
@Override
|
||||
public List<DataSet> getPersonsBalances(long eventId) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
} 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 ")
|
||||
.append("FROM (")
|
||||
.append("SELECT ALL EP.personID, EP.epersonID, IF(EB.projectedValue IS NULL, 0, EB.projectedValue) expenses, 0 paid ")
|
||||
.append("FROM ~g~.EventPerson EP ")
|
||||
.append("LEFT JOIN ~g~.EventBudget EB ON (EP.eventID=EB.eventID) ")
|
||||
.append("WHERE EP.eventID=? ")
|
||||
.append("UNION ALL ")
|
||||
.append("SELECT ALL EP.personID, EP.epersonID, EO.amount expenses, 0 paid ")
|
||||
.append("FROM ~g~.EventPerson EP ")
|
||||
.append("INNER JOIN ~g~.EventPersonOption EPO ON (EP.epersonID=EPO.epersonID) ")
|
||||
.append("INNER JOIN ~g~.EventOption EO ON (EPO.optionID=EO.optionID) ")
|
||||
.append("WHERE EP.eventID=? AND EPO.answer='Y' AND EO.amount IS NOT NULL AND EO.waive IS FALSE ")
|
||||
.append("UNION ALL ")
|
||||
.append("SELECT ALL EP.personID, EP.epersonID, EO.amount expenses, 0 paid ")
|
||||
.append("FROM ~g~.EventPerson EP ")
|
||||
.append("INNER JOIN ~g~.EventPersonOption EPO ON (EP.epersonID=EPO.epersonID) ")
|
||||
.append("INNER JOIN ~g~.EventOption EO ON (EPO.optionID=EO.optionID) ")
|
||||
.append("WHERE EP.eventID=? AND EPO.itemID IS NOT NULL ")
|
||||
.append("AND (EO.multiple IS FALSE OR EO.funded='option' OR EO.static IS NOT NULL) ")
|
||||
.append("AND EO.amount IS NOT NULL AND EO.waive IS FALSE ")
|
||||
.append("UNION ALL ")
|
||||
.append("SELECT ALL EP.personID, EP.epersonID, EOI.amount expenses, 0 paid ")
|
||||
.append("FROM ~g~.EventPerson EP ")
|
||||
.append("INNER JOIN ~g~.EventPersonOption EPO ON (EP.epersonID=EPO.epersonID) ")
|
||||
.append("INNER JOIN ~g~.EventOption EO ON (EPO.optionID=EO.optionID) ")
|
||||
.append("INNER JOIN ~g~.EventOptionItem EOI ON (EPO.itemID=EOI.itemID) ")
|
||||
.append("WHERE EP.eventID=? AND EO.waive IS FALSE AND EO.funded='selection' AND EOI.amount IS NOT NULL ")
|
||||
.append("UNION ALL ")
|
||||
.append("SELECT ALL EPP.personID, EP.epersonID, 0 expenses, EPP.amount paid ")
|
||||
.append("FROM ~g~.EventPersonPayment EPP ")
|
||||
.append("LEFT JOIN ~g~.EventPerson EP ON (EPP.eventID=EP.eventID AND EPP.personID=EP.personID) ")
|
||||
.append("WHERE EPP.eventID=?) TT ")
|
||||
.append("INNER JOIN ~p~.Person P ")
|
||||
.append("GROUP BY P.personID ")
|
||||
.append("ORDER BY P.lname, P.fname, P.suffix").toString());
|
||||
|
||||
}
|
@ -0,0 +1,89 @@
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1 @@
|
||||
com.poststats.api.golf.service.impl.DatabaseEventFinanceService
|
@ -0,0 +1 @@
|
||||
com.poststats.api.golf.service.impl.DatabaseEventPersonService
|
@ -0,0 +1 @@
|
||||
com.poststats.api.golf.service.impl.DatabaseEventService
|
24
src/main/webapp/WEB-INF/web.xml
Normal file
24
src/main/webapp/WEB-INF/web.xml
Normal file
@ -0,0 +1,24 @@
|
||||
<?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>
|
44
src/test/java/com/poststats/api/golf/VersionApiUnitTest.java
Normal file
44
src/test/java/com/poststats/api/golf/VersionApiUnitTest.java
Normal file
@ -0,0 +1,44 @@
|
||||
package com.poststats.api.golf;
|
||||
|
||||
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 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);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isValidFormat() throws IOException {
|
||||
String pattern = api.getRegexPattern();
|
||||
String current = api.get();
|
||||
Assert.assertTrue(Pattern.compile(pattern).matcher(current).matches());
|
||||
}
|
||||
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user