Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
hferentschik committed Feb 7, 2011
2 parents d040e5d + 2cecbc5 commit 7d51744
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 3 deletions.
Expand Up @@ -31,6 +31,7 @@
/**
* @author Hardy Ferentschik
* @author Gunnar Morling
* @author Kevin Pollet - SERLI - (kevin.pollet@serli.com)
*/
public final class PathImpl implements Path, Serializable {

Expand All @@ -43,7 +44,11 @@ public final class PathImpl implements Path, Serializable {
*
* @see <a href="http://www.regexplanet.com/simple/index.jsp">Regular expression tester</a>
*/
private static final Pattern PATH_PATTERN = Pattern.compile( "(\\w+)(\\[(\\w*)\\])?(\\.(.*))*" );
private static final String LEADING_PROPERTY_GROUP = "[^\\[\\.]+"; // everything up to a [ or .
private static final String OPTIONAL_INDEX_GROUP = "\\[(\\w*)\\]";
private static final String REMAINING_PROPERTY_STRING = "\\.(.*)"; // processed recursively

private static final Pattern PATH_PATTERN = Pattern.compile( "(" + LEADING_PROPERTY_GROUP + ")(" + OPTIONAL_INDEX_GROUP + ")?(" + REMAINING_PROPERTY_STRING + ")*" );
private static final int PROPERTY_NAME_GROUP = 1;
private static final int INDEXED_GROUP = 2;
private static final int INDEX_GROUP = 3;
Expand Down Expand Up @@ -284,8 +289,12 @@ private static PathImpl parseProperty(String property) {
Matcher matcher = PATH_PATTERN.matcher( tmp );
if ( matcher.matches() ) {

// create the node
String value = matcher.group( PROPERTY_NAME_GROUP );
if ( !isValidJavaIdentifier( value ) ) {
throw new IllegalArgumentException( value + " is not a valid Java Identifier" );
}

// create the node
path.addNode( value );

// is the node indexable
Expand Down Expand Up @@ -319,4 +328,32 @@ private static PathImpl parseProperty(String property) {

return path;
}

/**
* Validate that the given identifier is a valid Java identifier according to the Java Language Specification,
* <a href="http://java.sun.com/docs/books/jls/third_edition/html/lexical.html#3.8">chapter 3.8</a>
*
* @param identifier the identifier string
* @return true if the given identifier is a valid Java Identifier
*
* @throws IllegalArgumentException if the identifier is null
*/
private static boolean isValidJavaIdentifier(String identifier) {
Contracts.assertNotNull( identifier, "identifier param cannot be null" );

final char[] identifierChars = identifier.toCharArray();

if ( identifierChars.length == 0 || !Character.isJavaIdentifierStart( (int) identifierChars[0] ) ) {
return false;
}

for ( int i = 1; i < identifierChars.length; i++ ) {
if ( !Character.isJavaIdentifierPart( (int) identifierChars[i] ) ) {
return false;
}
}

return true;
}

}
Expand Up @@ -40,6 +40,7 @@
/**
* @author Hardy Ferentschik
* @author Gunnar Morling
* @author Kevin Pollet - SERLI - (kevin.pollet@serli.com)
*/
public class PathImplTest {

Expand Down Expand Up @@ -76,6 +77,35 @@ public void testParsing() {
assertEquals( path.toString(), property );
}

@Test
public void testParsingPropertyWithCurrencySymbol() {
PathImpl path = PathImpl.createPathFromString( "€Amount" );
Iterator<Path.Node> it = path.iterator();

assertEquals( it.next().getName(), "€Amount" );
}

@Test
public void testParsingPropertyWithGermanCharacter() {
PathImpl path = PathImpl.createPathFromString( "höchstBetrag" );
Iterator<Path.Node> it = path.iterator();

assertEquals( it.next().getName(), "höchstBetrag" );
}

@Test
public void testParsingPropertyWithUnicodeCharacter() {
PathImpl path = PathImpl.createPathFromString( "höchst\u00f6Betrag" );
Iterator<Path.Node> it = path.iterator();

assertEquals( it.next().getName(), "höchst\u00f6Betrag" );
}

@Test(expectedExceptions = IllegalArgumentException.class)
public void testParsingInvalidJavaProperty() {
PathImpl.createPathFromString( "1invalid" );
}

@Test
public void testParseMapBasedProperty() {
String property = "order[foo].deliveryAddress";
Expand Down
Expand Up @@ -23,18 +23,41 @@
import javax.validation.constraints.NotNull;
import javax.validation.metadata.BeanDescriptor;

import static org.testng.Assert.assertTrue;
import org.testng.annotations.Test;

import org.hibernate.validator.test.util.TestUtil;

import static org.hibernate.validator.test.util.TestUtil.assertCorrectPropertyPaths;
import static org.hibernate.validator.test.util.TestUtil.assertNumberOfViolations;
import static org.testng.Assert.assertTrue;

/**
* @author Hardy Ferentschik
* @author Kevin Pollet - SERLI - (kevin.pollet@serli.com)
*/
public class ValidatorTest {

/**
* HV-376
*/
@Test
public void testValidatePropertyWithCurrencySymbol() {
Validator validator = TestUtil.getValidator();
Ticket testInstance = new Ticket();
Set<ConstraintViolation<Ticket>> constraintViolations = validator.validateProperty( testInstance, "€price" );
assertNumberOfViolations( constraintViolations, 1 );
}

@Test
public void testValidateValueWithCurrencySymbol() {
Validator validator = TestUtil.getValidator();
Ticket testInstance = new Ticket();
Set<ConstraintViolation<Ticket>> constraintViolations = validator.validateValue(
Ticket.class, "€price", testInstance.€price
);
assertNumberOfViolations( constraintViolations, 1 );
}

/**
* HV-208
*/
Expand Down Expand Up @@ -70,4 +93,9 @@ public boolean hasB() {
return b;
}
}

class Ticket {
@NotNull
Floatprice;
}
}
3 changes: 3 additions & 0 deletions pom.xml
Expand Up @@ -55,6 +55,9 @@

<properties>
<slf4jVersion>1.6.1</slf4jVersion>

<!-- see http://maven.apache.org/general.html -->
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

<dependencyManagement>
Expand Down

0 comments on commit 7d51744

Please sign in to comment.