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

org.opendaylight.yangtools.yang.model.api.DataNodeContainer Maven / Gradle / Ivy

There is a newer version: 14.0.4
Show newest version
/*
 * Copyright (c) 2013 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.model.api;

import static com.google.common.base.Verify.verifyNotNull;
import static java.util.Objects.requireNonNull;

import com.google.common.base.VerifyException;
import java.util.Arrays;
import java.util.Collection;
import java.util.NoSuchElementException;
import java.util.Optional;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
import org.opendaylight.yangtools.yang.common.QName;

/**
 * Node which can contains other nodes.
 */
public interface DataNodeContainer {
    /**
     * Returns set of all newly defined types within this DataNodeContainer.
     *
     * @return typedef statements in lexicographical order
     */
    @NonNull Collection> getTypeDefinitions();

    /**
     * Returns set of all child nodes defined within this DataNodeContainer. Although the return type is a collection,
     * each node is guaranteed to be present at most once.
     *
     * 

* Note that the nodes returned are NOT {@code data nodes}, but rather {@link DataSchemaNode}s, * hence {@link ChoiceSchemaNode} and {@link CaseSchemaNode} are present instead of their children. This * is consistent with {@code schema tree}. * * @return child nodes in lexicographical order */ @NonNull Collection getChildNodes(); /** * Returns set of all groupings defined within this DataNodeContainer. * * @return grouping statements in lexicographical order */ @NonNull Collection getGroupings(); /** * Returns the child node corresponding to the specified name. * *

* Note that the nodes searched are NOT {@code data nodes}, but rather {@link DataSchemaNode}s, * hence {@link ChoiceSchemaNode} and {@link CaseSchemaNode} are returned instead of their matching children. This * is consistent with {@code schema tree}. * * @param name QName of child * @return child node of this DataNodeContainer if child with given name is present, null otherwise * @throws NullPointerException if {@code name} is null */ @Nullable DataSchemaNode dataChildByName(QName name); /** * Returns the child node corresponding to the specified name. * *

* Note that the nodes searched are NOT {@code data nodes}, but rather {@link DataSchemaNode}s, * hence {@link ChoiceSchemaNode} and {@link CaseSchemaNode} are returned instead of their matching children. This * is consistent with {@code schema tree}. * * @param name QName of child * @return child node of this DataNodeContainer * @throws NullPointerException if {@code name} is null * @throws VerifyException if the child does not exist */ default @NonNull DataSchemaNode getDataChildByName(final QName name) { return verifyNotNull(dataChildByName(name), "No child matching %s found", name); } /** * Returns the child node corresponding to the specified name. * *

* Note that the nodes searched are NOT {@code data nodes}, but rather {@link DataSchemaNode}s, * hence {@link ChoiceSchemaNode} and {@link CaseSchemaNode} are returned instead of their matching children. * * @param name QName of child * @return child node of this DataNodeContainer if child with given name is present, empty otherwise * @throws NullPointerException if {@code name} is null */ default Optional findDataChildByName(final QName name) { return Optional.ofNullable(dataChildByName(name)); } /** * Returns the child node corresponding to the specified name. * *

* Note that the nodes searched are NOT {@code data nodes}, but rather {@link DataSchemaNode}s, * hence {@link ChoiceSchemaNode} and {@link CaseSchemaNode} are returned instead of their matching children. * * @param first QName of first child * @param others QNames of subsequent children * @return child node of this DataNodeContainer if child with given name is present, empty otherwise * @throws NullPointerException if any argument is null */ default Optional findDataChildByName(final QName first, final QName... others) { var current = dataChildByName(first); for (var qname : others) { if (current instanceof DataNodeContainer container) { current = container.dataChildByName(qname); } else { return Optional.empty(); } } return Optional.ofNullable(current); } /** * Returns grouping nodes used ny this container. * * @return Set of all uses nodes defined within this DataNodeContainer */ @NonNull Collection getUses(); /** * Returns a {@code data node} identified by a QName. This method is distinct from * {@link #findDataChildByName(QName)} in that it skips over {@link ChoiceSchemaNode}s and {@link CaseSchemaNode}s, * hence mirroring layout of the {@code data tree}, not {@code schema tree}. * * @param name QName identifier of the data node * @return Direct or indirect child of this DataNodeContainer which is a {@code data node}, empty otherwise * @throws NullPointerException if {@code name} is {@code null} */ default Optional findDataTreeChild(final QName name) { // First we try to find a direct child and check if it is a data node (as per RFC7950) final var dataChild = dataChildByName(name); if (isDataNode(dataChild)) { return Optional.of(dataChild); } // There either is no such node present, or there are Choice/CaseSchemaNodes with the same name involved, // hence we have to resort to a full search. for (var child : getChildNodes()) { if (child instanceof ChoiceSchemaNode choice) { for (var choiceCase : choice.getCases()) { final var caseChild = choiceCase.findDataTreeChild(name); if (caseChild.isPresent()) { return caseChild; } } } } return Optional.empty(); } /** * Returns a {@code data node} identified by a series of QNames. This is equivalent to incrementally calling * {@link #findDataTreeChild(QName)}. * * @param path Series of QNames towards identifying the requested data node * @return Direct or indirect child of this DataNodeContainer which is a {@code data node}, empty otherwise * @throws IllegalArgumentException if {@code path} is determined to go beyond a not-container-nor-list node. * @throws NoSuchElementException if {@code path} is empty * @throws NullPointerException if {@code path} is {@code null} or contains a {@code null} element */ default Optional findDataTreeChild(final QName... path) { return findDataTreeChild(Arrays.asList(path)); } /** * Returns a {@code data node} identified by a series of QNames. This is equivalent to incrementally calling * {@link #findDataTreeChild(QName)}. * * @param path Series of QNames towards identifying the requested data node * @return Direct or indirect child of this DataNodeContainer which is a {@code data node}, empty otherwise * @throws IllegalArgumentException if {@code path} is determined to go beyond a not-container-nor-list node. * @throws NoSuchElementException if {@code path} is empty * @throws NullPointerException if {@code path} is {@code null} or contains a {@code null} element */ default Optional findDataTreeChild(final Iterable path) { final var it = path.iterator(); DataNodeContainer parent = this; do { final var optChild = parent.findDataTreeChild(requireNonNull(it.next())); if (optChild.isEmpty() || !it.hasNext()) { return optChild; } final var child = optChild.orElseThrow(); if (!(child instanceof DataNodeContainer container)) { throw new IllegalArgumentException("Path " + path + " extends beyond terminal child " + child); } parent = container; } while (true); } private static boolean isDataNode(final DataSchemaNode node) { return node instanceof ContainerSchemaNode || node instanceof LeafSchemaNode || node instanceof LeafListSchemaNode || node instanceof ListSchemaNode || node instanceof AnydataSchemaNode || node instanceof AnyxmlSchemaNode; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy