For this assignment you need to write an object-oriented console application in the Java programming language which adheres to basic object-oriented programming principles shown below:
The scenario we are modelling is that of Real Estate System for a real estate agency in which properties can be sold in two different ways:
Disclaimer: While the scenario described is based upon the concept of a real estate management system, the specification for this task is intended to represent simplified version of such a system and thus is not meant to be a 100% accurate simulation of the any real estate management system or service that is being used at a real life real estate management system.
In this assignment you will be required to complete the implementation of a partially complete object oriented program that models some of the basic functionality that may be required to handle both normal Sales and Auctions in the Real Estate System described above.
This task is divided up into several stages, each of which corresponds to the concepts discussed during the course as shown below:
There is no Startup code for this assignment you are expected to write the entire program yourself.
Your task begins with the implementation of the Sales class.
It of course goes without saying that working your way through the learning materials for the corresponding weeks highlighted above is strongly recommended before tackling each of the stages in this assignment.
Both normal Sales and Auctions share common details (such as the sale ID, property address and the reserve price), which will be encapsulated in this superclass.
A Sale automatically closes when an offer is made which is equal to or higher than the reserve (asking) price (indicating that the offer has been accepted and the property has been sold) - until that time the Sale will still continue to accept offers which are higher than the current offer.
Some tips below should help you to design and write the Sales class:
A) Create the Sale Class
The following instance variables should be defined in your Sales class.
Instance variable Type
saleID String
propertyAddress String
currentOffer Integer
reservePrice Integer
acceptingOffers Boolean
B) Constructor
You should define the following constructor in your Sales class. The constructor should be responsible for storing the supplied information in the corresponding instance variables.
public Sale(String saleID, String propertyAddress, int reservePrice)
C) Accessors (getters)
Simple accessors (getters) should be implemented for the saleID, propertyAddress, reservePrice, currentOffer and acceptingOffers instance variables defined in this Sale class.
D) Mutators (setters)
Simple mutators (setters) should be implemented for the currentOffer and acceptingOffers instance variables defined in this Sale class, which accept the new value to be stored as a parameter and update the corresponding instance variable accordingly. You should not defined setters for all of your instance variables.
E) Operations / Helper Methods
(i) Make an Offer
A method for making an offer should be implemented with the following method signature.
public boolean makeOffer(int offerPrice)
This method should processes an offer made for the Sale in the following manner:
If the Sale is not currently open for offers (ie. acceptingOffers is false), or the new offer price is less than or equal to the current offer then the method returns a false result.
Otherwise the currentOffer instance variable is set to the offer price that was passed in as a parameter and the method checks to see if the reserve price has been met (ie. the updated currentOffer is greater than or equal to the reservePrice) - if this is the case then the Sale is closed by setting the acceptingOffers instance variable to false.
Once the processing of the accepted offer has been completed (regardless of whether it resulted in the Sale being closed or not) the method returns a true result.
(ii) Get Property Status
A helper method should be implemented, which returns ON SALE when the acceptingOffers is true and SOLD when the acceptingOffers is false. The method should have the following signature.
public String getPropertyStatus()
Note that returning a value does not mean printing a value to the screen. The value should be returned to the code that calls the function and the calling code is responsible for the actual printing.
(iii) Print Property Details
A helper method should be implemented, which builds a string and returns it to the calling method. The calling method should then print the returned string to the console. The returned string should be formatted and include instance variables, as well as the current sale outcome for the Sale to the screen. The method signature is provided below as well as example output and formatting.
public String getSaleDetails()
The method should return a formatted string such that the data is presented in a human readable format of two columns as shown in the examples below.
Note that returning a value does not mean printing a value to the screen. The value should be returned to the code that calls the function and the calling code is responsible for the actual printing.
The formatting of the string can be achieved by using the format method on the String class which operates in the same way as the printf statement you learned about in week 2 of the course.
String firstLine = String.format("%-20s %sn", "Sale ID:", saleID);
Example 1:
Sale ID: PAR013
Property Address: 45 Park Avenue, Parkville
Current Offer: $0
Reserve Price: $3500000.0
Accepting offers: true
Sale Status: ACCEPTING BIDS
Highest Bidder: NO BID PLACED
Example 2:
Sale ID: SMA006
Property Address: Unit 4A, Smallville Drive, Smallville
Current Offer: $0
Reserve Price: $192500.0
Accepting offers: true
Sale Status: ON SALE
Example 3:
Sale ID: SAL001
Property Address: 123 Smith Street
Current Offer: $600000
Reserve Price: $400000.0
Accepting offers: false
Sale Status: SOLD
Now that the attribute and functionality required for a standard property sale has been modelled and encapsulated in the Sale class described above in Stage 1, you will begin with the implementation of the RealEstateSystem application class, which will use an array of Sale references called sales to store and manage sales that are added to the system by the user.
You may also use a JCF collection instance (eg. ArrayList or HashMap) to store and manage the sales that the user is adding to the system if you so wish - it is, however, not a requirement to do so for this task and using a simple array of Sale references as described above is still perfectly acceptable.
1.) You should create a class called 'RealEstateSystem'.
2.) You should implement a menu feature in the RealEstateSystem class, for which options are presented to:
A screen shot showing the presentation of this menu is shown below. (Note: the letters on the right represent what the user must type to use that feature. In other words, to add a new sale object the user must input 'A'. The greyed out sections will be added later in subsequent stages.)
*** Real Estate System Menu ***
Add New Sale A
Submit Offer B
Display Sales Summary C
Add New Auction D
Close Auction E
Exit Program X
Your task is to work on the implementation of this initial RealEstateSystem class by implementing the functionality for the first three features shown in the menu (the other two features will be addressed in Stage 4 of this specification).
A description of the functionality that needs to be implemented for each of these features is provided below.
A) Add New Sale Feature
Create a class called 'RealEstateSystem' and implement the menu shown above.
This first feature 'Add New Sale' should prompt the user to enter all relevant details for a normal Sale. Once the user has entered the required details, the program should then create a new Sale object accordingly, passing along the details the user has supplied.
Example:
Enter Sale ID for new PropertySale: SAL001
Enter Property Adddress for new PropertySale: 123 Smith Street
Enter Reserve Price for new PropertySale: 400000
New Property Sale added successfully for property at 123 Smith Street
After the object that has been created it should be added to the next (empty) spot in the array or collection instance you are using to store the Sale / Auction objects in. (Note: Sale IDs must be unique in the RealEstateSystem, so you will need to validate the sale ID entered by the user to make sure that there is not already another sale with the same sale ID in the system. This should be done by searching the current collection and checking for a duplicate ID, you should not modify the prescribed constructor for the Sales class nor should you implement automatic generation of unique ID's. )
If the sale ID already exists within the array/collection of sale objects then a suitable error message should be displayed and the program should go back to the menu immediately without creating or storing a new Sale object in the array / collection. This means that you should perform this check prior to creating the Sale object. Note the property address would also normally be unique, but for the purposes of this assignment you are only required to validate the uniqueness of the sale id.
Example 1:
Enter Sale ID for new PropertySale: SAL001
Enter Property Adddress for new PropertySale: 123 Cavill Avenue
Enter Reserve Price for new PropertySale: 400000
New Property Sale added successfully for property at 123 Cavill Avenue
Example 2:
Enter Sale ID for new PropertySale: SAL001
Error - Sale ID "SAL001" already exists in the system!
A total of 4 marks will be allocated to the basic creation and storage of the new Sale object and an additional 3 marks will be allocated to validating the sale ID entered by the user.
if you are unsure of how to check for / validate duplicate sale ID's then you can skip the validation for now and come back to it later.
B) Submit Offer Feature:
This feature should begin by prompting the user to enter the sale ID of the property for which they wish to submit an offer, once the user has entered the sale ID the feature should then attempt to locate the corresponding sale object within the array / collection of Sale references described above.
If a matching sale with the specified sale ID was not found then a suitable error message should be displayed to the screen.
Example:
Enter Sale ID: SAL002
Error - property sale ID SAL002 not found!
Otherwise the feature should then proceed to prompt the user to enter the offer price, after which it should invoke the makeOffer() method for the sale object in question and check the result returned by the method call (which indicates if the offer was accepted or not).
If the offer was accepted then the feature should check if the reserve has been met for the sale in question - if so then the a suitable message indicating that the reserve has been met/exceeded should be displayed to the screen, otherwise the feature should display a message indicating that the offer was below the reserve price.
Example 1:
Enter Sale ID: SAL001
Current offer: $0
Enter new offer: 100000
Offer accepted! (offer is below reserve price)
Example 2:
Enter Sale ID: SAL001
Current offer: $100000
Enter new offer: 600000
Offer accepted! (reserve price has been met/exceeded)
Example 3:
Enter Sale ID: SAL001
Current offer: $100000
Enter new offer: 50000
Error - New offer must be higher than current offer!
Offer rejected!
C) Build Sales Summary Feature
This feature should display the details for all objects currently stored in the array / collection of Sale references described above to the screen, by using a loop to step through the array / collection and calling the getSaleDetails() method for each object in the array/collection and printing the returned string to the console.
Sale ID: SMA006
Property Address: Unit 4A, Smallville Drive, Smallville
Current Offer: $0
Reserve Price: $192500.0
Accepting offers: true
Sale Status: ON SALE
Sale ID: SAL001
Property Address: 123 Smith Street
Current Offer: $600000
Reserve Price: $400000.0
Accepting offers: false
Sale Status: SOLD
Sale ID: SAL002
Property Address: 456 Cavill Avenue
Current Offer: $0
Reserve Price: $700000.0
Accepting offers: true
Sale Status: ON SALE
An Auction functions somewhat differently to a standard sale in that an Auction will continue to accept offers (bids) until the real estate agency deems that no further bids are forthcoming, at which point the Auction will be closed manually.
If at that point ("auction manually closed"), the reserve (asking) price has been met or exceeded by the highest offer (bid) that was made then the property is considered to be sold, otherwise it is considered to have been passed in (indicating that the property was not sold).
You should address these new requirements by designing and implementing an Auction subclass (which extends the basic Sale class), and which encapsulates the required additional properties and functionality as described below:
A) Create the Auction class by extending the Sale class
Extend the Sale class to define a new class Auction, which includes a new instance variable highestBidder (String)
NOTE: You should not need to redefine any of the instance variables that were defined previously in the Sale superclass in this Auction subclass.
Instance variable Type
highestBidder String
B) Implement a constructor
Implement a constructor which accepts the sale ID, property address and the reserve price for the new Auction as parameters and stores the information in the corresponding instance variables in the super class.
public Auction(String saleID, String propertyAddress, int reservePrice)
This constructor should also initialise the highestBidder instance variable to the value NO BIDS PLACED.
NOTE: You should use the super() facility to pass on the relevant arguments (sale ID, property address and reserve price) to the superclass constructor.
C) Overide methods
Override the helper method public String getPropertyStatus(), so that it returns ACCEPTING BIDS when the acceptingOffers instance variable is currently true, and SOLD (if the reserve has been met) or PASSED IN (if the reserve has not been met) when the acceptingOffers instance variable is currently false.
Note that returning a value does not mean printing a value to the screen. The value should be returned to the code that calls the function and the calling code is responsible for the actual printing.
Also note that you will need to use methods from the Sale superclass at various points to check and update specific properties defined at the superclass level (you should NOT be accessing these properties directly).
D) Implement additional method
Implement a new method public boolean closeAuction(), which updates an Auction to be closed (ie. no longer accepting bids).
public boolean closeAuction()
If the Auction is not currently open for offers (ie. the acceptingOffers instance variable for the Auction is false) then a false result should be returned (indicating that the Auction could not be closed).
Otherwise the method should update the acceptingOffers instance variable for the Auction to false and return true (indicating that the Auction was closed successfully).
Note that you will need to use accessors and mutators from the Sale superclass at various points to check and update specific properties defined at the superclass level (you should NOT be accessing these properties directly).
E) Override a makeOffer method
Override the method public boolean makeOffer(int offerPrice), so that it processes an offer (bid) made for the Auction in the following manner:
If the Auction is not currently open for offers (ie. the acceptingOffers instance variable for the Auction is false) then a false result should be returned. If the new offer price is less than or equal to the current (highest) offer then a false result should again be returned.
Otherwise the currentOffer instance variable should be set to the offer price that was passed in as a parameter and the user should be prompted to enter the name of the new highest bidder (their input should be stored in the highestBidder instance variable) - after this a result of true should be returned (you do not need to check to see if the reserve price has been met for this method in the Auction class nor should the Auction be closed automatically if the reserve has been exceeded).
Note that you will need to use accessors and mutators from the Sale superclass at various points to check and update specific properties defined at the superclass level (you should NOT be accessing these properties directly).
F) Override getSaleDetails method
Override the method public String getSaleDetails() so that it returns a summary of all of the details (instance variables) for the current Auction to the caller of the method (including the highestBidder for the Auction).
NOTE: The overriding version of the getSaleDetails() method in this Auction subclass will need to use the super reference invoke the corresponding method from the Sale superclass to get the basic Sale details first.
The next stage of this task is to update the RealEstateSystem application class implementation described in stage 2 so that it incorporates the other two features as required to allow the user to add and work with Auction objects in the system:
*** Real Estate System Menu ***
Add New Sale A
Submit Offer B
Display Sales Summary C
Add New Auction D
Close Auction E
Exit Program X
Enter selection:
A description of the functions that need to be implemented for each of these features is provided below.
A) Add New Auction Feature
This feature should prompt the user to enter all relevant details for an Auction (sale ID, property address and reserve price). Once the user has entered the required details the program should then create a new Auction object accordingly, passing along the details the user has supplied.
Example:
Enter Sale ID for new AuctionSale: AUC001
Enter Property Adddress for new AuctionSale: 6 - 9 Matthew Court
Enter Reserve Price for new AuctionSale: 600000
New Auction Sale added successfully for property at 6 - 9 Matthew Court
After this the object that has been created should be added to the next (empty) spot in the array or collection instance you are using to store the Sale / Auction objects in.
Note:
You need to store all Sale and Auction objects in a single collection (array), you should not have seperate collections of Sales and Auction objects.
Sale IDs must be unique in the RealEstateSystem, so you will need to validate the sale ID entered by the user to make sure that there is not already another sale with the same sale ID in the system.
If the sale ID already exists within the array/collection of sale objects then a suitable error message should be displayed and the program should go back to the menu immediately without creating or storing a new Auction object in the array / collection. This means that you should perform this check prior to creating the Auction object.
Example:
Enter Sale ID for new AuctionSale: AUC001
Error - Sale ID "AUC001" already exists in the system!
IMPORTANT NOTE: You should not need to define another array or JCF collection to store Auction objects in, as the existing array / collection of Sale references from Stage 2 can also store Auction objects.
B) Submit Offer Feature:
This feature should begin by prompting the user to enter the sale ID of the sale they wish to submit an offer for - once the user has entered the sale ID the feature should then attempt to locate the corresponding sale object within the array / collection of Sale references described above.
Example 1:
Enter Sale ID: AUC001
Current offer: $0
Enter new offer: 400000
Enter Bidder Name: Rodney
Offer accepted! (offer is below reserve price)
Example 1:
Enter Sale ID: AUC001
Current offer: $0
Enter new offer: 700000
Enter Bidder Name: Rodney
Offer accepted! (reserve price has been met/exceeded)
C) Close Auction Feature
This feature should prompt the user to enter the sale ID of the auction which is to be closed, after which it should proceed to locate the corresponding object in the array/collection of sale / auction objects described in requirement A) above,
If a matching object with the specified sale ID was not found then a message should be displayed to the screen indicating that the sale id was invalid.
Example:
Enter ID of Auction to be closed: AUC003
Error - property sale ID AUC003 not found!
If the object with the specified sale ID is not an Auction object then a message should be displayed indicating that the sale was not an auction
Example:
Enter ID of Auction to be closed: SAL001
Error - property sale ID SAL001 is not an auction!
If an Auction object with the specified ID was found then that Auction should be closed (by calling the closeAuction() method in a suitable fashion) - the feature should check the result returned from this call to the closeAuction() method to see if it worked or not and a suitable success/failure message should be displayed accordingly.
Example 1:
Enter ID of Auction to be closed: AUC001
Auction AUC001 has ended - property has been: PASSED IN
Example 2:
Enter ID of Auction to be closed: AUC001
Auction AUC001 has ended - property has been: SOLD
Define your own exception type OfferException which represents an issue that occurs when attempting to make an offer for a Sale.
A) Creating the Exception Class
This OfferException type should allow a suitable error message to be specified when a new OfferException object is created.
B) Generating Exceptions
Update the makeOffer() methods in the Sale and Auction classes, so that an OfferException containing a suitable error message is generated and thrown when an offer has been rejected.
This will initially require the rewriting of the program logic in the makeOffer() methods described in the specifications of the Sale and Auction classes described in stages 1 and 3, so that an OfferException is thrown if the acceptingOffers flag is not currently true (indicating that the sale is not open for offers) OR when the new offer price is less than the current offer price.
Once you have done so there will not be any need to return a value indicating the success or failure of the attempted operation, so the return type for these makeOffer() methods should also be changed to void.
C) Handling Exceptions
This OfferException should then be allowed to propagate back up to the RealEstateSystem class (ie. the exception should not be caught locally within the makeOffer() method(s)), where it will need to be caught and handled in an appropriate manner (by displaying the error message contained within the OfferException object that has propagated up from the relevant method call).
Your program should incorporate file handling functionality so that it writes the details for each sale object currently in the Real Estate System out to file when the program terminates (i.e. when the user selects the Exit option in the menu).
The data that was previously written out to file should then be read back in automatically when the program is started up again and the Sale information within should be used to create an appropriate set of Sale and Auction objects, which should be stored in the array or collection of Sale references described in Stage 2 above.
If the sale data file is not found in the local folder then the program should:
The sale data should be written out to and read in from (the same) text file (containing the details for both Sale and Auction objects in the Real Estate System). The format that you write sale data out in is entirely at your own discretion as long as it is done to a text file (strategies for handling the writing and reading of data for different types of objects will be discussed during week 09).
One aspect of this task is to record any changes that have been made during the previous run of the RealEstateSystem application, so your file handling functionality must be able to handle the writing out and reading in of all details for both types of sale in such a way that the state of the RealEstateSystem at the point where the program was last exited is reconstructed in full when the program is started up again.
You can make any changes or include any additional methods that you deem necessary to the Sale / Auction classes to facilitate the writing out and reading in of details for both sale types to satisfy this part of the specification.