The following method is used to add objects to a polymorphic ArrayList
from a file.
It reads lines from the file, and based on a specific line which denotes the category of the product object, it uses the loadFromFile() method of the specific class, before moving onto the next. We are taught to build programs in such a way to allow for future functionality, so I would like to find a way to modify this so if a new child class was created, it would be able to detect that and call the method of that class. instead of the developer needing to add to the switch case every time.
Each child class has slightly different attributes hence why this is needed. I am looking for a more sophisticated and future proof method.
public void loadFromFile(String fileName) throws FileNotFoundException, IOException, ParseException{
Filename = fileName;
String record;
FileReader reader;
reader = new FileReader(Filename);
BufferedReader bin = new BufferedReader(reader);
record = new String();
while ((record = bin.readLine())!=null)
{
switch(bin.readLine()){
case "Electronic":
ElectronicProduct eProduct = new ElectronicProduct();
Products.add(eProduct.loadFromFile(eProduct,bin));
break;
case "Kitchen":
KitchenProduct kProduct = new KitchenProduct();
Products.add(kProduct.loadFromFile(kProduct,bin));
break;
case "Food":
FoodProduct fProduct = new FoodProduct();
Products.add(fProduct.loadFromFile(fProduct,bin));
break;
case "Book":
BookProduct bProduct = new BookProduct();
Products.add(bProduct.loadFromFile(bProduct,bin));
break;
}
bin.close();
bin =null;
}
}
EDIT
Below shows entire class, some methods not fully functional as currently upgrading from iteration 1 to iteration 2.
package mysupermarket;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.Optional;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
/**
*
* @author x
*/
public class ProductList {
private ArrayList<Product>Products;
private String Filename;
public ProductList(){
Filename = "ProductList.txt";
}
public void add(Product src) throws IOException{
Products.add (src);
}
public void remove(Product src){
Products.remove (src);
}
public Optional<Product> find(String nameInput){
Optional<Product> aProduct= this.Products.stream()
.filter(p->p.getName().equalsIgnoreCase(nameInput))
.findFirst();
return aProduct;
}
public void display (javax.swing.JTextArea src){
this.Products.forEach((product) -> {
product.display(true, src);
});
}
public void displayReorders(javax.swing.JTextArea src){
src.setText(null);
for(Product product: this.Products){
if(scanForLowStock(product)){
src.append("Product: " + product.getName()+"\n");
src.append("Quantity: " + product.getQuantity()+"\n");
src.append("Min Restock amount: " + (product.getMinimumStockLevel()-product.getQuantity())+"\n");
}
}
}
public void displayImage(JLabel imageArea, String image) throws IOException{
String noImageFound = "no-image-available.jpg";
BufferedImage img = null;
try {
img = (BufferedImage)ImageIO.read(new File(image));
Image actualimage = img.getScaledInstance(imageArea.getWidth(), imageArea.getHeight(), 0);
imageArea.setIcon(new ImageIcon(actualimage));
}
catch (IOException e) {
img = (BufferedImage)ImageIO.read(new File(noImageFound));
Image actualimage = img.getScaledInstance(imageArea.getWidth(), imageArea.getHeight(), 0);
imageArea.setIcon(new ImageIcon(actualimage));
System.out.println(e.getMessage());
}
}
public void loadFromFile(String fileName) throws FileNotFoundException, IOException, ParseException{
Filename = fileName;
String record;
FileReader reader;
reader = new FileReader(Filename);
BufferedReader bin = new BufferedReader(reader);
record = new String();
while ((record = bin.readLine())!=null)
{
switch(bin.readLine()){
case "Electronic":
ElectronicProduct eProduct = new ElectronicProduct();
Products.add(eProduct.loadFromFile(eProduct,bin));
break;
case "Kitchen":
KitchenProduct kProduct = new KitchenProduct();
Products.add(kProduct.loadFromFile(kProduct,bin));
break;
case "Food":
FoodProduct fProduct = new FoodProduct();
Products.add(fProduct.loadFromFile(fProduct,bin));
break;
case "Book":
BookProduct bProduct = new BookProduct();
Products.add(bProduct.loadFromFile(bProduct,bin));
break;
}
bin.close();
bin =null;
}
}
public void saveToFile(boolean append, String fileName) throws IOException, ParseException{
Filename = fileName+".txt";
try{//This simply overwrites the file with a blank file
FileWriter aWriter = new FileWriter(Filename,false);
}
catch(IOException ioe){
System.out.println("Failed to wipe file");
}
//Now file writing begins
FileWriter aWriter = new FileWriter(Filename,true);
aWriter.write(System.getProperty("line.separator"));
this.Products.forEach((product) -> {
try {
product.saveToFile(aWriter);
} catch (IOException ex) {
Logger.getLogger(ProductList.class.getName()).log(Level.SEVERE, null, ex);
} catch (ParseException ex) {
Logger.getLogger(ProductList.class.getName()).log(Level.SEVERE, null, ex);
}
});
try{
aWriter.close();
}
catch(IOException ioe){
System.out.println("Failed to save product list");
}
}
public int generateProductID(){
//This is superior to using ArrayList index as it, as that is dynamic and this is static once set.
Boolean NewIDFound = false;
Boolean inUse = false;
int potentialID;
for(potentialID=0;NewIDFound==false;potentialID++){
inUse=false;
for(Product productToCompare: this.Products){
if (potentialID==productToCompare.getID()){
inUse=true;
}
}
if(inUse!=true){
NewIDFound=true;
return potentialID;
}
}
return potentialID;
}
public int calculateSuggestedQuantity(Product chosenProduct){
int suggestedQuantity = chosenProduct.getMaximumStockLevel()-chosenProduct.getQuantity();
return suggestedQuantity;
}
public String calculateAdvisedOrderDate(Product chosenProduct,int deliveryTime) throws ParseException{
String date = "";
date = chosenProduct.getExpiryDate();
SimpleDateFormat formatter = new SimpleDateFormat("dd/MM/yy");
Calendar cal = Calendar.getInstance();
cal.setTime(formatter.parse(date));
cal.add(Calendar.DATE,-deliveryTime);
date = formatter.format(cal.getTime());
return date;
}
public double calculateOrderCost(Product chosenProduct, int orderQuantity){
Double orderCost = 0.0;
orderCost= orderQuantity * chosenProduct.getUnitCost();
return orderCost;
}
public boolean checkIfNameInUse(String input){
boolean alreadyInStock =false;
for(Product product : this.Products){
if(input.equals(product.getName())){
alreadyInStock =true;
break;
}
}
return alreadyInStock;
}
public void updateLastOrderDate(Product input){
String date = new SimpleDateFormat("dd/MM/yy").format(new Date());
input.setDateOfLastOrderPlacement(date);
}
public int setStockDefaultValue(String userInput){
int output = 0;
if(!userInput.equalsIgnoreCase("")){
output=Integer.valueOf(userInput);
}
return output;
}
public boolean confirmStockLevelsSet(Product chosenProduct){
boolean reOrderPossible =true;
if(chosenProduct.getMaximumStockLevel()==0||chosenProduct.getMinimumStockLevel()==0){
reOrderPossible=false;
}
return reOrderPossible;
}
public boolean scanForLowStock(Product chosenProduct){
boolean warningRequired = false;
if(chosenProduct.getQuantity()<chosenProduct.getMinimumStockLevel()){
warningRequired=true;
}
return warningRequired;
}
public String getFilename() {
return Filename;
}
public void setFilename(String Filename) {
this.Filename = Filename;
}
public boolean checkIfFileExists(String fileName){
String filename = fileName;
File tempFile = new File(filename);
boolean exists = tempFile.exists();
return exists;
}
}
EDIT 2
An extract of a child class is as follows, all child classes are similar with one or two unique attributes
public KitchenProduct loadFromFile(KitchenProduct kProduct, BufferedReader bin) throws IOException, ParseException{
super.loadFromFile(kProduct,bin);
kProduct.setFragile(super.convertTextToBoolean(bin.readLine()));
return kProduct;
}
below is an extract of the parent class
public Product loadFromFile(Product aProduct, BufferedReader bin) throws IOException, ParseException{
aProduct.edit(
/*int ID*/Integer.valueOf(bin.readLine()),
/*String name*/bin.readLine(),
/*String Supplier*/bin.readLine(),
/*String deliverycomapyn*/bin.readLine(),
/*String caTEGORY*/bin.readLine(),
/*double price*/Double.valueOf(bin.readLine()),
/*double unit cosre*/Double.valueOf(bin.readLine()),
/*int quantity*/Integer.valueOf(bin.readLine()),
/*int wiehgt*/Integer.valueOf(bin.readLine()),
/*int shelf life*/Integer.valueOf(bin.readLine()),
/*string date of last order*/bin.readLine(),
/*string image name*/bin.readLine(),
/*String min stock*/Integer.valueOf(bin.readLine()),
/*string max stock */Integer.valueOf(bin.readLine()));
return aProduct;
}
product list is as follows, different child classes have different amount of attributes which is reflected in file and detected when reading.
6
Potatoes
Farm Wholesale
UPS
veg
5.0
0.5
100
50
14
18/01/20
food
30
300
1
spatula
amazon
UPS
Farm
2.0
0.3
10
1
4
20/01/20
kitchen
4
15
true
Product
class, and at least 1 derived product class. (IseProduct.loadFromFile
a virtual method or a static method? We can’t tell yet.). Also, a sampleProductList.txt
file. After pasting your properly formatted code from your editor into the post, select the entire code and press Ctrl-K or Cmd-K to properly format it here, with the correct indentation. \$\endgroup\$