This commit is contained in:
2025-09-29 09:59:37 -04:00
parent b02c9546d9
commit 6cabfec4e9
31 changed files with 1023 additions and 74 deletions

View File

@@ -0,0 +1,60 @@
/**
* license: GPLv3
* lodge.reservationsystem
*/
package lodge;
import lodge.datamodel.Account;
import lodge.datamodel.Address;
import lodge.datamodel.EmailAddress;
import lodge.reservationsystem.AccomodationManager;
/**
* The Tests for the ReservationSystem Module
*
* <p>
* This class main function acts as a driver function to run the test functions.
* </p>
*
* @author Sherwin Price
* @version 1.0
* @since 2025
*/
public final class TestAccountLoad {
// Request that Manager updates specific accounts files with data stored in
static void Test_AddAccount(AccomodationManager mgr, Account acct) throws Exception {
mgr.AddAccount(acct);
// 4. Request that Manager updates specific accounts files with data stored in
// memory
mgr.UpdateAccount(acct);
}
public static void main(String[] args) throws Exception {
// Configure data repository
AccomodationManager mgr = new AccomodationManager(getRepositoryConfig.getPath());
// 3. Add new account object to the list managed by Manager (if account object
// already exists on add action with the same account number, it is considered
// an error)
Test_AddAccount(mgr, mgr.newAccount("701-456-7890",
new Address("10 wilco ave", "wilco", "WY", "82801"),
new EmailAddress("wilco@wyommin.net")));
Test_AddAccount(mgr, mgr.newAccount("701-456-7890",
new Address("10 wilco ave", "wilco", "WY", "82801"),
new EmailAddress("wilco@wyommin.net")));
mgr.showAccountList();
System.out.println("Program Completed.");
}
public final static class getRepositoryConfig {
public final static String getPath() {
String home = System.getenv("HOME") != null ? System.getenv("HOME")
: System.getenv("HOMEDRIVE") + System.getenv("HOMEPATH");
return home.replace('\\', '/') + "/workspace/reservationsystem/src/resources";
}
}
}

View File

@@ -0,0 +1,160 @@
/**
* license: GPLv3
* lodge.reservationsystem
*/
package lodge;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.temporal.ChronoUnit;
import lodge.datamodel.Account;
import lodge.datamodel.Address;
import lodge.datamodel.DuplicateObjectException;
import lodge.datamodel.EmailAddress;
import lodge.datamodel.IReservation;
import lodge.datamodel.Reservation;
import lodge.datamodel.ReservationStatusEnum;
import lodge.reservationsystem.AccomodationManager;
import lodge.reservationsystem.CabinReservation;
import lodge.reservationsystem.HotelReservation;
import lodge.reservationsystem.HouseReservation;
/**
* The Tests for the ReservationSystem Module
*
* <p>
* This class main function acts as a driver function to run the test functions.
* </p>
*
* @author Sherwin Price
* @version 1.0
* @since 2025
*/
public final class TestReservations {
// Request that Manager updates specific accounts files with data stored in
static void Test_AddAccount(AccomodationManager mgr, Account acct) throws Exception {
mgr.AddAccount(acct);
// 4. Request that Manager updates specific accounts files with data stored in
// memory
mgr.UpdateAccount(acct);
}
static void Test_AddReservation(AccomodationManager mgr, Account acct, Reservation rsrv, Address mlAddr,
ZonedDateTime zdtStrt)
throws Exception {
rsrv.setMailing_address(mlAddr);
rsrv.setNumberOfBeds(2);
rsrv.setNumberOfFloors(1);
rsrv.setNumberOfBedRooms(1);
rsrv.setSquareFeet(450);
rsrv.setReservation_start_date(zdtStrt);
rsrv.setReservation_end_date(zdtStrt.plus(4, ChronoUnit.DAYS));
mgr.addReservation(acct, rsrv);
mgr.UpdateAccount(acct);
}
public static void main(String[] args) throws Exception {
// Configure data repository
AccomodationManager mgr = new AccomodationManager(getRepositoryConfig.getPath());
// 1. Get the list of loaded accounts from Manager
mgr.loadAll();
// 2. Retrieve a loaded account object that matches a specific account number
mgr.retrieveAccount("A1450981765");
// 3. Add new account object to the list managed by Manager (if account object
// already exists on add action with the same account number, it is considered
// an error)
Test_AddAccount(mgr, mgr.newAccount("701-456-7890",
new Address("10 wilco ave", "wilco", "WY", "82801"),
new EmailAddress("wilco@wyommin.net")));
Test_AddAccount(mgr, mgr.newAccount("301-356-3890",
new Address("30 Amstadam ave", "New York", "NY", "12010"),
new EmailAddress("newbee952@aol.com")));
// 5. Add draft lodging reservation to an account (if reservation object already
// exists with the same reservation number, it is considered an error)
Account acct2 = mgr.retrieveLoadedAccounts().get(1);
Test_AddReservation(mgr, acct2,
new HotelReservation(
new Address("400 hotel ave", "Maryland City", "MD", "20723")),
new Address("400 hotel ave", "Maryland City", "MD", "20723"),
ZonedDateTime.of(2025, 9, 05, 10, 0, 0, 0, ZoneId.of("UTC")));
Account acct1 = mgr.retrieveLoadedAccounts().get(0);
Test_AddReservation(mgr, acct2,
new CabinReservation(new Address("30 cabin ave", "Carnelian", "CA", "96140")),
new Address("30 cabin ave", "Carnelian Bay", "CA", "96140"),
ZonedDateTime.of(2025, 9, 05, 10, 0, 0, 0, ZoneId.of("UTC")));
Test_AddReservation(mgr, acct1,
new CabinReservation(new Address("40 cabin ave", "Carnelian", "CA", "96140")),
new Address("40 cabin ave", "Carnelian Bay", "CA", "96140"),
ZonedDateTime.of(2025, 9, 05, 10, 0, 0, 0, ZoneId.of("UTC")));
Test_AddReservation(mgr, acct1,
new HouseReservation(new Address("3000 Osage ave", "GreenBelt", "MD", "20740")),
new Address("40012 College ave", "College Park", "MD", "20740"),
ZonedDateTime.of(2025, 9, 05, 10, 0, 0, 0, ZoneId.of("UTC")));
try {
IReservation irsrv = acct1.getAllReservations().next();
if (mgr.addReservation(acct1, acct1.findReservation(irsrv.getReservation_number()))) {
mgr.UpdateAccount(mgr.retrieveAccount(irsrv.getAccountNumber()));
}
} catch (DuplicateObjectException e) {
System.out.println(e.getMessage());
}
Account account = mgr.retrieveLoadedAccounts().get(0);
// 6. Complete reservation that is associated with an account
IReservation irsrv = account.getAllReservations().next();
Reservation rsrv = account.findReservation(irsrv.getReservation_number());
rsrv.Change(rsrv, ReservationStatusEnum.Completed);
mgr.UpdateAccount(mgr.retrieveAccount(account.getAccount_number()));
// 7. Cancel reservation that is associated with an account
account = mgr.retrieveLoadedAccounts().getLast();
IReservation ir = account.getAllReservations().next();
rsrv = (Reservation) ir;
rsrv.Change(rsrv, ReservationStatusEnum.Canceled);
mgr.UpdateAccount(mgr.retrieveAccount(rsrv.getAccountNumber()));
// 8. Change reservation values that can be changed (if reservation is
// cancelled, completed, or for past date, it is considered an error)
rsrv.Change(rsrv, ReservationStatusEnum.Completed);
rsrv.update(rsrv);
// 9. Request for price per night to be calculated and returned for a
// per night
// reservation
System.out.println(String.format("%s Per Night Rate: %f",
rsrv.ReservationType().replace("Reservation", ""), rsrv.getPricePerNight()));
// 10. Request for total reservation price to be calculated and returned for
// specific reservation
rsrv = account.findReservation(rsrv.getReservation_number());
rsrv.calculatePrice();
mgr.showReservationList();
System.out.println("Program Completed.");
}
public final static class getRepositoryConfig {
public final static String getPath() {
String home = System.getenv("HOME") != null ? System.getenv("HOME")
: System.getenv("HOMEDRIVE") + System.getenv("HOMEPATH");
return home.replace('\\', '/') + "/workspace/reservationsystem/src/resources";
}
}
}

