initial commit

This commit is contained in:
Brian Long 2021-12-21 17:19:13 -05:00
commit c987bc725f
38 changed files with 2304 additions and 0 deletions

12
.gitignore vendored Normal file
View File

@ -0,0 +1,12 @@
# Maven
pom.xml.versionsBackup
target
# Eclipse
.project
.classpath
.settings
# Visual Studio Code
.factorypath

View File

@ -0,0 +1,64 @@
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.inteligr8.buxfer</groupId>
<artifactId>buxfer-public-rest-api</artifactId>
<version>1.0-SNAPSHOT</version>
<name>Buxfer ReST API for Java</name>
<properties>
<project.build.sourceEncoding>utf-8</project.build.sourceEncoding>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>jakarta.ws.rs</groupId>
<artifactId>jakarta.ws.rs-api</artifactId>
<version>2.1.6</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.module</groupId>
<artifactId>jackson-module-jaxb-annotations</artifactId>
<version>2.12.2</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-javadoc-plugin</artifactId>
<executions>
<execution>
<id>javadoc</id>
<phase>package</phase>
<goals><goal>jar</goal></goals>
<configuration>
<show>public</show>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>inteligr8-public</id>
<url>https://repos.inteligr8.com/nexus/repository/inteligr8-public</url>
</repository>
</repositories>
<distributionManagement>
<repository>
<id>inteligr8-releases</id>
<url>https://repos.inteligr8.com/nexus/repository/inteligr8-public</url>
</repository>
<snapshotRepository>
<id>inteligr8-snapshots</id>
<url>https://repos.inteligr8.com/nexus/repository/inteligr8-snapshots</url>
</snapshotRepository>
</distributionManagement>
</project>

View File

@ -0,0 +1,15 @@
package com.inteligr8.buxfer;
import com.inteligr8.buxfer.api.CommandApi;
/**
* This interface consolidates the JAX-RS APIs available in the Buxfer Public
* ReST API.
*
* @author brian@inteligr8.com
*/
public interface BuxferPublicRestApi {
CommandApi getCommandApi();
}

View File

@ -0,0 +1,187 @@
package com.inteligr8.buxfer.api;
import java.time.LocalDate;
import java.time.YearMonth;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import com.inteligr8.buxfer.model.AccountsResponse;
import com.inteligr8.buxfer.model.BudgetsResponse;
import com.inteligr8.buxfer.model.ContactsResponse;
import com.inteligr8.buxfer.model.GroupsResponse;
import com.inteligr8.buxfer.model.LoansResponse;
import com.inteligr8.buxfer.model.RemindersResponse;
import com.inteligr8.buxfer.model.Response;
import com.inteligr8.buxfer.model.TagsResponse;
import com.inteligr8.buxfer.model.Transaction.Status;
import com.inteligr8.buxfer.model.TransactionsResponse;
@Path("/api")
public interface CommandApi {
@GET
@Path("/transactions")
@Produces({ "application/json" })
public Response<TransactionsResponse> getTransactions(
@QueryParam("startDate") LocalDate startDate,
@QueryParam("endDate") LocalDate endDate,
@QueryParam("status") Status status,
@QueryParam("page") int page);
@GET
@Path("/transactions")
@Produces({ "application/json" })
public Response<TransactionsResponse> getTransactionsInTag(
@QueryParam("tagName") String tagName,
@QueryParam("startDate") LocalDate startDate,
@QueryParam("endDate") LocalDate endDate,
@QueryParam("status") Status status,
@QueryParam("page") int page);
@GET
@Path("/transactions")
@Produces({ "application/json" })
public Response<TransactionsResponse> getTransactionsInAccount(
@QueryParam("accountName") String accountName,
@QueryParam("startDate") LocalDate startDate,
@QueryParam("endDate") LocalDate endDate,
@QueryParam("status") Status status,
@QueryParam("page") int page);
@GET
@Path("/transactions")
@Produces({ "application/json" })
public Response<TransactionsResponse> getTransactions(
@QueryParam("accountName") String accountName,
@QueryParam("tagName") String tagName,
@QueryParam("startDate") LocalDate startDate,
@QueryParam("endDate") LocalDate endDate,
@QueryParam("budgetName") String budgetName,
@QueryParam("contactName") String contactName,
@QueryParam("groupName") String groupName,
@QueryParam("status") Status status,
@QueryParam("page") int page);
@GET
@Path("/transactions")
@Produces({ "application/json" })
public Response<TransactionsResponse> getTransactions(
@QueryParam("accountName") String accountName,
@QueryParam("tagName") String tagName,
@QueryParam("startDate") YearMonth month,
@QueryParam("budgetName") String budgetName,
@QueryParam("contactName") String contactName,
@QueryParam("groupName") String groupName,
@QueryParam("status") Status status,
@QueryParam("page") int page);
@GET
@Path("/transactions")
@Produces({ "application/json" })
public Response<TransactionsResponse> getTransactionsByIds(
@QueryParam("accountId") String accountId,
@QueryParam("tagId") String tagId,
@QueryParam("startDate") LocalDate startDate,
@QueryParam("endDate") LocalDate endDate,
@QueryParam("budgetId") String budgetId,
@QueryParam("contactId") String contactId,
@QueryParam("groupId") String groupId,
@QueryParam("status") Status status,
@QueryParam("page") int page);
@GET
@Path("/transactions")
@Produces({ "application/json" })
public Response<TransactionsResponse> getTransactionsByIds(
@QueryParam("accountId") String accountId,
@QueryParam("tagId") String tagId,
@QueryParam("startDate") YearMonth month,
@QueryParam("budgetId") String budgetId,
@QueryParam("contactId") String contactId,
@QueryParam("groupId") String groupId,
@QueryParam("status") Status status,
@QueryParam("page") int page);
@GET
@Path("/transactions")
@Produces({ "application/json" })
public Response<TransactionsResponse> getTransactions(
@QueryParam("accountId") String accountId,
@QueryParam("accountName") String accountName,
@QueryParam("tagId") String tagId,
@QueryParam("tagName") String tagName,
@QueryParam("startDate") LocalDate startDate,
@QueryParam("endDate") LocalDate endDate,
@QueryParam("budgetId") String budgetId,
@QueryParam("budgetName") String budgetName,
@QueryParam("contactId") String contactId,
@QueryParam("contactName") String contactName,
@QueryParam("groupId") String groupId,
@QueryParam("groupName") String groupName,
@QueryParam("status") Status status,
@QueryParam("page") int page);
@GET
@Path("/transactions")
@Produces({ "application/json" })
public Response<TransactionsResponse> getTransactions(
@QueryParam("accountId") String accountId,
@QueryParam("accountName") String accountName,
@QueryParam("tagId") String tagId,
@QueryParam("tagName") String tagName,
@QueryParam("month") YearMonth month,
@QueryParam("budgetId") String budgetId,
@QueryParam("budgetName") String budgetName,
@QueryParam("contactId") String contactId,
@QueryParam("contactName") String contactName,
@QueryParam("groupId") String groupId,
@QueryParam("groupName") String groupName,
@QueryParam("status") Status status,
@QueryParam("page") int page);
@GET
@Path("/transactions")
@Produces({ "application/json" })
public String getJson(
@QueryParam("accountName") String accountName,
@QueryParam("page") int page);
@GET
@Path("/accounts")
@Produces({ "application/json" })
public Response<AccountsResponse> getAccounts();
@GET
@Path("/loans")
@Produces({ "application/json" })
public Response<LoansResponse> getLoans();
@GET
@Path("/tags")
@Produces({ "application/json" })
public Response<TagsResponse> getTags();
@GET
@Path("/budgets")
@Produces({ "application/json" })
public Response<BudgetsResponse> getBudgets();
@GET
@Path("/reminders")
@Produces({ "application/json" })
public Response<RemindersResponse> getReminders();
@GET
@Path("/groups")
@Produces({ "application/json" })
public Response<GroupsResponse> getGroups();
@GET
@Path("/contacts")
@Produces({ "application/json" })
public Response<ContactsResponse> getContacts();
}

