Refactor RpcRoutingStrategy
[mdsal.git] / dom / mdsal-dom-spi / src / main / java / org / opendaylight / mdsal / dom / spi / ContentRoutedRpcContext.java
1 /*
2  * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
3  * Copyright (c) 2022 PANTHEON.tech, s.r.o.
4  *
5  * This program and the accompanying materials are made available under the
6  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
7  * and is available at http://www.eclipse.org/legal/epl-v10.html
8  */
9 package org.opendaylight.mdsal.dom.spi;
10
11 import static java.util.Objects.requireNonNull;
12
13 import org.eclipse.jdt.annotation.NonNull;
14 import org.eclipse.jdt.annotation.Nullable;
15 import org.opendaylight.yangtools.odlext.model.api.ContextReferenceEffectiveStatement;
16 import org.opendaylight.yangtools.yang.common.QName;
17 import org.opendaylight.yangtools.yang.model.api.stmt.InputEffectiveStatement;
18 import org.opendaylight.yangtools.yang.model.api.stmt.RpcEffectiveStatement;
19 import org.opendaylight.yangtools.yang.model.api.stmt.SchemaTreeEffectiveStatement;
20
21 /**
22  * Information pertaining to the concept of {@code Routed RPCs}. "Routed" in this context means being bound to a certain
23  * data tree node, identified by a {@code leaf} within the RPC input. This is very much similar to a RFC7950
24  * {@code action}, except it operates strictly within the confines of RFC6020.
25  *
26  * @param identity QName which refers RPC Routing context {@code identity}
27  * @param leaf QName of the leaf in which RPC Route is stored
28  */
29 public record ContentRoutedRpcContext(@NonNull QName identity, @NonNull QName leaf) {
30     public ContentRoutedRpcContext {
31         requireNonNull(identity);
32         requireNonNull(identity);
33     }
34
35     /**
36      * Attempt to construct a {@link ContentRoutedRpcContext} for a particular {@code rpc}.
37      *
38      * @param rpc RPC statement
39      * @return A {@link ContentRoutedRpcContext}, or {@code null} if the RPC does not contain context information
40      */
41     public static @Nullable ContentRoutedRpcContext forRpc(final RpcEffectiveStatement rpc) {
42         final var input = rpc.findFirstEffectiveSubstatement(InputEffectiveStatement.class)
43             .orElseThrow(() -> new IllegalArgumentException("Cannot find input in " + rpc));
44
45         for (var stmt : input.effectiveSubstatements()) {
46             // TODO: LeafEffectiveStatement instead? Because that is what we are promising for #leaf()'s QName
47             if (stmt instanceof SchemaTreeEffectiveStatement<?> schemaStmt) {
48                 final var context =
49                     stmt.findFirstEffectiveSubstatementArgument(ContextReferenceEffectiveStatement.class);
50                 if (context.isPresent()) {
51                     return new ContentRoutedRpcContext(context.orElseThrow(), schemaStmt.argument());
52                 }
53             }
54         }
55
56         return null;
57     }
58 }