Question
// java //1.Class Q3_Ticket_manager package ticket; import java.util.TreeMap; public class Q3_Ticket_Manager { public static void main(String[] args) { new Q3_Ticket_Manager().manage(); } // Constants used to
// java
//1.Class Q3_Ticket_manager
package ticket;
import java.util.TreeMap; public class Q3_Ticket_Manager { public static void main(String[] args) { new Q3_Ticket_Manager().manage(); } // Constants used to display menu options, and figure out what user entered. static final int ADD_TICKET = 1; static final int SEARCH_BY_ID = 2; static final int DELETE_BY_TICKET_ID = 3; static final int SHOW_NEXT_TICKET = 4; static final int SHOW_ALL_TICKETS = 5; static final int QUIT = 9; // Global objects - the data stores, and the user interface TicketStore ticketStore = TicketStore.getInstance(); TicketUI ticketUI = new TicketUI(); // TODO Q5 create a ResolvedTicketStore object // Write and read to files in this directory. The tests will use a different directory, but same filenames. static String ticketDataDirectory = "TicketData"; void manage() { TreeMapoptions = configureMenuOptions(); loadTickets(); boolean quit = false; while (!quit) { int userChoice = ticketUI.showMenuGetChoice(options); switch (userChoice) { case ADD_TICKET: menuOptionAddTicket(); break; case SEARCH_BY_ID: menuOptionSearchById(); break; case DELETE_BY_TICKET_ID: menuOptionDeleteById(); break; case SHOW_NEXT_TICKET: menuOptionShowNextTicket(); break; case SHOW_ALL_TICKETS: menuOptionDisplayAllTickets(); break; case QUIT: menuOptionQuitProgram(); quit = true; } } } protected void menuOptionAddTicket() { // Get ticket data from user interface Ticket newTicket = ticketUI.getNewTicketInfo(); // Add to the ticket store ticketStore.add(newTicket); ticketUI.userMessage("Ticket added to the ticket queue"); } protected void menuOptionSearchById() { int ticketID = ticketUI.getTicketID(); Ticket ticket = ticketStore.getTicketById(ticketID); if (ticket == null) { ticketUI.userMessage("No ticket found with that ID"); } else { ticketUI.displayTicket(ticket); } } protected void menuOptionDeleteById() { // Get a ticket ID int ticketID = ticketUI.getTicketID(); Ticket toDelete = ticketStore.getTicketById(ticketID); ticketUI.displayTicket(toDelete); deleteTicketById(ticketID); } protected void menuOptionShowNextTicket() { Ticket next = ticketStore.peekNextTicket(); ticketUI.displayTicket(next); } protected void menuOptionDisplayAllTickets() { ticketUI.displayTickets(ticketStore.getAllTickets()); } protected void menuOptionSearchByDescription() { // TODO problem 3 implement this method. // Use TicketUI getSearchTerm method to ask user for search term e.g. "server" or "powerpoint" // Create a method in TicketStore to get list of matching Tickets for a search term; // this method should return a list of all tickets which contain the user's // search term in their description // Use TicketUI displayTickets method to print the list of matching tickets } protected void menuOptionDeleteTicketByDescription() { // TODO problem 4 implement this method. // Ask user for search term e.g. "server" // If there are matching tickets, use TicketUI to ask user which ticket ID to delete; // call deleteTicketById(ticketID) to delete the ticket. // else, use TicketUI to show user 'not found' message } protected void menuOptionQuitProgram() { //TODO Problem 6 use the TicketFileIO methods to save all open tickets to a file //TODO Save all resolved tickets to a separate file containing today's filename //TODO save the ticket ID counter so when the program re-opens, it does not reset to 1 // Make sure you save all of your files in the directory given by String ticketDataDirectory = "TicketData"; } protected void loadTickets() { //TODO problem 7 load open tickets from a file, using your new TicketFileIO class //TODO Configure ticketIDCounter // Read your files from the directory given by ticketDataDirectory = "TicketData"; } protected void deleteTicketById(int ticketID) { // TODO problem 5 use TicketUI to get the resolution for this Ticket // This method will be called by menuOptionDeleteTicketByDescription and menuOptionDeleteById // Save the resolution and the current date in this Ticket // add it to the ResolvedTicketStore object. if (ticketUI.areYouSure("Delete the above ticket, are you sure?")) { boolean deleted = ticketStore.deleteTicketById(ticketID); if (deleted) { ticketUI.userMessage("Ticket deleted"); } else { ticketUI.userMessage("Ticket with this ID not found in the ticket queue"); } } else { ticketUI.userMessage("No ticket deleted."); } } private TreeMap configureMenuOptions() { TreeMap options = new TreeMap<>(); options.put(ADD_TICKET, "Add new ticket"); options.put(SEARCH_BY_ID, "Search by ticket ID"); options.put(DELETE_BY_TICKET_ID, "Delete by ticket ID"); options.put(SHOW_NEXT_TICKET, "Show next ticket in ticket queue"); options.put(SHOW_ALL_TICKETS, "Show all open tickets"); options.put(QUIT, "Save and quit"); return options; } }
==========================================
//2. class ResolvedTicketStore
package ticket; import java.util.LinkedList; public class ResolvedTicketStore { private static LinkedListresolvedTickets; private static ResolvedTicketStore instance; private ResolvedTicketStore() { resolvedTickets = new LinkedList (); } public static ResolvedTicketStore getInstance(){ if (instance == null) { instance = new ResolvedTicketStore(); } return instance; } public void addTicket(Ticket t) { resolvedTickets.add(t); } public LinkedList getAll() { return resolvedTickets; } }
============================================================================================
// 3. Class Ticket
package ticket; import java.util.Date; public class Ticket { private int priority; private String reporter; //Stores person or department who reported problem private String description; private Date dateReported; //TODO 1: Make sure you understand how ticketIdCounter and ticketID interact. Why is ticketIdCounter static and ticketID is not? //STATIC Counter - one variable, shared by all Ticket objects. //If any Ticket object modifies this counter, all Ticket objects will have the modified value //Make it private - only Ticket objects should have access private static int ticketIdCounter = 1; //The ID for each ticket - an instance variable. Each Ticket will have it's own ticketID variable private int ticketID; // TODO 6: tickets need to store the resolution Date and a String describing the resolution public Ticket(String desc, int p, String rep, Date date) { this.description = desc; this.priority = p; this.reporter = rep; this.dateReported = date; this.ticketID = ticketIdCounter; ticketIdCounter++; // Increment ticketIDCounter so the next ticket's number is one higher } // TODO 7: add your constructor to create a Ticket from existing Ticket data read from a file // TODO 7: Ensure that every new Ticket created has a unique ID, even if the program is closed and restarted public void setPriority(int priority) { this.priority = priority; } public String getReporter() { return reporter; } public void setReporter(String reporter) { this.reporter = reporter; } public void setDescription(String description) { this.description = description; } public Date getDateReported() { return dateReported; } public void setDateReported(Date dateReported) { this.dateReported = dateReported; } protected int getPriority() { return priority; } public int getTicketID() { return ticketID; } public String getDescription() { return description; } public String toString(){ return("ID: " + this.ticketID + " Description: " + this.description + " Priority: " + this.priority + " Reported by: " + this.reporter + " Reported on: " + this.dateReported); } // TODO you may want to add a method to generate a String representing this Ticket, suitable // for writing to a file. Whatever you write out, should be able to be read and turned back into a Ticket object. }
=================================================================================================================
//4. class TicketStore
package ticket; import java.util.LinkedList; import java.util.Comparator; /** * A data structure to store Tickets in memory as the program runs * Stores tickets in priority order, so tickets with priority 5 are at the start * If more than one ticket with same priority, oldest tickets are before newer tickets * Supports add, delete, search operations on the list of Tickets * * * Implemented as a Singleton - there can only ever be one TicketStore. * If you want to work with the TicketStore, call TicketStore.getInstance() * */ public class TicketStore { private LinkedListticketQueue; private static TicketStore instance; private TicketStore() { ticketQueue = new LinkedList<>(); } public static TicketStore getInstance() { if (instance == null) { instance = new TicketStore(); } return instance; } /** Add all of the tickets in a list to the Ticket Queue, in priority order. * @param tickets a list of tickets. */ public void addAll(LinkedList tickets) { ticketQueue.addAll(tickets); ticketQueue.sort(ticketComparator); } /** Add ticket, and then sort list to keep the highest-priority at the top of the queue. * @param newTicket the new Ticket to add. */ public void add(Ticket newTicket) { ticketQueue.add(newTicket); ticketQueue.sort(ticketComparator); } /** Returns all tickets in the queue. * * @return All the tickets. */ public LinkedList getAllTickets() { return ticketQueue; } /** Returns, but does not remove, the tickets from the top of the TicketQueue * @return the ticket at the top of the queue */ public Ticket peekNextTicket() { return ticketQueue.peek(); } /** How many currently open tickets in the list? * @return the number of open tickets */ public int ticketsInQueue() { return ticketQueue.size(); } /** Searches store for ticket with given ID. * @param id The ticket ID * @return The ticket with this ID, if found; null otherwise */ public Ticket getTicketById(int id) { for (Ticket t : ticketQueue) { if (t.getTicketID() == id) { return t; } } return null; // If ticket with this ID is not found } /** Delete a single ticket by ticket ID. * @return true if a ticket was found and deleted, false if a ticket with this ID is not in the queue */ public boolean deleteTicketById(int deleteID) { //Loop over all tickets. Delete the one with this ticket ID for (Ticket ticket : ticketQueue) { if (ticket.getTicketID() == deleteID) { ticketQueue.remove(ticket); return true; } } // Not found? Return false return false; } /** Create a list of tickets, with a description containing * the given String. The search is not case sensitive. * @param description Text to search for in Ticket descriptions * @return a list of matching Tickets. If no matches, return an empty list. */ public LinkedList searchByDescription(String description) { //TODO problem 3, implement this method return null; } /** Remove all tickets from the Ticket queue */ public void removeAll() { ticketQueue.clear(); } // This is to sort tickets with highest priority first // If two tickets have the same priority, oldest first private Comparator ticketComparator = new Comparator () { @Override public int compare(Ticket t1, Ticket t2) { //Joint equal priorities, sort with oldest first if (t1.getPriority() == t2.getPriority()){ return t1.getDateReported().compareTo(t2.getDateReported()); } else { // Sort with smallest priority number at the start return t1.getPriority() - t2.getPriority(); } } }; }
===================================================================================================
//5. Class TicketUI
package ticket; import java.util.Date; import java.util.LinkedList; import java.util.TreeMap; import static input.InputUtils.intInput; import static input.InputUtils.stringInput; import static input.InputUtils.yesNoInput; public class TicketUI { /** User interaction - user input and printing - for the ticket manager */ protected int showMenuGetChoice(TreeMapallOptions) { while (true) { for (int option : allOptions.keySet()) { System.out.println(String.format("%d: %s", option, allOptions.get(option))); } int task = intInput("Enter your selection"); // If the user's option is in the map's key set, it's a valid choice. Return it. if (allOptions.keySet().contains(task)) { return task; } // Else, loop until user enters valid choice from the menu } } protected Ticket getNewTicketInfo() { Date dateReported = new Date(); //Default constructor creates Date with current date/time String description = stringInput("Enter description of the problem: "); String reporter = stringInput("Who reported this problem? "); // TODO Problem 2 ensure the priority is between 1 and 5 int priority = intInput("Enter priority of " + description); Ticket t = new Ticket(description, priority, reporter, dateReported); return t; } protected int getTicketID() { return intInput("Enter Ticket ID: "); } protected String getSearchTerm() { return stringInput("Enter text to search for: "); } protected boolean areYouSure(String question) { return yesNoInput(question); } protected void displayTickets(LinkedList tickets) { System.out.println(" ------- All tickets ----------"); for ( Ticket t : tickets ) { System.out.println(t); // This calls the toString method for the Ticket object. } System.out.println(" ------- End of ticket list ----------"); } public void userMessage(String s) { System.out.println(s); } public void displayTicket(Ticket next) { System.out.println(next); } }
====================================================================
INSTRUCTIONS
This program is a prototype to manage IT support tickets for a company. Users would call or email a helpdesk to report computer problems, and this program keeps a record of all current problems. Tickets need to store a description of the problem, the date the issue was reported, and the user who reported it. The tickets are assigned a priority between 1-5. 1 is the most urgent (e.g. all servers down) 5 is the least serious (e.g. missing mouse mat). Each ticket will have a unique integer ID. This is generated internally in the `Ticket` class. (We'll improve on this approach later in the semester when we cover databases.) When a problem is fixed, the ticket is removed from the list of open tickets and added to a separate list of resolved tickets. A String describing the resolution is stored in the Ticket, and the date the ticket was resolved. For this question, you'll add some features to the program. Run and test the program with some example support tickets. ### Problem 1: To think about: What is each class for? How are different responsibilities divided between the classes? If `TicketStore` used a database instead of an in-memory LinkedList, would `TicketUI` or `Question_3_Support_Ticket_Manager` have to do anything differently? Make sure you understand the role of the static and instance `ticketID` and `ticketIdCounter` variables in the Ticket class. Why are a static variable, and an instance variable, declared in the class? How are these used to create ID values for each ticket? ### Problem 2: Add a check to `TicketUI.getNewTicketInfo()` method, to ensure that the priority entered for a new ticket is between 1 and 5, inclusive. ### Problem 3: Add two new options to the menu: Delete by Description, and Search by Description. You'll need to add some more int constants; and modify the `configureMenuOptions` method; and modify the switch statement in `manage`. You *don't* need to modify TicketUI. Search By Description will search your ticket list and returns a new list of Tickets whose descriptions contain a certain String. For example, you might want to search for all tickets with the word server in the description. The search should NOT be case sensitive. Note that you should not modify the description when you save tickets. (So, the approach of saving all descriptions in lowercase or uppercase is not an acceptable solution for this problem.) Implement `TicketStore.searchByDescription` to search the list and return all matching tickets. If `TicketStore.searchByDescription` doesn't find any matches, return an empty list. If `TicketStore.searchByDescription` is called with an empty string, it should return an empty list. Implement Question_3_Support_Ticket_Manager.searchByDescription. Use the `getSearchTerm` method in TicketUI to ask the user for the search string. Use `TicketStore.searchByDescription` to search for matching tickets Use the `displayTickets` method in TicketUI to display all matching tickets. ### Problem 4: Implement Delete by Description. Follow the notes in `deleteTicketByDescription`. ### Problem 5: Modify the program so you can save information about deleted tickets. Your Ticket objects should be able to store another date; `resolvedDate`, the date the ticket was closed. And, a String that documents why the ticket was closed the fix or the resolution for the ticket. This String should be called `resolution` When a ticket is deleted, it has been resolved in some way. Either a technician fixed the problem, or the user has figured out how to change their own screensaver, or its become a non-issue in some other way. Now, when you delete a Ticket, your `deleteTicketById` method should ask for the resolution. It should store the resolution string , plus the current date in the correct Ticket. Now, remove this Ticket from the ticketQueue list. A ResolvedTicketStore class is provided for you. It stores resolved tickets in a list, and provides an `addTicket` method. Create a ResolvedTicketStore object when the program starts. When tickets are resolved, add the resolved ticket to your ResolvedTicketStore. Add any other resolved tickets created in this session to the ResolvedTicketStore. ### Problem 6: When the program is closed, all the data is lost. Add the ability to save all data to file. You can decide how to organize and structure the data in your files. Create a new class called `TicketFileIO` to manage the file input and output. Question_3_Support_Ticket_Manager will use methods in this class when the program starts and ends. Your `Question_3_Support_Ticket_Manager` should not do any file reading or writing. Delegate these tasks to your TicketFileIO class. When the program closes, write out all the data about all open tickets to one file in the **TicketData** directory of your project. Open tickets should be saved in a file called `open_tickets.txt`. Write all data about tickets that have been resolved in this session, to a separate file. Resolved tickets should go into one file, per day. This file should have todays date in the filename and be in the format of `resolved_tickets_February_20_2014.txt`. If you run the program twice on one day, make sure you don't overwrite existing tickets in that day's file. Use a static method with this name, and arguments, ``` /* Write the list of tickets to the file with the name provided. The append argument specifies what to do if the file already exists. If append=true, add data to the file If append=false, create a new file for this data. public static void saveTickets(LinkedListticketList, String fileName, boolean append) { // TODO implement this method } ``` Here's some code to generate today's date as a string in the correct format, ``` SimpleDateFormat filenameFormatter = new SimpleDateFormat("MMMM_dd_yyyy"); Date date = new Date(); //defaults to today, right now String s = filenameFormatter.format(date); // s will be in the format "September_28_2017" ``` ### Problem 7: When your program opens, it should look for a file called `TicketData/open_tickets.txt`. If this file exists, read in this file, and create Ticket objects, and store these in the TicketStore object list so the user can see all open tickets. Use a static method with this name and arguments. ``` /** Read a file, turn the data into Ticket objects, and return a list of Ticket objects */ public static LinkedListloadTickets(String fileName) { // TODO implement this method and return a LinkedList of Tickets } ``` You don't need to read in the previous resolved tickets, you only need to read the open tickets from the `open_tickets.txt` file What happens to ticket IDs when the program is closed and opened? Make sure they don't reset to 1 when the user restarts the program. Every ticket created should always have a unique positive integer ID, (excluding 0) no matter how many times the program is used*. If you save the ticket ID in a file, make sure it's also in the the **TicketData** directory. The tests will create a separate test directory and will read and write to this location, so if you keep all of your files in **TicketData** then the tests won't overwrite your files. You will need to create a second constructor for creating a tickets when the ID is already known. Make sure you don't break your mechanism for ensuring unique IDs. *Actually, you'll only be able to create approx 2 billion ticket IDs with this approach. That should be enough for now, although perhaps something that will be revisited in a future version using a relational database.
Step by Step Solution
There are 3 Steps involved in it
Step: 1
Get Instant Access to Expert-Tailored Solutions
See step-by-step solutions with expert insights and AI powered tools for academic success
Step: 2
Step: 3
Ace Your Homework with AI
Get the answers you need in no time with our AI-driven, step-by-step assistance
Get Started