Cleanup yang-parser-impl Utils 52/27152/10
authorRobert Varga <rovarga@cisco.com>
Fri, 18 Sep 2015 09:52:45 +0000 (11:52 +0200)
committerRobert Varga <rovarga@cisco.com>
Thu, 1 Oct 2015 06:17:28 +0000 (08:17 +0200)
Pre-compiled paterns, reused splitters and similar.

Change-Id: Ia8b6aebb0d3d1922018078b3e33ebba7e9740769
Signed-off-by: Robert Varga <rovarga@cisco.com>
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/Utils.java

index cbeae98ac6ae4762c4d54260ae8b8a04b6f0fa2f..d688ec50ab06ff6156c4fd2db7fe09ebb0a4197c 100644 (file)
@@ -11,6 +11,7 @@ import static org.opendaylight.yangtools.yang.parser.spi.meta.StmtContextUtils.f
 import com.google.common.base.CharMatcher;
 import com.google.common.base.Preconditions;
 import com.google.common.base.Splitter;
+import com.google.common.base.Strings;
 import com.google.common.collect.Iterables;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -22,7 +23,9 @@ import java.util.LinkedList;
 import java.util.List;
 import java.util.Objects;
 import java.util.Set;
+import java.util.regex.Pattern;
 import javax.annotation.Nullable;
+import javax.annotation.concurrent.GuardedBy;
 import javax.xml.xpath.XPath;
 import javax.xml.xpath.XPathExpressionException;
 import javax.xml.xpath.XPathFactory;
@@ -67,23 +70,25 @@ public final class Utils {
     private static final Logger LOG = LoggerFactory.getLogger(Utils.class);
     private static final CharMatcher DOUBLE_QUOTE_MATCHER = CharMatcher.is('"');
     private static final CharMatcher SINGLE_QUOTE_MATCHER = CharMatcher.is('\'');
+    private static final Splitter SLASH_SPLITTER = Splitter.on('/').omitEmptyStrings().trimResults();
+    private static final Splitter SPACE_SPLITTER = Splitter.on(' ').omitEmptyStrings().trimResults();
+    private static final Pattern PATH_ABS = Pattern.compile("/[^/].*");
 
-    private static final char SEPARATOR_NODENAME = '/';
-
-    private static final String REGEX_PATH_ABS = "/[^/].*";
-
-    public static final char SEPARATOR = ' ';
+    // XPathFactory is documented as non-threadsafe
+    @GuardedBy("Utils.class")
+    private static final XPathFactory XPATH_FACTORY = XPathFactory.newInstance();
 
     private Utils() {
+        throw new UnsupportedOperationException();
     }
 
     public static Collection<SchemaNodeIdentifier.Relative> transformKeysStringToKeyNodes(final StmtContext<?, ?, ?> ctx,
             final String value) {
-        Splitter keySplitter = Splitter.on(SEPARATOR).omitEmptyStrings().trimResults();
-        List<String> keyTokens = keySplitter.splitToList(value);
+        List<String> keyTokens = SPACE_SPLITTER.splitToList(value);
 
         // to detect if key contains duplicates
         if ((new HashSet<>(keyTokens)).size() < keyTokens.size()) {
+            // FIXME: report all duplicate keys
             throw new IllegalArgumentException();
         }
 
@@ -100,20 +105,20 @@ public final class Utils {
     }
 
     public static List<String> splitPathToNodeNames(final String path) {
-
-        Splitter keySplitter = Splitter.on(SEPARATOR_NODENAME).omitEmptyStrings().trimResults();
-        return keySplitter.splitToList(path);
+        return SLASH_SPLITTER.splitToList(path);
     }
 
     public static void validateXPath(final StmtContext<?, ?, ?> ctx, final String path) {
-
-        final XPath xPath = XPathFactory.newInstance().newXPath();
+        final XPath xPath;
+        synchronized (Utils.class) {
+            xPath = XPATH_FACTORY.newXPath();
+        }
 
         try {
             xPath.compile(path);
         } catch (XPathExpressionException e) {
             throw new IllegalArgumentException(String.format("Argument %s is not valid XPath string at %s", path, ctx
-                    .getStatementSourceReference().toString()), e);
+                    .getStatementSourceReference()), e);
         }
     }
 
@@ -125,7 +130,7 @@ public final class Utils {
 
         validateXPath(ctx, trimSingleLastSlashFromXPath(path));
 
-        return path.matches(REGEX_PATH_ABS);
+        return PATH_ABS.matcher(path).matches();
     }
 
     public static QName trimPrefix(final QName identifier) {
@@ -179,7 +184,7 @@ public final class Utils {
         validateXPath(ctx, trimmedPath);
 
         List<String> nodeNames = splitPathToNodeNames(trimmedPath);
-        List<QName> qNames = new ArrayList<>();
+        List<QName> qNames = new ArrayList<>(nodeNames.size());
 
         for (String nodeName : nodeNames) {
             try {
@@ -217,8 +222,7 @@ public final class Utils {
     }
 
     public static QName qNameFromArgument(StmtContext<?, ?, ?> ctx, final String value) {
-
-        if (value == null || value.equals("")) {
+        if (Strings.isNullOrEmpty(value)) {
             return ctx.getPublicDefinition().getStatementName();
         }
 
@@ -251,10 +255,8 @@ public final class Utils {
             break;
         }
 
-        if (qNameModule == null) {
-            throw new IllegalArgumentException("Error in module '" + ctx.getRoot().rawStatementArgument()
-                    + "': can not resolve QNameModule for '" + value + "'.");
-        }
+        Preconditions.checkArgument(qNameModule != null, "Error in module '%s': can not resolve QNameModule for '%s'.",
+                ctx.getRoot().rawStatementArgument(), value);
 
         QNameModule resultQNameModule = qNameModule.getRevision() == null ? QNameModule.create(
                 qNameModule.getNamespace(), SimpleDateFormatUtil.DEFAULT_DATE_REV) : qNameModule;