All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.opendaylight.yangtools.yang.parser.spi.ParserNamespaces Maven / Gradle / Ivy

There is a newer version: 14.0.5
Show newest version
/*
 * Copyright (c) 2022 PANTHEON.tech, s.r.o. and others.  All rights reserved.
 *
 * 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/epl-v10.html
 */
package org.opendaylight.yangtools.yang.parser.spi;

import com.google.common.collect.SetMultimap;
import java.util.Collection;
import java.util.Optional;
import org.eclipse.jdt.annotation.NonNull;
import org.opendaylight.yangtools.yang.common.Empty;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.common.QNameModule;
import org.opendaylight.yangtools.yang.common.UnresolvedQName.Unqualified;
import org.opendaylight.yangtools.yang.common.XMLNamespace;
import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
import org.opendaylight.yangtools.yang.model.api.source.SourceIdentifier;
import org.opendaylight.yangtools.yang.model.api.stmt.ExtensionEffectiveStatement;
import org.opendaylight.yangtools.yang.model.api.stmt.ExtensionStatement;
import org.opendaylight.yangtools.yang.model.api.stmt.FeatureEffectiveStatement;
import org.opendaylight.yangtools.yang.model.api.stmt.FeatureSet;
import org.opendaylight.yangtools.yang.model.api.stmt.FeatureStatement;
import org.opendaylight.yangtools.yang.model.api.stmt.GroupingEffectiveStatement;
import org.opendaylight.yangtools.yang.model.api.stmt.GroupingStatement;
import org.opendaylight.yangtools.yang.model.api.stmt.IdentityEffectiveStatement;
import org.opendaylight.yangtools.yang.model.api.stmt.IdentityStatement;
import org.opendaylight.yangtools.yang.model.api.stmt.ModuleEffectiveStatement;
import org.opendaylight.yangtools.yang.model.api.stmt.ModuleStatement;
import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier;
import org.opendaylight.yangtools.yang.model.api.stmt.SchemaTreeAwareEffectiveStatement;
import org.opendaylight.yangtools.yang.model.api.stmt.SchemaTreeEffectiveStatement;
import org.opendaylight.yangtools.yang.model.api.stmt.SubmoduleEffectiveStatement;
import org.opendaylight.yangtools.yang.model.api.stmt.SubmoduleStatement;
import org.opendaylight.yangtools.yang.model.api.stmt.TypedefEffectiveStatement;
import org.opendaylight.yangtools.yang.model.api.stmt.TypedefStatement;
import org.opendaylight.yangtools.yang.model.api.stmt.UnknownStatement;
import org.opendaylight.yangtools.yang.parser.spi.meta.ParserNamespace;
import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContextUtils;
import org.opendaylight.yangtools.yang.parser.spi.source.PrefixResolver;

/**
 * Baseline {@link ParserNamespace}s mostly derived from YANG specification.
 */
public final class ParserNamespaces {
    /**
     * Extension namespace. All extension names defined in a module and its submodules share the same extension
     * identifier namespace, where each extension is identified by a QName formed from the defining module's QNameModule
     * and the identifier specified in extension statement's argument.
     */
    public static final @NonNull ParserNamespace> EXTENSION =
        new ParserNamespace<>("extension");

    /**
     * Feature namespace. All feature names defined in a module and its submodules share the same feature identifier
     * namespace. Each feature is identified by a QName formed from the defining module's QNameModule and the feature
     * name.
     */
    public static final @NonNull ParserNamespace> FEATURE = new ParserNamespace<>("feature");