View File

@ -0,0 +1,21 @@
package com.inteligr8.buxfer.api;
import javax.ws.rs.FormParam;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import com.inteligr8.buxfer.model.Response;
import com.inteligr8.buxfer.model.TokenResponse;
@Path("/api")
public interface SecurityApi {
@POST
@Path("/login")
@Produces({ "application/json" })
public Response<TokenResponse> login(
@FormParam("email") String email,
@FormParam("password") String password);
}

View File

@ -0,0 +1,107 @@
package com.inteligr8.buxfer.model;
import java.time.LocalDateTime;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
/**
* {
* "id": long,
* "name": string,
* "bank": string,
* "balance": double,
* "currency": string, // e.g. USD
* "lastSynced": date/time, // e.g. 2021-12-20 23:59:04
* "availableCredit": double,
* "apr": double, // e.g. 12.99
* "totalCreditLine": double
* }
*
* @author brian@inteligr8.com
*/
@JsonIgnoreProperties(ignoreUnknown = true)
public class Account extends NamedItem {
@JsonProperty
private String bank;
@JsonProperty
private Double balance;
@JsonProperty
private String currency;
@JsonProperty("lastSynced")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime lastSyncd;
@JsonProperty
private Double apr;
@JsonProperty
private Double availableCredit;
@JsonProperty("totalCreditLine")
private Double totalCredit;
public String getBank() {
return this.bank;
}
public void setBank(String bank) {
this.bank = bank;
}
public Double getBalance() {
return this.balance;
}
public void setBalance(Double balance) {
this.balance = balance;
}
public String getCurrency() {
return this.currency;
}
public void setCurrency(String currency) {
this.currency = currency;
}
public LocalDateTime getLastSyncd() {
return this.lastSyncd;
}
public void setLastSyncd(LocalDateTime lastSyncd) {
this.lastSyncd = lastSyncd;
}
public Double getApr() {
return this.apr;
}
public void setApr(Double apr) {
this.apr = apr;
}
public Double getAvailableCredit() {
return this.availableCredit;
}
public void setAvailableCredit(Double availableCredit) {
this.availableCredit = availableCredit;
}
public Double getTotalCredit() {
return this.totalCredit;
}
public void setTotalCredit(Double totalCredit) {
this.totalCredit = totalCredit;
}
}

View File

@ -0,0 +1,24 @@
package com.inteligr8.buxfer.model;
import java.util.List;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
@JsonIgnoreProperties(ignoreUnknown = true)
public class AccountsResponse extends ArrayResponse<Account> {
@JsonProperty("accounts")
private List<Account> items;
public List<Account> getItems() {
return this.items;
}
public void setItems(List<Account> items) {
this.items = items;
}
}

View File

@ -0,0 +1,14 @@
package com.inteligr8.buxfer.model;
import java.util.List;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
@JsonIgnoreProperties(ignoreUnknown = true)
public abstract class ArrayResponse<T> extends BaseResponse {
public abstract List<T> getItems();
public abstract void setItems(List<T> items);
}

View File

@ -0,0 +1,36 @@
package com.inteligr8.buxfer.model;
import com.fasterxml.jackson.annotation.JsonProperty;
public class BaseResponse {
public enum Status {
OK,
ERROR
}
@JsonProperty
private Status status;
@JsonProperty(value = "error_description", required = false)
private String error;
public Status getStatus() {
return this.status;
}
public void setStatus(Status status) {
this.status = status;
}
public String getError() {
return this.error;
}
public void setError(String error) {
this.error = error;
}
}

View File

