From dea4adf5b8e3101ca6efc2470e00b2a14cfebdb6 Mon Sep 17 00:00:00 2001 From: Tony Tkacik Date: Wed, 16 Jul 2014 12:58:21 +0200 Subject: [PATCH] Bug 1093: Extracted static inner classes from SchemaAwareRpcBroker. Change-Id: I68bc1d3e4a3b279877e5ece19bcc9e1bfcd0c3dc Signed-off-by: Tony Tkacik --- .../broker/impl/GlobalRpcRegistration.java | 38 +++ .../sal/dom/broker/impl/RoutedRpcRegImpl.java | 48 +++ .../dom/broker/impl/RoutedRpcSelector.java | 104 +++++++ .../dom/broker/impl/SchemaAwareRpcBroker.java | 279 ++---------------- .../broker/spi/rpc/RpcRoutingStrategy.java | 142 +++++++++ 5 files changed, 361 insertions(+), 250 deletions(-) create mode 100644 opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/GlobalRpcRegistration.java create mode 100644 opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/RoutedRpcRegImpl.java create mode 100644 opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/RoutedRpcSelector.java create mode 100644 opendaylight/md-sal/sal-dom-spi/src/main/java/org/opendaylight/controller/md/sal/dom/broker/spi/rpc/RpcRoutingStrategy.java diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/GlobalRpcRegistration.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/GlobalRpcRegistration.java new file mode 100644 index 0000000000..f63e5ea768 --- /dev/null +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/GlobalRpcRegistration.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2014 Cisco Systems, Inc. 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.controller.sal.dom.broker.impl; + +import org.opendaylight.controller.sal.core.api.Broker.RpcRegistration; +import org.opendaylight.controller.sal.core.api.RpcImplementation; +import org.opendaylight.yangtools.concepts.AbstractObjectRegistration; +import org.opendaylight.yangtools.yang.common.QName; + +class GlobalRpcRegistration extends AbstractObjectRegistration implements + RpcRegistration { + private final QName type; + private SchemaAwareRpcBroker router; + + public GlobalRpcRegistration(final QName type, final RpcImplementation instance, final SchemaAwareRpcBroker router) { + super(instance); + this.type = type; + this.router = router; + } + + @Override + public QName getType() { + return type; + } + + @Override + protected void removeRegistration() { + if (router != null) { + router.remove(this); + router = null; + } + } +} \ No newline at end of file diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/RoutedRpcRegImpl.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/RoutedRpcRegImpl.java new file mode 100644 index 0000000000..e4f19bbb2a --- /dev/null +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/RoutedRpcRegImpl.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2014 Cisco Systems, Inc. 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.controller.sal.dom.broker.impl; + +import org.opendaylight.controller.sal.core.api.Broker.RoutedRpcRegistration; +import org.opendaylight.controller.sal.core.api.RpcImplementation; +import org.opendaylight.yangtools.concepts.AbstractObjectRegistration; +import org.opendaylight.yangtools.yang.common.QName; +import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier; + +class RoutedRpcRegImpl extends AbstractObjectRegistration implements + RoutedRpcRegistration { + + private final QName type; + private final RoutedRpcSelector router; + + public RoutedRpcRegImpl(final QName rpcType, final RpcImplementation implementation, final RoutedRpcSelector routedRpcSelector) { + super(implementation); + this.type = rpcType; + router = routedRpcSelector; + } + + @Override + public void registerPath(final QName context, final InstanceIdentifier path) { + router.addPath(context, path, this); + } + + @Override + public void unregisterPath(final QName context, final InstanceIdentifier path) { + router.removePath(context, path, this); + } + + @Override + protected void removeRegistration() { + + } + + @Override + public QName getType() { + return type; + } + +} \ No newline at end of file diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/RoutedRpcSelector.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/RoutedRpcSelector.java new file mode 100644 index 0000000000..a22aed7ab1 --- /dev/null +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/RoutedRpcSelector.java @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2014 Cisco Systems, Inc. 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.controller.sal.dom.broker.impl; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkState; + +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +import org.opendaylight.controller.md.sal.dom.broker.spi.rpc.RpcRoutingStrategy; +import org.opendaylight.controller.sal.core.api.Broker.RoutedRpcRegistration; +import org.opendaylight.controller.sal.core.api.RpcImplementation; +import org.opendaylight.controller.sal.core.api.RpcRoutingContext; +import org.opendaylight.yangtools.concepts.Identifiable; +import org.opendaylight.yangtools.yang.common.QName; +import org.opendaylight.yangtools.yang.common.RpcResult; +import org.opendaylight.yangtools.yang.data.api.CompositeNode; +import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier; +import org.opendaylight.yangtools.yang.data.api.SimpleNode; + +import com.google.common.collect.ImmutableSet; +import com.google.common.util.concurrent.ListenableFuture; + +class RoutedRpcSelector implements RpcImplementation, AutoCloseable, Identifiable { + + private final RpcRoutingStrategy strategy; + private final Set supportedRpcs; + private final RpcRoutingContext identifier; + final ConcurrentMap implementations = new ConcurrentHashMap<>(); + private final SchemaAwareRpcBroker router; + + public RoutedRpcSelector(final RpcRoutingStrategy strategy, final SchemaAwareRpcBroker router) { + super(); + this.strategy = strategy; + supportedRpcs = ImmutableSet.of(strategy.getIdentifier()); + identifier = RpcRoutingContext.create(strategy.getContext(), strategy.getIdentifier()); + this.router = router; + } + + @Override + public RpcRoutingContext getIdentifier() { + return identifier; + } + + @Override + public void close() throws Exception { + + } + + @Override + public Set getSupportedRpcs() { + return supportedRpcs; + } + + public RoutedRpcRegistration addRoutedRpcImplementation(final QName rpcType, final RpcImplementation implementation) { + return new RoutedRpcRegImpl(rpcType, implementation, this); + } + + @Override + public ListenableFuture> invokeRpc(final QName rpc, final CompositeNode input) { + CompositeNode inputContainer = input.getFirstCompositeByName(QName.create(rpc,"input")); + checkArgument(inputContainer != null, "Rpc payload must contain input element"); + SimpleNode routeContainer = inputContainer.getFirstSimpleByName(strategy.getLeaf()); + checkArgument(routeContainer != null, "Leaf %s must be set with value", strategy.getLeaf()); + Object route = routeContainer.getValue(); + checkArgument(route instanceof InstanceIdentifier, + "The routed node %s is not an instance identifier", route); + RpcImplementation potential = null; + if (route != null) { + RoutedRpcRegImpl potentialReg = implementations.get(route); + if (potentialReg != null) { + potential = potentialReg.getInstance(); + } + } + if (potential == null) { + return router.invokeRpc(rpc, (InstanceIdentifier) route, input); + } + checkState(potential != null, "No implementation is available for rpc:%s path:%s", rpc, route); + return potential.invokeRpc(rpc, input); + } + + public void addPath(final QName context, final InstanceIdentifier path, final RoutedRpcRegImpl routedRpcRegImpl) { + //checkArgument(strategy.getContext().equals(context),"Supplied context is not supported."); + RoutedRpcRegImpl previous = implementations.put(path, routedRpcRegImpl); + if (previous == null) { + router.notifyPathAnnouncement(context,strategy.getIdentifier(), path); + } + + } + + public void removePath(final QName context, final InstanceIdentifier path, final RoutedRpcRegImpl routedRpcRegImpl) { + boolean removed = implementations.remove(path, routedRpcRegImpl); + if (removed) { + router.notifyPathWithdrawal(context, strategy.getIdentifier(), path); + } + } +} \ No newline at end of file diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/SchemaAwareRpcBroker.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/SchemaAwareRpcBroker.java index 32139308b1..7bc827dcb0 100644 --- a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/SchemaAwareRpcBroker.java +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/SchemaAwareRpcBroker.java @@ -14,10 +14,10 @@ import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; -import com.google.common.base.Preconditions; import org.opendaylight.controller.md.sal.common.api.routing.RouteChange; import org.opendaylight.controller.md.sal.common.api.routing.RouteChangeListener; import org.opendaylight.controller.md.sal.common.impl.routing.RoutingUtils; +import org.opendaylight.controller.md.sal.dom.broker.spi.rpc.RpcRoutingStrategy; import org.opendaylight.controller.sal.core.api.Broker.RoutedRpcRegistration; import org.opendaylight.controller.sal.core.api.Broker.RpcRegistration; import org.opendaylight.controller.sal.core.api.RoutedRpcDefaultImplementation; @@ -25,7 +25,6 @@ import org.opendaylight.controller.sal.core.api.RpcImplementation; import org.opendaylight.controller.sal.core.api.RpcRegistrationListener; import org.opendaylight.controller.sal.core.api.RpcRoutingContext; import org.opendaylight.controller.sal.dom.broker.spi.RpcRouter; -import org.opendaylight.yangtools.concepts.AbstractObjectRegistration; import org.opendaylight.yangtools.concepts.Identifiable; import org.opendaylight.yangtools.concepts.ListenerRegistration; import org.opendaylight.yangtools.concepts.util.ListenerRegistry; @@ -33,17 +32,13 @@ import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.common.RpcResult; import org.opendaylight.yangtools.yang.data.api.CompositeNode; import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier; -import org.opendaylight.yangtools.yang.data.api.SimpleNode; -import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode; -import org.opendaylight.yangtools.yang.model.api.DataSchemaNode; import org.opendaylight.yangtools.yang.model.api.Module; import org.opendaylight.yangtools.yang.model.api.RpcDefinition; import org.opendaylight.yangtools.yang.model.api.SchemaContext; -import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.google.common.base.Optional; +import com.google.common.base.Preconditions; import com.google.common.collect.FluentIterable; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; @@ -53,8 +48,7 @@ public class SchemaAwareRpcBroker implements RpcRouter, Identifiable, Ro private static final Logger LOG = LoggerFactory.getLogger(SchemaAwareRpcBroker.class); - private static final QName CONTEXT_REFERENCE = QName.create("urn:opendaylight:yang:extension:yang-ext", - "2013-07-09", "context-reference"); + private final ListenerRegistry rpcRegistrationListeners = new ListenerRegistry<>(); private final ListenerRegistry> routeChangeListeners = new ListenerRegistry<>(); @@ -65,7 +59,7 @@ public class SchemaAwareRpcBroker implements RpcRouter, Identifiable, Ro private SchemaContextProvider schemaProvider; private RoutedRpcDefaultImplementation defaultDelegate; - public SchemaAwareRpcBroker(String identifier, SchemaContextProvider schemaProvider) { + public SchemaAwareRpcBroker(final String identifier, final SchemaContextProvider schemaProvider) { super(); this.identifier = identifier; this.schemaProvider = schemaProvider; @@ -75,7 +69,7 @@ public class SchemaAwareRpcBroker implements RpcRouter, Identifiable, Ro return defaultImplementation; } - public void setDefaultImplementation(RpcImplementation defaultImplementation) { + public void setDefaultImplementation(final RpcImplementation defaultImplementation) { this.defaultImplementation = defaultImplementation; } @@ -83,7 +77,7 @@ public class SchemaAwareRpcBroker implements RpcRouter, Identifiable, Ro return schemaProvider; } - public void setSchemaProvider(SchemaContextProvider schemaProvider) { + public void setSchemaProvider(final SchemaContextProvider schemaProvider) { this.schemaProvider = schemaProvider; } @@ -92,18 +86,18 @@ public class SchemaAwareRpcBroker implements RpcRouter, Identifiable, Ro } @Override - public void setRoutedRpcDefaultDelegate(RoutedRpcDefaultImplementation defaultDelegate) { + public void setRoutedRpcDefaultDelegate(final RoutedRpcDefaultImplementation defaultDelegate) { this.defaultDelegate = defaultDelegate; } @Override - public RoutedRpcRegistration addRoutedRpcImplementation(QName rpcType, RpcImplementation implementation) { + public RoutedRpcRegistration addRoutedRpcImplementation(final QName rpcType, final RpcImplementation implementation) { checkArgument(rpcType != null, "RPC Type should not be null"); checkArgument(implementation != null, "RPC Implementatoin should not be null"); return getOrCreateRoutedRpcRouter(rpcType).addRoutedRpcImplementation(rpcType, implementation); } - private RoutedRpcSelector getOrCreateRoutedRpcRouter(QName rpcType) { + private RoutedRpcSelector getOrCreateRoutedRpcRouter(final QName rpcType) { RoutedRpcSelector potential = getRoutedRpcRouter(rpcType); if (potential != null) { return potential; @@ -114,15 +108,15 @@ public class SchemaAwareRpcBroker implements RpcRouter, Identifiable, Ro return potential; } RpcDefinition definition = findRpcDefinition(rpcType); - RoutingStrategy strategy = getRoutingStrategy(definition); - checkState(strategy instanceof RoutedRpcStrategy, "Rpc %s is not routed.", rpcType); - potential = new RoutedRpcSelector((RoutedRpcStrategy) strategy, this); + RpcRoutingStrategy strategy = RpcRoutingStrategy.from(definition); + checkState(strategy.isContextBasedRouted(), "Rpc %s is not routed.", rpcType); + potential = new RoutedRpcSelector( strategy, this); implementations.put(rpcType, potential); return potential; } } - private RoutedRpcSelector getRoutedRpcRouter(QName rpcType) { + private RoutedRpcSelector getRoutedRpcRouter(final QName rpcType) { RpcImplementation potential = implementations.get(rpcType); if (potential != null) { checkState(potential instanceof RoutedRpcSelector, "Rpc %s is not routed.", rpcType); @@ -133,13 +127,13 @@ public class SchemaAwareRpcBroker implements RpcRouter, Identifiable, Ro } @Override - public RpcRegistration addRpcImplementation(QName rpcType, RpcImplementation implementation) + public RpcRegistration addRpcImplementation(final QName rpcType, final RpcImplementation implementation) throws IllegalArgumentException { checkArgument(rpcType != null, "RPC Type should not be null"); checkArgument(implementation != null, "RPC Implementatoin should not be null"); checkState(!hasRpcImplementation(rpcType), "Implementation already registered"); RpcDefinition definition = findRpcDefinition(rpcType); - checkArgument(!isRoutedRpc(definition), "RPC Type must not be routed."); + checkArgument(!RpcRoutingStrategy.from(definition).isContextBasedRouted(), "RPC Type must not be content routed."); GlobalRpcRegistration reg = new GlobalRpcRegistration(rpcType, implementation, this); final RpcImplementation previous = implementations.putIfAbsent(rpcType, implementation); Preconditions.checkState(previous == null, "Rpc %s is already registered.",rpcType); @@ -147,7 +141,7 @@ public class SchemaAwareRpcBroker implements RpcRouter, Identifiable, Ro return reg; } - private void notifyRpcAdded(QName rpcType) { + private void notifyRpcAdded(final QName rpcType) { for (ListenerRegistration listener : rpcRegistrationListeners) { try { listener.getInstance().onRpcImplementationAdded(rpcType); @@ -158,12 +152,8 @@ public class SchemaAwareRpcBroker implements RpcRouter, Identifiable, Ro } } - private boolean isRoutedRpc(RpcDefinition definition) { - return getRoutingStrategy(definition) instanceof RoutedRpcStrategy; - } - @Override - public ListenerRegistration addRpcRegistrationListener(RpcRegistrationListener listener) { + public ListenerRegistration addRpcRegistrationListener(final RpcRegistrationListener listener) { ListenerRegistration reg = rpcRegistrationListeners.register(listener); for (QName impl : implementations.keySet()) { listener.onRpcImplementationAdded(impl); @@ -182,11 +172,11 @@ public class SchemaAwareRpcBroker implements RpcRouter, Identifiable, Ro } @Override - public ListenableFuture> invokeRpc(QName rpc, CompositeNode input) { + public ListenableFuture> invokeRpc(final QName rpc, final CompositeNode input) { return findRpcImplemention(rpc).invokeRpc(rpc, input); } - private RpcImplementation findRpcImplemention(QName rpc) { + private RpcImplementation findRpcImplemention(final QName rpc) { checkArgument(rpc != null, "Rpc name should not be null"); RpcImplementation potentialImpl = implementations.get(rpc); if (potentialImpl != null) { @@ -201,11 +191,11 @@ public class SchemaAwareRpcBroker implements RpcRouter, Identifiable, Ro return potentialImpl; } - private boolean hasRpcImplementation(QName rpc) { + private boolean hasRpcImplementation(final QName rpc) { return implementations.containsKey(rpc); } - private RpcDefinition findRpcDefinition(QName rpcType) { + private RpcDefinition findRpcDefinition(final QName rpcType) { checkArgument(rpcType != null, "Rpc name must be supplied."); checkState(schemaProvider != null, "Schema Provider is not available."); SchemaContext ctx = schemaProvider.getSchemaContext(); @@ -215,7 +205,7 @@ public class SchemaAwareRpcBroker implements RpcRouter, Identifiable, Ro return findRpcDefinition(rpcType, module.getRpcs()); } - static private RpcDefinition findRpcDefinition(QName rpcType, Set rpcs) { + static private RpcDefinition findRpcDefinition(final QName rpcType, final Set rpcs) { checkState(rpcs != null, "Rpc schema is not available."); for (RpcDefinition rpc : rpcs) { if (rpcType.equals(rpc.getQName())) { @@ -225,225 +215,17 @@ public class SchemaAwareRpcBroker implements RpcRouter, Identifiable, Ro throw new IllegalArgumentException("Supplied Rpc Type is not defined."); } - private RoutingStrategy getRoutingStrategy(RpcDefinition rpc) { - ContainerSchemaNode input = rpc.getInput(); - if (input != null) { - for (DataSchemaNode schemaNode : input.getChildNodes()) { - Optional context = getRoutingContext(schemaNode); - if (context.isPresent()) { - return createRoutedStrategy(rpc, context.get(), schemaNode.getQName()); - } - } - } - return createGlobalStrategy(rpc); - } - - private static RoutingStrategy createRoutedStrategy(RpcDefinition rpc, QName context, QName leafNode) { - return new RoutedRpcStrategy(rpc.getQName(), context, leafNode); - } - - private Optional getRoutingContext(DataSchemaNode schemaNode) { - for (UnknownSchemaNode extension : schemaNode.getUnknownSchemaNodes()) { - if (CONTEXT_REFERENCE.equals(extension.getNodeType())) { - return Optional.fromNullable(extension.getQName()); - } - } - return Optional.absent(); - } - - private static RoutingStrategy createGlobalStrategy(RpcDefinition rpc) { - GlobalRpcStrategy ret = new GlobalRpcStrategy(rpc.getQName()); - return ret; - } - @Override - public ListenableFuture> invokeRpc(QName rpc, InstanceIdentifier identifier, CompositeNode input) { - checkState(defaultDelegate != null); - return defaultDelegate.invokeRpc(rpc, identifier, input); - } - - private static abstract class RoutingStrategy implements Identifiable { - - private final QName identifier; - - public RoutingStrategy(QName identifier) { - super(); - this.identifier = identifier; - } - - @Override - public QName getIdentifier() { - return identifier; - } - } - - private static class GlobalRpcStrategy extends RoutingStrategy { - - public GlobalRpcStrategy(QName identifier) { - super(identifier); - } - } - - private static class RoutedRpcStrategy extends RoutingStrategy { - - private final QName context; - private final QName leaf; - - public RoutedRpcStrategy(QName identifier, QName ctx, QName leaf) { - super(identifier); - this.context = ctx; - this.leaf = leaf; - } - - public QName getContext() { - return context; - } - - public QName getLeaf() { - return leaf; - } + public ListenableFuture> invokeRpc(final QName rpc, final InstanceIdentifier route, final CompositeNode input) { + checkState(defaultDelegate != null, "No implementation is available for rpc:%s path:%s", rpc, route); + return defaultDelegate.invokeRpc(rpc, route, input); } - private static class RoutedRpcSelector implements RpcImplementation, AutoCloseable, Identifiable { - - private final RoutedRpcStrategy strategy; - private final Set supportedRpcs; - private final RpcRoutingContext identifier; - private RpcImplementation defaultDelegate; - private final ConcurrentMap implementations = new ConcurrentHashMap<>(); - private final SchemaAwareRpcBroker router; - - public RoutedRpcSelector(RoutedRpcStrategy strategy, SchemaAwareRpcBroker router) { - super(); - this.strategy = strategy; - supportedRpcs = ImmutableSet.of(strategy.getIdentifier()); - identifier = RpcRoutingContext.create(strategy.context, strategy.getIdentifier()); - this.router = router; - } - - @Override - public RpcRoutingContext getIdentifier() { - return identifier; - } - - @Override - public void close() throws Exception { - - } - - @Override - public Set getSupportedRpcs() { - return supportedRpcs; - } - - public RoutedRpcRegistration addRoutedRpcImplementation(QName rpcType, RpcImplementation implementation) { - return new RoutedRpcRegImpl(rpcType, implementation, this); - } - - @Override - public ListenableFuture> invokeRpc(QName rpc, CompositeNode input) { - CompositeNode inputContainer = input.getFirstCompositeByName(QName.create(rpc,"input")); - checkArgument(inputContainer != null, "Rpc payload must contain input element"); - SimpleNode routeContainer = inputContainer.getFirstSimpleByName(strategy.getLeaf()); - checkArgument(routeContainer != null, "Leaf %s must be set with value", strategy.getLeaf()); - Object route = routeContainer.getValue(); - checkArgument(route instanceof InstanceIdentifier, - "The routed node %s is not an instance identifier", route); - RpcImplementation potential = null; - if (route != null) { - RoutedRpcRegImpl potentialReg = implementations.get(route); - if (potentialReg != null) { - potential = potentialReg.getInstance(); - } - } - if (potential == null) { - return router.invokeRpc(rpc, (InstanceIdentifier) route, input); - } - checkState(potential != null, "No implementation is available for rpc:%s path:%s", rpc, route); - return potential.invokeRpc(rpc, input); - } - - public void addPath(QName context, InstanceIdentifier path, RoutedRpcRegImpl routedRpcRegImpl) { - //checkArgument(strategy.getContext().equals(context),"Supplied context is not supported."); - RoutedRpcRegImpl previous = implementations.put(path, routedRpcRegImpl); - if (previous == null) { - router.notifyPathAnnouncement(context,strategy.getIdentifier(), path); - } - - } - - public void removePath(QName context, InstanceIdentifier path, RoutedRpcRegImpl routedRpcRegImpl) { - boolean removed = implementations.remove(path, routedRpcRegImpl); - if (removed) { - router.notifyPathWithdrawal(context, strategy.getIdentifier(), path); - } - } - } - - private static class GlobalRpcRegistration extends AbstractObjectRegistration implements - RpcRegistration { - private final QName type; - private SchemaAwareRpcBroker router; - - public GlobalRpcRegistration(QName type, RpcImplementation instance, SchemaAwareRpcBroker router) { - super(instance); - this.type = type; - this.router = router; - } - - @Override - public QName getType() { - return type; - } - - @Override - protected void removeRegistration() { - if (router != null) { - router.remove(this); - router = null; - } - } - } - - private static class RoutedRpcRegImpl extends AbstractObjectRegistration implements - RoutedRpcRegistration { - - private final QName type; - private final RoutedRpcSelector router; - - public RoutedRpcRegImpl(QName rpcType, RpcImplementation implementation, RoutedRpcSelector routedRpcSelector) { - super(implementation); - this.type = rpcType; - router = routedRpcSelector; - } - - @Override - public void registerPath(QName context, InstanceIdentifier path) { - router.addPath(context, path, this); - } - - @Override - public void unregisterPath(QName context, InstanceIdentifier path) { - router.removePath(context, path, this); - } - - @Override - protected void removeRegistration() { - - } - - @Override - public QName getType() { - return type; - } - - } - - private void remove(GlobalRpcRegistration registration) { + void remove(final GlobalRpcRegistration registration) { implementations.remove(registration.getType(), registration); } - private void notifyPathAnnouncement(QName context, QName identifier, InstanceIdentifier path) { + void notifyPathAnnouncement(final QName context, final QName identifier, final InstanceIdentifier path) { RpcRoutingContext contextWrapped = RpcRoutingContext.create(context, identifier); RouteChange change = RoutingUtils.announcementChange(contextWrapped , path); for(ListenerRegistration> routeListener : routeChangeListeners) { @@ -451,15 +233,12 @@ public class SchemaAwareRpcBroker implements RpcRouter, Identifiable, Ro routeListener.getInstance().onRouteChange(change); } catch (Exception e) { LOG.error("Unhandled exception during invoking onRouteChange for {}",routeListener.getInstance(),e); - } } } - - - private void notifyPathWithdrawal(QName context,QName identifier, InstanceIdentifier path) { + void notifyPathWithdrawal(final QName context,final QName identifier, final InstanceIdentifier path) { RpcRoutingContext contextWrapped = RpcRoutingContext.create(context, identifier); RouteChange change = RoutingUtils.removalChange(contextWrapped , path); for(ListenerRegistration> routeListener : routeChangeListeners) { @@ -473,7 +252,7 @@ public class SchemaAwareRpcBroker implements RpcRouter, Identifiable, Ro @Override public > ListenerRegistration registerRouteChangeListener( - L listener) { + final L listener) { ListenerRegistration reg = routeChangeListeners.registerWithType(listener); RouteChange initial = createInitialRouteChange(); try { diff --git a/opendaylight/md-sal/sal-dom-spi/src/main/java/org/opendaylight/controller/md/sal/dom/broker/spi/rpc/RpcRoutingStrategy.java b/opendaylight/md-sal/sal-dom-spi/src/main/java/org/opendaylight/controller/md/sal/dom/broker/spi/rpc/RpcRoutingStrategy.java new file mode 100644 index 0000000000..81203c55fe --- /dev/null +++ b/opendaylight/md-sal/sal-dom-spi/src/main/java/org/opendaylight/controller/md/sal/dom/broker/spi/rpc/RpcRoutingStrategy.java @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2014 Cisco Systems, Inc. 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.controller.md.sal.dom.broker.spi.rpc; + +import org.opendaylight.yangtools.concepts.Identifiable; +import org.opendaylight.yangtools.yang.common.QName; +import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode; +import org.opendaylight.yangtools.yang.model.api.DataSchemaNode; +import org.opendaylight.yangtools.yang.model.api.RpcDefinition; +import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode; + +import com.google.common.base.Optional; + +public abstract class RpcRoutingStrategy implements Identifiable { + + private final QName identifier; + private static final QName CONTEXT_REFERENCE = QName.create("urn:opendaylight:yang:extension:yang-ext", + "2013-07-09", "context-reference"); + + private RpcRoutingStrategy(final QName identifier) { + super(); + this.identifier = identifier; + } + + /** + * Returns leaf QName in which RPC Route is stored + * + * + * @return leaf QName in which RPC Route is stored + * @throws UnsupportedOperationException If RPC is not content routed. + * ({@link #isContextBasedRouted()} returned false) + */ + public abstract QName getLeaf(); + + /** + * Returns identity QName which represents RPC Routing context + * + * @return identity QName which represents RPC Routing context + * @throws UnsupportedOperationException If RPC is not content routed. + * ({@link #isContextBasedRouted()} returned false) + */ + public abstract QName getContext(); + + @Override + public QName getIdentifier() { + return identifier; + } + + /** + * Returns true if RPC is routed by context. + * + * @return true if RPC is routed by content. + */ + public abstract boolean isContextBasedRouted(); + + public static RpcRoutingStrategy from(final RpcDefinition rpc) { + ContainerSchemaNode input = rpc.getInput(); + if (input != null) { + for (DataSchemaNode schemaNode : input.getChildNodes()) { + Optional context = getRoutingContext(schemaNode); + if (context.isPresent()) { + return createRoutedStrategy(rpc, context.get(), schemaNode.getQName()); + } + } + } + return createGlobalStrategy(rpc); + } + + public static Optional getRoutingContext(final DataSchemaNode schemaNode) { + for (UnknownSchemaNode extension : schemaNode.getUnknownSchemaNodes()) { + if (CONTEXT_REFERENCE.equals(extension.getNodeType())) { + return Optional.fromNullable(extension.getQName()); + } + } + return Optional.absent(); + } + + private static RpcRoutingStrategy createRoutedStrategy(final RpcDefinition rpc, final QName context, final QName leafNode) { + return new RoutedRpcStrategy(rpc.getQName(), context, leafNode); + } + + + + private static RpcRoutingStrategy createGlobalStrategy(final RpcDefinition rpc) { + GlobalRpcStrategy ret = new GlobalRpcStrategy(rpc.getQName()); + return ret; + } + + private static class RoutedRpcStrategy extends RpcRoutingStrategy { + + final QName context; + private final QName leaf; + + private RoutedRpcStrategy(final QName identifier, final QName ctx, final QName leaf) { + super(identifier); + this.context = ctx; + this.leaf = leaf; + } + + @Override + public QName getContext() { + return context; + } + + @Override + public QName getLeaf() { + return leaf; + } + + @Override + public boolean isContextBasedRouted() { + return true; + } + } + + private static class GlobalRpcStrategy extends RpcRoutingStrategy { + + public GlobalRpcStrategy(final QName identifier) { + super(identifier); + } + + @Override + public boolean isContextBasedRouted() { + return false; + } + + @Override + public QName getContext() { + throw new UnsupportedOperationException("Not routed strategy does not have context."); + } + + @Override + public QName getLeaf() { + throw new UnsupportedOperationException("Not routed strategy does not have context."); + } + } +} \ No newline at end of file -- 2.36.6