connecting two objects to each other - java

I've got these four classes.
What I'm trying to do is to add a "Liftcard" to a "User" by using the customerID. this is what I got so far, but it don't seem to work. Im pretty sure the problem is in the public void regLiftCard() method in the window class. Anyone got any idea what i should do?
(Im using arraylist)
User class:
public class User implements Serializable {
private String surename, firstName, gender, age;
private int customerID;
public LiftCard liftCard;
User next;
Same class:
public LiftCard getLiftCard(){
return liftCard;
}
public void setLiftCard(LiftCard liftC){
liftCard = liftC;
}
Window class:
public void regLiftCard()
{
int cardtype = Integer.parseInt(cardTypeField.getText());
int customerID = Integer.parseInt(findCustomerField.getText());
if(cardtype == 1 || cardtype == 2 || cardtype == 3 || customerID != 0)
{
//JOptionPane.showMessageDialog(this, "Du må fylle inn hvilket kort du skal ha 1/2/3");
try
{
User uu = userA.findById(customerID);
if (uu != null) {
if (uu.getLiftCard() != null) {
JOptionPane.showMessageDialog(this, "Kunden har allerede kort");
}
}
String fornavn = firstNameField.getText();
String etternavn = surenameField.getText();
String alder = ageField.getText();
String kjonn = genderField.getText();
LiftCard c = new LiftCard(cardNumber, cardtype);
if (userA.findByCardNumber(cardNumber) == null) {
uu.setLiftCard(c);
} else {
uu = new User(customerID, fornavn, etternavn, alder, kjonn);
}
JOptionPane.showMessageDialog(this, "Nytt kort/kunde er registrert");
} catch (NumberFormatException e) {
JOptionPane.showMessageDialog(this, "Feil i nummerformat!");
}
}
}
UserArchive class:
public void regLiftCard(User u) {
list.add(u);
}
Liftcard class:
private int cardNumber, cardType;
public LiftCard(int cN, int cT)
{
cardNumber = cN;
cardType = cT;
}
public int getCardNumber(){
return cardNumber;
}
public int getcardType(){
return cardType;
}
public String toString()
{
return cardNumber + "\t" + cardType;
}
}