@ -0,0 +1,204 @@
package com.inteligr8.buxfer.model;
import java.time.LocalDate;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
/**
* {
* "id": long
* "name": string,
* "editMode": string,
* "periodSize": int,
* "periodUnit": string, // e.g. week
* "startDate": date, // e.g. 2020-08-23
* "stopDate": date,
* "budgetId": long,
* "type": int,
* "tagId": long,
* "tag": { see Tag doc },
* "limit": double,
* "spent": double,
* "balance": double,
* "period": string, // e.g. "19 - 25 Dec",
* "isRolledOver": int,
* "eventId": long,
* }
*
* @author brian@inteligr8.com
*/
@JsonIgnoreProperties(ignoreUnknown = true)
public class Budget extends NamedItem {
@JsonProperty
private String editMode;
@JsonProperty
private Double limit;
@JsonProperty
private Double spent;
@JsonProperty
private Double balance;
@JsonProperty
private Double remaining;
@JsonProperty
private String period;
@JsonProperty
private int periodSize;
@JsonProperty
private String periodUnit;
@JsonProperty
@JsonFormat(pattern = "yyyy-MM-dd")
private LocalDate startDate;
@JsonProperty
@JsonFormat(pattern = "yyyy-MM-dd")
private LocalDate endDate;
@JsonProperty
private Long budgetId;
@JsonProperty
private Long tagId;
@JsonProperty
private Tag tag;
@JsonProperty
private Long eventId;
@JsonProperty("isRolledOver")
private Integer rolledOver;
public String getEditMode() {
return this.editMode;
}
public void setEditMode(String editMode) {
this.editMode = editMode;
}
public Double getLimit() {
return this.limit;
}
public void setLimit(Double limit) {
this.limit = limit;
}
public Double getSpent() {
return this.spent;
}
public void setSpent(Double spent) {
this.spent = spent;
}
public Double getBalance() {
return this.balance;
}
public void setBalance(Double balance) {
this.balance = balance;
}
public Double getRemaining() {
return this.remaining;
}
public void setRemaining(Double remaining) {
this.remaining = remaining;
}
public String getPeriod() {
return this.period;
}
public void setPeriod(String period) {
this.period = period;
}
public int getPeriodSize() {
return this.periodSize;
}
public void setPeriodSize(int periodSize) {
this.periodSize = periodSize;
}
public String getPeriodUnit() {
return this.periodUnit;
}
public void setPeriodUnit(String periodUnit) {
this.periodUnit = periodUnit;
}
public LocalDate getStartDate() {
return this.startDate;
}
public void setStartDate(LocalDate startDate) {
this.startDate = startDate;
}
public LocalDate getEndDate() {
return this.endDate;
}
public void setEndDate(LocalDate endDate) {
this.endDate = endDate;
}
public Long getBudgetId() {
return this.budgetId;
}
public void setBudgetId(Long budgetId) {
this.budgetId = budgetId;
}
public Long getTagId() {
return this.tagId;
}
public void setTagId(Long tagId) {
this.tagId = tagId;
}
public Tag getTag() {
return this.tag;
}
public void setTag(Tag tag) {
this.tag = tag;
}
public Long getEventId() {
return this.eventId;
}
public void setEventId(Long eventId) {
this.eventId = eventId;
}
public boolean isRolledOver() {
return this.rolledOver != null && this.rolledOver != 0;
}
public void setRolledOver(boolean rolledOver) {
this.rolledOver = rolledOver ? 1 : 0;
}
}

View File

@ -0,0 +1,24 @@
package com.inteligr8.buxfer.model;
import java.util.List;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
@JsonIgnoreProperties(ignoreUnknown = true)
public class BudgetsResponse extends ArrayResponse<Budget> {
@JsonProperty("budgets")
private List<Budget> items;
public List<Budget> getItems() {
return this.items;
}
public void setItems(List<Budget> items) {
this.items = items;
}
}

View File

@ -0,0 +1,24 @@
package com.inteligr8.buxfer.model;
import java.util.List;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
@JsonIgnoreProperties(ignoreUnknown = true)
public class ContactsResponse extends ArrayResponse<Person> {
@JsonProperty("contacts")
private List<Person> items;
public List<Person> getItems() {
return this.items;
}
public void setItems(List<Person> items) {
this.items = items;
}
}

View File

@ -0,0 +1,35 @@
package com.inteligr8.buxfer.model;
import java.util.Map;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
@JsonIgnoreProperties(ignoreUnknown = true)
public class Group extends NamedItem {
@JsonProperty
private boolean consolidated;
@JsonProperty
private Map<String, Person> members;
public boolean isConsolidated() {
return this.consolidated;
}
public void setConsolidated(boolean consolidated) {
this.consolidated = consolidated;
}
public Map<String, Person> getMembers() {
return this.members;
}
public void setMembers(Map<String, Person> members) {
this.members = members;
}
}

View File

@ -0,0 +1,24 @@
package com.inteligr8.buxfer.model;
import java.util.List;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
@JsonIgnoreProperties(ignoreUnknown = true)
public class GroupsResponse extends ArrayResponse<Group> {
@JsonProperty("reminders")
private List<Group> items;
public List<Group> getItems() {
return this.items;
}
public void setItems(List<Group> items) {
this.items = items;
}
}

View File

@ -0,0 +1,22 @@
package com.inteligr8.buxfer.model;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
@JsonIgnoreProperties(ignoreUnknown = true)
public class Item {
@JsonProperty
private long id;
public long getId() {
return this.id;
}
public void setId(long id) {
this.id = id;
}
}

View File

@ -0,0 +1,55 @@
package com.inteligr8.buxfer.model;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
@JsonIgnoreProperties(ignoreUnknown = true)
public class Loan extends NamedItem {
@JsonProperty
private String entity;
@JsonProperty
private String type;
@JsonProperty
private Double balance;
@JsonProperty
private String description;
public String getEntity() {
return this.entity;
}
public void setEntity(String entity) {
this.entity = entity;
}
public String getType() {
return this.type;
}
public void setType(String type) {
this.type = type;
}
public Double getBalance() {
return this.balance;
}
public void setBalance(Double balance) {
this.balance = balance;
}
public String getDescription() {
return this.description;
}
public void setDescription(String description) {
this.description = description;
}
}

