You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@wicket.apache.org by pe...@apache.org on 2016/09/21 01:09:54 UTC
wicket git commit: WICKET-4008 parser differentiates java identifiers
from bean properties
Repository: wicket
Updated Branches:
refs/heads/WICKET-4008-property-expression-parser b0f7da85e -> 697052f71
WICKET-4008 parser differentiates java identifiers from bean properties
Project: http://git-wip-us.apache.org/repos/asf/wicket/repo
Commit: http://git-wip-us.apache.org/repos/asf/wicket/commit/697052f7
Tree: http://git-wip-us.apache.org/repos/asf/wicket/tree/697052f7
Diff: http://git-wip-us.apache.org/repos/asf/wicket/diff/697052f7
Branch: refs/heads/WICKET-4008-property-expression-parser
Commit: 697052f713345484b93f4ef61163587473b7b202
Parents: b0f7da8
Author: Pedro Henrique Oliveira dos Santos <pe...@apache.org>
Authored: Tue Sep 20 22:09:36 2016 -0300
Committer: Pedro Henrique Oliveira dos Santos <pe...@apache.org>
Committed: Tue Sep 20 22:09:36 2016 -0300
----------------------------------------------------------------------
.../core/util/lang/PropertyExpression.java | 70 ++++++++++++++---
.../util/lang/PropertyExpressionParser.java | 69 ++++++++++------
.../util/lang/PropertyExpressionParserTest.java | 82 +++++++++++---------
.../wicket/util/lang/PropertyResolverTest.java | 10 ++-
4 files changed, 160 insertions(+), 71 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/wicket/blob/697052f7/wicket-core/src/main/java/org/apache/wicket/core/util/lang/PropertyExpression.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/core/util/lang/PropertyExpression.java b/wicket-core/src/main/java/org/apache/wicket/core/util/lang/PropertyExpression.java
index 635f95e..dab79ec 100644
--- a/wicket-core/src/main/java/org/apache/wicket/core/util/lang/PropertyExpression.java
+++ b/wicket-core/src/main/java/org/apache/wicket/core/util/lang/PropertyExpression.java
@@ -18,21 +18,76 @@ package org.apache.wicket.core.util.lang;
public class PropertyExpression
{
- Property property;
+ JavaProperty javaProperty;
+ BeanProperty beanProperty;
CharSequence index;
PropertyExpression next;
- static class Property
+ static class BeanProperty
+ {
+ CharSequence propertyName;
+ CharSequence index;
+
+ public BeanProperty()
+ {
+ }
+
+ public BeanProperty(String name, String index)
+ {
+ this.propertyName = name;
+ this.index = index;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((index == null) ? 0 : index.hashCode());
+ result = prime * result + ((propertyName == null) ? 0 : propertyName.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj)
+ {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ BeanProperty other = (BeanProperty)obj;
+ if (index == null)
+ {
+ if (other.index != null)
+ return false;
+ }
+ else if (!index.equals(other.index))
+ return false;
+ if (propertyName == null)
+ {
+ if (other.propertyName != null)
+ return false;
+ }
+ else if (!propertyName.equals(other.propertyName))
+ return false;
+ return true;
+ }
+
+ }
+
+ static class JavaProperty
{
CharSequence javaIdentifier;
CharSequence index;
public boolean hasMethodSign;
- public Property()
+ public JavaProperty()
{
}
- public Property(String javaIdentifier, String index, boolean hasMethodSign)
+ public JavaProperty(String javaIdentifier, String index, boolean hasMethodSign)
{
this.javaIdentifier = javaIdentifier;
this.index = index;
@@ -59,7 +114,7 @@ public class PropertyExpression
return false;
if (getClass() != obj.getClass())
return false;
- Property other = (Property)obj;
+ JavaProperty other = (JavaProperty)obj;
if (hasMethodSign != other.hasMethodSign)
return false;
if (index == null)
@@ -79,11 +134,6 @@ public class PropertyExpression
return true;
}
- @Override
- public String toString()
- {
- return javaIdentifier + (index == null ? "" : "[" + index + "]");
- }
}
}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/wicket/blob/697052f7/wicket-core/src/main/java/org/apache/wicket/core/util/lang/PropertyExpressionParser.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/core/util/lang/PropertyExpressionParser.java b/wicket-core/src/main/java/org/apache/wicket/core/util/lang/PropertyExpressionParser.java
index 3ecb81e..2102456 100644
--- a/wicket-core/src/main/java/org/apache/wicket/core/util/lang/PropertyExpressionParser.java
+++ b/wicket-core/src/main/java/org/apache/wicket/core/util/lang/PropertyExpressionParser.java
@@ -20,25 +20,25 @@ import static java.lang.Character.isJavaIdentifierPart;
import static java.lang.Character.isJavaIdentifierStart;
import static java.lang.String.format;
-import org.apache.wicket.core.util.lang.PropertyExpression.Property;
+import org.apache.wicket.core.util.lang.PropertyExpression.BeanProperty;
+import org.apache.wicket.core.util.lang.PropertyExpression.JavaProperty;
/**
* EBNF like description of the property expression syntax <code>
*
- * java letter = "_" | "$" | "A" | "a" | "B" | "b" | (...) ;
+ * java letter = "_" | "$" | "A" | "a" | "B" | "b" | (...);
* java letter or digit = java letter | "0" | "1" | (...) ;
* char = java letter or digit | "." | "(" | ")" | "[" | "]" | "!" | "@" | "#" | (...);
- * index char = char - "]"
+ * index char = char - "]";
*
- * java identifier = java letter , {java letter or digit}
- * property name = java letter or digit , {java letter or digit}
- * method sign = "(" , { " " } , ")"
- * index = "[" , index char , {index char} , "]" ;
+ * java identifier = java letter , {java letter or digit};
+ * property name = java letter or digit , {java letter or digit};
+ * method sign = "(" , { " " } , ")";
+ * index = "[" , index char , { index char } , "]";
*
- * bean property = property name, [ index ]
- * java property = java identifier , [ index | method sign ]
- * map property = index
- * property expression = [ bean property | java property | map property ], { "." , property expression } ;
+ * bean property = property name, [ index ];
+ * java property = java identifier , [ index | method sign ];
+ * property expression = [ bean property | java property | index ] , { "." , property expression };
*
* </code>
*
@@ -99,9 +99,17 @@ public class PropertyExpressionParser
{
expression.index = index();
}
+ else if (Character.isJavaIdentifierStart(currentToken))
+ {
+ expression.javaProperty = javaProperty();
+ }
+ else if (Character.isJavaIdentifierPart(currentToken))
+ {
+ expression.beanProperty = beanProperty();
+ }
else
{
- expression.property = property();
+ throw new ParserException("Expecting an expression but got: " + currentToken);
}
switch (lookaheadToken)
{
@@ -113,14 +121,27 @@ public class PropertyExpressionParser
case END_OF_EXPRESSION :
return expression;
default :
- throw new ParserException(
- "Expecting a new expression but got: '" + lookaheadToken + "'");
+ throw new ParserException(format(
+ "Expecting a new expression but got the invalid character '%s' at: '%s<--'",
+ lookaheadToken, text.substring(0, nextPosition + 1)));
+ }
+ }
+
+ private BeanProperty beanProperty()
+ {
+ BeanProperty property = new BeanProperty();
+ property.propertyName = propertyName();
+ if (lookaheadToken == '[')
+ {
+ advance();// skips left bracket
+ property.index = index();
}
+ return property;
}
- private Property property()
+ private JavaProperty javaProperty()
{
- Property property = new Property();
+ JavaProperty property = new JavaProperty();
property.javaIdentifier = javaIdentifier();
switch (lookaheadToken)
{
@@ -136,13 +157,8 @@ public class PropertyExpressionParser
return property;
}
-
- private CharSequence javaIdentifier()
+ private CharSequence propertyName()
{
- if (!isJavaIdentifierStart(currentToken))
- {
- throw new ParserException("Expeting a java identifier but got a :" + currentToken);
- }
int begin = currentPosition;
while (isJavaIdentifierPart(lookaheadToken))
{
@@ -151,6 +167,15 @@ public class PropertyExpressionParser
return text.substring(begin, nextPosition);
}
+ private CharSequence javaIdentifier()
+ {
+ if (!isJavaIdentifierStart(currentToken))
+ {
+ throw new ParserException("Expeting a java identifier but got a :" + currentToken);
+ }
+ return propertyName();
+ }
+
private CharSequence index()
{
advance();// escape bracket
http://git-wip-us.apache.org/repos/asf/wicket/blob/697052f7/wicket-core/src/test/java/org/apache/wicket/core/util/lang/PropertyExpressionParserTest.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/test/java/org/apache/wicket/core/util/lang/PropertyExpressionParserTest.java b/wicket-core/src/test/java/org/apache/wicket/core/util/lang/PropertyExpressionParserTest.java
index 104a01d..ac5ed26 100644
--- a/wicket-core/src/test/java/org/apache/wicket/core/util/lang/PropertyExpressionParserTest.java
+++ b/wicket-core/src/test/java/org/apache/wicket/core/util/lang/PropertyExpressionParserTest.java
@@ -1,10 +1,11 @@
package org.apache.wicket.core.util.lang;
import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.nullValue;
import static org.junit.Assert.assertThat;
-import org.apache.wicket.core.util.lang.PropertyExpression.Property;
-import org.hamcrest.CoreMatchers;
+import org.apache.wicket.core.util.lang.PropertyExpression.BeanProperty;
+import org.apache.wicket.core.util.lang.PropertyExpression.JavaProperty;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
@@ -15,57 +16,62 @@ public class PropertyExpressionParserTest
@Rule
public ExpectedException expectedException = ExpectedException.none();
private PropertyExpressionParser parser = new PropertyExpressionParser();
-
+
@Test
public void shouldParsePropertyExpressions()
{
PropertyExpression expression = parser.parse("person");
- assertThat(expression.index, CoreMatchers.nullValue());
- assertThat(expression.property, is(new Property("person", null, false)));
- assertThat(expression.next, CoreMatchers.nullValue());
+ assertThat(expression.index, nullValue());
+ assertThat(expression.beanProperty, nullValue());
+ assertThat(expression.javaProperty, is(new JavaProperty("person", null, false)));
+ assertThat(expression.next, nullValue());
}
@Test
public void shouldParsePropertyExpressionStartingWithDigits()
{
PropertyExpression expression = parser.parse("1person");
- assertThat(expression.index, CoreMatchers.nullValue());
- assertThat(expression.property, is(new Property("person", null, false)));
- assertThat(expression.next, CoreMatchers.nullValue());
+ assertThat(expression.index, nullValue());
+ assertThat(expression.beanProperty, is(new BeanProperty("1person", null)));
+ assertThat(expression.javaProperty, nullValue());
+ assertThat(expression.next, nullValue());
}
-
+
@Test
public void shouldParseShortPropertyExpressions()
{
PropertyExpression expression = parser.parse("a");
- assertThat(expression.index, CoreMatchers.nullValue());
- assertThat(expression.property, is(new Property("a", null, false)));
- assertThat(expression.next, CoreMatchers.nullValue());
+ assertThat(expression.index, nullValue());
+ assertThat(expression.beanProperty, nullValue());
+ assertThat(expression.javaProperty, is(new JavaProperty("a", null, false)));
+ assertThat(expression.next, nullValue());
}
@Test
public void shouldParseIndexedPropertyExpressions()
{
PropertyExpression expression = parser.parse("person[age]");
- assertThat(expression.index, CoreMatchers.nullValue());
- assertThat(expression.property, is(new Property("person", "age", false)));
- assertThat(expression.next, CoreMatchers.nullValue());
+ assertThat(expression.index, nullValue());
+ assertThat(expression.beanProperty, nullValue());
+ assertThat(expression.javaProperty, is(new JavaProperty("person", "age", false)));
+ assertThat(expression.next, nullValue());
}
@Test
public void shouldParseMethodExpressions()
{
PropertyExpression expression = parser.parse("person()");
- assertThat(expression.index, CoreMatchers.nullValue());
- assertThat(expression.property, is(new Property("person", null, true)));
- assertThat(expression.next, CoreMatchers.nullValue());
+ assertThat(expression.index, nullValue());
+ assertThat(expression.beanProperty, nullValue());
+ assertThat(expression.javaProperty, is(new JavaProperty("person", null, true)));
+ assertThat(expression.next, nullValue());
}
@Test
public void shouldParsePropertyExpressionsWithSpaceInMethod()
{
final PropertyExpression parse = parser.parse("person( )");
- assertThat(parse.property, is(new Property("person", null, true)));
+ assertThat(parse.javaProperty, is(new JavaProperty("person", null, true)));
}
@Test
@@ -73,40 +79,40 @@ public class PropertyExpressionParserTest
{
PropertyExpression expression = parser.parse("[person#name]");
assertThat(expression.index, is("person#name"));
- assertThat(expression.property, CoreMatchers.nullValue());
- assertThat(expression.next, CoreMatchers.nullValue());
+ assertThat(expression.javaProperty, nullValue());
+ assertThat(expression.next, nullValue());
}
@Test
public void shouldParseChainedPropertyExpressions()
{
PropertyExpression expression = parser.parse("person.child");
- assertThat(expression.property, is(new Property("person", null, false)));
- assertThat(expression.next.property, is(new Property("child", null, false)));
+ assertThat(expression.javaProperty, is(new JavaProperty("person", null, false)));
+ assertThat(expression.next.javaProperty, is(new JavaProperty("child", null, false)));
}
@Test
public void shouldParseShortChainedPropertyExpressions()
{
PropertyExpression expression = parser.parse("a.b");
- assertThat(expression.property, is(new Property("a", null, false)));
- assertThat(expression.next.property, is(new Property("b", null, false)));
+ assertThat(expression.javaProperty, is(new JavaProperty("a", null, false)));
+ assertThat(expression.next.javaProperty, is(new JavaProperty("b", null, false)));
}
@Test
public void shouldParseChainedIndexedPropertyExpressions()
{
PropertyExpression expression = parser.parse("person[1].child");
- assertThat(expression.property, is(new Property("person", "1", false)));
- assertThat(expression.next.property, is(new Property("child", null, false)));
+ assertThat(expression.javaProperty, is(new JavaProperty("person", "1", false)));
+ assertThat(expression.next.javaProperty, is(new JavaProperty("child", null, false)));
}
@Test
public void shouldParseChainedMethodExpressions()
{
PropertyExpression expression = parser.parse("person().child");
- assertThat(expression.property, is(new Property("person", null, true)));
- assertThat(expression.next.property, is(new Property("child", null, false)));
+ assertThat(expression.javaProperty, is(new JavaProperty("person", null, true)));
+ assertThat(expression.next.javaProperty, is(new JavaProperty("child", null, false)));
}
@Test
@@ -114,16 +120,16 @@ public class PropertyExpressionParserTest
{
PropertyExpression expression = parser.parse("[person].child");
assertThat(expression.index, is("person"));
- assertThat(expression.next.property, is(new Property("child", null, false)));
+ assertThat(expression.next.javaProperty, is(new JavaProperty("child", null, false)));
}
@Test
public void shouldParseDeeperChainedPropertyExpressions()
{
PropertyExpression expression = parser.parse("person.child.name");
- assertThat(expression.property, is(new Property("person", null, false)));
- assertThat(expression.next.property, is(new Property("child", null, false)));
- assertThat(expression.next.next.property, is(new Property("name", null, false)));
+ assertThat(expression.javaProperty, is(new JavaProperty("person", null, false)));
+ assertThat(expression.next.javaProperty, is(new JavaProperty("child", null, false)));
+ assertThat(expression.next.next.javaProperty, is(new JavaProperty("name", null, false)));
}
@@ -139,7 +145,8 @@ public class PropertyExpressionParserTest
public void shouldFailParsePropertyExpressionsWithSpace()
{
expectedException.expect(ParserException.class);
- expectedException.expectMessage("Expecting a new expression but got: ' '");
+ expectedException.expectMessage(
+ "Expecting a new expression but got the invalid character ' ' at: 'per <--'");
parser.parse("per son");
}
@@ -161,13 +168,12 @@ public class PropertyExpressionParserTest
parser.parse("repository.getPerson(filter)");
}
- //TODO: better exception message
@Test
public void shouldFailParseInvalidMethodName()
{
expectedException.expect(ParserException.class);
- // expectedException.expectMessage(
- // "The expression can't have method parameters: 'repository.getPerson(<--'");
+ expectedException.expectMessage(
+ "Expecting a new expression but got the invalid character '#' at: 'repository.get#<--'");
parser.parse("repository.get#name()");
}
http://git-wip-us.apache.org/repos/asf/wicket/blob/697052f7/wicket-core/src/test/java/org/apache/wicket/util/lang/PropertyResolverTest.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/test/java/org/apache/wicket/util/lang/PropertyResolverTest.java b/wicket-core/src/test/java/org/apache/wicket/util/lang/PropertyResolverTest.java
index 14c0a98..5929eef 100644
--- a/wicket-core/src/test/java/org/apache/wicket/util/lang/PropertyResolverTest.java
+++ b/wicket-core/src/test/java/org/apache/wicket/util/lang/PropertyResolverTest.java
@@ -246,13 +246,21 @@ public class PropertyResolverTest extends WicketTestCase
}
@Test
- public void shouldMapKeysWithSpecialCharacters() throws Exception
+ public void shouldAllowMapKeysWithSpecialCharacters() throws Exception
{
String expression = "[!@#$%^&*()_+-=[{}|]";
PropertyResolver.setValue(expression, integerMap, AN_INTEGER, CONVERTER);
assertThat(PropertyResolver.getValue(expression, integerMap), is(AN_INTEGER));
assertThat(integerMap.get(expression), is(AN_INTEGER));
+ }
+ @Test
+ public void shouldAllowMapKeysHavingQuotes() throws Exception
+ {
+ String expression = "the\"key\"";
+ PropertyResolver.setValue(expression, integerMap, AN_INTEGER, CONVERTER);
+ assertThat(PropertyResolver.getValue(expression, integerMap), is(AN_INTEGER));
+ assertThat(integerMap.get(expression), is(AN_INTEGER));
}
@Test