gatein SVN: r5310 - in portal/branches/navcontroller/component/web/controller: src/main/java/org/exoplatform/web/controller/regexp and 3 other directories.
by do-not-reply@jboss.org
Author: julien_viet
Date: 2010-11-27 16:29:45 -0500 (Sat, 27 Nov 2010)
New Revision: 5310
Added:
portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/router/MalformedRegExpException.java
Modified:
portal/branches/navcontroller/component/web/controller/pom.xml
portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/Parser.java
portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/RegExpParser.java
portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/SyntaxException.java
portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/router/RegExpAnalyser.java
portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/router/Route.java
portal/branches/navcontroller/component/web/controller/src/test/java/org/exoplatform/web/controller/regexp/TestParser.java
portal/branches/navcontroller/component/web/controller/src/test/java/org/exoplatform/web/controller/router/TestMatch.java
portal/branches/navcontroller/component/web/controller/src/test/java/org/exoplatform/web/controller/router/TestPortal.java
portal/branches/navcontroller/component/web/controller/src/test/java/org/exoplatform/web/controller/router/TestRegExpAnalyser.java
portal/branches/navcontroller/component/web/controller/src/test/java/org/exoplatform/web/controller/router/TestRender.java
Log:
- use checked exceptions
- fix wrong parsing of alternatives (|)
- use regex analyzer in router
Modified: portal/branches/navcontroller/component/web/controller/pom.xml
===================================================================
--- portal/branches/navcontroller/component/web/controller/pom.xml 2010-11-27 13:17:30 UTC (rev 5309)
+++ portal/branches/navcontroller/component/web/controller/pom.xml 2010-11-27 21:29:45 UTC (rev 5310)
@@ -40,5 +40,10 @@
<groupId>org.exoplatform.portal</groupId>
<artifactId>exo.portal.component.web.resources</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.exoplatform.portal</groupId>
+ <artifactId>exo.portal.component.test.core</artifactId>
+ <scope>test</scope>
+ </dependency>
</dependencies>
</project>
Modified: portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/Parser.java
===================================================================
--- portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/Parser.java 2010-11-27 13:17:30 UTC (rev 5309)
+++ portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/Parser.java 2010-11-27 21:29:45 UTC (rev 5310)
@@ -83,9 +83,16 @@
return to;
}
- protected final int lastIndexOf(char c)
+ /**
+ * Finds the first index of the occurence of the specified char from a specified index.
+ *
+ * @param c the char to match
+ * @param start the start index
+ * @return the matched char index or -1
+ */
+ protected final int indexOf(char c, int start)
{
- for (int i = to - 1;i >= from;i--)
+ for (int i = start;i < to;i++)
{
if (s.charAt(i) == c)
{
Modified: portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/RegExpParser.java
===================================================================
--- portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/RegExpParser.java 2010-11-27 13:17:30 UTC (rev 5309)
+++ portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/RegExpParser.java 2010-11-27 21:29:45 UTC (rev 5310)
@@ -73,10 +73,11 @@
* disjunction -> alternative | alternative '|' disjunction
*
* @return the disjunction
+ * @throws SyntaxException any syntax exception
*/
- public RENode.Disjunction parseDisjunction()
+ public RENode.Disjunction parseDisjunction() throws SyntaxException
{
- int pipe = lastIndexOf('|');
+ int pipe = indexOf('|', from);
if (pipe == -1)
{
return new RENode.Disjunction(parseAlternative());
@@ -96,8 +97,9 @@
* alternative -> expression | expression '|' alternative
*
* @return the alternative
+ * @throws SyntaxException any syntax exception
*/
- public RENode.Alternative parseAlternative()
+ public RENode.Alternative parseAlternative() throws SyntaxException
{
if (index < to)
{
@@ -119,7 +121,8 @@
}
/**
- * expression -> assertion | '(' disjunction ')' | character | expression quantifier
+ * expression -> assertion | group | character | expression quantifier
+ * group -> '(' disjunction ')' | '(' '?' ':' disjunction ')'
* assertion -> '^' | '$'
* character -> '.' | escaped | character_class | literal
* escaped -> '\' any char
@@ -127,8 +130,9 @@
* quantifier_prefix -> '*' | '+' | '?' | '{' count '}' | '{' count ',' '}' | '{' count ',' count '}'
*
* @return the expression
+ * @throws SyntaxException any syntax exception
*/
- public RENode.Exp parseExpression()
+ public RENode.Exp parseExpression() throws SyntaxException
{
if (index == to)
{
@@ -230,13 +234,13 @@
}
//
- exp.quantifier = parseQuantifierSymbol();
+ exp.quantifier = parseQuantifier();
//
return exp;
}
- Quantifier parseQuantifierSymbol()
+ Quantifier parseQuantifier() throws SyntaxException
{
if (index < to)
{
@@ -320,8 +324,9 @@
* @param begin the begin
* @param end the end
* @return a character class expression
+ * @throws SyntaxException any syntax exception
*/
- private RENode.CharacterClassExpr parseCharacterClass(int begin, int end)
+ private RENode.CharacterClassExpr parseCharacterClass(int begin, int end) throws SyntaxException
{
if (begin == end)
{
Modified: portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/SyntaxException.java
===================================================================
--- portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/SyntaxException.java 2010-11-27 13:17:30 UTC (rev 5309)
+++ portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/SyntaxException.java 2010-11-27 21:29:45 UTC (rev 5310)
@@ -23,7 +23,7 @@
* @author <a href="mailto:julien.viet@exoplatform.com">Julien Viet</a>
* @version $Revision$
*/
-public class SyntaxException extends RuntimeException
+public class SyntaxException extends Exception
{
public SyntaxException()
{
Added: portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/router/MalformedRegExpException.java
===================================================================
--- portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/router/MalformedRegExpException.java (rev 0)
+++ portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/router/MalformedRegExpException.java 2010-11-27 21:29:45 UTC (rev 5310)
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2010 eXo Platform SAS.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.exoplatform.web.controller.router;
+
+/**
+ * @author <a href="mailto:julien.viet@exoplatform.com">Julien Viet</a>
+ * @version $Revision$
+ */
+public class MalformedRegExpException extends Exception
+{
+ public MalformedRegExpException()
+ {
+ }
+
+ public MalformedRegExpException(String s)
+ {
+ super(s);
+ }
+
+ public MalformedRegExpException(String s, Throwable throwable)
+ {
+ super(s, throwable);
+ }
+
+ public MalformedRegExpException(Throwable throwable)
+ {
+ super(throwable);
+ }
+}
Modified: portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/router/RegExpAnalyser.java
===================================================================
--- portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/router/RegExpAnalyser.java 2010-11-27 13:17:30 UTC (rev 5309)
+++ portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/router/RegExpAnalyser.java 2010-11-27 21:29:45 UTC (rev 5310)
@@ -22,6 +22,7 @@
import org.exoplatform.web.controller.regexp.Quantifier;
import org.exoplatform.web.controller.regexp.RENode;
import org.exoplatform.web.controller.regexp.RegExpParser;
+import org.exoplatform.web.controller.regexp.SyntaxException;
/**
* @author <a href="mailto:julien.viet@exoplatform.com">Julien Viet</a>
@@ -31,47 +32,44 @@
{
/** . */
- private StringBuilder sb;
+ private StringBuilder pattern;
/** . */
- private boolean groupContainer;
-
- /** . */
private boolean needReset;
public RegExpAnalyser()
{
- this.sb = new StringBuilder();
- this.groupContainer = false;
+ this.pattern = new StringBuilder();
this.needReset = false;
}
- public boolean isGroupContainer()
- {
- return groupContainer;
- }
-
public String getPattern()
{
- return sb.toString();
+ return pattern.toString();
}
public RegExpAnalyser reset()
{
- sb.setLength(0);
- groupContainer = false;
+ pattern.setLength(0);
needReset = false;
return this;
}
- public void process(CharSequence pattern)
+ public void process(CharSequence pattern) throws MalformedRegExpException
{
- RegExpParser parser = new RegExpParser(pattern);
- RENode.Disjunction disjunction = parser.parseDisjunction();
- process(disjunction);
+ try
+ {
+ RegExpParser parser = new RegExpParser(pattern);
+ RENode.Disjunction disjunction = parser.parseDisjunction();
+ process(disjunction);
+ }
+ catch (SyntaxException e)
+ {
+ throw new MalformedRegExpException(e);
+ }
}
- public void process(RENode.Disjunction disjunction)
+ public void process(RENode.Disjunction disjunction) throws MalformedRegExpException
{
if (needReset)
{
@@ -83,18 +81,18 @@
visit(disjunction);
}
- private void visit(RENode.Disjunction disjunction)
+ private void visit(RENode.Disjunction disjunction) throws MalformedRegExpException
{
visit(disjunction.getAlternative());
RENode.Disjunction next = disjunction.getNext();
if (next != null)
{
- sb.append('|');
+ pattern.append('|');
visit(next);
}
}
- private void visit(RENode.Alternative alternative)
+ private void visit(RENode.Alternative alternative) throws MalformedRegExpException
{
visit(alternative.getExp());
RENode.Alternative next = alternative.getNext();
@@ -104,78 +102,84 @@
}
}
- private void visit(RENode.Exp expression)
+ private void visit(RENode.Exp expression) throws MalformedRegExpException
{
Quantifier quantifier = null;
if (expression instanceof RENode.Dot)
{
- sb.append('.');
+ pattern.append('.');
quantifier = expression.getQuantifier();
}
else if (expression instanceof RENode.Group)
{
RENode.Group group = (RENode.Group)expression;
- sb.append(groupContainer ? "(?:" : "(");
- groupContainer = true;
+ pattern.append("(?:");
visit(group.getDisjunction());
- sb.append(")");
+ pattern.append(")");
quantifier = expression.getQuantifier();
}
else if (expression instanceof RENode.Character)
{
RENode.Character character = (RENode.Character)expression;
- sb.append(character.getValue());
+ pattern.append(character.getValue());
quantifier = expression.getQuantifier();
}
else if (expression instanceof RENode.CharacterClass)
{
RENode.CharacterClass characterClass = (RENode.CharacterClass)expression;
- sb.append("[");
- visit(characterClass.getExpr());
- sb.append("]");
+ pattern.append("[");
+ visit(characterClass.getExpr(), true);
+ pattern.append("]");
quantifier = expression.getQuantifier();
}
//
if (quantifier != null)
{
- sb.append(quantifier);
+ pattern.append(quantifier);
}
}
- private void visit(RENode.CharacterClassExpr expr)
+ private void visit(RENode.CharacterClassExpr expr, boolean braced)
{
if (expr instanceof RENode.CharacterClassExpr.Simple)
{
RENode.CharacterClass.CharacterClassExpr.Simple simple = (RENode.CharacterClass.CharacterClassExpr.Simple)expr;
- sb.append(simple.getValue());
+ pattern.append(simple.getValue());
}
else if (expr instanceof RENode.CharacterClass.CharacterClassExpr.Range)
{
RENode.CharacterClass.CharacterClassExpr.Range range = (RENode.CharacterClass.CharacterClassExpr.Range)expr;
- sb.append(range.getFrom());
- sb.append('-');
- sb.append(range.getTo());
+ pattern.append(range.getFrom());
+ pattern.append('-');
+ pattern.append(range.getTo());
}
else if (expr instanceof RENode.CharacterClass.CharacterClassExpr.And)
{
RENode.CharacterClass.CharacterClassExpr.And and = (RENode.CharacterClass.CharacterClassExpr.And)expr;
- visit(and.getLeft());
- sb.append("&&");
- visit(and.getRight());
+ visit(and.getLeft(), false);
+ pattern.append("&&");
+ visit(and.getRight(), false);
}
else if (expr instanceof RENode.CharacterClass.CharacterClassExpr.Or)
{
RENode.CharacterClass.CharacterClassExpr.Or or = (RENode.CharacterClass.CharacterClassExpr.Or)expr;
- visit(or.getLeft());
- visit(or.getRight());
+ visit(or.getLeft(), false);
+ visit(or.getRight(), false);
}
else if (expr instanceof RENode.CharacterClass.CharacterClassExpr.Not)
{
RENode.CharacterClass.CharacterClassExpr.Not not = (RENode.CharacterClass.CharacterClassExpr.Not)expr;
- sb.append("[^");
- visit(not.getNegated());
- sb.append(']');
+ if (!braced)
+ {
+ pattern.append("[");
+ }
+ pattern.append("^");
+ visit(not.getNegated(), false);
+ if (!braced)
+ {
+ pattern.append(']');
+ }
}
}
}
Modified: portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/router/Route.java
===================================================================
--- portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/router/Route.java 2010-11-27 13:17:30 UTC (rev 5309)
+++ portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/router/Route.java 2010-11-27 21:29:45 UTC (rev 5310)
@@ -396,12 +396,26 @@
for (int i = 0;i < route.params.size();i++)
{
PathParam param = route.params.get(i);
- String value = matcher.group(group++);
- if (param.encodingMode == EncodingMode.DEFAULT_FORM)
+
+ //
+ String value = matcher.group(group);
+
+ //
+ if (value != null)
{
- value = value.replace(slashEscape, '/');
+ if (param.encodingMode == EncodingMode.DEFAULT_FORM)
+ {
+ value = value.replace(slashEscape, '/');
+ }
+ response.put(param.name, value);
}
- response.put(param.name, value);
+ else
+ {
+ // We have an optional match
+ }
+
+ //
+ group++;
}
//
@@ -630,20 +644,27 @@
}
// Now analyse the regexp
-// RegExpAnalyser analyser = new RegExpAnalyser();
-// analyser.process(regex);
-// String regex2 = analyser.getPattern();
-// System.out.println("" + regex + " -> " + regex2);
+ String regex2;
+ try
+ {
+ RegExpAnalyser analyser = new RegExpAnalyser();
+ analyser.process(regex);
+ regex2 = analyser.getPattern();
+ System.out.println("" + regex + " -> " + regex2);
+ }
+ catch (MalformedRegExpException e)
+ {
+ throw new RuntimeException(e);
+ }
//
- builder.expr("(").expr(regex).expr(")");
+ builder.expr("(").expr(regex2).expr(")");
//
parameterPatterns.add(new PathParam(
parameterQName,
encodingMode,
- Pattern.compile("^" + regex + "$")
- ));
+ Pattern.compile("^" + regex + "$")));
previous = end.get(i) + 1;
}
@@ -653,6 +674,7 @@
// Julien : should the pattern end with a $ ?????? I don't see that for now
// we need to figure out clearly
Pattern pattern = builder.build();
+ System.out.println("pattern = " + pattern);
PatternRoute route = new PatternRoute(pattern, parameterPatterns, chunks);
// Wire
Modified: portal/branches/navcontroller/component/web/controller/src/test/java/org/exoplatform/web/controller/regexp/TestParser.java
===================================================================
--- portal/branches/navcontroller/component/web/controller/src/test/java/org/exoplatform/web/controller/regexp/TestParser.java 2010-11-27 13:17:30 UTC (rev 5309)
+++ portal/branches/navcontroller/component/web/controller/src/test/java/org/exoplatform/web/controller/regexp/TestParser.java 2010-11-27 21:29:45 UTC (rev 5310)
@@ -19,7 +19,9 @@
package org.exoplatform.web.controller.regexp;
+import junit.framework.AssertionFailedError;
import junit.framework.TestCase;
+import org.exoplatform.component.test.BaseGateInTest;
import java.util.regex.Pattern;
@@ -27,7 +29,7 @@
* @author <a href="mailto:julien.viet@exoplatform.com">Julien Viet</a>
* @version $Revision$
*/
-public class TestParser extends TestCase
+public class TestParser extends BaseGateInTest
{
@@ -52,18 +54,32 @@
}
ParserTester assertParseCharacterClass(String expectedValue)
{
- RENode node = parser.parseExpression();
- assertTrue(node instanceof RENode.CharacterClass);
- assertEquals(expectedValue, node.toString());
- return this;
+ try
+ {
+ RENode node = parser.parseExpression();
+ assertTrue(node instanceof RENode.CharacterClass);
+ assertEquals(expectedValue, node.toString());
+ return this;
+ }
+ catch (SyntaxException e)
+ {
+ return fail(e);
+ }
}
ParserTester assertParseDisjunction(String expectedValue)
{
- int expectedIndex = parser.getTo();
- RENode.Disjunction disjunction = parser.parseDisjunction();
- assertEquals(expectedValue, disjunction.toString());
- assertEquals(expectedIndex, parser.getIndex());
- return this;
+ try
+ {
+ int expectedIndex = parser.getTo();
+ RENode.Disjunction disjunction = parser.parseDisjunction();
+ assertEquals(expectedValue, disjunction.toString());
+ assertEquals(expectedIndex, parser.getIndex());
+ return this;
+ }
+ catch (SyntaxException e)
+ {
+ return fail(e);
+ }
}
ParserTester assertNotParseDisjunction()
{
@@ -81,10 +97,17 @@
}
ParserTester assertParseExpression(String expectedValue, int expectedIndex)
{
- RENode.Exp exp = parser.parseExpression();
- assertEquals(expectedValue, exp.toString());
- assertEquals(expectedIndex, parser.getIndex());
- return this;
+ try
+ {
+ RENode.Exp exp = parser.parseExpression();
+ assertEquals(expectedValue, exp.toString());
+ assertEquals(expectedIndex, parser.getIndex());
+ return this;
+ }
+ catch (SyntaxException e)
+ {
+ return fail(e);
+ }
}
ParserTester assertNotParseExpression()
{
@@ -103,14 +126,23 @@
ParserTester assertParseQuantifier(int expectedIndex, Quantifier expectedQuantifier)
{
int index = parser.getIndex();
+ Quantifier quantifier;
+ try
+ {
+ quantifier = parser.parseQuantifier();
+ }
+ catch (SyntaxException e)
+ {
+ return fail(e);
+ }
if (expectedQuantifier != null)
{
- assertEquals(expectedQuantifier, parser.parseQuantifierSymbol());
+ assertEquals(expectedQuantifier, quantifier);
assertEquals(expectedIndex, parser.getIndex());
}
else
{
- assertNull(parser.parseQuantifierSymbol());
+ assertNull(quantifier);
assertEquals(expectedIndex, parser.getIndex());
}
return this;
@@ -128,6 +160,7 @@
new ParserTester("^$").assertParseDisjunction("<^/><$/>");
new ParserTester("a").assertParseDisjunction("<c>a</c>");
new ParserTester("a|b").assertParseDisjunction("<c>a</c>|<c>b</c>");
+ new ParserTester("a|b|c").assertParseDisjunction("<c>a</c>|<c>b</c>|<c>c</c>");
new ParserTester("a+|b*").assertParseDisjunction("<+><c>a</c></+>|<*><c>b</c></*>");
}
Modified: portal/branches/navcontroller/component/web/controller/src/test/java/org/exoplatform/web/controller/router/TestMatch.java
===================================================================
--- portal/branches/navcontroller/component/web/controller/src/test/java/org/exoplatform/web/controller/router/TestMatch.java 2010-11-27 13:17:30 UTC (rev 5309)
+++ portal/branches/navcontroller/component/web/controller/src/test/java/org/exoplatform/web/controller/router/TestMatch.java 2010-11-27 21:29:45 UTC (rev 5310)
@@ -195,7 +195,7 @@
public void testLang() throws Exception
{
RouterDescriptor routerMD = new RouterDescriptor();
- routerMD.addRoute(new RouteDescriptor("/{a}b").addPathParam(QualifiedName.parse("a"), "(?:[A-Za-z]{2}/)?", EncodingMode.PRESERVE_PATH));
+ routerMD.addRoute(new RouteDescriptor("/{a}b").addPathParam(QualifiedName.parse("a"), "(([A-Za-z]{2})/)?", EncodingMode.PRESERVE_PATH));
Router router = new Router(routerMD);
//
Modified: portal/branches/navcontroller/component/web/controller/src/test/java/org/exoplatform/web/controller/router/TestPortal.java
===================================================================
--- portal/branches/navcontroller/component/web/controller/src/test/java/org/exoplatform/web/controller/router/TestPortal.java 2010-11-27 13:17:30 UTC (rev 5309)
+++ portal/branches/navcontroller/component/web/controller/src/test/java/org/exoplatform/web/controller/router/TestPortal.java 2010-11-27 21:29:45 UTC (rev 5310)
@@ -47,7 +47,7 @@
{
RouterDescriptor routerMD = new RouterDescriptor().addRoute(
new RouteDescriptor("/{gtn:lang}public").addPathParam(
- QualifiedName.parse("gtn:lang"), "([A-Za-z][A-Za-z]/)?", EncodingMode.PRESERVE_PATH)
+ QualifiedName.parse("gtn:lang"), "([A-Za-z]{2}/)?", EncodingMode.PRESERVE_PATH)
);
Router router = new Router(routerMD);
assertEquals(Collections.singletonMap(QualifiedName.parse("gtn:lang"), ""), router.route("/public"));
@@ -59,7 +59,7 @@
RouterDescriptor routerMD = new RouterDescriptor().
addRoute(new RouteDescriptor("/public")).
addRoute(new RouteDescriptor("/{gtn:lang}/public").
- addPathParam(QualifiedName.parse("gtn:lang"), "([A-Za-z][A-Za-z])", EncodingMode.DEFAULT_FORM
+ addPathParam(QualifiedName.parse("gtn:lang"), "([A-Za-z]{2})", EncodingMode.DEFAULT_FORM
)
);
Router router = new Router(routerMD);
Modified: portal/branches/navcontroller/component/web/controller/src/test/java/org/exoplatform/web/controller/router/TestRegExpAnalyser.java
===================================================================
--- portal/branches/navcontroller/component/web/controller/src/test/java/org/exoplatform/web/controller/router/TestRegExpAnalyser.java 2010-11-27 13:17:30 UTC (rev 5309)
+++ portal/branches/navcontroller/component/web/controller/src/test/java/org/exoplatform/web/controller/router/TestRegExpAnalyser.java 2010-11-27 21:29:45 UTC (rev 5310)
@@ -19,49 +19,72 @@
package org.exoplatform.web.controller.router;
-import junit.framework.TestCase;
+import org.exoplatform.component.test.BaseGateInTest;
/**
* @author <a href="mailto:julien.viet@exoplatform.com">Julien Viet</a>
* @version $Revision$
*/
-public class TestRegExpAnalyser extends TestCase
+public class TestRegExpAnalyser extends BaseGateInTest
{
/** . */
private RegExpAnalyser analyser = new RegExpAnalyser();
- private void assertAnalyse(String expectedPattern, boolean expectedGroupContainer, String pattern)
+ private void assertAnalyse(String expectedPattern, String pattern)
{
+ try
+ {
+ analyser.reset();
+ analyser.process(pattern);
+ assertEquals(expectedPattern, analyser.getPattern());
+ }
+ catch (MalformedRegExpException e)
+ {
+ fail(e);
+ }
+ }
+
+ private void assertAnalyseFails(String pattern)
+ {
analyser.reset();
- analyser.process(pattern);
- assertEquals(expectedPattern, analyser.getPattern());
- assertEquals(expectedGroupContainer, analyser.isGroupContainer());
+ try
+ {
+ analyser.process(pattern);
+ fail();
+ }
+ catch (MalformedRegExpException e)
+ {
+ }
}
public void testCharacterClass()
{
- assertAnalyse("[a]", false, "[a]");
- assertAnalyse("[ab]", false, "[ab]");
- assertAnalyse("[ab]", false, "[a[b]]");
- assertAnalyse("[abc]", false, "[abc]");
- assertAnalyse("[abc]", false, "[[a]bc]");
- assertAnalyse("[abc]", false, "[a[b]c]");
- assertAnalyse("[abc]", false, "[ab[c]]");
- assertAnalyse("[abc]", false, "[[ab]c]");
- assertAnalyse("[abc]", false, "[a[bc]]");
- assertAnalyse("[abc]", false, "[[abc]]");
+ assertAnalyse("[a]", "[a]");
+ assertAnalyse("[ab]", "[ab]");
+ assertAnalyse("[ab]", "[a[b]]");
+ assertAnalyse("[abc]", "[abc]");
+ assertAnalyse("[abc]", "[[a]bc]");
+ assertAnalyse("[abc]", "[a[b]c]");
+ assertAnalyse("[abc]", "[ab[c]]");
+ assertAnalyse("[abc]", "[[ab]c]");
+ assertAnalyse("[abc]", "[a[bc]]");
+ assertAnalyse("[abc]", "[[abc]]");
+ assertAnalyse("[^a]", "[^a]");
}
public void testGroupContainer()
{
- assertAnalyse("(abc)", true, "(abc)");
- assertAnalyse("(a(?:bc))", true, "(a(bc))");
- assertAnalyse("(a)(?:b)", true, "(a)(b)");
+ assertAnalyse("(?:a)", "(a)");
+ assertAnalyse("(?:a(?:b))", "(a(?:b))");
+ assertAnalyse("(?:a(?:b))", "(?:a(b))");
+ assertAnalyse("(?:a)(?:b)", "(a)(?:b)");
+ assertAnalyse("(?:a(?:b))", "(a(b))");
+ assertAnalyse("(?:a)(?:b)", "(a)(b)");
}
public void testBilto()
{
- assertAnalyse("[a]+", false, "[a]+");
+ assertAnalyse("[a]+", "[a]+");
}
}
Modified: portal/branches/navcontroller/component/web/controller/src/test/java/org/exoplatform/web/controller/router/TestRender.java
===================================================================
--- portal/branches/navcontroller/component/web/controller/src/test/java/org/exoplatform/web/controller/router/TestRender.java 2010-11-27 13:17:30 UTC (rev 5309)
+++ portal/branches/navcontroller/component/web/controller/src/test/java/org/exoplatform/web/controller/router/TestRender.java 2010-11-27 21:29:45 UTC (rev 5310)
@@ -153,7 +153,7 @@
public void testLang() throws Exception
{
RouterDescriptor routerMD = new RouterDescriptor();
- routerMD.addRoute(new RouteDescriptor("/{a}b").addPathParam(QualifiedName.parse("a"), "(?:[A-Za-z]{2}/)?", EncodingMode.PRESERVE_PATH));
+ routerMD.addRoute(new RouteDescriptor("/{a}b").addPathParam(QualifiedName.parse("a"), "(([A-Za-z]{2})/)?", EncodingMode.PRESERVE_PATH));
Router router = new Router(routerMD);
//
14 years, 1 month
gatein SVN: r5309 - portal/branches/navcontroller/component/test/core/src/main/java/org/exoplatform/component/test.
by do-not-reply@jboss.org
Author: julien_viet
Date: 2010-11-27 08:17:30 -0500 (Sat, 27 Nov 2010)
New Revision: 5309
Added:
portal/branches/navcontroller/component/test/core/src/main/java/org/exoplatform/component/test/BaseGateInTest.java
Modified:
portal/branches/navcontroller/component/test/core/src/main/java/org/exoplatform/component/test/AbstractGateInTest.java
Log:
introduce BaseGateInTest to have some usefull things not in junit
Modified: portal/branches/navcontroller/component/test/core/src/main/java/org/exoplatform/component/test/AbstractGateInTest.java
===================================================================
--- portal/branches/navcontroller/component/test/core/src/main/java/org/exoplatform/component/test/AbstractGateInTest.java 2010-11-27 12:47:01 UTC (rev 5308)
+++ portal/branches/navcontroller/component/test/core/src/main/java/org/exoplatform/component/test/AbstractGateInTest.java 2010-11-27 13:17:30 UTC (rev 5309)
@@ -29,7 +29,7 @@
* @author <a href="mailto:julien.viet@exoplatform.com">Julien Viet</a>
* @version $Revision$
*/
-public abstract class AbstractGateInTest extends TestCase
+public abstract class AbstractGateInTest extends BaseGateInTest
{
/** . */
Added: portal/branches/navcontroller/component/test/core/src/main/java/org/exoplatform/component/test/BaseGateInTest.java
===================================================================
--- portal/branches/navcontroller/component/test/core/src/main/java/org/exoplatform/component/test/BaseGateInTest.java (rev 0)
+++ portal/branches/navcontroller/component/test/core/src/main/java/org/exoplatform/component/test/BaseGateInTest.java 2010-11-27 13:17:30 UTC (rev 5309)
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2010 eXo Platform SAS.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.exoplatform.component.test;
+
+import junit.framework.Assert;
+import junit.framework.AssertionFailedError;
+import junit.framework.TestCase;
+
+/**
+ * @author <a href="mailto:julien.viet@exoplatform.com">Julien Viet</a>
+ * @version $Revision$
+ */
+public class BaseGateInTest extends TestCase
+{
+
+ public BaseGateInTest()
+ {
+ }
+
+ public BaseGateInTest(String name)
+ {
+ super(name);
+ }
+
+ public static <T> T assertInstanceOf(Object o, Class<T> expectedType)
+ {
+ if (expectedType != null)
+ {
+ if (expectedType.isInstance(o))
+ {
+ fail();
+ return null;
+ }
+ else
+ {
+ return expectedType.cast(o);
+ }
+ }
+ else
+ {
+ fail("Need an expected type");
+ return null;
+ }
+ }
+
+ public static <T> T fail(String msg, Throwable t)
+ {
+ AssertionFailedError afe = new AssertionFailedError(msg);
+ afe.initCause(t);
+ throw afe;
+ }
+
+ public static <T> T fail(Throwable t)
+ {
+ AssertionFailedError afe = new AssertionFailedError();
+ afe.initCause(t);
+ throw afe;
+ }
+}
14 years, 1 month
gatein SVN: r5308 - in portal/branches/navcontroller/component/web/controller/src: test/java/org/exoplatform/web/controller/regexp and 1 other directory.
by do-not-reply@jboss.org
Author: julien_viet
Date: 2010-11-27 07:47:01 -0500 (Sat, 27 Nov 2010)
New Revision: 5308
Modified:
portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/RENode.java
portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/RegExpParser.java
portal/branches/navcontroller/component/web/controller/src/test/java/org/exoplatform/web/controller/regexp/TestParser.java
Log:
support for non capturing group in parser
Modified: portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/RENode.java
===================================================================
--- portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/RENode.java 2010-11-27 12:27:16 UTC (rev 5307)
+++ portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/RENode.java 2010-11-27 12:47:01 UTC (rev 5308)
@@ -220,13 +220,17 @@
/** . */
private final Disjunction disjunction;
- public Group(Disjunction disjunction)
+ /** . */
+ private final boolean capturing;
+
+ public Group(Disjunction disjunction, boolean capturing)
{
if (disjunction == null)
{
throw new NullPointerException();
}
this.disjunction = disjunction;
+ this.capturing = capturing;
}
public Disjunction getDisjunction()
@@ -234,10 +238,15 @@
return disjunction;
}
+ public boolean isCapturing()
+ {
+ return capturing;
+ }
+
@Override
protected void writeTo(StringBuilder sb)
{
- sb.append("<(>").append(disjunction).append("</)>");
+ sb.append("<").append(capturing ? "(" : "(?:").append('>').append(disjunction).append("</").append(capturing ? ")" : ":?)").append(">");
}
}
Modified: portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/RegExpParser.java
===================================================================
--- portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/RegExpParser.java 2010-11-27 12:27:16 UTC (rev 5307)
+++ portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/RegExpParser.java 2010-11-27 12:47:01 UTC (rev 5308)
@@ -147,14 +147,43 @@
index++;
break;
case '(':
- int closingParenthesis = findClosing(index, to, '(', ')');
- if (closingParenthesis == -1)
+ int endGroup = findClosing(index, to, '(', ')');
+ if (endGroup == -1)
{
throw new SyntaxException();
}
- RENode.Disjunction grouped = new RegExpParser(s, index + 1, closingParenthesis).parseDisjunction();
- exp = new RENode.Group(grouped);
- index = closingParenthesis + 1;
+
+ // Do we have a special construct ?
+ int startGroup = index + 1;
+ boolean capturing = true;
+ if (startGroup < endGroup)
+ {
+ if (s.charAt(startGroup) == '?')
+ {
+ if (startGroup + 1 < endGroup)
+ {
+ if (s.charAt(startGroup + 1) == ':')
+ {
+ // It's a non capturing group, so it's ok
+ startGroup += 2;
+ capturing = false;
+ }
+ else
+ {
+ throw createSyntaxException("Only non capturing group syntax is supported", index + 1, index + 3);
+ }
+ }
+ else
+ {
+ throw createSyntaxException("Group containing a single question mark are not allowed", index, index + 2);
+ }
+ }
+ }
+
+ //
+ RENode.Disjunction grouped = new RegExpParser(s, startGroup, endGroup).parseDisjunction();
+ exp = new RENode.Group(grouped, capturing);
+ index = endGroup + 1;
break;
case '*':
case '+':
Modified: portal/branches/navcontroller/component/web/controller/src/test/java/org/exoplatform/web/controller/regexp/TestParser.java
===================================================================
--- portal/branches/navcontroller/component/web/controller/src/test/java/org/exoplatform/web/controller/regexp/TestParser.java 2010-11-27 12:27:16 UTC (rev 5307)
+++ portal/branches/navcontroller/component/web/controller/src/test/java/org/exoplatform/web/controller/regexp/TestParser.java 2010-11-27 12:47:01 UTC (rev 5308)
@@ -50,14 +50,14 @@
{
this.parser = new RegExpParser(s, from, to);
}
- ParserTester assertParseBracketExpression(String expectedValue)
+ ParserTester assertParseCharacterClass(String expectedValue)
{
RENode node = parser.parseExpression();
assertTrue(node instanceof RENode.CharacterClass);
assertEquals(expectedValue, node.toString());
return this;
}
- ParserTester assertParseExtendedRegExp(String expectedValue)
+ ParserTester assertParseDisjunction(String expectedValue)
{
int expectedIndex = parser.getTo();
RENode.Disjunction disjunction = parser.parseDisjunction();
@@ -65,7 +65,7 @@
assertEquals(expectedIndex, parser.getIndex());
return this;
}
- ParserTester assertNotParseExtendedRegExp()
+ ParserTester assertNotParseDisjunction()
{
int expectedIndex = parser.getIndex();
try
@@ -86,7 +86,7 @@
assertEquals(expectedIndex, parser.getIndex());
return this;
}
- ParserTester assertNotParseEREExpression()
+ ParserTester assertNotParseExpression()
{
int index = parser.getIndex();
try
@@ -124,16 +124,16 @@
public void testExtendedRegexp()
{
- new ParserTester("^").assertParseExtendedRegExp("<^/>");
- new ParserTester("^$").assertParseExtendedRegExp("<^/><$/>");
- new ParserTester("a").assertParseExtendedRegExp("<c>a</c>");
- new ParserTester("a|b").assertParseExtendedRegExp("<c>a</c>|<c>b</c>");
- new ParserTester("a+|b*").assertParseExtendedRegExp("<+><c>a</c></+>|<*><c>b</c></*>");
+ new ParserTester("^").assertParseDisjunction("<^/>");
+ new ParserTester("^$").assertParseDisjunction("<^/><$/>");
+ new ParserTester("a").assertParseDisjunction("<c>a</c>");
+ new ParserTester("a|b").assertParseDisjunction("<c>a</c>|<c>b</c>");
+ new ParserTester("a+|b*").assertParseDisjunction("<+><c>a</c></+>|<*><c>b</c></*>");
}
public void testExpression()
{
- new ParserTester("").assertNotParseEREExpression();
+ new ParserTester("").assertNotParseExpression();
new ParserTester("^").assertParseExpression("<^/>", 1);
new ParserTester("^+").assertParseExpression("<+><^/></+>", 2);
new ParserTester("$").assertParseExpression("<$/>", 1);
@@ -144,13 +144,20 @@
new ParserTester(".+").assertParseExpression("<+><./></+>", 2);
new ParserTester("\\+").assertParseExpression("<c>+</c>", 2);
new ParserTester("\\++").assertParseExpression("<+><c>+</c></+>", 3);
- new ParserTester("*").assertNotParseEREExpression();
- new ParserTester("+").assertNotParseEREExpression();
- new ParserTester("?").assertNotParseEREExpression();
- new ParserTester("{").assertNotParseEREExpression();
- new ParserTester("|").assertNotParseEREExpression();
+ new ParserTester("*").assertNotParseExpression();
+ new ParserTester("+").assertNotParseExpression();
+ new ParserTester("?").assertNotParseExpression();
+ new ParserTester("{").assertNotParseExpression();
+ new ParserTester("|").assertNotParseExpression();
+ }
+
+ public void testGroup()
+ {
new ParserTester("(a)").assertParseExpression("<(><c>a</c></)>", 3);
new ParserTester("(a(b)c)").assertParseExpression("<(><c>a</c><(><c>b</c></)><c>c</c></)>", 7);
+ new ParserTester("(?:a)").assertParseExpression("<(?:><c>a</c></:?)>", 5);
+ new ParserTester("(?)").assertNotParseExpression();
+ new ParserTester("(?a)").assertNotParseExpression();
}
// missing stuff:
@@ -180,22 +187,22 @@
public void testParseBracketExpression()
{
- new ParserTester("[a]").assertParseBracketExpression("[a]");
- new ParserTester("[^a]").assertParseBracketExpression("[^[a]]");
- new ParserTester("[^a-b]").assertParseBracketExpression("[^[a-b]]");
- new ParserTester("[a-b]").assertParseBracketExpression("[a-b]");
- new ParserTester("[ab]").assertParseBracketExpression("[[a][b]]");
- new ParserTester("[a&]").assertParseBracketExpression("[[a][&]]");
- new ParserTester("[a&&b]").assertParseBracketExpression("[[a]&&[b]]");
- new ParserTester("[a&&[^b]]").assertParseBracketExpression("[[a]&&[^[b]]]");
- new ParserTester("[a[^b]]").assertParseBracketExpression("[[a][^[b]]]");
- new ParserTester("[a[b]]").assertParseBracketExpression("[[a][b]]");
- new ParserTester("[a[b]c]").assertParseBracketExpression("[[a][[b][c]]]");
- new ParserTester("[[a]bc]").assertParseBracketExpression("[[a][[b][c]]]");
- new ParserTester("[-]").assertParseBracketExpression("[-]");
- new ParserTester("[a-]").assertParseBracketExpression("[[a][-]]");
- new ParserTester("[---]").assertParseBracketExpression("[---]");
- new ParserTester("[#--]").assertParseBracketExpression("[#--]");
+ new ParserTester("[a]").assertParseCharacterClass("[a]");
+ new ParserTester("[^a]").assertParseCharacterClass("[^[a]]");
+ new ParserTester("[^a-b]").assertParseCharacterClass("[^[a-b]]");
+ new ParserTester("[a-b]").assertParseCharacterClass("[a-b]");
+ new ParserTester("[ab]").assertParseCharacterClass("[[a][b]]");
+ new ParserTester("[a&]").assertParseCharacterClass("[[a][&]]");
+ new ParserTester("[a&&b]").assertParseCharacterClass("[[a]&&[b]]");
+ new ParserTester("[a&&[^b]]").assertParseCharacterClass("[[a]&&[^[b]]]");
+ new ParserTester("[a[^b]]").assertParseCharacterClass("[[a][^[b]]]");
+ new ParserTester("[a[b]]").assertParseCharacterClass("[[a][b]]");
+ new ParserTester("[a[b]c]").assertParseCharacterClass("[[a][[b][c]]]");
+ new ParserTester("[[a]bc]").assertParseCharacterClass("[[a][[b][c]]]");
+ new ParserTester("[-]").assertParseCharacterClass("[-]");
+ new ParserTester("[a-]").assertParseCharacterClass("[[a][-]]");
+ new ParserTester("[---]").assertParseCharacterClass("[---]");
+ new ParserTester("[#--]").assertParseCharacterClass("[#--]");
}
}
14 years, 1 month
gatein SVN: r5307 - in portal/branches/navcontroller/component/web/controller/src: main/java/org/exoplatform/web/controller/router and 1 other directories.
by do-not-reply@jboss.org
Author: julien_viet
Date: 2010-11-27 07:27:16 -0500 (Sat, 27 Nov 2010)
New Revision: 5307
Modified:
portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/Parser.java
portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/RegExpParser.java
portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/router/RegExpAnalyser.java
portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/router/Route.java
portal/branches/navcontroller/component/web/controller/src/test/java/org/exoplatform/web/controller/router/TestRegExpAnalyser.java
Log:
fix a bug in the RegExpAnalyser
Modified: portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/Parser.java
===================================================================
--- portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/Parser.java 2010-11-27 12:06:14 UTC (rev 5306)
+++ portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/Parser.java 2010-11-27 12:27:16 UTC (rev 5307)
@@ -95,6 +95,13 @@
return -1;
}
+ protected final SyntaxException createSyntaxException(String msg, int start, int end)
+ {
+ StringBuilder sb = new StringBuilder(msg).append(" : ");
+ sb.append(s, 0, start).append(" ->").append(s, start, end).append("<- ").append(s, end, s.length());
+ return new SyntaxException(sb.toString());
+ }
+
/**
* Find the closing char.
*
Modified: portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/RegExpParser.java
===================================================================
--- portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/RegExpParser.java 2010-11-27 12:06:14 UTC (rev 5306)
+++ portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/RegExpParser.java 2010-11-27 12:27:16 UTC (rev 5307)
@@ -161,7 +161,7 @@
case '?':
case '{':
case '|':
- throw new SyntaxException();
+ throw createSyntaxException("Was not expecting the char " + c, index, index + 1);
case '[':
int closingBracket = findClosing(index, to, '[', ']');
Modified: portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/router/RegExpAnalyser.java
===================================================================
--- portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/router/RegExpAnalyser.java 2010-11-27 12:06:14 UTC (rev 5306)
+++ portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/router/RegExpAnalyser.java 2010-11-27 12:27:16 UTC (rev 5307)
@@ -133,6 +133,7 @@
sb.append("[");
visit(characterClass.getExpr());
sb.append("]");
+ quantifier = expression.getQuantifier();
}
//
Modified: portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/router/Route.java
===================================================================
--- portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/router/Route.java 2010-11-27 12:06:14 UTC (rev 5306)
+++ portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/router/Route.java 2010-11-27 12:27:16 UTC (rev 5307)
@@ -629,6 +629,12 @@
regex = "[^/]+";
}
+ // Now analyse the regexp
+// RegExpAnalyser analyser = new RegExpAnalyser();
+// analyser.process(regex);
+// String regex2 = analyser.getPattern();
+// System.out.println("" + regex + " -> " + regex2);
+
//
builder.expr("(").expr(regex).expr(")");
Modified: portal/branches/navcontroller/component/web/controller/src/test/java/org/exoplatform/web/controller/router/TestRegExpAnalyser.java
===================================================================
--- portal/branches/navcontroller/component/web/controller/src/test/java/org/exoplatform/web/controller/router/TestRegExpAnalyser.java 2010-11-27 12:06:14 UTC (rev 5306)
+++ portal/branches/navcontroller/component/web/controller/src/test/java/org/exoplatform/web/controller/router/TestRegExpAnalyser.java 2010-11-27 12:27:16 UTC (rev 5307)
@@ -59,4 +59,9 @@
assertAnalyse("(a(?:bc))", true, "(a(bc))");
assertAnalyse("(a)(?:b)", true, "(a)(b)");
}
+
+ public void testBilto()
+ {
+ assertAnalyse("[a]+", false, "[a]+");
+ }
}
14 years, 1 month
gatein SVN: r5306 - in portal/branches/navcontroller/component/web/controller/src: test/java/org/exoplatform/web/controller/router and 1 other directory.
by do-not-reply@jboss.org
Author: julien_viet
Date: 2010-11-27 07:06:14 -0500 (Sat, 27 Nov 2010)
New Revision: 5306
Added:
portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/router/RegExpAnalyser.java
portal/branches/navcontroller/component/web/controller/src/test/java/org/exoplatform/web/controller/router/TestRegExpAnalyser.java
Modified:
portal/branches/navcontroller/component/web/controller/src/test/java/org/exoplatform/web/controller/router/TestMatch.java
portal/branches/navcontroller/component/web/controller/src/test/java/org/exoplatform/web/controller/router/TestRender.java
Log:
- start the regexp analyser based on the regexp parser
- start to write unit test for language matching in the url path
Added: portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/router/RegExpAnalyser.java
===================================================================
--- portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/router/RegExpAnalyser.java (rev 0)
+++ portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/router/RegExpAnalyser.java 2010-11-27 12:06:14 UTC (rev 5306)
@@ -0,0 +1,180 @@
+/*
+ * Copyright (C) 2010 eXo Platform SAS.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.exoplatform.web.controller.router;
+
+import org.exoplatform.web.controller.regexp.Quantifier;
+import org.exoplatform.web.controller.regexp.RENode;
+import org.exoplatform.web.controller.regexp.RegExpParser;
+
+/**
+ * @author <a href="mailto:julien.viet@exoplatform.com">Julien Viet</a>
+ * @version $Revision$
+ */
+public class RegExpAnalyser
+{
+
+ /** . */
+ private StringBuilder sb;
+
+ /** . */
+ private boolean groupContainer;
+
+ /** . */
+ private boolean needReset;
+
+ public RegExpAnalyser()
+ {
+ this.sb = new StringBuilder();
+ this.groupContainer = false;
+ this.needReset = false;
+ }
+
+ public boolean isGroupContainer()
+ {
+ return groupContainer;
+ }
+
+ public String getPattern()
+ {
+ return sb.toString();
+ }
+
+ public RegExpAnalyser reset()
+ {
+ sb.setLength(0);
+ groupContainer = false;
+ needReset = false;
+ return this;
+ }
+
+ public void process(CharSequence pattern)
+ {
+ RegExpParser parser = new RegExpParser(pattern);
+ RENode.Disjunction disjunction = parser.parseDisjunction();
+ process(disjunction);
+ }
+
+ public void process(RENode.Disjunction disjunction)
+ {
+ if (needReset)
+ {
+ throw new IllegalStateException();
+ }
+
+ //
+ needReset = true;
+ visit(disjunction);
+ }
+
+ private void visit(RENode.Disjunction disjunction)
+ {
+ visit(disjunction.getAlternative());
+ RENode.Disjunction next = disjunction.getNext();
+ if (next != null)
+ {
+ sb.append('|');
+ visit(next);
+ }
+ }
+
+ private void visit(RENode.Alternative alternative)
+ {
+ visit(alternative.getExp());
+ RENode.Alternative next = alternative.getNext();
+ if (next != null)
+ {
+ visit(next);
+ }
+ }
+
+ private void visit(RENode.Exp expression)
+ {
+ Quantifier quantifier = null;
+ if (expression instanceof RENode.Dot)
+ {
+ sb.append('.');
+ quantifier = expression.getQuantifier();
+ }
+ else if (expression instanceof RENode.Group)
+ {
+ RENode.Group group = (RENode.Group)expression;
+ sb.append(groupContainer ? "(?:" : "(");
+ groupContainer = true;
+ visit(group.getDisjunction());
+ sb.append(")");
+ quantifier = expression.getQuantifier();
+ }
+ else if (expression instanceof RENode.Character)
+ {
+ RENode.Character character = (RENode.Character)expression;
+ sb.append(character.getValue());
+ quantifier = expression.getQuantifier();
+ }
+ else if (expression instanceof RENode.CharacterClass)
+ {
+ RENode.CharacterClass characterClass = (RENode.CharacterClass)expression;
+ sb.append("[");
+ visit(characterClass.getExpr());
+ sb.append("]");
+ }
+
+ //
+ if (quantifier != null)
+ {
+ sb.append(quantifier);
+ }
+ }
+
+ private void visit(RENode.CharacterClassExpr expr)
+ {
+ if (expr instanceof RENode.CharacterClassExpr.Simple)
+ {
+ RENode.CharacterClass.CharacterClassExpr.Simple simple = (RENode.CharacterClass.CharacterClassExpr.Simple)expr;
+ sb.append(simple.getValue());
+ }
+ else if (expr instanceof RENode.CharacterClass.CharacterClassExpr.Range)
+ {
+ RENode.CharacterClass.CharacterClassExpr.Range range = (RENode.CharacterClass.CharacterClassExpr.Range)expr;
+ sb.append(range.getFrom());
+ sb.append('-');
+ sb.append(range.getTo());
+ }
+ else if (expr instanceof RENode.CharacterClass.CharacterClassExpr.And)
+ {
+ RENode.CharacterClass.CharacterClassExpr.And and = (RENode.CharacterClass.CharacterClassExpr.And)expr;
+ visit(and.getLeft());
+ sb.append("&&");
+ visit(and.getRight());
+ }
+ else if (expr instanceof RENode.CharacterClass.CharacterClassExpr.Or)
+ {
+ RENode.CharacterClass.CharacterClassExpr.Or or = (RENode.CharacterClass.CharacterClassExpr.Or)expr;
+ visit(or.getLeft());
+ visit(or.getRight());
+ }
+ else if (expr instanceof RENode.CharacterClass.CharacterClassExpr.Not)
+ {
+ RENode.CharacterClass.CharacterClassExpr.Not not = (RENode.CharacterClass.CharacterClassExpr.Not)expr;
+ sb.append("[^");
+ visit(not.getNegated());
+ sb.append(']');
+ }
+ }
+}
Modified: portal/branches/navcontroller/component/web/controller/src/test/java/org/exoplatform/web/controller/router/TestMatch.java
===================================================================
--- portal/branches/navcontroller/component/web/controller/src/test/java/org/exoplatform/web/controller/router/TestMatch.java 2010-11-27 12:02:10 UTC (rev 5305)
+++ portal/branches/navcontroller/component/web/controller/src/test/java/org/exoplatform/web/controller/router/TestMatch.java 2010-11-27 12:06:14 UTC (rev 5306)
@@ -191,4 +191,15 @@
assertEquals(expectedParameters, router.route("/a"));
assertEquals(Collections.singletonMap(QualifiedName.create("a"), "a"), router.route("/a/b"));
}
+
+ public void testLang() throws Exception
+ {
+ RouterDescriptor routerMD = new RouterDescriptor();
+ routerMD.addRoute(new RouteDescriptor("/{a}b").addPathParam(QualifiedName.parse("a"), "(?:[A-Za-z]{2}/)?", EncodingMode.PRESERVE_PATH));
+ Router router = new Router(routerMD);
+
+ //
+ assertEquals(Collections.singletonMap(QualifiedName.create("a"), "fr/"), router.route("/fr/b"));
+ assertEquals(Collections.singletonMap(QualifiedName.create("a"), ""), router.route("/b"));
+ }
}
Added: portal/branches/navcontroller/component/web/controller/src/test/java/org/exoplatform/web/controller/router/TestRegExpAnalyser.java
===================================================================
--- portal/branches/navcontroller/component/web/controller/src/test/java/org/exoplatform/web/controller/router/TestRegExpAnalyser.java (rev 0)
+++ portal/branches/navcontroller/component/web/controller/src/test/java/org/exoplatform/web/controller/router/TestRegExpAnalyser.java 2010-11-27 12:06:14 UTC (rev 5306)
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2010 eXo Platform SAS.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.exoplatform.web.controller.router;
+
+import junit.framework.TestCase;
+
+/**
+ * @author <a href="mailto:julien.viet@exoplatform.com">Julien Viet</a>
+ * @version $Revision$
+ */
+public class TestRegExpAnalyser extends TestCase
+{
+
+ /** . */
+ private RegExpAnalyser analyser = new RegExpAnalyser();
+
+ private void assertAnalyse(String expectedPattern, boolean expectedGroupContainer, String pattern)
+ {
+ analyser.reset();
+ analyser.process(pattern);
+ assertEquals(expectedPattern, analyser.getPattern());
+ assertEquals(expectedGroupContainer, analyser.isGroupContainer());
+ }
+
+ public void testCharacterClass()
+ {
+ assertAnalyse("[a]", false, "[a]");
+ assertAnalyse("[ab]", false, "[ab]");
+ assertAnalyse("[ab]", false, "[a[b]]");
+ assertAnalyse("[abc]", false, "[abc]");
+ assertAnalyse("[abc]", false, "[[a]bc]");
+ assertAnalyse("[abc]", false, "[a[b]c]");
+ assertAnalyse("[abc]", false, "[ab[c]]");
+ assertAnalyse("[abc]", false, "[[ab]c]");
+ assertAnalyse("[abc]", false, "[a[bc]]");
+ assertAnalyse("[abc]", false, "[[abc]]");
+ }
+
+ public void testGroupContainer()
+ {
+ assertAnalyse("(abc)", true, "(abc)");
+ assertAnalyse("(a(?:bc))", true, "(a(bc))");
+ assertAnalyse("(a)(?:b)", true, "(a)(b)");
+ }
+}
Modified: portal/branches/navcontroller/component/web/controller/src/test/java/org/exoplatform/web/controller/router/TestRender.java
===================================================================
--- portal/branches/navcontroller/component/web/controller/src/test/java/org/exoplatform/web/controller/router/TestRender.java 2010-11-27 12:02:10 UTC (rev 5305)
+++ portal/branches/navcontroller/component/web/controller/src/test/java/org/exoplatform/web/controller/router/TestRender.java 2010-11-27 12:06:14 UTC (rev 5306)
@@ -149,4 +149,15 @@
//
assertEquals("/a/b", router.render(Collections.singletonMap(QualifiedName.create("p"), "a")));
}
+
+ public void testLang() throws Exception
+ {
+ RouterDescriptor routerMD = new RouterDescriptor();
+ routerMD.addRoute(new RouteDescriptor("/{a}b").addPathParam(QualifiedName.parse("a"), "(?:[A-Za-z]{2}/)?", EncodingMode.PRESERVE_PATH));
+ Router router = new Router(routerMD);
+
+ //
+ assertEquals("/fr/b", router.render(Collections.singletonMap(QualifiedName.parse("a"), "fr/")));
+ assertEquals("/b", router.render(Collections.singletonMap(QualifiedName.parse("a"), "")));
+ }
}
14 years, 1 month
gatein SVN: r5305 - in portal/branches/navcontroller/component/web/controller/src: test/java/org/exoplatform/web/controller/regexp and 1 other directory.
by do-not-reply@jboss.org
Author: julien_viet
Date: 2010-11-27 07:02:10 -0500 (Sat, 27 Nov 2010)
New Revision: 5305
Modified:
portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/Parser.java
portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/RENode.java
portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/RegExpParser.java
portal/branches/navcontroller/component/web/controller/src/test/java/org/exoplatform/web/controller/regexp/TestParser.java
Log:
fix a bug in the character class parser
Modified: portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/Parser.java
===================================================================
--- portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/Parser.java 2010-11-26 21:24:55 UTC (rev 5304)
+++ portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/Parser.java 2010-11-27 12:02:10 UTC (rev 5305)
@@ -95,18 +95,31 @@
return -1;
}
- protected final int indexOfBlah(int from, int to, char start, char end)
+ /**
+ * Find the closing char.
+ *
+ * @param from the index to start from, the char at this index should be the opening char
+ * @param to the max exclusive value this closing char can be
+ * @param openingChar the opening char
+ * @param closingChar the closing char
+ * @return the index of the closing char or -1
+ */
+ protected final int findClosing(int from, int to, char openingChar, char closingChar)
{
+ if (s.charAt(from) != openingChar)
+ {
+ throw new AssertionError();
+ }
int closing = -1;
int depth = 0;
for (int i = from + 1;i < to;i++)
{
char c = s.charAt(i);
- if (c == start)
+ if (c == openingChar)
{
depth++;
}
- else if (c == end)
+ else if (c == closingChar)
{
if (depth == 0)
{
Modified: portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/RENode.java
===================================================================
--- portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/RENode.java 2010-11-26 21:24:55 UTC (rev 5304)
+++ portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/RENode.java 2010-11-27 12:02:10 UTC (rev 5305)
@@ -28,41 +28,15 @@
public abstract String toString();
- public abstract void accept(Visitor visitor);
-
- /**
- * A visitor.
- */
- public static abstract class Visitor
+ public static final class Disjunction extends RENode
{
- public void enter(Disjunction disjunction) {}
- public void leave(Disjunction disjunction) {}
- public void enter(Alternative alternative) {}
- public void leave(Alternative alternative) {}
- public void enter(Group group) {}
- public void leave(Group group) {}
- public void visit(Assertion assertion) {}
- public void visit(Dot dot) {}
- public void visit(Character character) {}
- public void enter(CharacterClass.Not not) {}
- public void leave(CharacterClass.Not not) {}
- public void enter(CharacterClass.Or or) {}
- public void leave(CharacterClass.Or or) {}
- public void enter(CharacterClass.And and) {}
- public void leave(CharacterClass.And and) {}
- public void visit(CharacterClass.Simple simple) {}
- public void visit(CharacterClass.Range range) {}
- }
- public static class Disjunction extends RENode
- {
+ /** . */
+ private final Alternative alternative;
/** . */
private final Disjunction next;
- /** . */
- private final Alternative alternative;
-
public Disjunction(Alternative alternative)
{
this(alternative, null);
@@ -80,6 +54,16 @@
this.next = next;
}
+ public Disjunction getNext()
+ {
+ return next;
+ }
+
+ public Alternative getAlternative()
+ {
+ return alternative;
+ }
+
@Override
public String toString()
{
@@ -92,21 +76,9 @@
return alternative.toString();
}
}
-
- @Override
- public void accept(Visitor visitor)
- {
- visitor.enter(this);
- alternative.accept(visitor);
- if (next != null)
- {
- next.accept(visitor);
- }
- visitor.leave(this);
- }
}
- public static class Alternative extends RENode
+ public static final class Alternative extends RENode
{
/** . */
@@ -130,6 +102,16 @@
this.next = next;
}
+ public Exp getExp()
+ {
+ return exp;
+ }
+
+ public Alternative getNext()
+ {
+ return next;
+ }
+
@Override
public String toString()
{
@@ -142,18 +124,6 @@
return exp.toString();
}
}
-
- @Override
- public void accept(Visitor visitor)
- {
- visitor.enter(this);
- exp.accept(visitor);
- if (next != null)
- {
- next.accept(visitor);
- }
- visitor.leave(this);
- }
}
public static abstract class Exp extends RENode
@@ -162,6 +132,15 @@
/** . */
Quantifier quantifier;
+ private Exp()
+ {
+ }
+
+ public Quantifier getQuantifier()
+ {
+ return quantifier;
+ }
+
@Override
public final String toString()
{
@@ -170,26 +149,27 @@
{
String q = quantifier.toString();
sb.append('<').append(q).append('>');
- toString(sb);
+ writeTo(sb);
sb.append("</").append(q).append('>');
}
else
{
- toString(sb);
+ writeTo(sb);
}
return sb.toString();
}
- protected abstract void toString(StringBuilder sb);
+ protected abstract void writeTo(StringBuilder sb);
}
public static abstract class Assertion extends Exp
{
+
/** . */
public static final Assertion BEGIN = new Assertion()
{
@Override
- protected void toString(StringBuilder sb)
+ protected void writeTo(StringBuilder sb)
{
sb.append("<^/>");
}
@@ -199,7 +179,7 @@
public static final Assertion END = new Assertion()
{
@Override
- protected void toString(StringBuilder sb)
+ protected void writeTo(StringBuilder sb)
{
sb.append("<$/>");
}
@@ -208,16 +188,13 @@
private Assertion()
{
}
-
- @Override
- public void accept(Visitor visitor)
- {
- visitor.visit(this);
- }
}
public static abstract class Atom extends Exp
{
+ private Atom()
+ {
+ }
}
public static final class Dot extends Atom
@@ -231,16 +208,10 @@
}
@Override
- protected void toString(StringBuilder sb)
+ protected void writeTo(StringBuilder sb)
{
sb.append("<./>");
}
-
- @Override
- public void accept(Visitor visitor)
- {
- visitor.visit(this);
- }
}
public static final class Group extends Atom
@@ -258,18 +229,15 @@
this.disjunction = disjunction;
}
- @Override
- protected void toString(StringBuilder sb)
+ public Disjunction getDisjunction()
{
- sb.append("<(>").append(disjunction).append("</)>");
+ return disjunction;
}
@Override
- public void accept(Visitor visitor)
+ protected void writeTo(StringBuilder sb)
{
- visitor.enter(this);
- disjunction.accept(visitor);
- visitor.leave(this);
+ sb.append("<(>").append(disjunction).append("</)>");
}
}
@@ -279,36 +247,64 @@
/** . */
private final char value;
+ public char getValue()
+ {
+ return value;
+ }
+
public Character(char value)
{
this.value = value;
}
@Override
- protected void toString(StringBuilder sb)
+ protected void writeTo(StringBuilder sb)
{
sb.append("<c>").append(value).append("</c>");
}
+ }
+ public static class CharacterClass extends Atom
+ {
+
+ /** . */
+ private final CharacterClassExpr expr;
+
+ protected CharacterClass(CharacterClassExpr expr)
+ {
+ if (expr == null)
+ {
+ throw new NullPointerException();
+ }
+ this.expr = expr;
+ }
+
+ public CharacterClassExpr getExpr()
+ {
+ return expr;
+ }
+
@Override
- public void accept(Visitor visitor)
+ protected void writeTo(StringBuilder sb)
{
- visitor.visit(this);
+ sb.append(expr);
}
}
- public static abstract class CharacterClass extends Atom
+ public static abstract class CharacterClassExpr extends RENode
{
- protected abstract void toString(StringBuilder sb);
+ private CharacterClassExpr()
+ {
+ }
- public static class Not extends CharacterClass
+ public static class Not extends CharacterClassExpr
{
/** . */
- private final CharacterClass negated;
+ private final CharacterClassExpr negated;
- public Not(CharacterClass negated)
+ public Not(CharacterClassExpr negated)
{
if (negated == null)
{
@@ -317,33 +313,28 @@
this.negated = negated;
}
- @Override
- protected void toString(StringBuilder sb)
+ public CharacterClassExpr getNegated()
{
- sb.append("[^");
- negated.toString(sb);
- sb.append("]");
+ return negated;
}
@Override
- public void accept(Visitor visitor)
+ public String toString()
{
- visitor.enter(this);
- negated.accept(visitor);
- visitor.leave(this);
+ return "[^" + negated + "]";
}
}
- public static class Or extends CharacterClass
+ public static class Or extends CharacterClassExpr
{
/** . */
- private final CharacterClass left;
+ private final CharacterClassExpr left;
/** . */
- private final CharacterClass right;
+ private final CharacterClassExpr right;
- public Or(CharacterClass left, CharacterClass right)
+ public Or(CharacterClassExpr left, CharacterClassExpr right)
{
if (left == null)
{
@@ -357,35 +348,33 @@
this.right = right;
}
- @Override
- protected void toString(StringBuilder sb)
+ public CharacterClassExpr getLeft()
{
- sb.append("[");
- left.toString(sb);
- right.toString(sb);
- sb.append("]");
+ return left;
}
+ public CharacterClassExpr getRight()
+ {
+ return right;
+ }
+
@Override
- public void accept(Visitor visitor)
+ public String toString()
{
- visitor.enter(this);
- left.accept(visitor);
- right.accept(visitor);
- visitor.leave(this);
+ return "[" + left + right + "]";
}
}
- public static class And extends CharacterClass
+ public static class And extends CharacterClassExpr
{
/** . */
- private final CharacterClass left;
+ private final CharacterClassExpr left;
/** . */
- private final CharacterClass right;
+ private final CharacterClassExpr right;
- public And(CharacterClass left, CharacterClass right)
+ public And(CharacterClassExpr left, CharacterClassExpr right)
{
if (left == null)
{
@@ -399,27 +388,24 @@
this.right = right;
}
- @Override
- protected void toString(StringBuilder sb)
+ public CharacterClassExpr getLeft()
{
- sb.append("[");
- left.toString(sb);
- sb.append("&&");
- right.toString(sb);
- sb.append("]");
+ return left;
}
+ public CharacterClassExpr getRight()
+ {
+ return right;
+ }
+
@Override
- public void accept(Visitor visitor)
+ public String toString()
{
- visitor.enter(this);
- left.accept(visitor);
- right.accept(visitor);
- visitor.leave(this);
+ return "[" + left + "&&" + right + "]";
}
}
- public static class Simple extends CharacterClass
+ public static class Simple extends CharacterClassExpr
{
/** . */
@@ -430,22 +416,19 @@
this.value = value;
}
- @Override
- protected void toString(StringBuilder sb)
+ public char getValue()
{
- sb.append("[");
- sb.append(value);
- sb.append("]");
+ return value;
}
@Override
- public void accept(Visitor visitor)
+ public String toString()
{
- visitor.visit(this);
+ return "[" + value + "]";
}
}
- public static class Range extends CharacterClass
+ public static class Range extends CharacterClassExpr
{
/** From inclusive. */
@@ -460,20 +443,20 @@
this.to = to;
}
- @Override
- protected void toString(StringBuilder sb)
+ public char getFrom()
{
- sb.append("[");
- sb.append(from);
- sb.append('-');
- sb.append(to);
- sb.append("]");
+ return from;
}
+ public char getTo()
+ {
+ return to;
+ }
+
@Override
- public void accept(Visitor visitor)
+ public String toString()
{
- visitor.visit(this);
+ return "[" + from + "-" + to + "]";
}
}
}
Modified: portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/RegExpParser.java
===================================================================
--- portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/RegExpParser.java 2010-11-26 21:24:55 UTC (rev 5304)
+++ portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/RegExpParser.java 2010-11-27 12:02:10 UTC (rev 5305)
@@ -147,7 +147,7 @@
index++;
break;
case '(':
- int closingParenthesis = indexOfBlah(index + 1, to, '(', ')');
+ int closingParenthesis = findClosing(index, to, '(', ')');
if (closingParenthesis == -1)
{
throw new SyntaxException();
@@ -164,12 +164,12 @@
throw new SyntaxException();
case '[':
- int closingBracket = indexOfBlah(index + 1, to, '[', ']');
+ int closingBracket = findClosing(index, to, '[', ']');
if (closingBracket == -1)
{
throw new SyntaxException();
}
- exp = parseCharacterClass(index, closingBracket + 1);
+ exp = new RENode.CharacterClass(parseCharacterClass(index, closingBracket + 1));
index = closingBracket + 1;
break;
case '\\':
@@ -285,84 +285,84 @@
/**
* character_class -> '[' bracket_list ']' | '[' '^' bracket_list ']'
- * bracket_term -> bracket_term | bracket_term bracket_term | bracket_term '&' '&' bracket_term
+ * bracket_list -> bracket_term | bracket_term bracket_list | bracket_term '&' '&' bracket_list
* bracket_term -> character_class | single_term | range_term
*
* @param begin the begin
* @param end the end
* @return a character class expression
*/
- private RENode.CharacterClass parseCharacterClass(int begin, int end)
+ private RENode.CharacterClassExpr parseCharacterClass(int begin, int end)
{
if (begin == end)
{
throw new SyntaxException();
}
- // Check if we do have bracket around or not
- boolean matching = true;
- if (s.charAt(begin) == '[')
+ //
+ if (begin < end)
{
- if (end - begin < 3)
+ RENode.CharacterClassExpr next;
+ if (s.charAt(begin) == '[')
{
- throw new SyntaxException();
- }
- if (s.charAt(end - 1) != ']')
- {
- throw new SyntaxException();
- }
+ int closing = findClosing(begin, end, '[', ']');
+ if (closing == -1)
+ {
+ throw new SyntaxException("Was expecting a closing brack");
+ }
- //
- begin++;
- end--;
+ //
+ boolean matching = true;
+ int nestedStart = begin + 1;
+ int nestedEnd = closing;
+ if (s.charAt(nestedStart) == '^' && nestedStart + 1 < nestedEnd)
+ {
+ nestedStart++;
+ matching = false;
+ }
- //
- if (s.charAt(begin) == '^' && begin + 1 < end)
+ //
+ RENode.CharacterClassExpr nested = parseCharacterClass(nestedStart, nestedEnd);
+ next = matching ? nested : new RENode.CharacterClassExpr.Not(nested);
+ begin = closing + 1;
+ }
+ else
{
+ char c = s.charAt(begin);
begin++;
- matching = false;
+ if (begin + 1 < end && s.charAt(begin) == '-')
+ {
+ next = new RENode.CharacterClassExpr.Range(c, s.charAt(begin + 1));
+ begin += 2;
+ }
+ else
+ {
+ next = new RENode.CharacterClassExpr.Simple(c);
+ }
}
- }
- //
- //
- RENode.CharacterClass cc;
- char c = s.charAt(begin);
- begin++;
- if (begin + 1 < end && s.charAt(begin) == '-')
- {
- cc = new RENode.CharacterClass.Range(c, s.charAt(begin + 1));
- begin += 2;
- }
- else
- {
- cc = new RENode.CharacterClass.Simple(c);
- }
-
- //
- if (begin < end)
- {
- char n = s.charAt(begin);
- if (n == '&' && begin + 1 < end && s.charAt(begin + 1) == '&')
+ //
+ if (begin < end)
{
- RENode.CharacterClass next = parseCharacterClass(begin + 2, end);
- cc = new RENode.CharacterClass.And(cc, next);
+ char n = s.charAt(begin);
+ if (n == '&' && begin + 1 < end && s.charAt(begin + 1) == '&')
+ {
+ RENode.CharacterClassExpr next2 = parseCharacterClass(begin + 2, end);
+ next = new RENode.CharacterClassExpr.And(next, next2);
+ }
+ else
+ {
+ RENode.CharacterClassExpr next2 = parseCharacterClass(begin, end);
+ next = new RENode.CharacterClassExpr.Or(next, next2);
+ }
}
- else
- {
- RENode.CharacterClass next = parseCharacterClass(begin, end);
- cc = new RENode.CharacterClass.Or(cc, next);
- }
- }
- //
- if (matching)
- {
- return cc;
+ //
+ return next;
}
else
{
- return new RENode.CharacterClass.Not(cc);
+ throw new UnsupportedOperationException();
}
}
}
Modified: portal/branches/navcontroller/component/web/controller/src/test/java/org/exoplatform/web/controller/regexp/TestParser.java
===================================================================
--- portal/branches/navcontroller/component/web/controller/src/test/java/org/exoplatform/web/controller/regexp/TestParser.java 2010-11-26 21:24:55 UTC (rev 5304)
+++ portal/branches/navcontroller/component/web/controller/src/test/java/org/exoplatform/web/controller/regexp/TestParser.java 2010-11-27 12:02:10 UTC (rev 5305)
@@ -190,6 +190,8 @@
new ParserTester("[a&&[^b]]").assertParseBracketExpression("[[a]&&[^[b]]]");
new ParserTester("[a[^b]]").assertParseBracketExpression("[[a][^[b]]]");
new ParserTester("[a[b]]").assertParseBracketExpression("[[a][b]]");
+ new ParserTester("[a[b]c]").assertParseBracketExpression("[[a][[b][c]]]");
+ new ParserTester("[[a]bc]").assertParseBracketExpression("[[a][[b][c]]]");
new ParserTester("[-]").assertParseBracketExpression("[-]");
new ParserTester("[a-]").assertParseBracketExpression("[[a][-]]");
new ParserTester("[---]").assertParseBracketExpression("[---]");
14 years, 1 month
gatein SVN: r5304 - portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp.
by do-not-reply@jboss.org
Author: julien_viet
Date: 2010-11-26 16:24:55 -0500 (Fri, 26 Nov 2010)
New Revision: 5304
Modified:
portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/RENode.java
Log:
preliminary visitor support
Modified: portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/RENode.java
===================================================================
--- portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/RENode.java 2010-11-26 21:11:05 UTC (rev 5303)
+++ portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/RENode.java 2010-11-26 21:24:55 UTC (rev 5304)
@@ -28,6 +28,32 @@
public abstract String toString();
+ public abstract void accept(Visitor visitor);
+
+ /**
+ * A visitor.
+ */
+ public static abstract class Visitor
+ {
+ public void enter(Disjunction disjunction) {}
+ public void leave(Disjunction disjunction) {}
+ public void enter(Alternative alternative) {}
+ public void leave(Alternative alternative) {}
+ public void enter(Group group) {}
+ public void leave(Group group) {}
+ public void visit(Assertion assertion) {}
+ public void visit(Dot dot) {}
+ public void visit(Character character) {}
+ public void enter(CharacterClass.Not not) {}
+ public void leave(CharacterClass.Not not) {}
+ public void enter(CharacterClass.Or or) {}
+ public void leave(CharacterClass.Or or) {}
+ public void enter(CharacterClass.And and) {}
+ public void leave(CharacterClass.And and) {}
+ public void visit(CharacterClass.Simple simple) {}
+ public void visit(CharacterClass.Range range) {}
+ }
+
public static class Disjunction extends RENode
{
@@ -66,6 +92,18 @@
return alternative.toString();
}
}
+
+ @Override
+ public void accept(Visitor visitor)
+ {
+ visitor.enter(this);
+ alternative.accept(visitor);
+ if (next != null)
+ {
+ next.accept(visitor);
+ }
+ visitor.leave(this);
+ }
}
public static class Alternative extends RENode
@@ -104,6 +142,18 @@
return exp.toString();
}
}
+
+ @Override
+ public void accept(Visitor visitor)
+ {
+ visitor.enter(this);
+ exp.accept(visitor);
+ if (next != null)
+ {
+ next.accept(visitor);
+ }
+ visitor.leave(this);
+ }
}
public static abstract class Exp extends RENode
@@ -158,6 +208,12 @@
private Assertion()
{
}
+
+ @Override
+ public void accept(Visitor visitor)
+ {
+ visitor.visit(this);
+ }
}
public static abstract class Atom extends Exp
@@ -179,6 +235,12 @@
{
sb.append("<./>");
}
+
+ @Override
+ public void accept(Visitor visitor)
+ {
+ visitor.visit(this);
+ }
}
public static final class Group extends Atom
@@ -201,6 +263,14 @@
{
sb.append("<(>").append(disjunction).append("</)>");
}
+
+ @Override
+ public void accept(Visitor visitor)
+ {
+ visitor.enter(this);
+ disjunction.accept(visitor);
+ visitor.leave(this);
+ }
}
public static final class Character extends Atom
@@ -219,6 +289,12 @@
{
sb.append("<c>").append(value).append("</c>");
}
+
+ @Override
+ public void accept(Visitor visitor)
+ {
+ visitor.visit(this);
+ }
}
public static abstract class CharacterClass extends Atom
@@ -248,6 +324,14 @@
negated.toString(sb);
sb.append("]");
}
+
+ @Override
+ public void accept(Visitor visitor)
+ {
+ visitor.enter(this);
+ negated.accept(visitor);
+ visitor.leave(this);
+ }
}
public static class Or extends CharacterClass
@@ -281,6 +365,15 @@
right.toString(sb);
sb.append("]");
}
+
+ @Override
+ public void accept(Visitor visitor)
+ {
+ visitor.enter(this);
+ left.accept(visitor);
+ right.accept(visitor);
+ visitor.leave(this);
+ }
}
public static class And extends CharacterClass
@@ -315,6 +408,15 @@
right.toString(sb);
sb.append("]");
}
+
+ @Override
+ public void accept(Visitor visitor)
+ {
+ visitor.enter(this);
+ left.accept(visitor);
+ right.accept(visitor);
+ visitor.leave(this);
+ }
}
public static class Simple extends CharacterClass
@@ -335,6 +437,12 @@
sb.append(value);
sb.append("]");
}
+
+ @Override
+ public void accept(Visitor visitor)
+ {
+ visitor.visit(this);
+ }
}
public static class Range extends CharacterClass
@@ -361,6 +469,12 @@
sb.append(to);
sb.append("]");
}
+
+ @Override
+ public void accept(Visitor visitor)
+ {
+ visitor.visit(this);
+ }
}
}
}
14 years, 1 month
gatein SVN: r5303 - in portal/branches/navcontroller/component/web/controller/src: test/java/org/exoplatform/web/controller/regexp and 1 other directory.
by do-not-reply@jboss.org
Author: julien_viet
Date: 2010-11-26 16:11:05 -0500 (Fri, 26 Nov 2010)
New Revision: 5303
Modified:
portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/RENode.java
portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/RegExpParser.java
portal/branches/navcontroller/component/web/controller/src/test/java/org/exoplatform/web/controller/regexp/TestParser.java
Log:
simplify a bit
Modified: portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/RENode.java
===================================================================
--- portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/RENode.java 2010-11-26 20:50:07 UTC (rev 5302)
+++ portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/RENode.java 2010-11-26 21:11:05 UTC (rev 5303)
@@ -19,8 +19,6 @@
package org.exoplatform.web.controller.regexp;
-import org.hibernate.criterion.Disjunction;
-
/**
* @author <a href="mailto:julien.viet@exoplatform.com">Julien Viet</a>
* @version $Revision$
@@ -28,6 +26,8 @@
public abstract class RENode
{
+ public abstract String toString();
+
public static class Disjunction extends RENode
{
@@ -39,12 +39,17 @@
public Disjunction(Alternative alternative)
{
- this.alternative = alternative;
- this.next = null;
+ this(alternative, null);
}
public Disjunction(Alternative alternative, Disjunction next)
{
+ if (alternative == null)
+ {
+ throw new NullPointerException();
+ }
+
+ //
this.alternative = alternative;
this.next = next;
}
@@ -74,12 +79,15 @@
public Alternative(Exp exp)
{
- this.exp = exp;
- this.next = null;
+ this(exp, null);
}
public Alternative(Exp exp, Alternative next)
{
+ if (exp == null)
+ {
+ throw new NullPointerException();
+ }
this.exp = exp;
this.next = next;
}
@@ -98,24 +106,42 @@
}
}
- public String toString()
- {
- throw new UnsupportedOperationException();
- }
-
public static abstract class Exp extends RENode
{
+
+ /** . */
+ Quantifier quantifier;
+
+ @Override
+ public final String toString()
+ {
+ StringBuilder sb = new StringBuilder();
+ if (quantifier != null)
+ {
+ String q = quantifier.toString();
+ sb.append('<').append(q).append('>');
+ toString(sb);
+ sb.append("</").append(q).append('>');
+ }
+ else
+ {
+ toString(sb);
+ }
+ return sb.toString();
+ }
+
+ protected abstract void toString(StringBuilder sb);
}
- public static class Assertion extends Exp
+ public static abstract class Assertion extends Exp
{
/** . */
public static final Assertion BEGIN = new Assertion()
{
@Override
- public String toString()
+ protected void toString(StringBuilder sb)
{
- return "<^/>";
+ sb.append("<^/>");
}
};
@@ -123,9 +149,9 @@
public static final Assertion END = new Assertion()
{
@Override
- public String toString()
+ protected void toString(StringBuilder sb)
{
- return "<$/>";
+ sb.append("<$/>");
}
};
@@ -134,27 +160,6 @@
}
}
- public static final class QuantifiedExp extends Exp
- {
- /** . */
- private final Exp exp;
-
- /** . */
- private final Quantifier quantifier;
-
- public QuantifiedExp(Exp exp, Quantifier quantifier)
- {
- this.exp = exp;
- this.quantifier = quantifier;
- }
-
- @Override
- public String toString()
- {
- return "<" + quantifier + ">" + exp + "</" + quantifier + ">";
- }
- }
-
public static abstract class Atom extends Exp
{
}
@@ -169,9 +174,10 @@
{
}
- public String toString()
+ @Override
+ protected void toString(StringBuilder sb)
{
- return "<./>";
+ sb.append("<./>");
}
}
@@ -183,13 +189,17 @@
public Group(Disjunction disjunction)
{
+ if (disjunction == null)
+ {
+ throw new NullPointerException();
+ }
this.disjunction = disjunction;
}
@Override
- public String toString()
+ protected void toString(StringBuilder sb)
{
- return "<(>" + disjunction + "</)>";
+ sb.append("<(>").append(disjunction).append("</)>");
}
}
@@ -205,9 +215,9 @@
}
@Override
- public String toString()
+ protected void toString(StringBuilder sb)
{
- return "<c>" + value + "</c>";
+ sb.append("<c>").append(value).append("</c>");
}
}
@@ -224,18 +234,14 @@
public Not(CharacterClass negated)
{
+ if (negated == null)
+ {
+ throw new NullPointerException();
+ }
this.negated = negated;
}
@Override
- public String toString()
- {
- StringBuilder sb = new StringBuilder();
- toString(sb);
- return sb.toString();
- }
-
- @Override
protected void toString(StringBuilder sb)
{
sb.append("[^");
@@ -255,25 +261,25 @@
public Or(CharacterClass left, CharacterClass right)
{
+ if (left == null)
+ {
+ throw new NullPointerException();
+ }
+ if (right == null)
+ {
+ throw new NullPointerException();
+ }
this.left = left;
this.right = right;
}
@Override
- public String toString()
- {
- StringBuilder sb = new StringBuilder();
- sb.append("[");
- toString(sb);
- sb.append("]");
- return sb.toString();
- }
-
- @Override
protected void toString(StringBuilder sb)
{
+ sb.append("[");
left.toString(sb);
right.toString(sb);
+ sb.append("]");
}
}
@@ -288,26 +294,26 @@
public And(CharacterClass left, CharacterClass right)
{
+ if (left == null)
+ {
+ throw new NullPointerException();
+ }
+ if (right == null)
+ {
+ throw new NullPointerException();
+ }
this.left = left;
this.right = right;
}
@Override
- public String toString()
- {
- StringBuilder sb = new StringBuilder();
- sb.append("[");
- toString(sb);
- sb.append("]");
- return sb.toString();
- }
-
- @Override
protected void toString(StringBuilder sb)
{
+ sb.append("[");
left.toString(sb);
sb.append("&&");
right.toString(sb);
+ sb.append("]");
}
}
@@ -323,20 +329,12 @@
}
@Override
- public String toString()
+ protected void toString(StringBuilder sb)
{
- StringBuilder sb = new StringBuilder();
sb.append("[");
- toString(sb);
+ sb.append(value);
sb.append("]");
- return sb.toString();
}
-
- @Override
- protected void toString(StringBuilder sb)
- {
- sb.append(value);
- }
}
public static class Range extends CharacterClass
@@ -355,21 +353,13 @@
}
@Override
- public String toString()
- {
- StringBuilder sb = new StringBuilder();
- sb.append("[");
- toString(sb);
- sb.append("]");
- return sb.toString();
- }
-
- @Override
protected void toString(StringBuilder sb)
{
+ sb.append("[");
sb.append(from);
sb.append('-');
sb.append(to);
+ sb.append("]");
}
}
}
Modified: portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/RegExpParser.java
===================================================================
--- portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/RegExpParser.java 2010-11-26 20:50:07 UTC (rev 5302)
+++ portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/RegExpParser.java 2010-11-26 21:11:05 UTC (rev 5303)
@@ -201,11 +201,7 @@
}
//
- Quantifier quantifier = parseQuantifierSymbol();
- if (quantifier != null)
- {
- exp = new RENode.QuantifiedExp(exp, quantifier);
- }
+ exp.quantifier = parseQuantifierSymbol();
//
return exp;
Modified: portal/branches/navcontroller/component/web/controller/src/test/java/org/exoplatform/web/controller/regexp/TestParser.java
===================================================================
--- portal/branches/navcontroller/component/web/controller/src/test/java/org/exoplatform/web/controller/regexp/TestParser.java 2010-11-26 20:50:07 UTC (rev 5302)
+++ portal/branches/navcontroller/component/web/controller/src/test/java/org/exoplatform/web/controller/regexp/TestParser.java 2010-11-26 21:11:05 UTC (rev 5303)
@@ -181,17 +181,17 @@
public void testParseBracketExpression()
{
new ParserTester("[a]").assertParseBracketExpression("[a]");
- new ParserTester("[^a]").assertParseBracketExpression("[^a]");
- new ParserTester("[^a-b]").assertParseBracketExpression("[^a-b]");
+ new ParserTester("[^a]").assertParseBracketExpression("[^[a]]");
+ new ParserTester("[^a-b]").assertParseBracketExpression("[^[a-b]]");
new ParserTester("[a-b]").assertParseBracketExpression("[a-b]");
- new ParserTester("[ab]").assertParseBracketExpression("[ab]");
- new ParserTester("[a&]").assertParseBracketExpression("[a&]");
- new ParserTester("[a&&b]").assertParseBracketExpression("[a&&b]");
- new ParserTester("[a&&[^b]]").assertParseBracketExpression("[a&&[^b]]");
- new ParserTester("[a[^b]]").assertParseBracketExpression("[a[^b]]");
- new ParserTester("[a[b]]").assertParseBracketExpression("[ab]");
+ new ParserTester("[ab]").assertParseBracketExpression("[[a][b]]");
+ new ParserTester("[a&]").assertParseBracketExpression("[[a][&]]");
+ new ParserTester("[a&&b]").assertParseBracketExpression("[[a]&&[b]]");
+ new ParserTester("[a&&[^b]]").assertParseBracketExpression("[[a]&&[^[b]]]");
+ new ParserTester("[a[^b]]").assertParseBracketExpression("[[a][^[b]]]");
+ new ParserTester("[a[b]]").assertParseBracketExpression("[[a][b]]");
new ParserTester("[-]").assertParseBracketExpression("[-]");
- new ParserTester("[a-]").assertParseBracketExpression("[a-]");
+ new ParserTester("[a-]").assertParseBracketExpression("[[a][-]]");
new ParserTester("[---]").assertParseBracketExpression("[---]");
new ParserTester("[#--]").assertParseBracketExpression("[#--]");
}
14 years, 1 month
gatein SVN: r5302 - in portal/branches/navcontroller/component/web/controller/src: test/java/org/exoplatform/web/controller/regexp and 1 other directory.
by do-not-reply@jboss.org
Author: julien_viet
Date: 2010-11-26 15:50:07 -0500 (Fri, 26 Nov 2010)
New Revision: 5302
Added:
portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/SubCharSequence.java
portal/branches/navcontroller/component/web/controller/src/test/java/org/exoplatform/web/controller/regexp/TestSubCharSequence.java
Modified:
portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/Quantifier.java
portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/RegExpParser.java
portal/branches/navcontroller/component/web/controller/src/test/java/org/exoplatform/web/controller/regexp/TestParser.java
Log:
- implement fully quantifier
- implement reluctant and possessive quantifier
- implement grouping
Modified: portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/Quantifier.java
===================================================================
--- portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/Quantifier.java 2010-11-26 19:21:57 UTC (rev 5301)
+++ portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/Quantifier.java 2010-11-26 20:50:07 UTC (rev 5302)
@@ -23,41 +23,113 @@
* @author <a href="mailto:julien.viet@exoplatform.com">Julien Viet</a>
* @version $Revision$
*/
-public abstract class Quantifier
+public class Quantifier
{
- private Quantifier()
+ public enum Mode
{
- }
- /** . */
- public static final Quantifier STAR = new Quantifier()
- {
- @Override
- public String toString()
+ GREEDY(""), RELUCTANT("?"), POSSESSIVE("+");
+
+ /** . */
+ private final String value;
+
+ Mode(String value)
{
- return "*";
+ this.value = value;
}
- };
+ }
/** . */
- public static final Quantifier PLUS = new Quantifier()
+ private final Mode mode;
+
+ /** . */
+ private final int min;
+
+ /** . */
+ private final Integer max;
+
+ protected Quantifier(Mode mode, int min, Integer max)
{
- @Override
- public String toString()
+ this.mode = mode;
+ this.min = min;
+ this.max = max;
+ }
+
+ public static Quantifier onceOrNotAtAll(Mode mode)
+ {
+ return new Quantifier(mode, 0, 1);
+ }
+
+ public static Quantifier zeroOrMore(Mode mode)
+ {
+ return new Quantifier(mode, 0, null);
+ }
+
+ public static Quantifier oneOrMore(Mode mode)
+ {
+ return new Quantifier(mode, 1, null);
+ }
+
+ public static Quantifier exactly(Mode mode, int value)
+ {
+ return new Quantifier(mode, value, value);
+ }
+
+ public static Quantifier atLeast(Mode mode, int value)
+ {
+ return new Quantifier(mode, value, null);
+ }
+
+ public static Quantifier between(Mode mode, int min, int max)
+ {
+ return new Quantifier(mode, min, max);
+ }
+
+ @Override
+ public boolean equals(Object o)
+ {
+ if (o == this)
{
- return "+";
+ return true;
}
- };
+ else if (o instanceof Quantifier)
+ {
+ Quantifier that = (Quantifier)o;
+ return mode == that.mode && min == that.min && (max == null ? that.max == null : max.equals(that.max));
+ }
+ return false;
+ }
- /** . */
- public static final Quantifier QUESTION_MARK = new Quantifier()
+ @Override
+ public String toString()
{
- @Override
- public String toString()
+ if (min == 0)
{
- return "?";
+ if (max == null)
+ {
+ return "*" + mode.value;
+ }
+ else if (max == 1)
+ {
+ return "?" + mode.value;
+ }
}
- };
-
+ else if (min == 1 && max == null)
+ {
+ return "+" + mode.value;
+ }
+ if (max == null)
+ {
+ return "{" + min + ",}" + mode.value;
+ }
+ else if (min == max)
+ {
+ return "{" + min + "}" + mode.value;
+ }
+ else
+ {
+ return "{" + min + "," + max + "}" + mode.value;
+ }
+ }
}
Modified: portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/RegExpParser.java
===================================================================
--- portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/RegExpParser.java 2010-11-26 19:21:57 UTC (rev 5301)
+++ portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/RegExpParser.java 2010-11-26 20:50:07 UTC (rev 5302)
@@ -21,6 +21,8 @@
import java.util.HashSet;
import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
/**
* @author <a href="mailto:julien.viet@exoplatform.com">Julien Viet</a>
@@ -41,6 +43,9 @@
}
/** . */
+ private static final Pattern pattern = Pattern.compile("^([0-9]+)" + "(?:" + "(,)([0-9]+)?" + ")?$");
+
+ /** . */
private int index;
public RegExpParser(CharSequence s)
@@ -114,12 +119,12 @@
}
/**
- * expression -> assertion | '(' disjunction ')' | '(' '?' disjunction ')' | character | expression quantifier
- * assertion -> '^' | '$'
- * character -> '.' | escaped | character_class | literal
- * escaped -> '\' any char
- * quantifier -> '*' | '+' | '?' | '{' count '}' | '{' count ',' '}' | '{' count ',' count '}'
- * literal -> todo
+ * expression -> assertion | '(' disjunction ')' | character | expression quantifier
+ * assertion -> '^' | '$'
+ * character -> '.' | escaped | character_class | literal
+ * escaped -> '\' any char
+ * quantifier -> quantifier_prefix | quantifier_prefix ?
+ * quantifier_prefix -> '*' | '+' | '?' | '{' count '}' | '{' count ',' '}' | '{' count ',' count '}'
*
* @return the expression
*/
@@ -215,16 +220,46 @@
{
case '*':
index++;
- return Quantifier.STAR;
+ return Quantifier.zeroOrMore(parseQuantifierMode());
case '+':
index++;
- return Quantifier.PLUS;
+ return Quantifier.oneOrMore(parseQuantifierMode());
case '?':
index++;
- return Quantifier.QUESTION_MARK;
+ return Quantifier.onceOrNotAtAll(parseQuantifierMode());
case '{':
index++;
- throw new UnsupportedOperationException();
+ int closingBrace = indexOf(index, '}', to);
+ if (closingBrace == -1)
+ {
+ throw new SyntaxException();
+ }
+ SubCharSequence sub = new SubCharSequence(s, index, closingBrace);
+ index = closingBrace + 1;
+ Matcher matcher = pattern.matcher(sub);
+ if (!matcher.matches())
+ {
+ throw new SyntaxException();
+ }
+ if (matcher.group(2) == null)
+ {
+ return Quantifier.exactly(
+ parseQuantifierMode(),
+ Integer.parseInt(matcher.group(1)));
+ }
+ else if (matcher.group(3) == null)
+ {
+ return Quantifier.atLeast(
+ parseQuantifierMode(),
+ Integer.parseInt(matcher.group(1)));
+ }
+ else
+ {
+ return Quantifier.between(
+ parseQuantifierMode(),
+ Integer.parseInt(matcher.group(1)),
+ Integer.parseInt(matcher.group(3)));
+ }
default:
return null;
}
@@ -235,6 +270,23 @@
}
}
+ private Quantifier.Mode parseQuantifierMode()
+ {
+ if (index < to)
+ {
+ switch (s.charAt(index))
+ {
+ case '?':
+ index++;
+ return Quantifier.Mode.RELUCTANT;
+ case '+':
+ index++;
+ return Quantifier.Mode.POSSESSIVE;
+ }
+ }
+ return Quantifier.Mode.GREEDY;
+ }
+
/**
* character_class -> '[' bracket_list ']' | '[' '^' bracket_list ']'
* bracket_term -> bracket_term | bracket_term bracket_term | bracket_term '&' '&' bracket_term
Added: portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/SubCharSequence.java
===================================================================
--- portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/SubCharSequence.java (rev 0)
+++ portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/SubCharSequence.java 2010-11-26 20:50:07 UTC (rev 5302)
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2010 eXo Platform SAS.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.exoplatform.web.controller.regexp;
+
+/**
+ * Should make it to org.gatein.common somehow.
+ *
+ * @author <a href="mailto:julien.viet@exoplatform.com">Julien Viet</a>
+ * @version $Revision$
+ */
+public class SubCharSequence implements CharSequence
+{
+
+ /** . */
+ private final CharSequence s;
+
+ /** . */
+ private final int from;
+
+ /** . */
+ private final int to;
+
+ public SubCharSequence(CharSequence s, int from, int to)
+ {
+ if (s == null)
+ {
+ throw new NullPointerException("No null string accepted");
+ }
+ if (from < 0)
+ {
+ throw new IllegalArgumentException("No negative lower bound accepted");
+ }
+ if (to > s.length())
+ {
+ throw new IllegalArgumentException("Upper bound cannot be greater than the sequence length");
+ }
+ if (from > to)
+ {
+ throw new IllegalArgumentException("Upper bound cannot be lesser than the lower bound");
+ }
+
+ //
+ this.s = s;
+ this.from = from;
+ this.to = to;
+ }
+
+ public int length()
+ {
+ return to - from;
+ }
+
+ public char charAt(int index)
+ {
+ if (index < 0)
+ {
+ throw new IndexOutOfBoundsException("Index cannot be negative");
+ }
+ index += from;
+ if (index >= to)
+ {
+ throw new IndexOutOfBoundsException("Index cannot be negative");
+ }
+ return s.charAt(index);
+ }
+
+ public CharSequence subSequence(int start, int end)
+ {
+ if (start < 0)
+ {
+ throw new IndexOutOfBoundsException("The start argument cannot be negative");
+ }
+ if (end < 0)
+ {
+ throw new IndexOutOfBoundsException("The start argument cannot be negative");
+ }
+ if (start > end)
+ {
+ throw new IndexOutOfBoundsException("The start argument cannot greater than the end argument");
+ }
+ end += from;
+ if (end > to)
+ {
+ throw new IndexOutOfBoundsException("The end argument cannot greater than the length");
+ }
+ return new SubCharSequence(s, from + start, end);
+ }
+
+ @Override
+ public String toString()
+ {
+ return s.subSequence(from, to).toString();
+ }
+}
Modified: portal/branches/navcontroller/component/web/controller/src/test/java/org/exoplatform/web/controller/regexp/TestParser.java
===================================================================
--- portal/branches/navcontroller/component/web/controller/src/test/java/org/exoplatform/web/controller/regexp/TestParser.java 2010-11-26 19:21:57 UTC (rev 5301)
+++ portal/branches/navcontroller/component/web/controller/src/test/java/org/exoplatform/web/controller/regexp/TestParser.java 2010-11-26 20:50:07 UTC (rev 5302)
@@ -100,18 +100,18 @@
}
return this;
}
- ParserTester assertParseEREDuplSymbol(Quantifier expectedQuantifier)
+ ParserTester assertParseQuantifier(int expectedIndex, Quantifier expectedQuantifier)
{
int index = parser.getIndex();
if (expectedQuantifier != null)
{
assertEquals(expectedQuantifier, parser.parseQuantifierSymbol());
- assertEquals(index + 1, parser.getIndex());
+ assertEquals(expectedIndex, parser.getIndex());
}
else
{
assertNull(parser.parseQuantifierSymbol());
- assertEquals(index, parser.getIndex());
+ assertEquals(expectedIndex, parser.getIndex());
}
return this;
}
@@ -154,19 +154,28 @@
}
// missing stuff:
- // ()
- // +?
- // {0,2}
// escape in bracket
- public void testEREDuplSymbol()
+ public void testQuantifier()
{
- new ParserTester("*").assertParseEREDuplSymbol(Quantifier.STAR);
- new ParserTester("+").assertParseEREDuplSymbol(Quantifier.PLUS);
- new ParserTester("?").assertParseEREDuplSymbol(Quantifier.QUESTION_MARK);
- new ParserTester("a").assertParseEREDuplSymbol(null);
- new ParserTester("").assertParseEREDuplSymbol(null);
+ new ParserTester("*").assertParseQuantifier(1, Quantifier.zeroOrMore(Quantifier.Mode.GREEDY));
+ new ParserTester("+").assertParseQuantifier(1, Quantifier.oneOrMore(Quantifier.Mode.GREEDY));
+ new ParserTester("?").assertParseQuantifier(1, Quantifier.onceOrNotAtAll(Quantifier.Mode.GREEDY));
+ new ParserTester("*a").assertParseQuantifier(1, Quantifier.zeroOrMore(Quantifier.Mode.GREEDY));
+ new ParserTester("+a").assertParseQuantifier(1, Quantifier.oneOrMore(Quantifier.Mode.GREEDY));
+ new ParserTester("?a").assertParseQuantifier(1, Quantifier.onceOrNotAtAll(Quantifier.Mode.GREEDY));
+ new ParserTester("*?").assertParseQuantifier(2, Quantifier.zeroOrMore(Quantifier.Mode.RELUCTANT));
+ new ParserTester("+?").assertParseQuantifier(2, Quantifier.oneOrMore(Quantifier.Mode.RELUCTANT));
+ new ParserTester("??").assertParseQuantifier(2, Quantifier.onceOrNotAtAll(Quantifier.Mode.RELUCTANT));
+ new ParserTester("*+").assertParseQuantifier(2, Quantifier.zeroOrMore(Quantifier.Mode.POSSESSIVE));
+ new ParserTester("++").assertParseQuantifier(2, Quantifier.oneOrMore(Quantifier.Mode.POSSESSIVE));
+ new ParserTester("?+").assertParseQuantifier(2, Quantifier.onceOrNotAtAll(Quantifier.Mode.POSSESSIVE));
+ new ParserTester("a").assertParseQuantifier(0, null);
+ new ParserTester("").assertParseQuantifier(0, null);
+ new ParserTester("{2}").assertParseQuantifier(3, Quantifier.exactly(Quantifier.Mode.GREEDY, 2));
+ new ParserTester("{2,}").assertParseQuantifier(4, Quantifier.atLeast(Quantifier.Mode.GREEDY, 2));
+ new ParserTester("{2,4}").assertParseQuantifier(5, Quantifier.between(Quantifier.Mode.GREEDY, 2, 4));
}
public void testParseBracketExpression()
Added: portal/branches/navcontroller/component/web/controller/src/test/java/org/exoplatform/web/controller/regexp/TestSubCharSequence.java
===================================================================
--- portal/branches/navcontroller/component/web/controller/src/test/java/org/exoplatform/web/controller/regexp/TestSubCharSequence.java (rev 0)
+++ portal/branches/navcontroller/component/web/controller/src/test/java/org/exoplatform/web/controller/regexp/TestSubCharSequence.java 2010-11-26 20:50:07 UTC (rev 5302)
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2010 eXo Platform SAS.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.exoplatform.web.controller.regexp;
+
+import junit.framework.TestCase;
+
+/**
+ * @author <a href="mailto:julien.viet@exoplatform.com">Julien Viet</a>
+ * @version $Revision$
+ */
+public class TestSubCharSequence extends TestCase
+{
+
+ private final CharSequence seq = new SubCharSequence("abcdef", 1, 5);
+
+ public void testState()
+ {
+ assertEquals(4, seq.length());
+ assertEquals('b', seq.charAt(0));
+ assertEquals('c', seq.charAt(1));
+ assertEquals('d', seq.charAt(2));
+ assertEquals('e', seq.charAt(3));
+ assertEquals("bcde", seq.toString());
+ }
+
+ public void testSubSequence()
+ {
+ CharSequence sub = seq.subSequence(1, 3);
+ assertEquals(2, sub.length());
+ assertEquals('c', sub.charAt(0));
+ assertEquals('d', sub.charAt(1));
+ assertEquals("cd", sub.toString());
+ }
+
+ public void testSubSequenceThrowsIOOBE()
+ {
+ assertSubSequenceThrowsIIOBE(-1, 3);
+ assertSubSequenceThrowsIIOBE(1, 5);
+ assertSubSequenceThrowsIIOBE(1, -1);
+ assertSubSequenceThrowsIIOBE(5, 1);
+ }
+
+ private void assertSubSequenceThrowsIIOBE(int start, int end)
+ {
+ try
+ {
+ seq.subSequence(start, end);
+ fail();
+ }
+ catch (IndexOutOfBoundsException e)
+ {
+ }
+ }
+
+ public void testCharAtThrowsIOOBE()
+ {
+ try
+ {
+ seq.charAt(-1);
+ fail();
+ }
+ catch (IndexOutOfBoundsException e)
+ {
+ }
+ try
+ {
+ seq.charAt(4);
+ fail();
+ }
+ catch (IndexOutOfBoundsException e)
+ {
+ }
+ }
+
+ public void testCtorThrowsNPE()
+ {
+ try
+ {
+ new SubCharSequence(null, 1, 5);
+ fail();
+ }
+ catch (NullPointerException e)
+ {
+ }
+ }
+
+ public void testCtorThrowsIAE()
+ {
+ assertCtorThrowsIAE("a", -1, 1);
+ assertCtorThrowsIAE("a", 0, 2);
+ assertCtorThrowsIAE("a", 1, 0);
+ }
+
+ private void assertCtorThrowsIAE(String s, int from, int to)
+ {
+ try
+ {
+ new SubCharSequence(s, from, to);
+ fail();
+ }
+ catch (IllegalArgumentException e)
+ {
+ }
+ }
+}
14 years, 1 month
gatein SVN: r5301 - in portal/branches/navcontroller/component/web/controller/src: main/java/org/exoplatform/web/controller/regexp and 2 other directories.
by do-not-reply@jboss.org
Author: julien_viet
Date: 2010-11-26 14:21:57 -0500 (Fri, 26 Nov 2010)
New Revision: 5301
Added:
portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/
portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/Parser.java
portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/Quantifier.java
portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/RENode.java
portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/RegExpParser.java
portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/SyntaxException.java
portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/package-info.java
portal/branches/navcontroller/component/web/controller/src/test/java/org/exoplatform/web/controller/regexp/
portal/branches/navcontroller/component/web/controller/src/test/java/org/exoplatform/web/controller/regexp/TestParser.java
Log:
start to implement regexp analyser
Added: portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/Parser.java
===================================================================
--- portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/Parser.java (rev 0)
+++ portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/Parser.java 2010-11-26 19:21:57 UTC (rev 5301)
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2010 eXo Platform SAS.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.exoplatform.web.controller.regexp;
+
+/**
+ * @author <a href="mailto:julien.viet@exoplatform.com">Julien Viet</a>
+ * @version $Revision$
+ */
+public abstract class Parser
+{
+
+ /** . */
+ protected final CharSequence s;
+
+ /** . */
+ protected final int from;
+
+ /** . */
+ protected final int to;
+
+ public Parser(CharSequence s)
+ {
+ if (s == null)
+ {
+ throw new NullPointerException();
+ }
+
+ //
+ this.s = s;
+ this.from = 0;
+ this.to = s.length();
+ }
+
+ public Parser(CharSequence s, int from, int to)
+ {
+ if (s == null)
+ {
+ throw new NullPointerException();
+ }
+ if (to > s.length())
+ {
+ throw new IllegalArgumentException();
+ }
+ if (from < 0)
+ {
+ throw new IllegalArgumentException();
+ }
+ if (from > to)
+ {
+ throw new IllegalArgumentException();
+ }
+
+ //
+ this.s = s;
+ this.from = from;
+ this.to = to;
+ }
+
+ public final int getFrom()
+ {
+ return from;
+ }
+
+ public final int getTo()
+ {
+ return to;
+ }
+
+ protected final int lastIndexOf(char c)
+ {
+ for (int i = to - 1;i >= from;i--)
+ {
+ if (s.charAt(i) == c)
+ {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ protected final int indexOfBlah(int from, int to, char start, char end)
+ {
+ int closing = -1;
+ int depth = 0;
+ for (int i = from + 1;i < to;i++)
+ {
+ char c = s.charAt(i);
+ if (c == start)
+ {
+ depth++;
+ }
+ else if (c == end)
+ {
+ if (depth == 0)
+ {
+ closing = i;
+ break;
+ }
+ else
+ {
+ depth--;
+ }
+ }
+ }
+ return closing;
+ }
+
+ protected final int indexOf(int from, char c, int to)
+ {
+ for (int i = from;i < to;i++)
+ {
+ if (s.charAt(i) == c)
+ {
+ return i;
+ }
+ }
+ return -1;
+ }
+}
Added: portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/Quantifier.java
===================================================================
--- portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/Quantifier.java (rev 0)
+++ portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/Quantifier.java 2010-11-26 19:21:57 UTC (rev 5301)
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2010 eXo Platform SAS.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.exoplatform.web.controller.regexp;
+
+/**
+ * @author <a href="mailto:julien.viet@exoplatform.com">Julien Viet</a>
+ * @version $Revision$
+ */
+public abstract class Quantifier
+{
+
+ private Quantifier()
+ {
+ }
+
+ /** . */
+ public static final Quantifier STAR = new Quantifier()
+ {
+ @Override
+ public String toString()
+ {
+ return "*";
+ }
+ };
+
+ /** . */
+ public static final Quantifier PLUS = new Quantifier()
+ {
+ @Override
+ public String toString()
+ {
+ return "+";
+ }
+ };
+
+ /** . */
+ public static final Quantifier QUESTION_MARK = new Quantifier()
+ {
+ @Override
+ public String toString()
+ {
+ return "?";
+ }
+ };
+
+}
Added: portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/RENode.java
===================================================================
--- portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/RENode.java (rev 0)
+++ portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/RENode.java 2010-11-26 19:21:57 UTC (rev 5301)
@@ -0,0 +1,376 @@
+/*
+ * Copyright (C) 2010 eXo Platform SAS.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.exoplatform.web.controller.regexp;
+
+import org.hibernate.criterion.Disjunction;
+
+/**
+ * @author <a href="mailto:julien.viet@exoplatform.com">Julien Viet</a>
+ * @version $Revision$
+ */
+public abstract class RENode
+{
+
+ public static class Disjunction extends RENode
+ {
+
+ /** . */
+ private final Disjunction next;
+
+ /** . */
+ private final Alternative alternative;
+
+ public Disjunction(Alternative alternative)
+ {
+ this.alternative = alternative;
+ this.next = null;
+ }
+
+ public Disjunction(Alternative alternative, Disjunction next)
+ {
+ this.alternative = alternative;
+ this.next = next;
+ }
+
+ @Override
+ public String toString()
+ {
+ if (next != null)
+ {
+ return alternative + "|" + next;
+ }
+ else
+ {
+ return alternative.toString();
+ }
+ }
+ }
+
+ public static class Alternative extends RENode
+ {
+
+ /** . */
+ private final Exp exp;
+
+ /** . */
+ private final Alternative next;
+
+ public Alternative(Exp exp)
+ {
+ this.exp = exp;
+ this.next = null;
+ }
+
+ public Alternative(Exp exp, Alternative next)
+ {
+ this.exp = exp;
+ this.next = next;
+ }
+
+ @Override
+ public String toString()
+ {
+ if (next != null)
+ {
+ return exp.toString() + next;
+ }
+ else
+ {
+ return exp.toString();
+ }
+ }
+ }
+
+ public String toString()
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ public static abstract class Exp extends RENode
+ {
+ }
+
+ public static class Assertion extends Exp
+ {
+ /** . */
+ public static final Assertion BEGIN = new Assertion()
+ {
+ @Override
+ public String toString()
+ {
+ return "<^/>";
+ }
+ };
+
+ /** . */
+ public static final Assertion END = new Assertion()
+ {
+ @Override
+ public String toString()
+ {
+ return "<$/>";
+ }
+ };
+
+ private Assertion()
+ {
+ }
+ }
+
+ public static final class QuantifiedExp extends Exp
+ {
+ /** . */
+ private final Exp exp;
+
+ /** . */
+ private final Quantifier quantifier;
+
+ public QuantifiedExp(Exp exp, Quantifier quantifier)
+ {
+ this.exp = exp;
+ this.quantifier = quantifier;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "<" + quantifier + ">" + exp + "</" + quantifier + ">";
+ }
+ }
+
+ public static abstract class Atom extends Exp
+ {
+ }
+
+ public static final class Dot extends Atom
+ {
+
+ /** . */
+ public static Dot INSTANCE = new Dot();
+
+ private Dot()
+ {
+ }
+
+ public String toString()
+ {
+ return "<./>";
+ }
+ }
+
+ public static final class Group extends Atom
+ {
+
+ /** . */
+ private final Disjunction disjunction;
+
+ public Group(Disjunction disjunction)
+ {
+ this.disjunction = disjunction;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "<(>" + disjunction + "</)>";
+ }
+ }
+
+ public static final class Character extends Atom
+ {
+
+ /** . */
+ private final char value;
+
+ public Character(char value)
+ {
+ this.value = value;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "<c>" + value + "</c>";
+ }
+ }
+
+ public static abstract class CharacterClass extends Atom
+ {
+
+ protected abstract void toString(StringBuilder sb);
+
+ public static class Not extends CharacterClass
+ {
+
+ /** . */
+ private final CharacterClass negated;
+
+ public Not(CharacterClass negated)
+ {
+ this.negated = negated;
+ }
+
+ @Override
+ public String toString()
+ {
+ StringBuilder sb = new StringBuilder();
+ toString(sb);
+ return sb.toString();
+ }
+
+ @Override
+ protected void toString(StringBuilder sb)
+ {
+ sb.append("[^");
+ negated.toString(sb);
+ sb.append("]");
+ }
+ }
+
+ public static class Or extends CharacterClass
+ {
+
+ /** . */
+ private final CharacterClass left;
+
+ /** . */
+ private final CharacterClass right;
+
+ public Or(CharacterClass left, CharacterClass right)
+ {
+ this.left = left;
+ this.right = right;
+ }
+
+ @Override
+ public String toString()
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.append("[");
+ toString(sb);
+ sb.append("]");
+ return sb.toString();
+ }
+
+ @Override
+ protected void toString(StringBuilder sb)
+ {
+ left.toString(sb);
+ right.toString(sb);
+ }
+ }
+
+ public static class And extends CharacterClass
+ {
+
+ /** . */
+ private final CharacterClass left;
+
+ /** . */
+ private final CharacterClass right;
+
+ public And(CharacterClass left, CharacterClass right)
+ {
+ this.left = left;
+ this.right = right;
+ }
+
+ @Override
+ public String toString()
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.append("[");
+ toString(sb);
+ sb.append("]");
+ return sb.toString();
+ }
+
+ @Override
+ protected void toString(StringBuilder sb)
+ {
+ left.toString(sb);
+ sb.append("&&");
+ right.toString(sb);
+ }
+ }
+
+ public static class Simple extends CharacterClass
+ {
+
+ /** . */
+ private final char value;
+
+ public Simple(char value)
+ {
+ this.value = value;
+ }
+
+ @Override
+ public String toString()
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.append("[");
+ toString(sb);
+ sb.append("]");
+ return sb.toString();
+ }
+
+ @Override
+ protected void toString(StringBuilder sb)
+ {
+ sb.append(value);
+ }
+ }
+
+ public static class Range extends CharacterClass
+ {
+
+ /** From inclusive. */
+ private final char from;
+
+ /** To inclusive. */
+ private final char to;
+
+ public Range(char from, char to)
+ {
+ this.from = from;
+ this.to = to;
+ }
+
+ @Override
+ public String toString()
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.append("[");
+ toString(sb);
+ sb.append("]");
+ return sb.toString();
+ }
+
+ @Override
+ protected void toString(StringBuilder sb)
+ {
+ sb.append(from);
+ sb.append('-');
+ sb.append(to);
+ }
+ }
+ }
+}
Added: portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/RegExpParser.java
===================================================================
--- portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/RegExpParser.java (rev 0)
+++ portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/RegExpParser.java 2010-11-26 19:21:57 UTC (rev 5301)
@@ -0,0 +1,320 @@
+/*
+ * Copyright (C) 2010 eXo Platform SAS.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.exoplatform.web.controller.regexp;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * @author <a href="mailto:julien.viet@exoplatform.com">Julien Viet</a>
+ * @version $Revision$
+ */
+public class RegExpParser extends Parser
+{
+
+ /** . */
+ private static final Set<Character> ESCAPABLE = new HashSet<Character>();
+
+ static
+ {
+ for (char c : "^.[$()|*+?{\\".toCharArray())
+ {
+ ESCAPABLE.add(c);
+ }
+ }
+
+ /** . */
+ private int index;
+
+ public RegExpParser(CharSequence s)
+ {
+ super(s);
+
+ //
+ this.index = 0;
+ }
+
+ public RegExpParser(CharSequence s, int from, int to)
+ {
+ super(s, from, to);
+
+ //
+ this.index = from;
+ }
+
+ public int getIndex()
+ {
+ return index;
+ }
+
+ /**
+ * disjunction -> alternative | alternative '|' disjunction
+ *
+ * @return the disjunction
+ */
+ public RENode.Disjunction parseDisjunction()
+ {
+ int pipe = lastIndexOf('|');
+ if (pipe == -1)
+ {
+ return new RENode.Disjunction(parseAlternative());
+ }
+ else
+ {
+ RegExpParser left = new RegExpParser(s, from, pipe);
+ RENode.Alternative alternative = left.parseAlternative();
+ RegExpParser right = new RegExpParser(s, pipe + 1, to);
+ RENode.Disjunction next = right.parseDisjunction();
+ index = to;
+ return new RENode.Disjunction(alternative, next);
+ }
+ }
+
+ /**
+ * alternative -> expression | expression '|' alternative
+ *
+ * @return the alternative
+ */
+ public RENode.Alternative parseAlternative()
+ {
+ if (index < to)
+ {
+ RENode.Exp exp = parseExpression();
+ if (index < to)
+ {
+ RENode.Alternative next = parseAlternative();
+ return new RENode.Alternative(exp, next);
+ }
+ else
+ {
+ return new RENode.Alternative(exp);
+ }
+ }
+ else
+ {
+ throw new SyntaxException();
+ }
+ }
+
+ /**
+ * expression -> assertion | '(' disjunction ')' | '(' '?' disjunction ')' | character | expression quantifier
+ * assertion -> '^' | '$'
+ * character -> '.' | escaped | character_class | literal
+ * escaped -> '\' any char
+ * quantifier -> '*' | '+' | '?' | '{' count '}' | '{' count ',' '}' | '{' count ',' count '}'
+ * literal -> todo
+ *
+ * @return the expression
+ */
+ public RENode.Exp parseExpression()
+ {
+ if (index == to)
+ {
+ throw new SyntaxException();
+ }
+ RENode.Exp exp;
+ char c = s.charAt(index);
+ switch (c)
+ {
+ case '^':
+ exp = RENode.Exp.Assertion.BEGIN;
+ index++;
+ break;
+ case '$':
+ exp = RENode.Exp.Assertion.END;
+ index++;
+ break;
+ case '(':
+ int closingParenthesis = indexOfBlah(index + 1, to, '(', ')');
+ if (closingParenthesis == -1)
+ {
+ throw new SyntaxException();
+ }
+ RENode.Disjunction grouped = new RegExpParser(s, index + 1, closingParenthesis).parseDisjunction();
+ exp = new RENode.Group(grouped);
+ index = closingParenthesis + 1;
+ break;
+ case '*':
+ case '+':
+ case '?':
+ case '{':
+ case '|':
+ throw new SyntaxException();
+
+ case '[':
+ int closingBracket = indexOfBlah(index + 1, to, '[', ']');
+ if (closingBracket == -1)
+ {
+ throw new SyntaxException();
+ }
+ exp = parseCharacterClass(index, closingBracket + 1);
+ index = closingBracket + 1;
+ break;
+ case '\\':
+ if (index +1 < to)
+ {
+ index++;
+ char escaped = s.charAt(index);
+ if (!ESCAPABLE.contains(escaped))
+ {
+ throw new SyntaxException();
+ }
+ exp = new RENode.Character(escaped);
+ index++;
+ break;
+ }
+ else
+ {
+ throw new SyntaxException();
+ }
+ case '.':
+ exp = RENode.Dot.INSTANCE;
+ index++;
+ break;
+ default:
+ exp = new RENode.Character(c);
+ index++;
+ break;
+ //
+ }
+
+ //
+ Quantifier quantifier = parseQuantifierSymbol();
+ if (quantifier != null)
+ {
+ exp = new RENode.QuantifiedExp(exp, quantifier);
+ }
+
+ //
+ return exp;
+ }
+
+ Quantifier parseQuantifierSymbol()
+ {
+ if (index < to)
+ {
+ char c = s.charAt(index);
+ switch (c)
+ {
+ case '*':
+ index++;
+ return Quantifier.STAR;
+ case '+':
+ index++;
+ return Quantifier.PLUS;
+ case '?':
+ index++;
+ return Quantifier.QUESTION_MARK;
+ case '{':
+ index++;
+ throw new UnsupportedOperationException();
+ default:
+ return null;
+ }
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ /**
+ * character_class -> '[' bracket_list ']' | '[' '^' bracket_list ']'
+ * bracket_term -> bracket_term | bracket_term bracket_term | bracket_term '&' '&' bracket_term
+ * bracket_term -> character_class | single_term | range_term
+ *
+ * @param begin the begin
+ * @param end the end
+ * @return a character class expression
+ */
+ private RENode.CharacterClass parseCharacterClass(int begin, int end)
+ {
+ if (begin == end)
+ {
+ throw new SyntaxException();
+ }
+
+ // Check if we do have bracket around or not
+ boolean matching = true;
+ if (s.charAt(begin) == '[')
+ {
+ if (end - begin < 3)
+ {
+ throw new SyntaxException();
+ }
+ if (s.charAt(end - 1) != ']')
+ {
+ throw new SyntaxException();
+ }
+
+ //
+ begin++;
+ end--;
+
+ //
+ if (s.charAt(begin) == '^' && begin + 1 < end)
+ {
+ begin++;
+ matching = false;
+ }
+ }
+
+ //
+ //
+ RENode.CharacterClass cc;
+ char c = s.charAt(begin);
+ begin++;
+ if (begin + 1 < end && s.charAt(begin) == '-')
+ {
+ cc = new RENode.CharacterClass.Range(c, s.charAt(begin + 1));
+ begin += 2;
+ }
+ else
+ {
+ cc = new RENode.CharacterClass.Simple(c);
+ }
+
+ //
+ if (begin < end)
+ {
+ char n = s.charAt(begin);
+ if (n == '&' && begin + 1 < end && s.charAt(begin + 1) == '&')
+ {
+ RENode.CharacterClass next = parseCharacterClass(begin + 2, end);
+ cc = new RENode.CharacterClass.And(cc, next);
+ }
+ else
+ {
+ RENode.CharacterClass next = parseCharacterClass(begin, end);
+ cc = new RENode.CharacterClass.Or(cc, next);
+ }
+ }
+
+ //
+ if (matching)
+ {
+ return cc;
+ }
+ else
+ {
+ return new RENode.CharacterClass.Not(cc);
+ }
+ }
+}
Added: portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/SyntaxException.java
===================================================================
--- portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/SyntaxException.java (rev 0)
+++ portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/SyntaxException.java 2010-11-26 19:21:57 UTC (rev 5301)
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2010 eXo Platform SAS.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.exoplatform.web.controller.regexp;
+
+/**
+ * @author <a href="mailto:julien.viet@exoplatform.com">Julien Viet</a>
+ * @version $Revision$
+ */
+public class SyntaxException extends RuntimeException
+{
+ public SyntaxException()
+ {
+ }
+
+ public SyntaxException(String s)
+ {
+ super(s);
+ }
+
+ public SyntaxException(String s, Throwable throwable)
+ {
+ super(s, throwable);
+ }
+
+ public SyntaxException(Throwable throwable)
+ {
+ super(throwable);
+ }
+}
Added: portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/package-info.java
===================================================================
--- portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/package-info.java (rev 0)
+++ portal/branches/navcontroller/component/web/controller/src/main/java/org/exoplatform/web/controller/regexp/package-info.java 2010-11-26 19:21:57 UTC (rev 5301)
@@ -0,0 +1,42 @@
+/**
+ * Grammar:
+ * extended_reg_exp -> ERE_branch | extended_reg_exp '|' ERE_branch
+ * ERE_branch -> ERE_expression | ERE_branch ERE_expression
+ * ERE_expression -> one_character_ERE | '^' | '$' | '(' extended_reg_exp ')' | ERE_expression ERE_dupl_symbol
+ * one_character_ERE -> ORD_CHAR | QUOTED_CHAR | '.' | bracket_expression
+ * ERE_dupl_symbol -> '*' | '+' | '?' | '{' DUP_COUNT '}' | '{' DUP_COUNT ',' '}' | '{' DUP_COUNT ',' DUP_COUNT '}'
+ *
+ * bracket_expression -> '[' matching_list ']' | '[' nonmatching_list ']'
+ * matching_list -> bracket_list
+ * nonmatching_list -> '^' bracket_list
+ * bracket_list -> follow_list | follow_list '-'
+ * follow_list -> expression_term | follow_list expression_term
+ * expression_term -> single_expression | range_expression
+ * single_expression -> end_range | character_class | equivalence_class
+ * range_expression -> start_range end_range | start_range '-'
+ * start_range -> end_range '-'
+ * end_range -> COLL_ELEM | collating_symbol
+ * collating_symbol -> Open_dot COLL_ELEM Dot_close Open_dot META_CHAR Dot_close
+ * equivalence_class -> Open_equal COLL_ELEM Equal_close
+ * character_class -> Open_colon class_name Colon_close
+ *
+ * ORD_CHAR : A character, other than one of the special characters in SPEC_CHAR
+ * SPEC_CHAR : '^' '.' '[' '$' '(' ')' '|' '*' '+' '?' '{' '\'
+ * QUOTED_CHAR : '\^' '\.' '\[' '\$' '\(' '\)' '\|' '\*' '\+' '\?' '\{' '\\'
+ * DUP_COUNT : Represents a numeric constant. This token will only be recognised when the context of the grammar
+ * requires it. At all other times, digits not preceded by '\' will be treated as ORD_CHAR
+ * COLL_ELEM : Any single-character collating element, unless it is a META_CHAR
+ * META_CHAR :
+ * '^' when found first in a bracket expression
+ * '-' when found anywhere but first (after an initial '^', if any) or last in a bracket expression, or as the ending
+ * range point in a range expression
+ * ']' when found anywhere but first (after an initial '^' if any) in a bracket expression
+ *
+ * Open_dot : '[.'
+ * Dot_close : '.]'
+ * Open_equal : '[='
+ * Equal_close : '=]'
+ * Open_colon : '[:'
+ * Colon_close : ':]'
+ */
+package org.exoplatform.web.controller.regexp;
\ No newline at end of file
Added: portal/branches/navcontroller/component/web/controller/src/test/java/org/exoplatform/web/controller/regexp/TestParser.java
===================================================================
--- portal/branches/navcontroller/component/web/controller/src/test/java/org/exoplatform/web/controller/regexp/TestParser.java (rev 0)
+++ portal/branches/navcontroller/component/web/controller/src/test/java/org/exoplatform/web/controller/regexp/TestParser.java 2010-11-26 19:21:57 UTC (rev 5301)
@@ -0,0 +1,190 @@
+/*
+ * Copyright (C) 2010 eXo Platform SAS.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.exoplatform.web.controller.regexp;
+
+import junit.framework.TestCase;
+
+import java.util.regex.Pattern;
+
+/**
+ * @author <a href="mailto:julien.viet@exoplatform.com">Julien Viet</a>
+ * @version $Revision$
+ */
+public class TestParser extends TestCase
+{
+
+
+ public void testSomeStuff()
+ {
+ Pattern pattern = Pattern.compile("^[\\^a\b]$");
+ assertTrue(pattern.matcher("^").matches());
+ assertTrue(pattern.matcher("a").matches());
+
+ }
+
+ private static class ParserTester
+ {
+ private final RegExpParser parser;
+ private ParserTester(CharSequence s)
+ {
+ this.parser = new RegExpParser(s);
+ }
+ private ParserTester(CharSequence s, int from, int to)
+ {
+ this.parser = new RegExpParser(s, from, to);
+ }
+ ParserTester assertParseBracketExpression(String expectedValue)
+ {
+ RENode node = parser.parseExpression();
+ assertTrue(node instanceof RENode.CharacterClass);
+ assertEquals(expectedValue, node.toString());
+ return this;
+ }
+ ParserTester assertParseExtendedRegExp(String expectedValue)
+ {
+ int expectedIndex = parser.getTo();
+ RENode.Disjunction disjunction = parser.parseDisjunction();
+ assertEquals(expectedValue, disjunction.toString());
+ assertEquals(expectedIndex, parser.getIndex());
+ return this;
+ }
+ ParserTester assertNotParseExtendedRegExp()
+ {
+ int expectedIndex = parser.getIndex();
+ try
+ {
+ parser.parseDisjunction();
+ fail();
+ }
+ catch (SyntaxException e)
+ {
+ assertEquals(expectedIndex, parser.getIndex());
+ }
+ return this;
+ }
+ ParserTester assertParseExpression(String expectedValue, int expectedIndex)
+ {
+ RENode.Exp exp = parser.parseExpression();
+ assertEquals(expectedValue, exp.toString());
+ assertEquals(expectedIndex, parser.getIndex());
+ return this;
+ }
+ ParserTester assertNotParseEREExpression()
+ {
+ int index = parser.getIndex();
+ try
+ {
+ parser.parseExpression();
+ fail();
+ }
+ catch (SyntaxException e)
+ {
+ assertEquals(index, parser.getIndex());
+ }
+ return this;
+ }
+ ParserTester assertParseEREDuplSymbol(Quantifier expectedQuantifier)
+ {
+ int index = parser.getIndex();
+ if (expectedQuantifier != null)
+ {
+ assertEquals(expectedQuantifier, parser.parseQuantifierSymbol());
+ assertEquals(index + 1, parser.getIndex());
+ }
+ else
+ {
+ assertNull(parser.parseQuantifierSymbol());
+ assertEquals(index, parser.getIndex());
+ }
+ return this;
+ }
+ ParserTester assertIndex(int expectedIndex)
+ {
+ assertEquals(expectedIndex, parser.getIndex());
+ return this;
+ }
+ }
+
+ public void testExtendedRegexp()
+ {
+ new ParserTester("^").assertParseExtendedRegExp("<^/>");
+ new ParserTester("^$").assertParseExtendedRegExp("<^/><$/>");
+ new ParserTester("a").assertParseExtendedRegExp("<c>a</c>");
+ new ParserTester("a|b").assertParseExtendedRegExp("<c>a</c>|<c>b</c>");
+ new ParserTester("a+|b*").assertParseExtendedRegExp("<+><c>a</c></+>|<*><c>b</c></*>");
+ }
+
+ public void testExpression()
+ {
+ new ParserTester("").assertNotParseEREExpression();
+ new ParserTester("^").assertParseExpression("<^/>", 1);
+ new ParserTester("^+").assertParseExpression("<+><^/></+>", 2);
+ new ParserTester("$").assertParseExpression("<$/>", 1);
+ new ParserTester("$+").assertParseExpression("<+><$/></+>", 2);
+ new ParserTester("a").assertParseExpression("<c>a</c>", 1);
+ new ParserTester("a+").assertParseExpression("<+><c>a</c></+>", 2);
+ new ParserTester(".").assertParseExpression("<./>", 1);
+ new ParserTester(".+").assertParseExpression("<+><./></+>", 2);
+ new ParserTester("\\+").assertParseExpression("<c>+</c>", 2);
+ new ParserTester("\\++").assertParseExpression("<+><c>+</c></+>", 3);
+ new ParserTester("*").assertNotParseEREExpression();
+ new ParserTester("+").assertNotParseEREExpression();
+ new ParserTester("?").assertNotParseEREExpression();
+ new ParserTester("{").assertNotParseEREExpression();
+ new ParserTester("|").assertNotParseEREExpression();
+ new ParserTester("(a)").assertParseExpression("<(><c>a</c></)>", 3);
+ new ParserTester("(a(b)c)").assertParseExpression("<(><c>a</c><(><c>b</c></)><c>c</c></)>", 7);
+ }
+
+ // missing stuff:
+ // ()
+ // +?
+ // {0,2}
+ // escape in bracket
+
+
+ public void testEREDuplSymbol()
+ {
+ new ParserTester("*").assertParseEREDuplSymbol(Quantifier.STAR);
+ new ParserTester("+").assertParseEREDuplSymbol(Quantifier.PLUS);
+ new ParserTester("?").assertParseEREDuplSymbol(Quantifier.QUESTION_MARK);
+ new ParserTester("a").assertParseEREDuplSymbol(null);
+ new ParserTester("").assertParseEREDuplSymbol(null);
+ }
+
+ public void testParseBracketExpression()
+ {
+ new ParserTester("[a]").assertParseBracketExpression("[a]");
+ new ParserTester("[^a]").assertParseBracketExpression("[^a]");
+ new ParserTester("[^a-b]").assertParseBracketExpression("[^a-b]");
+ new ParserTester("[a-b]").assertParseBracketExpression("[a-b]");
+ new ParserTester("[ab]").assertParseBracketExpression("[ab]");
+ new ParserTester("[a&]").assertParseBracketExpression("[a&]");
+ new ParserTester("[a&&b]").assertParseBracketExpression("[a&&b]");
+ new ParserTester("[a&&[^b]]").assertParseBracketExpression("[a&&[^b]]");
+ new ParserTester("[a[^b]]").assertParseBracketExpression("[a[^b]]");
+ new ParserTester("[a[b]]").assertParseBracketExpression("[ab]");
+ new ParserTester("[-]").assertParseBracketExpression("[-]");
+ new ParserTester("[a-]").assertParseBracketExpression("[a-]");
+ new ParserTester("[---]").assertParseBracketExpression("[---]");
+ new ParserTester("[#--]").assertParseBracketExpression("[#--]");
+ }
+
+}
14 years, 1 month