5
\$\begingroup\$

I need to parse the data coming from a URL:

haschanged=true
version=1
timestamp=1389562122310
DATACENTER=/pr/hello/plc
    TotalNumberOfServers:4
    primary:{0=1, 1=2, 2=1, 3=2, 4=1, 5=2, 6=1, 7=2, 8=1, 9=2, 10=1, 11=2, 12=1, 13=2}
    secondary:{0=0, 1=0, 2=0, 3=1, 4=0, 5=0, 6=0, 7=1, 8=0, 9=0, 10=0, 11=1, 12=0, 13=0}
    hosttomachine:{3=plcdbx1115.plc.domain.com, 2=plcdbx1114.plc.domain.com, 1=plcdbx1113.plc.domain.com, 4=plcdbx1116.plc.domain.com}
DATACENTER=/pr/hello/pty
    TotalNumberOfServers:2
    primary:{0=1, 1=2, 2=1, 3=2, 4=1, 5=2, 6=1, 7=2, 8=1, 9=2, 10=1, 11=2, 12=1, 13=2, 14=1}
    secondary:{0=0, 1=0, 2=0, 3=1, 4=0, 5=0, 6=0, 7=1, 8=0, 9=0, 10=0, 11=1, 12=0, 13=0, 14=0}
    hosttomachine:{1=ptydbx1145.pty.domain.com, 4=ptydbx1148.pty.domain.com}
DATACENTER=/pr/hello/vgs
    TotalNumberOfServers:0
    primary:{}
    secondary:{}
    hosttomachine:{}

After parsing the data I need to store all datacenter data in a Map like this:

ConcurrentHashMap<String, Map<Integer, String>> primaryData

For example, the Key of primaryData is /pr/hello/plc and value is:

{0=1, 1=2, 2=1, 3=2, 4=1, 5=2, 6=1, 7=2, 8=1, 9=2, 10=1, 11=2, 12=1, 13=2}

which is for primary.

Similarly another Map for secondary for each datacenter:

ConcurrentHashMap<String, Map<Integer, String>> secondaryData

For example, the Key of secondaryData is /pr/hello/plc and value is:

{0=0, 1=0, 2=0, 3=1, 4=0, 5=0, 6=0, 7=1, 8=0, 9=0, 10=0, 11=1, 12=0, 13=0}

which is for secondary.

And lastly, one more map for hosttomachine mapping for each datacenter:

ConcurrentHashMap<String, Map<Integer, String>> hostMachineMapping -

For example, the key of hostMachineMapping is /pr/hello/plc and value is:

{3=plcdbx1115.plc.domain.com, 2=plcdbx1114.plc.domain.com, 1=plcdbx1113.plc.domain.com, 4=plcdbx1116.plc.domain.com}

which is for hosttomachine.

And all the above map will have data for its datacenter as I have three datacenter in the above example. So each each map will have three data. And also I will parse the above response only when haschanged is equal to true. If it is not true, then I won't parse anything.

Here is the code I have so far, but it takes more than 200 ms to parse the data and store it in its corresponding hashmap. Is there any way to parse the above data efficiently and store it in a particular ConcurrentHashMap?

private void parseResponse(String response) throws Exception {
    if (response != null) {
        ConcurrentHashMap<String, Map<Integer, String>> primaryData = null;
        ConcurrentHashMap<String, Map<Integer, String>> secondaryData = null;
        ConcurrentHashMap<String, Map<Integer, String>> hostMachineMapping = null;

        long version = -1;
        long timestamp = 0L;
        boolean changed = false;
        String splitResponse[] = response.split("DATACENTER=");

        boolean flag = false;
        for (String sr : splitResponse) {
            if (!flag) {
                flag = true;
                String[] header = sr.split("\n");
                changed = Boolean.parseBoolean(header[0].split("=")[1]);
                if (!changed) {
                return;
                } else {
                version = Integer.parseInt(header[1].split("=")[1]);
                timestamp = Long.parseLong(header[2].split("=")[1]);
                primaryData = new ConcurrentHashMap<String, Map<Integer, String>>();
                secondaryData = new ConcurrentHashMap<String, Map<Integer, String>>();
                hostMachineMapping = new ConcurrentHashMap<String, Map<Integer, String>>();
                }

            } else {
                generateDATACENTERMap(sr, primaryData, secondaryData, hostMachineMapping);
            }
        }

        if (changed) {
            Mapping.setPrimaryData(primaryData);
            Mapping.setSecondaryData(secondaryData);
            Mapping.setHostMachineMapping(hostMachineMapping);
            Mapping.setTimestamp(timestamp);
            Mapping.setVersion(version);
        }
    }
}

private void generateColoMap(String sr, ConcurrentMap<String, Map<Integer, String>> primaryData,
ConcurrentMap<String, Map<Integer, String>> secondaryData,
ConcurrentMap<String, Map<Integer, String>> hostMachineMapping) throws Exception {

String[] data = sr.split("\n\t");
String dcName = data[0];
int numOfServers = Integer.parseInt(data[1].split(":")[1]);

    if (numOfServers > 0) {
        primaryData.put(dcName, generateMap(data[2]));
        secondaryData.put(dcName, generateMap(data[3]));
        hostMachineMapping.put(dcName, generateMap(data[4]));
    }
}

private ConcurrentMap<Integer, String> generateMap(String map) throws Exception {

String tableString = map.split(":")[1];
ConcurrentMap<Integer, String> table = new ConcurrentHashMap<Integer, String>();
tableString = tableString.substring(1, tableString.length() - 1);
String[] entries = tableString.split(", ");

    for (String e : entries) {
        String[] entryVal = e.split("=");
        table.put(Integer.parseInt(entryVal[0]), entryVal[1]);
    }

    return table;
}
\$\endgroup\$
2
\$\begingroup\$

Regex to the rescue

  • Regex for key: (?<=DATACENTER=).*

  • Regex for primary values: (?<=primary:\{).*(?=\})

  • Regex for secondary values: (?<=secondary:\{).*(?=\})

  • Regex for hostMachine Mapping: (?<=hosttomachine:\}).*(?=\})

  • Split on "," for primary, secondary, and hostMachine

Use these as your patterns then go through each match. Each iteration should give you key with matching values.

\$\endgroup\$
  • \$\begingroup\$ I'm not entirely sure that regex is the best option here, but it seems like it's an option at least, so +1. \$\endgroup\$ – Simon Forsberg Feb 15 '14 at 0:10

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.