PROGRAM 1



Clarifications

  • No "header node" doesn't mean that you don't have a head reference at all! It only means you are not using a dummy node as the "header node". There is still a "head" reference to your linked list.
  • Your cloud application will not require you to use the "tail" reference. But you should still implement "tail" reference in your DLinkedList class. This is for you to learn how the operations require special cases if you use both head and tail pointer.
  • addToMachineList() function: breaking ties between machines of same price. Add the new machine after the old machine, which has the same price. If there are multiple old machines with the same price, you should add the new one after all those old machines.
  • Machine toString() formatting issue: To get rid of the inconsistent output, program specifiction for toString() function, Machine.java skeleton and the sameple output file have been updated. See Piazza post if you are intersted in knowing what changes have been made.
  • Cloud class option "b" description has been updated to eliminate inconsistencies in display message format. Please note the "space" after "Machine not needed:". The sampleOutput.txt has been updated as well.
  • ListADT<E> interface's add(int pos,E item) function description updated to reflect "size()" position to be an acceptable position.
  • You can assume the following: if machines have the same machineName then other corresponding fields of the two machines must be the same. See this Piazza post for further details.
  • Cloud.java outline has been updated to reflect same function descript as in program webpage.
  • In the Cloud application commands, if you enter a partial version of the supported commands then print "Invalid Command" and keep running the application. For example, if you enter "v" instead of "v:all", then print "Invalid command".
  • Your output should match exactly with that of sampleOutput.txt even for v:instock command.
  • If in option b of Cloud application command is used and you were able to rent a machine successfully, then you should print "Rented <MACHINE-NAME>"


Overview

Goals

The goals of this assignment are to:

  • Gain experience writing Java interfaces and classes that implement them.
  • Understand and implement a doubly-linked chain of nodes.
  • Implement checked exceptions.
  • Gain experience working with Java references.

Description

Cloud platforms that allow users to rent / use machines are become very famous. These rentable machines are maintained by the cloud provider. Cloudlab is an example of one such service; UW-Madison is one of the cloud providers for cloudlab. As the user, you will have a set of machines in your list, you can rent them if they are available. You will be using multiple linked lists to track the users of such a system, the machines that are available for renting, current list of machines that a user wants to rent and so on.

Your program will simulate the basic user experience allowing users to select what they'd like to add to their machinelist. Following are description of components of the program that will be initialized at program start up and will not be modified further:

  • The list of machines.
  • The list of users.
  • Fixed credit for each user to rent machines.

Users are then allowed to add and remove machines from their list. The items in a users machinelist are ordered by price from highest to lowest. The program enables a users to login to their account, view all the items in the cloud, add items to or remove items from their machinelists, and rent items on their machinelists that are in stock.

The main class Cloud prompts the user to login. It then enables the user to enter the required operation that can manipulate the machinelist of machines. Machinelists will be represented using a DLinkedList class that you will also write. Your DLinkedList class implements the ListADT interface using a doubly-linked chain of nodes. You will also implement a checked exception - InsufficientCreditException class which will be used to signal and handle problems when a user doesn't have enough credit to rent a machine. You will also be writing the User and Machine classes that track users and machines.

Specifications


The ListADT<E> Interface


A ListADT<E> interface, provided to you (see ListADT.java), is a generic interface that you will implement in your DLinkedList class. The interface describes the following methods:

Note: If a method throws two exceptions, follow the order as given in this specification and in the interface method header.
Method Description
void add(E item) Adds item to the end of the List.
Throws IllegalArgumentException if item is null.
void add(int pos,E item) Adds item at position pos in the List, moving the items originally in positions pos through size() - 1 one place to the right to make room.
Throws IllegalArgumentException if item is null and IndexOutOfBoundsException if pos is less than 0 or greater than size().
boolean contains(E item) Returns true iff item is in the List (i.e., there is an item x in the List such that x.equals(item))
Throws IllegalArgumentException if item is null or list is null.
E get(int pos) Returns the item at position pos in the List.
Throws IllegalArgumentException if list is null and IndexOutOfBoundsException if pos is less than 0 or greater than or equal to size().
boolean isEmpty() Returns true iff the List is empty.
E remove(int pos) Removes and returns the item at position pos in the List, moving the items originally in positions pos+1 through size() - 1 one place to the left to fill in the gap.
Throws IllegalArgumentException if list is null and IndexOutOfBoundsException if pos is less than 0 or greater than or equal to size()
int size() Return the number of items in the List.

Do not modify the ListADT interface in any way.

The DLinkedList<E> Class


Following are some specifications about the DLinkedList class that implements ListADT interface:

  • The doubly linked list does not use a header node. While implementing the methods, think about all the special cases that you need to be handling.
  • The doubly linked list uses a tail reference. Keep in mind that the tail reference needs to be updated accordingly after each operation.
  • Do not add any public methods to your DLinkedList class other than those in the ListADT interface and do not add any public fields.
  • Your DLinkedList will be using DblListnode to create the doubly linked list.