View File

@@ -0,0 +1,199 @@
/**
* license: GPLv3
* lodge.reservationsystem
*/
package lodge.datamodel;
import java.io.BufferedWriter;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ListIterator;
import lodge.reservationsystem.DataRepository;
/**
* Concrete account data class for account json storage record.
* Collects account attributes, and hash instance to enforce uniqueness.
*/
public class Account {
private String account_number = "-99";
private String phone_number;
private Address mailing_address;
private EmailAddress email_address;
private final AccountReservationList reservations = new AccountReservationList();
public Account() {
}
public Account(
String account_number,
String phone_number,
Address mailing_address,
EmailAddress email_address) {
this.account_number = account_number;
this.phone_number = phone_number;
this.mailing_address = mailing_address;
this.email_address = email_address;
}
public Account(String phone_number, Address mailing_address, EmailAddress email_address)
throws IllegalArgumentException {
if (phone_number == null) {
throw new IllegalArgumentException(String.format("%s %s", "Account: requires phone number",
mailing_address.toString()));
}
if (mailing_address == null) {
throw new IllegalArgumentException(String.format("%s %s", "Account: requires mailing address",
phone_number.substring(phone_number.length() - 4)));
}
if (email_address == null) {
throw new IllegalArgumentException(String.format("%s %s", "Account: requires phone number",
mailing_address.toString()));
}
this.account_number = AccountList.accountSerial(phone_number, mailing_address, email_address);
this.phone_number = phone_number;
this.mailing_address = mailing_address;
this.email_address = email_address;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("{ \"Account\":{");
sb.append("\"account_number\": \"").append(account_number).append("\",");
sb.append("\"phone_number\": \"").append(phone_number).append("\",");
sb.append("\"mailing_address\": ").append(mailing_address).append(",");
sb.append("\"email_address\": ").append(email_address).append(",");
sb.append(this.reservations.toString());
sb.append("}}");
return sb.toString();
}
public boolean add(Reservation rsrv) throws DuplicateObjectException {
boolean result = false;
if (rsrv == null) {
return false;
}
try {
result = reservations.add((IReservation) rsrv);
} catch (DuplicateObjectException e) {
System.out.println(String.format("%s", e.getMessage()));
} finally {
}
if (result) {
/* add account number to reservation for tracking purposes */
rsrv.setAccountNumber(this.account_number);
}
return result;
}
public static void Write(Account acct) throws IOException {
String dataRoot = DataRepository.getPath();
dataRoot = dataRoot + "/acc-" + acct.account_number + ".json";
Path path = Paths.get(dataRoot);
try (BufferedWriter writer = Files.newBufferedWriter(path, StandardCharsets.UTF_8)) {
writer.write(acct.toString());
writer.flush();
}
for (IReservation i : acct.reservations) {
Reservation r = (Reservation) i;
r.Write(r);
}
}
public String getAccount_number() {
return account_number;
}
public void setAccount_number(String account_number) {
this.account_number = account_number;
}
public String getPhone_number() {
return phone_number;
}
public void setPhone_number(String phone_number) {
this.phone_number = phone_number;
}
public Address getMailing_address() {
return mailing_address;
}
public void setMailing_address(Address mailing_address) {
this.mailing_address = mailing_address;
}
public EmailAddress getEmail_address() {
return email_address;
}
public void setEmail_address(EmailAddress email_address) {
this.email_address = email_address;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((account_number == null) ? 0 : account_number.hashCode());
return result;
}
public Reservation findReservation(String reservation_number) {
return this.reservations.find(reservation_number);
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Account other = (Account) obj;
if (account_number == null) {
if (other.account_number != null)
return false;
} else if (!account_number.equals(other.account_number))
return false;
return true;
}
public boolean checkValid() throws IllegalArgumentException {
if (email_address == null) {
throw new IllegalArgumentException(
String.format("not valid, email_address %s", this.getAccount_number()));
}
if (phone_number == null) {
throw new IllegalArgumentException(
String.format("not valid, phone_number: %s", this.getAccount_number()));
}
if (getMailing_address() == null) {
throw new IllegalArgumentException(
String.format("not valid, mailing_address: %s", this.getAccount_number()));
}
return true;
}
public void update(Account acct) {
this.setEmail_address(acct.email_address);
this.setPhone_number(acct.phone_number);
this.setMailing_address(acct.mailing_address);
}
public ListIterator<IReservation> getAllReservations() {
return this.reservations.listIterator();
}
}

