Product Management App

Product Management App

Β·

12 min read

The Product Management App that we are going to build will be used for tracking the item's name, type, and place it is kept and keeping track of its warranty. This will be a basic console-based app. (I'm using Vs code as the IDE).

The Services it will provide are

  1. Add Product

  2. Get all Product

  3. Get a Particular Product

  4. Get a Product by a specific text

  5. Get a Product at the same Place

  6. Get Products that are out of Warranty


Prerequisite

  1. First, we will start by creating a Main.java file. It is going to be our control centre from where we could run all the commands just like a Control panel of a spacecraft, which have every type of key and button to execute any task but the main wiring and logic with which it is working is underneath hidden from the user.

  2. Second, we will create a new Class file named Product.java. This will contain all the variables that we need. So for the given project, those variables are Name, Type, Place and Warranty. All of these variables will be Private because of the concept of Encapsulation in Java which says that all of your variables and property should be Private because of which they can only be accessed with the help of Getter-Setter. Also, we will add the 'overriding toString()' method so that when we are printing the values from the main instead of getting the object's class name and memory address now it will return a string that includes the values of its attributes making it more informative and easy to understand.

Encapsulation
Encapsulation in object-oriented programming (OOP) is about grouping related data and methods within a class in Java. It helps to hide the inner workings of the class and expose a controlled interface for interacting with it. In Java, this is accomplished by declaring instance variables as private, limiting direct access from outside the class. Public getter and setter methods are then used to retrieve and modify the instance variables, allowing controlled access while maintaining data validation and consistency within the class. Encapsulation ensures that the class's implementation details are hidden and only the necessary operations are exposed to the outside world.
Getter-Setter
Getters and setters are methods used to protect data and enhance code security in object-oriented programming. Getters retrieve the value of a variable (accessors) and typically have names starting with "get" followed by the variable name. They are used to conveniently access data types such as int, String, double, float, etc. On the other hand, setters are responsible for setting or updating the value of a variable (mutators). They allow the programmer to assign a new value to a variable within a class's programs. Setter methods typically start with the word "set" followed by the variable name. Using getters and setters provides convenience and consistency for setting and retrieving values of specific data types. It is a common convention to capitalize the first letter of the variable in both getters and setters, adhering to standard naming conventions in Java.
public class Product {
        //encapsulation
        private String name;   
        private String type; 
        private String place;
        private int waranty;

        //constructor
        public Product(String name, String type, String place, int waranty) {
            this.name = name;
            this.type = type;
            this.place = place;
            this.waranty = waranty;
        }
        //Getter-Setter
        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 String getPlace() {
            return place;
        }

        public void setPlace(String place) {
            this.place = place;
        }

        public int getWaranty() {
            return waranty;
        }

        public void setWaranty(int waranty) {
            this.waranty = waranty;
        }
        //toString()
        @Override
        public String toString() {
            return "Product [name=" + name + ", type=" + type + ", place=" + place + ", waranty=" + waranty + "]";
        }
}

NOTE - you can just add constructor, GetterSetter, toString() directly by Ctrl+. in VSCode and tick all the variable.
  1. Now we will create a new class file named ProductService.java. to delegate the work of the Main.java file. This will have all the logic of our system. First, we will create an array list to store the data that we will receive from the user in the Main.java file.

    List<Product> products = new ArrayList<>();

    For this also remember to import java.util.ArrayList and java.util.List


Let's Start Building

Adding the Products

Now, the User will have many items which will have a name, type, place and warranty which can be added by using the Main.java file but we will delegate the work to the ProductService.java file. First, let's create an object named service of ProductService in the Main.java file. Also, create one more object named Product p which will contain the product data that we want to add. And to add that p-value in the array list we will just ask the service to add the Product.

//in Main.java file
ProductService service = new ProductService();
Product p = new Product("Asus Vivobook", "Laptop", "Brown Table",2022);
service.addProduct(p);

But it service will say that it doesn't know what is addProduct. So, Now we will make a method in ProductService named addProduct() and pass the value of Product p in it.

//in ProductService.java file
public void addProduct(Product p)  //passing p as the product
    {
        products.add(p);   // .add(p) will add the product in the list
    }

This will add the product.πŸ₯³

Now creating a reference named p was fine for one Data set. But in the real world, there would be many data sets so to simplify the process what we will do is just take the data from p and then directly put it in service.addProduct(). As, in the method addProduct of ProductService.java, in Parameters, we have already specified Product p so it will automatically equate Product p with the Data Set we will specify in service.addProduct().

service.addProduct(new Product("Vivobook", "Laptop", "Brown Table",2022));
service.addProduct(new Product("Type C", "Cable", "Black Drawer", 2024));
service.addProduct(new Product("Mac Studio", "Computer", "White Table", 2025));
service.addProduct(new Product("Focusrite Mixer", "Audio System", "White Table", 2025));
service.addProduct(new Product("Asus Vivobook", "Laptop", "Brown Drawer", 2021));
service.addProduct(new Product("Asus Rog", "Laptop", "Black Table", 2021));
service.addProduct(new Product("Macbook pro", "Laptop", "Brown Drawer", 2022));
service.addProduct(new Product("Wacom Pad", "Writing Pad", "Black Drawer", 2020));
service.addProduct(new Product("Apple Keyboard", "Keyboard", "White Table", 2022));
service.addProduct(new Product("Logitech Keyboard", "Keyboard", "Black Table", 2024));
service.addProduct(new Product("Hdmi cable", "Cable", "Black Drawer", 2024));
service.addProduct(new Product("Java Black Book", "Cable", "Shelf", 2024));
service.addProduct(new Product("Logi Mouse", "Mouse", "Black Table", 2022));
service.addProduct(new Product("Apple Mouse", "Mouse", "White Table", 2022));
service.addProduct(new Product("Lenovo Mouse", "Mouse", "Black Drawer", 2022));
service.addProduct(new Product("BlackBeast", "Computer", "White Table", 2020));

You can use this example data point set if you want to experiment with the code. Happy Coding!😁

Printing the DataSet

As we have done earlier, similarly we will ask the service object in the Main.java file to get us all the products. Thus,

service.getAllProduct();

So, to make it work we will create a new method in the ProductService.java file named getAllProduct() in which we will ask to return the products list.

//here as we are returning list of product that's why the type is List<>.
public List<Product> getAllProducts() 
    {
        return products;
    }

We also have to accept the products list in the Main.java file to do so we will

List<Product> products = service.getAllProducts();
//System.out.println(products); we will not simply write this because it will print all data on the same line which we don't want.
//So we will use Enhanced for loop that will take Product value one at a time and print it on different line.
for(Product p : products)
    {
        System.out.println(p);
    }

Now, let us print a specific product

First, let's create a method in the ProductService.java file named getAProduct() whose job is to return a particular product from the DataSet.

public Product getProduct(String name)  //here we are not retreiving a list instead just a product so the type to be return in this method is Product
{
    for(Product p : products) //enhanced loop
    {
        if(p.getName().equals(name))  
        return p;
    }
    return null;
}

Here, what we are doing in this code is that for each Product object p in the collection, checks if the name of that product (p.getName()) is equal to the provided name. So, If a matching product is found, it immediately returns that Product object. If no matching product is found after checking all the products, it returns null to indicate that no product with the given name was found.

So, to catch the data that this method will send we again come back to the Main.java file and

//If I want to get Hdmi cable
Product p = service.getProduct("Hdmi cable");
System.out.println(p);

Now, let us print a product with a specific Text,

First, create a method in the ProductService.java named getProductWithText(String Text). (It will accept String Value). Now we must convert this text into lowercase otherwise because of type mismatch it might not produce the result that we want. so we will use

String str = Text.toLowerCase(); //this will make a string str that contains text in lowercase

After that, as that text could be in any number of DataSets so let's first build an ArrayList named prod in the ProductService.java. then we will again use enhanced for loop and declare a condition in that. So the code would look like this.

public List<Product> getProductWithText(String Text) 
    {
        String str = Text.toLowerCase();
        List<Product> prod = new ArrayList<>();
        for(Product p : products)
        {
            String name = p.getName().toLowerCase();
            String Type = p.getType().toLowerCase();
            String Place = p.getPlace().toLowerCase();

            if(name.contains(str)||Type.contains(str)||Place.contains(str))
            {
                prod.add(p);
            }
        }
        return prod;
    }

Now, what is happening here is because of for loop it loops through each Product object p in the products collection. And as we did earlier similarly we convert the name, type, and place to lowercase and assign them to separate variables. Now checks if the str variable is contained within the lowercase name, Type, or Place variables. If there is a match (i.e., the str is found in any of the lowercase variables), it adds that Product object p to the prod list. After checking all the products, it returns the prod list containing all the matching products.

Now we have to accept that value in the Main.java file and for that, we will ask the service for the same

//Black is the text we are searching for
List<Product> prod = service.getProductWithText("Black");
    for(Product productWithText : prod) //for will get one value at a time
    {
        System.out.println(productWithText);
    }

And DONE!!!!!!


Assignment Time

Today, we got the assignment to do was,

To search by 'Place'

//In ProductService.java file
public List<Product> getProductAtPlace(String Place) 
{
    String str = Place.toLowerCase();
    List<Product> prodatplace = new ArrayList<>();

    for(Product p : products)
    {
        String commonPlace = p.getPlace().toLowerCase();
        if(commonPlace.contains(str))
        {
            prodatplace.add(p);
        }
    }
    return prodatplace;
}

