Regex Pattern Mapping

Dear All,

I had a class to parse HttpResponses. It simply uses validPattern to check whether the response is in valid format. If not it considered to be an error. Additionally, if the matchGroup of the validResponse is having the acceptedPattern response considered to be ACCEPTED otherwise REJECTED.

Ex:

validPattern = ".*(OK|FAILED).*";

matchGroup = 1;

acceptedPattern = "OK"

Relavent class implementation similar as follows:

publicclass RegexResponseParserimplements ResponseParser{

privatestatic Logger cat = Logger.getLogger(RegexResponseParser.class);

Pattern validPattern;

int matchGroup = 0;

Pattern acceptedPattern;

/**

* Create a response parser.

*

* @param validPattern a String containing a regular expression that defines a valid response

* text. If the response text does not match this pattern then the response is considered an

* error. The validPattern should contain embeded match groups (see responseGroup param).

* @param matchGroup The match group within the validPattern that is used to extract

* the portion of the response to be tested with the acceptedPattern.

* @param acceptedPattern a String containing a regular expression that defines an accepted

* response. The match group indicated by matchGroup is tested against the accepted pattern.

* If there is a match then the response is considered accepted, otherwise rejected.

**/

public RegexResponseParser(String validPattern,int matchGroup, String acceptedPattern){

this.validPattern = Pattern.compile(validPattern, Pattern.DOTALL);

this.matchGroup = matchGroup;

this.acceptedPattern = Pattern.compile(acceptedPattern, Pattern.DOTALL);

}

public TransferResponse parse(String response){

Matcher validMatcher = validPattern.matcher(response);

if (validMatcher.matches() ==false){

returnnew ErrorTransferResponse(response);

}

String matchText = validMatcher.group(matchGroup);

Matcher acceptedMatcher = acceptedPattern.matcher(matchText);

if (acceptedMatcher.matches() ==false){

returnnew RejectedTransferResponse(response);

}

else{

returnnew AcceptedTransferResponse(response);

}

}

}

In the new version of the application release this class was replaced with following class. Here the class is generalized to have a (pattern, code) mapping such as:

- (".*OK.*", ACCEPTED)

- (".*FAILED.*", REJECTED)

Here is the new Parser implementation:

publicclass RegExResponseParserextends ResponseParser{

private Map patternToCodeMap =new HashMap();

publicvoid setPatternToCodeMap(Map patternToCodeMap){

this.patternToCodeMap = patternToCodeMap;

}

public LeadStatusCode parse(Map parseEnv)throws ParseException{

String body = getResponseBody(parseEnv);

Set matchedCodes =new HashSet();

for (Iterator it = patternToCodeMap.keySet().iterator(); it.hasNext();){

String key = (String) it.next();

if (Pattern.compile(key, Pattern.DOTALL).matcher(body).matches())

matchedCodes.add(patternToCodeMap.get(key));

}

if (matchedCodes.size() > 0){

StringBuffer msg =new StringBuffer("Multiple status codes were parsed from the response body: ");

for (Iterator it = matchedCodes.iterator(); it.hasNext();){

msg.append(((LeadStatusCode) it.next()).getName());

if (it.hasNext()) msg.append(", ");

}

thrownew ParseException(msg.toString());

}elseif (rejectingNoMatch && matchedCodes.size() == 0){

return LeadStatusCode.REJECTED;

}elseif (!rejectingNoMatch && matchedCodes.size() == 0){

returnnull;

}else{

return (LeadStatusCode) matchedCodes.iterator().next();

}

}

We have many configurations passed to created old ResponseParser beans though Spring framwork as follows:

<bean id="responseParser" class="x.y.z.RegexResponseParser">

<property name="validPatternString">

<value>.*(OK|FAILED).*</value>

</property>

<property name="matchGroup">

<value>1</value>

</property>

<property name="acceptedPatternString">

<value>OK</value>

</property>

</bean>

<bean id="responseParser2" class="x.y.z.RegexResponseParser">

<property name="validPatternString">

<value>.*(SUCCESS|FAILED|QUEUED|REJECTED).*</value>

</property>

<property name="matchGroup">

<value>1</value>

</property>

<property name="acceptedPatternString">

<value>SUCCESS|QUEUED</value>

</property>

</bean>

Now we need to have a method in the new ResponseParser implementation to convert old ResponseParser class to new ones. I would really appriciate if you can suggest a senario for the following method implementation:

publicclass RegExResponseParserextends ResponseParser{

public ResponseParser convert(x.y.z.ResponseParser oldResponseParser){

// Mapping old parser patterns to new parser pattern

return newResponseParser;

}

}

[8345 byte] By [Sumitha] at [2007-10-3 4:01:27]
# 1

It is not clear what you want to do. It does not seem to be the regex problem suggested by the thread title. You seem to just want an adapter. Since the new parser has 4 results and the old has just 2 then you must first specify the mapping.

Also, these forums will help you with a problem but they do not provide a programming service. I assume you are getting paid for this work so you must at least show some effort.

sabre150a at 2007-7-14 22:00:40 > top of Java-index,Java Essentials,Java Programming...
# 2

Dear Sabre,

This is my problem in simple terms:

I have following pattern mapping in the previous implementation. Please note that number of matches can be varied.

validPattern = ".*(MATCH1|MATCH2|MATCH3|MATCH#).*"

If the parsed string match the above pattern I inspect matchGroup 1. MatchGroup can be varied as specified by the following variable.

matchGroup = 1

If the matchGroup contains MATCH1 parsing value expected to be ACCEPTED if it matches something else (ex: MATCH2) it is considered to be rejected.

acceptedPattern = "MATCH1|MATCH2"

In the new implementation we want to implementation what I need is this. Intead of keeping settings as validPattern, matchGroup & accetedPattern we need to implement a general way to handle this.

Therefore we are going to have a mapping as follows (of course it can extended to handle more status than ACCEPT and REJECT).

- (".*(MATCH1|MATCH2).*", ACCEPTED)

- (".*(MATCH3|MATCH#).*", REJECT)

My question lies at the place generating patterns like ".*MATCH1|MATCH2.*" and ".*(MATCH3|MATCH#).*" from above validPattern & acceptedPattern. If you can just suggest me a generic way determining these patterns to two variables as follows that's enough.

newAccept=".*MATCH1|MATCH2.*"

newReject=".*MATCH3|MATCH#.*"

I am not expecting any other help from you guys regarding the application implementation. I though that incorparating code may clear the fact (But of course it hasn't been so).

Regarding your final comments. I am sorry if I made you desapointed as a newaby joined the Java forum. But of course I may increase the quality of post as it goes.

Thanks for you frank comments. Hope I made this problem clear.

Regards,

Sumith

Sumitha at 2007-7-14 22:00:40 > top of Java-index,Java Essentials,Java Programming...
# 3

Sorry but I don't understand. I still don't see it as a regex problem. All I see is that you are replacing one regex with two. I don't understand what you mean by "generating patterns like ...".

I think I will have to let others deal with this. Maybe uncle-alice (the local regex Guru) will be able to understand your requirement.

Note - with regard to "I am sorry if I made you desapointed as a newaby joined the Java forum". In my first post I was commenting on your apparent requrest for someone to write code for you.

sabre150a at 2007-7-14 22:00:40 > top of Java-index,Java Essentials,Java Programming...
# 4

I think I get it. Right now, you're applying one regex to find out if the response is valid, and another regex to find out if response indicated success. If the first regex matches and the second fails, you conclude that the response indicated failure. But in future, you want the first regex to check for a "success" response and the second to check for a "failure" response, and if neither regex matches, you conclude that the response was invalid. What you want to do is to automatically generate the "failure" regex from the "valid" and "success" regexes you have now. This should do it: String valid = ".*(SUCCESS|FAILED|QUEUED|REJECTED).*";

String accepted = "SUCCESS|QUEUED";

String rejected = valid.replaceAll(accepted, "")

.replaceAll("\\|\\|+", "|").replaceAll("\\|\\B|\\B\\|", "");

As you can see, the tricky part is getting rid of the extra pipe characters, but this seems to work.

uncle_alicea at 2007-7-14 22:00:40 > top of Java-index,Java Essentials,Java Programming...
# 5

Thank you uncle_alice,

Your suggestion was very helpful. Considering your suggestions I came up with following solution to answer my question.

String newRejected = validPatternStr.replaceAll(acceptedPatternStr, "").replaceAll("\\|\\|+", "|").replaceAll("\\|\\B|\\B\\|", "");

String newAccepted = valid.replaceAll("\\(.*\\)", accepted);

Regards,

SG

Sumitha at 2007-7-14 22:00:40 > top of Java-index,Java Essentials,Java Programming...
# 6

String newAccepted = valid.replaceAll("\\(.*\\)", accepted);

// result: ".*SUCCESS|QUEUED.*"

You need to leave the parentheses in place, or the meaning is radically changed. It's probably best to construct the new regex the old-fashioned way: String newAccepted = ".*(" + accepted + ").*";

uncle_alicea at 2007-7-14 22:00:40 > top of Java-index,Java Essentials,Java Programming...
# 7

Thanks for your suggestion uncle_alice,

But String newAccepted = ".*(" + accepted + ").*";

is not applicable since the implementation should support following type of cases too.

// Existing configuration

String valid = ".*&lt;Status&gt;(MATCH1|MATCH2|MATCH3|MATCH#)&lt;/Status&gt;.*";

int matchGroup = 1;

String accepted = "MATCH1|MATCH2";

//Proposed implementation

String newAccepted = valid.replaceAll("\\(.*\\)", "(" + accepted + ")");

// Expected result: ".*<Status&gt;(MATCH1|MATCH2)&lt;/Status&gt;.*";

Sumitha at 2007-7-14 22:00:40 > top of Java-index,Java Essentials,Java Programming...
# 8
Looks good.
uncle_alicea at 2007-7-14 22:00:40 > top of Java-index,Java Essentials,Java Programming...