BUG-865: deprecate pre-Beryllium parser elements
[yangtools.git] / yang / yang-parser-impl / src / main / java / org / opendaylight / yangtools / yang / parser / impl / ParserListenerUtils.java
index eaece86cadde4c6b930228fd38c2d95cb55d85ff..fadb1a23536237d29688e11c8da6a42b340ee92f 100644 (file)
@@ -3,15 +3,16 @@
  *
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/eplv10.html
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
  */
+
 package org.opendaylight.yangtools.yang.parser.impl;
 
 import static com.google.common.base.Preconditions.checkState;
-
 import com.google.common.base.CharMatcher;
 import com.google.common.base.Optional;
 import com.google.common.base.Splitter;
+import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Sets;
 import java.math.BigDecimal;
 import java.math.BigInteger;
@@ -19,7 +20,9 @@ import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Objects;
 import java.util.Set;
+import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 import java.util.regex.PatternSyntaxException;
 import org.antlr.v4.runtime.ParserRuleContext;
@@ -140,12 +143,224 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 public final class ParserListenerUtils {
+    private static final int UNICODE_SCRIPT_FIX_COUNTER = 30;
     private static final Logger LOG = LoggerFactory.getLogger(ParserListenerUtils.class);
     private static final Splitter KEYDEF_SPLITTER = Splitter.on(' ').omitEmptyStrings();
     private static final Splitter PIPE_SPLITTER = Splitter.on('|').trimResults();
     private static final Splitter DOT_DOT_SPLITTER = Splitter.on("..").trimResults();
     private static final CharMatcher DOUBLE_QUOTE_MATCHER = CharMatcher.is('"');
     private static final CharMatcher SINGLE_QUOTE_MATCHER = CharMatcher.is('\'');
+    private static final Pattern BETWEEN_CURLY_BRACES_PATTERN = Pattern.compile("\\{(.+?)\\}");
+    private static final Set<String> JAVA_UNICODE_BLOCKS = ImmutableSet.<String>builder()
+            .add("AegeanNumbers")
+            .add("AlchemicalSymbols")
+            .add("AlphabeticPresentationForms")
+            .add("AncientGreekMusicalNotation")
+            .add("AncientGreekNumbers")
+            .add("AncientSymbols")
+            .add("Arabic")
+            .add("ArabicPresentationForms-A")
+            .add("ArabicPresentationForms-B")
+            .add("ArabicSupplement")
+            .add("Armenian")
+            .add("Arrows")
+            .add("Avestan")
+            .add("Balinese")
+            .add("Bamum")
+            .add("BamumSupplement")
+            .add("BasicLatin")
+            .add("Batak")
+            .add("Bengali")
+            .add("BlockElements")
+            .add("Bopomofo")
+            .add("BopomofoExtended")
+            .add("BoxDrawing")
+            .add("Brahmi")
+            .add("BraillePatterns")
+            .add("Buginese")
+            .add("Buhid")
+            .add("ByzantineMusicalSymbols")
+            .add("Carian")
+            .add("Cham")
+            .add("Cherokee")
+            .add("CJKCompatibility")
+            .add("CJKCompatibilityForms")
+            .add("CJKCompatibilityIdeographs")
+            .add("CJKCompatibilityIdeographsSupplement")
+            .add("CJKRadicalsSupplement")
+            .add("CJKStrokes")
+            .add("CJKSymbolsandPunctuation")
+            .add("CJKUnifiedIdeographs")
+            .add("CJKUnifiedIdeographsExtensionA")
+            .add("CJKUnifiedIdeographsExtensionB")
+            .add("CJKUnifiedIdeographsExtensionC")
+            .add("CJKUnifiedIdeographsExtensionD")
+            .add("CombiningDiacriticalMarks")
+            .add("CombiningDiacriticalMarksSupplement")
+            .add("CombiningHalfMarks")
+            .add("CombiningDiacriticalMarksforSymbols")
+            .add("CommonIndicNumberForms")
+            .add("ControlPictures")
+            .add("Coptic")
+            .add("CountingRodNumerals")
+            .add("Cuneiform")
+            .add("CuneiformNumbersandPunctuation")
+            .add("CurrencySymbols")
+            .add("CypriotSyllabary")
+            .add("Cyrillic")
+            .add("CyrillicExtended-A")
+            .add("CyrillicExtended-B")
+            .add("CyrillicSupplementary")
+            .add("Deseret")
+            .add("Devanagari")
+            .add("DevanagariExtended")
+            .add("Dingbats")
+            .add("DominoTiles")
+            .add("EgyptianHieroglyphs")
+            .add("Emoticons")
+            .add("EnclosedAlphanumericSupplement")
+            .add("EnclosedAlphanumerics")
+            .add("EnclosedCJKLettersandMonths")
+            .add("EnclosedIdeographicSupplement")
+            .add("Ethiopic")
+            .add("EthiopicExtended")
+            .add("EthiopicExtended-A")
+            .add("EthiopicSupplement")
+            .add("GeneralPunctuation")
+            .add("GeometricShapes")
+            .add("Georgian")
+            .add("GeorgianSupplement")
+            .add("Glagolitic")
+            .add("Gothic")
+            .add("GreekandCoptic")
+            .add("GreekExtended")
+            .add("Gujarati")
+            .add("Gurmukhi")
+            .add("HalfwidthandFullwidthForms")
+            .add("HangulCompatibilityJamo")
+            .add("HangulJamo")
+            .add("HangulJamoExtended-A")
+            .add("HangulJamoExtended-B")
+            .add("HangulSyllables")
+            .add("Hanunoo")
+            .add("Hebrew")
+            .add("HighPrivateUseSurrogates")
+            .add("HighSurrogates")
+            .add("Hiragana")
+            .add("IdeographicDescriptionCharacters")
+            .add("ImperialAramaic")
+            .add("InscriptionalPahlavi")
+            .add("InscriptionalParthian")
+            .add("IPAExtensions")
+            .add("Javanese")
+            .add("Kaithi")
+            .add("KanaSupplement")
+            .add("Kanbun")
+            .add("Kangxi Radicals")
+            .add("Kannada")
+            .add("Katakana")
+            .add("KatakanaPhoneticExtensions")
+            .add("KayahLi")
+            .add("Kharoshthi")
+            .add("Khmer")
+            .add("KhmerSymbols")
+            .add("Lao")
+            .add("Latin-1Supplement")
+            .add("LatinExtended-A")
+            .add("LatinExtendedAdditional")
+            .add("LatinExtended-B")
+            .add("LatinExtended-C")
+            .add("LatinExtended-D")
+            .add("Lepcha")
+            .add("LetterlikeSymbols")
+            .add("Limbu")
+            .add("LinearBIdeograms")
+            .add("LinearBSyllabary")
+            .add("Lisu")
+            .add("LowSurrogates")
+            .add("Lycian")
+            .add("Lydian")
+            .add("MahjongTiles")
+            .add("Malayalam")
+            .add("Mandaic")
+            .add("MathematicalAlphanumericSymbols")
+            .add("MathematicalOperators")
+            .add("MeeteiMayek")
+            .add("MiscellaneousMathematicalSymbols-A")
+            .add("MiscellaneousMathematicalSymbols-B")
+            .add("MiscellaneousSymbols")
+            .add("MiscellaneousSymbolsandArrows")
+            .add("MiscellaneousSymbolsAndPictographs")
+            .add("MiscellaneousTechnical")
+            .add("ModifierToneLetters")
+            .add("Mongolian")
+            .add("MusicalSymbols")
+            .add("Myanmar")
+            .add("MyanmarExtended-A")
+            .add("NewTaiLue")
+            .add("NKo")
+            .add("NumberForms")
+            .add("Ogham")
+            .add("OlChiki")
+            .add("OldItalic")
+            .add("OldPersian")
+            .add("OldSouthArabian")
+            .add("OldTurkic")
+            .add("OpticalCharacterRecognition")
+            .add("Oriya")
+            .add("Osmanya")
+            .add("Phags-pa")
+            .add("PhaistosDisc")
+            .add("Phoenician")
+            .add("PhoneticExtensions")
+            .add("PhoneticExtensionsSupplement")
+            .add("PlayingCards")
+            .add("PrivateUseArea")
+            .add("Rejang")
+            .add("RumiNumeralSymbols")
+            .add("Runic")
+            .add("Samaritan")
+            .add("Saurashtra")
+            .add("Shavian")
+            .add("Sinhala")
+            .add("SmallFormVariants")
+            .add("SpacingModifierLetters")
+            .add("Specials")
+            .add("Sundanese")
+            .add("SuperscriptsandSubscripts")
+            .add("SupplementalArrows-A")
+            .add("SupplementalArrows-B")
+            .add("SupplementalMathematicalOperators")
+            .add("SupplementalPunctuation")
+            .add("SupplementaryPrivateUseArea-A")
+            .add("SupplementaryPrivateUseArea-B")
+            .add("SylotiNagri")
+            .add("Syriac")
+            .add("Tagalog")
+            .add("Tagbanwa")
+            .add("Tags")
+            .add("TaiLe")
+            .add("TaiTham")
+            .add("TaiViet")
+            .add("TaiXuanJingSymbols")
+            .add("Tamil")
+            .add("Telugu")
+            .add("Thaana")
+            .add("Thai")
+            .add("Tibetan")
+            .add("Tifinagh")
+            .add("TransportAndMapSymbols")
+            .add("Ugaritic")
+            .add("UnifiedCanadianAboriginalSyllabics")
+            .add("UnifiedCanadianAboriginalSyllabicsExtended")
+            .add("Vai")
+            .add("VariationSelectors")
+            .add("VariationSelectorsSupplement")
+            .add("VedicExtensions")
+            .add("VerticalForms")
+            .add("YiRadicals")
+            .add("YiSyllables")
+            .add("YijingHexagramSymbols").build();
 
     private ParserListenerUtils() {
     }
@@ -221,7 +436,9 @@ public final class ParserListenerUtils {
      *            context to parse
      * @param builder
      *            builder to fill in with parsed statements
+     * @deprecated Pre-Beryllium implementation, scheduled for removal.
      */
+    @Deprecated
     public static void parseSchemaNodeArgs(final ParseTree ctx, final SchemaNodeBuilder builder) {
         for (int i = 0; i < ctx.getChildCount(); i++) {
             final ParseTree child = ctx.getChild(i);
@@ -468,11 +685,11 @@ public final class ParserListenerUtils {
         public int hashCode() {
             final int prime = 31;
             int result = 1;
-            result = prime * result + ((qname == null) ? 0 : qname.hashCode());
-            result = prime * result + ((path == null) ? 0 : path.hashCode());
-            result = prime * result + ((unknownNodes == null) ? 0 : unknownNodes.hashCode());
-            result = prime * result + ((name == null) ? 0 : name.hashCode());
-            result = prime * result + ((value == null) ? 0 : value.hashCode());
+            result = prime * result + Objects.hashCode(qname);
+            result = prime * result + Objects.hashCode(path);
+            result = prime * result + Objects.hashCode(unknownNodes);
+            result = prime * result + Objects.hashCode(name);
+            result = prime * result + Objects.hashCode(value);
             return result;
         }
 
@@ -760,14 +977,47 @@ public final class ParserListenerUtils {
             }
         }
         final String rawPattern = parsePatternString(ctx);
-        final String pattern = wrapPattern(rawPattern);
+        final String fixedRawPattern = fixUnicodeScriptPattern(rawPattern);
+        final String pattern = wrapPattern(fixedRawPattern);
         if (isValidPattern(pattern, ctx, moduleName)) {
             return BaseConstraints.newPatternConstraint(pattern, description, reference);
         }
         return null;
     }
 
-    private static String wrapPattern(String rawPattern) {
+    private static String fixUnicodeScriptPattern(String rawPattern) {
+        for (int i = 0; i < UNICODE_SCRIPT_FIX_COUNTER; i++) {
+            try {
+                Pattern.compile(rawPattern);
+                return rawPattern;
+            } catch(PatternSyntaxException ex) {
+                LOG.debug("Invalid regex pattern syntax in: {}", rawPattern, ex);
+                if (ex.getMessage().contains("Unknown character script name")) {
+                    rawPattern = fixUnknownScripts(ex.getMessage(), rawPattern);
+                } else {
+                    return rawPattern;
+                }
+            }
+        }
+
+        LOG.warn("Regex pattern could not be fixed: {}", rawPattern);
+        return rawPattern;
+    }
+
+    private static String fixUnknownScripts(final String exMessage, final String rawPattern) {
+        StringBuilder result = new StringBuilder(rawPattern);
+        Matcher matcher = BETWEEN_CURLY_BRACES_PATTERN.matcher(exMessage);
+        if (matcher.find()) {
+            String capturedGroup = matcher.group(1);
+            if (JAVA_UNICODE_BLOCKS.contains(capturedGroup)) {
+                int idx = rawPattern.indexOf("Is" + capturedGroup);
+                result = result.replace(idx, idx + 2, "In");
+            }
+        }
+        return result.toString();
+    }
+
+    private static String wrapPattern(final String rawPattern) {
         final StringBuilder wrapPatternBuilder = new StringBuilder(rawPattern.length() + 2);
         wrapPatternBuilder.append('^');
         wrapPatternBuilder.append(rawPattern);
@@ -986,7 +1236,9 @@ public final class ParserListenerUtils {
      * @param line
      *            line in current module
      * @return config statement parsed from given context
+     * @deprecated Pre-Beryllium implementation, scheduled for removal.
      */
+    @Deprecated
     public static boolean getConfig(final ParseTree ctx, final Builder node, final String moduleName, final int line) {
         boolean result;
         // parse configuration statement
@@ -1017,6 +1269,10 @@ public final class ParserListenerUtils {
         return result;
     }
 
+    /**
+     * @deprecated Pre-Beryllium implementation, scheduled for removal.
+     */
+    @Deprecated
     private static boolean getParentConfig(final Builder node) {
         Builder parent = node.getParent();
         boolean config;
@@ -1080,9 +1336,12 @@ public final class ParserListenerUtils {
      *            current module qname
      * @param actualPath
      *            actual path in model
+     *
+     * @deprecated Pre-Beryllium implementation, scheduled for removal.
      */
-    public static void parseUnknownTypeWithBody(Type_body_stmtsContext typeBody, TypeAwareBuilder parent,
-            QName prefixedQName, ModuleBuilder moduleBuilder, QName moduleQName, SchemaPath actualPath) {
+    @Deprecated
+    public static void parseUnknownTypeWithBody(final Type_body_stmtsContext typeBody, final TypeAwareBuilder parent,
+            final QName prefixedQName, final ModuleBuilder moduleBuilder, final QName moduleQName, final SchemaPath actualPath) {
         final int line = typeBody.getStart().getLine();
 
         List<RangeConstraint> rangeStatements = getRangeConstraints(typeBody, moduleBuilder.getName());
@@ -1127,7 +1386,10 @@ public final class ParserListenerUtils {
      * @param parent
      *            parent builder
      * @return TypeDefinition object based on parsed values.
+     *
+     * @deprecated Pre-Beryllium implementation, scheduled for removal.
      */
+    @Deprecated
     public static TypeDefinition<?> parseTypeWithBody(final String typeName, final Type_body_stmtsContext typeBody,
             final SchemaPath actualPath, final QName moduleQName, final Builder parent) {
 
@@ -1392,7 +1654,10 @@ public final class ParserListenerUtils {
      *            context to parse
      * @param constraints
      *            ConstraintsBuilder to fill
+     *
+     * @deprecated Pre-Beryllium implementation, scheduled for removal.
      */
+    @Deprecated
     public static void parseConstraints(final ParseTree ctx, final ConstraintsBuilder constraints) {
         for (int i = 0; i < ctx.getChildCount(); ++i) {
             final ParseTree childNode = ctx.getChild(i);
@@ -1527,7 +1792,10 @@ public final class ParserListenerUtils {
      * @param moduleName
      *            name of current module
      * @return RefineHolder object representing this refine statement
+     *
+     * @deprecated Pre-Beryllium implementation, scheduled for removal.
      */
+    @Deprecated
     public static RefineHolderImpl parseRefine(final Refine_stmtContext refineCtx, final String moduleName) {
         final String refineTarget = stringFromNode(refineCtx);
         final RefineHolderImpl refine = new RefineHolderImpl(moduleName, refineCtx.getStart().getLine(), refineTarget);
@@ -1557,6 +1825,10 @@ public final class ParserListenerUtils {
         return refine;
     }
 
+    /**
+     * @deprecated Pre-Beryllium implementation, scheduled for removal.
+     */
+    @Deprecated
     private static void parseRefineDefault(final RefineHolderImpl refine, final ParseTree refineStmt) {
         for (int i = 0; i < refineStmt.getChildCount(); i++) {
             ParseTree refineArg = refineStmt.getChild(i);
@@ -1573,6 +1845,10 @@ public final class ParserListenerUtils {
         }
     }
 
+    /**
+     * @deprecated Pre-Beryllium implementation, scheduled for removal.
+     */
+    @Deprecated
     private static RefineBuilder parseRefine(final RefineHolderImpl refine, final Refine_leaf_stmtsContext refineStmt) {
         for (int i = 0; i < refineStmt.getChildCount(); i++) {
             ParseTree refineArg = refineStmt.getChild(i);
@@ -1596,6 +1872,10 @@ public final class ParserListenerUtils {
         return refine;
     }
 
+    /**
+     * @deprecated Pre-Beryllium implementation, scheduled for removal.
+     */
+    @Deprecated
     private static RefineBuilder parseRefine(final RefineBuilder refine, final Refine_container_stmtsContext refineStmt) {
         for (int i = 0; i < refineStmt.getChildCount(); i++) {
             ParseTree refineArg = refineStmt.getChild(i);
@@ -1609,6 +1889,10 @@ public final class ParserListenerUtils {
         return refine;
     }
 
+    /**
+     * @deprecated Pre-Beryllium implementation, scheduled for removal.
+     */
+    @Deprecated
     private static RefineBuilder parseRefine(final RefineHolderImpl refine, final Refine_list_stmtsContext refineStmt) {
         for (int i = 0; i < refineStmt.getChildCount(); i++) {
             ParseTree refineArg = refineStmt.getChild(i);
@@ -1626,6 +1910,10 @@ public final class ParserListenerUtils {
         return refine;
     }
 
+    /**
+     * @deprecated Pre-Beryllium implementation, scheduled for removal.
+     */
+    @Deprecated
     private static RefineBuilder parseRefine(final RefineHolderImpl refine, final Refine_leaf_list_stmtsContext refineStmt) {
         for (int i = 0; i < refineStmt.getChildCount(); i++) {
             ParseTree refineArg = refineStmt.getChild(i);
@@ -1643,6 +1931,10 @@ public final class ParserListenerUtils {
         return refine;
     }
 
+    /**
+     * @deprecated Pre-Beryllium implementation, scheduled for removal.
+     */
+    @Deprecated
     private static RefineBuilder parseRefine(final RefineHolderImpl refine, final Refine_choice_stmtsContext refineStmt) {
         for (int i = 0; i < refineStmt.getChildCount(); i++) {
             ParseTree refineArg = refineStmt.getChild(i);
@@ -1662,6 +1954,10 @@ public final class ParserListenerUtils {
         return refine;
     }
 
+    /**
+     * @deprecated Pre-Beryllium implementation, scheduled for removal.
+     */
+    @Deprecated
     private static RefineBuilder parseRefine(final RefineBuilder refine, final Refine_anyxml_stmtsContext refineStmt) {
         for (int i = 0; i < refineStmt.getChildCount(); i++) {
             ParseTree refineArg = refineStmt.getChild(i);