HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavaMinor

System to process data from a specific client

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
processsystemclientspecificfromdata

Problem

I'm working on an important project. We're an IT services provider and we have a project where we have to build a new system to process data from a specific client.

The problem is that usually we process their data, but they send us a pre-processed data that's easy to parse, but this time around, they're trying with a new format, which is extremely weird.

Anyways, there were two senior programmers that didn't want to mess with the project, and it's been on hold for one whole year. I'm a junior programmer and I managed to build a system that kind of works as intended but I want to improve on it. I don't like the way it ended up, even if it works.

The thing is, this format is for generating account statements for a local bank, and they're sending in RAW data. I managed to read and parse the data by using a configuration file that's able to read the data from it's position on the file, which can have up to 500 MB of text data. I built a loadInfo() method that uses reflection to fill in the data in the different classes.

The data comes grouped in Registers, which have many fields. Each Register holds specific information, like transactions, client info, balances and stuff. I created a superclass called Register, and then made the other corresponding types of register extend from this superclass. The thing is that there are 17 different kinds of registers, and a Register can have from 1 to more than 30 members.

I only use one loadInfo() from the Register superclass, and using reflection I can set the member variables for all the other registers.

I feel that my approach is kind of stupid, even if it works, and I'd like to improve it and make it more clean. Right now the whole system has like 25 different classes and I feel that my solution is too disorganized. Any advice on how to improve on my design?

I'm going to just include the code for the Registry that contains the information for the client. We are talking about bank data here, and this code

Solution

It's been a while since I asked this question and I'm still working on this project, so far, these are the refactorings that I've been able to make so far.

First, I changed the way all Registers are created, and then modified the parent Registry class like this:

import java.util.ArrayList;
import java.util.List;

public abstract class Registro {
    // dataReg holds information about the starting position, length and decimal places
    // for all the fields that make up the Registry
    private String dataReg; 
    private String idReg;  // registry ID
    private String[] fields;
    protected List fieldValues;

    public Registro(){      
    }

    public Registro(String dataReg){
        this();
        this.setDataRegistro(dataReg);
    }   

    public void setDataRegistro(String dataReg){
        this.fields= dataReg.split("\\|");      
    }

    public void loadInfo(String rawData) {
        this.setListaValores(rawData);

        callSetters();
    }

    public void setListaValores(String rawData) {
        this.fieldValues= new ArrayList();

        for(String valor : getCampos()) {
            this.fieldValues.add(new Campo(Campo.getField(valor, rawData, "_")));
        }
    }

    public String[] getCampos() {
        return this.fields;
    }

    public abstract void callSetters();

    public void setIdRegistro(String idReg){
        this.idReg = idReg;
    }

    public List getListaValores() {
        return this.fieldValues;
    }

    public String getDataRegistro(){
        return this.dataReg;
    }

    public String getIdRegistro(){
        return this.idReg;
    }

    @Override
    public String toString() {
        // TODO Auto-generated method stub
        return this.buildString();
    }

    protected abstract String buildString();
}


In my first implementation, I couldn't control very well the way that the Registry's childs were created since I used reflection to access all private members of each Registry sub-class and created them by using Campo's constructors, which didn't give me much control on their creation.

Here's the modified RegistroCL that holds the client's information:

public class RegistroCL extends Registro{

    private ClientInfo _person;

    public RegistroCL(String dataReg){
        super(dataReg);
        setIdRegistro("CL");
    }

    public String getFullName() {
        return _person.getFullName();
    }

    public String getName() {
        return _person.getName();
    }

    public String getFirstLastName() {
        return _person.getFirstLastName();
    }

    public String getSecondLastName() {
        return _person.getSecondLastName();
    }

    public String getPhysicalAddress(){
        return _person.getPhysicalAddress();
    }

    public String getEmail() {
        return _person.getEmail();
    }

    public String getDesProv() {
        return _person.getProvincia();
    }

    public String getMunicipio() {
        return _person.getMunicipio();
    }

    public String getSector() {
        return _person.getSector();
    }

    public String getStreet() {     
        return _person.getStreet();
    }

    public String getBuildingNumber() {
        return _person.getBuildingNumber();
    }

    public String getFloorNumber() {
        return _person.getFloorNumber();
    }

    public String getApartmentNumber() {
        return _person.getApartmentNumber();
    }

    public String getBlock() {      
        return _person.getBlock();
    }

    public String getBuildingName() {
        return _person.getBuildingName();
    }

    public String getDesEntreCalles1() {
        return _person.getDesEntreCalles1();
    }

    public String getDesEntreCalles2() {
        return _person.getDesEntreCalles2();
    }

    @Override
    public void callSetters() {
        _person = new ClientInfo(this.getListaValores());
    }

    @Override
    protected String buildString() {
        String output = this.getName();
        output = output.concat(" " + this.getFirstLastName());
        output = output.concat(" " + this.getSecondLastName() + "\n");

        return output;
    }
}