View File

@@ -0,0 +1,80 @@
/**
* license: GPLv3
* lodge.reservationsystem
*/
package lodge.datamodel;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.ListIterator;
public class AccountList extends ArrayList<Account> {
public static String accountSerial(String phone_number, Address mailing_address, EmailAddress email_address) {
return String.format("A%09d", Math.abs(java.util.Objects.hash(phone_number, mailing_address, email_address)));
}
// ** Add account throw error if account number is pre-existing. */
@Override
public synchronized boolean add(final Account account)
throws DuplicateObjectException {
try {
for (Account acct : this) {
if (acct.getAccount_number().compareTo(account.getAccount_number()) == 0) {
throw new DuplicateObjectException(
String.format("Account %s exists, duplicates not allowed.", acct.getAccount_number()));
}
}
} catch (DuplicateObjectException e) {
System.out.println(String.format("%s", e.getMessage()));
return false;
}
return super.add(account);
}
// save accounts in edit status
public void save(final Account acct) throws IOException {
if (acct == null) {
return;
}
Account.Write(acct);
}
// ** Find account return null not-existing. */
public final Account find(String account_number) {
for (Account acct : this) {
if (acct.getAccount_number().compareTo(account_number) == 0) {
return acct;
}
}
return null;
}
public List<? extends IReservation> getListOfReservations() {
ArrayList<IReservation> readList = new ArrayList<>();
for (Account acct : this) {
ListIterator<IReservation> itr = acct.getAllReservations();
while (itr.hasNext()) {
readList.add(itr.next());
}
}
return Collections.unmodifiableList(readList);
}
// Show the different accounts lists of resverations
public void showReservationList() {
for (IReservation irsrv : this.getListOfReservations()) {
System.out.println(String.format("Account %s: %s, %s", irsrv.getAccountNumber(),
irsrv.getReservation_number(), irsrv.getPhysical_address().getStreet()));
}
}
// show the accounts
public void showAccountList() {
for (Account acct : this) {
System.out.println(String.format("Account %s", acct.getAccount_number()));
}
}
}

View File

@@ -0,0 +1,75 @@
/**
* license: GPLv3
* lodge.reservationsystem
*/
package lodge.datamodel;
import java.util.ArrayList;
class AccountReservationList extends ArrayList<IReservation> {
private static String reservationSerial(Reservation reservation) {
return String.format("R%010d", Math.abs(java.util.Objects.hash(reservation.getPhysical_address())));
}
@Override
public synchronized boolean add(final IReservation reservation) throws RuntimeException {
boolean result = true;
((Reservation) reservation)
.setReservation_number(AccountReservationList.reservationSerial((Reservation) reservation));
Reservation rsrv = this.find(reservation.getReservation_number());
result = rsrv == null;
if (!result) {
throw new DuplicateObjectException(
String.format("Error No Dups, Reservation exists: %s.", rsrv.getReservation_number()));
}
result = ((IReservation) reservation).checkValid();
if (result) {
((Reservation) reservation).setPrice(reservation.calculatePrice());
result = super.add(reservation);
} else {
throw new IllegalArgumentException(String.format("error reservation invalid: %s",
((Reservation) reservation).getReservation_number()));
}
return result;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("\"reservations\":[");
for (int ix = 0; ix < this.size(); ix++) {
String name = this.get(ix).ReservationType() + "";
if ((this.size() - 1) == ix) {
sb.append(String.format("{\"%s\":{\"reservation_number\":\"%s\"}}", name,
this.get(ix).getReservation_number()));
} else {
sb.append(String.format("{\"%s\":{\"reservation_number\":\"%s\"}},", name,
this.get(ix).getReservation_number()));
}
}
sb.append("]");
return sb.toString();
}
public Reservation find(String reservation_number) {
for (IReservation rsrv : this) {
if (rsrv.getReservation_number().compareTo(reservation_number) == 0) {
return (Reservation) rsrv;
}
}
return null;
}
public void update(AccountReservationList incoming_reservation_list) {
for (IReservation rsrv : incoming_reservation_list) {
Reservation onListRsrv = find(rsrv.getReservation_number());
if (onListRsrv != null) {
onListRsrv.update((Reservation) rsrv);
}
}
}
}

View File

