X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=yang%2Fyang-parser-impl%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fyangtools%2Fyang%2Fparser%2Fspi%2Fmeta%2FStmtContextUtils.java;h=984c9e3eaba285ff026946486321eeba45d20ec4;hb=16db760aab4b98e1980877bc6adb971b413af198;hp=da704e5df417057aae3d038f29ae419e5fe7594f;hpb=d2d8522c64bede5324547689345e4c0188b5bb87;p=yangtools.git diff --git a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/spi/meta/StmtContextUtils.java b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/spi/meta/StmtContextUtils.java index da704e5df4..984c9e3eab 100644 --- a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/spi/meta/StmtContextUtils.java +++ b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/spi/meta/StmtContextUtils.java @@ -9,32 +9,41 @@ 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.api.stmt.UnknownStatement; +import org.opendaylight.yangtools.yang.model.api.stmt.UnrecognizedStatement; +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.spi.source.SupportedFeaturesNamespace; -import org.opendaylight.yangtools.yang.parser.spi.source.SupportedFeaturesNamespace.SupportedFeatures; -import org.opendaylight.yangtools.yang.parser.stmt.reactor.RootStatementContext; -import org.opendaylight.yangtools.yang.parser.stmt.reactor.StatementContextBase; -import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.UnknownStatementImpl; -import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.YangDataStatementImpl; public final class StmtContextUtils { public static final Splitter LIST_KEY_SPLITTER = Splitter.on(' ').omitEmptyStrings().trimResults(); @@ -44,77 +53,76 @@ public final class StmtContextUtils { } @SuppressWarnings("unchecked") - public static > AT firstAttributeOf( - final Iterable> contexts, final Class
declaredType) { + public static > A firstAttributeOf( + final Iterable> contexts, final Class declaredType) { for (final StmtContext ctx : contexts) { if (producesDeclared(ctx, declaredType)) { - return (AT) ctx.getStatementArgument(); + return (A) ctx.getStatementArgument(); } } return null; } @SuppressWarnings("unchecked") - public static > AT firstAttributeOf(final StmtContext ctx, - final Class
declaredType) { - return producesDeclared(ctx, declaredType) ? (AT) ctx.getStatementArgument() : null; + public static > A firstAttributeOf(final StmtContext ctx, + final Class declaredType) { + return producesDeclared(ctx, declaredType) ? (A) ctx.getStatementArgument() : null; } - public static > AT firstSubstatementAttributeOf( - final StmtContext ctx, final Class
declaredType) { - final AT firstAttribute = firstAttributeOf(ctx.effectiveSubstatements(), declaredType); - return firstAttribute != null ? firstAttribute : firstAttributeOf(ctx.declaredSubstatements(), declaredType); + public static > A firstSubstatementAttributeOf( + final StmtContext ctx, final Class declaredType) { + return firstAttributeOf(ctx.allSubstatements(), declaredType); } @SuppressWarnings("unchecked") - public static > StmtContext findFirstDeclaredSubstatement( - final StmtContext stmtContext, final Class
declaredType) { + public static > StmtContext findFirstDeclaredSubstatement( + final StmtContext stmtContext, final Class declaredType) { for (final StmtContext subStmtContext : stmtContext.declaredSubstatements()) { if (producesDeclared(subStmtContext, declaredType)) { - return (StmtContext) subStmtContext; + return (StmtContext) subStmtContext; } } return null; } @SuppressWarnings("unchecked") - public static > Collection> findAllDeclaredSubstatements( - final StmtContext stmtContext, final Class
declaredType) { - final ImmutableList.Builder> listBuilder = ImmutableList.builder(); + public static > Collection> findAllDeclaredSubstatements( + final StmtContext stmtContext, final Class declaredType) { + final ImmutableList.Builder> listBuilder = ImmutableList.builder(); for (final StmtContext subStmtContext : stmtContext.declaredSubstatements()) { if (producesDeclared(subStmtContext, declaredType)) { - listBuilder.add((StmtContext) subStmtContext); + listBuilder.add((StmtContext) subStmtContext); } } return listBuilder.build(); } @SuppressWarnings("unchecked") - public static > Collection> findAllEffectiveSubstatements( - final StmtContext stmtContext, final Class
type) { - final ImmutableList.Builder> listBuilder = ImmutableList.builder(); + public static > Collection> findAllEffectiveSubstatements( + final StmtContext stmtContext, final Class type) { + final ImmutableList.Builder> listBuilder = ImmutableList.builder(); for (final StmtContext subStmtContext : stmtContext.effectiveSubstatements()) { if (producesDeclared(subStmtContext, type)) { - listBuilder.add((StmtContext) subStmtContext); + listBuilder.add((StmtContext) subStmtContext); } } return listBuilder.build(); } - public static > Collection> findAllSubstatements( - final StmtContext stmtContext, final Class
type) { - final ImmutableList.Builder> listBuilder = ImmutableList.builder(); + public static > Collection> findAllSubstatements( + final StmtContext stmtContext, final Class type) { + final ImmutableList.Builder> listBuilder = ImmutableList.builder(); listBuilder.addAll(findAllDeclaredSubstatements(stmtContext, type)); listBuilder.addAll(findAllEffectiveSubstatements(stmtContext, type)); return listBuilder.build(); } @SuppressWarnings("unchecked") - public static > StmtContext findFirstEffectiveSubstatement( - final StmtContext stmtContext, final Class
declaredType) { + public static > StmtContext findFirstEffectiveSubstatement( + final StmtContext stmtContext, final Class declaredType) { for (final StmtContext subStmtContext : stmtContext.effectiveSubstatements()) { if (producesDeclared(subStmtContext, declaredType)) { - return (StmtContext) subStmtContext; + return (StmtContext) subStmtContext; } } return null; @@ -128,13 +136,13 @@ public final class StmtContextUtils { * * @param stmtContext statement context to search in * @param declaredType substatement type to search for - * @param statement argument type - * @param
declared statement type + * @param statement argument type + * @param declared statement type * @return statement context that was searched for or null if was not found */ - public static > StmtContext findFirstSubstatement( - final StmtContext stmtContext, final Class
declaredType) { - final StmtContext effectiveSubstatement = findFirstEffectiveSubstatement(stmtContext, declaredType); + public static > StmtContext findFirstSubstatement( + final StmtContext stmtContext, final Class declaredType) { + final StmtContext effectiveSubstatement = findFirstEffectiveSubstatement(stmtContext, declaredType); return effectiveSubstatement != null ? effectiveSubstatement : findFirstDeclaredSubstatement(stmtContext, declaredType); } @@ -155,8 +163,8 @@ public final class StmtContextUtils { return null; } - public static
> StmtContext findFirstDeclaredSubstatementOnSublevel( - final StmtContext stmtContext, final Class
declaredType, int sublevel) { + public static > StmtContext findFirstDeclaredSubstatementOnSublevel( + final StmtContext stmtContext, final Class declaredType, int sublevel) { for (final StmtContext subStmtContext : stmtContext.declaredSubstatements()) { if (sublevel == 1 && producesDeclared(subStmtContext, declaredType)) { return subStmtContext; @@ -173,8 +181,8 @@ public final class StmtContextUtils { return null; } - public static
> StmtContext findDeepFirstDeclaredSubstatement( - final StmtContext stmtContext, final Class
declaredType) { + public static > StmtContext findDeepFirstDeclaredSubstatement( + final StmtContext stmtContext, final Class declaredType) { for (final StmtContext subStmtContext : stmtContext.declaredSubstatements()) { if (producesDeclared(subStmtContext, declaredType)) { return subStmtContext; @@ -196,9 +204,9 @@ public final class StmtContextUtils { public static boolean isInExtensionBody(final StmtContext stmtCtx) { StmtContext current = stmtCtx; - while (!current.getParentContext().isRootContext()) { + while (current.getParentContext().getParentContext() != null) { current = current.getParentContext(); - if (producesDeclared(current, UnknownStatementImpl.class)) { + if (isUnknownStatement(current)) { return true; } } @@ -207,78 +215,43 @@ public final class StmtContextUtils { } /** - * Checks if the statement context has a 'yang-data' extension node as its parent. + * Returns true if supplied statement context represents unknown statement, + * otherwise returns false. * - * @param stmtCtx statement context to be checked - * @return true if the parent node is a 'yang-data' node, otherwise false + * @param stmtCtx + * statement context to be checked + * @return true if supplied statement context represents unknown statement, + * otherwise false + * @throws NullPointerException + * if supplied statement context is null */ - public static boolean hasYangDataExtensionParent(final StmtContext stmtCtx) { - return producesDeclared(stmtCtx.getParentContext(), YangDataStatementImpl.class); - } - public static boolean isUnknownStatement(final StmtContext stmtCtx) { - return producesDeclared(stmtCtx, UnknownStatementImpl.class); - } - - public static Collection replaceModuleQNameForKey( - final StmtContext, KeyStatement, ?> keyStmtCtx, - final QNameModule newQNameModule) { - - final Builder builder = ImmutableSet.builder(); - boolean replaced = false; - for (final SchemaNodeIdentifier arg : keyStmtCtx.getStatementArgument()) { - final QName qname = arg.getLastComponent(); - if (!newQNameModule.equals(qname)) { - final QName newQname = keyStmtCtx.getFromNamespace(QNameCacheNamespace.class, - QName.create(newQNameModule, qname.getLocalName())); - builder.add(SchemaNodeIdentifier.create(false, newQname)); - replaced = true; - } else { - builder.add(arg); - } - } - - // This makes sure we reuse the collection when a grouping is - // instantiated in the same module - return replaced ? builder.build() : keyStmtCtx.getStatementArgument(); + return UnknownStatement.class + .isAssignableFrom(stmtCtx.getPublicDefinition().getDeclaredRepresentationClass()); } - public static boolean areFeaturesSupported(final StmtContext.Mutable stmtContext) { - switch (stmtContext.getSupportedByFeatures()) { - case SUPPORTED: - return true; - case NOT_SUPPORTED: - return false; - default: - break; - } - - final Set supportedFeatures = stmtContext.getFromNamespace(SupportedFeaturesNamespace.class, - SupportedFeatures.SUPPORTED_FEATURES); - /* - * If set of supported features has not been provided, all features are - * supported by default. - */ - if (supportedFeatures == null) { - stmtContext.setSupportedByFeatures(true); - return true; - } - - final boolean result = checkFeatureSupport(stmtContext, supportedFeatures); - stmtContext.setSupportedByFeatures(result); - return result; + /** + * Returns true if supplied statement context represents unrecognized + * statement, otherwise returns false. + * + * @param stmtCtx + * statement context to be checked + * @return true if supplied statement context represents unrecognized + * statement, otherwise false + * @throws NullPointerException + * if supplied statement context is null + */ + public static boolean isUnrecognizedStatement(final StmtContext stmtCtx) { + return UnrecognizedStatement.class + .isAssignableFrom(stmtCtx.getPublicDefinition().getDeclaredRepresentationClass()); } - private static boolean checkFeatureSupport(final StmtContext.Mutable stmtContext, + public static boolean checkFeatureSupport(final StmtContext stmtContext, final Set supportedFeatures) { boolean isSupported = false; boolean containsIfFeature = false; - for (final StatementContextBase stmt : stmtContext.declaredSubstatements()) { + for (final StmtContext stmt : stmtContext.declaredSubstatements()) { if (YangStmtMapping.IF_FEATURE.equals(stmt.getPublicDefinition())) { - if (stmtContext.isInYangDataExtensionBody()) { - break; - } - containsIfFeature = true; if (((Predicate>) stmt.getStatementArgument()).test(supportedFeatures)) { isSupported = true; @@ -299,7 +272,7 @@ public final class StmtContextUtils { * statement context * @return true if it is a presence container */ - public static boolean isPresenceContainer(final StatementContextBase stmtCtx) { + public static boolean isPresenceContainer(final StmtContext stmtCtx) { return stmtCtx.getPublicDefinition() == YangStmtMapping.CONTAINER && containsPresenceSubStmt(stmtCtx); } @@ -310,11 +283,11 @@ public final class StmtContextUtils { * statement context * @return true if it is a non-presence container */ - public static boolean isNonPresenceContainer(final StatementContextBase stmtCtx) { + public static boolean isNonPresenceContainer(final StmtContext stmtCtx) { return stmtCtx.getPublicDefinition() == YangStmtMapping.CONTAINER && !containsPresenceSubStmt(stmtCtx); } - private static boolean containsPresenceSubStmt(final StatementContextBase stmtCtx) { + private static boolean containsPresenceSubStmt(final StmtContext stmtCtx) { return findFirstSubstatement(stmtCtx, PresenceStatement.class) != null; } @@ -327,7 +300,7 @@ public final class StmtContextUtils { * @return true if it is a mandatory leaf, choice, anyxml, list or leaf-list * according to RFC6020. */ - public static boolean isMandatoryNode(final StatementContextBase stmtCtx) { + public static boolean isMandatoryNode(final StmtContext stmtCtx) { if (!(stmtCtx.getPublicDefinition() instanceof YangStmtMapping)) { return false; } @@ -358,7 +331,7 @@ public final class StmtContextUtils { * statement definition and if it is not mandatory leaf, choice, * anyxml, list or leaf-list according to RFC6020 */ - public static boolean isNotMandatoryNodeOfType(final StatementContextBase stmtCtx, + public static boolean isNotMandatoryNodeOfType(final StmtContext stmtCtx, final StatementDefinition stmtDef) { return stmtCtx.getPublicDefinition().equals(stmtDef) && !isMandatoryNode(stmtCtx); } @@ -398,21 +371,25 @@ public final class StmtContextUtils { * * @return true if all of StmtContext's ancestors of specified type have a child of specified type, otherwise false */ - public static > boolean hasAncestorOfTypeWithChildOfType(final StmtContext ctx, + public static > boolean hasAncestorOfTypeWithChildOfType(final StmtContext ctx, final StatementDefinition ancestorType, final StatementDefinition ancestorChildType) { Preconditions.checkNotNull(ctx); Preconditions.checkNotNull(ancestorType); Preconditions.checkNotNull(ancestorChildType); + StmtContext current = ctx.getParentContext(); - while (!(current instanceof RootStatementContext)) { + StmtContext parent = current.getParentContext(); + while (parent != null) { if (ancestorType.equals(current.getPublicDefinition())) { @SuppressWarnings("unchecked") - final Class
ancestorChildTypeClass = (Class
) ancestorChildType.getDeclaredRepresentationClass(); + final Class ancestorChildTypeClass = (Class) ancestorChildType.getDeclaredRepresentationClass(); if (findFirstSubstatement(current, ancestorChildTypeClass) == null) { return false; } } - current = current.getParentContext(); + + current = parent; + parent = current.getParentContext(); } return true; @@ -487,8 +464,7 @@ public final class StmtContextUtils { } private static void disallowIfFeatureAndWhenOnListKeys(final StmtContext leafStmtCtx) { - Iterables.concat(leafStmtCtx.declaredSubstatements(), leafStmtCtx.effectiveSubstatements()).forEach( - leafSubstmtCtx -> { + leafStmtCtx.allSubstatements().forEach(leafSubstmtCtx -> { final StatementDefinition statementDef = leafSubstmtCtx.getPublicDefinition(); SourceException.throwIf(YangStmtMapping.IF_FEATURE.equals(statementDef) || YangStmtMapping.WHEN.equals(statementDef), leafStmtCtx.getStatementSourceReference(), @@ -496,4 +472,118 @@ 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 && isUnknownStatement(ctx)) { + localName = value; + qNameModule = StmtContextUtils.getRootModuleQName(ctx); + } + if (qNameModule == null + && ctx.getCopyHistory().getLastOperation() == CopyType.ADDED_BY_AUGMENTATION) { + ctx = ctx.getOriginalCtx().orElse(null); + 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> 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; + } }