View File

@ -0,0 +1,24 @@
package com.inteligr8.buxfer.model;
import java.util.List;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
@JsonIgnoreProperties(ignoreUnknown = true)
public class LoansResponse extends ArrayResponse<Loan> {
@JsonProperty("loans")
private List<Loan> items;
public List<Loan> getItems() {
return this.items;
}
public void setItems(List<Loan> items) {
this.items = items;
}
}

View File

@ -0,0 +1,22 @@
package com.inteligr8.buxfer.model;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
@JsonIgnoreProperties(ignoreUnknown = true)
public class NamedItem extends Item {
@JsonProperty
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}

View File

@ -0,0 +1,33 @@
package com.inteligr8.buxfer.model;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
@JsonIgnoreProperties(ignoreUnknown = true)
public class Person extends NamedItem {
@JsonProperty
private String email;
@JsonProperty
private Double balance;
public String getEmail() {
return this.email;
}
public void setEmail(String email) {
this.email = email;
}
public Double getBalance() {
return this.balance;
}
public void setBalance(Double balance) {
this.balance = balance;
}
}

View File

@ -0,0 +1,217 @@
package com.inteligr8.buxfer.model;
import java.time.LocalDate;
import java.util.List;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
/**
* {
* "id": long,
* "name": string,
* "nextExecution": date,
* "dueDateDescription": string,
* "numDaysForDueDate": int,
* "tags": [ see Tag doc ]
* "editMode": string, // e.g. schedule_all
* "periodSize": int,
* "periodUnit": string, // e.g. month
* "startDate": date,
* "stopDate": date,
* "description": string,
* "type": string, // e.g. transfer
* "transactionType": int,
* "amount": double,
* "fromAccountId": long,
* "toAccountId": long
* }
*
* @author brian@inteligr8.com
*/
@JsonIgnoreProperties(ignoreUnknown = true)
public class Reminder extends NamedItem {
@JsonProperty
@JsonFormat(pattern = "yyyy-MM-dd")
private LocalDate nextExecution;
@JsonProperty
private String dueDateDescription;
@JsonProperty
private Integer numDaysForDueDate;
@JsonProperty
private List<Tag> tags;
@JsonProperty
private String editMode;
@JsonProperty
private Integer periodSize;
@JsonProperty
private String periodUnit;
@JsonProperty
@JsonFormat(pattern = "yyyy-MM-dd")
private LocalDate startDate;
@JsonProperty
@JsonFormat(pattern = "yyyy-MM-dd")
private LocalDate endDate;
@JsonProperty
private String description;
@JsonProperty
private String type;
@JsonProperty
private Integer transactionType;
@JsonProperty
private Double amount;
@JsonProperty
private Long accountId;
@JsonProperty
private Long fromAccountId;
@JsonProperty
private Long toAccountId;
public LocalDate getNextExecution() {
return this.nextExecution;
}
public void setNextExecution(LocalDate nextExecution) {
this.nextExecution = nextExecution;
}
public String getDueDateDescription() {
return this.dueDateDescription;
}
public void setDueDateDescription(String dueDateDescription) {
this.dueDateDescription = dueDateDescription;
}
public Integer getNumDaysForDueDate() {
return this.numDaysForDueDate;
}
public void setNumDaysForDueDate(Integer numDaysForDueDate) {
this.numDaysForDueDate = numDaysForDueDate;
}
public List<Tag> getTags() {
return this.tags;
}
public void setTags(List<Tag> tags) {
this.tags = tags;
}
public String getEditMode() {
return this.editMode;
}
public void setEditMode(String editMode) {
this.editMode = editMode;
}
public Integer getPeriodSize() {
return this.periodSize;
}
public void setPeriodSize(Integer periodSize) {
this.periodSize = periodSize;
}
public String getPeriodUnit() {
return this.periodUnit;
}
public void setPeriodUnit(String periodUnit) {
this.periodUnit = periodUnit;
}
public LocalDate getStartDate() {
return this.startDate;
}
public void setStartDate(LocalDate startDate) {
this.startDate = startDate;
}
public LocalDate getEndDate() {
return this.endDate;
}
public void setEndDate(LocalDate endDate) {
this.endDate = endDate;
}
public String getDescription() {
return this.description;
}
public void setDescription(String description) {
this.description = description;
}
public String getType() {
return this.type;
}
public void setType(String type) {
this.type = type;
}
public Integer getTransactionType() {
return this.transactionType;
}
public void setTransactionType(Integer transactionType) {
this.transactionType = transactionType;
}
public Double getAmount() {
return this.amount;
}
public void setAmount(Double amount) {
this.amount = amount;
}
public Long getAccountId() {
return this.accountId;
}
public void setAccountId(Long accountId) {
this.accountId = accountId;
}
public Long getFromAccountId() {
return this.fromAccountId;
}
public void setFromAccountId(Long fromAccountId) {
this.fromAccountId = fromAccountId;
}
public Long getToAccountId() {
return this.toAccountId;
}
public void setToAccountId(Long toAccountId) {
this.toAccountId = toAccountId;
}
}

View File

@ -0,0 +1,24 @@
package com.inteligr8.buxfer.model;
import java.util.List;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
@JsonIgnoreProperties(ignoreUnknown = true)
public class RemindersResponse extends ArrayResponse<Reminder> {
@JsonProperty("reminders")
private List<Reminder> items;
public List<Reminder> getItems() {
return this.items;
}
public void setItems(List<Reminder> items) {
this.items = items;
}
}

View File

@ -0,0 +1,20 @@
package com.inteligr8.buxfer.model;
import com.fasterxml.jackson.annotation.JsonProperty;
public class Response<T> {
@JsonProperty
private T response;
public T getResponse() {
return this.response;
}
public void setResponse(T response) {
this.response = response;
}
}