The DblListnode<E> Class


The DblListnode<E> class represents one node of a DLinkedList. This class is also provided to you (see DblListnode.java). It has the following methods and constructors:

Constructor Description
Listnode<E>(E data) Constructs a Listnode<E> with data and anull reference to its previous and next nodes.
Listnode<E>(E data, Listnode<E> next, Listnode<E> prev) Constructs a Listnode<E> with data and references to prev and next nodes.
Method Description
E getData() Returns the data cloudd in this node.
Listnode<E> getNext() Returns the Listnode<E> that comes after this Listnode<E>. Returns null if this node does not have a next node.
Listnode<E> getPrev() Returns the Listnode<E> that comes before this Listnode<E>. Returns null if this node does not have a previous node.
void setData(E data) Sets the data cloudd in this node to data.
void setNext(Listnode<E> next) Sets the next node to reference next Listnode<E>.
void setPrev(Listnode<E> prev) Sets the previous node to reference prev Listnode<E>.

Do not modify the Listnode class in any way.


The Machine Class


The Machine class represents a single Machine in the cloud platform. A shell of this class is also provided for you (see Machine.java). It has the following methods and constructor:

Constructor Description
Machine(String machineName, int numCPUs, int memorySize, int diskSize, double price) Constructs a Machine with a machineName, numCPUs, memorySize, diskSize and price.
Method Description
String getName() Returns the name of the machine.
int getCPUs() Returns the number of CPU's of the machine.
int getMemorySize() Returns the RAM size in GB's.
int getDiskSize() Returns the hard disk size in GB's.
double getPrice() Returns the price of the machine.
String toString() Returns a String of this Machine's information in the following format:<NAME> [Number of CPU's: <CPUs>, RAM size: <RAM>, Disk size: <DISK>] [Price: $<PRICE>]
For example, "Ubuntu1 [Number of CPU's: 16, RAM size: 8, Disk size: 200] [Price: $2000.0]"

Do not add any public methods or fields to the Machine class.


The User Class


The User class should use your DLinkedList class to build a machinelist of machines ordered by price from highest to lowest. A shell of this class is also provided for you (see User.java), you must implement all the methods.

User has the following methods and constructor:

Constructor Description
User(String name, String password, int credit) Constructs a User instance with a name, password, credit and an empty machinelist.
Method Description
boolean checkLogin(String username, String passwd) Checks if the credentials provided match this user's credentials.
Return true if credentials correct, false otherwise
Throws IllegalArgumentException if arguments are null.
void addToMachineList(Machine machine) Adds the machine to the user's machinelist.
Maintains the order of the machinelist from highest priced to lowest priced machines.
Throws IllegalArgumentException if arguments are null.
Machine removeFromMachineList(String machineName) Removes a machine from the user's machinelist. Do not charge the user for the price of this machine.
Return the machine on success, null if no such machine found.
Throws IllegalArgumentException if arguments are null.
void printMachineList() Print each machine in the user's machineList in its own line by using the machine's toString function.
boolean rent(String machineName) Rents the specified machine in the user's machinelist. Charge the user according to the price of the machine by updating the credit and removing the machine from the machinelist.
Throws an InsufficientCreditException if the price of the machine is greater than the credit available.
Throw the exception with a message using this format: Insufficient credit for <username>! Available credit is $<credit>.
Returns true if successfully bought, false if machine not found
double getCredit() Returns the credit of the user.
ListADT<Machine> generateMachineStock() Declare the first N items in the currentUser's machinelist to be in stock
N is generated randomly between 0 and size of the machinelist
This method has already been implemented for you
returns list of machines in stock

Do not add any public methods or fields to the User class.


The InsufficientCreditException Class


Below are the specifications for this class:

  • Code a checked exception class to be used by your implementation of User to signal when the user tries to rent an item but doesn't have enough credit.
  • Write the default constructor.
  • You should also write the constructor that enables you to pass a String message.
  • Your main program should catch this exception when it happens and display the following: "For rentingi <MACHINE-NAME>: <EXCEPTION-MESSAGE>". Use the getMessage() function for this purpose. Finally, proceed with processing the user input for the commands.

The Cloud Main Class


The application program, Cloud contains a list of machines, a list of users and keeps track of the current user logged in. A shell of this class is also provided for you (see Cloud.java). The static methods are outlined below which you need to implement in order for the Cloud to work correctly.

