DefaultResolver being able to handle parenthesis "(" and ")" in mapped property key names
-----------------------------------------------------------------------------------------
Key: BEANUTILS-330
URL: https://issues.apache.org/jira/browse/BEANUTILS-330
Project: Commons BeanUtils
Issue Type: Improvement
Components: Expression Syntax
Environment: java version "1.6.0_03"
Java(TM) SE Runtime Environment (build 1.6.0_03-b05)
Java HotSpot(TM) Client VM (build 1.6.0_03-b05, mixed mode, sharing)
Reporter: Pierre Post
Fix For: 1.8.0
Unfortunately, the new {{org.apache.commons.beanutils.expression.DefaultResolver}} class is
unable to handle mapped property key names that contain parenthesis "(" and ")". Following
properties cause an exception when using {{BeanUtils.populate()}}.
{code:title=Bean.properties}job[0].param(anotherParam(key))=value{code}
{code:title=Bean.java}// JavaBean class
public class Bean {
private List<Job> job;
public static class Job {
private Map<String, String> param;
// appropriate public getters and setters here
}
// appropriate public getters and setters here
}{code}
{noformat}
java.lang.IllegalArgumentException: No bean specified
at org.apache.commons.beanutils.PropertyUtilsBean.getPropertyDescriptor(PropertyUtilsBean.java:874)
at org.apache.commons.beanutils.BeanUtilsBean.setProperty(BeanUtilsBean.java:933)
at org.apache.commons.beanutils.BeanUtilsBean.populate(BeanUtilsBean.java:830)
...
{noformat}
I slightly modified the {{getKey()}} and {{next()}} methods so that they can handle multiple
nested mapped delimiters. Now, when using a {{BeanUtilsBean}} instance with a {{PropertyUtilsBean}}
and my new resolver, the above properties are accepted without exception:
{code:title=MyResolver.java}public class MyResolver extends DefaultResolver {
// delimiter constants here
public String getKey(String expression) {
if (expression == null || expression.length() == 0) {
return null;
}
for (int i = 0; i < expression.length(); i++) {
char c = expression.charAt(i);
if (c == NESTED || c == INDEXED_START) {
return null;
} else if (c == MAPPED_START) {
int end = getMappedEnd(expression, i);
if (end < 0) {
throw new IllegalArgumentException("Missing End Delimiter");
}
return expression.substring(i + 1, end);
}
}
return null;
}
public String next(String expression) {
if (expression == null || expression.length() == 0) {
return null;
}
boolean indexed = false;
int mappedCount = 0;
for (int i = 0; i < expression.length(); i++) {
char c = expression.charAt(i);
if (indexed) {
if (c == INDEXED_END) {
return expression.substring(0, i + 1);
}
} else if (mappedCount > 0) {
if (c == MAPPED_START) {
mappedCount++;
} else if (c == MAPPED_END) {
mappedCount--;
if (mappedCount == 0) {
return expression.substring(0, i + 1);
}
}
} else {
if (c == NESTED) {
return expression.substring(0, i);
} else if (c == MAPPED_START) {
mappedCount++;
} else if (c == INDEXED_START) {
indexed = true;
}
}
}
return expression;
}
private int getMappedEnd(String expression, int start) {
int count = 0;
for (int i = start; i < expression.length(); i++) {
char c = expression.charAt(i);
if (c == MAPPED_START) {
count++;
} else if (c == MAPPED_END) {
count--;
if (count == 0) {
return i;
}
}
}
return -1;
}
}{code}
If the changes don't affect the other uses of a resolver, I would recommend to adapt {{DefaultResolver}}
accordingly as nothing forbids to have "(" and ")" in a key name if I correctly understand.
Best regards,
Pierre
--
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.
|