lundi 30 novembre 2020

relate toString with object creation

I have a fairly basic Java class with some class variables. I have overwridden toString() to provide me with a string output (which will eventually be output to a text file).

I am trying to elegantly create a way for me to use this string output to recreate the object with all of the variables set as before. The class looks something like this:

public class Report {

    private String itemA;
    private String itemB;
    private String itemC;

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("Items are::");
        sb.append("\nItem A is: ").append(itemA);
        sb.append("\nItem B is: ").append(itemB);
        sb.append("\nItem C is: ").append(itemC);
        return sb.toString();
    }
}

this is how I can potentially tackle it using reflection:

public class Report {

    private String itemA;
    private String itemB;
    private String itemC;

    private final Map<String, String> MAPPING = new HashMap<>();

    public Report(String itemA, String itemB, String itemC) {
        this.itemA = itemA;
        this.itemB = itemB;
        this.itemC = itemC;

        MAPPING.put("Item A is: ", "itemA");
        MAPPING.put("Item B is: ", "itemB");
        MAPPING.put("Item C is: ", "itemC");
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("Items are::");

        MAPPING.entrySet().forEach(entry -> {
            sb.append("\n").append(entry.getKey()).append(BeanUtils.getProperty(this, entry.getValue()));
        });

        return sb.toString();
    }


    public Report createReportFromString(String reportString) {
        List<String> reportLines = Arrays.asList(reportString.split("\n"));
        HashMap<String, String> stringObjectRelationship = new HashMap<>();
        
        reportLines.forEach(reportLine -> {
            Optional<String> matchingKey = MAPPING.keySet().stream().filter(reportLine::contains).findFirst();
            matchingKey.ifPresent(key -> {stringObjectRelationship.put(MAPPING.get(key), reportLine.split(key)[1]);});
        });
        
        stringObjectRelationship.forEach((variableName, variableValue) -> BeanUtils.setProperty(this, variableName, variableValue));
        return this;
    }
}

I basically want to relate the key in the report ("Item A is: ") to the name of the corresponding variable ("itemA") and use this relationship in both the toString() method and the createReportFromString(String string) method. Now when doing this there are a lot of possible exceptions that can be thrown and need to either be handled or thrown - and it then looks a lot less elegant than I would like.

I don't know if this is possible to do without reflection - or perhaps I could rearrange this class to make this possible?

What I can`t change is the structure of the string output in the toString().





Aucun commentaire:

Enregistrer un commentaire