2 * Copyright (c) 2023 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.impl;
10 import com.google.common.base.VerifyException;
11 import java.lang.invoke.MethodHandle;
12 import java.lang.invoke.MethodHandles;
13 import java.lang.invoke.MethodType;
14 import java.lang.reflect.Method;
15 import java.util.List;
16 import org.eclipse.jdt.annotation.NonNull;
17 import org.opendaylight.mdsal.binding.runtime.api.AugmentRuntimeType;
18 import org.opendaylight.mdsal.binding.runtime.api.AugmentableRuntimeType;
19 import org.opendaylight.mdsal.binding.runtime.api.CompositeRuntimeType;
20 import org.opendaylight.yangtools.yang.binding.Augmentable;
21 import org.opendaylight.yangtools.yang.binding.DataObject;
22 import org.opendaylight.yangtools.yang.data.api.schema.DataContainerNode;
25 * Analysis of a {@link DataObject} specialization class. The primary point of this class is to separate out creation
26 * indices needed for {@link #proxyConstructor}. Since we want to perform as much indexing as possible in a single pass,
27 * we also end up indexing things that are not strictly required to arrive at that constructor.
29 final class CodecDataObjectAnalysis<R extends CompositeRuntimeType> extends AbstractDataContainerAnalysis<R> {
30 private static final MethodType CONSTRUCTOR_TYPE = MethodType.methodType(void.class,
31 AbstractDataObjectCodecContext.class, DataContainerNode.class);
32 private static final MethodType DATAOBJECT_TYPE = MethodType.methodType(DataObject.class,
33 AbstractDataObjectCodecContext.class, DataContainerNode.class);
35 final @NonNull Class<? extends CodecDataObject<?>> generatedClass;
36 final @NonNull List<AugmentRuntimeType> possibleAugmentations;
37 final @NonNull MethodHandle proxyConstructor;
39 CodecDataObjectAnalysis(final CommonDataObjectCodecPrototype<R> prototype, final CodecItemFactory itemFactory,
40 final Method keyMethod) {
41 this(prototype.getBindingClass(), prototype.getType(), prototype.getFactory(), itemFactory, keyMethod);
44 CodecDataObjectAnalysis(final Class<?> bindingClass, final R runtimeType, final CodecContextFactory factory,
45 final CodecItemFactory itemFactory, final Method keyMethod) {
46 super(bindingClass, runtimeType, factory, itemFactory);
48 // Final bits: generate the appropriate class, As a side effect we identify what Augmentations are possible
49 if (Augmentable.class.isAssignableFrom(bindingClass)) {
50 // Verify we have the appropriate backing runtimeType
51 if (!(runtimeType instanceof AugmentableRuntimeType augmentableRuntimeType)) {
52 throw new VerifyException(
53 "Unexpected type %s backing augmenable %s".formatted(runtimeType, bindingClass));
56 possibleAugmentations = augmentableRuntimeType.augments();
57 generatedClass = CodecDataObjectGenerator.generateAugmentable(factory.getLoader(), bindingClass,
58 leafContexts, daoProperties, keyMethod);
60 possibleAugmentations = List.of();
61 generatedClass = CodecDataObjectGenerator.generate(factory.getLoader(), bindingClass, leafContexts,
62 daoProperties, keyMethod);
65 // All done: acquire the constructor: it is supposed to be public
66 final MethodHandle ctor;
68 ctor = MethodHandles.publicLookup().findConstructor(generatedClass, CONSTRUCTOR_TYPE);
69 } catch (NoSuchMethodException | IllegalAccessException e) {
70 throw new LinkageError("Failed to find contructor for class " + generatedClass, e);
73 proxyConstructor = ctor.asType(DATAOBJECT_TYPE);