Split out BindingDataObjectCodecTreeNode.streamChild()
[mdsal.git] / binding / mdsal-binding-dom-codec-api / src / main / java / org / opendaylight / mdsal / binding / dom / codec / api / BindingDataObjectCodecTreeParent.java
1 /*
2  * Copyright (c) 2022 PANTHEON.tech, 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.mdsal.binding.dom.codec.api;
9
10 import com.google.common.annotations.Beta;
11 import org.eclipse.jdt.annotation.NonNull;
12 import org.opendaylight.yangtools.yang.binding.ChoiceIn;
13 import org.opendaylight.yangtools.yang.binding.DataObject;
14
15 /**
16  * Common interface for entities which can supply a {@link BindingDataObjectCodecTreeNode} based on Binding DataObject
17  * class instance.
18  *
19  * @param <T> Dummy parameter to work around problems with streaming {@link ChoiceIn} classes. Essentially we want
20  *            {@link #streamChild(Class)} to also service such classes, which are not {@link DataObject}s. The problem
21  *            really is that {@code case} interfaces are DataObjects and hence are an alluring target for that method.
22  *            The workaround works with two sides:
23  *            <ul>
24  *              <li>Here the fact that we are generic means that binary compatibility dictates that our signature be
25  *                  backwards compatible with anyone who might have seen us as non-generic, i.e. in streamChild() taking
26  *                  a raw class (because there were no generics)</li>
27  *              <li>Users pick it up from there: all they need to do is to go to raw types, then accepts any class, but
28  *                  from there we can just chain on method return, arriving into a type-safe world again</li>
29  *            </ul>
30  */
31 @Beta
32 // FIXME: Now the above documentation is fine and dandy, but can we adjust the shape of our classes somehow?
33 //        The problem seems to be grouping interfaces, which are pulling in 'DataObject' to the picture and thus
34 //        and up marking case statements even if we do not mark them specially. If we could disconnect concrete cases
35 //        from DataObject in a civil manner, then we could go the DataObject -> ChoiceIn -> CaseOf and not have
36 //        choice/case statements in the picture. But what would that do to all the concepts hanging off of DataObject?
37 public interface BindingDataObjectCodecTreeParent<T> {
38     /**
39      * Returns child context as if it was walked by {@link BindingStreamEventWriter}. This means that to enter case,
40      * one must issue {@code streamChild(ChoiceClass).streamChild(CaseClass)}.
41      *
42      * @param <E> Stream child DataObject type
43      * @param childClass Child class by Binding Stream navigation
44      * @return Context of child
45      * @throws IllegalArgumentException If supplied child class is not valid in specified context.
46      */
47     <E extends DataObject> @NonNull BindingDataObjectCodecTreeNode<E> streamChild(@NonNull Class<E> childClass);
48 }