Merge "Conversion class ToSalConversionsUtils."
authorEd Warnicke <eaw@cisco.com>
Wed, 18 Sep 2013 15:38:28 +0000 (15:38 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Wed, 18 Sep 2013 15:38:28 +0000 (15:38 +0000)
42 files changed:
opendaylight/connectionmanager/api/src/main/java/org/opendaylight/controller/connectionmanager/ConnectionLocality.java [new file with mode: 0644]
opendaylight/connectionmanager/api/src/main/java/org/opendaylight/controller/connectionmanager/IConnectionManager.java
opendaylight/connectionmanager/implementation/src/main/java/org/opendaylight/controller/connectionmanager/internal/ConnectionManager.java
opendaylight/connectionmanager/implementation/src/main/java/org/opendaylight/controller/connectionmanager/scheme/AbstractScheme.java
opendaylight/forwardingrulesmanager/implementation/src/main/java/org/opendaylight/controller/forwardingrulesmanager/internal/ForwardingRulesManager.java
opendaylight/northbound/commons/pom.xml
opendaylight/northbound/commons/src/main/java/org/opendaylight/controller/northbound/commons/JacksonJsonProcessingExceptionMapper.java [new file with mode: 0644]
opendaylight/northbound/commons/src/main/java/org/opendaylight/controller/northbound/commons/NorthboundApplication.java
opendaylight/northbound/integrationtest/src/test/java/org/opendaylight/controller/northbound/integrationtest/NorthboundIT.java
opendaylight/sal/yang-prototype/sal/model/model-flow-base/src/main/yang/group-types.yang [new file with mode: 0644]
opendaylight/sal/yang-prototype/sal/model/model-flow-service/src/main/yang/group-service.yang [new file with mode: 0644]
opendaylight/sal/yang-prototype/sal/pom.xml
opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/pom.xml
opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/codegen/RuntimeCodeHelper.xtend [new file with mode: 0644]
opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/codegen/RuntimeCodeSpecification.xtend [new file with mode: 0644]
opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/codegen/YangtoolsMappingHelper.xtend [new file with mode: 0644]
opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/codegen/impl/JavassistUtils.java [new file with mode: 0644]
opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/codegen/impl/RoutingPair.xtend [new file with mode: 0644]
opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/codegen/impl/RuntimeCodeGenerator.xtend [new file with mode: 0644]
opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/BindingAwareBrokerImpl.xtend
opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/DataProviderContext.xtend [new file with mode: 0644]
opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/NotificationBrokerImpl.xtend
opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/OsgiConsumerContext.xtend
opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/OsgiProviderContext.xtend
opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/_DataBrokerImpl.xtend [new file with mode: 0644]
opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/osgi/Constants.xtend [moved from opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/Constants.xtend with 84% similarity]
opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/osgi/PropertiesUtils.xtend [new file with mode: 0644]
opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/osgi/package-info.java [new file with mode: 0644]
opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/utils/GeneratorUtils.xtend [deleted file]
opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/utils/PropertiesUtils.xtend [deleted file]
opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/java/org/opendaylight/controller/sal/binding/impl/utils/package-info.java [deleted file]
opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/main/test/org/opendaylight/controller/sal/binding/test/GenerationTest.java [new file with mode: 0644]
opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/test/java/org/opendaylight/controller/sal/binding/test/RuntimeCodeGeneratorTest.java [new file with mode: 0644]
opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/test/java/org/opendaylight/controller/sal/binding/test/mock/BarUpdate.java [new file with mode: 0644]
opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/test/java/org/opendaylight/controller/sal/binding/test/mock/FooListener.java [new file with mode: 0644]
opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/test/java/org/opendaylight/controller/sal/binding/test/mock/FooService.java [new file with mode: 0644]
opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/test/java/org/opendaylight/controller/sal/binding/test/mock/FooUpdate.java [new file with mode: 0644]
opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/test/java/org/opendaylight/controller/sal/binding/test/mock/Grouping.java [new file with mode: 0644]
opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/test/java/org/opendaylight/controller/sal/binding/test/mock/InheritedContextInput.java [new file with mode: 0644]
opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/test/java/org/opendaylight/controller/sal/binding/test/mock/ReferencableObject.java [new file with mode: 0644]
opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/test/java/org/opendaylight/controller/sal/binding/test/mock/ReferencableObjectKey.java [new file with mode: 0644]
opendaylight/sal/yang-prototype/sal/sal-binding-broker-impl/src/test/java/org/opendaylight/controller/sal/binding/test/mock/SimpleInput.java [new file with mode: 0644]

diff --git a/opendaylight/connectionmanager/api/src/main/java/org/opendaylight/controller/connectionmanager/ConnectionLocality.java b/opendaylight/connectionmanager/api/src/main/java/org/opendaylight/controller/connectionmanager/ConnectionLocality.java
new file mode 100644 (file)
index 0000000..347ca07
--- /dev/null
@@ -0,0 +1,28 @@
+package org.opendaylight.controller.connectionmanager;
+
+public enum ConnectionLocality {
+    /**
+     * This controller is the (or one of the) master for a given node
+     */
+    LOCAL("This controller is the (or one of the) master for a given node"),
+
+    /**
+     * This controller is not the master for a given node
+     */
+    NOT_LOCAL("This controller is not the master for a given node"),
+
+    /**
+     * The given node is not connected to any of the controllers in the cluster
+     */
+    NOT_CONNECTED("The given node is not connected to any of the controllers in the cluster");
+
+    private ConnectionLocality(String description) {
+        this.description = description;
+    }
+
+    private String description;
+
+    public String toString() {
+        return description;
+    }
+}
index 12b196989e4a0c4fa1f608cd7a479d224064555c..788af16248ccd62c8cc0760dbcb20134983b3cac 100644 (file)
@@ -54,12 +54,27 @@ public interface IConnectionManager {
     public Set<Node> getLocalNodes();
 
     /**
+     * @deprecated Use getLocalityStatus(Node node) instead.
+     *
      * Method to test if a node is local to a controller.
      *
-     * @return true if node is local to this controller. false otherwise.
+     * @param node The node for which the locality is being tested
+     * @return true if node is local to this controller.<br>
+     *         false if either node is not connected to this controller or
+     *         not connected to any other controllers in the cluster.
      */
     public boolean isLocal(Node node);
 
+    /**
+     * getLocalityStatus provides the tri-state connectivity status as opposed to the
+     * binary status returned by isLocal.
+     * ConnectionLocality enum that is returned by this method also includes the case of
+     * a Node not connected to any of the controllers in the cluster.
+     * @param node The node for which the locality is being verified
+     * @return ConnectionLocality
+     */
+    public ConnectionLocality getLocalityStatus(Node node);
+
     /**
      * Disconnect a Node from the controller.
      *
index bd377190f2d2f2911f3ae9b43edda2b2b0c39bc2..df5175083b1870ef99b29443d42003eb2bb179c5 100644 (file)
@@ -37,6 +37,7 @@ import org.eclipse.osgi.framework.console.CommandProvider;
 import org.opendaylight.controller.clustering.services.ICacheUpdateAware;
 import org.opendaylight.controller.clustering.services.IClusterGlobalServices;
 import org.opendaylight.controller.clustering.services.ICoordinatorChangeAware;
+import org.opendaylight.controller.connectionmanager.ConnectionLocality;
 import org.opendaylight.controller.connectionmanager.ConnectionMgmtScheme;
 import org.opendaylight.controller.connectionmanager.IConnectionManager;
 import org.opendaylight.controller.connectionmanager.scheme.AbstractScheme;
@@ -185,6 +186,13 @@ public class ConnectionManager implements IConnectionManager, IConnectionListene
         return scheme.isLocal(node);
     }
 
+    @Override
+    public ConnectionLocality getLocalityStatus(Node node) {
+        AbstractScheme scheme = schemes.get(activeScheme);
+        if (scheme == null) return ConnectionLocality.NOT_CONNECTED;
+        return scheme.getLocalityStatus(node);
+    }
+
     @Override
     public void updateNode(Node node, UpdateType type, Set<Property> props) {
         logger.debug("updateNode: {} type {} props {}", node, type, props);
index 06b72219f7fbddc5b5b17357f421f003691a36f7..78f274c717585993d13a3deeb86812a32ad4ad5a 100644 (file)
@@ -14,6 +14,7 @@ import org.opendaylight.controller.clustering.services.CacheConfigException;
 import org.opendaylight.controller.clustering.services.CacheExistException;
 import org.opendaylight.controller.clustering.services.IClusterGlobalServices;
 import org.opendaylight.controller.clustering.services.IClusterServices;
+import org.opendaylight.controller.connectionmanager.ConnectionLocality;
 import org.opendaylight.controller.connectionmanager.ConnectionMgmtScheme;
 import org.opendaylight.controller.sal.core.Node;
 import org.opendaylight.controller.sal.utils.Status;
@@ -146,6 +147,15 @@ public abstract class AbstractScheme {
         return (controllers != null && controllers.contains(myController));
     }
 
+    public ConnectionLocality getLocalityStatus(Node node) {
+        if (nodeConnections == null) return ConnectionLocality.NOT_CONNECTED;
+        Set<InetAddress> controllers = nodeConnections.get(node);
+        if (controllers == null || controllers.size() == 0) return ConnectionLocality.NOT_CONNECTED;
+        InetAddress myController = clusterServices.getMyAddress();
+        return controllers.contains(myController) ? ConnectionLocality.LOCAL:
+                                                    ConnectionLocality.NOT_LOCAL;
+    }
+
     public Status removeNode (Node node) {
         return removeNodeFromController(node, clusterServices.getMyAddress());
     }
index 4e6818c3062511b01c9b8f73d3f5fa610c73134d..6e3e6b6633b0fc6098ee6795dac661df71a20fed 100644 (file)
@@ -39,6 +39,7 @@ import org.opendaylight.controller.clustering.services.ICacheUpdateAware;
 import org.opendaylight.controller.clustering.services.IClusterContainerServices;
 import org.opendaylight.controller.clustering.services.IClusterServices;
 import org.opendaylight.controller.configuration.IConfigurationContainerAware;
+import org.opendaylight.controller.connectionmanager.ConnectionLocality;
 import org.opendaylight.controller.connectionmanager.IConnectionManager;
 import org.opendaylight.controller.forwardingrulesmanager.FlowConfig;
 import org.opendaylight.controller.forwardingrulesmanager.FlowEntry;
@@ -273,7 +274,7 @@ public class ForwardingRulesManager implements
         }
 
         Node n = e.getNode();
-        if (!connectionManager.isLocal(n)) {
+        if (connectionManager.getLocalityStatus(n) == ConnectionLocality.NOT_LOCAL) {
             Callable<Future<Status>> worker = new DistributeOrderCallable(e, u, t);
             if (worker != null) {
                 Future<Future<Status>> workerRes = this.executor.submit(worker);
@@ -291,7 +292,7 @@ public class ForwardingRulesManager implements
             }
         }
 
-        logsync.trace("LOCAL Node {} so processing Entry:{} UpdateType:{}", n, e, t);
+        logsync.trace("Node {} could be local. so processing Entry:{} UpdateType:{}", n, e, t);
         return null;
     }
 
@@ -3109,7 +3110,7 @@ public class ForwardingRulesManager implements
                 return;
             }
             Node n = fei.getNode();
-            if (connectionManager.isLocal(n)) {
+            if (connectionManager.getLocalityStatus(n) == ConnectionLocality.LOCAL) {
                 logsync.trace("workOrder for fe {} processed locally", fe);
                 // I'm the controller in charge for the request, queue it for
                 // processing
index 692b17a9a6c5409bdb38d1e729b504a5177a4f27..972bece91fd2ce9e0400bf2500397e76a2d19691 100644 (file)
@@ -48,7 +48,9 @@
               org.osgi.service.packageadmin,
               org.osgi.util.tracker,
               javax.servlet.http,
+              org.codehaus.jackson,
               org.codehaus.jackson.jaxrs,
+              org.codehaus.jackson.map,
               org.slf4j
             </Import-Package>
           </instructions>
diff --git a/opendaylight/northbound/commons/src/main/java/org/opendaylight/controller/northbound/commons/JacksonJsonProcessingExceptionMapper.java b/opendaylight/northbound/commons/src/main/java/org/opendaylight/controller/northbound/commons/JacksonJsonProcessingExceptionMapper.java
new file mode 100644 (file)
index 0000000..ca0d1b7
--- /dev/null
@@ -0,0 +1,37 @@
+/**
+ * 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.northbound.commons;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.core.GenericEntity;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.ExceptionMapper;
+import javax.ws.rs.ext.Provider;
+
+import org.codehaus.jackson.JsonProcessingException;
+
+/**
+ * A custom exception mapper for handling Jackson JsonProcessingException types
+ */
+@Provider
+@Consumes({MediaType.APPLICATION_JSON, "text/json"})
+public class JacksonJsonProcessingExceptionMapper
+    implements ExceptionMapper<JsonProcessingException>
+{
+
+    @Override
+    public Response toResponse(JsonProcessingException exception) {
+        GenericEntity<String> entity =
+                new GenericEntity<String>(exception.getMessage()) {};
+        return Response.status(Response.Status.BAD_REQUEST).entity(entity).build();
+    }
+}
+
index 1d3919f4ea396739af2dfb89a953a24cf59dd5de..5b8219126b8abbb7c82124b22f502505c2791e8c 100644 (file)
@@ -20,6 +20,7 @@ import javax.xml.bind.JAXBException;
 import javax.xml.bind.annotation.XmlRootElement;
 
 import org.codehaus.jackson.jaxrs.JacksonJaxbJsonProvider;
+import org.codehaus.jackson.map.DeserializationConfig;
 import org.opendaylight.controller.northbound.bundlescanner.IBundleScanService;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
@@ -54,7 +55,8 @@ public class NorthboundApplication extends Application {
             }
 
         } );
