You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@commons.apache.org by "Niall Pemberton (JIRA)" <ji...@apache.org> on 2008/11/14 00:26:44 UTC

[jira] Commented: (BEANUTILS-330) DefaultResolver being able to handle parenthesis "(" and ")" in mapped property key names

    [ https://issues.apache.org/jira/browse/BEANUTILS-330?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12647460#action_12647460 ] 

Niall Pemberton commented on BEANUTILS-330:
-------------------------------------------

This has been requested before (BEANUTILS-109), but I'm not sure there a straightforward solution that works all the time - for example I don't believe your implementation would cope with a key of "ABC(DEF".



> 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
>
>   Original Estimate: 2h
>  Remaining Estimate: 2h
>
> 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.