@@ -0,0 +1,114 @@
/**
* license: GPLv3
* lodge.reservationsystem
*/
package lodge.datamodel;
public final class Address{
String street;
String city;
String state;
String zip;
/** not used
*
*/
@SuppressWarnings("unused")
private Address() {
}
public Address(String street, String city, String state, String zip) {
this.street = street;
this.city = city;
this.state = state;
this.zip = zip;
}
public String getStreet() {
return street;
}
public void setStreet(String street) {
this.street = street;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public String getZip() {
return zip;
}
public void setZip(String zip) {
this.zip = zip;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((street == null) ? 0 : street.hashCode());
result = prime * result + ((city == null) ? 0 : city.hashCode());
result = prime * result + ((state == null) ? 0 : state.hashCode());
result = prime * result + ((zip == null) ? 0 : zip.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Address other = (Address) obj;
if (street == null) {
if (other.street != null)
return false;
} else if (!street.equals(other.street))
return false;
if (city == null) {
if (other.city != null)
return false;
} else if (!city.equals(other.city))
return false;
if (state == null) {
if (other.state != null)
return false;
} else if (!state.equals(other.state))
return false;
if (zip == null) {
if (other.zip != null)
return false;
} else if (!zip.equals(other.zip))
return false;
return true;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("{ \"Address\":{");
sb.append("\"street\": \"" + street + "\",");
sb.append("\"city\": \"" + city + "\",");
sb.append("\"state\": \"" + state + "\",");
sb.append("\"zip\": \"" + zip + "\"");
sb.append("}}");
return sb.toString();
}
}

View File

@@ -0,0 +1,16 @@
/**
* license: GPLv3
* lodge.reservationsystem
*/
package lodge.datamodel;
public class DuplicateObjectException extends RuntimeException {
public DuplicateObjectException() {
super();
}
public DuplicateObjectException(String message) {
super(message);
}
}

View File

@@ -0,0 +1,56 @@
/**
* license: GPLv3
* lodge.reservationsystem
*/
package lodge.datamodel;
public class EmailAddress{
String email_address;
public EmailAddress(String email_address) {
this.email_address = email_address;
}
public String getEmail_address() {
return email_address;
}
public void setEmail_address(String email_address) {
this.email_address = email_address;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((email_address == null) ? 0 : email_address.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
EmailAddress other = (EmailAddress) obj;
if (email_address == null) {
if (other.email_address != null)
return false;
} else if (!email_address.equals(other.email_address))
return false;
return true;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("{ \"EmailAddress\":{");
sb.append("\"email\": \"" + email_address + "\"");
sb.append("}}");
return sb.toString();
}
}

View File

@@ -0,0 +1,13 @@
package lodge.datamodel;
public interface IReservation {
public abstract String ReservationType();
public static Reservation copy(String type){ return null; };
public String getReservation_number();
public String getAccountNumber();
public Address getPhysical_address();
public float getPricePerNight();
public float calculatePrice();
public boolean checkValid();
}

View File

@@ -0,0 +1,16 @@
/**
* license: GPLv3
* lodge.reservationsystem
*/
package lodge.datamodel;
public class IllegalOperationException extends RuntimeException {
public IllegalOperationException () {
super();
}
public IllegalOperationException (String message) {
super(message);
}
}

View File

@@ -0,0 +1,9 @@
/**
* license: GPLv3
* lodge.reservationsystem
*/
package lodge.datamodel;
public enum KitchenTypeEnum {
None, Kitchenette, FullKitchen;
}

View File

@@ -0,0 +1,267 @@
/**
* license: GPLv3
* lodge.reservationsystem
*/
package lodge.datamodel;
import java.io.BufferedWriter;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.ZonedDateTime;
import lodge.reservationsystem.DataRepository;
public abstract class Reservation implements IReservation{
private char type;
private String reservation_number = "-99";
private Address physical_address;
private Address mailing_address;
private ZonedDateTime reservation_start_date;
private ZonedDateTime reservation_end_date;
private ReservationStatusEnum reservation_status;
private KitchenTypeEnum kitchen;
private Integer numberOfBeds;
private Integer numberOfBedRooms;
private Integer numberOfBathRooms;
private Integer numberOfFloors;
private Integer squareFeet;
private Float price;
protected String accountNumber = null;
protected Reservation() {
numberOfBeds = 1;
numberOfBedRooms = 1;
numberOfBathRooms = 1;
numberOfFloors = 1;
kitchen = KitchenTypeEnum.None;
price = 120.0f;
reservation_status = ReservationStatusEnum.Draft;
mailing_address = null;
physical_address = null;
}
public void setReservation_number(String reservation_number) {
this.reservation_number = reservation_number;
}
public String getReservation_number() {
return this.reservation_number;
}
public String getAccountNumber() {
return this.accountNumber;
}
public void setAccountNumber(String account_number) {
this.accountNumber = account_number;
}
public void setPhysical_address(Address physical_address) {
this.physical_address = physical_address;
}
public Address mailing_address() {
return mailing_address;
}
public void setMailing_address(Address mailing_address) {
this.mailing_address = mailing_address;
}
public void setReservation_start_date(ZonedDateTime reservation_start_date) {
this.reservation_start_date = reservation_start_date;
}
public void setReservation_end_date(ZonedDateTime reservation_end_date) {
this.reservation_end_date = reservation_end_date;
}
public void setReservation_status(ReservationStatusEnum reservation_status) {
this.reservation_status = reservation_status;
}
public KitchenTypeEnum getKitchen() {
return kitchen;
}
public void setKitchen(KitchenTypeEnum kitchen) {
this.kitchen = kitchen;
}
public void setNumberOfBeds(Integer numberOfBeds) {
this.numberOfBeds = numberOfBeds;
}
public Integer numberOfBedRooms() {
return numberOfBedRooms;
}
public void setNumberOfBedRooms(Integer numberOfBedRooms) {
this.numberOfBedRooms = numberOfBedRooms;
}
public void setNumberOfBathRooms(Integer numberOfBathRooms) {
this.numberOfBathRooms = numberOfBathRooms;
}
public void setNumberOfFloors(Integer numberOfFloors) {
this.numberOfFloors = numberOfFloors;
}
public void setSquareFeet(Integer squareFeet) {
this.squareFeet = squareFeet;
}
public void setPrice(Float price) {
this.price = price;
}
public char getType() {
return type;
}
public void setType(char type) {
this.type = type;
}
public Address getPhysical_address() {
return physical_address;
}
public Address getMailing_address() {
return mailing_address;
}
public ZonedDateTime getReservation_start_date() {
return reservation_start_date;
}
public ZonedDateTime getReservation_end_date() {
return reservation_end_date;
}
public ReservationStatusEnum getReservation_status() {
return reservation_status;
}
public Integer getNumberOfBeds() {
return numberOfBeds;
}
public Integer getNumberOfBedRooms() {
return numberOfBedRooms;
}
public Integer getNumberOfBathRooms() {
return numberOfBathRooms;
}
public Integer getNumberOfFloors() {
return numberOfFloors;
}
public Integer getSquareFeet() {
return squareFeet;
}
public Float getPrice() {
return price;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((reservation_number == null) ? 0 : reservation_number.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Reservation other = (Reservation) obj;
if (reservation_number == null) {
if (other.reservation_number != null)
return false;
} else if (!reservation_number.equals(other.reservation_number))
return false;
return true;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(String.format("{ \"%s\":{", this.ReservationType()));
sb.append("\"reservation_type\": \"").append(ReservationType()).append("\",");
sb.append("\"reservation_number\": \"").append(reservation_number).append("\",");
sb.append("\"reservation_status\": \"").append(reservation_status).append("\",");
sb.append("\"reservation_start_date\": \"").append(reservation_start_date).append("\",");
sb.append("\"reservation_end_date\": \"").append(reservation_end_date).append("\",");
sb.append("\"account_number\": \"").append(accountNumber).append("\",");
sb.append("\"physical_address\": ").append(physical_address).append(",");
sb.append("\"mailing_address\": ").append(mailing_address).append(",");
sb.append("\"kitchen\": \"").append(kitchen).append("\",");
sb.append("\"numberOfBeds\": \"").append(numberOfBeds).append("\",");
sb.append("\"numberOfBedRooms\": \"").append(numberOfBedRooms).append("\",");
sb.append("\"numberOfBathRooms\": \"").append(numberOfBathRooms).append("\",");
sb.append("\"numberOfFloors\": \"").append(numberOfFloors).append("\",");
sb.append("\"squareFeet\": \"").append(squareFeet).append("\",");
sb.append("\"price\": \"").append(price).append("\"");
sb.append("}}");
return sb.toString();
}
// @TODO write reservation out in json
public void Write(Reservation reservation) throws IOException {
String dataRoot = DataRepository.getPath();
dataRoot = dataRoot + "/rsv-" + reservation.reservation_number + ".json";
Path path = Paths.get(dataRoot);
try (BufferedWriter writer = Files.newBufferedWriter(path, StandardCharsets.UTF_8)) {
writer.write(toString());
writer.flush();
}
}
public void Change(Reservation reservation, ReservationStatusEnum newStatus) throws IllegalOperationException {
try {
if (reservation.reservation_status == ReservationStatusEnum.Completed ||
reservation.reservation_status == ReservationStatusEnum.Canceled) {
if (newStatus == ReservationStatusEnum.Canceled) {
throw new IllegalOperationException(
String.format("Invalid Change, reservation has %s.", reservation.getReservation_status()));
}
if (ZonedDateTime.now().compareTo(this.reservation_start_date) > -1) {
throw new IllegalOperationException("Invalid Change, reservation has begun.");
}
}
if (newStatus == ReservationStatusEnum.Completed) {
IReservation irsrv = (IReservation) this;
this.setPrice(irsrv.calculatePrice());
}
reservation.setReservation_status(newStatus);
} catch (IllegalOperationException e) {
System.out.println(e.toString());
}
}
public void update(Reservation rsrv) {
}
public abstract String ReservationType();
}

View File

@@ -0,0 +1,12 @@
/**
* license: GPLv3
* lodge.reservationsystem
*/
package lodge.datamodel;
public enum ReservationStatusEnum {
Draft,
Canceled,
Completed
}

View File

@@ -0,0 +1,115 @@
/**
* license: GPLv3
* lodge.reservationsystem
*/
package lodge.reservationsystem;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Collections;
import java.util.List;
import lodge.datamodel.Account;
import lodge.datamodel.AccountList;
import lodge.datamodel.Address;
import lodge.datamodel.DuplicateObjectException;
import lodge.datamodel.EmailAddress;
import lodge.datamodel.IReservation;
import lodge.datamodel.IllegalOperationException;
import lodge.datamodel.Reservation;
public final class AccomodationManager {
private final AccountList accounts = new AccountList();
@SuppressWarnings("unused")
private AccomodationManager() {
};
public AccomodationManager(String home) {
setDataStoreRoot(home);
};
public final void setDataStoreRoot(String home) {
DataRepository.setDataStoreRoot(home);
}
public final void loadAll()throws IOException,IllegalArgumentException,IllegalOperationException,DuplicateObjectException{
accounts.clear();
// walk directories
Path rootDir = Paths.get(DataRepository.getPath());
DataRepository.WalkFileSystemTree(this, rootDir);
System.out.println(String.format("%s LoadAll Accounts %d", "Deserializing", accounts.size()));
}
// Load / Deserialize Account
protected void load(Path file) throws IOException,IllegalArgumentException,IllegalOperationException,DuplicateObjectException {
Account account = DataRepository.LoadAccount(file);
if (account == null) {
System.out.println(String.format("No Account: %s", file.toString()));
} else {
account.checkValid();
accounts.add(account);
}
}
public final List<Account> retrieveLoadedAccounts() {
return Collections.unmodifiableList(accounts);
}
public Account retrieveAccount(String acct_id) {
return accounts.find(acct_id);
}
public synchronized void AddAccount(final Account acct) throws Exception {
accounts.add(acct);
}
public synchronized void UpdateAccount(final Account acct) throws Exception {
if( acct != null ){
accounts.save(acct);
}
}
public final Account newAccount(String phone_number, Address mailing_address, EmailAddress email_address)
throws Exception {
Account acct = null;
try {
acct = new Account(phone_number, mailing_address, email_address);
} catch (Exception e) {
System.out.println(e.toString());
}
accounts.save(acct);
return acct;
}
public boolean addReservation(final Account account, final Reservation reservation){
boolean result = account.add(reservation);
return result;
}
public final Reservation findReservation(String reservation_number) {
Reservation rsrv = null;
for (Account acct : accounts) {
rsrv = acct.findReservation(reservation_number);
if( rsrv!=null ) break;
}
return rsrv;
}
public List<? extends IReservation> getReservationList() {
return accounts.getListOfReservations();
}
public void showReservationList() {
accounts.showReservationList();
}
public void showAccountList() {
accounts.showAccountList();
}
}

View File

@@ -0,0 +1,86 @@
/**
* license: GPLv3
* lodge.reservationsystem
*/
package lodge.reservationsystem;
import java.time.ZonedDateTime;
import java.time.temporal.ChronoUnit;
import lodge.datamodel.Address;
import lodge.datamodel.KitchenTypeEnum;
import lodge.datamodel.Reservation;
/**
* Concrete reservation data class for reservation storage record
*/
public final class CabinReservation extends Reservation {
public CabinReservation() {
super();
this.setType('C');
this.setNumberOfBeds(1);
this.setKitchen(KitchenTypeEnum.Kitchenette);
}
public CabinReservation(final Address physical_address) {
super();
this.setType('C');
this.setNumberOfBeds(1);
this.setKitchen(KitchenTypeEnum.Kitchenette);
this.setPhysical_address(
new Address(physical_address.getStreet(), physical_address.getCity(), physical_address.getState(),
physical_address.getZip()));
}
@Override
public String ReservationType() {
return "CabinReservation";
}
@Override
public boolean checkValid() throws IllegalArgumentException {
if (getPhysical_address() == null) {
throw new IllegalArgumentException(String.format("not valid, physical_address %s", this.getReservation_number()));
}
if (getMailing_address() == null) {
throw new IllegalArgumentException(String.format("not valid, mailing_address: %s", this.getReservation_number()));
}
return true;
}
@Override
public float getPricePerNight() {
float calcprice = (getSquareFeet() > 900.0f) ? 120.0f + 15.0f : 120.0f;
if (getKitchen() == KitchenTypeEnum.FullKitchen) {
calcprice = calcprice + 20.0f;
}
if (getNumberOfBathRooms() > 1) {
setPrice(getPrice() + (getNumberOfBathRooms() * 5.0f));
}
return calcprice;
}
// calculate and return the reservation's price
// Cabin price plus additional fee of $20 for full kitchen and $5 for each
// additional bathroom
@Override
public float calculatePrice() {
ZonedDateTime enddt = getReservation_end_date().truncatedTo(ChronoUnit.DAYS);
ZonedDateTime startdt = getReservation_start_date().truncatedTo(ChronoUnit.DAYS);
long days = ChronoUnit.DAYS.between(startdt, enddt);
days = (days < 2) ? 1 : days - 1;
float calcprice = (getSquareFeet() > 900.0f) ? 120.0f + 15.0f : 120.0f;
if (getKitchen() == KitchenTypeEnum.FullKitchen) {
calcprice = calcprice + 20.0f;
}
if (getNumberOfBathRooms() > 1) {
setPrice(getPrice() + (getNumberOfBathRooms() * 5.0f));
}
calcprice = calcprice * days;
return calcprice;
}
}

View File

@@ -0,0 +1,279 @@
/**
* license: GPLv3
* lodge.reservationsystem
*/
package lodge.reservationsystem;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.time.ZonedDateTime;
import com.google.gson.stream.JsonReader;
import lodge.datamodel.Account;
import lodge.datamodel.Address;
import lodge.datamodel.EmailAddress;
import lodge.datamodel.KitchenTypeEnum;
import lodge.datamodel.Reservation;
import lodge.datamodel.ReservationStatusEnum;
public final class DataRepository {
// SINGLETON CLASS
// hard code data store location for storage of
// account data files on filesystem
private String directoryPath;
private static final DataRepository instance = new DataRepository();
protected final static DataRepository getInstance() {
return instance;
}
public final static void setDataStoreRoot(final String direcoryPath) {
getInstance().directoryPath = direcoryPath;
}
public final static String getPath() {
return getInstance().directoryPath;
}
public final static Reservation Reservation(String type) {
switch (type) {
case "HotelReservation":
return new HotelReservation();
case "HouseReservation":
return new HouseReservation();
case "CabinReservation":
return new CabinReservation();
}
return null;
}
public static void WalkFileSystemTree(final AccomodationManager manager, final Path rootDir) throws IOException {
Files.walkFileTree(rootDir, new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult visitFile(final Path file, final BasicFileAttributes attrs) {
System.out.println("File: " + file.toAbsolutePath());
// load account number, and content
if (attrs.isRegularFile()) {
final String namestring = file.getName(file.getNameCount() - 1).toString();
if (namestring.endsWith("json")) {
if (namestring.startsWith("acc")) { // * load Account *//
try {
manager.load(file);
} catch (final Exception e) {
e.printStackTrace();
}
}
}
}
// load reservation
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult preVisitDirectory(final Path dir, final BasicFileAttributes attrs) {
System.out.println("Directory: " + dir.toAbsolutePath());
// prepare to load account number
return FileVisitResult.CONTINUE;
}
});
}
public final static Account LoadAccount(final Path file) throws IOException {
/** @TODO finish loading Account */
try (BufferedReader in = new BufferedReader(new FileReader(file.toFile(), StandardCharsets.UTF_8));
JsonReader jsonReader = new JsonReader(in)) {
jsonReader.beginObject();
Account ac = new Account();
while (jsonReader.hasNext()) {
final String name = jsonReader.nextName();
switch (name) {
case "Account":
jsonReader.beginObject();
break;
case "account_number":
ac.setAccount_number(jsonReader.nextString());
break;
case "phone_number":
ac.setPhone_number(jsonReader.nextString());
break;
case "mailing_address":
jsonReader.beginObject();
break;
case "Address":
jsonReader.beginObject();
jsonReader.nextName();
String mstreet = jsonReader.nextString();
jsonReader.nextName();
String mcity = jsonReader.nextString();
jsonReader.nextName();
String mstate = jsonReader.nextString();
jsonReader.nextName();
String mzip = jsonReader.nextString();
jsonReader.endObject();
jsonReader.endObject();
ac.setMailing_address(new Address(mstreet, mcity, mstate, mzip));
break;
case "email_address":
jsonReader.beginObject();
break;
case "EmailAddress":
jsonReader.beginObject();
break;
case "email":
String s = jsonReader.nextString();
s = s != null ? s : "";
ac.setEmail_address(new EmailAddress(s));
jsonReader.endObject();
jsonReader.endObject();
break;
case "reservations":
loadReservationRefList(jsonReader, ac);
break;
default:
System.out.println(name);
}
}
jsonReader.close();
return ac.getAccount_number().length() > 8 ? ac : null;
}
}
static void loadReservationRefList(JsonReader rdr, Account ac) throws IOException {
rdr.beginArray();
while (rdr.hasNext()) {
rdr.beginObject();
String reservationType = rdr.nextName();
rdr.beginObject();
rdr.nextName();
String reservationNumber = rdr.nextString();
loadReservation(ac, reservationType, reservationNumber);
rdr.endObject();
rdr.endObject();
}
rdr.endArray();
}
private static void loadReservation(Account ac, String reservationType,
String reservationNumber) throws IOException {
String filename = String.format("rsv-%s.json", reservationNumber);
Path basePath = Paths.get(getPath());
Path resolvedPath = basePath.resolve(filename);
try (BufferedReader in = new BufferedReader(new FileReader(resolvedPath.toFile(), StandardCharsets.UTF_8))) {
try (JsonReader jsonReader = new JsonReader(in)) {
jsonReader.beginObject();
Reservation rsrv = null;
try {
while (jsonReader.hasNext()) {
String name = jsonReader.nextName();
switch (name) {
case "HotelReservation":
jsonReader.beginObject();
rsrv = Reservation("HotelReservation");
break;
case "HouseReservation":
jsonReader.beginObject();
rsrv = Reservation("HouseReservation");
break;
case "CabinReservation":
jsonReader.beginObject();
rsrv = Reservation("CabinReservation");
break;
case "physical_address":
jsonReader.beginObject();
jsonReader.nextName();
jsonReader.beginObject();
jsonReader.nextName();
String street = jsonReader.nextString();
jsonReader.nextName();
String city = jsonReader.nextString();
jsonReader.nextName();
String state = jsonReader.nextString();
jsonReader.nextName();
String zip = jsonReader.nextString();
jsonReader.endObject();
jsonReader.endObject();
rsrv.setPhysical_address(new Address(street, city, state, zip));
break;
case "mailing_address":
jsonReader.beginObject();
jsonReader.nextName();
jsonReader.beginObject();
jsonReader.nextName();
String mstreet = jsonReader.nextString();
jsonReader.nextName();
String mcity = jsonReader.nextString();
jsonReader.nextName();
String mstate = jsonReader.nextString();
jsonReader.nextName();
String mzip = jsonReader.nextString();
jsonReader.endObject();
jsonReader.endObject();
rsrv.setMailing_address(new Address(mstreet, mcity, mstate, mzip));
break;
case "reservation_type":
jsonReader.nextString();
break;
case "reservation_number":
rsrv.setReservation_number(jsonReader.nextString());
break;
case "reservation_status":
rsrv.setReservation_status(ReservationStatusEnum.valueOf(jsonReader.nextString()));
break;
case "kitchen":
rsrv.setKitchen(KitchenTypeEnum.valueOf(jsonReader.nextString()));
break;
case "numberOfBeds":
rsrv.setNumberOfBeds(Integer.valueOf(jsonReader.nextString()));
break;
case "numberOfBedRooms":
rsrv.setNumberOfBedRooms(Integer.valueOf(jsonReader.nextString()));
break;
case "numberOfBathRooms":
rsrv.setNumberOfBathRooms(Integer.valueOf(jsonReader.nextString()));
break;
case "numberOfFloors":
rsrv.setNumberOfFloors(Integer.valueOf(jsonReader.nextString()));
break;
case "squareFeet":
rsrv.setSquareFeet(Integer.valueOf(jsonReader.nextString()));
break;
case "price":
rsrv.setPrice(Float.valueOf(jsonReader.nextString()));
break;
case "reservation_start_date":
rsrv.setReservation_start_date(ZonedDateTime.parse(jsonReader.nextString()));
break;
case "reservation_end_date":
rsrv.setReservation_end_date(ZonedDateTime.parse(jsonReader.nextString()));
break;
case "account_number":
rsrv.setAccountNumber(jsonReader.nextString());
break;
default:
System.out.println(name);
}
}
ac.add(rsrv);
} catch (Exception e) {
System.out.println(e.toString());
}
}
}
}
}

View File

@@ -0,0 +1,104 @@
/**
* license: GPLv3
* lodge.reservationsystem
*/
package lodge.reservationsystem;
import java.time.LocalTime;
import java.time.ZonedDateTime;
import java.time.temporal.ChronoUnit;
import lodge.datamodel.Address;
import lodge.datamodel.KitchenTypeEnum;
import lodge.datamodel.Reservation;
/**
* Concrete reservation data class for reservation storage record
*/
public final class HotelReservation extends Reservation {
public HotelReservation() {
super();
this.setType('H');
this.setNumberOfBeds(2);
this.setNumberOfBeds(2);
this.setNumberOfBedRooms(1);
this.setNumberOfBathRooms(1);
this.setNumberOfFloors(1);
this.setKitchen(KitchenTypeEnum.Kitchenette);
}
public static Reservation copy(String reservationType) {
return new HotelReservation();
}
public HotelReservation(final Address physical_address) {
super();
this.setType('H');
this.setNumberOfBeds(2);
this.setNumberOfBeds(2);
this.setNumberOfBedRooms(1);
this.setNumberOfBathRooms(1);
this.setNumberOfFloors(1);
this.setKitchen(KitchenTypeEnum.Kitchenette);
this.setPhysical_address(
new Address(physical_address.getStreet(), physical_address.getCity(), physical_address.getState(),
physical_address.getZip()));
}
@Override
public final String ReservationType() {
return "HotelReservation";
}
@Override
public boolean checkValid() throws IllegalArgumentException {
if (getNumberOfBathRooms() != 1) {
throw new IllegalArgumentException("not valid, Baths");
}
if (getNumberOfBedRooms() != 1) {
throw new IllegalArgumentException("not valid, BedRooms");
}
if (getNumberOfBeds() != 2) {
throw new IllegalArgumentException("not valid, Beds");
}
if (getPhysical_address() == null) {
throw new IllegalArgumentException(String.format("not valid, physical_address %s", this.getReservation_number()));
}
if (getMailing_address() == null) {
throw new IllegalArgumentException(String.format("not valid, mailing_address: %s", this.getReservation_number()));
}
return true;
}
@Override
public float getPricePerNight() {
float calcprice = (getSquareFeet() > 900.0f) ? 120.0f + 15.0f : 120.0f;
if (getKitchen() == KitchenTypeEnum.FullKitchen) {
calcprice = calcprice + 10.0f;
}
return calcprice;
}
// calculate and return the reservation's price
// Hotel price plus additional flat fee of $50 plus $10 for kitchenette
@Override
public float calculatePrice() {
ZonedDateTime enddt = getReservation_end_date().truncatedTo(ChronoUnit.DAYS);
ZonedDateTime startdt = getReservation_start_date().truncatedTo(ChronoUnit.DAYS);
long days = ChronoUnit.DAYS.between(startdt, enddt);
ZonedDateTime checkOutTime = enddt.with(LocalTime.of(12, 0));
if (getReservation_end_date().isBefore(checkOutTime)) {
days = days - 1;
}
float calcprice = (getSquareFeet() > 900.0f) ? 120.0f + 15.0f : 120.0f;
if (getKitchen() == KitchenTypeEnum.FullKitchen) {
calcprice = calcprice + 10.0f;
}
calcprice = calcprice * days;
calcprice = calcprice + 50.0f;
return calcprice;
}
}

View File

@@ -0,0 +1,80 @@
/**
* license: GPLv3
* lodge.reservationsystem
*/
package lodge.reservationsystem;
import java.time.ZonedDateTime;
import java.time.temporal.ChronoUnit;
import lodge.datamodel.Address;
import lodge.datamodel.KitchenTypeEnum;
import lodge.datamodel.Reservation;
/**
* Concrete reservation data class for reservation storage record
*/
public final class HouseReservation extends Reservation {
public HouseReservation() {
super();
this.setType('Z');
this.setNumberOfBeds(2);
this.setNumberOfBedRooms(1);
this.setNumberOfBathRooms(1);
this.setNumberOfFloors(1);
this.setKitchen(KitchenTypeEnum.Kitchenette);
}
public static Reservation copy(String reservationType) {
return new HouseReservation();
}
public HouseReservation(final Address physical_address) {
super();
this.setType('Z');
this.setNumberOfBeds(2);
this.setNumberOfBedRooms(1);
this.setNumberOfBathRooms(1);
this.setNumberOfFloors(1);
this.setKitchen(KitchenTypeEnum.Kitchenette);
this.setPhysical_address(
new Address(physical_address.getStreet(), physical_address.getCity(), physical_address.getState(),
physical_address.getZip()));
}
@Override
public final String ReservationType() {
return "HouseReservation";
}
@Override
public boolean checkValid() throws IllegalArgumentException {
if (getPhysical_address() == null) {
throw new IllegalArgumentException(String.format("not valid, physical_address %s", this.getReservation_number()));
}
if (getMailing_address() == null) {
throw new IllegalArgumentException(String.format("not valid, mailing_address: %s", this.getReservation_number()));
}
return true;
}
// House price plus additional flat fee for additional space per day
@Override
public float getPricePerNight() {
return (getSquareFeet() > 900.0f) ? 120.0f + 15.0f : 120.0f;
}
// calculate and return the reservation's price
@Override
public float calculatePrice() {
ZonedDateTime enddt = getReservation_end_date().truncatedTo(ChronoUnit.DAYS);
ZonedDateTime startdt = getReservation_start_date().truncatedTo(ChronoUnit.DAYS);
long days = ChronoUnit.DAYS.between(startdt, enddt);
days = (days < 2) ? 1 : days - 1;
float calcprice = getPricePerNight() * days;
return calcprice;
}
}