Skip to main content
edited body
Source Link

Also, if you may know any batterbetter way to operate with chars in Apex Stings, please, tell me, I'm wondering if it is one though.

Also, if you may know any batter way to operate with chars in Apex Stings, please, tell me, I'm wondering if it is one though.

Also, if you may know any better way to operate with chars in Apex Stings, please, tell me, I'm wondering if it is one though.

Source Link

I suggest you to run through the pattern string and extract full numeric values on run, then replace them with suitable condition and move further (I have stored condition parts in Map, so there will be no misconception, if any keyVal may be omitted):

private static Map<String, Integer> getKeyValMap(List<Integer> patternChars, Integer startingPos) {
    String keyVal = String.fromCharArray(new List<Integer>{patternChars[startingPos]});
    Integer lastPos = startingPos;
    for (Integer i = startingPos + 1, n = patternChars.size(); i < n; i++) {
        String currentChar = String.fromCharArray(new List<Integer>{patternChars[i]});
        if (currentChar.isNumeric()) {
            keyVal += currentChar;
            lastPos = i;
        } else {
            break;
        }
    }
    return new Map<String, Integer>{
            'keyVal' => Integer.valueOf(keyVal),
            'lastPos' => lastPos
    };
}

public static String getCondition(String pattern, Map<Integer, String> conditionParts) {
    String condition = '';

    List<Integer> patternChars = pattern.getChars();
    for (Integer i = 0, n = patternChars.size(); i < n; i++) {
        String currentChar = String.fromCharArray(new List<Integer>{patternChars[i]});
        if (currentChar.isNumeric()) {
            Map<String, Integer> keyValMap = getKeyValMap(patternChars, i);
            condition += conditionParts.get(keyValMap.get('keyVal'));
            i = keyValMap.get('lastPos');
        } else {
            condition += currentChar;
        }
    }

    return condition;
}

You may get conditionParts map with this method:

public static Map<Integer, String> getConditionParts(String jsonString) {
    Map<Integer, String> conditionParts = new Map<Integer, String>();
    for (Object tmp : (List<Object>) JSON.deserializeUntyped(jsonString)) {
        Map<String, Object> conditionPart = (Map<String, Object>) tmp;
        conditionParts.put(
                (Integer) conditionPart.get('keyVal'),
                (String) conditionPart.get('field') + (String) conditionPart.get('condition') + (String) conditionPart.get('value')
        );
    }
    return conditionParts;
}

I have tested it on several examples and it looks fine:

@IsTest
static void test_getCondition() {
    String jsonString = '[{"keyVal":1,"field":"Mobile__c","condition":"=","value":"null"},{"keyVal":2,"field":"Store__r.Name","condition":"=","value":"null"},{"keyVal":3,"field":"Name","condition":"!=","value":"null"}]';
    Map<Integer, String> conditionParts = ConditionBuilder.getConditionParts(jsonString);
    String pattern = '(1 OR 2) AND 3';
    String condition = ConditionBuilder.getCondition(pattern, conditionParts);
    System.assertEquals('(Mobile__c=null OR Store__r.Name=null) AND Name!=null', condition);

    jsonString = '[{"keyVal":10,"field":"A","condition":"=","value":"2"},{"keyVal":2,"field":"B","condition":"=","value":"\'x\'"}]';
    conditionParts = ConditionBuilder.getConditionParts(jsonString);
    pattern = '10 AND 2';
    condition = ConditionBuilder.getCondition(pattern, conditionParts);
    System.assertEquals('A=2 AND B=\'x\'', condition);
}

Also, if you may know any batter way to operate with chars in Apex Stings, please, tell me, I'm wondering if it is one though.