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

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

/*
 * Copyright (c) 2015 Cisco Systems, Inc. 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.annotations.Beta;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import java.util.Optional;
import org.eclipse.jdt.annotation.NonNull;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
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.UnknownStatement;
import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceBehaviour;
import org.opendaylight.yangtools.yang.parser.spi.meta.StatementNamespace;
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.SourceException;

/**
 * Statement local namespace, which holds direct schema node descendants. This corresponds to the contents of the schema
 * tree as exposed through {@link SchemaTreeAwareEffectiveStatement}.
 */
// FIXME: 7.0.0: this contract seems to fall on the reactor side of things rather than parser-spi. Consider moving this
//               into yang-(parser-)reactor-api.
@Beta
public final class SchemaTreeNamespace,
            E extends SchemaTreeEffectiveStatement>
        extends NamespaceBehaviour, SchemaTreeNamespace>
        implements StatementNamespace {
    private static final @NonNull SchemaTreeNamespace INSTANCE = new SchemaTreeNamespace<>();

    @SuppressWarnings({ "rawtypes", "unchecked" })
    private SchemaTreeNamespace() {
        super((Class) SchemaTreeNamespace.class);
    }

    @SuppressWarnings("unchecked")
    public static , E extends SchemaTreeEffectiveStatement>
            @NonNull SchemaTreeNamespace getInstance() {
        return (SchemaTreeNamespace) INSTANCE;
    }

    /**
     * {@inheritDoc}
     *
     * 

* This method is analogous to {@link SchemaTreeAwareEffectiveStatement#findSchemaTreeNode(QName)}. */ @Override public StmtContext getFrom(final NamespaceStorageNode storage, final QName key) { // Get the backing storage node for the requested storage final NamespaceStorageNode storageNode = globalOrStatementSpecific(storage); // Check try to look up existing node final StmtContext existing = storageNode.getFromLocalStorage(getIdentifier(), key); // An existing node takes precedence, if it does not exist try to request it return existing != null ? existing : requestFrom(storageNode, key); } private static , E extends SchemaTreeEffectiveStatement> StmtContext requestFrom(final NamespaceStorageNode storageNode, final QName key) { return storageNode instanceof OnDemandSchemaTreeStorageNode ? ((OnDemandSchemaTreeStorageNode) storageNode).requestSchemaTreeChild(key) : null; } @Override public Map> getAllFrom(final NamespaceStorageNode storage) { // FIXME: 7.0.0: this method needs to be well-defined return null; } @Override @SuppressWarnings("unchecked") public void addTo(final NamespaceStorageNode storage, final QName key, final StmtContext value) { final StmtContext prev = globalOrStatementSpecific(storage).putToLocalStorageIfAbsent( SchemaTreeNamespace.class, key, value); if (prev != null) { throw new SourceException(value, "Error in module '%s': cannot add '%s'. Node name collision: '%s' already declared at %s", value.getRoot().rawArgument(), key, prev.argument(), prev.sourceReference()); } } /** * 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> findNode(final StmtContext root, final SchemaNodeIdentifier identifier) { final Iterator iterator = identifier.getNodeIdentifiers().iterator(); if (!iterator.hasNext()) { return Optional.of(root); } QName nextPath = iterator.next(); @SuppressWarnings("unchecked") StmtContext current = (StmtContext) root.getFromNamespace(SchemaTreeNamespace.class, nextPath); if (current == null) { return Optional.ofNullable(tryToFindUnknownStatement(nextPath.getLocalName(), root)); } while (current != null && iterator.hasNext()) { nextPath = iterator.next(); @SuppressWarnings("unchecked") final StmtContext nextNodeCtx = (StmtContext) current.getFromNamespace( SchemaTreeNamespace.class, 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 StmtContext unknownSubstatement : unknownSubstatements) { if (localName.equals(unknownSubstatement.rawArgument())) { return unknownSubstatement; } } return null; } private static NamespaceStorageNode globalOrStatementSpecific(final NamespaceStorageNode storage) { NamespaceStorageNode current = storage; while (!isLocalOrGlobal(current.getStorageNodeType())) { current = current.getParentNamespaceStorage(); } return current; } private static boolean isLocalOrGlobal(final StorageNodeType type) { return type == StorageNodeType.STATEMENT_LOCAL || type == StorageNodeType.GLOBAL; } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy