From: Ed Warnicke Date: Wed, 18 Sep 2013 15:36:19 +0000 (+0000) Subject: Merge "Added Router code generation and unit tests for runtime code generator" X-Git-Tag: releasepom-0.1.0~68 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=commitdiff_plain;h=ee00c6cd40491fa11a2928b574adb1a99c709a44;hp=5d796fc880196eeb080f28e4bc0b3f3a57281e8a;p=controller.git Merge "Added Router code generation and unit tests for runtime code generator" --- 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(); +}