I suppose you're trying to register a card to a unique User, so on regListCard:
You're looking for a user.
If the user is not null, you look for it's card.
If the card it's not null you're saying that this user already has a card.
Then, you get all the attributes input about the user and the card.
Then, you create a card.
Then, searchs for a user with this card and you set the card you created before to this user.
BUT, there's a possibility that the user you're assigning this card maybe null, because you're looking for a user by it's card, and if it's null, you assign this card to him which is not possible if he is null, and seems that here is the problem.
Then, if there are no user with this card, you are instantiating a new User, but not assigning any card.
So, put this:
else {
uu = new User(customerID, fornavn, etternavn, alder, kjonn);
uu.setLiftCard(c);
}
after this:
if (uu != null) {
if (uu.getLiftCard() != null) {
JOptionPane.showMessageDialog(this, "Kunden har allerede kort");
}
and get the inputs before the "if". Try it and tell us how it worked, and sorry if I do not understood your code.

Related

Variable cannot be resolved error in Java

I know this is a very very common error but I am stuck on this one and I totally don't understand why is it happening.
Here is a part of my code
import java.util.ArrayList;
import java.util.Scanner;
public class Manager {
private static Scanner sc = new Scanner(System.in);
protected static ArrayList<String> identifications = new ArrayList<String>();
protected static String[] signIn() {
System.out.println("Hi !");
System.out.println("Welcome to School Management System");
System.out.print("Please enter your ID number : ");
boolean idValid = false;
String providedID = null;
int idListPosition = -1;
do {
try {
providedID = sc.nextLine();
} catch (Exception e) {
System.out.println("Sorry there was an error. Please try again");
System.out.print("Please enter your ID number : ");
}
} while (providedID == null);
while (idValid != true) {
for (String element : identifications) {
if (element.equals(providedID)) {
idValid = true;
idListPosition = identifications.indexOf(element);
break;
}
}
if (idValid && idListPosition != -1) {
System.out.println("Welcome !");
String[] returnValue = {"true", identifications.get(idListPosition), identifications.get(idListPosition + 1), identifications.get(idListPosition + 2)};
return (returnValue);
} else {
System.out.println("Error : the ID you entered does not exist. Please try again");
providedID = null;
do {
try {
providedID = sc.nextLine();
} catch (Exception e) {
System.out.println("Sorry there was an error. Please try again");
System.out.print("Please enter your ID number : ");
}
} while (providedID == null);
}
}
}
public static void main(String[] args) {
init();
String[] response = signIn();
if (response[2].equals("teacher")) {
Teacher user = new Teacher(response[1], response[2], response[3]);
}
if (response[2].equals("student")) {
Student user = new Student(response[1], response[2], response[3]);
}
System.out.println(user);
while(true) {
System.out.println("For help type in help");
System.out.print("Enter a command : ");
String commandWanted = sc.nextLine();
if (commandWanted.equals("info")) user.showInfos();
}
}
protected static void init() {
identifications.add("056789");
identifications.add("teacher");
identifications.add("Temperson");
}
}
The Teacher and Student classes are empty for now. I just made them use the super constructor of their parent class Person :
public class Person {
String type;
String name;
String idNumber;
public Person(String idnumber, String newType, String providedName) {
this.idNumber = idnumber;
this.type = newType;
this.name = providedName;
}
protected String[] showInfos() {
String[] returnValue = {this.type, this.name, this.idNumber};
return returnValue;
}
}
But I get user cannot be resolved to a variable and user cannot be resolved error.
Normally the code that needs user will never run unless sign in has completed. And since sign in never ends before a correct ID is entered, the user variable will always be assigned to a a value.
Thanks for helping !
The scope of the user object is limited to the if condition, hence you are getting this error.
If Teacher and Student extends Person then you can try this piece of code:
public static void main(String[] args) {
init();
String[] response = signIn();
Person user = null;
if (response[2].equals("teacher")) {
user = new Teacher(response[1], response[2], response[3]);
}
if (response[2].equals("student")) {
user = new Student(response[1], response[2], response[3]);
}
System.out.println(user);
while(true) {
System.out.println("For help type in help");
System.out.print("Enter a command : ");
String commandWanted = sc.nextLine();
if (commandWanted.equals("info")) user.showInfos();
}
}
You're having a Scope problem here:
if (response[2].equals("teacher")) {
Teacher user = new Teacher(response[1], response[2], response[3]);
}
if (response[2].equals("student")) {
Student user = new Student(response[1], response[2], response[3]);
}
System.out.println(user);
Variables declared in a if block are local to that if block. You can see this in it's simplest form with an example like this:
if(true) {
String value = "Out of Scope";
}
System.out.println(value); //value cannot be seen outside the if block
You will need to declare your Teacher and/or Student variable outside the if block if you wish to use them after the block (this is where using your inheritance class would come in handy). Using the previous example:
boolean someCondition = true;
String value;
if(someCondition) {
value = "In Scope - True";
} else {
value = "In Scope - False";
}
System.out.println(value); //value can now be seen
You have declared 2 different versions of user, so the print statement can't know which you mean. Or it couldn't if it could see either, but since each is declared inside of its own block, the print doesn't see either of them.

How do I use contains to search through a custom object ArrayList for a particular string?

I'm completely brand new to programming (started yesterday...) and Java so excuse any stupid mistakes and really awful code (I have no clue how to order/format). I've been given a task to make an inventory of videos and I want to be able to search through the inventory to check if a particular video is there.
I know I can use contains to do this but I can't get it to work with my custom objects ArrayList (videos) and I want it to search through all the data (each InventoryRow below). I've overridden equals and HashCode but it still won't work - whenever I try to run the code it will always tell me it can't find the video even if the video is there. (FYI I use contains towards the end of my code under the rent and check functions)
I'd really appreciate any help as I've been googling all day to no avail. Also if this can't be done or another method would be better please let me know! Thanks.
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.*;
class InventoryRow {
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result
+ ((availability == null) ? 0 : availability.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
result = prime * result
+ ((returndate == null) ? 0 : returndate.hashCode());
result = prime * result + ((type == null) ? 0 : type.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;
InventoryRow other = (InventoryRow) obj;
if (availability == null) {
if (other.availability != null)
return false;
} else if (!availability.equals(other.availability))
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
if (returndate == null) {
if (other.returndate != null)
return false;
} else if (!returndate.equals(other.returndate))
return false;
if (type == null) {
if (other.type != null)
return false;
} else if (!type.equals(other.type))
return false;
return true;
}
private String name;
private String type;
private Character availability;
private String returndate;
public InventoryRow(String name, String type, Character availability,
String returndate) {
this.name = name;
this.type = type;
this.availability = availability;
this.returndate = returndate;
}
public String getReturndate() {
return returndate;
}
public void setReturndate(String returndate) {
this.returndate = returndate;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public Character getAvailability() {
return availability;
}
public void setAvailability(Character availability) {
this.availability = availability;
}
public String toString() {
return name + " " + type + " " + availability + " " + returndate;
}
}
public class InventorySort {
public static void main(String[] args) {
List<InventoryRow> videos = new ArrayList<InventoryRow>();
videos.add(new InventoryRow("Casablanca", "Old", 'Y', "1 January 2015"));
videos.add(new InventoryRow("Jurassic Park", "Regular", 'N',
"1 January 2015"));
videos.add(new InventoryRow("2012", "Regular", 'Y', "1 January 2015"));
videos.add(new InventoryRow("Ant-Man", "New", 'Y', "1 January 2015"));
// Another ArrayList because I can't seem to search through the first
// one?
/*ArrayList<String> names = new ArrayList<String>();
names.add("Casablanca");
names.add("Jurassic Park");
names.add("2012");
names.add("Ant-Man");*/
Scanner input = new Scanner(System.in);
// Output the prompt
System.out.println("What do you want to do?");
// Wait for the user to enter a line of text
String line = input.nextLine();
// List, rent and check functions
// List function
if (line.equals("l")) {
// Sort function
Collections.sort(videos, new Comparator<InventoryRow>() {
public int compare(InventoryRow o1, InventoryRow o2) {
return o1.getName().compareTo(o2.getName());
}
});
for (InventoryRow inventory : videos) {
System.out.println(inventory);
}
// Rent function
} else if (line.equals("r")) {
System.out.println("Which video would you like to rent?");
String line2 = input.nextLine();
// Search through ArrayList
if (videos.contains(line2)) {
System.out.println("Video available to rent!");
} else {
System.out.println("Video unavailable to rent.");
}
// Check function
} else if (line.equals("c")) {
System.out
.println("Which video would you like to check is in the inventory?");
String line3 = input.nextLine();
// Search through ArrayList
if (videos.contains(line3)) {
System.out.println("Video found!");
} else {
System.out
.println("Video not found. Please see the inventory below.");
Collections.sort(videos, new Comparator<InventoryRow>() {
public int compare(InventoryRow o1, InventoryRow o2) {
return o1.getName().compareTo(o2.getName());
}
});
for (InventoryRow inventory : videos) {
System.out.println(inventory);
}
}
// If anything else is entered
} else {
System.out
.println("The only options are to list (l), rent (r) or check (c).");
}
}
}
You can use contains. But, for the first day of programming, it might be more understandable to simply iterate over your inventory, comparing the input string with the video name:
boolean foundIt = false;
for (InventoryRow ir : videos) {
if (line3.equals(ir.getName())) {
foundIt = true;
break;
}
}
if (foundIt) {
System.out.println("Video found!");
Alternative to #kilo answer, you could implement equals and hashcode method only on the name of video class and check it in the following way.
String line3 = input.nextLine();
// Search through ArrayList
if (videos.contains(new Video(line3, null, null, null))) {
System.out.println("Video found!");
}
This will return contains = true only if the name matches.

Using Command pattern for undo and redo in ArrayLists

So I have a program where you can log in and add/remove friends to and from the friends arraylist. Also I can like a certain thing and that thing will be stored into the likes arraylist. I'm asked to make undo and redo options for whichever action I do.
So I want to add apple as a friend. After that when I select the undo option, I can undo that action so apple wouldn't be my friend. How I can approach this with a Command Pattern when the input is whatever name or word I inputted to store into the friends arraylist?
I did some research and found that using a command pattern could be my best bet since this has to be done under the Facebook Class I already have. I'm assuming I'll have to use two different stacks, but I'm getting a bit lost in the topic.
I decided to add parts of what I have so that I can get a bit more help on what I need to do and what my program does.
In the driver program
Facebook facebook1 = new Facebook();
if (userInput == 6)
{
System.out.println("Login");
String operand1 = getOperand("What is the Username? ");
String operand2 = getOperand("What is the Password? ");
System.out.println("Enter a friend to be added. ");
String operand3 = getOperand("What is the Username? ");
facebook1.friend(operand3);
}
if (userInput == 7)
{
System.out.println("Login");
String operand1 = getOperand("What is the Username? ");
String operand2 = getOperand("What is the Password? ");
System.out.println("Enter a friend to be removed. ");
String operand3 = getOperand("What is the Username? ");
facebook1.defriend(operand3);
}
if (userInput == 12)
{
System.out.println("Login");
String operand1 = getOperand("What is the Password? ");
facebook1.undo();
}
if (userInput == 13)
{
System.out.println("Login");
String operand1 = getOperand("What is the Password? ");
facebook1.redo();
}
In the Facebook Class
ArrayList<FacebookUser> recommendedFriends = new ArrayList<FacebookUser>();
void friend(String newFriend)
{
boolean positiveChecker = false;
for (int i = 0; i < recommendedFriends.size(); i++)
{
if (recommendedFriends.get(i).toString().equalsIgnoreCase(newFriend))
{
System.out.println("Error: This friend already exists.");
positiveChecker = true;
}
}
if (positiveChecker == false)
{
FacebookUser friend = new FacebookUser(newFriend, newFriend );
recommendedFriends.add(friend);
System.out.println(friend + " is now your friend.");
}
positiveChecker = false;
}
void defriend(String formerFriend)
{
boolean positiveChecker = false;
for (int i = 0; i < recommendedFriends.size(); i++)
{
if (recommendedFriends.get(i).toString().equalsIgnoreCase(formerFriend))
{
recommendedFriends.remove(i);
System.out.println(formerFriend + " has been removed from your friends list.");
positiveChecker = true;
}
if (recommendedFriends.size() == (i + 1) && recommendedFriends.get(i).toString() != formerFriend
&& positiveChecker == false)
{
System.out.println("Error: There is no friend with this username.");
}
}
positiveChecker = false;
}
public interface Command
{
public void undo();
public void redo();
}
When you undo 2 things then do a completely new action, you need to "forget" the "redo history" and replace it with the new command, right?
For example...
Add Friend Jim
Add Friend Bill
Add Friend Jill
Remove Jim
Undo
Undo
State should be "Jim" and "Bill".
So you only really need one list and a pointer to the current "command", for example...
// Note: NOT thread safe!
public class CommandStack {
private List<Command> commands = Collections.emptyList();
private int nextPointer = 0;
public void doCommand(Command command) {
List<Command> newList = new ArrayList<>(nextPointer + 1)
for(int k = 0; k < nextPointer; k++) {
newList.add(commands.get(k));
}
newList.add(command);
commands = newList;
nextPointer++;
// Do the command here, or return it to whatever called this to be done, or maybe it has already been done by now or something
// (I can only guess on what your code currently looks like...)
command.execute();
}
public boolean canUndo() {
return nextPointer > 0;
}
public void undo() {
if(canUndo()) {
nextPointer--;
Command commandToUndo = commands.get(nextPointer);
// Undo the command, or return it to whatever called this to be undone, or something
command.undo();
} else {
throw new IllegalStateExcpetion("Cannot undo");
}
}
public boolean canRedo() {
return nextPointer < commands.size();
}
public void redo() {
if(canRedo()) {
commandToDo = commands.get(nextPointer);
nextPointer++;
// Do the command, or return it to whatever called this to be re-done, or something
commandToDo.execute();
} else {
throw new IllegalStateException("Cannot redo");
}
}
}
If I had...
interface Command { /* execute / undo etc */ }
public class AddFriendCommand implements Command {
private String friendName;
// ... other fields, constructor / getters etc ...
public void execute() {
// Actually do it...
System.out.println("Added friend " + name);
}
public void undo() {
// Undo it...
System.out.println("Removed friend " + name);
}
}
public class RemoveFriendCommand implements Command {
private String friendName;
// ... other fields, constructor / getters etc ...
public void execute() {
// Actually do it, maybe throw exception if friend does not exist?
// (that would have to be a runtime exception unless you want the interface's method to throw stuff);
System.out.println("Removed friend " + name);
}
public void undo() {
// Undo it...
System.out.println("Added friend " + name);
}
}
You could repeat the sequence above using...
CommandStack stack = new CommandStack();
stack.doCommand(new AddFriendCommand("Jim"));
stack.doCommand(new AddFriendCommand("Bill"));
stack.doCommand(new AddFriendCommand("Jill"));
stack.doCommand(new RemoveFreindCommand("Jim"));
stack.undo();
stack.undo();
If you now did a new command (via doCommand) it would forget that you ever added "Jill" or removed "Jim", but instead would now remember the new command and the rest of the command history that was not undone.
Hope this helps.
You are misunderstanding how the command pattern works. You want to have a separate List of your Commands, where each instance of Command represents an action.
So you would want to have something like:
List<Command> actionStack;
and then have stuff like
public class AddCommand implements Command {
private final void List<FacebookUser> userList;
private final void FacebookUser newUser;
public AddCommand(List<FacebookUser> userList, FacebookUser newUser) {
this.userList = userList;
this.newUser = newUser;
}
#Override
public void undo() {
userList.remove(newUser);
}
#Override
public void redo() {
userList.add(newUser);
}
}

How do I store information from methods to be used in another session?

So I'm making a program that will store the meetings I've had with some kids I'm tutoring. It'll keep tabs on the meeting times, discussions, and how many hours I've done. I know how to write all the methods to do that, but my issue is that the program will only hold that information for the session that the program is open... how would I go about storing this information and accessing it after the program is closed and opened again?
This is some excerpts from a test score keeper program I did in java class that has this same issue...
public class Student {
private String name;
private int test1;
private int test2;
private int test3;
public Student() {
name = "";
test1 = 0;
test2 = 0;
test3 = 0;
}
public Student(String nm, int t1, int t2, int t3){
name = nm;
test1 = t1;
test2 = t2;
test3 = t3;
}
public Student(Student s){
name = s.name;
test1 = s.test1;
test2 = s.test2;
test3 = s.test3;
}
public void setName(String nm){
name = nm;
}
public String getName (){
return name;
}
public void setScore (int i, int score){
if (i == 1) test1 = score;
else if (i == 2) test2 = score;
else test3 = score;
}
public int getScore (int i){
if (i == 1) return test1;
else if (i == 2) return test2;
else return test3;
}
public int getAverage(){
int average;
average = (int) Math.round((test1 + test2 + test3) / 3.0);
return average;
}
public int getHighScore(){
int highScore;
highScore = test1;
if (test2 > highScore) highScore = test2;
if (test3 > highScore) highScore = test3;
return highScore;
}
public String toString(){
String str;
str = "Name: " + name + "\n" + //\n makes a newline
"Test 1: " + test1 + "\n" +
"Test 2: " + test2 + "\n" +
"Test 3: " + test3 + "\n" +
"Average: " + getAverage();
return str;
}
}
If your data is not too big or complicated - something that you could save in a Rolodex in days gone by - you can save it to a file. Add methods to your class that will format the data properly and write it to a given OutputStream or Writer or whatever. And a method that will read it back.
To write to the file, add an option "save" in your program menu, and when it's chosen, open a file, iterate through your data, and call the saving method for each of your object.
To read from the file, add an option "load" in your program menu, and when it's chosen, open a file, and use your method of reading for each object.
The method for reading can be a static method in the class, that will first see if there are any data in the file and if it can read them properly, and only if it did, will create an object and return it (otherwise return null). There are other options, but this is the one that most encapsulates the needs of the object.
There is also an option to serialize and deserialize each object and put it in an object stream.
If the data is complicated, and there are many objects with various relations between them, you should use a database. This will require learning some database design and SQL.
To demonstrate the file reading/writing idea, add to your Student class:
public void save(PrintWriter outfile) {
outfile.format("%s|%d|%d|%d%n", name, test1, test2, test3);
}
This will write a line with the fields separated by "|" (vertical bar). Of course, you'll have to make sure none of the student names has a vertical bar in it. So you'll need to modify your 4-parameter constructor and your setter:
public Student(String nm, int t1, int t2, int t3) {
name = nm.replaceAll("\\|", "");
test1 = t1;
test2 = t2;
test3 = t3;
}
public void setName(String nm) {
name = nm.replaceAll("\\|", "");
}
Now, to read the file, we add a static method:
public static Student load(BufferedReader infile) throws IOException {
String line;
line = infile.readLine();
// Check if we reached end of file
if (line == null) {
return null;
}
// Split the fields by the "|", and check that we have no less than 4
// fields.
String[] fields = line.split("\\|");
if (fields.length < 4) {
return null;
}
// Parse the test scores
int[] tests = new int[3];
for (int i = 0; i < 3; i++) {
try {
tests[i] = Integer.parseInt(fields[i + 1]);
} catch (NumberFormatException e) {
// The field is not a number. Return null as we cannot parse
// this line.
return null;
}
}
// All checks done, data ready, create a new student record and return
// it
return new Student(fields[0], tests[0], tests[1], tests[2]);
}
You can see that this is more complicated, because you need to check that everything is OK at every step. In any case when things are not OK, we return null but of course, you can decide to just display a warning and read the next line. You'll have to return null when there are no more lines, though.
So, assuming we have a List<Student> students, here is how we write it to a file. I just chose "students.txt" but you can specify a full path leading where you want it. Note how I'm making a backup of the old file before I open the new file. If something goes wrong, at least you have the previous version of the file.
File f = new File("students.txt");
if (f.exists()) {
File backup = new File("students.bak");
if ( ! f.renameTo(backup) ) {
System.err.println( "Could not create backup.");
return;
}
f = new File("students.txt");
}
try ( PrintWriter outFile = new PrintWriter(f);) {
for (Student student : students) {
student.save(outFile);
}
} catch (FileNotFoundException e) {
System.err.println("Could not open file for writing.");
return;
}
After you do this, if you look for the file "students.txt", you will see the records you wrote in it.
How about reading it? Assume we have an empty students list (not null!):
try ( BufferedReader inFile = new BufferedReader(new FileReader(f))) {
Student student;
while ( ( student = Student.load(inFile)) != null) {
students.add(student);
}
} catch (FileNotFoundException e) {
System.err.println( "Could not open file for reading.");
return;
} catch (IOException e) {
System.err.println( "An error occured while reading from the file.");
}
Having done this, you can check your students list, and unless there were errors in the file, all your records will be there.
This is a demonstration, of course. You may want to read into some other collection or instead of printing an error and returning do something else. But it should give you the idea.
You could use db4o for persisting your data. Its an object-database with a spimple api to use. You can store java object read or delete them..
Download it here DB4O
And use the snippets of this tutorial (GER):Tutorial in German
Here is an example:
and Code:
package db4o.example;
public class Student {
String name;
public Student(String name) {
this.name = name;
}
#Override
public String toString() {
return "Student Name: " + name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
package db4o.example;
import java.util.List;
import com.db4o.Db4oEmbedded;
import com.db4o.ObjectContainer;
public class Main {
public static void main(String[] args) {
ObjectContainer db = Db4oEmbedded.openFile("F:\\studentDB");
saveExample(db);
readAllExample(db);
readExample(db);
deleteAllExample(db);
db.close();
}
private static void deleteAllExample(ObjectContainer db) {
System.out.println("DeleteAllExample Example:");
List<Student> allStudents =readAllExample(db);
for (Student student : allStudents) {
db.delete(student);
}
db.commit();
}
private static List<Student> readAllExample(ObjectContainer db) {
System.out.println("ReadAllExample Example:");
List<Student> allStudents = db.query(Student.class);
System.out.println("Count: " + allStudents.size());
for (Student student : allStudents) {
System.out.println(student);
}
return allStudents;
}
private static void readExample(ObjectContainer db) {
System.out.println("ReadExample Example:");
Student queryStudent = new Student("Max Mustermann");
// Gets all Students named Max Mustermann
List<Student> students = db.queryByExample(queryStudent);
System.out.println("Count: " + students.size());
for (Student student : students) {
System.out.println(student);
}
}
private static void saveExample(ObjectContainer db) {
System.out.println("Save Example:");
Student myStudent = new Student("Max Mustermann");
db.store(myStudent);
db.commit();
}
}

Check for null field in arraylist

I can find plenty of Q&A on here about whether an arraylist can equal null, which was helpful in its own way, but I can't find an answer for throwing errors if any fields in the arraylist are null. As I'm adding objects to the arraylist, I want to throw an exception if the user tries to pass in anything that is null. Here is the code:
void addInvoiceItem(Item item, Integer quantity, double discount) throws Exception {
for (InvoiceItem thing: invoiceList) {
if (thing == null) {
throw new IllegalArgumentException("Part of the invoice item is blank (null). Please review your invoice items and ensure you have specified values for the item.");
}
else {
invoiceList.add(thing);
thing.setItemQuantity(quantity);
thing.setItemDiscount(discount);
System.out.println(invoiceList);
}
}
}
Here is the Item class:
final class Item {
String itemDescription;
double itemPrice;
Integer itemSKU;
Item (String description, double price, Integer sku) {
this.itemDescription = description;
this.itemPrice = price;
this.itemSKU = sku;
}
}
Here are the test methods that are letting me know I'm definitely omitting something. One is to test for a valid InvoiceItem, the other for an invalid one (contains nulls):
public class InvoiceTest {
//create the static values to be used
//for InvoiceItem
String goodDescription = "wheel";
double goodPrice = 500.00;
Integer goodSku = 0002;
Item goodInvoiceItem = new Item(goodDescription, goodPrice, goodSku);
String emptyDescription = null;
double emptyPrice = 0;
Integer emptySku = 0;
Item badInvoiceItem = new Item(emptyDescription, emptyPrice, emptySku);
Integer itemQuantity = 0;
double itemDiscount = 0.05;
#Test
public void invalidItemAddTest() {
Invoice badInvoice = new Invoice(null);
try {
badInvoice.addInvoiceItem(badInvoiceItem, itemQuantity, itemDiscount);
System.out.println(badInvoice);
} catch (Exception e) {
e.printStackTrace();
}
}
#Test
public void validItemAddTest() {
Invoice goodInvoice = new Invoice(null);
try {
goodInvoice.addInvoiceItem(goodInvoiceItem, itemQuantity, itemDiscount);
System.out.println(goodInvoice);
} catch (Exception e) {
e.printStackTrace();
}
}
Thanks in advance for all your help
Edit with additions:
So Mel's answer was my starting point and I made some additions to get it working the way I needed to. My adding method now looks like this:
void addInvoiceItem(Item item, Integer quantity, double discount) {
if(item == null || quantity == 0 || discount == 0) {
throw new IllegalArgumentException("Part of the invoice item is blank (null). Please review your invoice items and ensure you have specified values for the item.");
} else {
InvoiceItem invoice = new InvoiceItem(item, quantity, discount);
invoiceList.add(invoice);
}
}
and my test methods look like this:
public class InvoiceTest {
//create the static values to be used
//for InvoiceItem
String goodDescription = "wheel";
double goodPrice = 500.00;
int goodSku = 0002;
Item goodInvoiceItem = new Item(goodDescription, goodPrice, goodSku);
String emptyDescription = null;
double emptyPrice = 0;
int emptySku = 0;
Item badInvoiceItem = new Item(emptyDescription, emptyPrice, emptySku);
int badItemQuantity = 0;
double badItemDiscount = 0;
int goodItemQuantity = 1;
double goodItemDiscount = 0.05;
/**
* #Before - initialize what we need for the test
* #throws Exception
*/
#Before
public void setUp() {
//things needed for testInvalidItemAdd()
}
/**
* #throws Exception
* #Test - confirm you cannot add an item that is null
*/
#Test
public void invalidItemAddTest() {
boolean exceptionThrown = false;
Invoice badInvoice = new Invoice(null);
try {
badInvoice.addInvoiceItem(badInvoiceItem, badItemQuantity, badItemDiscount);
System.out.println(badInvoice);
} catch (Exception e) {
e.printStackTrace();
exceptionThrown = true;
}
assertTrue(exceptionThrown);
}
#Test
public void validItemAddTest() {
boolean exceptionThrown = false;
Invoice goodInvoice = new Invoice(null);
try {
goodInvoice.addInvoiceItem(goodInvoiceItem, goodItemQuantity, goodItemDiscount);
System.out.println(goodInvoice);
} catch (Exception e) {
e.printStackTrace();
exceptionThrown = true;
}
assertFalse(exceptionThrown);
}
Your add routine is a little off. It tries to use an item that is already in the list rather than creating a new one. Try this:
void addInvoiceItem(Item item, Integer quantity, double discount) {
if(
item == null ||
quantity == null ||
item.sku == null ||
item.description == null
) {
throw new NullPointerException();
}
InvoiceItem invoice = new InvoiceItem(item, quantity, discount);
invoiceList.add(invoice);
}
Also take a look a checkNotNull( ) from the google library to reduce typing a bit.
It may be useful to check for null in the InvoiceItem constructor rather than in the adder, unless you want to allow nulls elsewhere.

Categories