X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=binding%2Fmdsal-binding-dom-adapter%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fmdsal%2Fbinding%2Fdom%2Fadapter%2FBindingToNormalizedNodeCodec.java;h=55fde2cd655b19b5e47517d3ca0ec7895f84cf50;hb=6e6ebc43866204667658f8bbf7cfb6233caffdc7;hp=9648fedf7318b7272a05939baa9bdd540b19cdae;hpb=3c4c7866da0788014b9ce1ed81ea63683cfa8e51;p=mdsal.git diff --git a/binding/mdsal-binding-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/dom/adapter/BindingToNormalizedNodeCodec.java b/binding/mdsal-binding-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/dom/adapter/BindingToNormalizedNodeCodec.java index 9648fedf73..55fde2cd65 100644 --- a/binding/mdsal-binding-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/dom/adapter/BindingToNormalizedNodeCodec.java +++ b/binding/mdsal-binding-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/dom/adapter/BindingToNormalizedNodeCodec.java @@ -7,12 +7,10 @@ */ package org.opendaylight.mdsal.binding.dom.adapter; +import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkState; import static java.util.Objects.requireNonNull; -import com.google.common.base.Function; -import com.google.common.base.Optional; -import com.google.common.base.Preconditions; import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; @@ -20,44 +18,54 @@ import com.google.common.collect.ImmutableBiMap; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Iterators; import java.lang.reflect.Method; +import java.time.Instant; import java.util.AbstractMap.SimpleEntry; import java.util.Collection; import java.util.HashSet; import java.util.Map.Entry; +import java.util.Optional; import java.util.Set; import java.util.concurrent.TimeUnit; +import java.util.function.Function; import java.util.stream.Collectors; -import javassist.ClassPool; -import javax.annotation.Nonnull; +import javax.annotation.PreDestroy; +import javax.inject.Inject; +import javax.inject.Singleton; +import org.eclipse.jdt.annotation.NonNull; import org.opendaylight.mdsal.binding.api.DataTreeIdentifier; import org.opendaylight.mdsal.binding.dom.codec.api.BindingCodecTree; import org.opendaylight.mdsal.binding.dom.codec.api.BindingCodecTreeFactory; import org.opendaylight.mdsal.binding.dom.codec.api.BindingCodecTreeNode; +import org.opendaylight.mdsal.binding.dom.codec.api.BindingDataObjectCodecTreeNode; +import org.opendaylight.mdsal.binding.dom.codec.api.BindingLazyContainerNode; import org.opendaylight.mdsal.binding.dom.codec.api.BindingNormalizedNodeSerializer; -import org.opendaylight.mdsal.binding.dom.codec.gen.impl.StreamWriterGenerator; import org.opendaylight.mdsal.binding.dom.codec.impl.BindingNormalizedNodeCodecRegistry; import org.opendaylight.mdsal.binding.dom.codec.impl.MissingSchemaException; import org.opendaylight.mdsal.binding.generator.api.ClassLoadingStrategy; import org.opendaylight.mdsal.binding.generator.util.BindingRuntimeContext; -import org.opendaylight.mdsal.binding.generator.util.JavassistUtils; +import org.opendaylight.mdsal.binding.spec.naming.BindingMapping; +import org.opendaylight.mdsal.binding.spec.reflect.BindingReflections; import org.opendaylight.mdsal.dom.api.DOMDataTreeIdentifier; import org.opendaylight.mdsal.dom.api.DOMSchemaService; import org.opendaylight.yangtools.concepts.ListenerRegistration; -import org.opendaylight.yangtools.yang.binding.BindingMapping; +import org.opendaylight.yangtools.yang.binding.Action; import org.opendaylight.yangtools.yang.binding.DataContainer; import org.opendaylight.yangtools.yang.binding.DataObject; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument; import org.opendaylight.yangtools.yang.binding.Notification; +import org.opendaylight.yangtools.yang.binding.RpcInput; +import org.opendaylight.yangtools.yang.binding.RpcOutput; import org.opendaylight.yangtools.yang.binding.RpcService; -import org.opendaylight.yangtools.yang.binding.util.BindingReflections; import org.opendaylight.yangtools.yang.common.QNameModule; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; +import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier; import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode; import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; import org.opendaylight.yangtools.yang.data.impl.codec.DeserializationException; import org.opendaylight.yangtools.yang.data.impl.schema.Builders; import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes; +import org.opendaylight.yangtools.yang.model.api.ActionDefinition; import org.opendaylight.yangtools.yang.model.api.DocumentedNode.WithStatus; import org.opendaylight.yangtools.yang.model.api.ListSchemaNode; import org.opendaylight.yangtools.yang.model.api.Module; @@ -76,6 +84,7 @@ import org.slf4j.LoggerFactory; *

