From 871687bc398410e4b2e4e35dce06edce53920f00 Mon Sep 17 00:00:00 2001 From: Robert Varga Date: Mon, 5 Sep 2016 09:48:10 +0200 Subject: [PATCH] BUG-5410: introduce RegularExpression.toPatternString() This patch adds a method useful for converting a RegularExpression into a Pattern-compatible string. Change-Id: I6ab002dc6e9324967d41072ea46af4d65363bff0 Signed-off-by: Robert Varga --- .../yangtools/xsd/regex/RangeToken.java | 26 ++-- .../xsd/regex/RegularExpression.java | 14 ++- .../yangtools/xsd/regex/Token.java | 12 +- .../xsd/regex/ToPatternStringTest.java | 118 ++++++++++++++++++ 4 files changed, 159 insertions(+), 11 deletions(-) create mode 100644 third-party/xsd-regex/src/test/java/org/opendaylight/yangtools/xsd/regex/ToPatternStringTest.java diff --git a/third-party/xsd-regex/src/main/java/org/opendaylight/yangtools/xsd/regex/RangeToken.java b/third-party/xsd-regex/src/main/java/org/opendaylight/yangtools/xsd/regex/RangeToken.java index a6640e4ec2..1328475764 100644 --- a/third-party/xsd-regex/src/main/java/org/opendaylight/yangtools/xsd/regex/RangeToken.java +++ b/third-party/xsd-regex/src/main/java/org/opendaylight/yangtools/xsd/regex/RangeToken.java @@ -594,11 +594,11 @@ final class RangeToken extends Token implements java.io.Serializable { sb.append(','); } if (this.ranges[i] == this.ranges[i+1]) { - sb.append(escapeCharInCharClass(this.ranges[i])); + sb.append(escapeCharInCharClass(this.ranges[i], options)); } else { - sb.append(escapeCharInCharClass(this.ranges[i])); + sb.append(escapeCharInCharClass(this.ranges[i], options)); sb.append('-'); - sb.append(escapeCharInCharClass(this.ranges[i+1])); + sb.append(escapeCharInCharClass(this.ranges[i+1], options)); } } sb.append(']'); @@ -619,11 +619,11 @@ final class RangeToken extends Token implements java.io.Serializable { sb.append(','); } if (this.ranges[i] == this.ranges[i+1]) { - sb.append(escapeCharInCharClass(this.ranges[i])); + sb.append(escapeCharInCharClass(this.ranges[i], options)); } else { - sb.append(escapeCharInCharClass(this.ranges[i])); + sb.append(escapeCharInCharClass(this.ranges[i], options)); sb.append('-'); - sb.append(escapeCharInCharClass(this.ranges[i+1])); + sb.append(escapeCharInCharClass(this.ranges[i+1], options)); } } sb.append(']'); @@ -633,7 +633,7 @@ final class RangeToken extends Token implements java.io.Serializable { return ret; } - private static String escapeCharInCharClass(int ch) { + private static String escapeCharInCharClass(int ch, int options) { String ret; switch (ch) { case '[': case ']': case '-': case '^': @@ -645,6 +645,11 @@ final class RangeToken extends Token implements java.io.Serializable { case '\r': ret = "\\r"; break; case '\t': ret = "\\t"; break; case 0x1b: ret = "\\e"; break; + case '$': + if (isSet(options, RegularExpression.XMLSCHEMA_MODE)) { + ret = "\\$"; + break; + } //case 0x0b: ret = "\\v"; break; default: if (ch < 0x20) { @@ -652,7 +657,12 @@ final class RangeToken extends Token implements java.io.Serializable { ret = "\\x"+pre.substring(pre.length()-2, pre.length()); } else if (ch >= 0x10000) { String pre = "0"+Integer.toHexString(ch); - ret = "\\v"+pre.substring(pre.length()-6, pre.length()); + String sub = pre.substring(pre.length()-6, pre.length()); + if (isSet(options, RegularExpression.XMLSCHEMA_MODE)) { + ret = "\\x{"+sub+"}"; + } else { + ret = "\\v"+sub; + } } else { ret = ""+(char)ch; } diff --git a/third-party/xsd-regex/src/main/java/org/opendaylight/yangtools/xsd/regex/RegularExpression.java b/third-party/xsd-regex/src/main/java/org/opendaylight/yangtools/xsd/regex/RegularExpression.java index ef6df06631..7f3a445306 100644 --- a/third-party/xsd-regex/src/main/java/org/opendaylight/yangtools/xsd/regex/RegularExpression.java +++ b/third-party/xsd-regex/src/main/java/org/opendaylight/yangtools/xsd/regex/RegularExpression.java @@ -2369,11 +2369,21 @@ public class RegularExpression implements java.io.Serializable { } /** - * Represents this instence in String. + * Represents this instance in String. */ @Override public String toString() { - return this.tokentree.toString(this.options); + return this.tokentree.toString(this.options & ~XMLSCHEMA_MODE); + } + + /** + * Returns a {@link java.util.regex.Pattern}-compatible string representation of this expression. + * + * @return A Pattern-compatible String representation + */ + public String toPatternString() { + final String str = this.tokentree.toString(this.options); + return isSet(options, XMLSCHEMA_MODE) ? "^" + str + "$" : str; } /** diff --git a/third-party/xsd-regex/src/main/java/org/opendaylight/yangtools/xsd/regex/Token.java b/third-party/xsd-regex/src/main/java/org/opendaylight/yangtools/xsd/regex/Token.java index 14620cf8ad..5a85f0b14e 100644 --- a/third-party/xsd-regex/src/main/java/org/opendaylight/yangtools/xsd/regex/Token.java +++ b/third-party/xsd-regex/src/main/java/org/opendaylight/yangtools/xsd/regex/Token.java @@ -421,7 +421,7 @@ class Token implements java.io.Serializable { static final int FC_CONTINUE = 0; static final int FC_TERMINAL = 1; static final int FC_ANY = 2; - private static final boolean isSet(int options, int flag) { + static final boolean isSet(int options, int flag) { return (options & flag) == flag; } final int analyzeFirstCharacter(RangeToken result, int options) { @@ -1269,6 +1269,16 @@ class Token implements java.io.Serializable { default: ret = null; } + + if (isSet(options, RegularExpression.XMLSCHEMA_MODE)) { + if ("$".equals(ret)) { + return "\\$"; + } + if ("^".equals(ret)) { + return "\\^"; + } + } + return ret; } diff --git a/third-party/xsd-regex/src/test/java/org/opendaylight/yangtools/xsd/regex/ToPatternStringTest.java b/third-party/xsd-regex/src/test/java/org/opendaylight/yangtools/xsd/regex/ToPatternStringTest.java new file mode 100644 index 0000000000..bc4e31560a --- /dev/null +++ b/third-party/xsd-regex/src/test/java/org/opendaylight/yangtools/xsd/regex/ToPatternStringTest.java @@ -0,0 +1,118 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.opendaylight.yangtools.xsd.regex; + +import static org.junit.Assert.assertEquals; +import java.util.regex.Pattern; +import org.junit.Test; + +public class ToPatternStringTest { + + private static void testPattern(final String xsd, final String java) { + final RegularExpression regex = new RegularExpression(xsd, "Xu"); + final String patternString = regex.toPatternString(); + + final String expected = '^' + java + "$"; + assertEquals(expected, patternString); + Pattern.compile(patternString); + } + + @Test + public void testCaret() { + testPattern("^", "\\^"); + } + + @Test + public void testTextCaret() { + testPattern("abc^", "abc\\^"); + } + + @Test + public void testTextDollar() { + testPattern("abc$", "abc\\$"); + } + + @Test + public void testCaretCaret() { + testPattern("^^", "\\^\\^"); + } + + @Test + public void testCaretDollar() { + testPattern("^$", "\\^\\$"); + } + + @Test + public void testDot() { + testPattern(".", "."); + } + + @Test + public void testNotColon() { + testPattern("[^:]+", "[\\x00-9;-\\x{10ffff}]+"); + } + + @Test + public void testDollar() { + testPattern("$", "\\$"); + } + + @Test + public void testDollarOneDollar() { + testPattern("$1$", "\\$1\\$"); + } + + @Test + public void testDollarPercentRange() { + testPattern("[$-%]+", "[\\$-%]+"); + } + + @Test + public void testDollarRange() { + testPattern("[$$]+", "[\\$]+"); + } + + @Test + public void testDollarCaretRange() { + testPattern("[$^]+", "[\\$\\^]+"); + } + + @Test + public void testSimple() { + testPattern("abc", "abc"); + } + + @Test + public void testDotPlus() { + testPattern(".+", ".+"); + } + + @Test + public void testDotStar() { + testPattern(".*", ".*"); + } + + @Test + public void testSimpleOptional() { + testPattern("a?", "a?"); + } + + @Test + public void testRangeOptional() { + testPattern("[a-z]?", "[a-z]?"); + } +} -- 2.36.6