-        singletons.add(new JacksonJaxbJsonProvider());
+        singletons.add(getJsonProvider());
+        singletons.add(new JacksonJsonProcessingExceptionMapper());
         return singletons;
     }
 
@@ -65,6 +67,13 @@ public class NorthboundApplication extends Application {
         return result;
     }
 
+    private static final JacksonJaxbJsonProvider getJsonProvider() {
+        JacksonJaxbJsonProvider jsonProvider = new JacksonJaxbJsonProvider();
+        jsonProvider.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES,
+                false);
+        return jsonProvider;
+    }
+
     private BundleContext getBundleContext() {
         ClassLoader tlcl = Thread.currentThread().getContextClassLoader();
         Bundle bundle = null;
index 4404951135391f632a968aae8345e472e8f413c0..e7ca7f57822a438e4243a29115fd38f854dce5ed 100644 (file)
@@ -428,6 +428,11 @@ public class NorthboundIT {
         // Test GET deleted subnet1
         result = getJsonResult(baseURL + "default/subnet/" + name1);
         Assert.assertEquals(404, httpResponseCode.intValue());
+
+        // TEST PUT bad subnet, expect 400, validate JSON exception mapper
+        JSONObject joBad = new JSONObject().put("foo", "bar");
+        result = getJsonResult(baseURL + "default/subnet/foo", "PUT", joBad.toString());
+        Assert.assertEquals(400, httpResponseCode.intValue());
   }
 
     @Test
diff --git a/opendaylight/sal/yang-prototype/sal/model/model-flow-base/src/main/yang/group-types.yang b/opendaylight/sal/yang-prototype/sal/model/model-flow-base/src/main/yang/group-types.yang
new file mode 100644 (file)
index 0000000..626eabd
--- /dev/null
@@ -0,0 +1,175 @@
+module opendaylight-group-types {
+    namespace "urn:opendaylight:group:types";
+    prefix group;
+
+    import ietf-inet-types {prefix inet;}
+    import ietf-yang-types {prefix yang;}
+       import opendaylight-flow-types {prefix flow-types;}
+
+    revision "2013-09-17" {
+        description "Initial revision of group service";
+    }
+
+       typedef group-ref {
+               type instance-identifier;
+       }
+       
+       grouping group-types {
+               leaf group-type {
+                       type enumeration {
+                               enum group-all;
+                               enum group_select;
+                               enum group_indirect;
+                               enum group_ff;
+                       }
+               }
+       }
+       
+       grouping group {
+        
+        uses group-types;       
+               
+               leaf group-id {
+            type group-ref;
+        }
+               
+               container buckets {
+                       list bucket {
+                               key "order";
+                               leaf order {
+                                       type int32;
+                               }
+                               
+                               leaf weight {
+                                       type uint16;
+                               }
+                               
+                               leaf watch_port {
+                                       type uint32;
+                               }
+                               
+                               leaf watch_group {
+                                       type uint32;
+                               }
+                               
+                               container actions {
+                                       list action {
+                                               key "action-order";
+                                               leaf action-order {
+                                                       type int32;
+                                               }
+            
+                                               uses flow-types:action;
+                                       }
+                               }
+                       }
+               }
+    }
+       
+       grouping group-statistics-request {
+               list group-stats {
+                       key "group-id";                 
+                       
+                       leaf group-id {
+                               type int32;
+                       }                       
+               }
+       }
+       
+       grouping group-statistics {
+                       
+               leaf group-id {
+            type int32;
+               }
+               
+           leaf ref-count {
+            type yang:counter32;
+               }
+               
+               leaf packet-count {
+            type yang:counter64;
+        } 
+               
+        leaf byte-count {
+            type yang:counter64;
+        }
+
+        container duration {
+            leaf second {
+                type yang:counter32;
+            }
+            leaf nanosecond {
+                type yang:counter32;
+            }
+        }
+               
+               container buckets {
+                       list bucket-counter {
+                               key "order";
+                               leaf order {
+                                       type int32;
+                               }
+                               
+                               leaf packet-count {
+                                       type yang:counter64;
+                               } 
+               
+                               leaf byte-count {
+                                       type yang:counter64;
+                               }
+                       }
+               }               
+    }
+
+       grouping group-statistics-reply {
+               list group-stats {
+                       key "group-stats-order";
+                       leaf group-stats-order {
+                               type int32;
+                       }
+                       
+                       uses group-statistics;
+               }
+       }
+       
+       grouping group-desc-stats {
+               list group-desc-stats {
+                       key "order-id";                 
+                       
+                       leaf order-id {
+                               type int32;
+                       }
+                       
+                       uses group;
+               }
+       }
+       
+    grouping group-features {
+               list group-features {
+                       key "order";
+                       leaf order {
+                               type int32;
+                       }
+                       
+                       uses group-types;
+                       type capabilities {
+                               enum select-weight;
+                               enum select-liveness;
+                               enum chaining;
+                               enum chaining-checks;
+                       }       
+
+                       leaf-list max-groups {
+                               type uint32;
+                               description "Maximum number of groups for each type";
+                               max-elements 4;
+                       }
+                       
+                       leaf-list actions {
+                               type uint32;
+                               description "Bitmap number OFPAT_* that are supported";
+                               max-elements 4;
+                       }
+               }
+       }    
+}
\ No newline at end of file
diff --git a/opendaylight/sal/yang-prototype/sal/model/model-flow-service/src/main/yang/group-service.yang b/opendaylight/sal/yang-prototype/sal/model/model-flow-service/src/main/yang/group-service.yang
new file mode 100644 (file)
index 0000000..1ea2d34
--- /dev/null
@@ -0,0 +1,49 @@
+module sal-group {
+    namespace "urn:opendaylight:group:service";
+    prefix group;
+
+    import yang-ext {prefix ext;}
+    import opendaylight-inventory {prefix inv;}
+    import ietf-inet-types {prefix inet;}
+    import opendaylight-group-types {prefix group-type;}
+
+    revision "2013-09-17" {
+        description "Initial revision of group service";
+    }        
+       
+    grouping node-group {
+        leaf node {
+            type inv:node-ref;
+        }
+        
+        uses group-type:group;
+    }
+
+    /** Base configuration structure **/
+    grouping group-update {
+        container original-group {
+            uses group-type:group;
+        }
+        container updated-group {
+            uses group-type:group;
+        }
+    }
+
+    rpc add-group {
+        input {
+            uses node-group;
+        }
+    }
+
+    rpc remove-group {
+        input {
+            uses node-group;
+        }
+    }
+
+    rpc update-group {
+        input {
+            uses node-group;
+        }
+    }     
+}
\ No newline at end of file
index 0442e8f9b2646d8f9b4d159fdfff7ea1e47d0287..75f9d68bdd816c88a1d85802c386592c24cf9054 100644 (file)
@@ -25,7 +25,7 @@
                <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
                <slf4j.version>1.7.2</slf4j.version>
                <nexusproxy>http://nexus.opendaylight.org/content</nexusproxy>
-               <yang.version>0.5.7-SNAPSHOT</yang.version>
+               <yang.version>0.5.8-SNAPSHOT</yang.version>
                <maven.bundle.version>2.4.0</maven.bundle.version>
         <releaseplugin.version>2.3.2</releaseplugin.version>
         <guava.version>14.0.1</guava.version>
index 549e427d82e816fb4374d3b80b3b44e2b9aeee1d..96a16dcd5772d6000421f680259b3373d4f978c3 100644 (file)
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-       xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-       <modelVersion>4.0.0</modelVersion>
-       <parent>
-               <groupId>org.opendaylight.controller</groupId>
-               <artifactId>sal-parent</artifactId>
-               <version>1.0-SNAPSHOT</version>
-       </parent>
-       <artifactId>sal-binding-broker-impl</artifactId>
-       <packaging>bundle</packaging>
+    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.opendaylight.controller</groupId>
+        <artifactId>sal-parent</artifactId>
+        <version>1.0-SNAPSHOT</version>
+    </parent>
+    <artifactId>sal-binding-broker-impl</artifactId>
+    <packaging>bundle</packaging>
     <scm>
-      <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>
-      <developerConnection>scm:git:ssh://git.opendaylight.org:29418/controller.git</developerConnection>
-      <url>https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL</url>
+        <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>
+        <developerConnection>scm:git:ssh://git.opendaylight.org:29418/controller.git</developerConnection>
+        <url>https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL</url>
     </scm>
 
-       <build>
-               <plugins>
-                       <plugin>
-                               <groupId>org.apache.felix</groupId>
-                               <artifactId>maven-bundle-plugin</artifactId>
-                               <version>${maven.bundle.version}</version>
-                               <extensions>true</extensions>
-                               <configuration>
-                                       <instructions>
-                                               <Bundle-Name>${project.groupId}.${project.artifactId}</Bundle-Name>
-                                               <Bundle-Activator>org.opendaylight.controller.sal.binding.impl.BrokerActivator</Bundle-Activator>
-                                               <Private-Package>
-                                                       org.opendaylight.controller.sal.binding.impl,
-                                                       org.opendaylight.controller.sal.binding.impl.utils,
-                                                       org.eclipse.xtend2.lib,
-                                                       org.eclipse.xtext.xbase.*
-                                               </Private-Package>
-                                       </instructions>
-                               </configuration>
-                       </plugin>
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <version>${maven.bundle.version}</version>
+                <extensions>true</extensions>
+                <configuration>
+                    <instructions>
+                        <Bundle-Name>${project.groupId}.${project.artifactId}</Bundle-Name>
+                        <Bundle-Activator>org.opendaylight.controller.sal.binding.impl.BrokerActivator</Bundle-Activator>
+                        <Private-Package>
+                            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.*
+                        </Private-Package>
+                    </instructions>
+                </configuration>
+            </plugin>
 
-                       <plugin>
-                               <groupId>org.eclipse.xtend</groupId>
-                               <artifactId>xtend-maven-plugin</artifactId>
-                               <version>2.4.2</version>
-                               <executions>
-                                       <execution>
-                                               <goals>
-                                                       <goal>compile</goal>
-                                               </goals>
-                                               <configuration>
-                                                       <outputDirectory>${basedir}/src/main/xtend-gen</outputDirectory>
-                                               </configuration>
-                                       </execution>
-                               </executions>
-                       </plugin>
-                       <plugin>
-                               <artifactId>maven-clean-plugin</artifactId>
-                               <version>2.4.1</version>
-                               <configuration>
-                                       <filesets>
-                                               <fileset>
-                                                       <directory>${basedir}/src/main/xtend-gen</directory>
-                                                       <includes>
-                                                               <include>**</include>
-                                                       </includes>
-                                               </fileset>
-                                       </filesets>
-                               </configuration>
-                       </plugin>
-               </plugins>
-       </build>
+            <plugin>
+                <groupId>org.eclipse.xtend</groupId>
+                <artifactId>xtend-maven-plugin</artifactId>
+                <version>2.4.2</version>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>compile</goal>
+                        </goals>
+                        <configuration>
+                            <outputDirectory>${basedir}/src/main/xtend-gen</outputDirectory>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <artifactId>maven-clean-plugin</artifactId>
+                <version>2.4.1</version>
+                <configuration>
+                    <filesets>
+                        <fileset>
+                            <directory>${basedir}/src/main/xtend-gen</directory>
+                            <includes>
+                                <include>**</include>
+                            </includes>
+                        </fileset>
+                    </filesets>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
 
-       <dependencies>
-               <dependency>
-                       <groupId>org.opendaylight.controller</groupId>
-                       <artifactId>sal-common-util</artifactId>
-                       <version>1.0-SNAPSHOT</version>
-               </dependency>
-               <dependency>
-                       <groupId>org.opendaylight.controller</groupId>
-                       <artifactId>sal-binding-api</artifactId>
-                       <version>1.0-SNAPSHOT</version>
-               </dependency>
-               <!-- >dependency> <groupId>org.opendaylight.controller</groupId> <artifactId>sal-core-api</artifactId> 
-                       <version>1.0-SNAPSHOT</version> </dependency -->
+    <dependencies>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>sal-common-util</artifactId>
+            <version>1.0-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>sal-binding-api</artifactId>
+            <version>1.0-SNAPSHOT</version>
+        </dependency>
+        <!-- >dependency> <groupId>org.opendaylight.controller</groupId> 
+            <artifactId>sal-core-api</artifactId> <version>1.0-SNAPSHOT</version> </dependency -->
 
-               <dependency>
-                       <groupId>org.slf4j</groupId>
-                       <artifactId>slf4j-api</artifactId>
-               </dependency>
-               <dependency>
-                       <groupId>org.osgi</groupId>
-                       <artifactId>org.osgi.core</artifactId>
-                       <version>5.0.0</version>
-               </dependency>
-               <dependency>
-                       <groupId>com.google.guava</groupId>
-                       <artifactId>guava</artifactId>
-               </dependency>
-               <dependency>
-                       <groupId>org.reflections</groupId>
-                       <artifactId>reflections</artifactId>
-                       <version>0.9.9-RC1</version>
-               </dependency>
-               <dependency>
-                       <groupId>org.javassist</groupId>
-                       <artifactId>javassist</artifactId>
-                       <version>3.17.1-GA</version>
-               </dependency>
-               <dependency>
-                       <groupId>org.eclipse.xtend</groupId>
-                       <artifactId>org.eclipse.xtend.lib</artifactId>
-                       <version>2.4.2</version>
-               </dependency>
-       </dependencies>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.core</artifactId>
+            <version>5.0.0</version>
+        </dependency>
+        <dependency>
+            <groupId>com.google.guava</groupId>
+            <artifactId>guava</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.reflections</groupId>
+            <artifactId>reflections</artifactId>
+            <version>0.9.9-RC1</version>
+        </dependency>
+        <dependency>
+            <groupId>org.javassist</groupId>
+            <artifactId>javassist</artifactId>
+            <version>3.17.1-GA</version>
+        </dependency>
+        <dependency>
+            <groupId>org.eclipse.xtend</groupId>
+            <artifactId>org.eclipse.xtend.lib</artifactId>
+            <version>2.4.2</version>
+        </dependency>
+        <dependency>
+            <groupId>org.mockito</groupId>
+            <artifactId>mockito-all</artifactId>
+            <version>1.9.5</version>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
 </project>
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 (file)
index 0000000..6bdb3c8
--- /dev/null
@@ -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 <T extends RpcService> 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<InstanceIdentifier, ? extends RpcService> getRoutingTable(RpcService target,
+        Class<? extends BaseIdentity> 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<InstanceIdentifier, ? extends RpcService>;
+    }
+
+    public static def void setRoutingTable(RpcService target, Class<? extends BaseIdentity> tableClass,
+        Map<InstanceIdentifier, ? extends RpcService> 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 (file)
index 0000000..c6e76c2
--- /dev/null
@@ -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<? extends NotificationListener> listener) {
+        getGeneratedName(listener, INVOKER_SUFFIX);
+    }
+
+    /**
+     * Returns a name for DirectProxy implementation
+     * 
+     * 
+     */
+    public static def getDirectProxyName(Class<? extends RpcService> base) {
+        getGeneratedName(base, DIRECT_PROXY_SUFFIX);
+    }
+
+    /**
+     * Returns a name for Router implementation
+     * 
+     */
+    public static def getRouterName(Class<? extends RpcService> 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<? extends BaseIdentity> 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 (file)
index 0000000..18d3e26
--- /dev/null
@@ -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 (file)
index 0000000..c6be284
--- /dev/null
@@ -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 (file)
index 0000000..4324b4e
--- /dev/null
@@ -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<? extends BaseIdentity> 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 (file)
index 0000000..3b3f419
--- /dev/null
@@ -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 <T extends RpcService> Class<? extends T> generateDirectProxy(Class<T> 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 <T extends RpcService> Class<? extends T> generateRouter(Class<T> iface) {
+        val supertype = iface.asCtClass
+        val targetCls = createClass(iface.routerName, supertype) [
+            //field(ROUTING_TABLE_FIELD,Map)
+            field(DELEGATE_FIELD, iface)
+            val contexts = new HashMap<String, Class<? extends BaseIdentity>>();
+            // 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<? extends NotificationListener> 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)
+        }
+    }
+}
index 2953466b2928a419eb0a2c3a09f4d74b771b7ab9..298a74ece5f71982ae7bcbb48f205e4039c44046 100644 (file)
@@ -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<Class<? extends RpcService>, RpcProxyContext> managedProxies = new HashMap();
     private var NotificationBrokerImpl notifyBroker
     private var ServiceRegistration<NotificationProviderService> 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<String, String>()
         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<? extends RpcService> 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<T>(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 <T extends RpcService> 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 (file)
index 0000000..398a219
--- /dev/null
@@ -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;
+}
index da1ba79997d16a910ccafe023076e72db460ae7c..22db73526e2e2e386636cc8b45320b3c246f24ad 100644 (file)
@@ -45,6 +45,7 @@ class NotificationBrokerImpl implements NotificationProviderService {
         notification.class.interfaces.filter[it != Notification && Notification.isAssignableFrom(it)]
     }
 
+    @SuppressWarnings("unchecked")
     def notifyAll(Collection<NotificationListener<?>> listeners, Notification notification) {
         listeners.forEach[(it as NotificationListener).onNotification(notification)]
     }
index a87fa0642a4eec5b33eca03630e2122f9d01ba61..a9031240c777961e9fdb5ad5bcb642b70c311f0a 100644 (file)
@@ -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 <T extends BindingAwareService> getSALService(Class<T> service) {
-               // SAL Services are global
-               var ref =  bundleContext.getServiceReference(service);
-               return bundleContext.getService(ref) as T;
-       }
-       
-       
-
-       override def <T extends RpcService> T getRpcService(Class<T> 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<T>;
-                               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 <T extends BindingAwareService> getSALService(Class<T> service) {
+
+        // SAL Services are global
+        var ref = bundleContext.getServiceReference(service);
+        return bundleContext.getService(ref) as T;
+    }
+
+    override def <T extends RpcService> T getRpcService(Class<T> 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<T>;
+                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»)'''
+    }
 }
index 195fa8b9597ba19b5784e68e15d8d2fc563eef42..c769ca1ee38509fa3dbebd52948f81735fddf59c 100644 (file)
@@ -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<String, String>();
-        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 (file)
index 0000000..b278df5
--- /dev/null
@@ -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<DataStoreIdentifier, DataProviderContext> dataProviders;
+    var DataProviderContext defaultDataProvider;
+
+    override <T extends DataRoot> getData(DataStoreIdentifier store, Class<T> rootType) {
+        val dataStore = resolveProvider(store, rootType);
+        return dataStore.provider.getData(store, rootType);
+    }
+
+    override <T extends DataRoot> getData(DataStoreIdentifier store, T filter) {
+    }
+
+    override <T extends DataRoot> T getCandidateData(DataStoreIdentifier store, Class<T> rootType) {
+        throw new UnsupportedOperationException("TODO: auto-generated method stub");
+    }
+
+    override <T extends DataRoot> 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<? extends DataRoot> root) {
+    }
+
+}
@@ -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 (file)
index 0000000..d04ca7f
--- /dev/null
@@ -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<String, String> properties, String value) {
+        properties.put(SAL_SERVICE_TYPE, value)
+        return properties
+    }
+
+    static def getSalServiceType(Hashtable<String, String> properties) {
+        return properties.get(SAL_SERVICE_TYPE)
+    }
+
+    static def newProperties() {
+        new Hashtable<String, String>()
+    }
+
+}
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 (file)
index 0000000..d788ccf
--- /dev/null
@@ -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 (file)
index c888121..0000000
+++ /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 (file)
index 7ba62f5..0000000
+++ /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<String,String> properties, String value) {
-               properties.put(Constants.SAL_SERVICE_TYPE,value)
-               return properties
-       }
-       
-       static def getSalServiceType(Hashtable<String,String> properties) {
-               return properties.get(Constants.SAL_SERVICE_TYPE)
-       }
-       
-       static def newProperties() {
-               new Hashtable<String,String>()
-       }
-       
-}
\ 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 (file)
index 5110238..0000000
+++ /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 (file)
index 0000000..9bbb501
--- /dev/null
@@ -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<RpcResult<java.lang.Void>> cancelToast();
+           
+           Future<RpcResult<java.lang.Void>> makeToast(String input);
+       }
+       
+       @Test
+       public void test() {
+               ProxyFactoryGenerator generator = new ProxyFactoryGenerator();
+               Class<? extends RpcServiceProxy<MockService>> 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 (file)
index 0000000..5dddd1a
--- /dev/null
@@ -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<? extends FooService> product = codeGenerator.generateDirectProxy(FooService.class);
+        assertNotNull(product);
+    }
+
+    @Test
+    public void testGenerateRouter() throws Exception {
+        Class<? extends FooService> 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<InstanceIdentifier,FooService> 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<service.length;i++) {
+            for (InstanceIdentifier instance : identifiers[i]) {
+                routingTable.put(instance, service[i]);
+            }
+        }
+        
+        assertEquals("All instances should be registered.", servicesCount*instancesPerService, routingTable.size());
+        
+        SimpleInput[] instance_0_input = new SimpleInputImpl[] {
+            new SimpleInputImpl(identifiers[0][0]),
+            new SimpleInputImpl(identifiers[0][1]),
+            new SimpleInputImpl(identifiers[0][2])
+        };
+        
+        SimpleInput[] instance_1_input = new SimpleInputImpl[] {
+                new SimpleInputImpl(identifiers[1][0]),
+                new SimpleInputImpl(identifiers[1][1]),
+                new SimpleInputImpl(identifiers[1][2])
+        };
+        
+        // We test sending mock messages
+        
+        product.simple(instance_0_input[0]);
+        verify(service[0]).simple(instance_0_input[0]);
+        
+        product.simple(instance_0_input[1]);
+        product.simple(instance_0_input[2]);
+        
+        verify(service[0]).simple(instance_0_input[1]);
+        verify(service[0]).simple(instance_0_input[2]);
+        
+        product.simple(instance_1_input[0]);
+        verify(service[1]).simple(instance_1_input[0]);
+    }
+
+    private InstanceIdentifier[][] identifiers(int serviceSize, int instancesPerService) {
+        InstanceIdentifier[][] ret = new InstanceIdentifier[serviceSize][];
+        int service = 0;
+        for (int i = 0;i<serviceSize;i++) {
+            
+            InstanceIdentifier[] instanceIdentifiers = new InstanceIdentifier[instancesPerService];
+            ret[i] = instanceIdentifiers;
+            for(int id = 0;id<instancesPerService;id++) {
+                instanceIdentifiers[id] = referencableIdentifier(service*instancesPerService+id);
+            }
+            service++;
+        }
+        
+        return ret;
+    }
+
+    private InstanceIdentifier referencableIdentifier(int i) {
+        ReferencableObjectKey key = new ReferencableObjectKey(i);
+        IdentifiableItem<ReferencableObject,ReferencableObjectKey> pathArg = new IdentifiableItem<>(ReferencableObject.class,key);
+        return new InstanceIdentifier(Arrays.<PathArgument>asList(pathArg), ReferencableObject.class);
+    }
+
+    private static class SimpleInputImpl implements SimpleInput {
+        private final InstanceIdentifier identifier;
+
+        public SimpleInputImpl(InstanceIdentifier _identifier) {
+            this.identifier = _identifier;
+        }
+
+        @Override
+        public <E extends Augmentation<SimpleInput>> E getAugmentation(Class<E> 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 (file)
index 0000000..b64ebdf
--- /dev/null
@@ -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 (file)
index 0000000..3629689
--- /dev/null
@@ -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 (file)
index 0000000..3161e93
--- /dev/null
@@ -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<RpcResult<Void>> foo();
+    
+    Future<RpcResult<Void>> simple(SimpleInput obj);
+    
+    Future<RpcResult<Void>> 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 (file)
index 0000000..a5a5eb8
--- /dev/null
@@ -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 (file)
index 0000000..86624e0
--- /dev/null
@@ -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 (file)
index 0000000..39b20cc
--- /dev/null
@@ -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 (file)
index 0000000..8e0d457
--- /dev/null
@@ -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<ReferencableObjectKey> {
+
+}
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 (file)
index 0000000..d2e1817
--- /dev/null
@@ -0,0 +1,44 @@
+package org.opendaylight.controller.sal.binding.test.mock;
+
+import org.opendaylight.yangtools.yang.binding.Identifier;
+
+public class ReferencableObjectKey implements Identifier<ReferencableObject> {
+
+    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 (file)
index 0000000..dedbd98
--- /dev/null
@@ -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<SimpleInput> {
+
+    @RoutingContext(BaseIdentity.class)
+    InstanceIdentifier getIdentifier();
+}