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%2FCurrentAdapterSerializer.java;h=c5b99844f2ce0c23528a1163b8ee9c634168fb11;hb=caa883d073dc41475a3153f406166910ba197c11;hp=d6ff0c336f25aae9e3949264578391d23a6f803c;hpb=cb0f3a767fa856c220edd674fda4d55dde408c64;p=mdsal.git diff --git a/binding/mdsal-binding-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/dom/adapter/CurrentAdapterSerializer.java b/binding/mdsal-binding-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/dom/adapter/CurrentAdapterSerializer.java index d6ff0c336f..c5b99844f2 100644 --- a/binding/mdsal-binding-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/dom/adapter/CurrentAdapterSerializer.java +++ b/binding/mdsal-binding-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/dom/adapter/CurrentAdapterSerializer.java @@ -13,39 +13,40 @@ import static java.util.Objects.requireNonNull; import com.google.common.annotations.Beta; import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.VerifyException; import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; -import com.google.common.collect.ImmutableBiMap; -import java.lang.reflect.Method; import java.util.Collection; import java.util.Map; import java.util.Map.Entry; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; import java.util.stream.Collectors; import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; import org.opendaylight.mdsal.binding.api.ActionSpec; import org.opendaylight.mdsal.binding.api.DataTreeIdentifier; import org.opendaylight.mdsal.binding.api.InstanceNotificationSpec; import org.opendaylight.mdsal.binding.dom.codec.spi.BindingDOMCodecServices; import org.opendaylight.mdsal.binding.dom.codec.spi.ForwardingBindingDOMCodecServices; -import org.opendaylight.mdsal.binding.runtime.api.BindingRuntimeContext; -import org.opendaylight.mdsal.binding.spec.naming.BindingMapping; -import org.opendaylight.mdsal.binding.spec.reflect.BindingReflections; +import org.opendaylight.mdsal.binding.model.api.JavaTypeName; +import org.opendaylight.mdsal.binding.runtime.api.ActionRuntimeType; +import org.opendaylight.mdsal.binding.runtime.api.InputRuntimeType; +import org.opendaylight.mdsal.binding.runtime.api.NotificationRuntimeType; +import org.opendaylight.mdsal.binding.runtime.api.RuntimeType; import org.opendaylight.mdsal.dom.api.DOMDataTreeIdentifier; +import org.opendaylight.yangtools.yang.binding.BindingContract; import org.opendaylight.yangtools.yang.binding.DataObject; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; -import org.opendaylight.yangtools.yang.binding.RpcService; -import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.common.QNameModule; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; -import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier; -import org.opendaylight.yangtools.yang.model.api.Module; -import org.opendaylight.yangtools.yang.model.api.RpcDefinition; import org.opendaylight.yangtools.yang.model.api.stmt.ActionEffectiveStatement; import org.opendaylight.yangtools.yang.model.api.stmt.ListEffectiveStatement; import org.opendaylight.yangtools.yang.model.api.stmt.NotificationEffectiveStatement; import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier.Absolute; +import org.opendaylight.yangtools.yang.model.api.stmt.SchemaTreeEffectiveStatement; import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -63,6 +64,7 @@ public final class CurrentAdapterSerializer extends ForwardingBindingDOMCodecSer } }); + private final ConcurrentMap extractors = new ConcurrentHashMap<>(); private final @NonNull BindingDOMCodecServices delegate; public CurrentAdapterSerializer(final BindingDOMCodecServices delegate) { @@ -83,7 +85,7 @@ public final class CurrentAdapterSerializer extends ForwardingBindingDOMCodecSer } DOMDataTreeIdentifier toDOMDataTreeIdentifier(final DataTreeIdentifier path) { - return new DOMDataTreeIdentifier(path.getDatastoreType(), toYangInstanceIdentifier(path.getRootIdentifier())); + return DOMDataTreeIdentifier.of(path.datastore(), toYangInstanceIdentifier(path.path())); } Collection toDOMDataTreeIdentifiers(final Collection> subtrees) { @@ -91,20 +93,62 @@ public final class CurrentAdapterSerializer extends ForwardingBindingDOMCodecSer } @NonNull Absolute getActionPath(final @NonNull ActionSpec spec) { - final var entry = resolvePath(spec.path()); - final var stack = entry.getKey(); - final var stmt = stack.enterSchemaTree(BindingReflections.findQName(spec.type()).bindTo(entry.getValue())); - verify(stmt instanceof ActionEffectiveStatement, "Action %s resolved to unexpected statement %s", spec, stmt); - return stack.toSchemaNodeIdentifier(); + return getSchemaNodeIdentifier(spec.path(), spec.type(), ActionRuntimeType.class, + ActionEffectiveStatement.class); } @NonNull Absolute getNotificationPath(final @NonNull InstanceNotificationSpec spec) { - final var entry = resolvePath(spec.path()); + return getSchemaNodeIdentifier(spec.path(), spec.type(), NotificationRuntimeType.class, + NotificationEffectiveStatement.class); + } + + private @NonNull Absolute getSchemaNodeIdentifier(final @NonNull InstanceIdentifier path, + final @NonNull Class> type, final @NonNull Class expectedRuntime, + final @NonNull Class> expectedStatement) { + final var typeName = JavaTypeName.create(type); + final var runtimeType = getRuntimeContext().getTypes().findSchema(typeName) + .orElseThrow(() -> new IllegalArgumentException(typeName + " is not known")); + final T casted; + try { + casted = expectedRuntime.cast(runtimeType); + } catch (ClassCastException e) { + throw new IllegalArgumentException(typeName + " resolved to unexpected " + runtimeType, e); + } + final var qname = expectedStatement.cast(casted.statement()).argument(); + + final var entry = resolvePath(path); final var stack = entry.getKey(); - final var stmt = stack.enterSchemaTree(BindingReflections.findQName(spec.type()).bindTo(entry.getValue())); - verify(stmt instanceof NotificationEffectiveStatement, "Notification %s resolved to unexpected statement %s", - spec, stmt); - return stack.toSchemaNodeIdentifier(); + final var stmt = stack.enterSchemaTree(qname.bindTo(entry.getValue())); + if (expectedStatement.isInstance(stmt)) { + return stack.toSchemaNodeIdentifier(); + } + throw new VerifyException(path + " child " + typeName + " resolved to unexpected statement" + stmt); + } + + @Nullable ContextReferenceExtractor findExtractor(final @NonNull InputRuntimeType inputType) { + final var inputName = inputType.getIdentifier(); + final var cached = extractors.get(inputName); + if (cached != null) { + return cached; + } + + // Load the class + final Class inputClass; + try { + inputClass = getRuntimeContext().loadClass(inputName); + } catch (ClassNotFoundException e) { + throw new IllegalArgumentException("Failed to load class for " + inputType, e); + } + + // Check if there is an extractor at all + final var created = ContextReferenceExtractor.of(inputClass); + if (created == null) { + return null; + } + + // Reconcile with cache + final var raced = extractors.putIfAbsent(inputName, created); + return raced != null ? raced : created; } private @NonNull Entry resolvePath(final @NonNull InstanceIdentifier path) { @@ -115,13 +159,6 @@ public final class CurrentAdapterSerializer extends ForwardingBindingDOMCodecSer QNameModule lastNamespace; do { final var arg = it.next(); - if (arg instanceof AugmentationIdentifier) { - final var augChildren = ((AugmentationIdentifier) arg).getPossibleChildNames(); - verify(!augChildren.isEmpty(), "Invalid empty augmentation %s", arg); - lastNamespace = augChildren.iterator().next().getModule(); - continue; - } - final var qname = arg.getNodeType(); final var stmt = stack.enterDataTree(qname); lastNamespace = qname.getModule(); @@ -138,55 +175,4 @@ public final class CurrentAdapterSerializer extends ForwardingBindingDOMCodecSer return Map.entry(stack, lastNamespace); } - - // FIXME: This should be probably part of Binding Runtime context - ImmutableBiMap getRpcMethodToSchema(final Class key) { - final Module module = getModule(key); - final ImmutableBiMap.Builder ret = ImmutableBiMap.builder(); - try { - for (final RpcDefinition rpcDef : module.getRpcs()) { - final Method method = findRpcMethod(key, rpcDef); - ret.put(method, rpcDef); - } - } catch (final NoSuchMethodException e) { - throw new IllegalStateException("Rpc defined in model does not have representation in generated class.", e); - } - return ret.build(); - } - - // FIXME: This should be probably part of Binding Runtime context - ImmutableBiMap getRpcMethodToQName(final Class key) { - final Module module = getModule(key); - final ImmutableBiMap.Builder ret = ImmutableBiMap.builder(); - try { - for (final RpcDefinition rpcDef : module.getRpcs()) { - final Method method = findRpcMethod(key, rpcDef); - ret.put(method,rpcDef.getQName()); - } - } catch (final NoSuchMethodException e) { - throw new IllegalStateException("Rpc defined in model does not have representation in generated class.", e); - } - return ret.build(); - } - - private Module getModule(final Class modeledClass) { - final QNameModule moduleName = BindingReflections.getQNameModule(modeledClass); - final BindingRuntimeContext localRuntimeContext = getRuntimeContext(); - final Module module = localRuntimeContext.getEffectiveModelContext().findModule(moduleName).orElse(null); - if (module != null) { - return module; - } - - LOG.trace("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 trace log", modeledClass, moduleName)); - } - - private Method findRpcMethod(final Class key, final RpcDefinition rpcDef) - throws NoSuchMethodException { - final var rpcName = rpcDef.getQName(); - final var inputClz = getRuntimeContext().getRpcInput(rpcName); - return key.getMethod(BindingMapping.getRpcMethodName(rpcName), inputClz); - } }