final var argType = arg.getType();
final var context = childNonNull(pathChildPrototype(argType), argType,
"Class %s is not valid child of %s", argType, getBindingClass())
- .get();
+ .getCodecContext();
if (context instanceof ChoiceCodecContext<?> choice) {
choice.addYangPathArgument(arg, builder);
return null;
}
final var caze = byYangCaseChild.get(first.name());
- return ((CaseCodecContext<D>) caze.get()).deserialize(data);
+ return ((CaseCodecContext<D>) caze.getCodecContext()).deserialize(data);
}
@Override
}
}
- return childNonNull(result, type, "Class %s is not child of any cases for %s", type, bindingArg()).get();
+ return childNonNull(result, type, "Class %s is not child of any cases for %s", type, bindingArg())
+ .getCodecContext();
}
/**
*/
package org.opendaylight.mdsal.binding.dom.codec.impl;
-import com.google.common.annotations.Beta;
import org.eclipse.jdt.annotation.NonNullByDefault;
/**
* Type capture of an entity producing NodeCodecContexts. Implementations are required to perform memoization. This
* interface does not form API surface and is exposed only for generated code. It can change at any time.
*/
-@Beta
-@FunctionalInterface
@NonNullByDefault
-public interface CodecContextSupplier {
- CodecContext get();
+sealed interface CodecContextSupplier permits LazyCodecContextSupplier, ValueNodeCodecContext {
+
+ CodecContext getCodecContext();
}
protected final Object codecMember(final VarHandle handle, final CodecContextSupplier supplier) {
final Object cached = handle.getAcquire(this);
- return cached != null ? unmaskNull(cached) : loadMember(handle, supplier.get());
+ return cached != null ? unmaskNull(cached) : loadMember(handle, supplier.getCodecContext());
}
protected final @NonNull Object codecMemberOrEmpty(final @Nullable Object value,
import static java.util.Objects.requireNonNull;
-import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
-import java.lang.invoke.MethodHandles;
-import java.lang.invoke.VarHandle;
import org.eclipse.jdt.annotation.NonNull;
import org.opendaylight.mdsal.binding.runtime.api.CompositeRuntimeType;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.Item;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
-abstract sealed class CommonDataObjectCodecPrototype<T extends CompositeRuntimeType> implements CodecContextSupplier
+abstract sealed class CommonDataObjectCodecPrototype<T extends CompositeRuntimeType>
+ extends LazyCodecContextSupplier<CommonDataObjectCodecContext<?, T>>
permits AugmentationCodecPrototype, DataObjectCodecPrototype {
- private static final VarHandle INSTANCE;
-
- static {
- try {
- INSTANCE = MethodHandles.lookup().findVarHandle(CommonDataObjectCodecPrototype.class,
- "instance", CommonDataObjectCodecContext.class);
- } catch (NoSuchFieldException | IllegalAccessException e) {
- throw new ExceptionInInitializerError(e);
- }
- }
-
private final @NonNull T type;
private final @NonNull CodecContextFactory factory;
private final @NonNull Item<?> bindingArg;
- // Accessed via INSTANCE
- @SuppressWarnings("unused")
- @SuppressFBWarnings(value = "UUF_UNUSED_FIELD", justification = "https://github.com/spotbugs/spotbugs/issues/2749")
- private volatile CommonDataObjectCodecContext<?, T> instance;
-
CommonDataObjectCodecPrototype(final Item<?> bindingArg, final T type, final CodecContextFactory factory) {
this.bindingArg = requireNonNull(bindingArg);
this.type = requireNonNull(type);
}
abstract @NonNull NodeIdentifier getYangArg();
-
- @Override
- public final CommonDataObjectCodecContext<?, T> get() {
- final var existing = (CommonDataObjectCodecContext<?, T>) INSTANCE.getAcquire(this);
- return existing != null ? existing : loadInstance();
- }
-
- private @NonNull CommonDataObjectCodecContext<?, T> loadInstance() {
- final var tmp = createInstance();
- final var witness = (CommonDataObjectCodecContext<?, T>) INSTANCE.compareAndExchangeRelease(this, null, tmp);
- return witness == null ? tmp : witness;
- }
-
- // This method must allow concurrent loading, i.e. nothing in it may have effects outside of the loaded object
- abstract @NonNull CommonDataObjectCodecContext<?, T> createInstance();
}
// FIXME: It really feels like we should be specializing DataContainerCodecPrototype so as to ditch
// createInstance() and then we could do an instanceof check instead.
if (childProto.getType() instanceof ChoiceRuntimeType) {
- final var choice = (ChoiceCodecContext<?>) childProto.get();
+ final var choice = (ChoiceCodecContext<?>) childProto.getCodecContext();
for (var cazeChild : choice.getCaseChildrenClasses()) {
byBindingArgClassBuilder.put(cazeChild, childProto);
}
} else {
supplier = null;
}
- return childNonNull(supplier, arg, "Argument %s is not valid child of %s", arg, getSchema()).get();
+ return childNonNull(supplier, arg, "Argument %s is not valid child of %s", arg, getSchema()).getCodecContext();
}
abstract @Nullable CodecContextSupplier yangChildSupplier(@NonNull NodeIdentifier arg);
@Override
public final <C extends DataObject> CommonDataObjectCodecContext<C, ?> streamChild(final Class<C> childClass) {
final var childProto = streamChildPrototype(requireNonNull(childClass));
- return childProto == null ? null : (CommonDataObjectCodecContext<C, ?>) childProto.get();
+ return childProto == null ? null : (CommonDataObjectCodecContext<C, ?>) childProto.getCodecContext();
}
abstract @Nullable CommonDataObjectCodecPrototype<?> streamChildPrototype(@NonNull Class<?> childClass);
final var bindingClass = entry.getKey();
final var codecProto = augmentToPrototype.get(bindingClass);
if (codecProto != null) {
- final var bindingObj = codecProto.get().deserializeObject(entry.getValue().build());
+ final var bindingObj = codecProto.getCodecContext().deserializeObject(entry.getValue().build());
if (bindingObj != null) {
map.put(bindingClass, bindingObj);
}
--- /dev/null
+/*
+ * Copyright (c) 2024 PANTHEON.tech, s.r.o. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.mdsal.binding.dom.codec.impl;
+
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import org.eclipse.jdt.annotation.NonNull;
+
+/**
+ * Abstract base class for lazily-instantiated {@link CodecContextSupplier} instances.
+ *
+ * @param <C> {@link CodecContext} type
+ */
+public abstract sealed class LazyCodecContextSupplier<C extends CodecContext> implements CodecContextSupplier
+ permits CommonDataObjectCodecPrototype {
+ private static final VarHandle INSTANCE;
+
+ static {
+ try {
+ INSTANCE = MethodHandles.lookup().findVarHandle(LazyCodecContextSupplier.class, "instance",
+ CodecContext.class);
+ } catch (NoSuchFieldException | IllegalAccessException e) {
+ throw new ExceptionInInitializerError(e);
+ }
+ }
+
+ // Accessed via INSTANCE
+ @SuppressWarnings("unused")
+ @SuppressFBWarnings(value = "UUF_UNUSED_FIELD", justification = "https://github.com/spotbugs/spotbugs/issues/2749")
+ private volatile C instance;
+
+ @Override
+ public final C getCodecContext() {
+ final var existing = (C) INSTANCE.getAcquire(this);
+ return existing != null ? existing : loadInstance();
+ }
+
+ private @NonNull C loadInstance() {
+ final var tmp = createInstance();
+ final var witness = (C) INSTANCE.compareAndExchangeRelease(this, null, tmp);
+ return witness == null ? tmp : witness;
+ }
+
+ // This method must allow concurrent loading, i.e. nothing in it may have effects outside of the loaded object
+ abstract @NonNull C createInstance();
+}
}
@Override
- public final CodecContext get() {
+ public final CodecContext getCodecContext() {
return this;
}