BUG-5410: introduce RegularExpression.toPatternString() 44/45144/5
authorRobert Varga <rovarga@cisco.com>
Mon, 5 Sep 2016 07:48:10 +0000 (09:48 +0200)
committerRobert Varga <nite@hq.sk>
Thu, 13 Oct 2016 14:48:34 +0000 (14:48 +0000)
This patch adds a method useful for converting a RegularExpression
into a Pattern-compatible string.

Change-Id: I6ab002dc6e9324967d41072ea46af4d65363bff0
Signed-off-by: Robert Varga <rovarga@cisco.com>
third-party/xsd-regex/src/main/java/org/opendaylight/yangtools/xsd/regex/RangeToken.java
third-party/xsd-regex/src/main/java/org/opendaylight/yangtools/xsd/regex/RegularExpression.java
third-party/xsd-regex/src/main/java/org/opendaylight/yangtools/xsd/regex/Token.java
third-party/xsd-regex/src/test/java/org/opendaylight/yangtools/xsd/regex/ToPatternStringTest.java [new file with mode: 0644]

index a6640e4ec29c351e9c698e869995be17f4fb8b9c..1328475764c3b3b396a9822ed6df679906ccfed2 100644 (file)
@@ -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;
             }
index ef6df06631c6633a4545652fc8d7bdfaeb1d68aa..7f3a4453067ff7c113751b4b4e64a1bf34b95e38 100644 (file)
@@ -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;
     }
 
     /**
index 14620cf8ad78f58c793e7f4c040380e2cd20307c..5a85f0b14e1bb0989b3a793f7dacdc77a89e3d39 100644 (file)
@@ -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 (file)
index 0000000..bc4e315
--- /dev/null
@@ -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]?");
+    }
+}