View File

@ -0,0 +1,47 @@
package com.inteligr8.buxfer.model;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
/**
* {
* "id": long,
* "name": string, // full tag path; "\/" delimited
* "relativeName": string, // leave in tag path
* "parentId": long
* }
*
* @author brian@inteligr8.com
*/
@JsonIgnoreProperties(ignoreUnknown = true)
public class Tag extends NamedItem {
@JsonProperty
private String relativeName;
@JsonProperty
private Long parentId;
public String getPath() {
return this.getName().replace(" \\/ ", " / ");
}
public String getRelativeName() {
return this.relativeName;
}
public void setRelativeName(String relativeName) {
this.relativeName = relativeName;
}
public Long getParentId() {
return this.parentId;
}
public void setParentId(Long parentId) {
this.parentId = parentId;
}
}

View File

@ -0,0 +1,24 @@
package com.inteligr8.buxfer.model;
import java.util.List;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
@JsonIgnoreProperties(ignoreUnknown = true)
public class TagsResponse extends ArrayResponse<Tag> {
@JsonProperty("tags")
private List<Tag> items;
public List<Tag> getItems() {
return this.items;
}
public void setItems(List<Tag> items) {
this.items = items;
}
}

View File

@ -0,0 +1,22 @@
package com.inteligr8.buxfer.model;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
@JsonIgnoreProperties(ignoreUnknown = true)
public class TokenResponse extends BaseResponse {
@JsonProperty
private String token;
public String getToken() {
return this.token;
}
public void setToken(String token) {
this.token = token;
}
}

View File

@ -0,0 +1,219 @@
package com.inteligr8.buxfer.model;
import java.time.LocalDate;
import java.util.List;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
/**
* {
* "id": long,
* "description": string,
* "date": date,
* "type": string, // e.g. expense (depreciated?)
* "transactionType": string // e.g. expense, investment purchase
* "amount": double,
* "expenseAmount": double, // signed (negative for income/refund)
* "accountId": long,
* "accountName": string,
* "fromAccouint": {
* "id": long,
* "name": string
* },
* "toAccouint": {
* "id": long,
* "name": string
* },
* "tags": string, // e.g. Tag1, Tag2 (depreciated?)
* "tagNames": [ string, ... ],
* "status": string // e.g. cleared
* "isFutureDated": boolean,
* "isPending": boolean
* }
*
* @author brian@inteligr8.com
*/
@JsonIgnoreProperties(ignoreUnknown = true)
public class Transaction extends Item {
public enum Status {
@JsonProperty("pending")
Pending,
@JsonProperty("reconciled")
Reconciled,
@JsonProperty("cleared")
Cleared
}
public enum Type {
@JsonProperty("income")
Income,
@JsonProperty("expense")
Expense,
@JsonProperty("refund")
Refund,
@JsonProperty("transfer")
Transfer,
@JsonProperty("investment purchase")
Buy,
@JsonProperty("investment sale")
Sell,
@JsonProperty("dividend")
Dividend,
@JsonProperty("sharedbill")
SharedBill,
@JsonProperty("paidforfriend")
PaidForFriend,
@JsonProperty("loan")
Loan
}
@JsonProperty
private String description;
@JsonProperty
@JsonFormat(pattern = "yyyy-MM-dd")
private LocalDate date;
@JsonProperty
private Type transactionType;
@JsonProperty
private Double amount;
@JsonProperty
private Double expenseAmount;
@JsonProperty
private Long accountId;
@JsonProperty
private String accountName;
@JsonProperty
private NamedItem fromAccount;
@JsonProperty
private NamedItem toAccount;
@JsonProperty
private List<String> tagNames;
@JsonProperty
private Status status;
@JsonProperty
private Boolean isFutureDated;
@JsonProperty
private Boolean isPending;
public String getDescription() {
return this.description;
}
public void setDescription(String description) {
this.description = description;
}
public LocalDate getDate() {
return this.date;
}
public void setDate(LocalDate date) {
this.date = date;
}
public Type getType() {
return this.transactionType;
}
public void setType(Type type) {
this.transactionType = type;
}
public Double getAmount() {
return this.amount;
}
public void setAmount(Double amount) {
this.amount = amount;
}
public Double getExpenseAmount() {
return this.expenseAmount;
}
public void setExpenseAmount(Double expenseAmount) {
this.expenseAmount = expenseAmount;
}
public Long getAccountId() {
return this.accountId;
}
public void setAccountId(Long accountId) {
this.accountId = accountId;
}
public String getAccountName() {
return this.accountName;
}
public void setAccountName(String accountName) {
this.accountName = accountName;
}
public NamedItem getFromAccount() {
return this.fromAccount;
}
public void setFromAccount(NamedItem fromAccount) {
this.fromAccount = fromAccount;
}
public NamedItem getToAccount() {
return this.toAccount;
}
public void setToAccount(NamedItem toAccount) {
this.toAccount = toAccount;
}
public List<String> getTagNames() {
return this.tagNames;
}
public void setTagNames(List<String> tagNames) {
this.tagNames = tagNames;
}
public Status getStatus() {
return this.status;
}
public void setStatus(Status status) {
this.status = status;
}
public Boolean getIsFutureDated() {
return this.isFutureDated;
}
public void setIsFutureDated(Boolean isFutureDated) {
this.isFutureDated = isFutureDated;
}
public Boolean getIsPending() {
return this.isPending;
}
public void setIsPending(Boolean isPending) {
this.isPending = isPending;
}
}

View File

@ -0,0 +1,35 @@
package com.inteligr8.buxfer.model;
import java.util.List;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
@JsonIgnoreProperties(ignoreUnknown = true)
public class TransactionsResponse extends ArrayResponse<Transaction> {
@JsonProperty("transactions")
private List<Transaction> items;
@JsonProperty("numTransactions")
private long totalItems;
public long getTotalItems() {
return this.totalItems;
}
public void setTotalItems(long totalItems) {
this.totalItems = totalItems;
}
public List<Transaction> getItems() {
return this.items;
}
public void setItems(List<Transaction> items) {
this.items = items;
}
}

