From 912f6fac2a92a2091ec581825d8da46fea7e029c Mon Sep 17 00:00:00 2001 From: Tony Tkacik Date: Tue, 17 Sep 2013 17:32:11 +0200 Subject: [PATCH] Added Router code generation and unit tests for runtime code generator Added implementation of Router generation - SAL implementation of service responsible for routing requests to southbound components based on ContextReference field, which is conceptually same as NodeType in HARD SAL, but more flexible and does allow selecting implementation on different fields than only NodeType. Moved runtime code generation code to separate packages .codegen Change-Id: I3c89151071c6e34af1490a79b4f19f6195a878a5 Signed-off-by: Tony Tkacik --- opendaylight/sal/yang-prototype/sal/pom.xml | 2 +- .../sal/sal-binding-broker-impl/pom.xml | 218 +++++++++--------- .../binding/codegen/RuntimeCodeHelper.xtend | 65 ++++++ .../codegen/RuntimeCodeSpecification.xtend | 65 ++++++ .../codegen/YangtoolsMappingHelper.xtend | 19 ++ .../binding/codegen/impl/JavassistUtils.java | 27 +++ .../binding/codegen/impl/RoutingPair.xtend | 21 ++ .../codegen/impl/RuntimeCodeGenerator.xtend | 186 +++++++++++++++ .../binding/impl/BindingAwareBrokerImpl.xtend | 71 +----- .../binding/impl/DataProviderContext.xtend | 19 ++ .../binding/impl/NotificationBrokerImpl.xtend | 1 + .../binding/impl/OsgiConsumerContext.xtend | 85 +++---- .../binding/impl/OsgiProviderContext.xtend | 5 +- .../sal/binding/impl/_DataBrokerImpl.xtend | 78 +++++++ .../binding/impl/{ => osgi}/Constants.xtend | 4 +- .../binding/impl/osgi/PropertiesUtils.xtend | 31 +++ .../sal/binding/impl/osgi/package-info.java | 8 + .../binding/impl/utils/GeneratorUtils.xtend | 30 --- .../binding/impl/utils/PropertiesUtils.xtend | 30 --- .../sal/binding/impl/utils/package-info.java | 8 - .../sal/binding/test/GenerationTest.java | 31 +++ .../test/RuntimeCodeGeneratorTest.java | 142 ++++++++++++ .../sal/binding/test/mock/BarUpdate.java | 7 + .../sal/binding/test/mock/FooListener.java | 10 + .../sal/binding/test/mock/FooService.java | 16 ++ .../sal/binding/test/mock/FooUpdate.java | 7 + .../sal/binding/test/mock/Grouping.java | 11 + .../test/mock/InheritedContextInput.java | 5 + .../binding/test/mock/ReferencableObject.java | 8 + .../test/mock/ReferencableObjectKey.java | 44 ++++ .../sal/binding/test/mock/SimpleInput.java | 13 ++ 31 files changed, 988 insertions(+), 279 deletions(-) create mode 100644 opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/codegen/RuntimeCodeHelper.xtend create mode 100644 opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/codegen/RuntimeCodeSpecification.xtend create mode 100644 opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/codegen/YangtoolsMappingHelper.xtend create mode 100644 opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/codegen/impl/JavassistUtils.java create mode 100644 opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/codegen/impl/RoutingPair.xtend create mode 100644 opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/codegen/impl/RuntimeCodeGenerator.xtend create mode 100644 opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/DataProviderContext.xtend create mode 100644 opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/_DataBrokerImpl.xtend rename opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/{ => osgi}/Constants.xtend (84%) create mode 100644 opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/osgi/PropertiesUtils.xtend create mode 100644 opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/osgi/package-info.java delete mode 100644 opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/utils/GeneratorUtils.xtend delete mode 100644 opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/utils/PropertiesUtils.xtend delete mode 100644 opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/utils/package-info.java create mode 100644 opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/test/org/opendaylight/controller/sal/binding/test/GenerationTest.java create mode 100644 opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/test/java/org/opendaylight/controller/sal/binding/test/RuntimeCodeGeneratorTest.java create mode 100644 opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/test/java/org/opendaylight/controller/sal/binding/test/mock/BarUpdate.java create mode 100644 opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/test/java/org/opendaylight/controller/sal/binding/test/mock/FooListener.java create mode 100644 opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/test/java/org/opendaylight/controller/sal/binding/test/mock/FooService.java create mode 100644 opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/test/java/org/opendaylight/controller/sal/binding/test/mock/FooUpdate.java create mode 100644 opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/test/java/org/opendaylight/controller/sal/binding/test/mock/Grouping.java create mode 100644 opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/test/java/org/opendaylight/controller/sal/binding/test/mock/InheritedContextInput.java create mode 100644 opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/test/java/org/opendaylight/controller/sal/binding/test/mock/ReferencableObject.java create mode 100644 opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/test/java/org/opendaylight/controller/sal/binding/test/mock/ReferencableObjectKey.java create mode 100644 opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/test/java/org/opendaylight/controller/sal/binding/test/mock/SimpleInput.java diff --git a/opendaylight/sal/yang-prototype/sal/pom.xml b/opendaylight/sal/yang-prototype/sal/pom.xml index 0442e8f9b2..75f9d68bdd 100644 --- a/opendaylight/sal/yang-prototype/sal/pom.xml +++ b/opendaylight/sal/yang-prototype/sal/pom.xml @@ -25,7 +25,7 @@ UTF-8 1.7.2 http://nexus.opendaylight.org/content - 0.5.7-SNAPSHOT + 0.5.8-SNAPSHOT 2.4.0 2.3.2 14.0.1 diff --git a/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/pom.xml b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/pom.xml index 549e427d82..96a16dcd57 100644 --- a/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/pom.xml +++ b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/pom.xml @@ -1,113 +1,121 @@ - 4.0.0 - - org.opendaylight.controller - sal-parent - 1.0-SNAPSHOT - - sal-binding-broker-impl - bundle + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + 4.0.0 + + org.opendaylight.controller + sal-parent + 1.0-SNAPSHOT + + sal-binding-broker-impl + bundle - scm:git:ssh://git.opendaylight.org:29418/controller.git - scm:git:ssh://git.opendaylight.org:29418/controller.git - https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL + scm:git:ssh://git.opendaylight.org:29418/controller.git + scm:git:ssh://git.opendaylight.org:29418/controller.git + https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL - - - - org.apache.felix - maven-bundle-plugin - ${maven.bundle.version} - true - - - ${project.groupId}.${project.artifactId} - org.opendaylight.controller.sal.binding.impl.BrokerActivator - - org.opendaylight.controller.sal.binding.impl, - org.opendaylight.controller.sal.binding.impl.utils, - org.eclipse.xtend2.lib, - org.eclipse.xtext.xbase.* - - - - + + + + org.apache.felix + maven-bundle-plugin + ${maven.bundle.version} + true + + + ${project.groupId}.${project.artifactId} + org.opendaylight.controller.sal.binding.impl.BrokerActivator + + org.opendaylight.controller.sal.binding.impl, + org.opendaylight.controller.sal.binding.impl.*, + org.opendaylight.controller.sal.binding.codegen.*, + org.eclipse.xtend2.lib, + org.eclipse.xtend.lib, + org.eclipse.xtext.xbase.* + + + + - - org.eclipse.xtend - xtend-maven-plugin - 2.4.2 - - - - compile - - - ${basedir}/src/main/xtend-gen - - - - - - maven-clean-plugin - 2.4.1 - - - - ${basedir}/src/main/xtend-gen - - ** - - - - - - - + + org.eclipse.xtend + xtend-maven-plugin + 2.4.2 + + + + compile + + + ${basedir}/src/main/xtend-gen + + + + + + maven-clean-plugin + 2.4.1 + + + + ${basedir}/src/main/xtend-gen + + ** + + + + + + + - - - org.opendaylight.controller - sal-common-util - 1.0-SNAPSHOT - - - org.opendaylight.controller - sal-binding-api - 1.0-SNAPSHOT - - + + + org.opendaylight.controller + sal-common-util + 1.0-SNAPSHOT + + + org.opendaylight.controller + sal-binding-api + 1.0-SNAPSHOT + + - - org.slf4j - slf4j-api - - - org.osgi - org.osgi.core - 5.0.0 - - - com.google.guava - guava - - - org.reflections - reflections - 0.9.9-RC1 - - - org.javassist - javassist - 3.17.1-GA - - - org.eclipse.xtend - org.eclipse.xtend.lib - 2.4.2 - - + + org.slf4j + slf4j-api + + + org.osgi + org.osgi.core + 5.0.0 + + + com.google.guava + guava + + + org.reflections + reflections + 0.9.9-RC1 + + + org.javassist + javassist + 3.17.1-GA + + + org.eclipse.xtend + org.eclipse.xtend.lib + 2.4.2 + + + org.mockito + mockito-all + 1.9.5 + test + + diff --git a/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/codegen/RuntimeCodeHelper.xtend b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/codegen/RuntimeCodeHelper.xtend new file mode 100644 index 0000000000..6bdb3c8fbe --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/codegen/RuntimeCodeHelper.xtend @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2013 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.binding.codegen + +import java.util.Map + +import org.opendaylight.yangtools.yang.binding.BaseIdentity +import org.opendaylight.yangtools.yang.binding.RpcService +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier + +import static extension org.opendaylight.controller.sal.binding.codegen.RuntimeCodeSpecification.* + +class RuntimeCodeHelper { + /** + * Helper method to return delegate from ManagedDirectedProxy with use of reflection. + * + * Note: This method uses reflection, but access to delegate field should be + * avoided and called only if neccessary. + * + */ + public static def getDelegate(RpcService proxy) { + val field = proxy.class.getField(DELEGATE_FIELD) + if (field == null) throw new UnsupportedOperationException("Unable to get delegate from proxy"); + return field.get(proxy) as T + } + + /** + * Helper method to set delegate to ManagedDirectedProxy with use of reflection. + * + * Note: This method uses reflection, but setting delegate field should not occur too much + * to introduce any significant performance hits. + * + */ + public static def void setDelegate(RpcService proxy, RpcService delegate) { + val field = proxy.class.getField(DELEGATE_FIELD) + if (field == null) throw new UnsupportedOperationException("Unable to set delegate to proxy"); + if (field.type.isAssignableFrom(delegate.class)) { + field.set(proxy, delegate) + } else + throw new IllegalArgumentException("delegate class is not assignable to proxy"); + } + + public static def Map getRoutingTable(RpcService target, + Class tableClass) { + val field = target.class.getField(tableClass.routingTableField) + if (field == null) throw new UnsupportedOperationException( + "Unable to get routing table. Table field does not exists"); + return field.get(target) as Map; + } + + public static def void setRoutingTable(RpcService target, Class tableClass, + Map routingTable) { + val field = target.class.getField(tableClass.routingTableField) + if (field == null) throw new UnsupportedOperationException( + "Unable to set routing table. Table field does not exists"); + field.set(target,routingTable); + + } + +} diff --git a/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/codegen/RuntimeCodeSpecification.xtend b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/codegen/RuntimeCodeSpecification.xtend new file mode 100644 index 0000000000..c6e76c2907 --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/codegen/RuntimeCodeSpecification.xtend @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2013 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.binding.codegen + +import org.opendaylight.yangtools.yang.binding.RpcService +import org.opendaylight.yangtools.yang.binding.BaseIdentity +import org.opendaylight.yangtools.yang.binding.NotificationListener + +/** + * + * + */ +class RuntimeCodeSpecification { + + public static val PACKAGE_PREFIX = "_gen."; + + public static val DIRECT_PROXY_SUFFIX = "DirectProxy"; + public static val ROUTER_SUFFIX = "Router"; + public static val INVOKER_SUFFIX = "Invoker"; + + public static val DELEGATE_FIELD = "_delegate" + public static val ROUTING_TABLE_FIELD_PREFIX = "_routes_" + + public static def getInvokerName(Class listener) { + getGeneratedName(listener, INVOKER_SUFFIX); + } + + /** + * Returns a name for DirectProxy implementation + * + * + */ + public static def getDirectProxyName(Class base) { + getGeneratedName(base, DIRECT_PROXY_SUFFIX); + } + + /** + * Returns a name for Router implementation + * + */ + public static def getRouterName(Class base) { + getGeneratedName(base, ROUTER_SUFFIX); + } + + /** + * Returns a name for generated interface + * + */ + public static def getGeneratedName(Class cls, String suffix) { + '''«PACKAGE_PREFIX»«cls.package.name».«cls.simpleName»$«suffix»'''.toString() + } + + /** + * Returns a field name for specified routing context + * + */ + public static def getRoutingTableField(Class routingContext) { + return '''_routes_«routingContext.simpleName»'''.toString; + } +} diff --git a/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/codegen/YangtoolsMappingHelper.xtend b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/codegen/YangtoolsMappingHelper.xtend new file mode 100644 index 0000000000..18d3e26346 --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/codegen/YangtoolsMappingHelper.xtend @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2013 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.binding.codegen + +import java.lang.reflect.Method +import org.opendaylight.yangtools.yang.binding.Notification + +public static class YangtoolsMappingHelper { + + public static def boolean isNotificationCallback(Method it) { + return name.startsWith("on") && parameterTypes.size === 1 && + Notification.isAssignableFrom(parameterTypes.get(0)) + } +} diff --git a/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/codegen/impl/JavassistUtils.java b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/codegen/impl/JavassistUtils.java new file mode 100644 index 0000000000..c6be284f4c --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/codegen/impl/JavassistUtils.java @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2013 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.binding.codegen.impl; + +import javassist.CtClass; +import javassist.CtField; +import javassist.CtMethod; + +public class JavassistUtils { + + public static interface ClassGenerator { + void process(CtClass cls); + } + + public static interface MethodGenerator { + void process(CtMethod method); + } + + public static interface FieldGenerator { + void process(CtField field); + } +} diff --git a/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/codegen/impl/RoutingPair.xtend b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/codegen/impl/RoutingPair.xtend new file mode 100644 index 0000000000..4324b4eb9a --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/codegen/impl/RoutingPair.xtend @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2013 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.binding.codegen.impl + +import org.opendaylight.yangtools.yang.binding.BaseIdentity +import javassist.CtMethod +import java.lang.reflect.Method + +@Data +class RoutingPair { + + @Property + val Class context; + @Property + val CtMethod getter; +} diff --git a/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/codegen/impl/RuntimeCodeGenerator.xtend b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/codegen/impl/RuntimeCodeGenerator.xtend new file mode 100644 index 0000000000..3b3f4190cf --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/codegen/impl/RuntimeCodeGenerator.xtend @@ -0,0 +1,186 @@ +/* + * Copyright (c) 2013 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.binding.codegen.impl + +import javassist.ClassPool +import org.opendaylight.yangtools.yang.binding.RpcService + +import javassist.CtClass +import static com.google.common.base.Preconditions.* + +import javassist.CtField +import javassist.Modifier +import javassist.CtMethod +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier +import org.opendaylight.yangtools.yang.binding.annotations.RoutingContext +import org.opendaylight.yangtools.yang.binding.BaseIdentity + +import java.util.Map +import java.util.HashMap +import javassist.NotFoundException +import javassist.LoaderClassPath +import org.opendaylight.controller.sal.binding.codegen.impl.JavassistUtils.MethodGenerator +import org.opendaylight.controller.sal.binding.codegen.impl.JavassistUtils.ClassGenerator +import org.opendaylight.yangtools.yang.binding.NotificationListener +import org.opendaylight.yangtools.yang.binding.Notification +import java.util.Arrays + +import static extension org.opendaylight.controller.sal.binding.codegen.YangtoolsMappingHelper.* +import static extension org.opendaylight.controller.sal.binding.codegen.RuntimeCodeSpecification.* + +class RuntimeCodeGenerator { + + val ClassPool classPool; + + public new(ClassPool pool) { + classPool = pool; + } + + def Class generateDirectProxy(Class iface) { + val supertype = iface.asCtClass + val targetCls = createClass(iface.directProxyName, supertype) [ + field(DELEGATE_FIELD, iface); + implementMethodsFrom(supertype) [ + body = '''return ($r) «DELEGATE_FIELD».«it.name»($$);''' + ] + ] + return targetCls.toClass(iface.classLoader) + } + + def Class generateRouter(Class iface) { + val supertype = iface.asCtClass + val targetCls = createClass(iface.routerName, supertype) [ + //field(ROUTING_TABLE_FIELD,Map) + field(DELEGATE_FIELD, iface) + val contexts = new HashMap>(); + // We search for routing pairs and add fields + supertype.methods.filter[declaringClass == supertype && parameterTypes.size === 1].forEach [ method | + val routingPair = method.routingContextInput; + if (routingPair !== null) + contexts.put(routingPair.context.routingTableField, routingPair.context); + ] + for (ctx : contexts.entrySet) { + field(ctx.key, Map) + } + implementMethodsFrom(supertype) [ + if (parameterTypes.size === 1) { + val routingPair = routingContextInput; + val bodyTmp = ''' + { + final «InstanceIdentifier.name» identifier = $1.«routingPair.getter.name»(); + «supertype.name» instance = («supertype.name») «routingPair.context.routingTableField».get(identifier); + if(instance == null) { + instance = «DELEGATE_FIELD»; + } + return ($r) instance.«it.name»($$); + }''' + body = bodyTmp + } else if (parameterTypes.size === 0) { + body = '''return ($r) «DELEGATE_FIELD».«it.name»($$);''' + } + ] + ] + return targetCls.toClass(iface.classLoader) + } + + def Class generateListenerInvoker(Class iface) { + val targetCls = createClass(iface.invokerName) [ + field(DELEGATE_FIELD, iface) + it.method(Void, "invoke", Notification) [ + val callbacks = iface.methods.filter[notificationCallback] + body = ''' + { + «FOR callback : callbacks SEPARATOR " else "» + if($1 instanceof «val cls = callback.parameterTypes.get(0).name») { + «DELEGATE_FIELD».«callback.name»((«cls») $1); + return; + } + «ENDFOR» + } + ''' + ] + ] + return targetCls.toClass(iface.classLoader); + } + + def void method(CtClass it, Class returnType, String name, Class parameter, MethodGenerator function1) { + val method = new CtMethod(returnType.asCtClass, name, Arrays.asList(parameter.asCtClass), it); + function1.process(method); + it.addMethod(method); + } + + private def routingContextInput(CtMethod method) { + val inputClass = method.parameterTypes.get(0); + return inputClass.contextInstance; + } + + private def RoutingPair getContextInstance(CtClass dataClass) { + for (method : dataClass.methods) { + if (method.parameterTypes.size === 0 && method.name.startsWith("get")) { + for (annotation : method.availableAnnotations) { + if (annotation instanceof RoutingContext) { + return new RoutingPair((annotation as RoutingContext).value, method) + } + } + } + } + for (iface : dataClass.interfaces) { + val ret = getContextInstance(iface); + if (ret != null) return ret; + } + return null; + } + + private def void implementMethodsFrom(CtClass target, CtClass source, MethodGenerator function1) { + for (method : source.methods) { + if (method.declaringClass == source) { + val redeclaredMethod = new CtMethod(method, target, null); + function1.process(redeclaredMethod); + target.addMethod(redeclaredMethod); + } + } + } + + private def CtClass createClass(String fqn, ClassGenerator cls) { + val target = classPool.makeClass(fqn); + cls.process(target); + return target; + } + + private def CtClass createClass(String fqn, CtClass superInterface, ClassGenerator cls) { + val target = classPool.makeClass(fqn); + target.implementsType(superInterface); + cls.process(target); + return target; + } + + private def void implementsType(CtClass it, CtClass supertype) { + checkArgument(supertype.interface, "Supertype must be interface"); + addInterface(supertype); + } + + private def asCtClass(Class class1) { + classPool.get(class1); + } + + private def CtField field(CtClass it, String name, Class returnValue) { + val field = new CtField(returnValue.asCtClass, name, it); + field.modifiers = Modifier.PUBLIC + addField(field); + return field; + } + + def get(ClassPool pool, Class cls) { + try { + return pool.get(cls.name) + } catch (NotFoundException e) { + pool.appendClassPath(new LoaderClassPath(cls.classLoader)); + return pool.get(cls.name) + } + } +} diff --git a/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/BindingAwareBrokerImpl.xtend b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/BindingAwareBrokerImpl.xtend index 2953466b29..298a74ece5 100644 --- a/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/BindingAwareBrokerImpl.xtend +++ b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/BindingAwareBrokerImpl.xtend @@ -11,30 +11,29 @@ import org.opendaylight.controller.sal.binding.api.BindingAwareConsumer import org.opendaylight.controller.sal.binding.api.BindingAwareProvider import org.opendaylight.yangtools.yang.binding.RpcService import javassist.ClassPool -import javassist.CtMethod -import javassist.CtField import org.osgi.framework.BundleContext import java.util.Map import java.util.HashMap import javassist.LoaderClassPath import org.opendaylight.controller.sal.binding.api.BindingAwareBroker import java.util.Hashtable +import static extension org.opendaylight.controller.sal.binding.codegen.RuntimeCodeHelper.* -import static extension org.opendaylight.controller.sal.binding.impl.utils.PropertiesUtils.* -import static extension org.opendaylight.controller.sal.binding.impl.utils.GeneratorUtils.* import org.opendaylight.controller.sal.binding.api.NotificationProviderService import org.osgi.framework.ServiceRegistration -import org.opendaylight.controller.sal.binding.impl.utils.PropertiesUtils +import static org.opendaylight.controller.sal.binding.impl.osgi.Constants.* +import static extension org.opendaylight.controller.sal.binding.impl.osgi.PropertiesUtils.* import org.opendaylight.controller.sal.binding.api.NotificationService import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext -import javassist.Modifier + import org.slf4j.LoggerFactory +import org.opendaylight.controller.sal.binding.codegen.impl.RuntimeCodeGenerator class BindingAwareBrokerImpl implements BindingAwareBroker { - private static val DELEGATE_FIELD = "_delegate" private static val log = LoggerFactory.getLogger(BindingAwareBrokerImpl) private val clsPool = ClassPool.getDefault() + private var RuntimeCodeGenerator generator; private Map, RpcProxyContext> managedProxies = new HashMap(); private var NotificationBrokerImpl notifyBroker private var ServiceRegistration notifyBrokerRegistration @@ -47,7 +46,7 @@ class BindingAwareBrokerImpl implements BindingAwareBroker { // Initialization of notificationBroker notifyBroker = new NotificationBrokerImpl(null); - val brokerProperties = PropertiesUtils.newProperties(); + val brokerProperties = newProperties(); notifyBrokerRegistration = brokerBundleContext.registerService(NotificationProviderService, notifyBroker, brokerProperties) brokerBundleContext.registerService(NotificationService, notifyBroker, brokerProperties) @@ -56,7 +55,8 @@ class BindingAwareBrokerImpl implements BindingAwareBroker { def initGenerator() { // YANG Binding Class Loader - clsPool.appendClassPath(new LoaderClassPath(RpcService.classLoader)) + clsPool.appendClassPath(new LoaderClassPath(RpcService.classLoader)); + generator = new RuntimeCodeGenerator(clsPool); } override registerConsumer(BindingAwareConsumer consumer, BundleContext bundleCtx) { @@ -97,35 +97,16 @@ class BindingAwareBrokerImpl implements BindingAwareBroker { if ((existing = managedProxies.get(service)) != null) { return existing.proxy } - val proxyClass = service.generateDirectProxy() + val proxyClass = generator.generateDirectProxy(service) val rpcProxyCtx = new RpcProxyContext(proxyClass) val properties = new Hashtable() rpcProxyCtx.proxy = proxyClass.newInstance as RpcService - properties.salServiceType = Constants.SAL_SERVICE_TYPE_CONSUMER_PROXY + properties.salServiceType = SAL_SERVICE_TYPE_CONSUMER_PROXY rpcProxyCtx.registration = brokerBundleContext.registerService(service, rpcProxyCtx.proxy as T, properties) managedProxies.put(service, rpcProxyCtx) return rpcProxyCtx.proxy } - - protected def generateDirectProxy(Class delegate) { - val targetFqn = delegate.generatedName(Constants.PROXY_DIRECT_SUFFIX) - log.debug("Generating DirectProxy for {} Proxy name: {}",delegate,targetFqn); - val objCls = clsPool.get(Object) - val delegateCls = clsPool.get(delegate) - val proxyCls = clsPool.makeClass(targetFqn) - proxyCls.addInterface(delegateCls) - val delField = new CtField(delegateCls, DELEGATE_FIELD, proxyCls); - delField.modifiers = Modifier.PUBLIC - proxyCls.addField(delField) - delegateCls.methods.filter[it.declaringClass != objCls].forEach [ - val proxyMethod = new CtMethod(it, proxyCls, null); - proxyMethod.body = '''return ($r) «DELEGATE_FIELD».«it.name»($$);''' - proxyCls.addMethod(proxyMethod) - ] - return proxyCls.toClass(delegate.classLoader) - } - /** * Registers RPC Implementation * @@ -140,34 +121,4 @@ class BindingAwareBrokerImpl implements BindingAwareBroker { proxy.delegate = service; return new RpcServiceRegistrationImpl(type, service, osgiReg); } - - /** - * Helper method to return delegate from ManagedDirectedProxy with use of reflection. - * - * Note: This method uses reflection, but access to delegate field should be - * avoided and called only if neccessary. - * - */ - def getDelegate(RpcService proxy) { - val field = proxy.class.getField(DELEGATE_FIELD) - if(field == null) throw new UnsupportedOperationException("Unable to get delegate from proxy"); - return field.get(proxy) as T - } - - /** - * Helper method to set delegate to ManagedDirectedProxy with use of reflection. - * - * Note: This method uses reflection, but setting delegate field should not occur too much - * to introduce any significant performance hits. - * - */ - def void setDelegate(RpcService proxy, RpcService delegate) { - val field = proxy.class.getField(DELEGATE_FIELD) - if(field == null) throw new UnsupportedOperationException("Unable to set delegate to proxy"); - if (field.type.isAssignableFrom(delegate.class)) { - field.set(proxy,delegate) - } else throw new IllegalArgumentException("delegate class is not assignable to proxy"); - } - - } diff --git a/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/DataProviderContext.xtend b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/DataProviderContext.xtend new file mode 100644 index 0000000000..398a2196c6 --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/DataProviderContext.xtend @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2013 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.binding.impl + +import org.opendaylight.controller.sal.common.DataStoreIdentifier +import org.opendaylight.controller.sal.binding.api.data.RuntimeDataProvider + +class DataProviderContext { + + @Property + var DataStoreIdentifier identifier; + @Property + var RuntimeDataProvider provider; +} diff --git a/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/NotificationBrokerImpl.xtend b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/NotificationBrokerImpl.xtend index da1ba79997..22db73526e 100644 --- a/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/NotificationBrokerImpl.xtend +++ b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/NotificationBrokerImpl.xtend @@ -45,6 +45,7 @@ class NotificationBrokerImpl implements NotificationProviderService { notification.class.interfaces.filter[it != Notification && Notification.isAssignableFrom(it)] } + @SuppressWarnings("unchecked") def notifyAll(Collection> listeners, Notification notification) { listeners.forEach[(it as NotificationListener).onNotification(notification)] } diff --git a/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/OsgiConsumerContext.xtend b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/OsgiConsumerContext.xtend index a87fa0642a..a9031240c7 100644 --- a/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/OsgiConsumerContext.xtend +++ b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/OsgiConsumerContext.xtend @@ -1,3 +1,10 @@ +/* + * Copyright (c) 2013 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.binding.impl; import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ConsumerContext; @@ -7,47 +14,45 @@ import org.osgi.framework.BundleContext; import org.osgi.framework.InvalidSyntaxException; import org.osgi.framework.ServiceReference; import org.slf4j.LoggerFactory +import static org.opendaylight.controller.sal.binding.impl.osgi.Constants.* class OsgiConsumerContext implements ConsumerContext { - static val log = LoggerFactory.getLogger(OsgiConsumerContext) - protected val BundleContext bundleContext; - protected val BindingAwareBrokerImpl broker; - - new(BundleContext ctx,BindingAwareBrokerImpl broker) { - this.bundleContext = ctx; - this.broker = broker; - } - - - override def getSALService(Class service) { - // SAL Services are global - var ref = bundleContext.getServiceReference(service); - return bundleContext.getService(ref) as T; - } - - - - override def T getRpcService(Class module) { - try { - - val services = bundleContext.getServiceReferences(module, getProxyFilter()); - - // Proxy service found / using first implementation - // FIXME: Add advanced logic to retrieve service with right set of models - if(false == services.empty) { - val ref = services.iterator().next() as ServiceReference; - return bundleContext.getService(ref) as T; - } - } catch (InvalidSyntaxException e) { - log.error("Created filter was invalid:", e.message,e) - } - return null; - - - } - - private def getProxyFilter() { - return '''(«Constants.SAL_SERVICE_TYPE»=«Constants.SAL_SERVICE_TYPE_CONSUMER_PROXY»)''' - } + static val log = LoggerFactory.getLogger(OsgiConsumerContext) + protected val BundleContext bundleContext; + protected val BindingAwareBrokerImpl broker; + + new(BundleContext ctx, BindingAwareBrokerImpl broker) { + this.bundleContext = ctx; + this.broker = broker; + } + + override def getSALService(Class service) { + + // SAL Services are global + var ref = bundleContext.getServiceReference(service); + return bundleContext.getService(ref) as T; + } + + override def T getRpcService(Class module) { + try { + + val services = bundleContext.getServiceReferences(module, getProxyFilter()); + + // Proxy service found / using first implementation + // FIXME: Add advanced logic to retrieve service with right set of models + if (false == services.empty) { + val ref = services.iterator().next() as ServiceReference; + return bundleContext.getService(ref) as T; + } + } catch (InvalidSyntaxException e) { + log.error("Created filter was invalid:", e.message, e) + } + return null; + + } + + private def getProxyFilter() { + return '''(«SAL_SERVICE_TYPE»=«SAL_SERVICE_TYPE_CONSUMER_PROXY»)''' + } } diff --git a/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/OsgiProviderContext.xtend b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/OsgiProviderContext.xtend index 195fa8b959..c769ca1ee3 100644 --- a/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/OsgiProviderContext.xtend +++ b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/OsgiProviderContext.xtend @@ -16,7 +16,8 @@ import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.RpcService import org.opendaylight.yangtools.yang.binding.RpcService; import org.osgi.framework.BundleContext; -import static extension org.opendaylight.controller.sal.binding.impl.utils.PropertiesUtils.*; +import static org.opendaylight.controller.sal.binding.impl.osgi.Constants.*; +import static extension org.opendaylight.controller.sal.binding.impl.osgi.PropertiesUtils.*; class OsgiProviderContext extends OsgiConsumerContext implements ProviderContext { @@ -32,7 +33,7 @@ class OsgiProviderContext extends OsgiConsumerContext implements ProviderContext // TODO Auto-generated method stub val properties = new Hashtable(); - properties.salServiceType = Constants.SAL_SERVICE_TYPE_PROVIDER + properties.salServiceType = SAL_SERVICE_TYPE_PROVIDER // Fill requirements val salReg = broker.registerRpcImplementation(type, implementation, this, properties) diff --git a/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/_DataBrokerImpl.xtend b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/_DataBrokerImpl.xtend new file mode 100644 index 0000000000..b278df56f8 --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/_DataBrokerImpl.xtend @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2013 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.binding.impl + +import org.opendaylight.controller.sal.binding.api.data.DataBrokerService +import org.opendaylight.controller.sal.common.DataStoreIdentifier +import org.opendaylight.yangtools.yang.binding.DataRoot +import org.opendaylight.controller.sal.binding.api.data.DataProviderService +import org.opendaylight.controller.sal.binding.api.data.DataCommitHandler +import org.opendaylight.controller.sal.binding.api.data.DataRefresher +import org.opendaylight.controller.sal.binding.api.data.DataValidator +import org.opendaylight.yangtools.yang.common.RpcResult +import org.opendaylight.controller.sal.binding.api.data.RuntimeDataProvider +import java.util.Map + +class _DataBrokerImpl implements DataProviderService { + + Map dataProviders; + var DataProviderContext defaultDataProvider; + + override getData(DataStoreIdentifier store, Class rootType) { + val dataStore = resolveProvider(store, rootType); + return dataStore.provider.getData(store, rootType); + } + + override getData(DataStoreIdentifier store, T filter) { + } + + override T getCandidateData(DataStoreIdentifier store, Class rootType) { + throw new UnsupportedOperationException("TODO: auto-generated method stub"); + } + + override T getCandidateData(DataStoreIdentifier store, T filter) { + throw new UnsupportedOperationException("TODO: auto-generated method stub"); + } + + override commit(DataStoreIdentifier store) { + throw new UnsupportedOperationException("TODO: auto-generated method stub") + } + + override editCandidateData(DataStoreIdentifier store, DataRoot changeSet) { + throw new UnsupportedOperationException("TODO: auto-generated method stub") + } + + override addCommitHandler(DataStoreIdentifier store, DataCommitHandler provider) { + throw new UnsupportedOperationException("TODO: auto-generated method stub") + } + + override addRefresher(DataStoreIdentifier store, DataRefresher refresher) { + throw new UnsupportedOperationException("TODO: auto-generated method stub") + } + + override addValidator(DataStoreIdentifier store, DataValidator validator) { + throw new UnsupportedOperationException("TODO: auto-generated method stub") + } + + override removeRefresher(DataStoreIdentifier store, DataRefresher refresher) { + throw new UnsupportedOperationException("TODO: auto-generated method stub") + } + + override removeCommitHandler(DataStoreIdentifier store, DataCommitHandler provider) { + throw new UnsupportedOperationException("TODO: auto-generated method stub") + + } + + override removeValidator(DataStoreIdentifier store, DataValidator validator) { + throw new UnsupportedOperationException("TODO: auto-generated method stub") + } + + def DataProviderContext resolveProvider(DataStoreIdentifier store, Class root) { + } + +} diff --git a/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/Constants.xtend b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/osgi/Constants.xtend similarity index 84% rename from opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/Constants.xtend rename to opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/osgi/Constants.xtend index 668635a39e..9fb2140e83 100644 --- a/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/Constants.xtend +++ b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/osgi/Constants.xtend @@ -5,7 +5,7 @@ * 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.binding.impl +package org.opendaylight.controller.sal.binding.impl.osgi class Constants { @@ -16,6 +16,4 @@ class Constants { public static val SAL_SERVICE_TYPE_CONSUMER_PROXY = "consumerProxy" public static val SAL_SERVICE_TYPE_PROVIDER = "provider" public static val SAL_SERVICE_TYPE_CONNECTOR = "connector" - - public static val PROXY_DIRECT_SUFFIX = "DirectProxy"; } diff --git a/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/osgi/PropertiesUtils.xtend b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/osgi/PropertiesUtils.xtend new file mode 100644 index 0000000000..d04ca7f4ce --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/osgi/PropertiesUtils.xtend @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2013 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.binding.impl.osgi + +import java.util.Hashtable +import static org.opendaylight.controller.sal.binding.impl.osgi.Constants.* + +class PropertiesUtils { + + private new() { + } + + static def setSalServiceType(Hashtable properties, String value) { + properties.put(SAL_SERVICE_TYPE, value) + return properties + } + + static def getSalServiceType(Hashtable properties) { + return properties.get(SAL_SERVICE_TYPE) + } + + static def newProperties() { + new Hashtable() + } + +} diff --git a/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/osgi/package-info.java b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/osgi/package-info.java new file mode 100644 index 0000000000..d788ccf3a3 --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/osgi/package-info.java @@ -0,0 +1,8 @@ +/* + * Copyright (c) 2013 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.binding.impl.osgi; \ No newline at end of file diff --git a/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/utils/GeneratorUtils.xtend b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/utils/GeneratorUtils.xtend deleted file mode 100644 index c888121eb9..0000000000 --- a/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/utils/GeneratorUtils.xtend +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (c) 2013 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.binding.impl.utils - -import javassist.ClassPool -import javassist.NotFoundException -import javassist.LoaderClassPath - -class GeneratorUtils { - - static val PREFIX = "_gen."; - - public static def generatedName(Class cls, String suffix) { - '''«PREFIX»«cls.package.name».«cls.simpleName»$«suffix»'''.toString() - } - - public static def get(ClassPool pool, Class cls) { - try { - return pool.get(cls.name) - } catch (NotFoundException e) { - pool.appendClassPath(new LoaderClassPath(cls.classLoader)); - return pool.get(cls.name) - } - } -} diff --git a/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/utils/PropertiesUtils.xtend b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/utils/PropertiesUtils.xtend deleted file mode 100644 index 7ba62f5ca1..0000000000 --- a/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/utils/PropertiesUtils.xtend +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (c) 2013 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.binding.impl.utils - -import java.util.Hashtable -import org.opendaylight.controller.sal.binding.impl.Constants - -class PropertiesUtils { - - private new() {} - - static def setSalServiceType(Hashtable properties, String value) { - properties.put(Constants.SAL_SERVICE_TYPE,value) - return properties - } - - static def getSalServiceType(Hashtable properties) { - return properties.get(Constants.SAL_SERVICE_TYPE) - } - - static def newProperties() { - new Hashtable() - } - -} \ No newline at end of file diff --git a/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/utils/package-info.java b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/utils/package-info.java deleted file mode 100644 index 511023860e..0000000000 --- a/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/utils/package-info.java +++ /dev/null @@ -1,8 +0,0 @@ -/* - * Copyright (c) 2013 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.binding.impl.utils; \ No newline at end of file diff --git a/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/test/org/opendaylight/controller/sal/binding/test/GenerationTest.java b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/test/org/opendaylight/controller/sal/binding/test/GenerationTest.java new file mode 100644 index 0000000000..9bbb5013c0 --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/test/org/opendaylight/controller/sal/binding/test/GenerationTest.java @@ -0,0 +1,31 @@ +package org.opendaylight.controller.sal.binding.test; +import static org.junit.Assert.*; + +import java.util.concurrent.Future; + +import org.junit.Test; +import org.opendaylight.controller.sal.binding.impl.ProxyFactoryGenerator; +import org.opendaylight.controller.sal.binding.impl.RpcServiceProxy; +import org.opendaylight.yangtools.yang.binding.RpcService; +import org.opendaylight.yangtools.yang.common.RpcResult; + + +public class GenerationTest { + + public interface MockService extends RpcService { + + Future> cancelToast(); + + Future> makeToast(String input); + } + + @Test + public void test() { + ProxyFactoryGenerator generator = new ProxyFactoryGenerator(); + Class> ret = generator.generate(MockService.class); + + assertTrue(RpcServiceProxy.class.isAssignableFrom(ret)); + assertTrue(MockService.class.isAssignableFrom(ret)); + } + +} diff --git a/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/test/java/org/opendaylight/controller/sal/binding/test/RuntimeCodeGeneratorTest.java b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/test/java/org/opendaylight/controller/sal/binding/test/RuntimeCodeGeneratorTest.java new file mode 100644 index 0000000000..5dddd1ab9d --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/test/java/org/opendaylight/controller/sal/binding/test/RuntimeCodeGeneratorTest.java @@ -0,0 +1,142 @@ +package org.opendaylight.controller.sal.binding.test; +import static org.junit.Assert.*; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + +import javassist.ClassPool; + +import org.junit.Before; +import org.junit.Test; +import static org.opendaylight.controller.sal.binding.codegen.RuntimeCodeHelper.*; +import org.opendaylight.controller.sal.binding.codegen.impl.RuntimeCodeGenerator; +import org.opendaylight.controller.sal.binding.test.mock.FooService; +import org.opendaylight.controller.sal.binding.test.mock.ReferencableObject; +import org.opendaylight.controller.sal.binding.test.mock.ReferencableObjectKey; +import org.opendaylight.controller.sal.binding.test.mock.SimpleInput; +import org.opendaylight.yangtools.yang.binding.Augmentation; +import org.opendaylight.yangtools.yang.binding.BaseIdentity; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.IdentifiableItem; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument; + +import static org.mockito.Mockito.*; + + +public class RuntimeCodeGeneratorTest { + + private RuntimeCodeGenerator codeGenerator; + + + @Before + public void initialize() { + this.codeGenerator = new RuntimeCodeGenerator(ClassPool.getDefault()); + } + + @Test + public void testGenerateDirectProxy() { + Class product = codeGenerator.generateDirectProxy(FooService.class); + assertNotNull(product); + } + + @Test + public void testGenerateRouter() throws Exception { + Class product = codeGenerator.generateRouter(FooService.class); + assertNotNull(product); + assertNotNull(product.getSimpleName()); + assertEquals("2 fields should be generated.",2,product.getFields().length); + + verifyRouting(product.newInstance()); + } + + private void verifyRouting(FooService product) { + Map routingTable = new HashMap<>(); + setRoutingTable(product, BaseIdentity.class, routingTable); + + assertSame("Returned routing table should be same instance",routingTable,getRoutingTable(product, BaseIdentity.class)); + + int servicesCount = 2; + int instancesPerService = 3; + + InstanceIdentifier[][] identifiers = identifiers(servicesCount,instancesPerService); + FooService service[] = new FooService[] { + mock(FooService.class, "Instance 0"), + mock(FooService.class,"Instance 1") + }; + + for(int i = 0;i pathArg = new IdentifiableItem<>(ReferencableObject.class,key); + return new InstanceIdentifier(Arrays.asList(pathArg), ReferencableObject.class); + } + + private static class SimpleInputImpl implements SimpleInput { + private final InstanceIdentifier identifier; + + public SimpleInputImpl(InstanceIdentifier _identifier) { + this.identifier = _identifier; + } + + @Override + public > E getAugmentation(Class augmentationType) { + return null; + } + + @Override + public InstanceIdentifier getIdentifier() { + return this.identifier; + } + } +} diff --git a/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/test/java/org/opendaylight/controller/sal/binding/test/mock/BarUpdate.java b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/test/java/org/opendaylight/controller/sal/binding/test/mock/BarUpdate.java new file mode 100644 index 0000000000..b64ebdf86b --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/test/java/org/opendaylight/controller/sal/binding/test/mock/BarUpdate.java @@ -0,0 +1,7 @@ +package org.opendaylight.controller.sal.binding.test.mock; + +import org.opendaylight.yangtools.yang.binding.Notification; + +public interface BarUpdate extends Grouping,Notification { + +} diff --git a/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/test/java/org/opendaylight/controller/sal/binding/test/mock/FooListener.java b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/test/java/org/opendaylight/controller/sal/binding/test/mock/FooListener.java new file mode 100644 index 0000000000..3629689cdf --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/test/java/org/opendaylight/controller/sal/binding/test/mock/FooListener.java @@ -0,0 +1,10 @@ +package org.opendaylight.controller.sal.binding.test.mock; + +import org.opendaylight.yangtools.yang.binding.NotificationListener; + +public interface FooListener extends NotificationListener { + + void onFooUpdate(FooUpdate notification); + void onBarUpdate(BarUpdate notification); + +} diff --git a/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/test/java/org/opendaylight/controller/sal/binding/test/mock/FooService.java b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/test/java/org/opendaylight/controller/sal/binding/test/mock/FooService.java new file mode 100644 index 0000000000..3161e936dc --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/test/java/org/opendaylight/controller/sal/binding/test/mock/FooService.java @@ -0,0 +1,16 @@ +package org.opendaylight.controller.sal.binding.test.mock; + +import java.util.concurrent.Future; + +import org.opendaylight.yangtools.yang.binding.RpcService; +import org.opendaylight.yangtools.yang.common.RpcResult; + +public interface FooService extends RpcService { + + Future> foo(); + + Future> simple(SimpleInput obj); + + Future> inheritedContextInput(InheritedContextInput obj); + +} diff --git a/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/test/java/org/opendaylight/controller/sal/binding/test/mock/FooUpdate.java b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/test/java/org/opendaylight/controller/sal/binding/test/mock/FooUpdate.java new file mode 100644 index 0000000000..a5a5eb8ecb --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/test/java/org/opendaylight/controller/sal/binding/test/mock/FooUpdate.java @@ -0,0 +1,7 @@ +package org.opendaylight.controller.sal.binding.test.mock; + +import org.opendaylight.yangtools.yang.binding.Notification; + +public interface FooUpdate extends Notification { + +} diff --git a/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/test/java/org/opendaylight/controller/sal/binding/test/mock/Grouping.java b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/test/java/org/opendaylight/controller/sal/binding/test/mock/Grouping.java new file mode 100644 index 0000000000..86624e0732 --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/test/java/org/opendaylight/controller/sal/binding/test/mock/Grouping.java @@ -0,0 +1,11 @@ +package org.opendaylight.controller.sal.binding.test.mock; + +import org.opendaylight.yangtools.yang.binding.BaseIdentity; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.yangtools.yang.binding.annotations.RoutingContext; + +public interface Grouping { + + @RoutingContext(BaseIdentity.class) + InstanceIdentifier getInheritedIdentifier(); +} diff --git a/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/test/java/org/opendaylight/controller/sal/binding/test/mock/InheritedContextInput.java b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/test/java/org/opendaylight/controller/sal/binding/test/mock/InheritedContextInput.java new file mode 100644 index 0000000000..39b20cc1f1 --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/test/java/org/opendaylight/controller/sal/binding/test/mock/InheritedContextInput.java @@ -0,0 +1,5 @@ +package org.opendaylight.controller.sal.binding.test.mock; + +public interface InheritedContextInput extends Grouping { + +} diff --git a/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/test/java/org/opendaylight/controller/sal/binding/test/mock/ReferencableObject.java b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/test/java/org/opendaylight/controller/sal/binding/test/mock/ReferencableObject.java new file mode 100644 index 0000000000..8e0d4579eb --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/test/java/org/opendaylight/controller/sal/binding/test/mock/ReferencableObject.java @@ -0,0 +1,8 @@ +package org.opendaylight.controller.sal.binding.test.mock; + +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.Identifiable; + +public interface ReferencableObject extends DataObject,Identifiable { + +} diff --git a/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/test/java/org/opendaylight/controller/sal/binding/test/mock/ReferencableObjectKey.java b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/test/java/org/opendaylight/controller/sal/binding/test/mock/ReferencableObjectKey.java new file mode 100644 index 0000000000..d2e18175e1 --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/test/java/org/opendaylight/controller/sal/binding/test/mock/ReferencableObjectKey.java @@ -0,0 +1,44 @@ +package org.opendaylight.controller.sal.binding.test.mock; + +import org.opendaylight.yangtools.yang.binding.Identifier; + +public class ReferencableObjectKey implements Identifier { + + final Integer value; + + public ReferencableObjectKey(Integer _value) { + this.value = _value; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((value == null) ? 0 : value.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + ReferencableObjectKey other = (ReferencableObjectKey) obj; + if (value == null) { + if (other.value != null) + return false; + } else if (!value.equals(other.value)) + return false; + return true; + } + + @Override + public String toString() { + return "ReferencableObjectKey [value=" + value + "]"; + } + + +} diff --git a/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/test/java/org/opendaylight/controller/sal/binding/test/mock/SimpleInput.java b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/test/java/org/opendaylight/controller/sal/binding/test/mock/SimpleInput.java new file mode 100644 index 0000000000..dedbd9885e --- /dev/null +++ b/opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/test/java/org/opendaylight/controller/sal/binding/test/mock/SimpleInput.java @@ -0,0 +1,13 @@ +package org.opendaylight.controller.sal.binding.test.mock; + +import org.opendaylight.yangtools.yang.binding.Augmentable; +import org.opendaylight.yangtools.yang.binding.BaseIdentity; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.yangtools.yang.binding.annotations.RoutingContext; + +public interface SimpleInput extends DataObject,Augmentable { + + @RoutingContext(BaseIdentity.class) + InstanceIdentifier getIdentifier(); +} -- 2.36.6