3 — Adopting Pets
Due Thursday, 25 January 2024, 11:59:59pm
Purpose
The purpose of this milestone is to implement a portion of the primary functionality of the Husky Animal Lovers Park.
A client enters the shelter;
They walk through, viewing one animal at a time;
If an animal seems like a potential match, the client can take the animal out of its enclosure to get to know them better, and return them after a time;
Finally, when everything works out, they can request to adopt their new furry best friend.
3.1 Adoption Protocol
To enable these potential interactions at HALP, you will create classes that implement a protocol between three parties: the client, the shelter, and an object representing a particular client’s progress through their visit.
Client ShelterEntry |
| | |
| | |
| viewAnimals() | |
|------------------------------------->| |
| PetViewer | |
|<=====================================| |
| | |
| | |
In this diagram, the dashed arrow (–>) represents the party on the left calling a method of the object on the right, and the double-dashed (<==) represents the method’s return and its result type, if any.
They call the viewNext method to look at the next pet, if there are any remaining available that they have not seen yet.
If viewNext returns Optional.empty(), the client has viewed all available pets and the interaction is over. (If the client wants they can call viewAnimals again to get another PetViewer.)
If the result of viewNext is not empty, then the client may optionally call the tryPlay method to request a one-on-one interaction with the animal. Since it’s possible another client may have taken the animal out of its enclosure in the meantime, either by calling tryPlay or tryAdopt, the method returns a boolean. A true value indicates that the client succeed in taking the animal out for some play time.
If everything goes well, the client can request to adopt the current animal by calling the tryAdopt method. Like for tryPlay, the animal may no longer be available for adoption. The method returns true if the adoption succeeded and false otherwise.
If adoption succeeded, the interactions between the client and the PetViewer are finished.
Otherwise, the client may repeatedly call viewNext. If they had previously taken an animal to play with, a call to viewNext implies that they have returned that animal to its (temporary) home.
At any point, the client may call the finished method on the PetViewer, indicating that they are done looking at the animals (at least for now). Like above, a call to finished implies that they have returned that animal to its (temporary) home.
The following diagram represents the core of these interactions:
Client PetViewer |
| | |
| | |
+->| viewNext() | |
| |------------------------------------->| |
| | Optional<AdoptablePet> | |
| |<=====================================| |
| | | |
| | if result is not empty: | |
| | | |
| | | |
| | (optionally) | |
| | | |
| | tryPlay() | |
| |------------------------------------->| |
| | boolean | |
| |<=====================================| |
| | | |
| | | |
| | (optionally) | |
| | | |
| | tryAdopt() | |
| |------------------------------------->| |
| | boolean | |
| |<=====================================| |
| | | |
| | | |
+--|(unless adoption succeeded) | |
| | |
The first task is to design and implement classes implementing the ShelterEntry and PetViewer interfaces. These interfaces are provided to you below (see Interfaces). Your implementation should take whatever steps necessary to ensure it is safe to use with numerous concurrent clients.
No client can view, play with, or adopt a pet while another client is playing with that animal.
Likewise, once an animal is adopted by one client, no other clients can interact with it.
Multiple clients may view the same animal at the same time (assuming none have taken it out of its enclosure.)
3.2 Initialization and Connecting Clients
public static ClientEntry initialize(Reader configReader) { |
... |
} |
This method will be called with a Reader from which you can obtain the JSON Configuration.
The returned ClientEntry is an object that allows clients to connect to the system. It has one method:
void connectClient(Consumer<ShelterEntry> client); |
The connectClient method simply passes a ShelterEntry to a client Consumer to interact with according to the above protocol. However, connectClient should create and run a Thread for each client.
This setup mimics the behavior we would use to allow clients to connect over a network but avoids a great deal of the ceremony and boilerplate doing so would require.
3.3 Interfaces
The attached interfaces for AdoptablePet, ClientEntry, PetViewer, and ShelterEntry correspond to the protocols described above. Also: the PetType enum. Include them in your project under the com.neu.halp.client package. Do not modify them.
3.4 Testing Task
To aid in testing, implement (at least one) potential client behavior. The client will eagerly try to adopt a pet. It should optain a PetViewer and try to meet then adopt a pet as quickly as it can. The test client will report a result, an Optional<AdoptablePet> describing the pet it managed to adopt (if any). Concretely, it should:
Obtain a PetViewer;
Call viewNext;
If the result of viewNext is present, call tryPlay; otherwise stop with an Optional.empty result.
If tryPlay succeeds, call tryAdopt;
If tryAdopt succeeds, stop;
Otherwise, go back to step 2;
Finally, the client will take a parameter describing its patience—
Implementation Task
Implement the com.neu.halp.test.EagerClientFactory class. The class must include the following public methods:
public EagerClientFactory() { |
... |
} |
public TestClient newClient(int patience) { |
... |
} |
Interface
getFinished, reporting a boolean that returns true if the client is finished running; and
getResult, returning an Optional<AdoptablePet> describing either the pet the client adopted, or is empty if no adoption attempt succeeded.
Include the interface in your project in the com.neu.halp.test package. Again, do not modify the interface.
3.5 Delivery
Your project should generate a JAR named Milestone2.jar Milestone3.jar (see
—