3
buxfer-public-rest-client/.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
# Personal
buxfer-personal.properties

View File

@ -0,0 +1,205 @@
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.inteligr8.buxfer</groupId>
<artifactId>buxfer-public-rest-client</artifactId>
<version>1.0-SNAPSHOT</version>
<name>Buxfer ReST Client for Java</name>
<properties>
<project.build.sourceEncoding>utf-8</project.build.sourceEncoding>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<jaxrs.impl>jersey</jaxrs.impl>
<junit.version>5.7.2</junit.version>
<spring.version>5.2.14.RELEASE</spring.version>
<api.model.disabled>false</api.model.disabled>
</properties>
<dependencies>
<dependency>
<groupId>com.inteligr8</groupId>
<artifactId>common-rest-api</artifactId>
<version>1.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.inteligr8.buxfer</groupId>
<artifactId>buxfer-public-rest-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
<version>2.12.2</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.9</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>3.2.0</version>
<executions>
<execution>
<id>add-jaxrs-src</id>
<goals><goal>add-source</goal></goals>
<configuration>
<sources>
<source>src/main/${jaxrs.impl}</source>
</sources>
</configuration>
</execution>
<execution>
<id>add-test-src</id>
<goals><goal>add-test-source</goal></goals>
<configuration>
<sources>
<source>src/test/${jaxrs.impl}</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<classifier>${jaxrs.impl}</classifier>
</configuration>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M5</version>
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>${junit.version}</version>
</dependency>
</dependencies>
</plugin>
<plugin>
<artifactId>maven-failsafe-plugin</artifactId>
<version>3.0.0-M5</version>
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>${junit.version}</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>jersey-impl</id>
<activation>
<activeByDefault>true</activeByDefault>
<property>
<name>jaxrs.impl</name>
<value>jersey</value>
</property>
</activation>
<properties>
<jaxrs.impl>jersey</jaxrs.impl>
<jersey.version>2.34</jersey.version>
</properties>
<dependencies>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-client</artifactId>
<version>${jersey.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.ext</groupId>
<artifactId>jersey-proxy-client</artifactId>
<version>${jersey.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.inject</groupId>
<artifactId>jersey-hk2</artifactId>
<version>${jersey.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>${jersey.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
</profile>
<profile>
<id>cxf-impl</id>
<activation>
<property>
<name>jaxrs.impl</name>
<value>cxf</value>
</property>
</activation>
<properties>
<jaxrs.impl>cxf</jaxrs.impl>
<cxf.version>3.3.2</cxf.version>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-rs-client</artifactId>
<version>${cxf.version}</version>
<scope>provided</scope>
</dependency>
</dependencies>
</profile>
</profiles>
<repositories>
<repository>
<id>inteligr8-public</id>
<url>https://repos.inteligr8.com/nexus/repository/inteligr8-public</url>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>inteligr8-public</id>
<url>https://repos.inteligr8.com/nexus/repository/inteligr8-public</url>
</pluginRepository>
</pluginRepositories>
<distributionManagement>
<repository>
<id>inteligr8-releases</id>
<url>https://repos.inteligr8.com/nexus/repository/inteligr8-public</url>
</repository>
<snapshotRepository>
<id>inteligr8-snapshots</id>
<url>https://repos.inteligr8.com/nexus/repository/inteligr8-snapshots</url>
</snapshotRepository>
</distributionManagement>
</project>

View File

@ -0,0 +1,44 @@
package com.inteligr8.buxfer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;
import com.inteligr8.rs.ClientCxfConfiguration;
import com.inteligr8.rs.ClientCxfImpl;
/**
* This class provides a POJO &amp; Spring-based implementation of the Apache
* CXF client. You can use it outside of the Spring context, but you will need
* the spring-context and spring-beans libraries in your non-Spring
* application.
*
* @author brian@inteligr8.com
*/
@Component("buxfer.client")
@Lazy
public class BuxferClientCxfImpl extends ClientCxfImpl {
@Autowired
private BuxferClientConfiguration config;
/**
* This constructor is for Spring use.
*/
protected BuxferClientCxfImpl() {
}
/**
* This constructor is for POJO use.
* @param config
*/
public BuxferClientCxfImpl(BuxferClientConfiguration config) {
this.config = config;
}
@Override
protected ClientCxfConfiguration getConfig() {
return this.config;
}
}

View File

@ -0,0 +1,65 @@
package com.inteligr8.buxfer;
import java.io.IOException;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.client.ClientRequestContext;
import javax.ws.rs.client.Entity;
import javax.ws.rs.core.Form;
import javax.ws.rs.core.GenericType;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response.Status;
import javax.ws.rs.core.UriBuilder;
import com.inteligr8.buxfer.model.Response;
import com.inteligr8.buxfer.model.TokenResponse;
import com.inteligr8.rs.AuthorizationFilter;
public class BuxferAuthorizationFilter implements AuthorizationFilter {
private String email;
private String password;
private String token;
public BuxferAuthorizationFilter(String email, String password) {
this.email = email;
this.password = password;
}
@Override
public void filter(ClientRequestContext requestContext) throws IOException {
if (requestContext.getUri().getPath().endsWith("/login"))
return;
if (this.token == null)
this.requestToken(requestContext);
requestContext.setUri(
UriBuilder.fromUri(requestContext.getUri())
.queryParam("token", this.token)
.build());
}
protected void requestToken(ClientRequestContext requestContext) {
UriBuilder loginUri = UriBuilder.fromUri(requestContext.getUri())
.replacePath("/api/login");
Form form = new Form();
form.param("email", this.email);
form.param("password", this.password);
GenericType<Response<TokenResponse>> responseType = new GenericType<Response<TokenResponse>>() {};
TokenResponse response = requestContext.getClient()
.target(loginUri)
.request()
.accept(MediaType.APPLICATION_JSON)
.post(Entity.form(form), responseType)
.getResponse();
if (!com.inteligr8.buxfer.model.BaseResponse.Status.OK.equals(response.getStatus()))
throw new WebApplicationException(response.getError(), Status.UNAUTHORIZED.getStatusCode());
this.token = response.getToken();
}
}

View File

@ -0,0 +1,89 @@
package com.inteligr8.buxfer;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import com.inteligr8.rs.AuthorizationFilter;
import com.inteligr8.rs.ClientCxfConfiguration;
import com.inteligr8.rs.ClientJerseyConfiguration;
/**
* This class provides a POJO &amp; Spring-based implementation of the
* ClientConfiguration interface. You can use it outside of the Spring
* context, but you will need the spring-context and spring-beans libraries in
* your non-Spring application.
*
* @author brian@inteligr8.com
*/
@Configuration
@ComponentScan
public class BuxferClientConfiguration implements ClientCxfConfiguration, ClientJerseyConfiguration {
@Value("${buxfer.service.baseUrl:http://localhost:8080/alfresco}")
private String baseUrl;
@Value("${buxfer.service.security.auth.email}")
private String authEmail;
@Value("${buxfer.service.security.auth.password}")
private String authPassword;
@Value("${buxfer.service.cxf.defaultBusEnabled:true}")
private boolean defaultBusEnabled;
@Value("${buxfer.service.jersey.putBodyRequired:true}")
private boolean putBodyRequired;
public String getBaseUrl() {
return this.baseUrl;
}
public void setBaseUrl(String baseUrl) {
this.baseUrl = baseUrl;
}
public String getAuthEmail() {
return this.authEmail;
}
public void setAuthEmail(String authEmail) {
this.authEmail = authEmail;
}
public String getAuthPassword() {
return this.authPassword;
}
public void setAuthPassword(String authPassword) {
this.authPassword = authPassword;
}
public boolean isUnwrapRootValueEnabled() {
return true;
}
public boolean isDefaultBusEnabled() {
return this.defaultBusEnabled;
}
public void setDefaultBusEnabled(boolean defaultBusEnabled) {
this.defaultBusEnabled = defaultBusEnabled;
}
public boolean isPutBodyRequired() {
return this.putBodyRequired;
}
public void setPutBodyRequired(boolean putBodyRequired) {
this.putBodyRequired = putBodyRequired;
}
@Override
public AuthorizationFilter createAuthorizationFilter() {
return new BuxferAuthorizationFilter(this.getAuthEmail(), this.getAuthPassword());
}
}

View File

@ -0,0 +1,28 @@
package com.inteligr8.buxfer;
import com.inteligr8.buxfer.api.CommandApi;
import com.inteligr8.rs.Client;
/**
* This class serves as the entrypoint to the JAX-RS API for the Buxfer Public
* ReST API.
*
* @author brian@inteligr8.com
*/
public class BuxferPublicRestApiImpl implements BuxferPublicRestApi {
private final Client client;
public BuxferPublicRestApiImpl(Client client) {
this.client = client;
}
protected final <T> T getApi(Class<T> apiClass) {
return this.client.getApi(apiClass);
}
public CommandApi getCommandApi() {
return this.client.getApi(CommandApi.class);
}
}

View File

@ -0,0 +1,52 @@
package com.inteligr8.buxfer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;
import com.inteligr8.rs.ClientJerseyConfiguration;
import com.inteligr8.rs.ClientJerseyImpl;
/**
* This class provides a POJO &amp; Spring-based implementation of the Apache
* CXF client. You can use it outside of the Spring context, but you will need
* the spring-context and spring-beans libraries in your non-Spring
* application.
*
* @author brian@inteligr8.com
*/
@Component("buxfer.client")
@Lazy
public class BuxferClientJerseyImpl extends ClientJerseyImpl {
@Autowired
private BuxferClientConfiguration config;
private final BuxferPublicRestApi api;
/**
* This constructor is for Spring use.
*/
protected BuxferClientJerseyImpl() {
this.api = new BuxferPublicRestApiImpl(this);
}
/**
* This constructor is for POJO use.
* @param config
*/
public BuxferClientJerseyImpl(BuxferClientConfiguration config) {
this.config = config;
this.api = new BuxferPublicRestApiImpl(this);
}
@Override
protected ClientJerseyConfiguration getConfig() {
return this.config;
}
public BuxferPublicRestApi getApi() {
return this.api;
}
}

View File

@ -0,0 +1,26 @@
package com.inteligr8.buxfer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
import com.inteligr8.rs.ClientConfiguration;
@TestPropertySource(locations = {"/buxfer-personal.properties"})
@SpringJUnitConfig(classes = {BuxferClientConfiguration.class, BuxferClientCxfImpl.class})
public class ConnectionCxfClientIT extends ConnectionClientIT {
@Autowired
private BuxferClientCxfImpl client;
@Override
public BuxferPublicRestApi getClient() {
return this.client.getApi(BuxferPublicRestApi.class);
}
@Override
public ClientConfiguration getConfiguration() {
return this.client.getConfig();
}
}

View File

@ -0,0 +1,35 @@
package com.inteligr8.buxfer;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.client.methods.RequestBuilder;
import org.apache.http.impl.client.DefaultRedirectStrategy;
import org.apache.http.impl.client.HttpClientBuilder;
import com.inteligr8.rs.ClientConfiguration;
public abstract class ConditionalIT {
public abstract ClientConfiguration getConfiguration();
public boolean hostExists() {
String uri = this.getConfiguration().getBaseUrl();
HttpUriRequest request = RequestBuilder.get()
.setUri(uri)
.build();
HttpClient client = HttpClientBuilder.create()
.setRedirectStrategy(DefaultRedirectStrategy.INSTANCE)
.build();
try {
HttpResponse response = client.execute(request);
return response.getStatusLine().getStatusCode() < 300;
} catch (Exception e) {
return false;
}
}
}

View File

@ -0,0 +1,176 @@
package com.inteligr8.buxfer;
import java.time.LocalDate;
import java.util.Collection;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.EnabledIf;
import com.inteligr8.buxfer.api.CommandApi;
import com.inteligr8.buxfer.model.Account;
import com.inteligr8.buxfer.model.ArrayResponse;
import com.inteligr8.buxfer.model.BaseResponse;
import com.inteligr8.buxfer.model.BaseResponse.Status;
import com.inteligr8.buxfer.model.Budget;
import com.inteligr8.buxfer.model.Item;
import com.inteligr8.buxfer.model.NamedItem;
import com.inteligr8.buxfer.model.Reminder;
import com.inteligr8.buxfer.model.Tag;
import com.inteligr8.buxfer.model.Transaction;
import com.inteligr8.buxfer.model.TransactionsResponse;
public abstract class ConnectionClientIT extends ConditionalIT {
public abstract BuxferPublicRestApi getClient();
private CommandApi api;
public boolean fullTest() {
return false;
//return this.hostExists();
}
@BeforeEach
public void getApi() {
this.api = this.getClient().getCommandApi();
}
@Test
@EnabledIf("hostExists")
public void testTransactions() {
TransactionsResponse response = this.api.getTransactions(
LocalDate.of(2021, 12, 1),
LocalDate.of(2021, 12, 31),
null,
1
).getResponse();
this.assertArrayNotEmpty(response);
Assertions.assertTrue(response.getTotalItems() > 0L);
this.assertItems(response.getItems());
}
@Test
@EnabledIf("hostExists")
public void testAccounts() {
ArrayResponse<? extends Item> response = this.api.getAccounts().getResponse();
this.assertArrayNotEmpty(response);
this.assertItems(response.getItems());
}
@Test
@EnabledIf("hostExists")
public void testTags() {
ArrayResponse<? extends Item> response = this.api.getTags().getResponse();
this.assertArrayNotEmpty(response);
this.assertItems(response.getItems());
}
@Test
@EnabledIf("hostExists")
public void testBudgets() {
ArrayResponse<? extends Item> response = this.api.getBudgets().getResponse();
this.assertArrayNotEmpty(response);
this.assertItems(response.getItems());
}
@Test
@EnabledIf("hostExists")
public void testReminders() {
ArrayResponse<? extends Item> response = this.api.getReminders().getResponse();
this.assertArrayNotEmpty(response);
this.assertItems(response.getItems());
}
@Test
@EnabledIf("fullTest")
public void testGroups() {
ArrayResponse<? extends Item> response = this.api.getGroups().getResponse();
this.assertArrayEmpty(response);
}
@Test
@EnabledIf("fullTest")
public void testContacts() {
ArrayResponse<? extends Item> response = this.api.getContacts().getResponse();
this.assertArrayEmpty(response);
}
private void assertOk(BaseResponse response) {
Assertions.assertNotNull(response);
Assertions.assertEquals(Status.OK, response.getStatus());
Assertions.assertNull(response.getError());
}
private void assertArrayEmpty(ArrayResponse<?> response) {
this.assertOk(response);
Assertions.assertNotNull(response.getItems());
Assertions.assertTrue(response.getItems().isEmpty());
}
private void assertArrayNotEmpty(ArrayResponse<?> response) {
this.assertOk(response);
Assertions.assertNotNull(response.getItems());
Assertions.assertFalse(response.getItems().isEmpty());
}
private void assertItem(Item item) {
Assertions.assertTrue(item.getId() > 0);
}
private void assertNamedItem(NamedItem item) {
this.assertItem(item);
Assertions.assertNotNull(item.getName());
Assertions.assertNotEquals(0, item.getName().length());
}
private void assertSpecificItem(Item item) {
if (item instanceof Transaction) {
this.assertTransaction((Transaction)item);
} else if (item instanceof Budget) {
this.assertBudget((Budget)item);
} else if (item instanceof Reminder) {
this.assertReminder((Reminder)item);
} else if (item instanceof Tag) {
this.assertTag((Tag)item);
} else if (item instanceof Account) {
this.assertAccount((Account)item);
}
}
private void assertTransaction(Transaction item) {
this.assertItem(item);
Assertions.assertNotNull(item.getType());
Assertions.assertNotNull(item.getAmount());
Assertions.assertNotNull(item.getDate());
}
private void assertAccount(Account item) {
this.assertNamedItem(item);
Assertions.assertNotNull(item.getBank());
Assertions.assertNotEquals(0, item.getBank().length());
Assertions.assertNotNull(item.getBalance());
}
private void assertTag(Tag item) {
this.assertNamedItem(item);
}
private void assertBudget(Budget item) {
this.assertNamedItem(item);
}
private void assertReminder(Reminder item) {
this.assertNamedItem(item);
Assertions.assertNotNull(item.getStartDate());
Assertions.assertTrue(item.getStartDate().isAfter(LocalDate.of(2010, 1, 1)));
}
private void assertItems(Collection<? extends Item> items) {
for (Item item : items) {
this.assertSpecificItem(item);
}
}
}

View File

@ -0,0 +1,26 @@
package com.inteligr8.buxfer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
import com.inteligr8.rs.ClientConfiguration;
@TestPropertySource(locations = {"/buxfer-personal.properties"})
@SpringJUnitConfig(classes = {BuxferClientConfiguration.class, BuxferClientJerseyImpl.class})
public class ConnectionJerseyClientIT extends ConnectionClientIT {
@Autowired
private BuxferClientJerseyImpl client;
@Override
public BuxferPublicRestApi getClient() {
return this.client.getApi();
}
@Override
public ClientConfiguration getConfiguration() {
return this.client.getConfig();
}
}