    /**
     * Grouping namespace. * All grouping names defined within a parent node or at the top level of the module
     * or its submodules share the same grouping identifier namespace. This namespace is scoped to all
     * descendant nodes of the parent node or module.
     *
     * 

This means that any descendant node may use that grouping, and it MUST NOT define a grouping with the same * name. */ public static final @NonNull ParserNamespace> GROUPING = new ParserNamespace<>("grouping"); /** * Identity namespace. All identity names defined in a module and its submodules share the same identity identifier * namespace. */ public static final @NonNull ParserNamespace> IDENTITY = new ParserNamespace<>("identity"); /** * Module namespace. All modules known to the reactor are populated to this namespace. Each module is identified * by a {@link SourceIdentifier}. */ public static final @NonNull ParserNamespace> MODULE = new ParserNamespace<>("module"); /** * Submodule equivalent of {@link #MODULE}. */ public static final @NonNull ParserNamespace> SUBMODULE = new ParserNamespace<>("submodule"); /** * Derived types namespace. All derived type names defined within a parent node or at the top level of the module * (or its submodules) share the same type identifier namespace. * *

This namespace is scoped to all descendant nodes of the parent node or module. This means that any descendant * node may use that typedef, and it MUST NOT define a typedef with the same name. * *

This namespace includes all type definitions implied by the language in which the current statement resides * (e.g. RFC6020/RFC7950 for YANG 1.0/1.1). */ public static final @NonNull ParserNamespace> TYPE = new ParserNamespace<>("typedef"); /** * A derived namespace allowing lookup of modules based on their {@link QNameModule}. */ public static final @NonNull ParserNamespace> NAMESPACE_TO_MODULE = new ParserNamespace<>("namespace-to-module"); /** * Intermediate-stage namespace equivalent to {@link #MODULE} except it is keyed by module names. This namespace is * used to resolve inter-module references before actual linkage occurs. */ public static final @NonNull ParserNamespace> PRELINKAGE_MODULE = new ParserNamespace<>("prelinkage-module"); /** * Source-specific mapping of belongsTo prefixes to module identifiers. This mapping allows source-specific context * to correctly populate prefixes map for actual parsing phase and eventually, resolve QName for any valid declared * statement. */ public static final @NonNull ParserNamespace> BELONGSTO_PREFIX_TO_MODULECTX = new ParserNamespace<>("belongsto-prefix-to-module"); /** * Source-specific mapping of prefixes to namespaces. */ // FIXME: bad javadoc public static final @NonNull ParserNamespace BELONGSTO_PREFIX_TO_MODULE_NAME = new ParserNamespace<>("belongsto-prefix-to-name"); /** * Namespace similar to {@link ParserNamespaces#MODULE} for storing modules into Yang model storage but keyed by * plain name. */ // FIXME: Better name? public static final @NonNull ParserNamespace> MODULE_FOR_BELONGSTO = new ParserNamespace<>("module-belongsto"); /** * Pre-linkage source-specific mapping of prefixes to module namespaces. */ // FIXME: a better name? public static final @NonNull ParserNamespace IMP_PREFIX_TO_NAMESPACE = new ParserNamespace<>("prefix-to-xmlnamespace"); /** * Source-specific mapping of prefix strings to module context. */ // FIXME: the context should expose ModuleStatement public static final @NonNull ParserNamespace> IMPORT_PREFIX_TO_MODULECTX = new ParserNamespace<>("import-prefix-to-modulectx"); // FIXME: document this public static final @NonNull ParserNamespace> IMPORTED_MODULE = new ParserNamespace<>("imported-module"); // FIXME: document this // FIXME: is this 'included submodule' instead? public static final @NonNull ParserNamespace> INCLUDED_MODULE = new ParserNamespace<>("included-module"); /** * Source-specific mapping of prefixes to namespaces. */ // FIXME: bad javadoc // FIXME: the context should expose SubmoduleStatement public static final @NonNull ParserNamespace> INCLUDED_SUBMODULE_NAME_TO_MODULECTX = new ParserNamespace<>("included-submodule-to-modulectx"); /** * Source-specific mapping of prefixes to namespaces. */ // FIXME: bad javadoc public static final @NonNull ParserNamespace MODULE_NAME_TO_QNAME = new ParserNamespace<>("module-name-to-qnamemodule"); /** * Global mapping of modules to QNameModules. */ public static final @NonNull ParserNamespace, QNameModule> MODULECTX_TO_QNAME = new ParserNamespace<>("modulectx-to-qnamemodule"); public static final @NonNull ParserNamespace SUPPORTED_FEATURES = new ParserNamespace<>("supportedFeatures"); /** * Source-specific mapping of prefixes to namespaces. This namespace is populated by all statements which have * impact on the XML namespace, for example {@code import}, {@code belongs-to} and really anywhere a {@code prefix} * statement is present. * * @see PrefixResolver */ public static final @NonNull ParserNamespace PREFIX_TO_MODULE = new ParserNamespace<>("prefix-to-qnamemodule"); /** * Namespace used for storing information about modules that support deviation resolution. * Map key (QNameModule) denotes a module which can be deviated by the modules specified in the Map value. */ public static final @NonNull ParserNamespace> MODULES_DEVIATED_BY = new ParserNamespace<>("moduleDeviations"); /** * Source-specific mapping of prefixes to namespaces. */ // FIXME: bad javadoc public static final @NonNull ParserNamespace MODULE_NAMESPACE_TO_NAME = new ParserNamespace<>("qnamemodule-to-name"); /** * Pre-linkage global mapping of module names to namespaces. */ public static final @NonNull ParserNamespace MODULE_NAME_TO_NAMESPACE = new ParserNamespace<>("module-name-to-xmlnamespace"); /** * Global mapping of modules to source identifier. */ public static final @NonNull ParserNamespace, SourceIdentifier> MODULECTX_TO_SOURCE = new ParserNamespace<>("modulectx-to-source"); private static final @NonNull ParserNamespace SCHEMA_TREE = new ParserNamespace<>("schemaTree"); /** * Statement local namespace, which holds direct schema node descendants. This corresponds to the contents of the * schema tree as exposed through {@link SchemaTreeAwareEffectiveStatement}. * *

Unlike all other namespaces this namespaces is polymorphic, hence it is exposed throught this method. * * @return Schema tree namespace */ @SuppressWarnings("unchecked") public static , E extends SchemaTreeEffectiveStatement> @NonNull ParserNamespace> schemaTree() { return (ParserNamespace>) SCHEMA_TREE; } private ParserNamespaces() { // Hidden on purpose } /** * Find statement context identified by interpreting specified {@link SchemaNodeIdentifier} starting at specified * {@link StmtContext}. * * @param root Search root context * @param identifier {@link SchemaNodeIdentifier} relative to search root * @return Matching statement context, if present. * @throws NullPointerException if any of the arguments is null */ public static Optional> findSchemaTreeStatement(final StmtContext root, final SchemaNodeIdentifier identifier) { final var iterator = identifier.getNodeIdentifiers().iterator(); if (!iterator.hasNext()) { return Optional.of(root); } QName nextPath = iterator.next(); var current = root.namespaceItem(schemaTree(), nextPath); if (current == null) { return Optional.ofNullable(tryToFindUnknownStatement(nextPath.getLocalName(), root)); } while (current != null && iterator.hasNext()) { nextPath = iterator.next(); final var nextNodeCtx = current.namespaceItem(schemaTree(), nextPath); if (nextNodeCtx == null) { return Optional.ofNullable(tryToFindUnknownStatement(nextPath.getLocalName(), current)); } current = nextNodeCtx; } return Optional.ofNullable(current); } @SuppressWarnings("unchecked") private static StmtContext tryToFindUnknownStatement(final String localName, final StmtContext current) { final Collection> unknownSubstatements = StmtContextUtils.findAllSubstatements( current, UnknownStatement.class); for (final var unknownSubstatement : unknownSubstatements) { if (localName.equals(unknownSubstatement.rawArgument())) { return unknownSubstatement; } } return null; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy