144473a6907f757363b467e31eaf0acd16802a01
[yangtools.git] / model / yang-model-api / src / main / java / org / opendaylight / yangtools / yang / model / api / stmt / SchemaTreeAwareEffectiveStatement.java
1 /*
2  * Copyright (c) 2018 Pantheon Technologies, s.r.o. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.yangtools.yang.model.api.stmt;
9
10 import static java.util.Objects.requireNonNull;
11 import static org.opendaylight.yangtools.yang.model.api.stmt.DefaultMethodHelpers.filterOptional;
12
13 import com.google.common.annotations.Beta;
14 import java.util.Arrays;
15 import java.util.Iterator;
16 import java.util.List;
17 import java.util.NoSuchElementException;
18 import java.util.Optional;
19 import org.eclipse.jdt.annotation.NonNull;
20 import org.eclipse.jdt.annotation.NonNullByDefault;
21 import org.opendaylight.yangtools.yang.common.QName;
22 import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
23 import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
24 import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier.Descendant;
25
26 /**
27  * Interface implemented by all {@link EffectiveStatement}s which can contain a {@code schema tree} child. This tree
28  * can be walked using {@link SchemaNodeIdentifier}, looking up each component of
29  * {@link SchemaNodeIdentifier#getNodeIdentifiers()} using {@link #findSchemaTreeNode(QName)}.
30  *
31  * @param <A> Argument type
32  * @param <D> Class representing declared version of this statement.
33  * @author Robert Varga
34  */
35 @Beta
36 public interface SchemaTreeAwareEffectiveStatement<A, D extends DeclaredStatement<A>> extends EffectiveStatement<A, D> {
37     /**
38      * Namespace of {@code schema node}s defined within this node.
39      *
40      * @param <T> Child statement type
41      * @author Robert Varga
42      */
43     @NonNullByDefault
44     abstract class Namespace<T extends SchemaTreeEffectiveStatement<?>> extends EffectiveStatementNamespace<T> {
45         private Namespace() {
46             // Should never be instantiated
47         }
48     }
49
50     /**
51      * Find a {@code schema tree} child {@link SchemaTreeEffectiveStatement}, as identified by its QName argument.
52      *
53      * @param qname Child identifier
54      * @return Schema tree child, or empty
55      * @throws NullPointerException if {@code qname} is null
56      */
57     default @NonNull Optional<SchemaTreeEffectiveStatement<?>> findSchemaTreeNode(final @NonNull QName qname) {
58         return get(Namespace.class, requireNonNull(qname));
59     }
60
61     /**
62      * Find a {@code schema tree} child {@link SchemaTreeEffectiveStatement}, as identified by its QName argument.
63      *
64      * @param <E> Effective substatement type
65      * @param type Effective substatement class
66      * @param qname Child identifier
67      * @return Schema tree child, or empty
68      * @throws NullPointerException if any argument is null
69      */
70     default <E> @NonNull Optional<E> findSchemaTreeNode(final @NonNull Class<E> type, final @NonNull QName qname) {
71         return filterOptional(type, findSchemaTreeNode(qname));
72     }
73
74     /**
75      * Find a {@code schema tree} child {@link SchemaTreeEffectiveStatement}, as identified by its QName argument.
76      *
77      * @param qnames Child identifiers
78      * @return Schema tree child, or empty
79      * @throws NullPointerException if {@code qnames} is null or contains a null element
80      * @throws NoSuchElementException if {@code qnames} is empty
81      */
82     default @NonNull Optional<SchemaTreeEffectiveStatement<?>> findSchemaTreeNode(final @NonNull QName... qnames) {
83         return findSchemaTreeNode(Arrays.asList(qnames));
84     }
85
86     /**
87      * Find a {@code schema tree} child {@link SchemaTreeEffectiveStatement}, as identified by its QName argument.
88      *
89      * @param <E> Effective substatement type
90      * @param type Effective substatement class
91      * @param qnames Child identifiers
92      * @return Schema tree child, or empty
93      * @throws NullPointerException if any argument is null or if {@code qnames} contains a null element
94      * @throws NoSuchElementException if {@code qnames} is empty
95      */
96     default <E> @NonNull Optional<E> findSchemaTreeNode(final @NonNull Class<E> type, final @NonNull QName... qnames) {
97         return filterOptional(type, findSchemaTreeNode(Arrays.asList(qnames)));
98     }
99
100     /**
101      * Find a {@code schema tree} child {@link SchemaTreeEffectiveStatement}, as identified by its QName argument.
102      *
103      * @param qnames Child identifiers
104      * @return Schema tree child, or empty
105      * @throws NullPointerException if {@code qnames} is null or contains a null element
106      * @throws NoSuchElementException if {@code qnames} is empty
107      */
108     default @NonNull Optional<SchemaTreeEffectiveStatement<?>> findSchemaTreeNode(final @NonNull List<QName> qnames) {
109         final Iterator<QName> it = qnames.iterator();
110         SchemaTreeAwareEffectiveStatement<?, ?> parent = this;
111         while (true) {
112             final Optional<SchemaTreeEffectiveStatement<?>> found = parent.findSchemaTreeNode(it.next());
113             if (!it.hasNext() || found.isEmpty()) {
114                 return found;
115             }
116             final SchemaTreeEffectiveStatement<?> node = found.orElseThrow();
117             if (node instanceof SchemaTreeAwareEffectiveStatement) {
118                 parent = (SchemaTreeAwareEffectiveStatement<?, ?>) node;
119             } else {
120                 return Optional.empty();
121             }
122         }
123     }
124
125     /**
126      * Find a {@code schema tree} child {@link SchemaTreeEffectiveStatement}, as identified by its QName argument.
127      *
128      * @param <E> Effective substatement type
129      * @param type Effective substatement class
130      * @param qnames Child identifiers
131      * @return Schema tree child, or empty
132      * @throws NullPointerException if {@code qnames} is null or contains a null element
133      * @throws NoSuchElementException if {@code qnames} is empty
134      */
135     default <E> @NonNull Optional<E> findSchemaTreeNode(final @NonNull Class<E> type,
136             final @NonNull List<QName> qnames) {
137         return filterOptional(type, findSchemaTreeNode(qnames));
138     }
139
140     /**
141      * Find a {@code schema tree} child {@link SchemaTreeEffectiveStatement}, as identified by its
142      * {@link Descendant descendant schema node identifier}.
143      *
144      * @implSpec
145      *     Default implementation defers to {@link #findSchemaTreeNode(List)}.
146      *
147      * @param descendant Descendant schema node identifier
148      * @return Schema tree child, or empty
149      * @throws NullPointerException if {@code descendant} is null
150      */
151     default @NonNull Optional<SchemaTreeEffectiveStatement<?>> findSchemaTreeNode(
152             final @NonNull Descendant descendant) {
153         return findSchemaTreeNode(descendant.getNodeIdentifiers());
154     }
155
156     /**
157      * Find a {@code schema tree} child {@link SchemaTreeEffectiveStatement}, as identified by its
158      * {@link Descendant descendant schema node identifier}.
159      *
160      * @implSpec
161      *     Default implementation defers to {@link #findSchemaTreeNode(Class, List)}.
162      *
163      * @param <E> Effective substatement type
164      * @param type Effective substatement class
165      * @param descendant Descendant schema node identifier
166      * @return Schema tree child, or empty
167      * @throws NullPointerException if {@code descendant} is null
168      */
169     default <E> @NonNull Optional<E> findSchemaTreeNode(final @NonNull Class<E> type,
170             final @NonNull Descendant descendant) {
171         return findSchemaTreeNode(type, descendant.getNodeIdentifiers());
172     }
173 }