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=cad0c4fda686a081f4071a41ec026dfb696bdba3;hb=77d4d3fb01c2164be405b683d2df7f9662884e2c;hp=ac1a6fec292e529cd8c3f0053d205fd2e8b7ecff;hpb=39d6eb62e31264d4528f20794c3b6ed3a8d14511;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 ac1a6fec29..cad0c4fda6 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 @@ -16,37 +16,32 @@ import com.google.common.annotations.VisibleForTesting; 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.runtime.api.RpcRuntimeType; -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.dom.api.DOMDataTreeIdentifier; 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.RpcEffectiveStatement; import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier.Absolute; import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack; import org.slf4j.Logger; @@ -65,6 +60,7 @@ public final class CurrentAdapterSerializer extends ForwardingBindingDOMCodecSer } }); + private final ConcurrentMap extractors = new ConcurrentHashMap<>(); private final @NonNull BindingDOMCodecServices delegate; public CurrentAdapterSerializer(final BindingDOMCodecServices delegate) { @@ -85,7 +81,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) { @@ -93,22 +89,60 @@ public final class CurrentAdapterSerializer extends ForwardingBindingDOMCodecSer } @NonNull Absolute getActionPath(final @NonNull ActionSpec spec) { + final var type = getRuntimeContext().getTypes().findSchema(JavaTypeName.create(spec.type())) + .orElseThrow(() -> new IllegalArgumentException("Action " + spec + " is not known")); + if (!(type instanceof ActionRuntimeType actionType)) { + throw new IllegalArgumentException("Action " + spec + " resolved to unexpected " + type); + } + final var entry = resolvePath(spec.path()); final var stack = entry.getKey(); - final var stmt = stack.enterSchemaTree(BindingReflections.findQName(spec.type()).bindTo(entry.getValue())); + final var stmt = stack.enterSchemaTree(actionType.statement().argument().bindTo(entry.getValue())); verify(stmt instanceof ActionEffectiveStatement, "Action %s resolved to unexpected statement %s", spec, stmt); return stack.toSchemaNodeIdentifier(); } @NonNull Absolute getNotificationPath(final @NonNull InstanceNotificationSpec spec) { + final var type = getRuntimeContext().getTypes().findSchema(JavaTypeName.create(spec.type())) + .orElseThrow(() -> new IllegalArgumentException("Notification " + spec + " is not known")); + if (!(type instanceof NotificationRuntimeType notifType)) { + throw new IllegalArgumentException("Notification " + spec + " resolved to unexpected " + type); + } + final var entry = resolvePath(spec.path()); final var stack = entry.getKey(); - final var stmt = stack.enterSchemaTree(BindingReflections.findQName(spec.type()).bindTo(entry.getValue())); + final var stmt = stack.enterSchemaTree(notifType.statement().argument().bindTo(entry.getValue())); verify(stmt instanceof NotificationEffectiveStatement, "Notification %s resolved to unexpected statement %s", spec, stmt); return stack.toSchemaNodeIdentifier(); } + @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) { final var stack = SchemaInferenceStack.of(getRuntimeContext().getEffectiveModelContext()); final var it = toYangInstanceIdentifier(path).getPathArguments().iterator(); @@ -117,13 +151,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(); @@ -140,72 +167,4 @@ public final class CurrentAdapterSerializer extends ForwardingBindingDOMCodecSer return Map.entry(stack, lastNamespace); } - - // FIXME: This should be probably part of Binding Runtime context and RpcServices perhaps should have their own - // RuntimeType - ImmutableBiMap getRpcMethodToSchema(final Class key) { - final var runtimeContext = getRuntimeContext(); - final var types = runtimeContext.getTypes(); - final var qnameModule = BindingReflections.getQNameModule(key); - - // We are dancing a bit here to reconstruct things a RpcServiceRuntimeType could easily hold - final var module = runtimeContext.getEffectiveModelContext().findModuleStatement(qnameModule) - .orElseThrow(() -> new IllegalStateException("No module found for " + qnameModule + " service " + key)); - return module.streamEffectiveSubstatements(RpcEffectiveStatement.class) - .map(rpc -> { - final var rpcName = rpc.argument(); - final var inputClz = runtimeContext.getRpcInput(rpcName); - final var methodName = BindingMapping.getRpcMethodName(rpcName); - - final Method method; - try { - method = key.getMethod(methodName, inputClz); - } catch (NoSuchMethodException e) { - throw new IllegalStateException("Cannot find RPC method for " + rpc, e); - } - - final var type = types.schemaTreeChild(rpcName); - if (!(type instanceof RpcRuntimeType rpcType)) { - throw new IllegalStateException("Unexpected run-time type " + type + " for " + rpcName); - } - return Map.entry(method, rpcType); - }) - .collect(ImmutableBiMap.toImmutableBiMap(Entry::getKey, Entry::getValue)); - } - - // 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); - } }