Fix {Data,Schema}TreeAwareEffectiveStatement.Namespace
[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  */
34 @Beta
35 public interface SchemaTreeAwareEffectiveStatement<A, D extends DeclaredStatement<A>> extends EffectiveStatement<A, D> {
36     /**
37      * Namespace of {@code schema node}s defined within this node.
38      */
39     @NonNullByDefault
40     abstract class Namespace extends EffectiveStatementNamespace<SchemaTreeEffectiveStatement<?>> {
41         private Namespace() {
42             // Should never be instantiated
43         }
44     }
45
46     /**
47      * Find a {@code schema tree} child {@link SchemaTreeEffectiveStatement}, as identified by its QName argument.
48      *
49      * @param qname Child identifier
50      * @return Schema tree child, or empty
51      * @throws NullPointerException if {@code qname} is null
52      */
53     default @NonNull Optional<SchemaTreeEffectiveStatement<?>> findSchemaTreeNode(final @NonNull QName qname) {
54         return get(Namespace.class, requireNonNull(qname));
55     }
56
57     /**
58      * Find a {@code schema tree} child {@link SchemaTreeEffectiveStatement}, as identified by its QName argument.
59      *
60      * @param <E> Effective substatement type
61      * @param type Effective substatement class
62      * @param qname Child identifier
63      * @return Schema tree child, or empty
64      * @throws NullPointerException if any argument is null
65      */
66     default <E> @NonNull Optional<E> findSchemaTreeNode(final @NonNull Class<E> type, final @NonNull QName qname) {
67         return filterOptional(type, findSchemaTreeNode(qname));
68     }
69
70     /**
71      * Find a {@code schema tree} child {@link SchemaTreeEffectiveStatement}, as identified by its QName argument.
72      *
73      * @param qnames Child identifiers
74      * @return Schema tree child, or empty
75      * @throws NullPointerException if {@code qnames} is null or contains a null element
76      * @throws NoSuchElementException if {@code qnames} is empty
77      */
78     default @NonNull Optional<SchemaTreeEffectiveStatement<?>> findSchemaTreeNode(final @NonNull QName... qnames) {
79         return findSchemaTreeNode(Arrays.asList(qnames));
80     }
81
82     /**
83      * Find a {@code schema tree} child {@link SchemaTreeEffectiveStatement}, as identified by its QName argument.
84      *
85      * @param <E> Effective substatement type
86      * @param type Effective substatement class
87      * @param qnames Child identifiers
88      * @return Schema tree child, or empty
89      * @throws NullPointerException if any argument is null or if {@code qnames} contains a null element
90      * @throws NoSuchElementException if {@code qnames} is empty
91      */
92     default <E> @NonNull Optional<E> findSchemaTreeNode(final @NonNull Class<E> type, final @NonNull QName... qnames) {
93         return filterOptional(type, findSchemaTreeNode(Arrays.asList(qnames)));
94     }
95
96     /**
97      * Find a {@code schema tree} child {@link SchemaTreeEffectiveStatement}, as identified by its QName argument.
98      *
99      * @param qnames Child identifiers
100      * @return Schema tree child, or empty
101      * @throws NullPointerException if {@code qnames} is null or contains a null element
102      * @throws NoSuchElementException if {@code qnames} is empty
103      */
104     default @NonNull Optional<SchemaTreeEffectiveStatement<?>> findSchemaTreeNode(final @NonNull List<QName> qnames) {
105         final Iterator<QName> it = qnames.iterator();
106         SchemaTreeAwareEffectiveStatement<?, ?> parent = this;
107         while (true) {
108             final Optional<SchemaTreeEffectiveStatement<?>> found = parent.findSchemaTreeNode(it.next());
109             if (!it.hasNext() || found.isEmpty()) {
110                 return found;
111             }
112             final SchemaTreeEffectiveStatement<?> node = found.orElseThrow();
113             if (node instanceof SchemaTreeAwareEffectiveStatement) {
114                 parent = (SchemaTreeAwareEffectiveStatement<?, ?>) node;
115             } else {
116                 return Optional.empty();
117             }
118         }
119     }
120
121     /**
122      * Find a {@code schema tree} child {@link SchemaTreeEffectiveStatement}, as identified by its QName argument.
123      *
124      * @param <E> Effective substatement type
125      * @param type Effective substatement class
126      * @param qnames Child identifiers
127      * @return Schema tree child, or empty
128      * @throws NullPointerException if {@code qnames} is null or contains a null element
129      * @throws NoSuchElementException if {@code qnames} is empty
130      */
131     default <E> @NonNull Optional<E> findSchemaTreeNode(final @NonNull Class<E> type,
132             final @NonNull List<QName> qnames) {
133         return filterOptional(type, findSchemaTreeNode(qnames));
134     }
135
136     /**
137      * Find a {@code schema tree} child {@link SchemaTreeEffectiveStatement}, as identified by its
138      * {@link Descendant descendant schema node identifier}.
139      *
140      * @implSpec
141      *     Default implementation defers to {@link #findSchemaTreeNode(List)}.
142      *
143      * @param descendant Descendant schema node identifier
144      * @return Schema tree child, or empty
145      * @throws NullPointerException if {@code descendant} is null
146      */
147     default @NonNull Optional<SchemaTreeEffectiveStatement<?>> findSchemaTreeNode(
148             final @NonNull Descendant descendant) {
149         return findSchemaTreeNode(descendant.getNodeIdentifiers());
150     }
151
152     /**
153      * Find a {@code schema tree} child {@link SchemaTreeEffectiveStatement}, as identified by its
154      * {@link Descendant descendant schema node identifier}.
155      *
156      * @implSpec
157      *     Default implementation defers to {@link #findSchemaTreeNode(Class, List)}.
158      *
159      * @param <E> Effective substatement type
160      * @param type Effective substatement class
161      * @param descendant Descendant schema node identifier
162      * @return Schema tree child, or empty
163      * @throws NullPointerException if {@code descendant} is null
164      */
165     default <E> @NonNull Optional<E> findSchemaTreeNode(final @NonNull Class<E> type,
166             final @NonNull Descendant descendant) {
167         return findSchemaTreeNode(type, descendant.getNodeIdentifiers());
168     }
169 }