/* * Copyright (c) 2018 Pantheon Technologies, 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.model.api.stmt; import static java.util.Objects.requireNonNull; import static org.opendaylight.yangtools.yang.model.api.stmt.DefaultMethodHelpers.filterOptional; import com.google.common.annotations.Beta; import java.util.Arrays; import java.util.Iterator; import java.util.List; import java.util.NoSuchElementException; import java.util.Optional; import org.eclipse.jdt.annotation.NonNull; import org.eclipse.jdt.annotation.NonNullByDefault; import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement; import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement; import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier.Descendant; /** * Interface implemented by all {@link EffectiveStatement}s which can contain a {@code schema tree} child. This tree * can be walked using {@link SchemaNodeIdentifier}, looking up each component of * {@link SchemaNodeIdentifier#getNodeIdentifiers()} using {@link #findSchemaTreeNode(QName)}. * * @param Argument type * @param Class representing declared version of this statement. * @author Robert Varga */ @Beta public interface SchemaTreeAwareEffectiveStatement> extends EffectiveStatement { /** * Namespace of {@code schema node}s defined within this node. * * @param Child statement type * @author Robert Varga */ @NonNullByDefault abstract class Namespace> extends EffectiveStatementNamespace { private Namespace() { // Should never be instantiated } } /** * Find a {@code schema tree} child {@link SchemaTreeEffectiveStatement}, as identified by its QName argument. * * @param qname Child identifier * @return Schema tree child, or empty * @throws NullPointerException if {@code qname} is null */ default @NonNull Optional> findSchemaTreeNode(final @NonNull QName qname) { return get(Namespace.class, requireNonNull(qname)); } /** * Find a {@code schema tree} child {@link SchemaTreeEffectiveStatement}, as identified by its QName argument. * * @param Effective substatement type * @param type Effective substatement class * @param qname Child identifier * @return Schema tree child, or empty * @throws NullPointerException if any argument is null */ default @NonNull Optional findSchemaTreeNode(final @NonNull Class type, final @NonNull QName qname) { return filterOptional(type, findSchemaTreeNode(qname)); } /** * Find a {@code schema tree} child {@link SchemaTreeEffectiveStatement}, as identified by its QName argument. * * @param qnames Child identifiers * @return Schema tree child, or empty * @throws NullPointerException if {@code qnames} is null or contains a null element * @throws NoSuchElementException if {@code qnames} is empty */ default @NonNull Optional> findSchemaTreeNode(final @NonNull QName... qnames) { return findSchemaTreeNode(Arrays.asList(qnames)); } /** * Find a {@code schema tree} child {@link SchemaTreeEffectiveStatement}, as identified by its QName argument. * * @param Effective substatement type * @param type Effective substatement class * @param qnames Child identifiers * @return Schema tree child, or empty * @throws NullPointerException if any argument is null or if {@code qnames} contains a null element * @throws NoSuchElementException if {@code qnames} is empty */ default @NonNull Optional findSchemaTreeNode(final @NonNull Class type, final @NonNull QName... qnames) { return filterOptional(type, findSchemaTreeNode(Arrays.asList(qnames))); } /** * Find a {@code schema tree} child {@link SchemaTreeEffectiveStatement}, as identified by its QName argument. * * @param qnames Child identifiers * @return Schema tree child, or empty * @throws NullPointerException if {@code qnames} is null or contains a null element * @throws NoSuchElementException if {@code qnames} is empty */ default @NonNull Optional> findSchemaTreeNode(final @NonNull List qnames) { final Iterator it = qnames.iterator(); SchemaTreeAwareEffectiveStatement parent = this; while (true) { final Optional> found = parent.findSchemaTreeNode(it.next()); if (!it.hasNext() || found.isEmpty()) { return found; } final SchemaTreeEffectiveStatement node = found.orElseThrow(); if (node instanceof SchemaTreeAwareEffectiveStatement) { parent = (SchemaTreeAwareEffectiveStatement) node; } else { return Optional.empty(); } } } /** * Find a {@code schema tree} child {@link SchemaTreeEffectiveStatement}, as identified by its QName argument. * * @param Effective substatement type * @param type Effective substatement class * @param qnames Child identifiers * @return Schema tree child, or empty * @throws NullPointerException if {@code qnames} is null or contains a null element * @throws NoSuchElementException if {@code qnames} is empty */ default @NonNull Optional findSchemaTreeNode(final @NonNull Class type, final @NonNull List qnames) { return filterOptional(type, findSchemaTreeNode(qnames)); } /** * Find a {@code schema tree} child {@link SchemaTreeEffectiveStatement}, as identified by its * {@link Descendant descendant schema node identifier}. * * @implSpec * Default implementation defers to {@link #findSchemaTreeNode(List)}. * * @param descendant Descendant schema node identifier * @return Schema tree child, or empty * @throws NullPointerException if {@code descendant} is null */ default @NonNull Optional> findSchemaTreeNode( final @NonNull Descendant descendant) { return findSchemaTreeNode(descendant.getNodeIdentifiers()); } /** * Find a {@code schema tree} child {@link SchemaTreeEffectiveStatement}, as identified by its * {@link Descendant descendant schema node identifier}. * * @implSpec * Default implementation defers to {@link #findSchemaTreeNode(Class, List)}. * * @param Effective substatement type * @param type Effective substatement class * @param descendant Descendant schema node identifier * @return Schema tree child, or empty * @throws NullPointerException if {@code descendant} is null */ default @NonNull Optional findSchemaTreeNode(final @NonNull Class type, final @NonNull Descendant descendant) { return findSchemaTreeNode(type, descendant.getNodeIdentifiers()); } }