Recently I had to update a lot of user access rules in RSA IGL again.

If I have to do such batch jobs, I usually create an XML file and import it through the provided user interface.

This time I had to adjust the rule design, which basically meant parsing SQL where statements and changing the way they work technically, without changing the result of the where clause.

One important part of that was to keep of course the logical order, but my colleagues had made excessive use of unnecessary parenthesis during the rule implementation.

So here is a small method, which will replace unmatched parenthesis in a provided text for you. 

I can not recommend to try and do this with regular expressions. You will most likely fail and even if you succeed it bears a certain risk opposed to using a simple Stack.

However, be careful when using this. I had to make sure not to change the meaning of the rules, which I accomplished using a mix of regular expressions and the below method.

I replaced with regex and then used this to clean up afterwards. Luckily I could follow this approach.

Source Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
	/**
	 * Replaces each unmatched parenthesis in a provided StringBuffer with a
	 * whitespace.
	 *
	 * @param text
	 *            - a text to replace unmatched parenthesis in.
	 * @return the passed StringBuffer, which is anyhow handed by reference.
	 *         Just for convenience / readability.
	 */
	public static StringBuffer replaceUnmatchedParenthesis(StringBuffer text) {
		Stack<Integer> st = new Stack<Integer>();
		/*
		 * Loop over all chars in provided StringBuffer.
		 */
		for (int i = 0; i < text.length(); i++) {
			/*
			 * If a[i] is opening bracket then push into stack.
			 */
			if (text.charAt(i) == '(') {
				st.push(i);
				/*
				 * If a[i] is closing bracket ')'.
				 */
			} else if (text.charAt(i) == ')') {
				/*
				 * The stack will be empty, if this closing bracket is
				 * unmatched.
				 */
				if (st.empty()) {
					text.replace(i, i + 1, " ");
				} else {
					/*
					 * Pop the opening parenthesis position from our stack,
					 * since we found a closing match.
					 */
					st.pop();
				}
			}
		}
		/*
		 * If the stack is not empty, we still have to pop out and replace all
		 * positions of unmatched opening parenthesis.
		 */
		while (!st.empty()) {
			text.replace(st.peek(), st.peek() + 1, " ");
			st.pop();
		}
		return text
	}