BUG-7052: Move qnameFromArgument to StmtContextUtils
[yangtools.git] / yang / yang-parser-impl / src / main / java / org / opendaylight / yangtools / yang / parser / spi / meta / StmtContextUtils.java
index 2877fc374f705636c7035a48cbb9e4cb98ac7b93..9e7aa45ce8c87b75f31dccea295c61539f6725e5 100644 (file)
@@ -9,34 +9,46 @@ package org.opendaylight.yangtools.yang.parser.spi.meta;
 
 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.ImmutableSet;
 import com.google.common.collect.ImmutableSet.Builder;
 import com.google.common.collect.Iterables;
 import java.util.Collection;
+import java.util.Date;
+import java.util.Optional;
 import java.util.Set;
 import java.util.function.Predicate;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.common.QNameModule;
+import org.opendaylight.yangtools.yang.common.SimpleDateFormatUtil;
 import org.opendaylight.yangtools.yang.common.YangVersion;
+import org.opendaylight.yangtools.yang.model.api.ModuleIdentifier;
 import org.opendaylight.yangtools.yang.model.api.YangStmtMapping;
 import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
 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.KeyStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.LeafStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.MandatoryStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.MinElementsStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.ModuleStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.PresenceStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.RevisionStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier;
+import org.opendaylight.yangtools.yang.model.api.stmt.SubmoduleStatement;
+import org.opendaylight.yangtools.yang.model.repo.api.RevisionSourceIdentifier;
+import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier;
+import org.opendaylight.yangtools.yang.parser.spi.source.BelongsToPrefixToModuleName;
+import org.opendaylight.yangtools.yang.parser.spi.source.ImpPrefixToModuleIdentifier;
+import org.opendaylight.yangtools.yang.parser.spi.source.ModuleCtxToModuleQName;
+import org.opendaylight.yangtools.yang.parser.spi.source.ModuleIdentifierToModuleQName;
+import org.opendaylight.yangtools.yang.parser.spi.source.ModuleNameToModuleQName;
 import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
 import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.UnknownStatementImpl;
 import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.YangDataStatementImpl;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 public final class StmtContextUtils {
-    private static final Logger LOG = LoggerFactory.getLogger(StmtContextUtils.class);
-
     public static final Splitter LIST_KEY_SPLITTER = Splitter.on(' ').omitEmptyStrings().trimResults();
 
     private StmtContextUtils() {
@@ -474,4 +486,125 @@ public final class StmtContextUtils {
                     statementDef.getStatementName(), leafStmtCtx.getStatementArgument());
         });
     }
+
+    public static QName qnameFromArgument(StmtContext<?, ?, ?> ctx, final String value) {
+        if (Strings.isNullOrEmpty(value)) {
+            return ctx.getPublicDefinition().getStatementName();
+        }
+
+        String prefix;
+        QNameModule qNameModule = null;
+        String localName = null;
+
+        final String[] namesParts = value.split(":");
+        switch (namesParts.length) {
+        case 1:
+            localName = namesParts[0];
+            qNameModule = StmtContextUtils.getRootModuleQName(ctx);
+            break;
+        default:
+            prefix = namesParts[0];
+            localName = namesParts[1];
+            qNameModule = StmtContextUtils.getModuleQNameByPrefix(ctx, prefix);
+            // in case of unknown statement argument, we're not going to parse it
+            if (qNameModule == null
+                    && ctx.getPublicDefinition().getDeclaredRepresentationClass()
+                    .isAssignableFrom(UnknownStatementImpl.class)) {
+                localName = value;
+                qNameModule = StmtContextUtils.getRootModuleQName(ctx);
+            }
+            if (qNameModule == null
+                    && ctx.getCopyHistory().getLastOperation() == CopyType.ADDED_BY_AUGMENTATION) {
+                ctx = ctx.getOriginalCtx();
+                qNameModule = StmtContextUtils.getModuleQNameByPrefix(ctx, prefix);
+            }
+            break;
+        }
+
+        qNameModule = InferenceException.throwIfNull(qNameModule, ctx.getStatementSourceReference(),
+            "Cannot resolve QNameModule for '%s'", value);
+
+        final QNameModule resultQNameModule;
+        if (qNameModule.getRevision() == null) {
+            resultQNameModule = QNameModule.create(qNameModule.getNamespace(), SimpleDateFormatUtil.DEFAULT_DATE_REV)
+                .intern();
+        } else {
+            resultQNameModule = qNameModule;
+        }
+
+        return ctx.getFromNamespace(QNameCacheNamespace.class, QName.create(resultQNameModule, localName));
+    }
+
+    public static QNameModule getRootModuleQName(final StmtContext<?, ?, ?> ctx) {
+        if (ctx == null) {
+            return null;
+        }
+
+        final StmtContext<?, ?, ?> rootCtx = ctx.getRoot();
+        final QNameModule qNameModule;
+
+        if (producesDeclared(rootCtx, ModuleStatement.class)) {
+            qNameModule = rootCtx.getFromNamespace(ModuleCtxToModuleQName.class, rootCtx);
+        } else if (producesDeclared(rootCtx, SubmoduleStatement.class)) {
+            final String belongsToModuleName = firstAttributeOf(rootCtx.declaredSubstatements(),
+                BelongsToStatement.class);
+            qNameModule = rootCtx.getFromNamespace(ModuleNameToModuleQName.class, belongsToModuleName);
+        } else {
+            qNameModule = null;
+        }
+
+        Preconditions.checkArgument(qNameModule != null, "Failed to look up root QNameModule for %s", ctx);
+        if (qNameModule.getRevision() != null) {
+            return qNameModule;
+        }
+
+        return QNameModule.create(qNameModule.getNamespace(), SimpleDateFormatUtil.DEFAULT_DATE_REV).intern();
+    }
+
+    public static QNameModule getModuleQNameByPrefix(final StmtContext<?, ?, ?> ctx, final String prefix) {
+        final ModuleIdentifier modId = ctx.getRoot().getFromNamespace(ImpPrefixToModuleIdentifier.class, prefix);
+        final QNameModule qNameModule = ctx.getFromNamespace(ModuleIdentifierToModuleQName.class, modId);
+
+        if (qNameModule == null && producesDeclared(ctx.getRoot(), SubmoduleStatement.class)) {
+            final String moduleName = ctx.getRoot().getFromNamespace(BelongsToPrefixToModuleName.class, prefix);
+            return ctx.getFromNamespace(ModuleNameToModuleQName.class, moduleName);
+        }
+        return qNameModule;
+    }
+
+    public static SourceIdentifier createSourceIdentifier(final StmtContext<?, ?, ?> root) {
+        final QNameModule qNameModule = root.getFromNamespace(ModuleCtxToModuleQName.class, root);
+        if (qNameModule != null) {
+            // creates SourceIdentifier for a module
+            return RevisionSourceIdentifier.create((String) root.getStatementArgument(),
+                qNameModule.getFormattedRevision());
+        }
+
+        // creates SourceIdentifier for a submodule
+        final Date revision = Optional.ofNullable(getLatestRevision(root.declaredSubstatements()))
+                .orElse(SimpleDateFormatUtil.DEFAULT_DATE_REV);
+        final String formattedRevision = SimpleDateFormatUtil.getRevisionFormat().format(revision);
+        return RevisionSourceIdentifier.create((String) root.getStatementArgument(), formattedRevision);
+    }
+
+    public static Date getLatestRevision(final Iterable<? extends StmtContext<?, ?, ?>> subStmts) {
+        Date revision = null;
+        for (final StmtContext<?, ?, ?> subStmt : subStmts) {
+            if (subStmt.getPublicDefinition().getDeclaredRepresentationClass().isAssignableFrom(RevisionStatement
+                    .class)) {
+                if (revision == null && subStmt.getStatementArgument() != null) {
+                    revision = (Date) subStmt.getStatementArgument();
+                } else if (subStmt.getStatementArgument() != null && ((Date) subStmt.getStatementArgument()).compareTo
+                        (revision) > 0) {
+                    revision = (Date) subStmt.getStatementArgument();
+                }
+            }
+        }
+        return revision;
+    }
+
+    public static boolean isUnknownNode(final StmtContext<?, ?, ?> stmtCtx) {
+        return stmtCtx != null && stmtCtx.getPublicDefinition().getDeclaredRepresentationClass()
+                .isAssignableFrom(UnknownStatementImpl.class);
+    }
 }