kadina
kadina

Reputation: 5376

Facing issues while working with string replace method in java

I am working on supporting notifications on Kindle device. We receive the expression sting from server which contains topics (topics will be in single quotes). We need to check if the device is subscribed to topic. If it is subscribed, then we need to replace the topic in the logical expression with '1' else with '0'. Below is the example how logical expression looks like.

('18' in topics || '4' in topics) && ('REG_92779' in topics && 'REG_91212' in topics)

assume device is subscribed to topics '18', '4' and not subscribed to 'REG_92779' and 'REG_91212'. The expression should become

('1' || '1') && ('0' && '0')

After that we need to remove spaces and quotes. The expression should become

(1||1)&&(0&0)

Below is the code

private boolean checkNotificationValid(String leString) {
        // Remove the 'in topics' string. examples of logical expression as below
        // ('4' in topics && '50000' in topics) || ('60' in topics || '3' in topics)
        // ('4' in topics && ('50000' in topics || '60' in topics))
        leString = leString.replaceAll("in topics", "");
        Log.d(TAG, "Notifications : ADM : LE : Logical Expression received : " + leString);
        boolean result = false;

        // Find the topics in the logical expression and check whether the device is subscribed to
        // the topic. If device is subscribed to the topic, replace the topic with 1 or replace the
        // topic with 0. Below is the example.
        // Assume device is subscribed to topics 3 and 4.
        // Expression : ('4' && '50000') || ('60' || '3')
        // After this block of code, it becomes : ('1' && '0') || ('0' || '1')
        Pattern p = Pattern.compile("'(.*?)'");
        Matcher m = p.matcher(leString);
        while(m.find()) {
            Log.d(TAG, "Notifications : ADM : LE : " + m.group(1));

            // Check whether the device is subscribed to the topic
            if(NotificationUtils.isTopicExistInSharedPref(m.group(1))) {
                leString = leString.replaceFirst(m.group(1), "1");
            } else {
                leString = leString.replaceFirst(m.group(1), "0");
            }
        }

        // Remove the quotes and spaces from the string, replace '||' with '|', replace '&&' with '&'
        // ('1' && '0') || ('0' || '1') -> (1&0)|(0|1)
        leString = leString.replaceAll("[' ]", "");
        leString = leString.replaceAll("\\|\\|", "|");
        leString = leString.replaceAll("&&", "&");

        return result;
    }

The code is working fine. But if the topics are '1' or '0', it is failing. Below is the example,

('18' in topics || '4' in topics) && ('1' in topics && '1' in topics)

after first 2 topics (18 and 4) verification, string becomes

('1' || '1') && ('1' && '1')

Now for topic '1', when I am trying to replace with 0 (as device is not subscribed), it is replacing first '1' where it should replace 3rd '1'. It is becoming as below.

('0' || '1') && ('1' && '1')

it should become

('1' || '1') && ('0' && '1')

Same issue is happening with topic '0' also.

This is happening because I used replaceFirst() method. If I tried to use replace() it is replacing all the occurrences in the string instead of replacing specific topic. Can any one please help me how to fix this issue.

NOTE: I first replaced with 1 or 0 based on device subscription and later I removed quotes ('4' -> '1' -> 1) as I couldn't figure out how to replace the topic with quote with 1 or 0 ('4' -> 1).

Upvotes: 3

Views: 90

Answers (1)

b.GHILAS
b.GHILAS

Reputation: 2303

Instead of using replaceFirst of String, you can use StringBuffer and append-and-replace appendReplacement method of Matcher.

Your code will become:

private boolean checkNotificationValid(String leString) {
    leString = leString.replaceAll("in topics", "");
    Log.d(TAG, "Notifications : ADM : LE : Logical Expression received : " + leString);
    boolean result = false;

    StringBuffer buffer = new StringBuffer();
    Pattern p = Pattern.compile("'(.*?)'");
    Matcher m = p.matcher(leString);
    while(m.find()) {
        Log.d(TAG, "Notifications : ADM : LE : " + m.group(1));

        if(NotificationUtils.isTopicExistInSharedPref(m.group(1))) {
            m.appendReplacement(buffer, "1");
        } else {
            m.appendReplacement(buffer, "0");
        }
    }

    m.appendTail(buffer);
    String finalStr = buffer.toString();
    finalStr = finalStr.replaceAll("[' ]", "");
    finalStr = finalStr.replaceAll("\\|\\|", "|");
    finalStr = finalStr.replaceAll("&&", "&");

    return result;
}

Upvotes: 3

Related Questions