User login(String username, String passwd) Tries to login for the given credentials. Updates the currentUser if login successful.
Returns the currentUser
void loadMachines(String fileName) Reads the specified file to create and load machines into the cloud.
Every line in the file has the format: <MACHINE NAME>#<NUMBER OF CPU's>#<MEMORY SIZE>#<DISK SIZE>#<PRICE>
Create new machines based on the attributes specified in each line and insert them into the machines list
Order of machines list should be the same as the machines in the file
For any problem in reading the file print: 'Error: Cannot access file'
void loadUser(String fileName) Reads the specified file to create and load a user into the cloud.
The first line in the file has the format:<NAME>#<PASSWORD>#<CREDIT>
Every other line after that is the same format as the machines file: <MACHINE NAME>#<NUMBER OF CPU's>#<MEMORY SIZE>#<DISK SIZE>#<PRICE>
For any problem in reading the file print: 'Error: Cannot access file'
void printMachines() The order of the machines should be the same as in input machines file. The output format should be the consolidated String format mentioned in Machine class.

Loading the Data:

  • The first step the application does is to load machines and users into the cloud which are read from text files specified in command line arguments.
  • The first command line argument specifies the Machine file and every argument after that is a User file.
  • Once the machines and users are initialized in the cloud object the program asks the user to login.
  • After login the user is allowed to make several commands listed below. Your job is to modify the userMenu method to implement the commands listed below. The userMenu() method is passed in a list of Machines called inStock which are in stock machines generated before each login.

The Cloud application commands are:

Command format Description
v:all Print all machines in the cloud. See printMachines() method of cloud.
v:machinelist For the current user print all machines in their machinelist. The order is the same as the machinelist.
v:instock Print all machines in the inStock list.
s:string Search for the String string in all of the machine names in the cloud and print out all the matching machines.
Print format for each machine is the same as specified in the toString method of Machine
For no matching machines, print nothing.
a:machineName Add the Machine whose name is specified by machineName to the user's machinelist.
Print "Machine not found" if no such machine.
r:machineName Remove the Machine whose name is specified by machineName from the user's machinelist.
Print "Machine not found" if no such machine.
b Rent the Machines shown to be in stock by the list inStock. This removes them from the user's machinelist and charges the user for it.
While doing the rent operation, check whether the machine in inStock is actually there in the user's machine list.
If the user has insufficient credit, print out: "For renting <MACHINE-NAME>: Insufficient credit for <PRODUCT-NAME>! Available credit is $<credit>" and proceed with processing the user input for the commands again.
If rent operation was not successful because of machine not being on machinelist, then print "Machine not needed: <MACHINE-NAME>"
If rent operation was successful, then print "Rented <MACHINE-NAME>"
c Shows the credit of the current user as $<CREDIT>.
l Logs out the current user and goes back to the login screen.

Items in stock:

  • A user can only rent items that are in stock. Every time a user logs in, the top N machines on his machinelist are declared to be in stock.
  • We have already provided this implementation in the skeleton using the method generateStock of the User class.
  • The N items are generated and made available for you to use in accordance with the program specifications
  • Before you rent a machine that is inStock, confirm that the user's machinelist has that machine. This will make a difference to successive rent operations.

Implement each command listed above. Your code uses your DLinkedList, User , Machine, and InsufficientCreditException classes, where appropriate. In addition to the command descriptions listed above, if the program user inputs an invalid command display the error message "Invalid Command" and allow them to enter a new command.

Steps

After you have read this program page and given thought to the problem we suggest the following steps:

  1. You may use the Java development environment of your choice in CS 367. However, all programs must compile and run on the lab computers for grading.
  2. Download the following to your programming assignment 1 directory:
  3. Incrementally implement and thoroughly test your DLinkedList<E> class. It might help to test on simple objects like Integers first.
  4. Incrementally implement and thoroughly test your Machine and User classes.
  5. Incrementally implement the Cloud class as specified in the main program section above. Test each step to ensure your program is working correctly before implementing the next step. Create small text files for testing (it will be easier to debug than larger ones) and make sure you test all the boundary and negative cases.
  6. Download these sample Machine and User files, Machines.txt, User1.txt, User2.txt, and make sure your program produces the exact same output as given in the sampleOutput.txt. except for v:instock command, which is going to be giving random output. The further buy, add and remove commands output will also depend on the machines available to rent inStock.
  7. If you are not using the lab computers to develop your program, make sure you compile and run your program to ensure that it works on the Linux lab computers. You can compile your Java source using javac in a terminal window as in this example: javac -cp . *.java and the run your program using java as in: java -cp . Cloud Machines.txt User1.txt User2.txt
  8. Submit your work for grading.

  9. SUBMISSION

    • Make sure your code follows the style and commenting standards. You should write appropriate private methods, instead of repeating the same code inside multiple public methods.
    • Follow the submission instructions from Programs page
    • For this pogram, you need to turn in the following files:
      • "Cloud.java" containing your Cloud application program,
      • "DLinkedList.java" containing your implementation of the DLinkedList<E> class,
      • "InsufficientCreditException.java" containing your implementation of the InsufficientCreditException" class
      • "Machine.java", containing your working Machine class
      • "User.java", containing a DLinkedList machinelist and enforcing correct order properties on it
      • "*.java" additional classes that you've implemented for your program.