Just like we did in the case of Specific text, we will create a method that will find the name of that particular place which can be a Drawer, Table or any sort of colour in the Place() of every dataset. Now to print the value we just have to accept the value in the Main.java file.

List<Product> prod = service.getProductAtPlace("Drawer");
for(Product prodatplace : prod)
{
    System.out.println(prodatplace);
}

Done!!!

To search for a Product that is out of 'Warranty'

//In ProductService.java file
public List<Product> getProductOutOfWarranty() {
Year year = Year.now();
int currentYear = year.getValue();
List<Product> prodOutOfWarranty = new ArrayList<>();

for(Product p : products)
    {
        int prodwaranty = p.getWaranty();
        if(prodwaranty< currentYear)
            prodOutOfWarranty.add(p);
    }

return prodOutOfWarranty;
}

In this, the method utilizes the Java Year class to obtain the current year. It then retrieves the integer value of the current year and stores it in the variable currentYear. An empty list named prodOutOfWarranty is created to hold the products that have expired warranties. The code iterates through each Product object in the products collection, checking the warranty year of each product using the getWarranty() method. If the warranty year is less than the currentYear, indicating that the product's warranty has expired, the product is added to the prodOutOfWarranty list. Finally, the method returns the prodOutOfWarranty list, containing all the products that are out of warranty based on the current year. Now, to accept we will again do the same thing

List<Product> prodWarranty = service.getProductOutOfWarranty();
    for(Product prodOutOfWarranty : prodWarranty)
    {
        System.out.println(prodOutOfWarranty);
    }

Done!!!

Implementing Stream API in the code

Stream API
The Stream API in Java is like a pipeline that lets you easily process a collection of data. It allows you to apply operations to the elements in the collection, such as filtering, transforming, or calculating. The API implies working with collections by handling the iteration and processing for you, making your code more concise and efficient. Also, When using the Stream API, you can perform operations on the elements of a collection without modifying the original collection itself. Instead, the Stream API processes the data and produces new streams or results based on the operations applied.

Now, time to implement Stream API on the code that we have run today.

  1. In Method getProduct()

     public Product getProduct(String name)
     {
         String str = name.toLowerCase();
         return products.stream().filter(p ->                 p.getName().toLowerCase().contains(str)).findFirst().orElse(null);
     }
    

    Here The getProduct method uses the Stream API to search for a Product object based on its name in a case-insensitive manner. It converts the provided name to lowercase, filters the products list based on the name condition, and returns the first matching Product. If no match is found, it returns null.

  2. In Method getProductWithText()

     public List<Product> getProductWithText(String Text) 
     {
         String str = Text.toLowerCase();
         return products.stream().filter(p -> p.getName().toLowerCase().contains(str)||p.getType().toLowerCase().contains(str)||p.getPlace().toLowerCase().contains(str)).collect(Collectors.toList());
     }
    

    NOTE - First, import java.util.stream.Collectors; in the ProductService.java file.

    Here, The getProductWithText method utilizes the Stream API in Java to perform a text-based search for Product objects. It takes a Text parameter converts it to lowercase, and creates a stream from the products list. The stream is then filtered based on whether the lowercase name, type, or place of each Product contains the Text value. The resulting stream is collected into a new list using Collectors.toList(), which contains the Product objects that match the search criteria. In essence, the method provides a way to retrieve a list of Product objects that have matching text in their name, type, or place, in a case-insensitive manner.

  3. In Method getProductAtPlace()

     public List<Product> getProductAtPlace(String Place) 
     {
         String str = Place.toLowerCase();
         return products.stream().filter(p -> p.getPlace().toLowerCase().contains(str)).collect(Collectors.toList());
     }
    

    We are doing the same as the 2nd case, just instead of checking in every variable we are looking at just a variable named Place.

  4. In Method getProductOutOfWarranty()

     public List<Product> getProductOutOfWarranty() 
     {
         Year year = Year.now();
         int currentYear = year.getValue();
         return products.stream().filter(p -> p.getWaranty()<currentYear).collect(Collectors.toList());
     }
    

    Here, The getProductOutOfWarranty method retrieves the current year and stores it in the currentYear variable. It creates a stream from the products list and applies a filter operation to check if the warranty year of each Product object is less than the current year. This filters out the Product objects with expired warranties. The filtered elements are then collected into a new list using Collectors.toList() and returned. In summary, the method provides a way to obtain a list of Product objects whose warranties have expired, based on the current year.

Done!!!!!!


Conclusion

It was fun making an Inventory based application and learning Stream API. In the coming days, we will make it more user-friendly and practical.

Thank you for joining me today! πŸ™Œ I hope you found my tech blog informative and learned something new. πŸ€“ Take care and continue to explore the fascinating world of technology! πŸš€πŸ’» Don't forget to show your appreciation by giving it a thumbs-up! 😁

Did you find this article valuable?

Support Indrajit Mandal by becoming a sponsor. Any amount is appreciated!

Β