Here's the new ClientInfo class:

```
import java.util.List;

public class ClientInfo {
private List _dataSource;
private String _name;
private String _firstLastName;
private String _secondLastName;
private PhysicalAddress _physicalAddress;
private String _email;

public ClientInfo(List dataSource) {
_dataSource = dataSource;
create();
}

public void create() {
_name = _dataSource.get(0).getFieldValue();
_firstLastName = _dataSource.get(1).getFieldValue();
_secondLastName = _dataSource.get(2).getFieldValue();
_email = _dataSource.get(4).getFieldValue().trim().toUpperCase();
_physicalAddress = new PhysicalAddress(_dataSource);
}

public String getFullName() {
return getName() + getFirstLastName() + getSecondLastName();
}

Code Snippets

import java.util.ArrayList;
import java.util.List;

public abstract class Registro {
    // dataReg holds information about the starting position, length and decimal places
    // for all the fields that make up the Registry
    private String dataReg; 
    private String idReg;  // registry ID
    private String[] fields;
    protected List<Campo> fieldValues;

    public Registro(){      
    }

    public Registro(String dataReg){
        this();
        this.setDataRegistro(dataReg);
    }   

    public void setDataRegistro(String dataReg){
        this.fields= dataReg.split("\\|");      
    }

    public void loadInfo(String rawData) {
        this.setListaValores(rawData);

        callSetters();
    }

    public void setListaValores(String rawData) {
        this.fieldValues= new ArrayList<Campo>();

        for(String valor : getCampos()) {
            this.fieldValues.add(new Campo(Campo.getField(valor, rawData, "_")));
        }
    }

    public String[] getCampos() {
        return this.fields;
    }

    public abstract void callSetters();

    public void setIdRegistro(String idReg){
        this.idReg = idReg;
    }

    public List<Campo> getListaValores() {
        return this.fieldValues;
    }

    public String getDataRegistro(){
        return this.dataReg;
    }

    public String getIdRegistro(){
        return this.idReg;
    }

    @Override
    public String toString() {
        // TODO Auto-generated method stub
        return this.buildString();
    }

    protected abstract String buildString();
}
public class RegistroCL extends Registro{

    private ClientInfo _person;

    public RegistroCL(String dataReg){
        super(dataReg);
        setIdRegistro("CL");
    }

    public String getFullName() {
        return _person.getFullName();
    }

    public String getName() {
        return _person.getName();
    }

    public String getFirstLastName() {
        return _person.getFirstLastName();
    }

    public String getSecondLastName() {
        return _person.getSecondLastName();
    }

    public String getPhysicalAddress(){
        return _person.getPhysicalAddress();
    }

    public String getEmail() {
        return _person.getEmail();
    }

    public String getDesProv() {
        return _person.getProvincia();
    }

    public String getMunicipio() {
        return _person.getMunicipio();
    }

    public String getSector() {
        return _person.getSector();
    }

    public String getStreet() {     
        return _person.getStreet();
    }

    public String getBuildingNumber() {
        return _person.getBuildingNumber();
    }

    public String getFloorNumber() {
        return _person.getFloorNumber();
    }

    public String getApartmentNumber() {
        return _person.getApartmentNumber();
    }

    public String getBlock() {      
        return _person.getBlock();
    }

    public String getBuildingName() {
        return _person.getBuildingName();
    }

    public String getDesEntreCalles1() {
        return _person.getDesEntreCalles1();
    }

    public String getDesEntreCalles2() {
        return _person.getDesEntreCalles2();
    }

    @Override
    public void callSetters() {
        _person = new ClientInfo(this.getListaValores());
    }

    @Override
    protected String buildString() {
        String output = this.getName();
        output = output.concat(" " + this.getFirstLastName());
        output = output.concat(" " + this.getSecondLastName() + "\n");

        return output;
    }
}
import java.util.List;

public class ClientInfo {
    private List<Campo> _dataSource;
    private String _name;
    private String _firstLastName;
    private String _secondLastName;
    private PhysicalAddress _physicalAddress;   
    private String _email;  

    public ClientInfo(List<Campo> dataSource) {
        _dataSource = dataSource;
        create();
    }

    public void create() {      
        _name = _dataSource.get(0).getFieldValue();
        _firstLastName = _dataSource.get(1).getFieldValue();
        _secondLastName = _dataSource.get(2).getFieldValue();
        _email = _dataSource.get(4).getFieldValue().trim().toUpperCase();
        _physicalAddress = new PhysicalAddress(_dataSource);
    }

    public String getFullName() {
        return getName() + getFirstLastName() + getSecondLastName();
    }

    public String getName() {
        return String.format("%1$-40s", _name);
    }

    public String getFirstLastName() {
        return String.format("%1$-36s", 
                appendCharacterToOriginalStringIfNotEmpty(_firstLastName, ' '));
    }

    private String appendCharacterToOriginalStringIfNotEmpty(String str, char appendWhat) {
        return !str.isEmpty() ? appendWhat + str : "";
    }

    public String getSecondLastName() {
        return String.format("%1$-36s", 
                appendCharacterToOriginalStringIfNotEmpty(_secondLastName, ' '));
    }

    public String getEmail() {              
        return (_email.isEmpty() ? "--" : "EMAIL: " + _email);
    }

    public String getPhysicalAddress() {
        return _physicalAddress.getDireccion();
    }

    public String getProvincia() {
        return _physicalAddress.getProvincia();
    }

    public String getMunicipio() {
        return _physicalAddress.getMunicipio();
    }

    public String getSector() {
        return _physicalAddress.getSector();
    }

    public String getStreet() {     
        return _physicalAddress.getStreet();
    }

    public String getBuildingNumber() {
        return _physicalAddress.getBuildingNumber();
    }

    public String getFloorNumber() {
        return _physicalAddress.getFloorNumber();
    }

    public String getApartmentNumber() {
        return _physicalAddress.getApartmentNumber();
    }

    public String getBlock() {      
        return _physicalAddress.getBlock();
    }

    public String getBuildingName() {
        return _physicalAddress.getBuildingName();
    }

    public String getDesEntreCalles1() {
        return _physicalAddress.getDesEntreCalles1();
    }

    public String getDesEntreCalles2() {
        return _physicalAddress.getDesEntreCalles2();
    }
}
import java.util.List;

public class PhysicalAddress {
    private List<Campo> _clientData;
    private String _street;
    private String _buildingNumber;
    private String _block;
    private String _buildingName;
    private String _floorNumber;
    private String _apartmentNumber;
    private String _entreCalle1;
    private String _entreCalle2;
    private String _municipio;
    private String _sector;
    private String _provincia;

    public PhysicalAddress(List<Campo> clientData){
        _clientData = clientData;
        create();
    }

    public void create() {
        _provincia = _clientData.get(10).getFieldValue();
        _sector = _clientData.get(16).getFieldValue();      
        _street = _clientData.get(21).getFieldValue();
        _buildingNumber = _clientData.get(22).getFieldValue();
        _floorNumber = _clientData.get(24).getFieldValue();
        _apartmentNumber = _clientData.get(25).getFieldValue();
        _block = _clientData.get(26).getFieldValue();
        _buildingName = _clientData.get(27).getFieldValue();
        _entreCalle1 = _clientData.get(32).getFieldValue();
        _entreCalle2 = _clientData.get(34).getFieldValue();
        setMunicipio();
    }

    public void setMunicipio() {
        _municipio = String.format("\n    %s, %s", getSector(), getProvincia());
    }

    public String getSector() {
        return _sector;
    }

    public String getProvincia() {
        return _provincia;
    }

    public String getDireccion(){
        return getStreet() + getBuildingNumber() + getBlock() + getBuildingName() + 
                getFloorNumber() + getApartmentNumber() + getDesEntreCalles1() +
                getDesEntreCalles2() + getMunicipio();
    }

    public String getStreet() {     
        return (_street.isEmpty() ? "" : "C/ " + _street + " ");
    }

    public String getBuildingNumber() {             
        return (_buildingNumber.isEmpty() ? "" : "#" + _buildingNumber + " ");
    }

    public String getBlock() {
        return (_block.isEmpty() ? "" : "MANZ. " + _block + " ");
    }

    public String getBuildingName() {
        return (_buildingName.isEmpty() ? "" : "EDIF. " + _buildingName + " ");
    }

    public String getFloorNumber() {
        return (_floorNumber.isEmpty() ? "" : "PISO: " + _floorNumber + " ");
    }

    public String getApartmentNumber() {
        return (_apartmentNumber.isEmpty() ? "" : "APTO. " + _apartmentNumber + " " );
    }

    public String getDesEntreCalles1() {
        return (_entreCalle1.isEmpty() ? "\n    --" : "\n    ENTRE ") + _entreCalle1;
    }

    public String getDesEntreCalles2() {
        return (_entreCalle2.isEmpty() ? "\n    --" : "\n    Y ") + _entreCalle2;
    }

    public String getMunicipio() {
        return _municipio;
    }

    public PhysicalAddress getPhysicalAddress(){
        return this;
    }
}
CL999999999999AAAAA AAAAAAAA                          AAAAAAAA AAAA                                                           AAAAAAAAAAA@BBBBB.CCC.DD                                                                              999AAA. AAAAAAAAAA     9  AAAAAA AAA AAAA     99AAAA AAA            99   AAAAAAAA AAAAAAAA                  999  AAAA  AAA                               9999 AA AAAAAAAAA                            99999AA AAAAAA                               AA9999999 AA AAAAAAA                                                                                       999                             9999999                                                                                                                                                                                                                                      AAAAAAA / AAAAAAA AAAAA AAAAAAA AAAAAAAA

Context

StackExchange Code Review Q#142514, answer score: 2

Revisions (0)

No revisions yet.