0

I am generating a report for a customer of our company.

I have a abstract class with lots of static final int members:

public abstract class Customer_ItemIDs {
   public static final int item_001 = 34535;
   public static final int item_002 = 23455;
   public static final int item_003 = 74565;
   public static final int item_004 = 83480;
   ...
   public static final int item_122 = 65487;

}

In my class where I generate my report I use them like this (simplified a bit):

int itemID_004;
itemID_004 = Customer_ItemIDs.item_004;

Now there is a change in the requirement.

I need to support another Customer with totally different ItemIDs which i want to put in another static class. The name of the items stay the same, just the values are different.

public abstract class CustomerB_ItemIDs {
   public static final int item_001 = 17538;
   public static final int item_002 = 56756;
   public static final int item_003 = 94445;
   public static final int item_004 = 93757;
   ...
   public static final int item_122 = 69483;

}

How do I properly parametrize this, without changing every line of code where I initialize my itemIDs? I don't want to initialize the itemIDs like this:

int itemID_004;
if (customer == customerA) {
   itemID_004 = CustomerA_itemIDs.item_004;
}
else if (customer == customerB) {
   itemID_004 = CustomerB_itemIDs.item_004;
}

I would like to change as little as possible.

Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
Josef
  • 77
  • 8
  • 2
    "without changing every line of code where i initialize my itemIDs" Then you don't. This is screaming for polymorphism, but if you're unwilling to change your existing code then you're stuck. – Michael Feb 01 '23 at 12:50
  • 5
    The longer I look at this question the more I wonder why it is designed that way and not with a DB and matching entities? But anyway, if you need different values for all the variables you have, then you have to touch all the variables. – QBrute Feb 01 '23 at 12:55
  • 1
    Would a `Map` (or base class with child classes) solve your problem? Still requires changes to your code, but well, this is what software development is about. If the requirements change, the code has to change too (most of the time) – knittl Feb 01 '23 at 12:56
  • 2
    This feels incredibly cumbersome, both in terms of scaling the number of items and the number of products. – Andy Turner Feb 01 '23 at 12:59
  • If those variables are just numbered and have the same types an array might be sufficient. If the names/keys are different I'd suggest a map too. – Thomas Feb 01 '23 at 12:59
  • 2
    Map, or a class w/ polymorphism as suggested already. Either way I'd populate the data from a configuration file rather than trying to hard code the data inside the app. Then you can add more items just by adding a data file, code changes can be avoided. – markspace Feb 01 '23 at 13:03

1 Answers1

-1

I think you should try Java Reflections: java.lang.reflect

To not to interrupt the existing classes source code, I would create a method which will return HashMap with all field's name as a key and its int values as value, using provided class name as a parameter:

public static Map<String, Integer> getStaticVariablesValue(Class givenClass) {
    
    Field[] fields = givenClass.getDeclaredFields();
    Map<String, Integer> resultValues = new HashMap<>();
    
    for (int i = 0; i < fields.length; i++)
        if (fields[i].getType() == int.class)
            try {
                resultValues.put(fields[i].getName(), fields[i].getInt(null));
            } catch (IllegalAccessException e) {
                e.printStackTrace(System.out);
            }
            
    return resultValues;
    
}

Here is simple example, which will print you all fields with values for provided Class:

import java.util.*;
import java.lang.reflect.*;

class Main {
    public static void main(String args[]) {
        
        Map<String, Integer> customer_ItemIDsValues = new HashMap<>();
        Map<String, Integer> customerB_ItemIDsValues = new HashMap<>();

        customer_ItemIDsValues = getStaticVariablesValue(Customer_ItemIDs.class);
        customerB_ItemIDsValues = getStaticVariablesValue(CustomerB_ItemIDs.class);
        
        //Output values to console
        for (Map.Entry<String, Integer> entry : customer_ItemIDsValues.entrySet()) {
            System.out.println(entry.getKey() + " = " + entry.getValue());
        }
            
        for (Map.Entry<String, Integer> entry : customerB_ItemIDsValues.entrySet()) {
            System.out.println(entry.getKey() + " = " + entry.getValue());
        }
    }
    
    public static Map<String, Integer> getStaticVariablesValue(Class givenClass) {
        
        Field[] fields = givenClass.getDeclaredFields();
        Map<String, Integer> resultValues = new HashMap<>();
        
        for (int i = 0; i < fields.length; i++)
            if (fields[i].getType() == int.class)
                try {
                    resultValues.put(fields[i].getName(), fields[i].getInt(null));
                } catch (IllegalAccessException e) {
                    e.printStackTrace(System.out);
                }
                
        return resultValues;
    }

    abstract class CustomerB_ItemIDs {
       public static final int item_001 = 17538;
       public static final int item_002 = 56756;
       public static final int item_003 = 94445;
       public static final int item_004 = 93757;
       public static final int item_122 = 69483;
    }

    class Customer_ItemIDs {
       public static final int item_001 = 34535;
       public static final int item_002 = 23455;
       public static final int item_003 = 74565;
       public static final int item_004 = 83480;
       public static final int item_122 = 65487;
    }
}