Search code examples
javasqljdbctemplatenamed-parameters

Can we Replace a portion of String in Java which has symbol in the start and end to Identify?


I have a String SELECT *FROM USERS WHERE ID = '@userid@' AND ROLE = '@role@' Now i have replace any string between @...@ , with a actual value .

Expected output SELECT *FROM USERS WHERE ID = '4' AND ROLE = 'Admin'

This replace will happen from a method , i have written this logic

public String replaceQueryKeyWithValueFromKeyValues(String query, int reportId) {
    try {
        REPMReportDao repmReportDao = new REPMReportDao();
        int Start = 0;
        int end;
        if (query.contains("@")) {
            boolean specialSymbolFound = false;
            for (int i = 0; i < query.length(); i++) {
                if (query.charAt(i) == '@') {
                    if (!specialSymbolFound) {
                        Start = i + 1;
                        specialSymbolFound = true;
                    } else {
                        specialSymbolFound = false;
                        end = i;
                        query = query.replace(query.substring(Start - 1, end + 1), repmReportDao.getReportManagerKeyValue(query.substring(Start - 1, end + 1).replaceAll("@", ""), reportId));

                    }
                }
            }
            return query;
        } else {
            return query;
        }

    } catch (Exception e) {
        logger.log(Priority.ERROR, e.getMessage());
        return e.getMessage();
    }
}

It works fine , but in the case if a single '@' symbol exist instead of start and end it will fail. Like :

SELECT  *FROM USERS WHERE emailid = '[email protected]' AND ROLE = '@role@'

Here it should replace the only role '@role@' and should left email as it is.

Expected Output => SELECT *FROM USERS WHERE emailid = '[email protected]' AND ROLE = 'Admin'


Solution

  • Complete example with mocked data returned by getReportManagerKeyValue:

    import java.util.HashMap;
    import java.util.Map;
    import java.util.regex.Matcher;
    import java.util.regex.Pattern;
    
    public class StackOverflow54842971 {
    
        private static Map<String, String> map;
    
        public static void main(String[] args) {
            // preparing test data
            map = new HashMap<>();
            map.put("role", "Admin");
            map.put("userid", "666");
    
            // original query string
            String query = "SELECT * FROM USERS WHERE ID = '@userid@' AND emailid = '[email protected]' AND ROLE = '@role@' ";
    
            // regular expression to match everything between '@ and @' with capture group
            // omitting single quotes
            Pattern p = Pattern.compile("'(@[^@]*@)'");
            Matcher m = p.matcher(query);
            while (m.find()) {
                // every match will be replaced with value from getReportManagerKeyValue
                query = query.replace(m.group(1), getReportManagerKeyValue(m.group(1).replaceAll("@", "")));
            }
            System.out.println(query);
        }
    
        // you won't need this function
        private static String getReportManagerKeyValue(String key) {
            System.out.println("getting key " + key);
            if (!map.containsKey(key)) {
                return "'null'";
            }
            return map.get(key);
        }
    }