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