* NOTE: this class is non-final to allow controller adapter migration without duplicated code. */ +@Singleton public class BindingToNormalizedNodeCodec implements BindingCodecTreeFactory, BindingNormalizedNodeSerializer, SchemaContextListener, AutoCloseable { @@ -85,7 +94,7 @@ public class BindingToNormalizedNodeCodec implements BindingCodecTreeFactory, private final LoadingCache, YangInstanceIdentifier> iiCache = CacheBuilder.newBuilder() .softValues().build(new CacheLoader, YangInstanceIdentifier>() { @Override - public YangInstanceIdentifier load(@Nonnull final InstanceIdentifier key) { + public YangInstanceIdentifier load(final InstanceIdentifier key) { return toYangInstanceIdentifierBlocking(key); } }); @@ -94,6 +103,7 @@ public class BindingToNormalizedNodeCodec implements BindingCodecTreeFactory, private final FutureSchema futureSchema; private ListenerRegistration listenerRegistration; + @Inject public BindingToNormalizedNodeCodec(final ClassLoadingStrategy classLoadingStrategy, final BindingNormalizedNodeCodecRegistry codecRegistry) { this(classLoadingStrategy, codecRegistry, false); @@ -101,15 +111,14 @@ public class BindingToNormalizedNodeCodec implements BindingCodecTreeFactory, public BindingToNormalizedNodeCodec(final ClassLoadingStrategy classLoadingStrategy, final BindingNormalizedNodeCodecRegistry codecRegistry, final boolean waitForSchema) { - this.classLoadingStrategy = Preconditions.checkNotNull(classLoadingStrategy, "classLoadingStrategy"); - this.codecRegistry = Preconditions.checkNotNull(codecRegistry, "codecRegistry"); + this.classLoadingStrategy = requireNonNull(classLoadingStrategy, "classLoadingStrategy"); + this.codecRegistry = requireNonNull(codecRegistry, "codecRegistry"); this.futureSchema = FutureSchema.create(WAIT_DURATION_SEC, TimeUnit.SECONDS, waitForSchema); } public static BindingToNormalizedNodeCodec newInstance(final ClassLoadingStrategy classLoadingStrategy, final DOMSchemaService schemaService) { - final BindingNormalizedNodeCodecRegistry codecRegistry = new BindingNormalizedNodeCodecRegistry( - StreamWriterGenerator.create(JavassistUtils.forClassPool(ClassPool.getDefault()))); + final BindingNormalizedNodeCodecRegistry codecRegistry = new BindingNormalizedNodeCodecRegistry(); BindingToNormalizedNodeCodec instance = new BindingToNormalizedNodeCodec( classLoadingStrategy, codecRegistry, true); instance.listenerRegistration = schemaService.registerSchemaContextListener(instance); @@ -141,7 +150,7 @@ public class BindingToNormalizedNodeCodec implements BindingCodecTreeFactory, } @Override - public final YangInstanceIdentifier toYangInstanceIdentifier(@Nonnull final InstanceIdentifier binding) { + public final YangInstanceIdentifier toYangInstanceIdentifier(final InstanceIdentifier binding) { return codecRegistry.toYangInstanceIdentifier(binding); } @@ -177,57 +186,97 @@ public class BindingToNormalizedNodeCodec implements BindingCodecTreeFactory, } @Override - public final Entry, DataObject> fromNormalizedNode(@Nonnull final YangInstanceIdentifier path, + public final Entry, DataObject> fromNormalizedNode(final YangInstanceIdentifier path, final NormalizedNode data) { return codecRegistry.fromNormalizedNode(path, data); } @Override - public final Notification fromNormalizedNodeNotification(@Nonnull final SchemaPath path, - @Nonnull final ContainerNode data) { + public final Notification fromNormalizedNodeNotification(final SchemaPath path, final ContainerNode data) { return codecRegistry.fromNormalizedNodeNotification(path, data); } @Override - public final DataObject fromNormalizedNodeRpcData(@Nonnull final SchemaPath path, - @Nonnull final ContainerNode data) { + public final Notification fromNormalizedNodeNotification(final SchemaPath path, final ContainerNode data, + final Instant eventInstant) { + return codecRegistry.fromNormalizedNodeNotification(path, data, eventInstant); + } + + @Override + public final DataObject fromNormalizedNodeRpcData(final SchemaPath path, final ContainerNode data) { return codecRegistry.fromNormalizedNodeRpcData(path, data); } @Override - public final InstanceIdentifier fromYangInstanceIdentifier(@Nonnull final YangInstanceIdentifier dom) { + public T fromNormalizedNodeActionInput(final Class> action, + final ContainerNode input) { + return codecRegistry.fromNormalizedNodeActionInput(action, input); + } + + @Override + public T fromNormalizedNodeActionOutput(final Class> action, + final ContainerNode output) { + return codecRegistry.fromNormalizedNodeActionOutput(action, output); + } + + @Override + public final InstanceIdentifier fromYangInstanceIdentifier(final YangInstanceIdentifier dom) { return codecRegistry.fromYangInstanceIdentifier(dom); } @Override - public final ContainerNode toNormalizedNodeNotification(@Nonnull final Notification data) { + public final ContainerNode toNormalizedNodeNotification(final Notification data) { return codecRegistry.toNormalizedNodeNotification(data); } @Override - public final ContainerNode toNormalizedNodeRpcData(@Nonnull final DataContainer data) { + public final ContainerNode toNormalizedNodeRpcData(final DataContainer data) { return codecRegistry.toNormalizedNodeRpcData(data); } + @Override + public ContainerNode toNormalizedNodeActionInput(final Class> action, + final RpcInput input) { + return codecRegistry.toNormalizedNodeActionInput(action, input); + } + + @Override + public ContainerNode toNormalizedNodeActionOutput(final Class> action, + final RpcOutput output) { + return codecRegistry.toNormalizedNodeActionOutput(action, output); + } + + @Override + public BindingLazyContainerNode toLazyNormalizedNodeActionInput( + final Class> action, final NodeIdentifier identifier, final RpcInput input) { + return codecRegistry.toLazyNormalizedNodeActionInput(action, identifier, input); + } + + @Override + public BindingLazyContainerNode toLazyNormalizedNodeActionOutput( + final Class> action, final NodeIdentifier identifier, final RpcOutput output) { + return codecRegistry.toLazyNormalizedNodeActionOutput(action, identifier, output); + } + /** * Returns a Binding-Aware instance identifier from normalized * instance-identifier if it is possible to create representation. * *

- * Returns Optional.absent for cases where target is mixin node except + * Returns Optional.empty for cases where target is mixin node except * augmentation. */ public final Optional> toBinding(final YangInstanceIdentifier normalized) throws DeserializationException { try { - return Optional.fromNullable(codecRegistry.fromYangInstanceIdentifier(normalized)); + return Optional.ofNullable(codecRegistry.fromYangInstanceIdentifier(normalized)); } catch (final IllegalArgumentException e) { - return Optional.absent(); + return Optional.empty(); } } public final Optional, DataObject>> toBinding( - @Nonnull final Entry> normalized) + final @NonNull Entry> normalized) throws DeserializationException { try { /* @@ -247,9 +296,9 @@ public class BindingToNormalizedNodeCodec implements BindingCodecTreeFactory, @SuppressWarnings("unchecked") final Entry, DataObject> binding = Entry.class.cast( codecRegistry.fromNormalizedNode(normalized.getKey(), normalized.getValue())); - return Optional.fromNullable(binding); + return Optional.ofNullable(binding); } catch (final IllegalArgumentException e) { - return Optional.absent(); + return Optional.empty(); } } @@ -260,9 +309,15 @@ public class BindingToNormalizedNodeCodec implements BindingCodecTreeFactory, futureSchema.onRuntimeContextUpdated(runtimeContext); } + /** + * Deprecated. + * + * @deprecated Use {@link BindingNormalizedNodeCodecRegistry#deserializeFunction} instead. + */ + @Deprecated public final Function>, Optional> deserializeFunction( final InstanceIdentifier path) { - return codecRegistry.deserializeFunction(path); + return codecRegistry.deserializeFunction(path)::apply; } public final BindingNormalizedNodeCodecRegistry getCodecRegistry() { @@ -270,6 +325,7 @@ public class BindingToNormalizedNodeCodec implements BindingCodecTreeFactory, } @Override + @PreDestroy public void close() { if (listenerRegistration != null) { listenerRegistration.close(); @@ -316,12 +372,17 @@ public class BindingToNormalizedNodeCodec implements BindingCodecTreeFactory, localRuntimeContext.getSchemaContext().findModule(moduleName).orElse(null); if (module == null && futureSchema.waitForSchema(moduleName)) { localRuntimeContext = runtimeContext(); - Preconditions.checkState(localRuntimeContext != null, "BindingRuntimeContext is not available."); + checkState(localRuntimeContext != null, "BindingRuntimeContext is not available."); module = localRuntimeContext.getSchemaContext().findModule(moduleName).orElse(null); } - checkState(module != null, "Schema for %s is not available; expected module name: %s.", modeledClass, - moduleName); - return module; + if (module != null) { + return module; + } + + LOG.debug("Schema for {} is not available; expected module name: {}; BindingRuntimeContext: {}", + modeledClass, moduleName, localRuntimeContext); + throw new IllegalStateException(String.format("Schema for %s is not available; expected module name: %s; " + + "full BindingRuntimeContext available in debug log", modeledClass, moduleName)); } private void waitForSchema(final Collection> binding, final MissingSchemaException exception) { @@ -334,7 +395,7 @@ public class BindingToNormalizedNodeCodec implements BindingCodecTreeFactory, private Method findRpcMethod(final Class key, final RpcDefinition rpcDef) throws NoSuchMethodException { - final String methodName = BindingMapping.getMethodName(rpcDef.getQName()); + final String methodName = BindingMapping.getRpcMethodName(rpcDef.getQName()); final Class inputClz = runtimeContext().getClassForSchema(rpcDef.getInput()); return key.getMethod(methodName, inputClz); } @@ -349,18 +410,17 @@ public class BindingToNormalizedNodeCodec implements BindingCodecTreeFactory, return codecRegistry.create(context, bindingClasses); } - @Nonnull - protected Entry, BindingCodecTreeNode> getSubtreeCodec( + protected @NonNull Entry, BindingDataObjectCodecTreeNode> getSubtreeCodec( final YangInstanceIdentifier domIdentifier) { final BindingCodecTree currentCodecTree = codecRegistry.getCodecContext(); final InstanceIdentifier bindingPath = codecRegistry.fromYangInstanceIdentifier(domIdentifier); - Preconditions.checkArgument(bindingPath != null); + checkArgument(bindingPath != null); /** * If we are able to deserialize YANG instance identifier, getSubtreeCodec must * return non-null value. */ - final BindingCodecTreeNode codecContext = currentCodecTree.getSubtreeCodec(bindingPath); + final BindingDataObjectCodecTreeNode codecContext = currentCodecTree.getSubtreeCodec(bindingPath); return new SimpleEntry<>(bindingPath, codecContext); } @@ -381,6 +441,12 @@ public class BindingToNormalizedNodeCodec implements BindingCodecTreeFactory, return result; } + SchemaPath getActionPath(final Class> type) { + final ActionDefinition schema = runtimeContext().getActionDefinition(type); + checkArgument(schema != null, "Failed to find schema for %s", type); + return schema.getPath(); + } + private BindingRuntimeContext runtimeContext() { return futureSchema.runtimeContext(); } @@ -393,8 +459,16 @@ public class BindingToNormalizedNodeCodec implements BindingCodecTreeFactory, return ImmutableNodes.fromInstanceId(runtimeContext().getSchemaContext(), parentPath); } + /** + * This method creates an empty list container of a particular type. + * + * @deprecated This method is not generally useful, as empty lists do not convey information in YANG (they are + * equivalent to non-present lists). It also leaks implementation details to a broader scope and should + * never have been public in the first place. + */ + @Deprecated public NormalizedNode getDefaultNodeFor(final YangInstanceIdentifier parentMapPath) { - final BindingCodecTreeNode mapCodec = requireNonNull( + final BindingCodecTreeNode mapCodec = requireNonNull( codecRegistry.getCodecContext().getSubtreeCodec(parentMapPath), "Codec not found for yang instance identifier: " + parentMapPath); final WithStatus schema = mapCodec.getSchema();