Bug 4662: Introduce a SemanticVersion concept - SchemaContextFactory
[yangtools.git] / yang / yang-parser-impl / src / main / java / org / opendaylight / yangtools / yang / parser / stmt / rfc6020 / Utils.java
index 71ae3700a38b3e075a6bbb384b8adffe934de40c..c797294da592fc9268aa6e1ad0b9867899c9c7e0 100644 (file)
@@ -8,17 +8,19 @@
 package org.opendaylight.yangtools.yang.parser.stmt.rfc6020;
 
 import static org.opendaylight.yangtools.yang.parser.spi.meta.StmtContextUtils.firstAttributeOf;
+
 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.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableMap.Builder;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Iterables;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.Date;
 import java.util.HashSet;
 import java.util.List;
@@ -40,7 +42,9 @@ import org.opendaylight.yangtools.yang.model.api.Deviation;
 import org.opendaylight.yangtools.yang.model.api.Deviation.Deviate;
 import org.opendaylight.yangtools.yang.model.api.ModuleIdentifier;
 import org.opendaylight.yangtools.yang.model.api.RevisionAwareXPath;
+import org.opendaylight.yangtools.yang.model.api.Rfc6020Mapping;
 import org.opendaylight.yangtools.yang.model.api.Status;
+import org.opendaylight.yangtools.yang.model.api.meta.StatementDefinition;
 import org.opendaylight.yangtools.yang.model.api.stmt.BelongsToStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.ModuleStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.RevisionStatement;
@@ -74,6 +78,7 @@ public final class Utils {
     private static final CharMatcher QUESTION_MARK_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 Splitter COLON_SPLITTER = Splitter.on(":").omitEmptyStrings().trimResults();
     private static final Pattern PATH_ABS = Pattern.compile("/[^/].*");
     private static final Pattern BETWEEN_CURLY_BRACES_PATTERN = Pattern.compile("\\{(.+?)\\}");
     private static final Set<String> JAVA_UNICODE_BLOCKS = ImmutableSet.<String>builder()
@@ -337,6 +342,19 @@ public final class Utils {
         return keyNodes;
     }
 
+    static Collection<SchemaNodeIdentifier.Relative> parseUniqueConstraintArgument(final StmtContext<?, ?, ?> ctx,
+            final String argumentValue) {
+        final Set<SchemaNodeIdentifier.Relative> uniqueConstraintNodes = new HashSet<>();
+        for (String uniqueArgToken : SPACE_SPLITTER.split(argumentValue)) {
+            final SchemaNodeIdentifier nodeIdentifier = Utils.nodeIdentifierFromPath(ctx, uniqueArgToken);
+            SourceException.throwIf(nodeIdentifier.isAbsolute(), ctx.getStatementSourceReference(),
+                    "Unique statement argument '%s' contains schema node identifier '%s' "
+                            + "which is not in the descendant node identifier form.", argumentValue, uniqueArgToken);
+            uniqueConstraintNodes.add((SchemaNodeIdentifier.Relative) nodeIdentifier);
+        }
+        return ImmutableSet.copyOf(uniqueConstraintNodes);
+    }
+
     private static String trimSingleLastSlashFromXPath(final String path) {
         return path.endsWith("/") ? path.substring(0, path.length() - 1) : path;
     }
@@ -368,6 +386,14 @@ public final class Utils {
         return identifier;
     }
 
+    public static String trimPrefix(final String identifier) {
+        List<String> namesParts = COLON_SPLITTER.splitToList(identifier);
+        if (namesParts.size() == 2) {
+            return namesParts.get(1);
+        }
+        return identifier;
+    }
+
     /**
      *
      * Based on identifier read from source and collections of relevant prefixes and statement definitions mappings
@@ -380,8 +406,8 @@ public final class Utils {
      * @return valid QName for declared statement to be written
      *
      */
-    public static QName getValidStatementDefinition(final PrefixToModule prefixes, final QNameToStatementDefinition
-            stmtDef, final QName identifier) {
+    public static QName getValidStatementDefinition(final PrefixToModule prefixes,
+            final QNameToStatementDefinition stmtDef, final QName identifier) {
         if (stmtDef.get(identifier) != null) {
             return stmtDef.get(identifier).getStatementName();
         } else {
@@ -391,9 +417,23 @@ public final class Utils {
             if (namesParts.length == 2) {
                 String prefix = namesParts[0];
                 String localName = namesParts[1];
-                if (prefixes != null && prefixes.get(prefix) != null
-                        && stmtDef.get(QName.create(prefixes.get(prefix), localName)) != null) {
-                    return QName.create(prefixes.get(prefix), localName);
+
+                if (prefixes == null) {
+                    return null;
+                }
+
+                QNameModule qNameModule = prefixes.get(prefix);
+                if (qNameModule == null) {
+                    return null;
+                }
+
+                if (prefixes.isPreLinkageMap()) {
+                    StatementDefinition foundStmtDef = stmtDef.getByNamespaceAndLocalName(qNameModule.getNamespace(),
+                            localName);
+                    return foundStmtDef != null ? foundStmtDef.getStatementName() : null;
+                } else {
+                    QName qName = QName.create(qNameModule, localName);
+                    return stmtDef.get(qName) != null ? qName : null;
                 }
             }
         }
@@ -420,7 +460,7 @@ public final class Utils {
         StringBuilder sb = new StringBuilder();
         List<TerminalNode> strings = context.STRING();
         if (strings.isEmpty()) {
-            strings = Arrays.asList(context.IDENTIFIER());
+            strings = Collections.singletonList(context.IDENTIFIER());
         }
         for (TerminalNode stringNode : strings) {
             final String str = stringNode.getText();
@@ -624,4 +664,27 @@ public final class Utils {
         }
         return result.toString();
     }
+
+    public static boolean belongsToTheSameModule(QName targetStmtQName, QName sourceStmtQName) {
+        if (targetStmtQName.getModule().equals(sourceStmtQName.getModule())) {
+            return true;
+        }
+        return false;
+    }
+
+    public static boolean isPresenceContainer(StatementContextBase<?, ?, ?> targetCtx) {
+        if (!targetCtx.getPublicDefinition().equals(Rfc6020Mapping.CONTAINER)) {
+            return false;
+        }
+
+        final List<StatementContextBase<?, ?, ?>> targetSubStatements = new ImmutableList.Builder<StatementContextBase<?, ?, ?>>()
+                .addAll(targetCtx.declaredSubstatements()).addAll(targetCtx.effectiveSubstatements()).build();
+        for (final StatementContextBase<?, ?, ?> subStatement : targetSubStatements) {
+            if (subStatement.getPublicDefinition().equals(Rfc6020Mapping.PRESENCE)) {
+                return true;
+            }
+        }
+
+        return false;
+    }
 }