2 * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
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
8 package org.opendaylight.yangtools.yang.parser.spi;
10 import com.google.common.annotations.Beta;
11 import java.io.Serial;
12 import java.util.Collection;
13 import java.util.Iterator;
14 import java.util.Optional;
15 import org.eclipse.jdt.annotation.NonNull;
16 import org.opendaylight.yangtools.yang.common.QName;
17 import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
18 import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier;
19 import org.opendaylight.yangtools.yang.model.api.stmt.SchemaTreeAwareEffectiveStatement;
20 import org.opendaylight.yangtools.yang.model.api.stmt.SchemaTreeEffectiveStatement;
21 import org.opendaylight.yangtools.yang.model.api.stmt.UnknownStatement;
22 import org.opendaylight.yangtools.yang.parser.spi.meta.StatementNamespace;
23 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
24 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContextUtils;
27 * Statement local namespace, which holds direct schema node descendants. This corresponds to the contents of the schema
28 * tree as exposed through {@link SchemaTreeAwareEffectiveStatement}.
30 // FIXME: 7.0.0: this contract seems to fall on the reactor side of things rather than parser-spi. Consider moving this
31 // into yang-(parser-)reactor-api.
33 public final class SchemaTreeNamespace<D extends DeclaredStatement<QName>, E extends SchemaTreeEffectiveStatement<D>>
34 extends StatementNamespace<QName, D, E> {
36 private static final long serialVersionUID = 1L;
37 private static final @NonNull SchemaTreeNamespace<?, ?> INSTANCE = new SchemaTreeNamespace<>();
39 private SchemaTreeNamespace() {
43 @SuppressWarnings("unchecked")
44 public static <D extends DeclaredStatement<QName>, E extends SchemaTreeEffectiveStatement<D>>
45 @NonNull SchemaTreeNamespace<D, E> instance() {
46 return (SchemaTreeNamespace<D, E>) INSTANCE;
50 * Find statement context identified by interpreting specified {@link SchemaNodeIdentifier} starting at specified
51 * {@link StmtContext}.
53 * @param root Search root context
54 * @param identifier {@link SchemaNodeIdentifier} relative to search root
55 * @return Matching statement context, if present.
56 * @throws NullPointerException if any of the arguments is null
58 public static Optional<StmtContext<?, ?, ?>> findNode(final StmtContext<?, ?, ?> root,
59 final SchemaNodeIdentifier identifier) {
60 final Iterator<QName> iterator = identifier.getNodeIdentifiers().iterator();
61 if (!iterator.hasNext()) {
62 return Optional.of(root);
65 QName nextPath = iterator.next();
66 StmtContext<?, ?, ?> current = root.getFromNamespace(SchemaTreeNamespace.INSTANCE, nextPath);
67 if (current == null) {
68 return Optional.ofNullable(tryToFindUnknownStatement(nextPath.getLocalName(), root));
70 while (current != null && iterator.hasNext()) {
71 nextPath = iterator.next();
72 final StmtContext<?, ?, ?> nextNodeCtx = current.getFromNamespace(SchemaTreeNamespace.INSTANCE, nextPath);
73 if (nextNodeCtx == null) {
74 return Optional.ofNullable(tryToFindUnknownStatement(nextPath.getLocalName(), current));
76 current = nextNodeCtx;
78 return Optional.ofNullable(current);
81 @SuppressWarnings("unchecked")
82 private static StmtContext<?, ?, ?> tryToFindUnknownStatement(final String localName,
83 final StmtContext<?, ?, ?> current) {
84 final Collection<? extends StmtContext<?, ?, ?>> unknownSubstatements = StmtContextUtils.findAllSubstatements(
85 current, UnknownStatement.class);
86 for (final StmtContext<?, ?, ?> unknownSubstatement : unknownSubstatements) {
87 if (localName.equals(unknownSubstatement.rawArgument())) {
88 return unknownSubstatement;