Merge "Added uses to extends list. Groupings in YANG are used through key word uses...
authorGiovanni Meo <gmeo@cisco.com>
Tue, 30 Jul 2013 15:46:00 +0000 (15:46 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Tue, 30 Jul 2013 15:46:00 +0000 (15:46 +0000)
27 files changed:
opendaylight/hosttracker/implementation/src/main/java/org/opendaylight/controller/hosttracker/internal/HostTracker.java
opendaylight/hosttracker_new/api/src/main/java/org/opendaylight/controller/hosttracker/Entity.java
opendaylight/hosttracker_new/implementation/src/main/java/org/opendaylight/controller/hosttracker/internal/DeviceManagerImpl.java
opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/vendorextension/v6extension/V6Match.java
opendaylight/protocol_plugins/openflow/src/test/java/org/opendaylight/controller/protocol_plugin/openflow/vendorextension/v6extension/V6ExtensionTest.java
opendaylight/sal/yang-prototype/code-generator/.gitignore
opendaylight/sal/yang-prototype/code-generator/binding-generator-impl/src/main/java/org/opendaylight/controller/sal/binding/yang/types/TypeProviderImpl.java
opendaylight/sal/yang-prototype/code-generator/binding-generator-impl/src/test/java/org/opendaylight/controller/sal/binding/generator/impl/GeneratedTypesTest.java
opendaylight/sal/yang-prototype/code-generator/binding-generator-impl/src/test/resources/demo-topology.yang
opendaylight/sal/yang-prototype/code-generator/binding-generator-impl/src/test/resources/leafref-test-models/abstract-topology@2013-02-08.yang
opendaylight/sal/yang-prototype/code-generator/binding-generator-util/src/main/java/org/opendaylight/controller/binding/generator/util/BindingGeneratorUtil.java
opendaylight/sal/yang-prototype/code-generator/binding-java-api-generator/pom.xml
opendaylight/sal/yang-prototype/code-generator/binding-java-api-generator/src/main/java/org/opendaylight/controller/sal/java/api/generator/BuilderClassDescriptor.java [new file with mode: 0644]
opendaylight/sal/yang-prototype/code-generator/binding-java-api-generator/src/main/java/org/opendaylight/controller/sal/java/api/generator/BuilderGenerator.java [new file with mode: 0644]
opendaylight/sal/yang-prototype/code-generator/binding-java-api-generator/src/main/java/org/opendaylight/controller/sal/java/api/generator/BuilderTemplate.xtend [new file with mode: 0644]
opendaylight/sal/yang-prototype/code-generator/binding-java-api-generator/src/main/java/org/opendaylight/controller/sal/java/api/generator/Constants.java
opendaylight/sal/yang-prototype/code-generator/binding-java-api-generator/src/main/java/org/opendaylight/controller/sal/java/api/generator/GeneratorJavaFile.java
opendaylight/sal/yang-prototype/code-generator/binding-java-api-generator/src/test/java/org/opendaylight/controller/sal/java/api/generator/test/GeneratorJavaFileTest.java
opendaylight/sal/yang-prototype/code-generator/code-generator-demo/pom.xml [deleted file]
opendaylight/sal/yang-prototype/code-generator/code-generator-demo/src/main/java/org/opendaylight/controller/yang/Demo.java [deleted file]
opendaylight/sal/yang-prototype/code-generator/code-generator-demo/src/main/resources/demo-topology.yang [deleted file]
opendaylight/sal/yang-prototype/code-generator/code-generator-demo/src/main/resources/demo/types1.yang [deleted file]
opendaylight/sal/yang-prototype/code-generator/code-generator-demo/src/main/resources/demo/types2.yang [deleted file]
opendaylight/sal/yang-prototype/code-generator/code-generator-demo/src/main/resources/demo/types3.yang [deleted file]
opendaylight/sal/yang-prototype/code-generator/samples/maven-code-gen-sample/src/main/yang/controller-network-ne.yang
opendaylight/sal/yang-prototype/code-generator/samples/maven-code-gen-sample/src/main/yang/demo-topology.yang [moved from opendaylight/sal/yang-prototype/code-generator/code-generator-demo/src/main/resources/test-topology.yang with 66% similarity]
opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/yang/model/util/SchemaContextUtil.java

index 5aa8f10706cae4e774455895fc30642a1fa8049d..f600e6b2acc3afbe456b616ae97aadecfd7f056e 100644 (file)
@@ -323,9 +323,13 @@ public class HostTracker implements IfIptoHost, IfHostListener, ISwitchManagerAw
             logger.debug("hostFind(): Host found for IP: {}", networkAddress.getHostAddress());
             return host;
         }
+
         /* host is not found, initiate a discovery */
+
         hostFinder.find(networkAddress);
+
         /* Also add this host to ARPPending List for any potential retries */
+
         AddtoARPPendingList(networkAddress);
         logger.debug("hostFind(): Host Not Found for IP: {}, Inititated Host Discovery ...",
                 networkAddress.getHostAddress());
@@ -447,7 +451,13 @@ public class HostTracker implements IfIptoHost, IfHostListener, ISwitchManagerAw
     private void replaceHost(InetAddress networkAddr, HostNodeConnector removedHost, HostNodeConnector newHost) {
         newHost.initArpSendCountDown();
         if (hostsDB.replace(networkAddr, removedHost, newHost)) {
-            logger.debug("Host move occurred. Old Host:{}, New Host: {}", removedHost, newHost);
+            logger.debug("Host move occurred: Old Host IP:{}, New Host IP: {}", removedHost.getNetworkAddress()
+                    .getHostAddress(), newHost.getNetworkAddress().getHostAddress());
+            logger.debug("Old Host MAC: {}, New Host MAC: {}",
+                    HexEncode.bytesToHexString(removedHost.getDataLayerAddressBytes()),
+                    HexEncode.bytesToHexString(newHost.getDataLayerAddressBytes()));
+            // Display the Old and New HostNodeConnectors also
+            logger.debug("Old {}, New {}", removedHost, newHost);
         } else {
             /*
              * Host replacement has failed, do the recovery
@@ -518,8 +528,9 @@ public class HostTracker implements IfIptoHost, IfHostListener, ISwitchManagerAw
     @Override
     public void hostListener(HostNodeConnector host) {
 
+        logger.debug("ARP received for Host: IP {}, MAC {}, {}", host.getNetworkAddress().getHostAddress(),
+                HexEncode.bytesToHexString(host.getDataLayerAddressBytes()), host);
         if (hostExists(host)) {
-            logger.debug("ARP received for Host: {}", host);
             HostNodeConnector existinghost = hostsDB.get(host.getNetworkAddress());
             existinghost.initArpSendCountDown();
             return;
@@ -532,6 +543,8 @@ public class HostTracker implements IfIptoHost, IfHostListener, ISwitchManagerAw
     private void notifyHostLearnedOrRemoved(HostNodeConnector host, boolean add) {
         // Update listeners if any
         if (newHostNotify != null) {
+            logger.debug("Notifying Applications for Host {} Being {}", host.getNetworkAddress().getHostAddress(),
+                    add ? "Added" : "Deleted");
             synchronized (this.newHostNotify) {
                 for (IfNewHostNotify ta : newHostNotify) {
                     try {
@@ -563,6 +576,8 @@ public class HostTracker implements IfIptoHost, IfHostListener, ISwitchManagerAw
         }
 
         if (topologyManager != null && p != null && h != null) {
+            logger.debug("Notifying Topology Manager for Host {} Being {}", h.getNetworkAddress().getHostAddress(),
+                    add ? "Added" : "Deleted");
             if (add == true) {
                 Tier tier = new Tier(1);
                 switchManager.setNodeProp(node, tier);
@@ -881,8 +896,12 @@ public class HostTracker implements IfIptoHost, IfHostListener, ISwitchManagerAw
             for (int i = 0; i < failedARPReqList.size(); i++) {
                 ARPPending arphost;
                 arphost = failedARPReqList.get(i);
-                logger.debug("Sending the ARP from FailedARPReqList fors IP: {}", arphost.getHostIP().getHostAddress());
-                hostFinder.find(arphost.getHostIP());
+                if (hostFinder == null) {
+                    logger.warn("ARPHandler Services are not available on subnet addition");
+                    continue;
+                }
+               logger.debug("Sending the ARP from FailedARPReqList fors IP: {}", arphost.getHostIP().getHostAddress());
+               hostFinder.find(arphost.getHostIP());
             }
         }
     }
@@ -898,18 +917,23 @@ public class HostTracker implements IfIptoHost, IfHostListener, ISwitchManagerAw
                 if (arphost.getSent_count() < switchManager.getHostRetryCount()) {
                     /*
                      * No reply has been received of first ARP Req, send the
-                     * next one
+                     * next one. Before sending the ARP, check if ARPHandler
+                     * is available or not
                      */
+                    if (hostFinder == null) {
+                        logger.warn("ARPHandler Services are not available for Outstanding ARPs");
+                        continue;
+                    }
                     hostFinder.find(arphost.getHostIP());
                     arphost.sent_count++;
                     logger.debug("ARP Sent from ARPPending List, IP: {}", arphost.getHostIP().getHostAddress());
                 } else if (arphost.getSent_count() >= switchManager.getHostRetryCount()) {
                     /*
-                     * Two ARP requests have been sent without receiving a
+                     * ARP requests have been sent without receiving a
                      * reply, remove this from the pending list
                      */
                     removePendingARPFromList(i);
-                    logger.debug("ARP reply not received after two attempts, removing from Pending List IP: {}",
+                    logger.debug("ARP reply not received after multiple attempts, removing from Pending List IP: {}",
                             arphost.getHostIP().getHostAddress());
                     /*
                      * Add this host to a different list which will be processed
@@ -973,6 +997,15 @@ public class HostTracker implements IfIptoHost, IfHostListener, ISwitchManagerAw
                                         HexEncode.bytesToHexString(host.getDataLayerAddressBytes()) });
                     }
                     host.setArpSendCountDown(arp_cntdown);
+                    if (hostFinder == null) {
+                        /*
+                         * If hostfinder is not available, then can't send the
+                         * probe. However, continue the age out the hosts since
+                         * we don't know if the host is indeed out there or not.
+                         */
+                        logger.warn("ARPHandler is not avaialable, can't send the probe");
+                        continue;
+                    }
                     hostFinder.probe(host);
                 }
             }
@@ -1254,6 +1287,12 @@ public class HostTracker implements IfIptoHost, IfHostListener, ISwitchManagerAw
         for (int i = 0; i < failedARPReqList.size(); i++) {
             arphost = failedARPReqList.get(i);
             logger.debug("Sending the ARP from FailedARPReqList fors IP: {}", arphost.getHostIP().getHostAddress());
+            if (hostFinder == null) {
+                logger.warn("ARPHandler is not available at interface  up");
+                logger.warn("Since this event is missed, host(s) connected to interface {} may not be discovered",
+                        nodeConnector);
+                continue;
+            }
             hostFinder.find(arphost.getHostIP());
         }
         HostNodeConnector host = inactiveStaticHosts.get(nodeConnector);
index 7c98e9505b28b1b51098a9d9c9c3e29ab9af6a2c..924d0717e966aa4731aa340e67a54efe18cbf991 100644 (file)
 
 package org.opendaylight.controller.hosttracker;
 
+import java.net.InetAddress;
 import java.util.Date;
 
+import org.opendaylight.controller.hosttracker.hostAware.HostNodeConnector;
 import org.opendaylight.controller.sal.core.NodeConnector;
+import org.opendaylight.controller.sal.utils.NetUtils;
 
 /**
  * An entity on the network is a visible trace of a device that corresponds to a
@@ -218,6 +221,19 @@ public class Entity implements Comparable<Entity> {
         return true;
     }
 
+    public HostNodeConnector toHostNodeConnector() {
+        try {
+            NodeConnector n = this.getPort();
+            InetAddress ip = InetAddress.getByAddress(NetUtils.intToByteArray4(this.getIpv4Address()));
+            byte[] macAddr = NetUtils.longToByteArray6(this.getMacAddress());
+            HostNodeConnector nc = new HostNodeConnector(macAddr, ip, n,
+                    (short) 0);
+            return nc;
+        } catch (Exception e) {
+            return null;
+        }
+    }
+
     @Override
     public String toString() {
         return "Entity [macAddress=" + macAddress + ", ipv4Address="
index 0a6c2713dde0a2e6a0087f7d7c889e5d77668765..95d33ceef90fcaf019cead9ffe9a2a97858e8e47 100755 (executable)
@@ -52,6 +52,7 @@ import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
+import java.util.Map.Entry;
 import java.util.Queue;
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
@@ -77,6 +78,8 @@ import org.opendaylight.controller.sal.core.Host;
 import org.opendaylight.controller.sal.core.Node;
 import org.opendaylight.controller.sal.core.NodeConnector;
 import org.opendaylight.controller.sal.core.NodeConnector.NodeConnectorIDType;
+import org.opendaylight.controller.sal.core.Property;
+import org.opendaylight.controller.sal.core.State;
 import org.opendaylight.controller.sal.core.Tier;
 import org.opendaylight.controller.sal.core.UpdateType;
 import org.opendaylight.controller.sal.packet.ARP;
@@ -96,6 +99,7 @@ import org.opendaylight.controller.sal.utils.NetUtils;
 import org.opendaylight.controller.sal.utils.SingletonTask;
 import org.opendaylight.controller.sal.utils.Status;
 import org.opendaylight.controller.sal.utils.StatusCode;
+import org.opendaylight.controller.switchmanager.IInventoryListener;
 import org.opendaylight.controller.switchmanager.ISwitchManager;
 import org.opendaylight.controller.topologymanager.ITopologyManager;
 import org.opendaylight.controller.topologymanager.ITopologyManagerAware;
@@ -110,7 +114,8 @@ import org.slf4j.LoggerFactory;
  * @author readams
  */
 public class DeviceManagerImpl implements IDeviceService, IEntityClassListener,
-        IListenDataPacket, ITopologyManagerAware, IfIptoHost {
+        IListenDataPacket, ITopologyManagerAware, IfIptoHost,
+        IInventoryListener {
     protected static Logger logger = LoggerFactory
             .getLogger(DeviceManagerImpl.class);
 
@@ -222,6 +227,7 @@ public class DeviceManagerImpl implements IDeviceService, IEntityClassListener,
      */
     protected ConcurrentHashMap<Long, Device> deviceMap;
 
+    protected ConcurrentHashMap<NodeConnector, Entity> inactiveStaticDevices;
     /**
      * Counter used to generate device keys
      */
@@ -305,7 +311,9 @@ public class DeviceManagerImpl implements IDeviceService, IEntityClassListener,
     /**
      * Using the IfNewHostNotify to notify listeners of host changes.
      */
-    private Set<IfNewHostNotify> newHostNotify = Collections.synchronizedSet(new HashSet<IfNewHostNotify>());
+    private Set<IfNewHostNotify> newHostNotify = Collections
+            .synchronizedSet(new HashSet<IfNewHostNotify>());
+
     /**
      * A device update event to be dispatched
      */
@@ -445,11 +453,11 @@ public class DeviceManagerImpl implements IDeviceService, IEntityClassListener,
     // Dependency injection
     // ********************
 
-    void setNewHostNotify(IfNewHostNotify obj){
+    void setNewHostNotify(IfNewHostNotify obj) {
         this.newHostNotify.add(obj);
     }
 
-    void unsetNewHostNotify(IfNewHostNotify obj){
+    void unsetNewHostNotify(IfNewHostNotify obj) {
         this.newHostNotify.remove(obj);
     }
 
@@ -496,6 +504,7 @@ public class DeviceManagerImpl implements IDeviceService, IEntityClassListener,
         secondaryIndexMap = new HashMap<EnumSet<DeviceField>, DeviceIndex>();
 
         deviceMap = new ConcurrentHashMap<Long, Device>();
+        inactiveStaticDevices = new ConcurrentHashMap<NodeConnector, Entity>();
         classStateMap = new ConcurrentHashMap<String, ClassState>();
         apComparator = new AttachmentPointComparator();
 
@@ -804,11 +813,11 @@ public class DeviceManagerImpl implements IDeviceService, IEntityClassListener,
         if (inPkt == null) {
             return PacketResult.IGNORED;
         }
-//        try {
-//            throw new Exception("Sample");
-//        } catch (Exception e) {
-//            logger.error("Sample stack trace", e);
-//        }
+        // try {
+        // throw new Exception("Sample");
+        // } catch (Exception e) {
+        // logger.error("Sample stack trace", e);
+        // }
 
         Packet formattedPak = this.dataPacketService.decodeDataPacket(inPkt);
         Ethernet eth;
@@ -1469,14 +1478,16 @@ public class DeviceManagerImpl implements IDeviceService, IEntityClassListener,
 
     protected void notifyListeners(List<IDeviceListener> listeners,
             DeviceUpdate update) {
-       // Topology update is for some reason outside of listeners registry
-       // logic
+        // Topology update is for some reason outside of listeners registry
+        // logic
         Entity[] ents = update.device.getEntities();
-        Entity e = ents[ents.length-1];
+        Entity e = ents[ents.length - 1];
+
         NodeConnector p = e.getPort();
         Node node = p.getNode();
         Host h = null;
         try {
+
             byte[] mac = NetUtils.longToByteArray6(e.getMacAddress());
             DataLinkAddress dla = new EthernetAddress(
                     mac);
@@ -1487,7 +1498,7 @@ public class DeviceManagerImpl implements IDeviceService, IEntityClassListener,
         } catch (ConstructionException ce) {
             p = null;
             h = null;
-        } catch (UnknownHostException ue){
+        } catch (UnknownHostException ue) {
             p = null;
             h = null;
         }
@@ -1512,19 +1523,20 @@ public class DeviceManagerImpl implements IDeviceService, IEntityClassListener,
             return;
         }
         /**
-         * TODO: IfNewHostNotify is needed for current controller API.
-         * Adding logic so that existing apps (like SimpleForwardingManager)
-         * work.  IDeviceListener adds additional methods and uses IListener's
-         * callback ordering.  The two interfaces need to be merged.
+         * TODO: IfNewHostNotify is needed for current controller API. Adding
+         * logic so that existing apps (like SimpleForwardingManager) work.
+         * IDeviceListener adds additional methods and uses IListener's callback
+         * ordering. The two interfaces need to be merged.
          */
 
-        for (IfNewHostNotify notify : newHostNotify){
+        for (IfNewHostNotify notify : newHostNotify) {
             switch (update.change) {
             case ADD:
                 notify.notifyHTClient(update.device.toHostNodeConnector());
                 break;
             case DELETE:
-                notify.notifyHTClientHostRemoved(update.device.toHostNodeConnector());
+                notify.notifyHTClientHostRemoved(update.device
+                        .toHostNodeConnector());
                 break;
             case CHANGE:
             }
@@ -1953,19 +1965,21 @@ public class DeviceManagerImpl implements IDeviceService, IEntityClassListener,
             }
         }
     }
+
     /**
-     * Send update notifications to listeners.
-     * IfNewHostNotify listeners need to remove old device and add new device.
+     * Send update notifications to listeners. IfNewHostNotify listeners need to
+     * remove old device and add new device.
+     *
      * @param device
      * @param oldDevice
      */
-    protected void sendDeviceMovedNotification(Device device, Device oldDevice){
-        for (IfNewHostNotify notify : newHostNotify){
-                notify.notifyHTClientHostRemoved(oldDevice.toHostNodeConnector());
-                notify.notifyHTClient(device.toHostNodeConnector());
-            }
-        sendDeviceMovedNotification(device);
+    protected void sendDeviceMovedNotification(Device device, Device oldDevice) {
+        for (IfNewHostNotify notify : newHostNotify) {
+            notify.notifyHTClientHostRemoved(oldDevice.toHostNodeConnector());
+            notify.notifyHTClient(device.toHostNodeConnector());
         }
+        sendDeviceMovedNotification(device);
+    }
 
     /**
      * this method will reclassify and reconcile a device - possibilities are -
@@ -2041,7 +2055,7 @@ public class DeviceManagerImpl implements IDeviceService, IEntityClassListener,
         return mac;
     }
 
-    /**
+     /**
      * Accepts an IPv4 address in a byte array and returns the corresponding
      * 32-bit integer value.
      *
@@ -2205,7 +2219,7 @@ public class DeviceManagerImpl implements IDeviceService, IEntityClassListener,
         Set<HostNodeConnector> nc = new HashSet<HostNodeConnector>();
         while (i.hasNext()) {
             Device device = i.next();
-            if(device.isStaticHost())
+            if (device.isStaticHost())
                 nc.add(device.toHostNodeConnector());
         }
         return nc;
@@ -2213,22 +2227,38 @@ public class DeviceManagerImpl implements IDeviceService, IEntityClassListener,
 
     @Override
     public Set<HostNodeConnector> getInactiveStaticHosts() {
-        // TODO Auto-generated method stub
-        return null;
+        Collection<Entity> devices = Collections
+                .unmodifiableCollection(inactiveStaticDevices.values());
+        Iterator<Entity> i = devices.iterator();
+        Set<HostNodeConnector> nc = new HashSet<HostNodeConnector>();
+        while (i.hasNext()) {
+            Entity ent = i.next();
+                nc.add(ent.toHostNodeConnector());
+
+        }
+        return nc;
     }
 
     @Override
     public Status addStaticHost(String networkAddress, String dataLayerAddress,
             NodeConnector nc, String vlan) {
         Long mac = HexEncode.stringToLong(dataLayerAddress);
-        try{
+        try {
             InetAddress addr = InetAddress.getByName(networkAddress);
             int ip = toIPv4Address(addr.getAddress());
             Entity e = new Entity(mac, Short.valueOf(vlan), ip, nc, new Date());
-            Device d = this.learnDeviceByEntity(e);
-            d.setStaticHost(true);
+
+            if (switchManager.isNodeConnectorEnabled(e.getPort())) {
+                Device d = this.learnDeviceByEntity(e);
+                d.setStaticHost(true);
+            } else {
+                logger.debug(
+                        "Switch or switchport is not up, adding host {} to inactive list",
+                        addr.getHostName());
+                 inactiveStaticDevices.put(e.getPort(), e);
+            }
             return new Status(StatusCode.SUCCESS);
-        }catch(UnknownHostException e){
+        } catch (UnknownHostException e) {
             return new Status(StatusCode.INTERNALERROR);
         }
     }
@@ -2237,26 +2267,122 @@ public class DeviceManagerImpl implements IDeviceService, IEntityClassListener,
     public Status removeStaticHost(String networkAddress) {
         Integer addr;
         try {
-            addr = toIPv4Address(InetAddress.getByName(networkAddress).getAddress());
+            addr = toIPv4Address(InetAddress.getByName(networkAddress)
+                    .getAddress());
         } catch (UnknownHostException e) {
             return new Status(StatusCode.NOTFOUND, "Host does not exist");
         }
-        Iterator<Device> di = this.getDeviceIteratorForQuery(null, null, addr, null);
-        List<IDeviceListener> listeners = deviceListeners
-                .getOrderedListeners();
-        while(di.hasNext()){
+        Iterator<Device> di = this.getDeviceIteratorForQuery(null, null, addr,
+                null);
+        List<IDeviceListener> listeners = deviceListeners.getOrderedListeners();
+        while (di.hasNext()) {
             Device d = di.next();
-            if(d.isStaticHost()){
+            if (d.isStaticHost()) {
                 deleteDevice(d);
                 for (IfNewHostNotify notify : newHostNotify)
                     notify.notifyHTClientHostRemoved(d.toHostNodeConnector());
                 for (IDeviceListener listener : listeners)
-                        listener.deviceRemoved(d);
+                    listener.deviceRemoved(d);
+            }
+        }
+        //go through inactive entites.
+        Set<HostNodeConnector> inactive = this.getInactiveStaticHosts();
+        for(HostNodeConnector nc : inactive){
+            Integer ip =toIPv4Address(nc.getNetworkAddress().getAddress());
+            if(ip.equals(addr)){
+                this.inactiveStaticDevices.remove(nc.getnodeConnector());
             }
         }
+
+
         return new Status(StatusCode.SUCCESS);
     }
 
+    @Override
+    public void notifyNode(Node node, UpdateType type,
+            Map<String, Property> propMap) {
+        if (node == null)
+            return;
+        List<IDeviceListener> listeners = deviceListeners.getOrderedListeners();
+        switch (type) {
+        case REMOVED:
+            logger.debug("Received removed node {}", node);
+            for (Entry<Long, Device> d : deviceMap.entrySet()) {
+                Device device = d.getValue();
+                HostNodeConnector host = device.toHostNodeConnector();
+                if (host.getnodeconnectorNode().equals(node)) {
+                    logger.debug("Node: {} is down, remove from Hosts_DB", node);
+                    deleteDevice(device);
+                    for (IfNewHostNotify notify : newHostNotify)
+                        notify.notifyHTClientHostRemoved(host);
+                    for (IDeviceListener listener : listeners)
+                        listener.deviceRemoved(device);
+                }
+            }
+            break;
+        default:
+            break;
+        }
+    }
+
+    @Override
+    public void notifyNodeConnector(NodeConnector nodeConnector,
+            UpdateType type, Map<String, Property> propMap) {
+        if (nodeConnector == null)
+            return;
+        List<IDeviceListener> listeners = deviceListeners.getOrderedListeners();
+        boolean up = false;
+        switch (type) {
+        case ADDED:
+            up = true;
+            break;
+        case REMOVED:
+            break;
+        case CHANGED:
+            State state = (State) propMap.get(State.StatePropName);
+            if ((state != null) && (state.getValue() == State.EDGE_UP)) {
+                up = true;
+            }
+            break;
+        default:
+            return;
+        }
+
+        if (up) {
+            logger.debug("handleNodeConnectorStatusUp {}", nodeConnector);
+
+            Entity ent = inactiveStaticDevices.get(nodeConnector);
+            Device device = this.learnDeviceByEntity(ent);
+            if(device!=null){
+                HostNodeConnector host = device.toHostNodeConnector();
+                if (host != null) {
+                    inactiveStaticDevices.remove(nodeConnector);
+                    for (IfNewHostNotify notify : newHostNotify)
+                        notify.notifyHTClient(host);
+                    for (IDeviceListener listener : listeners)
+                        listener.deviceAdded(device);
+                } else {
+                    logger.debug("handleNodeConnectorStatusDown {}", nodeConnector);
+                }
+            }
+        }else{
+                // remove all devices on the node that went down.
+                for (Entry<Long, Device> entry : deviceMap.entrySet()) {
+                    Device device = entry.getValue();
+                    HostNodeConnector host = device.toHostNodeConnector();
+                    if (host.getnodeConnector().equals(nodeConnector)) {
+                        deleteDevice(device);
+                        for (IfNewHostNotify notify : newHostNotify)
+                            notify.notifyHTClientHostRemoved(host);
+                        for (IDeviceListener listener : listeners)
+                            listener.deviceRemoved(device);
+                    }
+                }
+
+            }
+        }
+
+
     /**
      * For testing: consolidate the store NOW
      */
index 6c26af2dc710e91eb8bcc6e11d9b4fef2bac8f14..4daa591ba1e1811c9262b5c1a806d7fa7180a763 100644 (file)
@@ -1,4 +1,3 @@
-
 /*
  * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
  *
@@ -27,9 +26,8 @@ import org.slf4j.LoggerFactory;
  * This Class forms the vendor specific IPv6 Flow Match messages as well as
  * processes the vendor specific IPv6 Stats Reply message.
  *
- * For message creation, it parses the user entered IPv6 match fields, creates
- * a sub-message for each field which are later used to form the complete
- * message.
+ * For message creation, it parses the user entered IPv6 match fields, creates a
+ * sub-message for each field which are later used to form the complete message.
  *
  * For message processing, it parses the incoming message and reads each field
  * of the message and stores in appropriate field of V6Match object.
@@ -44,8 +42,7 @@ public class V6Match extends OFMatch implements Cloneable {
     protected short inputPortMask;
     protected byte[] dataLayerSourceMask;
     protected byte[] dataLayerDestinationMask;
-    protected short dataLayerVirtualLanMask;
-    protected byte dataLayerVirtualLanPriorityCodePointMask;
+    protected int dataLayerVirtualLanTCIMask;
     protected short dataLayerTypeMask;
     protected byte networkTypeOfServiceMask;
     protected byte networkProtocolMask;
@@ -57,7 +54,9 @@ public class V6Match extends OFMatch implements Cloneable {
     protected MatchFieldState inputPortState;
     protected MatchFieldState dlSourceState;
     protected MatchFieldState dlDestState;
-    protected MatchFieldState dlVlanState;
+    protected MatchFieldState dlVlanIDState;
+    protected MatchFieldState dlVlanPCPState;
+    protected MatchFieldState dlVlanTCIState;
     protected MatchFieldState ethTypeState;
     protected MatchFieldState nwTosState;
     protected MatchFieldState nwProtoState;
@@ -131,8 +130,7 @@ public class V6Match extends OFMatch implements Cloneable {
         this.dataLayerSourceMask = null;
         this.dataLayerDestinationMask = null;
         this.dataLayerTypeMask = 0;
-        this.dataLayerVirtualLanMask = 0;
-        this.dataLayerVirtualLanPriorityCodePointMask = 0;
+        this.dataLayerVirtualLanTCIMask = 0;
         this.networkTypeOfServiceMask = 0;
         this.networkProtocolMask = 0;
         this.transportSourceMask = 0;
@@ -141,7 +139,9 @@ public class V6Match extends OFMatch implements Cloneable {
         this.inputPortState = MatchFieldState.MATCH_ABSENT;
         this.dlSourceState = MatchFieldState.MATCH_ABSENT;
         this.dlDestState = MatchFieldState.MATCH_ABSENT;
-        this.dlVlanState = MatchFieldState.MATCH_ABSENT;
+        this.dlVlanIDState = MatchFieldState.MATCH_ABSENT;
+        this.dlVlanPCPState = MatchFieldState.MATCH_ABSENT;
+        this.dlVlanTCIState = MatchFieldState.MATCH_ABSENT;
         this.ethTypeState = MatchFieldState.MATCH_ABSENT;
         this.nwTosState = MatchFieldState.MATCH_ABSENT;
         this.nwProtoState = MatchFieldState.MATCH_ABSENT;
@@ -162,7 +162,7 @@ public class V6Match extends OFMatch implements Cloneable {
         if (match.getNetworkSource() != 0) {
             InetAddress address = NetUtils.getInetAddress(match.getNetworkSource());
             InetAddress mask = NetUtils.getInetNetworkMask(match.getNetworkSourceMaskLen(), false);
-            this.setNetworkDestination(address, mask);
+            this.setNetworkSource(address, mask);
         } else {
             this.nwSrcState = MatchFieldState.MATCH_ABSENT;
         }
@@ -184,13 +184,15 @@ public class V6Match extends OFMatch implements Cloneable {
         }
 
         this.dataLayerSourceMask = null;
-        if (match.getDataLayerSource() != null && !NetUtils.isZeroMAC(match.getDataLayerSource())) {
+        if (match.getDataLayerSource() != null
+                && !NetUtils.isZeroMAC(match.getDataLayerSource())) {
             this.setDataLayerSource(match.getDataLayerSource(), null);
         } else {
             this.dlSourceState = MatchFieldState.MATCH_ABSENT;
         }
         this.dataLayerDestinationMask = null;
-        if (match.getDataLayerDestination() != null && !NetUtils.isZeroMAC(match.getDataLayerDestination())) {
+        if (match.getDataLayerDestination() != null
+                && !NetUtils.isZeroMAC(match.getDataLayerDestination())) {
             this.setDataLayerDestination(match.getDataLayerDestination(), null);
         } else {
             this.dlDestState = MatchFieldState.MATCH_ABSENT;
@@ -204,27 +206,28 @@ public class V6Match extends OFMatch implements Cloneable {
             this.ethTypeState = MatchFieldState.MATCH_ABSENT;
         }
 
-        this.dataLayerVirtualLanMask = 0;
+        this.dataLayerVirtualLanTCIMask = 0;
+        this.dlVlanTCIState = MatchFieldState.MATCH_ABSENT;
         if (match.getDataLayerVirtualLan() != 0) {
             this.setDataLayerVirtualLan(match.getDataLayerVirtualLan(),
                     (short) 0);
         } else {
             this.dataLayerVirtualLan = 0;
-            this.dlVlanState = MatchFieldState.MATCH_ABSENT;
+            this.dlVlanIDState = MatchFieldState.MATCH_ABSENT;
         }
 
-        this.dataLayerVirtualLanPriorityCodePointMask = 0;
         if (match.getDataLayerVirtualLanPriorityCodePoint() != 0) {
-            this.setDataLayerVirtualLanPriorityCodePoint(match
-                    .getDataLayerVirtualLanPriorityCodePoint(), (byte) 0);
+            this.setDataLayerVirtualLanPriorityCodePoint(
+                    match.getDataLayerVirtualLanPriorityCodePoint(), (byte) 0);
         } else {
             this.dataLayerVirtualLanPriorityCodePoint = 0;
+            this.dlVlanPCPState = MatchFieldState.MATCH_ABSENT;
         }
 
         this.networkProtocolMask = 0;
         if (match.getNetworkProtocol() != 0) {
-            this.setNetworkProtocol(this.networkProtocol = match
-                    .getNetworkProtocol(), (byte) 0);
+            this.setNetworkProtocol(
+                    this.networkProtocol = match.getNetworkProtocol(), (byte) 0);
         } else {
             this.networkProtocol = 0;
             this.nwProtoState = MatchFieldState.MATCH_ABSENT;
@@ -232,8 +235,9 @@ public class V6Match extends OFMatch implements Cloneable {
 
         this.networkTypeOfServiceMask = 0;
         if (match.getNetworkTypeOfService() != 0) {
-            this.setNetworkTypeOfService(this.networkTypeOfService = match
-                    .getNetworkTypeOfService(), (byte) 0);
+            this.setNetworkTypeOfService(
+                    this.networkTypeOfService = match.getNetworkTypeOfService(),
+                    (byte) 0);
         } else {
             this.networkTypeOfService = match.getNetworkTypeOfService();
             this.nwTosState = MatchFieldState.MATCH_ABSENT;
@@ -327,13 +331,47 @@ public class V6Match extends OFMatch implements Cloneable {
         return (ipv6ext_etype_msg.array());
     }
 
-    private byte[] getIPv6ExtensionVlanIDMatchMsg(short VLAN) {
-        ByteBuffer ipv6ext_vlanid_msg = ByteBuffer.allocate(6);
+    private byte[] getVlanTCI(short dataLayerVirtualLanID,
+            byte dataLayerVirtualLanPriorityCodePoint) {
+        ByteBuffer vlan_tci = ByteBuffer.allocate(2);
+        int cfi = 1 << 12; // the cfi bit is in position 12
+        int pcp = dataLayerVirtualLanPriorityCodePoint << 13; // the pcp fields
+                                                              // have to move by
+                                                              // 13
+        int vlan_tci_int = pcp + cfi + dataLayerVirtualLanID;
+        vlan_tci.put((byte) (vlan_tci_int >> 8)); // bits 8 to 15
+        vlan_tci.put((byte) vlan_tci_int); // bits 0 to 7
+        return vlan_tci.array();
+    }
+
+    private byte[] getIPv6ExtensionVlanTCIMatchMsg(short dataLayerVirtualLanID,
+            byte dataLayerVirtualLanPriorityCodePoint) {
+        ByteBuffer ipv6ext_vlan_tci_msg = ByteBuffer.allocate(6);
         int nxm_header = getIPv6ExtensionMatchHeader(Extension_Types.OF_10,
                 OF_Match_Types.MATCH_OF_VLAN_TCI.getValue(), 0, 2);
-        ipv6ext_vlanid_msg.putInt(nxm_header);
-        ipv6ext_vlanid_msg.putShort(VLAN);
-        return (ipv6ext_vlanid_msg.array());
+        ipv6ext_vlan_tci_msg.putInt(nxm_header);
+        ipv6ext_vlan_tci_msg.put(getVlanTCI(dataLayerVirtualLanID,
+                dataLayerVirtualLanPriorityCodePoint));
+        return (ipv6ext_vlan_tci_msg.array());
+    }
+
+    private byte[] getIPv6ExtensionVlanTCIMatchWithMaskMsg(
+            short dataLayerVirtualLan,
+            byte dataLayerVirtualLanPriorityCodePoint,
+            int dataLayerVirtualLanTCIMask) {
+        ByteBuffer ipv6ext_vlan_tci_msg = ByteBuffer.allocate(8);
+        int nxm_header = getIPv6ExtensionMatchHeader(Extension_Types.OF_10,
+                OF_Match_Types.MATCH_OF_VLAN_TCI.getValue(), 1, 4);
+        ipv6ext_vlan_tci_msg.putInt(nxm_header);
+        ipv6ext_vlan_tci_msg.put(getVlanTCI(dataLayerVirtualLan,
+                dataLayerVirtualLanPriorityCodePoint));
+        ipv6ext_vlan_tci_msg.put((byte) (dataLayerVirtualLanTCIMask >> 8)); // bits
+                                                                            // 8
+                                                                            // to
+                                                                            // 15
+        ipv6ext_vlan_tci_msg.put((byte) (dataLayerVirtualLanTCIMask)); // bits 0
+                                                                       // to 7
+        return (ipv6ext_vlan_tci_msg.array());
     }
 
     private byte[] getIPv6ExtensionSrcIPv6MatchMsg(byte[] srcIpv6) {
@@ -392,11 +430,10 @@ public class V6Match extends OFMatch implements Cloneable {
         ipv6ext_proto_msg.putInt(nxm_header);
         if (protocol == IPProtocols.ICMP.getValue()) {
             /*
-             * The front end  passes the same protocol type values for IPv4
-             * and IPv6 flows. For the Protocol types we allow in our GUI
-             * (ICMP, TCP, UDP), ICMP is the only one which is different for
-             * IPv6. It is 1 for v4 and 58 for v6 Therefore, we overwrite it
-             * here.
+             * The front end passes the same protocol type values for IPv4 and
+             * IPv6 flows. For the Protocol types we allow in our GUI (ICMP,
+             * TCP, UDP), ICMP is the only one which is different for IPv6. It
+             * is 1 for v4 and 58 for v6 Therefore, we overwrite it here.
              */
             protocol = IPProtocols.ICMPV6.getValue();
         }
@@ -450,9 +487,11 @@ public class V6Match extends OFMatch implements Cloneable {
     }
 
     /**
-     * Sets this (V6Match) object's member variables based on a comma-separated key=value pair similar to OFMatch's fromString.
+     * Sets this (V6Match) object's member variables based on a comma-separated
+     * key=value pair similar to OFMatch's fromString.
      *
-     * @param match a key=value comma separated string.
+     * @param match
+     *            a key=value comma separated string.
      */
     @Override
     public void fromString(String match) throws IllegalArgumentException {
@@ -497,17 +536,45 @@ public class V6Match extends OFMatch implements Cloneable {
                     this.dataLayerType = U16.t(Integer.valueOf(values[1]
                             .replaceFirst("0x", ""), 16));
                 } else {
+
                     this.dataLayerType = U16.t(Integer.valueOf(values[1]));
                 }
                 ethTypeState = MatchFieldState.MATCH_FIELD_ONLY;
                 match_len += 6;
             } else if (values[0].equals(STR_DL_VLAN)) {
                 this.dataLayerVirtualLan = U16.t(Integer.valueOf(values[1]));
-                dlVlanState = MatchFieldState.MATCH_FIELD_ONLY;
-                match_len += 6;
+                this.dlVlanIDState = MatchFieldState.MATCH_FIELD_ONLY;
+                // the variable dlVlanIDState is not really used as a flag
+                // for serializing and deserializing. Rather it is used as a
+                // flag
+                // to check if the vlan id is being set so that we can set the
+                // dlVlanTCIState appropriately.
+                if (this.dlVlanPCPState != MatchFieldState.MATCH_ABSENT) {
+                    this.dlVlanTCIState = MatchFieldState.MATCH_FIELD_ONLY;
+                    match_len -= 2;
+                } else {
+                    this.dlVlanTCIState = MatchFieldState.MATCH_FIELD_WITH_MASK;
+                    this.dataLayerVirtualLanTCIMask = 0x1fff;
+                    match_len += 8;
+                }
+                this.wildcards &= ~OFPFW_DL_VLAN;
             } else if (values[0].equals(STR_DL_VLAN_PCP)) {
                 this.dataLayerVirtualLanPriorityCodePoint = U8.t(Short
                         .valueOf(values[1]));
+                this.dlVlanPCPState = MatchFieldState.MATCH_FIELD_ONLY;
+                // the variable dlVlanPCPState is not really used as a flag
+                // for serializing and deserializing. Rather it is used as a
+                // flag
+                // to check if the vlan pcp is being set so that we can set the
+                // dlVlanTCIState appropriately.
+                if (this.dlVlanIDState != MatchFieldState.MATCH_ABSENT) {
+                    this.dlVlanTCIState = MatchFieldState.MATCH_FIELD_ONLY;
+                    match_len -= 2;
+                } else {
+                    this.dlVlanTCIState = MatchFieldState.MATCH_FIELD_WITH_MASK;
+                    this.dataLayerVirtualLanTCIMask = 0xf000;
+                    match_len += 8;
+                }
                 this.wildcards &= ~OFPFW_DL_VLAN_PCP;
             } else if (values[0].equals(STR_NW_DST)
                     || values[0].equals("ip_dst")) {
@@ -524,7 +591,7 @@ public class V6Match extends OFMatch implements Cloneable {
                     }
                     this.setNetworkDestination(address, mask);
                 } catch (UnknownHostException e) {
-                    logger.error("",e);
+                    logger.error("", e);
                 }
             } else if (values[0].equals(STR_NW_SRC)
                     || values[0].equals("ip_src")) {
@@ -541,7 +608,7 @@ public class V6Match extends OFMatch implements Cloneable {
                     }
                     this.setNetworkSource(address, mask);
                 } catch (UnknownHostException e) {
-                    logger.error("",e);
+                    logger.error("", e);
                 }
             } else if (values[0].equals(STR_NW_PROTO)) {
                 this.networkProtocol = U8.t(Short.valueOf(values[1]));
@@ -571,8 +638,8 @@ public class V6Match extends OFMatch implements Cloneable {
         }
 
         /*
-         * In a V6 extension message action list should be preceded by a padding of 0 to
-         * 7 bytes based upon following formula.
+         * In a V6 extension message action list should be preceded by a padding
+         * of 0 to 7 bytes based upon following formula.
          */
 
         pad_size = (short) (((match_len + 7) / 8) * 8 - match_len);
@@ -602,9 +669,17 @@ public class V6Match extends OFMatch implements Cloneable {
             byte[] ipv6ext_srcmac_msg = getIPv6ExtensionSrcMacMatchMsg(this.dataLayerSource);
             data.put(ipv6ext_srcmac_msg);
         }
-        if (dlVlanState == MatchFieldState.MATCH_FIELD_ONLY) {
-            byte[] ipv6ext_vlan_id_msg = getIPv6ExtensionVlanIDMatchMsg(this.dataLayerVirtualLan);
-            data.put(ipv6ext_vlan_id_msg);
+        if (dlVlanTCIState == MatchFieldState.MATCH_FIELD_ONLY) {
+            byte[] ipv6ext_vlan_tci_msg = getIPv6ExtensionVlanTCIMatchMsg(
+                    this.dataLayerVirtualLan,
+                    this.dataLayerVirtualLanPriorityCodePoint);
+            data.put(ipv6ext_vlan_tci_msg);
+        } else if (dlVlanTCIState == MatchFieldState.MATCH_FIELD_WITH_MASK) {
+            byte[] ipv6ext_vlan_tci_msg_with_mask = getIPv6ExtensionVlanTCIMatchWithMaskMsg(
+                    this.dataLayerVirtualLan,
+                    this.dataLayerVirtualLanPriorityCodePoint,
+                    this.dataLayerVirtualLanTCIMask);
+            data.put(ipv6ext_vlan_tci_msg_with_mask);
         }
         if (nwSrcState == MatchFieldState.MATCH_FIELD_ONLY) {
             byte[] ipv6ext_src_ipv6_msg = getIPv6ExtensionSrcIPv6MatchMsg(this.nwSrc
@@ -728,33 +803,69 @@ public class V6Match extends OFMatch implements Cloneable {
         this.match_len += 6;
     }
 
+    private short getVlanID(byte firstByte, byte secondByte) {
+        short vlan_id_mask_firstByte = 0x0f;// this is the mask for the first
+                                            // byte
+        short vlan_id_mask_secondByte = 0xff;// this is the mask for the second
+                                             // byte
+        int vlanPart1 = (firstByte & vlan_id_mask_firstByte) << 8;
+        int vlanPart2 = secondByte & vlan_id_mask_secondByte;
+        return (short) (vlanPart1 + vlanPart2);
+    }
+
+    private byte getVlanPCP(byte pcpByte) {
+        short vlan_pcp_mask = 0xe0;// this is the vlan pcp mask
+        int pcp_int = pcpByte & vlan_pcp_mask;
+        return (byte) (pcp_int >> 5);
+    }
+
     private void readVlanTci(ByteBuffer data, int nxmLen, boolean hasMask) {
-        short vlan_mask = 0xfff;
         if (hasMask) {
             if ((nxmLen != 2 * 2) || (data.remaining() < 2 * 2)) {
                 return;
-            } else {
-                short vlan = data.getShort();
-                vlan &= vlan_mask;
-                super.setDataLayerVirtualLan(vlan);
-                this.dataLayerVirtualLanMask = data.getShort();
-                this.dlVlanState = MatchFieldState.MATCH_FIELD_WITH_MASK;
+            }
+            else {
+                byte firstByte = data.get();
+                byte secondByte = data.get();
+                this.dataLayerVirtualLanTCIMask = data.getShort() & 0xffff; // we
+                                                                            // need
+                                                                            // the
+                                                                            // last
+                                                                            // 16
+                                                                            // bits
+                // check the mask now
+                if ((this.dataLayerVirtualLanTCIMask & 0x0fff) != 0) {
+                    // if its a vlan id mask
+                    // extract the vlan id
+                    super.setDataLayerVirtualLan(getVlanID(firstByte,
+                            secondByte));
+                } else {
+                    this.wildcards ^= (1 << 1); // Sync with 0F 1.0 Match
+                }
+                if ((this.dataLayerVirtualLanTCIMask & 0xe000) != 0) {
+                    // else if its a vlan pcp mask
+                    // extract the vlan pcp
+                    super.setDataLayerVirtualLanPriorityCodePoint(getVlanPCP(firstByte));
+                } else {
+                    this.wildcards ^= (1 << 20);
+                }
+                this.dlVlanTCIState = MatchFieldState.MATCH_FIELD_WITH_MASK;
                 this.match_len += 8;
-                this.wildcards ^= (1 << 20);
             }
         } else {
             if ((nxmLen != 2) || (data.remaining() < 2)) {
                 return;
-            } else {
-                short vlan = data.getShort();
-                vlan &= vlan_mask;
-                super.setDataLayerVirtualLan(vlan);
-                this.dlVlanState = MatchFieldState.MATCH_FIELD_ONLY;
+            }
+            else {
+                // get the vlan pcp
+                byte firstByte = data.get();
+                byte secondByte = data.get();
+                super.setDataLayerVirtualLanPriorityCodePoint(getVlanPCP(firstByte));
+                super.setDataLayerVirtualLan(getVlanID(firstByte, secondByte));
+                this.dlVlanTCIState = MatchFieldState.MATCH_FIELD_ONLY;
                 this.match_len += 6;
             }
         }
-
-        this.wildcards ^= (1 << 1); // Sync with 0F 1.0 Match
     }
 
     private void readIpTos(ByteBuffer data, int nxmLen, boolean hasMask) {
@@ -812,7 +923,8 @@ public class V6Match extends OFMatch implements Cloneable {
                 super.setNetworkSource(address);
                 this.nwSrcState = MatchFieldState.MATCH_FIELD_ONLY;
                 this.match_len += 8;
-                this.wildcards ^= (((1 << 6) - 1) << 8); // Sync with 0F 1.0 Match
+                this.wildcards ^= (((1 << 6) - 1) << 8); // Sync with 0F 1.0
+                                                         // Match
             }
         }
     }
@@ -832,8 +944,10 @@ public class V6Match extends OFMatch implements Cloneable {
                 this.nwDstState = MatchFieldState.MATCH_FIELD_WITH_MASK;
                 this.match_len += 12;
                 int prefixlen = getNetworkMaskPrefixLength(mbytes);
-                this.wildcards ^= (((1 << 6) - 1) << 14); // Sync with 0F 1.0 Match
-                this.wildcards |= ((32 - prefixlen) << 14); // Sync with 0F 1.0 Match
+                this.wildcards ^= (((1 << 6) - 1) << 14); // Sync with 0F 1.0
+                                                          // Match
+                this.wildcards |= ((32 - prefixlen) << 14); // Sync with 0F 1.0
+                                                            // Match
             }
         } else {
             if ((nxmLen != 4) || (data.remaining() < 4)) {
@@ -844,7 +958,8 @@ public class V6Match extends OFMatch implements Cloneable {
                 int address = NetUtils.byteArray4ToInt(dbytes);
                 super.setNetworkDestination(address);
                 this.nwDstState = MatchFieldState.MATCH_FIELD_ONLY;
-                this.wildcards ^= (((1 << 6) - 1) << 14); // Sync with 0F 1.0 Match
+                this.wildcards ^= (((1 << 6) - 1) << 14); // Sync with 0F 1.0
+                                                          // Match
                 this.match_len += 8;
             }
         }
@@ -979,9 +1094,7 @@ public class V6Match extends OFMatch implements Cloneable {
                 + HexEncode.bytesToHexStringFormat(dataLayerSourceMask)
                 + ", dataLayerDestinationMask="
                 + HexEncode.bytesToHexStringFormat(dataLayerDestinationMask)
-                + ", dataLayerVirtualLanMask=" + dataLayerVirtualLanMask
-                + ", dataLayerVirtualLanPriorityCodePointMask="
-                + dataLayerVirtualLanPriorityCodePointMask
+                + ", dataLayerVirtualLanTCIMask=" + dataLayerVirtualLanTCIMask
                 + ", dataLayerTypeMask=" + dataLayerTypeMask
                 + ", networkTypeOfServiceMask=" + networkTypeOfServiceMask
                 + ", networkProtocolMask=" + networkProtocolMask
@@ -991,7 +1104,7 @@ public class V6Match extends OFMatch implements Cloneable {
                 + ", dstIPv6SubnetMaskbits=" + dstIPv6SubnetMaskbits
                 + ", inputPortState=" + inputPortState + ", dlSourceState="
                 + dlSourceState + ", dlDestState=" + dlDestState
-                + ", dlVlanState=" + dlVlanState + ", ethTypeState="
+                + ", dlVlanTCIState=" + dlVlanTCIState + ", ethTypeState="
                 + ethTypeState + ", nwTosState=" + nwTosState
                 + ", nwProtoState=" + nwProtoState + ", nwSrcState="
                 + nwSrcState + ", nwDstState=" + nwDstState + ", tpSrcState="
@@ -1001,8 +1114,9 @@ public class V6Match extends OFMatch implements Cloneable {
 
     /**
      * Read the data corresponding to the match field (received from the wire)
-     * Input: data: match field(s). Since match field is of variable length, the whole data that are passed in
-     * are assumed to fem0tbd.be the match fields.
+     * Input: data: match field(s). Since match field is of variable length, the
+     * whole data that are passed in are assumed to fem0tbd.be the match fields.
+     *
      * @param data
      */
     @Override
@@ -1018,8 +1132,8 @@ public class V6Match extends OFMatch implements Cloneable {
                 /*
                  * at least 4 bytes for each match header
                  */
-                logger.error("Invalid Vendor Extension Header. Size {}", data
-                        .remaining());
+                logger.error("Invalid Vendor Extension Header. Size {}",
+                        data.remaining());
                 return;
             }
             /*
@@ -1095,11 +1209,11 @@ public class V6Match extends OFMatch implements Cloneable {
         // Sync with 0F 1.0 Match
         if (super.getDataLayerType() == 0x800) {
             if (((this.wildcards >> 8) & 0x3f) == 0x3f) {
-                //ipv4 src processing
+                // ipv4 src processing
                 this.wildcards ^= (((1 << 5) - 1) << 8);
             }
             if (((this.wildcards >> 14) & 0x3f) == 0x3f) {
-                //ipv4 dest processing
+                // ipv4 dest processing
                 this.wildcards ^= (((1 << 5) - 1) << 14);
             }
         } else {
@@ -1204,24 +1318,40 @@ public class V6Match extends OFMatch implements Cloneable {
         }
     }
 
-    public short getDataLayerVirtualLanMask() {
-        return dataLayerVirtualLanMask;
-    }
-
     public void setDataLayerVirtualLan(short vlan, short mask) {
+        // mask is ignored as the code sets the appropriate mask
         super.dataLayerVirtualLan = vlan;
-        if (mask == 0) {
-            this.dlVlanState = MatchFieldState.MATCH_FIELD_ONLY;
-            this.match_len += 6;
+        this.dlVlanIDState = MatchFieldState.MATCH_FIELD_ONLY;
+        // the variable dlVlanIDState is not really used as a flag
+        // for serializing and deserializing. Rather it is used as a flag
+        // to check if the vlan id is being set so that we can set the
+        // dlVlanTCIState appropriately.
+        if (this.dlVlanPCPState != MatchFieldState.MATCH_ABSENT) {
+            this.dlVlanTCIState = MatchFieldState.MATCH_FIELD_ONLY;
+            match_len -= 2;
         } else {
-            this.dataLayerVirtualLanMask = mask;
-            this.dlVlanState = MatchFieldState.MATCH_FIELD_WITH_MASK;
-            this.match_len += 8;
+            this.dlVlanTCIState = MatchFieldState.MATCH_FIELD_WITH_MASK;
+            this.dataLayerVirtualLanTCIMask = 0x1fff;
+            match_len += 8;
         }
     }
 
     public void setDataLayerVirtualLanPriorityCodePoint(byte pcp, byte mask) {
+        // mask is ignored as the code sets the appropriate mask
         super.dataLayerVirtualLanPriorityCodePoint = pcp;
+        this.dlVlanPCPState = MatchFieldState.MATCH_FIELD_ONLY;
+        // the variable dlVlanPCPState is not really used as a flag
+        // for serializing and deserializing. Rather it is used as a flag
+        // to check if the vlan pcp is being set so that we can set the
+        // dlVlanTCIState appropriately.
+        if (this.dlVlanIDState != MatchFieldState.MATCH_ABSENT) {
+            this.dlVlanTCIState = MatchFieldState.MATCH_FIELD_ONLY;
+            match_len -= 2;
+        } else {
+            this.dlVlanTCIState = MatchFieldState.MATCH_FIELD_WITH_MASK;
+            this.dataLayerVirtualLanTCIMask = 0xf000;
+            match_len += 8;
+        }
     }
 
     public void setDataLayerType(short ethType, short mask) {
@@ -1347,28 +1477,38 @@ public class V6Match extends OFMatch implements Cloneable {
         result = prime * result + Arrays.hashCode(dataLayerDestinationMask);
         result = prime * result + Arrays.hashCode(dataLayerSourceMask);
         result = prime * result + dataLayerTypeMask;
-        result = prime * result + dataLayerVirtualLanMask;
-        result = prime * result + dataLayerVirtualLanPriorityCodePointMask;
-        result = prime * result + ((dlDestState == null) ? 0 : dlDestState.hashCode());
-        result = prime * result + ((dlSourceState == null) ? 0 : dlSourceState.hashCode());
-        result = prime * result + ((dlVlanState == null) ? 0 : dlVlanState.hashCode());
+        result = prime * result + dataLayerVirtualLanTCIMask;
+        result = prime * result
+                + ((dlDestState == null) ? 0 : dlDestState.hashCode());
+        result = prime * result
+                + ((dlSourceState == null) ? 0 : dlSourceState.hashCode());
+        result = prime * result
+                + ((dlVlanTCIState == null) ? 0 : dlVlanTCIState.hashCode());
         result = prime * result + dstIPv6SubnetMaskbits;
-        result = prime * result + ((ethTypeState == null) ? 0 : ethTypeState.hashCode());
+        result = prime * result
+                + ((ethTypeState == null) ? 0 : ethTypeState.hashCode());
         result = prime * result + inputPortMask;
-        result = prime * result + ((inputPortState == null) ? 0 : inputPortState.hashCode());
+        result = prime * result
+                + ((inputPortState == null) ? 0 : inputPortState.hashCode());
         result = prime * result + match_len;
         result = prime * result + networkProtocolMask;
         result = prime * result + networkTypeOfServiceMask;
         result = prime * result + ((nwDst == null) ? 0 : nwDst.hashCode());
-        result = prime * result + ((nwDstState == null) ? 0 : nwDstState.hashCode());
-        result = prime * result + ((nwProtoState == null) ? 0 : nwProtoState.hashCode());
+        result = prime * result
+                + ((nwDstState == null) ? 0 : nwDstState.hashCode());
+        result = prime * result
+                + ((nwProtoState == null) ? 0 : nwProtoState.hashCode());
         result = prime * result + ((nwSrc == null) ? 0 : nwSrc.hashCode());
-        result = prime * result + ((nwSrcState == null) ? 0 : nwSrcState.hashCode());
-        result = prime * result + ((nwTosState == null) ? 0 : nwTosState.hashCode());
+        result = prime * result
+                + ((nwSrcState == null) ? 0 : nwSrcState.hashCode());
+        result = prime * result
+                + ((nwTosState == null) ? 0 : nwTosState.hashCode());
         result = prime * result + pad_size;
         result = prime * result + srcIPv6SubnetMaskbits;
-        result = prime * result + ((tpDstState == null) ? 0 : tpDstState.hashCode());
-        result = prime * result + ((tpSrcState == null) ? 0 : tpSrcState.hashCode());
+        result = prime * result
+                + ((tpDstState == null) ? 0 : tpDstState.hashCode());
+        result = prime * result
+                + ((tpSrcState == null) ? 0 : tpSrcState.hashCode());
         result = prime * result + transportDestinationMask;
         result = prime * result + transportSourceMask;
         return result;
@@ -1395,21 +1535,15 @@ public class V6Match extends OFMatch implements Cloneable {
         if (dataLayerTypeMask != other.dataLayerTypeMask) {
             return false;
         }
-        if (dataLayerVirtualLanMask != other.dataLayerVirtualLanMask) {
+        if (dataLayerVirtualLanTCIMask != other.dataLayerVirtualLanTCIMask) {
             return false;
         }
-        if (dataLayerVirtualLanPriorityCodePointMask != other.dataLayerVirtualLanPriorityCodePointMask) {
-            return false;
-        }
-        if (dlDestState != other.dlDestState) {
+        if (dlVlanTCIState != other.dlVlanTCIState) {
             return false;
         }
         if (dlSourceState != other.dlSourceState) {
             return false;
         }
-        if (dlVlanState != other.dlVlanState) {
-            return false;
-        }
         if (dstIPv6SubnetMaskbits != other.dstIPv6SubnetMaskbits) {
             return false;
         }
index 6afaf5f67531ace92c1cebf282bc5d2d632c6773..2898dde363b01b605212a13004b38e47d3c5e76a 100644 (file)
@@ -6,9 +6,9 @@ import java.net.InetAddress;
 import java.net.UnknownHostException;
 import java.nio.ByteBuffer;
 import java.util.Arrays;
+
 import org.junit.Assert;
 import org.junit.Test;
-import org.opendaylight.controller.protocol_plugin.openflow.vendorextension.v6extension.V6Match;
 import org.openflow.protocol.OFMatch;
 
 public class V6ExtensionTest {
@@ -119,6 +119,7 @@ public class V6ExtensionTest {
         match.fromString("ip_src=2001:ddd:3e1:1234:0000:1111:2222:3333/64");
         match.fromString("ip_dst=2001:123:222:abc:111:aaa:1111:2222/64");
         match.fromString("dl_vlan=10");
+        match.fromString("dl_vpcp=1");
         match.fromString("nw_proto=6");
         match.fromString("nw_tos=100");
         match.fromString("tp_dst=8080");
@@ -142,7 +143,8 @@ public class V6ExtensionTest {
 
         Assert.assertTrue(match.getDataLayerVirtualLan() == match2
                 .getDataLayerVirtualLan());
-        // vlan pcp isn't part of write/read buffer
+        Assert.assertTrue(match.getDataLayerVirtualLanPriorityCodePoint() == match2
+                .getDataLayerVirtualLanPriorityCodePoint());
         Assert.assertTrue(match.getNetworkProtocol() == match2
                 .getNetworkProtocol());
         Assert.assertTrue(match.getNetworkTypeOfService() == match2
index 40a85ffb28f6c4b5ec29c3d60b733153ea07616a..acda8836cea878e3d670904f31751a69e9e6fa5a 100644 (file)
@@ -1 +1,2 @@
 /.settings
+/binding-java-api-generator/src/main/xtend-gen
index b6d8de62e6d170d6e7e4a44f7cfe6944e2bfed7c..f650004ba22e92d9bb419305edcd4e1d16c81540 100644 (file)
@@ -221,7 +221,7 @@ public final class TypeProviderImpl implements TypeProvider {
         final String strXPath = xpath.toString();
 
         if (strXPath != null) {
-            if (strXPath.matches(".*//[.* | .*//].*")) {
+            if (strXPath.contains("[")) {
                 returnType = Types.typeForClass(Object.class);
             } else {
                 final Module module = findParentModuleForTypeDefinition(schemaContext, leafrefType);
index ce9f131b754eb1ce724a09539a40ba62e8a5f116..a8b3b487af896c82c61f9f019631ead1614d7607 100644 (file)
@@ -8,12 +8,14 @@
 package org.opendaylight.controller.sal.binding.generator.impl;
 
 import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
 
 import java.io.File;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Set;
 
+import org.junit.Ignore;
 import org.junit.Test;
 import org.opendaylight.controller.sal.binding.generator.api.BindingGenerator;
 import org.opendaylight.controller.sal.binding.model.api.GeneratedProperty;
@@ -73,9 +75,8 @@ public class GeneratedTypesTest {
         assertNotNull(inetTypesPath);
         assertNotNull(yangTypesPath);
 
-        // final SchemaContext context = resolveSchemaContextFromFiles(
-        // topologyPath, interfacesPath, ifTypePath, inetTypesPath,
-        // yangTypesPath);
+        // final SchemaContext context = resolveSchemaContextFromFiles(topologyPath, interfacesPath, ifTypePath,
+        // inetTypesPath, yangTypesPath);
         final SchemaContext context = resolveSchemaContextFromFiles(topologyPath, interfacesPath, inetTypesPath,
                 yangTypesPath);
         assertNotNull(context);
@@ -94,6 +95,7 @@ public class GeneratedTypesTest {
         GeneratedType gtDest = null;
         GeneratedType gtTunnel = null;
         GeneratedTransferObject gtTunnelKey = null;
+        GeneratedType gtTopology = null;
         for (final Type type : genTypes) {
             String name = type.getName();
             if ("InterfaceKey".equals(name)) {
@@ -110,6 +112,8 @@ public class GeneratedTypesTest {
                 gtTunnel = (GeneratedType) type;
             } else if ("TunnelKey".equals(name)) {
                 gtTunnelKey = (GeneratedTransferObject) type;
+            } else if ("Topology".equals(name)) {
+                gtTopology = (GeneratedType) type;
             }
         }
 
@@ -120,6 +124,21 @@ public class GeneratedTypesTest {
         assertNotNull(gtDest);
         assertNotNull(gtTunnel);
         assertNotNull(gtTunnelKey);
+        assertNotNull(gtTopology);
+
+        // Topology
+        final List<MethodSignature> gtTopoMethods = gtTopology.getMethodDefinitions();
+        assertNotNull(gtTopoMethods);
+        MethodSignature condLeafref = null;
+        for (final MethodSignature method : gtTopoMethods) {
+            if (method.getName().equals("getCondLeafref")) {
+                condLeafref = method;
+            }
+        }
+        assertNotNull(condLeafref);
+        Type condLeafRT = condLeafref.getReturnType();
+        assertNotNull(condLeafRT);
+        assertEquals("java.lang.Object", condLeafRT.getFullyQualifiedName());
 
         // InterfaceId
         final List<GeneratedProperty> gtIfcKeyProps = gtIfcKey.getProperties();
@@ -133,8 +152,7 @@ public class GeneratedTypesTest {
         assertNotNull(ifcIdProp);
         Type ifcIdPropType = ifcIdProp.getReturnType();
         assertNotNull(ifcIdPropType);
-        assertFalse(ifcIdPropType.equals("java.lang.Void"));
-        assertEquals(ifcIdPropType.getName(), "String");
+        assertEquals("java.lang.String", ifcIdPropType.getFullyQualifiedName());
 
         // Interface
         final List<MethodSignature> gtIfcMethods = gtIfc.getMethodDefinitions();
@@ -151,14 +169,14 @@ public class GeneratedTypesTest {
         assertNotNull(getIfcKey);
         Type getIfcKeyType = getIfcKey.getReturnType();
         assertNotNull(getIfcKeyType);
-        assertFalse(getIfcKeyType.equals("java.lang.Void"));
-        assertEquals(getIfcKeyType.getName(), "InterfaceKey");
+        assertNotSame("java.lang.Void", getIfcKeyType);
+        assertEquals("InterfaceKey", getIfcKeyType.getName());
 
         assertNotNull(getHigherLayerIf);
         Type getHigherLayerIfType = getHigherLayerIf.getReturnType();
         assertNotNull(getHigherLayerIfType);
-        assertFalse(getHigherLayerIfType.equals("java.lang.Void"));
-        assertEquals(getHigherLayerIfType.getName(), "List");
+        assertNotSame("java.lang.Void", getHigherLayerIfType);
+        assertEquals("List", getHigherLayerIfType.getName());
 
         // NetworkLink
         final List<MethodSignature> gtNetworkLinkMethods = gtNetworkLink.getMethodDefinitions();
@@ -172,8 +190,8 @@ public class GeneratedTypesTest {
         assertNotNull(getIfc);
         Type getIfcType = getIfc.getReturnType();
         assertNotNull(getIfcType);
-        assertFalse(getIfcType.equals("java.lang.Void"));
-        assertEquals(getIfcType.getName(), "String");
+        assertNotSame("java.lang.Void", getIfcType);
+        assertEquals("String", getIfcType.getName());
 
         // SourceNode
         final List<MethodSignature> gtSourceMethods = gtSource.getMethodDefinitions();
@@ -187,8 +205,8 @@ public class GeneratedTypesTest {
         assertNotNull(getIdSource);
         Type getIdType = getIdSource.getReturnType();
         assertNotNull(getIdType);
-        assertFalse(getIdType.equals("java.lang.Void"));
-        assertEquals(getIdType.getName(), "Uri");
+        assertNotSame("java.lang.Void", getIdType);
+        assertEquals("Uri", getIdType.getName());
 
         // DestinationNode
         final List<MethodSignature> gtDestMethods = gtDest.getMethodDefinitions();
@@ -202,8 +220,8 @@ public class GeneratedTypesTest {
         assertNotNull(getIdDest);
         Type getIdDestType = getIdDest.getReturnType();
         assertNotNull(getIdDestType);
-        assertFalse(getIdDestType.equals("java.lang.Void"));
-        assertEquals(getIdDestType.getName(), "Uri");
+        assertNotSame("java.lang.Void", getIdDestType);
+        assertEquals("Uri", getIdDestType.getName());
 
         // Tunnel
         final List<MethodSignature> gtTunnelMethods = gtTunnel.getMethodDefinitions();
@@ -217,8 +235,8 @@ public class GeneratedTypesTest {
         assertNotNull(getTunnelKey);
         Type getTunnelKeyType = getTunnelKey.getReturnType();
         assertNotNull(getTunnelKeyType);
-        assertFalse(getTunnelKeyType.equals("java.lang.Void"));
-        assertEquals(getTunnelKeyType.getName(), "TunnelKey");
+        assertNotSame("java.lang.Void", getTunnelKeyType);
+        assertEquals("TunnelKey", getTunnelKeyType.getName());
 
         // TunnelKey
         final List<GeneratedProperty> gtTunnelKeyProps = gtTunnelKey.getProperties();
@@ -232,8 +250,8 @@ public class GeneratedTypesTest {
         assertNotNull(tunnelId);
         Type tunnelIdType = tunnelId.getReturnType();
         assertNotNull(tunnelIdType);
-        assertFalse(tunnelIdType.equals("java.lang.Void"));
-        assertEquals(tunnelIdType.getName(), "Uri");
+        assertNotSame("java.lang.Void", tunnelIdType);
+        assertEquals("Uri", tunnelIdType.getName());
     }
 
     @Test
@@ -256,14 +274,11 @@ public class GeneratedTypesTest {
         assertEquals(3, simpleContainer.getMethodDefinitions().size());
         assertEquals(2, nestedContainer.getMethodDefinitions().size());
 
-        int setFooMethodCounter = 0;
         int getFooMethodCounter = 0;
         int getBarMethodCounter = 0;
         int getNestedContainerCounter = 0;
 
         String getFooMethodReturnTypeName = "";
-        String setFooMethodInputParamName = "";
-        String setFooMethodInputParamTypeName = "";
         String getBarMethodReturnTypeName = "";
         String getNestedContainerReturnTypeName = "";
         for (final MethodSignature method : simpleContainer.getMethodDefinitions()) {
@@ -272,13 +287,6 @@ public class GeneratedTypesTest {
                 getFooMethodReturnTypeName = method.getReturnType().getName();
             }
 
-            if (method.getName().equals("setFoo")) {
-                setFooMethodCounter++;
-                final MethodSignature.Parameter param = method.getParameters().get(0);
-                setFooMethodInputParamName = param.getName();
-                setFooMethodInputParamTypeName = param.getType().getName();
-            }
-
             if (method.getName().equals("getBar")) {
                 getBarMethodCounter++;
                 getBarMethodReturnTypeName = method.getReturnType().getName();
@@ -290,31 +298,20 @@ public class GeneratedTypesTest {
             }
         }
 
-        assertEquals(getFooMethodCounter, 1);
-        assertEquals(getFooMethodReturnTypeName, "Integer");
-
-        // TODO no setter methods, because 'config' is default true
-        // assertEquals(setFooMethodCounter, 1);
-        // assertEquals(setFooMethodInputParamName, "foo");
-        // assertEquals(setFooMethodInputParamTypeName, "Integer");
+        assertEquals(1, getFooMethodCounter);
+        assertEquals("Integer", getFooMethodReturnTypeName);
 
-        assertEquals(getBarMethodCounter, 1);
-        assertEquals(getBarMethodReturnTypeName, "String");
+        assertEquals(1, getBarMethodCounter);
+        assertEquals("String", getBarMethodReturnTypeName);
 
-        assertEquals(getNestedContainerCounter, 1);
-        assertEquals(getNestedContainerReturnTypeName, "NestedContainer");
+        assertEquals(1, getNestedContainerCounter);
+        assertEquals("NestedContainer", getNestedContainerReturnTypeName);
 
-        setFooMethodCounter = 0;
         getFooMethodCounter = 0;
         getBarMethodCounter = 0;
-        int setBarMethodCounter = 0;
 
         getFooMethodReturnTypeName = "";
-        setFooMethodInputParamName = "";
-        setFooMethodInputParamTypeName = "";
         getBarMethodReturnTypeName = "";
-        String setBarMethodInputParamName = "";
-        String setBarMethodInputParamTypeName = "";
 
         for (final MethodSignature method : nestedContainer.getMethodDefinitions()) {
 
@@ -323,41 +320,17 @@ public class GeneratedTypesTest {
                 getFooMethodReturnTypeName = method.getReturnType().getName();
             }
 
-            if (method.getName().equals("setFoo")) {
-                setFooMethodCounter++;
-                final MethodSignature.Parameter param = method.getParameters().get(0);
-                setFooMethodInputParamName = param.getName();
-                setFooMethodInputParamTypeName = param.getType().getName();
-            }
-
             if (method.getName().equals("getBar")) {
                 getBarMethodCounter++;
                 getBarMethodReturnTypeName = method.getReturnType().getName();
             }
-
-            if (method.getName().equals("setBar")) {
-                setBarMethodCounter++;
-                final MethodSignature.Parameter param = method.getParameters().get(0);
-                setBarMethodInputParamName = param.getName();
-                setBarMethodInputParamTypeName = param.getType().getName();
-            }
         }
 
         assertEquals(1, getFooMethodCounter);
-        assertEquals(getFooMethodReturnTypeName, "Short");
-
-        // TODO no setter methods, because 'config' is default true
-        // assertEquals(1, setFooMethodCounter);
-        // assertEquals(setFooMethodInputParamName, "foo");
-        // assertEquals(setFooMethodInputParamTypeName, "Short");
+        assertEquals("Short", getFooMethodReturnTypeName);
 
         assertEquals(1, getBarMethodCounter);
-        assertEquals(getBarMethodReturnTypeName, "String");
-
-        // TODO no setter methods, because 'config' is default true
-        // assertEquals(1, setBarMethodCounter);
-        // assertEquals(setBarMethodInputParamName, "bar");
-        // assertEquals(setBarMethodInputParamTypeName, "String");
+        assertEquals("String", getBarMethodReturnTypeName);
     }
 
     @Test
@@ -380,14 +353,11 @@ public class GeneratedTypesTest {
         assertEquals(3, simpleContainer.getMethodDefinitions().size());
         assertEquals(2, nestedContainer.getMethodDefinitions().size());
 
-        int setFooMethodCounter = 0;
         int getFooMethodCounter = 0;
         int getBarMethodCounter = 0;
         int getNestedContainerCounter = 0;
 
         String getFooMethodReturnTypeName = "";
-        String setFooMethodInputParamName = "";
-        String setFooMethodInputParamTypeName = "";
         String getBarMethodReturnTypeName = "";
         String getNestedContainerReturnTypeName = "";
         for (final MethodSignature method : simpleContainer.getMethodDefinitions()) {
@@ -396,13 +366,6 @@ public class GeneratedTypesTest {
                 getFooMethodReturnTypeName = method.getReturnType().getName();
             }
 
-            if (method.getName().equals("setFoo")) {
-                setFooMethodCounter++;
-                final MethodSignature.Parameter param = method.getParameters().get(0);
-                setFooMethodInputParamName = param.getName();
-                setFooMethodInputParamTypeName = param.getType().getName();
-            }
-
             if (method.getName().equals("getBar")) {
                 getBarMethodCounter++;
                 getBarMethodReturnTypeName = method.getReturnType().getName();
@@ -415,26 +378,18 @@ public class GeneratedTypesTest {
         }
 
         assertEquals(1, getFooMethodCounter);
-        assertEquals(getFooMethodReturnTypeName, "List");
-
-        // TODO no setter methods, because 'config' is default true
-        // assertEquals(1, setFooMethodCounter);
-        // assertEquals(setFooMethodInputParamName, "foo");
-        // assertEquals(setFooMethodInputParamTypeName, "List");
+        assertEquals("List", getFooMethodReturnTypeName);
 
         assertEquals(1, getBarMethodCounter);
-        assertEquals(getBarMethodReturnTypeName, "String");
+        assertEquals("String", getBarMethodReturnTypeName);
 
         assertEquals(1, getNestedContainerCounter);
-        assertEquals(getNestedContainerReturnTypeName, "NestedContainer");
+        assertEquals("NestedContainer", getNestedContainerReturnTypeName);
 
-        setFooMethodCounter = 0;
         getFooMethodCounter = 0;
         getBarMethodCounter = 0;
 
         getFooMethodReturnTypeName = "";
-        setFooMethodInputParamName = "";
-        setFooMethodInputParamTypeName = "";
         getBarMethodReturnTypeName = "";
 
         for (final MethodSignature method : nestedContainer.getMethodDefinitions()) {
@@ -443,13 +398,6 @@ public class GeneratedTypesTest {
                 getFooMethodReturnTypeName = method.getReturnType().getName();
             }
 
-            if (method.getName().equals("setFoo")) {
-                setFooMethodCounter++;
-                final MethodSignature.Parameter param = method.getParameters().get(0);
-                setFooMethodInputParamName = param.getName();
-                setFooMethodInputParamTypeName = param.getType().getName();
-            }
-
             if (method.getName().equals("getBar")) {
                 getBarMethodCounter++;
                 getBarMethodReturnTypeName = method.getReturnType().getName();
@@ -457,15 +405,10 @@ public class GeneratedTypesTest {
         }
 
         assertEquals(1, getFooMethodCounter);
-        assertEquals(getFooMethodReturnTypeName, "Short");
-
-        // TODO no setter methods, because 'config' is default true
-        // assertEquals(1, setFooMethodCounter);
-        // assertEquals(setFooMethodInputParamName, "foo");
-        // assertEquals(setFooMethodInputParamTypeName, "Short");
+        assertEquals("Short", getFooMethodReturnTypeName);
 
         assertEquals(1, getBarMethodCounter);
-        assertEquals(getBarMethodReturnTypeName, "List");
+        assertEquals("List", getBarMethodReturnTypeName);
     }
 
     @Test
@@ -480,9 +423,6 @@ public class GeneratedTypesTest {
         assertNotNull(genTypes);
         assertEquals(6, genTypes.size());
 
-        int genTypesCount = 0;
-        int genTOsCount = 0;
-
         int listParentContainerMethodsCount = 0;
         int simpleListMethodsCount = 0;
         int listChildContainerMethodsCount = 0;
@@ -517,7 +457,6 @@ public class GeneratedTypesTest {
                 final GeneratedType genType = (GeneratedType) type;
                 if (genType.getName().equals("ListParentContainer")) {
                     listParentContainerMethodsCount = genType.getMethodDefinitions().size();
-                    genTypesCount++;
                 } else if (genType.getName().equals("SimpleList")) {
                     simpleListMethodsCount = genType.getMethodDefinitions().size();
                     final List<MethodSignature> methods = genType.getMethodDefinitions();
@@ -540,13 +479,10 @@ public class GeneratedTypesTest {
                             getBarMethodCount++;
                         }
                     }
-                    genTypesCount++;
                 } else if (genType.getName().equals("ListChildContainer")) {
                     listChildContainerMethodsCount = genType.getMethodDefinitions().size();
-                    genTypesCount++;
                 }
             } else if (type instanceof GeneratedTransferObject) {
-                genTOsCount++;
                 final GeneratedTransferObject genTO = (GeneratedTransferObject) type;
                 final List<GeneratedProperty> properties = genTO.getProperties();
                 final List<GeneratedProperty> hashProps = genTO.getHashCodeIdentifiers();
index 95de94375f7baab566df282f58cf4db930cd761f..4fef1cddd255fd2311237595ea4211b3f9be42a5 100644 (file)
@@ -1,6 +1,6 @@
 module demo-topology {
        yang-version 1;
-    namespace "";
+    namespace "urn:model.1demo-275topology.4.5.my";
     prefix "tp";
 
     organization "OPEN DAYLIGHT";
index 2d6fc2628760b496fe276f274df5161a779d53b6..be3119255e762da399de9cc5a67c1c356b3a54b0 100644 (file)
@@ -57,6 +57,12 @@ module abstract-topology {
             UNIQUE topology identifier.";
         }
 
+        leaf cond-leafref {
+            type leafref {
+                path "/tp:topology/tp:network-nodes/tp:network-node[node-id = 'super-node']";
+            }
+        }
+
         container network-nodes {
             list network-node {
                 key "node-id";
index a394edd906bc50de5f71d8a09eb54b393b3c42d4..0c4683ed03fd7930c0749ec6da9d95bf2fb57baa 100644 (file)
@@ -30,8 +30,11 @@ public final class BindingGeneratorUtil {
             if (packNameParts != null) {
                 final StringBuilder builder = new StringBuilder();
                 for (int i = 0; i < packNameParts.length; ++i) {
-                    if (JAVA_RESERVED_WORDS.contains(packNameParts[i])) {
-                        packNameParts[i] = "_" + packNameParts[i];
+                    final String packNamePart = packNameParts[i];
+                    if (Character.isDigit(packNamePart.charAt(0))) {
+                        packNameParts[i] = "_" + packNamePart;
+                    } else if (JAVA_RESERVED_WORDS.contains(packNamePart)) {
+                        packNameParts[i] = "_" + packNamePart;
                     }
                     if (i > 0) {
                         builder.append(".");
index fad725b1f8d51cc9d428f54003961c8ab3f13b41..86c8a8ad015a626308ffd3d52e0b4e83aba4b3c2 100644 (file)
@@ -7,6 +7,39 @@
         <version>0.5.4-SNAPSHOT</version>\r
     </parent>\r
     <artifactId>binding-java-api-generator</artifactId>\r
+    <build>\r
+        <plugins>\r
+            <plugin>\r
+                <groupId>org.eclipse.xtend</groupId>\r
+                <artifactId>xtend-maven-plugin</artifactId>\r
+                <version>2.4.2</version>\r
+                <executions>\r
+                    <execution>\r
+                        <goals>\r
+                            <goal>compile</goal>\r
+                        </goals>\r
+                        <configuration>\r
+                             <outputDirectory>${basedir}/src/main/xtend-gen</outputDirectory>\r
+                        </configuration>\r
+                    </execution>\r
+                </executions>\r
+            </plugin>\r
+            <plugin>\r
+               <artifactId>maven-clean-plugin</artifactId>\r
+                           <version>2.4.1</version>\r
+                           <configuration>\r
+                               <filesets>\r
+                                   <fileset>\r
+                                       <directory>${basedir}/src/main/xtend-gen</directory>\r
+                                       <includes>\r
+                                           <include>**</include>\r
+                                       </includes>\r
+                                   </fileset>\r
+                               </filesets>\r
+                           </configuration>\r
+            </plugin>\r
+        </plugins>\r
+    </build>\r
     <dependencies>\r
         <dependency>\r
             <groupId>org.opendaylight.controller</groupId>\r
             <groupId>junit</groupId>\r
             <artifactId>junit</artifactId>\r
         </dependency>\r
+           <dependency>\r
+                   <groupId>org.eclipse.xtend</groupId>\r
+                   <artifactId>org.eclipse.xtend.lib</artifactId>\r
+                   <version>2.4.2</version>\r
+           </dependency>\r
     </dependencies>\r
 </project>\r
diff --git a/opendaylight/sal/yang-prototype/code-generator/binding-java-api-generator/src/main/java/org/opendaylight/controller/sal/java/api/generator/BuilderClassDescriptor.java b/opendaylight/sal/yang-prototype/code-generator/binding-java-api-generator/src/main/java/org/opendaylight/controller/sal/java/api/generator/BuilderClassDescriptor.java
new file mode 100644 (file)
index 0000000..72b4c87
--- /dev/null
@@ -0,0 +1,331 @@
+package org.opendaylight.controller.sal.java.api.generator;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.opendaylight.controller.sal.binding.model.api.GeneratedTransferObject;
+import org.opendaylight.controller.sal.binding.model.api.GeneratedType;
+import org.opendaylight.controller.sal.binding.model.api.MethodSignature;
+import org.opendaylight.controller.sal.binding.model.api.ParameterizedType;
+import org.opendaylight.controller.sal.binding.model.api.Type;
+import org.opendaylight.controller.yang.binding.Augmentable;
+
+public class BuilderClassDescriptor {
+
+    private static final String GET_PREFIX = "get";
+    private static final String JAVA_UTIL = "java.util";
+    private static final String HASH_MAP = "HashMap";
+    private static final String MAP = "Map";
+    private static final String GET_AUGMENTATION_METHOD_NAME = "getAugmentation";
+
+    private final GeneratedType genType;
+    private Map<String, String> imports;
+    private final String packageName;
+    private final String className;
+    private final Set<MethodDeclaration> methods;
+    private final Set<FieldDeclaration> fields;
+    private final List<String> importsNames;
+    private FieldDeclaration augmentField;
+
+    class TypeDeclaration {
+
+        private final static String JAVA_LANG_PREFIX = "java.lang";
+        private final String name;
+        private final TypeDeclaration[] generics;
+
+        public TypeDeclaration(String pkg, String name, TypeDeclaration... generics) {
+            this.name = removeJavaLangPkgName(getRightTypeName(pkg, name));
+            if (generics != null && generics.length > 0) {
+                this.generics = generics;
+            } else {
+                this.generics = null;
+            }
+        }
+
+        public TypeDeclaration(final Type type) {
+            if (type == null) {
+                throw new IllegalArgumentException("Type cannot be NULL");
+            }
+
+            this.name = removeJavaLangPkgName(getRightTypeName(type.getPackageName(), type.getName()));
+            TypeDeclaration[] generics = null;
+            if (type instanceof ParameterizedType) {
+                final ParameterizedType pType = (ParameterizedType) type;
+                final Type[] actualTypeArguments = pType.getActualTypeArguments();
+                generics = new TypeDeclaration[actualTypeArguments.length];
+                for (int i = 0; i < actualTypeArguments.length; i++) {
+                    generics[i] = new TypeDeclaration(actualTypeArguments[i].getPackageName(),
+                            actualTypeArguments[i].getName());
+                }
+            }
+            if (generics != null && generics.length > 0) {
+                this.generics = generics;
+            } else {
+                this.generics = null;
+            }
+        }
+
+        private String removeJavaLangPkgName(final String typeName) {
+            if (typeName.startsWith(JAVA_LANG_PREFIX)) {
+                return typeName.substring(typeName.lastIndexOf(Constants.DOT) + 1);
+            }
+            return typeName;
+        }
+
+        private String getRightTypeName(final String pkg, final String name) {
+            if (name == null) {
+                throw new IllegalArgumentException("Name cannot be NULL!");
+            }
+
+            if (imports == null) {
+                return name;
+            }
+            final String pkgFromImports = imports.get(name);
+            if (pkgFromImports == null || pkgFromImports.equals(pkg)) {
+                return name;
+            }
+            return (pkg == null ? "" : pkg) + Constants.DOT + name;
+        }
+
+        public String getName() {
+            return name;
+        }
+
+        public TypeDeclaration[] getGenerics() {
+            return generics;
+        }
+
+    }
+
+    class ParameterDeclaration {
+
+        private final TypeDeclaration type;
+        private final String name;
+
+        public ParameterDeclaration(TypeDeclaration type, String name) {
+            this.type = type;
+            this.name = name;
+        }
+
+        public TypeDeclaration getType() {
+            return type;
+        }
+
+        public String getName() {
+            return name;
+        }
+
+    }
+
+    class MethodDeclaration {
+
+        private final TypeDeclaration returnType;
+        private final String name;
+        private final List<ParameterDeclaration> parameters;
+
+        public MethodDeclaration(final TypeDeclaration returnType, final String name,
+                final List<ParameterDeclaration> parameters) {
+            this.returnType = returnType;
+            this.name = name;
+            if (parameters != null && !parameters.isEmpty()) {
+                this.parameters = parameters;
+            } else {
+                this.parameters = null;
+            }
+        }
+
+        public TypeDeclaration getReturnType() {
+            return returnType;
+        }
+
+        public String getName() {
+            return name;
+        }
+
+        public List<ParameterDeclaration> getParameters() {
+            return parameters;
+        }
+
+    }
+
+    class FieldDeclaration extends ParameterDeclaration {
+
+        public FieldDeclaration(final TypeDeclaration type, final String name) {
+            super(type, name);
+        }
+
+    }
+
+    public BuilderClassDescriptor(final GeneratedType genType) {
+        if (genType == null) {
+            throw new IllegalArgumentException("Generated type reference cannot be NULL!");
+        }
+        this.genType = genType;
+        this.imports = GeneratorUtil.createImports(genType);
+        addToImports(genType.getPackageName(), genType.getName());
+        packageName = genType.getPackageName();
+        className = genType.getName();
+        methods = createMethods();
+        fields = createFieldsFromMethods();
+        importsNames = createImportsNames();
+    }
+
+    private Set<MethodDeclaration> createMethods() {
+        final Set<MethodDeclaration> methods = new LinkedHashSet<>();
+        storeMethodsOfIfc(methods, genType);
+        storeMethodsOfImplementedIfcs(methods, genType.getImplements());
+        return methods;
+    }
+
+    private void storeMethodsOfIfc(final Set<MethodDeclaration> methodStorage, final GeneratedType ifc) {
+        for (MethodSignature methodSignature : ifc.getMethodDefinitions()) {
+            final List<ParameterDeclaration> parameterDeclarations = getParameterDeclarationsFrom(methodSignature
+                    .getParameters());
+            methodStorage.add(new MethodDeclaration(new TypeDeclaration(methodSignature.getReturnType()),
+                    methodSignature.getName(), parameterDeclarations));
+        }
+        if (ifc.getEnclosedTypes() != null && !ifc.getEnclosedTypes().isEmpty()) {
+            addToImports(ifc.getPackageName(), ifc.getName() + ".*");
+        }
+    }
+
+    private List<ParameterDeclaration> getParameterDeclarationsFrom(final List<MethodSignature.Parameter> parameters) {
+        final List<ParameterDeclaration> parameterDeclarations = new ArrayList<>();
+        for (MethodSignature.Parameter mp : parameters) {
+            parameterDeclarations.add(new ParameterDeclaration(new TypeDeclaration(mp.getType()), mp.getName()));
+        }
+        return parameterDeclarations;
+    }
+
+    private void storeMethodsOfImplementedIfcs(final Set<MethodDeclaration> methodStorage,
+            final List<Type> implementedIfcs) {
+        if (implementedIfcs == null || implementedIfcs.isEmpty()) {
+            return;
+        }
+        for (Type implementedIfc : implementedIfcs) {
+            if ((implementedIfc instanceof GeneratedType && !(implementedIfc instanceof GeneratedTransferObject))) {
+                final GeneratedType ifc = ((GeneratedType) implementedIfc);
+                storeMethodsOfIfc(methodStorage, ifc);
+                storeMethodsOfImplementedIfcs(methodStorage, ifc.getImplements());
+            } else if (implementedIfc.getFullyQualifiedName().equals(Augmentable.class.getName())) {
+                for (Method m : Augmentable.class.getMethods()) {
+                    if (m.getName().equals(GET_AUGMENTATION_METHOD_NAME)) {
+                        addToImports(JAVA_UTIL, HASH_MAP);
+                        addToImports(JAVA_UTIL, MAP);
+                        java.lang.reflect.Type returnType = m.getReturnType();
+                        final String fullyQualifiedName = ((Class<?>) returnType).getName();
+                        addToImports(getPackageFrom(fullyQualifiedName), getNameFrom(fullyQualifiedName));
+                        TypeDeclaration augmentMethodType = new TypeDeclaration(getPackageFrom(fullyQualifiedName),
+                                getNameFrom(fullyQualifiedName), new TypeDeclaration(genType));
+                        augmentField = createFieldFromGetMethod(new MethodDeclaration(augmentMethodType, m.getName(),
+                                null));
+                    }
+                }
+            }
+        }
+    }
+
+    private void addToImports(final String pkg, final String name) {
+        if (imports == null) {
+            imports = new LinkedHashMap<>();
+        }
+        if (imports.get(name) == null) {
+            imports.put(name, pkg);
+        }
+    }
+
+    private String getPackageFrom(final String fullyQualifiedName) {
+        final int lastDotIndex = fullyQualifiedName.lastIndexOf(Constants.DOT);
+        return lastDotIndex == -1 ? "" : fullyQualifiedName.substring(0, lastDotIndex);
+    }
+
+    private String getNameFrom(final String fullyQualifiedName) {
+        final int lastDotIndex = fullyQualifiedName.lastIndexOf(Constants.DOT);
+        return lastDotIndex == -1 ? fullyQualifiedName : fullyQualifiedName.substring(lastDotIndex + 1);
+    }
+
+    private Set<FieldDeclaration> createFieldsFromMethods() {
+        final Set<FieldDeclaration> result = new LinkedHashSet<>();
+
+        if (methods == null || methods.isEmpty()) {
+            return result;
+        }
+
+        for (MethodDeclaration m : methods) {
+            final FieldDeclaration createdField = createFieldFromGetMethod(m);
+            if (createdField != null) {
+                result.add(createdField);
+            }
+        }
+        return result;
+    }
+
+    private FieldDeclaration createFieldFromGetMethod(final MethodDeclaration method) {
+        if (method == null || method.getName() == null || method.getName().isEmpty()) {
+            return null;
+        } else if (method.getName().startsWith(GET_PREFIX)) {
+            final String fieldNameFromMethod = method.getName().substring(GET_PREFIX.length());
+            final String fieldName = Character.toLowerCase(fieldNameFromMethod.charAt(0))
+                    + fieldNameFromMethod.substring(1);
+            return new FieldDeclaration(method.getReturnType(), fieldName);
+        }
+        return null;
+    }
+
+    private List<String> createImportsNames() {
+        final List<String> result = new ArrayList<>();
+
+        if (imports == null || imports.isEmpty()) {
+            return result;
+        }
+
+        for (Map.Entry<String, String> entry : imports.entrySet()) {
+            final String typeName = entry.getKey();
+            final String packageName = entry.getValue();
+            result.add(packageName + Constants.DOT + typeName);
+        }
+        return result;
+    }
+
+    public String getPackageName() {
+        return packageName;
+    }
+
+    /**
+     * @return list of imports or empty list
+     */
+    public List<String> getImportsNames() {
+        return importsNames;
+    }
+
+    public String getClassName() {
+        return className;
+    }
+
+    /**
+     * @return set of methods or empty set
+     */
+    public Set<FieldDeclaration> getFields() {
+        return fields;
+    }
+
+    /**
+     * @return set of methods or empty set
+     */
+    public Set<MethodDeclaration> getMethods() {
+        return methods;
+    }
+
+    /**
+     * @return declaration of augment field or NULL
+     */
+    public FieldDeclaration getAugmentField() {
+        return augmentField;
+    }
+
+}
diff --git a/opendaylight/sal/yang-prototype/code-generator/binding-java-api-generator/src/main/java/org/opendaylight/controller/sal/java/api/generator/BuilderGenerator.java b/opendaylight/sal/yang-prototype/code-generator/binding-java-api-generator/src/main/java/org/opendaylight/controller/sal/java/api/generator/BuilderGenerator.java
new file mode 100644 (file)
index 0000000..07ee733
--- /dev/null
@@ -0,0 +1,26 @@
+package org.opendaylight.controller.sal.java.api.generator;
+
+import java.io.IOException;
+import java.io.StringWriter;
+import java.io.Writer;
+
+import org.opendaylight.controller.sal.binding.model.api.CodeGenerator;
+import org.opendaylight.controller.sal.binding.model.api.GeneratedTransferObject;
+import org.opendaylight.controller.sal.binding.model.api.GeneratedType;
+import org.opendaylight.controller.sal.binding.model.api.Type;
+
+public final class BuilderGenerator implements CodeGenerator {
+
+    public static final String FILE_NAME_SUFFIX = "Builder";
+
+    @Override
+    public Writer generate(Type type) throws IOException {
+        Writer writer = new StringWriter();
+        if (type instanceof GeneratedType && !(type instanceof GeneratedTransferObject)) {
+            BuilderTemplate builerGeneratorXtend = new BuilderTemplate();
+            writer.write(builerGeneratorXtend.generate(new BuilderClassDescriptor((GeneratedType) type)).toString());
+        }
+        return writer;
+    }
+
+}
diff --git a/opendaylight/sal/yang-prototype/code-generator/binding-java-api-generator/src/main/java/org/opendaylight/controller/sal/java/api/generator/BuilderTemplate.xtend b/opendaylight/sal/yang-prototype/code-generator/binding-java-api-generator/src/main/java/org/opendaylight/controller/sal/java/api/generator/BuilderTemplate.xtend
new file mode 100644 (file)
index 0000000..484fbfb
--- /dev/null
@@ -0,0 +1,96 @@
+package org.opendaylight.controller.sal.java.api.generator
+
+import java.util.List
+import java.util.Set
+
+class BuilderTemplate {
+
+    val static BUILDER = 'Builder'
+    val static IMPL = 'Impl'
+
+    def generate(BuilderClassDescriptor cd) '''
+        package Â«cd.packageName»;
+        Â«IF !cd.importsNames.empty»
+            
+            Â«FOR in : cd.importsNames»
+                import Â«in»;
+            Â«ENDFOR»
+        Â«ENDIF»
+        
+        public class Â«cd.className»«BUILDER» {
+        
+            Â«fields(cd.fields, cd.augmentField)»
+
+            Â«IF !cd.fields.empty»
+                Â«FOR field : cd.fields SEPARATOR '\n'»
+                    public Â«cd.className»«BUILDER» set«field.name.toFirstUpper»(«field.type.name»«field.type.generics.print» Â«field.name») {
+                        this.«field.name» = Â«field.name»;
+                        return this;
+                    }
+                Â«ENDFOR»
+            Â«ENDIF»
+            Â«IF cd.augmentField != null»
+                
+                public Â«cd.className»«BUILDER» add«cd.augmentField.name.toFirstUpper»(Class<? extends Â«cd.augmentField.type.name»«cd.augmentField.type.generics.print»> augmentationType, Â«cd.augmentField.type.name»«cd.augmentField.type.generics.print» augmentation) {
+                    this.«cd.augmentField.name».put(augmentationType, augmentation);
+                    return this;
+                }
+            Â«ENDIF»
+
+            public Â«cd.className» build() {
+                return new Â«cd.className»«IMPL»();
+            }
+
+            private class Â«cd.className»«IMPL» implements Â«cd.className» {
+
+                Â«fields(cd.fields, cd.augmentField)»
+
+                private Â«cd.className»«IMPL»() {
+                    Â«IF !cd.fields.empty»
+                        Â«FOR field : cd.fields»
+                            this.«field.name» = Â«cd.className»«BUILDER».this.«field.name»;
+                        Â«ENDFOR»
+                    Â«ENDIF»
+                    Â«IF cd.augmentField != null»
+                        this.«cd.augmentField.name».putAll(«cd.className»«BUILDER».this.«cd.augmentField.name»);
+                    Â«ENDIF»
+                }
+
+                Â«IF !cd.fields.empty»
+                    Â«FOR field : cd.fields SEPARATOR '\n'»
+                        @Override
+                        public Â«field.type.name»«field.type.generics.print» get«field.name.toFirstUpper»() {
+                            return Â«field.name»;
+                        }
+                    Â«ENDFOR»
+                Â«ENDIF»
+                Â«IF cd.augmentField != null»
+
+                    @Override
+                    public <E extends Â«cd.augmentField.type.name»«cd.augmentField.type.generics.print»> E get«cd.augmentField.name.toFirstUpper»(Class<E> augmentationType) {
+                        if (augmentationType == null) {
+                            throw new IllegalArgumentException("Augmentation Type reference cannot be NULL!");
+                        }
+                        return (E) Â«cd.augmentField.name».get(augmentationType);
+                    }
+                Â«ENDIF»
+
+            }
+
+        }
+    '''
+
+    def private fields(Set<BuilderClassDescriptor.FieldDeclaration> fields, BuilderClassDescriptor.FieldDeclaration augmentField) '''
+        Â«IF !fields.empty»
+            Â«FOR field : fields»
+                private Â«field.type.name»«field.type.generics.print» Â«field.name»;
+            Â«ENDFOR»
+        Â«ENDIF»
+        Â«IF augmentField != null»
+            private Map<Class<? extends Â«augmentField.type.name»«augmentField.type.generics.print»>, Â«augmentField.type.name»«augmentField.type.generics.print»> Â«augmentField.name» = new HashMap<>();
+        Â«ENDIF»
+    '''
+
+    def private print(List<BuilderClassDescriptor.TypeDeclaration> generics) '''«IF generics != null && !generics.empty»<«FOR generic : generics SEPARATOR ', '»«generic.name»«ENDFOR»>«ENDIF»'''
+
+}
index bcc17906d6ee7f30e947576caa7797f4de152561..8f5c456f87c46b6e80bda965c92ab050a5278d84 100644 (file)
@@ -24,6 +24,8 @@ final class Constants {
 
     public static final String GAP = " ";
     public static final String COMMA = ",";
+    public static final String DOT = ".";
+    public static final String ASTERISK = "*";
     public static final String NL = "\n";
     public static final String SC = ";";
     public static final String TAB = "    ";
index 55b8d777b790522fea9ec27d0919ec3bac36e766..1d2e60f511fc970b4ad931e521fe4cdeffba002f 100644 (file)
@@ -23,6 +23,7 @@ public final class GeneratorJavaFile {
     private final CodeGenerator interfaceGenerator;
     private final ClassCodeGenerator classGenerator;
     private final EnumGenerator enumGenerator;
+    private final BuilderGenerator builderGenerator;
 
     private final Set<GeneratedType> genTypes;
     private final Set<GeneratedTransferObject> genTransferObjects;
@@ -35,6 +36,7 @@ public final class GeneratorJavaFile {
         this.enumerations = new HashSet<>();
         this.classGenerator = new ClassCodeGenerator();
         this.enumGenerator = new EnumGenerator();
+        this.builderGenerator = new BuilderGenerator();
     }
 
     public GeneratorJavaFile(final Set<GeneratedType> types, final Set<GeneratedTransferObject> genTransferObjects,
@@ -42,6 +44,7 @@ public final class GeneratorJavaFile {
         this.interfaceGenerator = new InterfaceGenerator();
         this.classGenerator = new ClassCodeGenerator();
         this.enumGenerator = new EnumGenerator();
+        this.builderGenerator = new BuilderGenerator();
 
         this.genTypes = types;
         this.genTransferObjects = genTransferObjects;
@@ -51,14 +54,19 @@ public final class GeneratorJavaFile {
     public List<File> generateToFile(final File parentDirectory) throws IOException {
         final List<File> result = new ArrayList<>();
         for (GeneratedType type : genTypes) {
-            final File genFile = generateTypeToJavaFile(parentDirectory, type, interfaceGenerator);
+            final File genFile = generateTypeToJavaFile(parentDirectory, type, interfaceGenerator, "");
+            final File genBuilderFile = generateTypeToJavaFile(parentDirectory, type, builderGenerator,
+                    BuilderGenerator.FILE_NAME_SUFFIX);
 
             if (genFile != null) {
                 result.add(genFile);
             }
+            if (genBuilderFile != null) {
+                result.add(genBuilderFile);
+            }
         }
         for (GeneratedTransferObject transferObject : genTransferObjects) {
-            final File genFile = generateTypeToJavaFile(parentDirectory, transferObject, classGenerator);
+            final File genFile = generateTypeToJavaFile(parentDirectory, transferObject, classGenerator, "");
 
             if (genFile != null) {
                 result.add(genFile);
@@ -66,7 +74,7 @@ public final class GeneratorJavaFile {
         }
 
         for (Enumeration enumeration : enumerations) {
-            final File genFile = generateTypeToJavaFile(parentDirectory, enumeration, enumGenerator);
+            final File genFile = generateTypeToJavaFile(parentDirectory, enumeration, enumGenerator, "");
 
             if (genFile != null) {
                 result.add(genFile);
@@ -76,7 +84,7 @@ public final class GeneratorJavaFile {
         return result;
     }
 
-    private File generateTypeToJavaFile(final File parentDir, final Type type, final CodeGenerator generator)
+    private File generateTypeToJavaFile(final File parentDir, final Type type, final CodeGenerator generator, String fileNameSuffix)
             throws IOException {
         if (parentDir == null) {
             log.warn("Parent Directory not specified, files will be generated "
@@ -95,7 +103,7 @@ public final class GeneratorJavaFile {
         if (!packageDir.exists()) {
             packageDir.mkdirs();
         }
-        final File file = new File(packageDir, type.getName() + ".java");
+        final File file = new File(packageDir, type.getName() + fileNameSuffix + ".java");
         try (final FileWriter fw = new FileWriter(file)) {
             file.createNewFile();
 
index db42d32fe6e7415f0ee90084c869fb06db9856c1..6a38050a4e5f7db6f037ef6b3cef5736e1010d2f 100644 (file)
@@ -90,10 +90,13 @@ public class GeneratorJavaFileTest {
                 + "controller" + FS + "gen").list();
         List<String> filesList = Arrays.asList(files);
 
-        assertEquals(3, files.length);
+        assertEquals(6, files.length);
         assertTrue(filesList.contains("Type1.java"));
         assertTrue(filesList.contains("Type2.java"));
         assertTrue(filesList.contains("Type3.java"));
+        assertTrue(filesList.contains("Type1Builder.java"));
+        assertTrue(filesList.contains("Type2Builder.java"));
+        assertTrue(filesList.contains("Type3Builder.java"));
     }
 
     @Ignore
diff --git a/opendaylight/sal/yang-prototype/code-generator/code-generator-demo/pom.xml b/opendaylight/sal/yang-prototype/code-generator/code-generator-demo/pom.xml
deleted file mode 100644 (file)
index d4c5b05..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\r
-       xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">\r
-       <modelVersion>4.0.0</modelVersion>\r
-    <groupId>org.opendaylight.controller</groupId>\r
-       <artifactId>code-generator-demo</artifactId>\r
-    <version>1.0</version>\r
-    <packaging>jar</packaging>\r
-\r
-       <dependencies>\r
-               <dependency>\r
-                       <groupId>org.antlr</groupId>\r
-                       <artifactId>antlr4</artifactId>\r
-                       <version>4.0</version>\r
-               </dependency>\r
-               <dependency>\r
-                       <groupId>org.opendaylight.controller</groupId>\r
-                       <artifactId>binding-generator-impl</artifactId>\r
-               </dependency>\r
-               <dependency>\r
-                       <groupId>org.opendaylight.controller</groupId>\r
-                       <artifactId>binding-java-api-generator</artifactId>\r
-               </dependency>\r
-       </dependencies>\r
-\r
-       <build>\r
-               <plugins>\r
-                       <plugin>\r
-                               <artifactId>maven-assembly-plugin</artifactId>\r
-                               <version>2.4</version>\r
-                               <configuration>\r
-                                       <descriptorRefs>\r
-                                               <descriptorRef>jar-with-dependencies</descriptorRef>\r
-                                       </descriptorRefs>\r
-                                       <archive>\r
-                                               <manifest>\r
-                                                       <mainClass>org.opendaylight.controller.yang.Demo</mainClass>\r
-                                               </manifest>\r
-                                       </archive>\r
-                               </configuration>\r
-                               <executions>\r
-                                       <execution>\r
-                                               <id>make-assembly</id>\r
-                                               <phase>package</phase>\r
-                                               <goals>\r
-                                                       <goal>single</goal>\r
-                                               </goals>\r
-                                       </execution>\r
-                               </executions>\r
-                       </plugin>\r
-               </plugins>\r
-       </build>\r
-</project>\r
-\r
diff --git a/opendaylight/sal/yang-prototype/code-generator/code-generator-demo/src/main/java/org/opendaylight/controller/yang/Demo.java b/opendaylight/sal/yang-prototype/code-generator/code-generator-demo/src/main/java/org/opendaylight/controller/yang/Demo.java
deleted file mode 100644 (file)
index ee54887..0000000
+++ /dev/null
@@ -1,93 +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.yang;
-
-import java.io.File;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-import org.opendaylight.controller.sal.binding.generator.api.BindingGenerator;
-import org.opendaylight.controller.sal.binding.generator.impl.BindingGeneratorImpl;
-import org.opendaylight.controller.sal.binding.model.api.GeneratedTransferObject;
-import org.opendaylight.controller.sal.binding.model.api.GeneratedType;
-import org.opendaylight.controller.sal.binding.model.api.Type;
-import org.opendaylight.controller.sal.java.api.generator.GeneratorJavaFile;
-import org.opendaylight.controller.yang.model.api.Module;
-import org.opendaylight.controller.yang.model.api.SchemaContext;
-import org.opendaylight.controller.yang.parser.impl.YangParserImpl;
-
-public class Demo {
-    private static final String ERR_MSG = "2 parameters expected: 1. -f=<path-to-input-folder>, 2. -o=<output-folder>";
-
-    public static void main(String[] args) throws Exception {
-        if (args.length != 2) {
-            System.err.println(ERR_MSG);
-            return;
-        }
-
-        String inputFilesDir = null;
-        String outputFilesDir = null;
-        if (args[0].startsWith("-f=")) {
-            inputFilesDir = args[0].substring(3);
-        } else {
-            System.err.println("Missing input-folder declaration (-f=)");
-        }
-
-        if (args[1].startsWith("-o=")) {
-            outputFilesDir = args[1].substring(3);
-        } else {
-            System.err.println("Missing output-folder declaration (-o=)");
-        }
-        
-        File resourceDir = new File(inputFilesDir);
-        if (!resourceDir.exists()) {
-            throw new IllegalArgumentException(
-                    "Specified input-folder does not exists: "
-                            + resourceDir.getAbsolutePath());
-        }
-        
-        final File outputFolder = new File(outputFilesDir);
-        if (!outputFolder.exists()) {
-            outputFolder.mkdirs();
-        }
-        
-        String[] dirList = resourceDir.list();
-        List<File> inputFiles = new ArrayList<File>();
-        for (String fileName : dirList) {
-            inputFiles.add(new File(resourceDir, fileName));
-        }
-
-        final YangParserImpl parser = new YangParserImpl();
-        final BindingGenerator bindingGenerator = new BindingGeneratorImpl();
-        final Set<Module> modulesToBuild = parser.parseYangModels(inputFiles);
-
-        final SchemaContext context = parser
-                .resolveSchemaContext(modulesToBuild);
-        final List<Type> types = bindingGenerator.generateTypes(context);
-        final Set<GeneratedType> typesToGenerate = new HashSet<GeneratedType>();
-        final Set<GeneratedTransferObject> tosToGenerate = new HashSet<GeneratedTransferObject>();
-        for (Type type : types) {
-            if (type instanceof GeneratedType && !(type instanceof GeneratedTransferObject)) {
-                typesToGenerate.add((GeneratedType) type);
-            }
-
-            if (type instanceof GeneratedTransferObject) {
-                tosToGenerate.add((GeneratedTransferObject) type);
-            } else if (type instanceof GeneratedType) {
-                typesToGenerate.add((GeneratedType) type);
-            }
-        }
-
-        final GeneratorJavaFile generator = new GeneratorJavaFile(typesToGenerate, tosToGenerate);
-        
-        generator.generateToFile(outputFolder);
-        System.out.println("Modules built: " + modulesToBuild.size());
-    }
-}
diff --git a/opendaylight/sal/yang-prototype/code-generator/code-generator-demo/src/main/resources/demo-topology.yang b/opendaylight/sal/yang-prototype/code-generator/code-generator-demo/src/main/resources/demo-topology.yang
deleted file mode 100644 (file)
index 303edc2..0000000
+++ /dev/null
@@ -1,223 +0,0 @@
-module demo-topology {
-    yang-version 1;
-    namespace "urn:demo.simple-topology";
-    prefix "tp";
-    import simple-list-demo { prefix "simple"; revision-date 2008-01-01; }
-    import controller-network {prefix "cn";}
-       import mount  {prefix "mnt";}
-
-    organization "OPEN DAYLIGHT";
-    contact "http://www.opendaylight.org/";
-
-    description "
-        This module contains the definitions of elements that creates network 
-        topology i.e. definition of network nodes and links. This module is
-        not designed to be used solely for network representation. This module
-        SHOULD be used as base module in defining the network topology.
-    ";
-
-    revision "2013-02-08"{
-        reference " WILL BE DEFINED LATER";
-    }
-    
-    
-    
-    
-    
-    deviation /base:system/base:user/base:type {
-         deviate add {
-             default "admin"; // new users are 'admin' by default
-         }
-     }
-     
-    deviation /base:system/base:name-server {
-         deviate replace {
-             max-elements 3;
-         }
-     }
-     
-     deviation "/base:system" {
-         deviate delete {
-             must "daytime or time";
-         }
-     }
-     
-     
-     
-     
-     
-    
-    grouping target {
-       status "current";
-         leaf address {
-             type inet:ip-address;
-             description "Target IP address";
-         }
-         leaf port {
-             type inet:port-number;
-             description "Target port number";
-         }
-     }
-     
-     augment "/cn:network/cn:topologies/cn:topology" {
-        container prefixes {
-            container "prefix" {
-                leaf id {
-                    type string;
-
-                    description "";
-                }
-
-                leaf-list advertising-node-id {
-                    type cn:node-ref;
-
-                    description "";
-                }
-            }
-        }
-        mnt:mountpoint point  {
-               mnt:target-ref target;
-           
-            } 
-    }
-
-     container peer {
-         container destination {
-             uses target;
-         }
-     }
-
-    container topology {
-    
-       leaf ifType {
-             type enumeration {
-                 enum ethernet;
-                 enum atm;
-             }
-         }
-         leaf ifMTU {
-             type uint32;
-         }
-         must "ifType != 'ethernet' or " +
-              "(ifType = 'ethernet' and ifMTU = 1500)" {
-             error-message "An ethernet MTU must be 1500";
-         }
-    
-       presence "test-presence";
-    
-        description "
-            This is the model of abstract topology which contains only Network
-            Nodes and Network Links. Each topology MUST be identified by
-            unique topology-id for reason that the store could contain many
-            topologies.
-        ";
-
-        leaf topology-id {
-            type string;
-            description "
-                It is presumed that datastore will contain many topologies. To
-                distinguish between topologies it is vital to have UNIQUE
-                topology identifier.
-            ";
-        }
-
-        container network-nodes {
-            list network-node {
-               ordered-by system;
-                description "The list of network nodes defined for topology.";
-
-                key "node-id";
-
-                leaf node-id {
-                    type string;
-                    description "The Topology identifier of network-node.";
-                }
-                
-                list network-interface {
-                    key "interface-id";
-                    
-                    leaf interface-id {
-                        type uint8;
-                    }
-                    
-                    leaf interface-address {
-                        type string;
-                    }
-                }
-                
-                container node-attributes {
-                    description "
-                        Additional attributes that can Network Node contains.
-                    ";
-
-                    leaf geo-latitude {
-                        type decimal64 {
-                            fraction-digits 2;
-                        }
-                        config true;
-                    }
-
-                    leaf geo-longitude {
-                        type decimal64 {
-                            fraction-digits 2;
-                        }
-                        config true;
-                    }
-                }
-            }
-        }
-        
-        container network-links {
-            list network-link {
-                description "
-                    The Network Link which is defined by Local (Source) and
-                    Remote (Destination) Network Nodes. Every link MUST be
-                    defined either by identifier and his local and remote
-                    Network Nodes (in real applications it is common that many
-                    links are originated from one node and end up in same
-                    remote node). To ensure that we would always know to
-                    distinguish between links, every link SHOULD have
-                    identifier.
-                ";
-                key "link-id";
-
-                leaf link-id {
-                    type string;
-                    description "";
-                }
-
-                container source {
-                    leaf node-id {
-                        type string;
-                        description "Source node identifier.";
-                    }
-                }
-
-                container destination {
-                    leaf node-id {
-                        type string;
-                        description "Destination node identifier.";
-                    }
-                }
-
-                container link-attributes {
-                    description "Aditional attributes that can Network Link contains.";
-                }
-            }
-        }
-    }
-    
-    rpc activate-software-image {
-         input {
-             leaf image-name {
-                 type string;
-             }
-         }
-         output {
-             leaf status {
-                 type string;
-             }
-         }
-     }
-     
-}
diff --git a/opendaylight/sal/yang-prototype/code-generator/code-generator-demo/src/main/resources/demo/types1.yang b/opendaylight/sal/yang-prototype/code-generator/code-generator-demo/src/main/resources/demo/types1.yang
deleted file mode 100644 (file)
index 1025298..0000000
+++ /dev/null
@@ -1,80 +0,0 @@
-module types1 {
-       yang-version 1;
-    namespace "urn:simple.container.demo";
-    prefix "t1";
-    
-
-    organization "Cisco";
-
-    contact "WILL-BE-DEFINED-LATER";
-    
-    
-    leaf mybits {
-         type bits {
-             bit disable-nagle {
-                 position 0;
-             }
-             bit auto-sense-speed {
-                 position 1;
-             }
-             bit 10-Mb-only {
-                 position 2;
-             }
-         }
-         default "auto-sense-speed";
-     }
-    
-    container interfaces {
-         list ifEntry {
-             key "ifIndex";
-
-             leaf ifIndex {
-                 type uint32;
-             }
-             leaf ifDescr {
-                 type string;
-             }
-             leaf ifType {
-                 type uint8;
-             }
-             leaf ifMtu {
-                 type int32;
-             }
-         }
-     }
-    
-    
-       container topology {
-               leaf name {
-                       type string;
-               }
-       }
-       
-       
-       
-       
-       
-       
-       
-//     typedef my-string {
-//             type string {
-//                     length "0..4";
-//             pattern "[0-9a-fA-F]*";
-//             }
-//     }
-
-
-//     leaf completed {
-//             type types2:percent;
-//  }
-
-//     leaf testleaf {
-//             type data:my-base-int32-type;
-//     }
-
-//     leaf-list domain-search {
-//             type string;
-//             description "List of domain names to search";
-//     }
-       
-}
diff --git a/opendaylight/sal/yang-prototype/code-generator/code-generator-demo/src/main/resources/demo/types2.yang b/opendaylight/sal/yang-prototype/code-generator/code-generator-demo/src/main/resources/demo/types2.yang
deleted file mode 100644 (file)
index a056bdb..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-module types2 {
-       yang-version 1;
-    namespace "urn:simple.types.data.demo";
-    prefix "t2";
-    
-    import types1 {
-         prefix "t1";
-     }
-
-    organization "Cisco";
-
-    contact "WILL-BE-DEFINED-LATER";
-
-    description "This is types-data test description";
-
-    revision "2013-02-27" {
-        reference " WILL BE DEFINED LATER";
-    }
-    
-    
-     augment "/t1:interfaces/t1:ifEntry" {
-         when "t1:ifType='ds0'";
-         leaf ds0ChannelNumber {
-             type string;
-         }
-     }
-     
-     typedef my-leaf-ref {
-               type leafref {
-                       path "/t1:topology/t1:name";
-               }
-               description "This type is used for leafs that reference network node instance.";
-       }
-     
-}
diff --git a/opendaylight/sal/yang-prototype/code-generator/code-generator-demo/src/main/resources/demo/types3.yang b/opendaylight/sal/yang-prototype/code-generator/code-generator-demo/src/main/resources/demo/types3.yang
deleted file mode 100644 (file)
index 0d09259..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-module types3 {
-       yang-version 1;
-    namespace "urn:simple.types3.data.demo";
-    prefix "scd";
-
-    organization "Cisco";
-
-    contact "WILL-BE-DEFINED-LATER";
-
-    description "This is types-data test description";
-
-    revision "2013-02-27" {
-        reference " WILL BE DEFINED LATER";
-    }
-    
-    typedef my-decimal {
-         type decimal64 {
-               fraction-digits 2;
-         }
-    }
-
-       typedef my-base-int32-type {
-         type int32 {
-               range "0..32";
-         }
-    }
-    
-    typedef percent {
-         type uint8 {
-             range "0 .. 100";
-         }
-         description "Percentage";
-       }
-       
-}
index 8b576c3ce96a43d29480acb1cfe6f7a810666b4e..ca8507f9f4c90331691819a37e9e078f6aeecab1 100644 (file)
@@ -14,7 +14,7 @@ module controller-openflow-ne {
 
     augment "/cn:network/cn:network-elements/cn:network-element" {
 
-        container flow-tables {
+        container flow-tables2 {
             list flow-table {
 
                 key "id";
similarity index 66%
rename from opendaylight/sal/yang-prototype/code-generator/code-generator-demo/src/main/resources/test-topology.yang
rename to opendaylight/sal/yang-prototype/code-generator/samples/maven-code-gen-sample/src/main/yang/demo-topology.yang
index 797ab2ced24d6d799f4c81a90da677ee27ab7a68..4fef1cddd255fd2311237595ea4211b3f9be42a5 100644 (file)
@@ -1,13 +1,9 @@
-// vi: set smarttab sw=4 tabstop=4:
-module abstract-topology {
+module demo-topology {
        yang-version 1;
-    namespace "pre:simple.test.demo";
+    namespace "urn:model.1demo-275topology.4.5.my";
     prefix "tp";
 
-       import ietf-inet-types { prefix "inet"; }
-    import abstract-prefixes { prefix "abs-pref"; }
-    
-       organization "OPEN DAYLIGHT";
+    organization "OPEN DAYLIGHT";
     contact "http://www.opendaylight.org/";
 
     description "
@@ -16,30 +12,9 @@ module abstract-topology {
                not designed to be used solely for network representation. This module
                SHOULD be used as base module in defining the network topology.
        ";
-    
-    revision "2012-02-08" {
-        reference " WILL BE DEFINED LATER";
-    }
-
-    typedef topology-id-ref {
-       type leafref {
-               path "/tp:topology/tp:topology-id";
-       }
-       description "This type is used for leafs that reference topology identifier instance.";
-    }
 
-       typedef network-node-id-ref {
-               type leafref {
-                       path "/tp:topology/tp:network-nodes/tp:network-node/tp:node-id";
-               }
-               description "This type is used for leafs that reference network node instance.";
-       }
-
-       typedef link-id-ref {
-               type leafref {
-                       path "/tp:topology/tp:network-links/tp:network-link/tp:link-id";
-               }
-               description "This type is used for leafs that reference network link instance.";
+    revision "2013-02-08"{
+               reference " WILL BE DEFINED LATER";
        }
 
        container topology {
@@ -51,7 +26,7 @@ module abstract-topology {
                ";
 
         leaf topology-id {
-            type inet:uri;
+            type string;
             description "
                                It is presumed that datastore will contain many topologies. To
                                distinguish between topologies it is vital to have UNIQUE
@@ -66,14 +41,40 @@ module abstract-topology {
                        key "node-id";
 
                        leaf node-id {
-                               type inet:uri;
+                               type string;
                                description "The Topology identifier of network-node.";
                        }
-
-                   container attributes {
+                
+                list network-interface {
+                    key "interface-id";
+                    
+                    leaf interface-id {
+                        type uint8;
+                    }
+                    
+                    leaf interface-address {
+                        type string;
+                    }
+                }
+                
+                   container node-attributes {
                                        description "
                                                Additional attributes that can Network Node contains.
                                        ";
+
+                                       leaf geo-latitude {
+                                               type decimal64 {
+                                                       fraction-digits 2;
+                                               }
+                                               config true;
+                                       }
+
+                                       leaf geo-longitude {
+                                               type decimal64 {
+                                                       fraction-digits 2;
+                                               }
+                                               config true;
+                                       }
                                }
                }
         }
@@ -93,30 +94,28 @@ module abstract-topology {
                        key "link-id";
 
                        leaf link-id {
-                               type inet:uri;
+                               type string;
                                description "";
                        }
 
                    container source {
                                        leaf node-id {
-                                               type node-id-ref;
+                                               type string;
                                                description "Source node identifier.";
                                        }
                                }
 
                                container destination {
                                        leaf node-id {
-                                               type node-id-ref;
+                                               type string;
                                                description "Destination node identifier.";
                                        }
                                }
 
-                               container attributes {
+                               container link-attributes {
                                        description "Aditional attributes that can Network Link contains.";
                                }
                    }
         }
     }
-
-    //TODO: add base operations
-}
+}
\ No newline at end of file
index 44ef804e2c0c9dd9bb10223d9bf6fafaaf5b49c3..1d702c26d842d27af07b52ab1d7fb49112df8195 100644 (file)
@@ -16,99 +16,254 @@ import java.util.Set;
 import org.opendaylight.controller.yang.common.QName;
 import org.opendaylight.controller.yang.model.api.*;
 
+/**
+ * The Schema Context Util contains support methods for searching through Schema Context modules for specified schema
+ * nodes via Schema Path or Revision Aware XPath. The Schema Context Util is designed as mixin,
+ * so it is not instantiable.
+ *
+ * @author Lukas Sedlak <lsedlak@cisco.com>
+ */
 public final class SchemaContextUtil {
 
     private SchemaContextUtil() {
     }
 
+    /**
+     * Method attempts to find DataSchemaNode in Schema Context via specified Schema Path. The returned
+     * DataSchemaNode from method will be the node at the end of the SchemaPath. If the DataSchemaNode is not present
+     * in the Schema Context the method will return <code>null</code>.
+     * <br>
+     * In case that Schema Context or Schema Path are not specified correctly (i.e. contains <code>null</code>
+     * values) the method will return IllegalArgumentException.
+     *
+     * @throws IllegalArgumentException
+     * 
+     * @param context
+     *            Schema Context
+     * @param schemaPath
+     *            Schema Path to search for
+     * @return DataSchemaNode from the end of the Schema Path or
+     *         <code>null</code> if the Node is not present.
+     */
     public static DataSchemaNode findDataSchemaNode(final SchemaContext context, final SchemaPath schemaPath) {
-        if (schemaPath != null) {
-            final Module module = resolveModuleFromSchemaPath(context, schemaPath);
-            final Queue<QName> prefixedPath = new LinkedList<>(schemaPath.getPath());
+        if (context == null) {
+            throw new IllegalArgumentException("Schema Context reference cannot be NULL!");
+        }
+        if (schemaPath == null) {
+            throw new IllegalArgumentException("Schema Path reference cannot be NULL");
+        }
 
-            if ((module != null) && (prefixedPath != null)) {
-                return findSchemaNodeForGivenPath(context, module, prefixedPath);
-            }
+        final Module module = resolveModuleFromSchemaPath(context, schemaPath);
+        final Queue<QName> prefixedPath = new LinkedList<>(schemaPath.getPath());
+
+        if ((module != null) && (prefixedPath != null)) {
+            return findSchemaNodeForGivenPath(context, module, prefixedPath);
         }
         return null;
     }
 
+    /**
+     * Method attempts to find DataSchemaNode inside of provided Schema Context and Yang Module accordingly to
+     * Non-conditional Revision Aware XPath. The specified Module MUST be present in Schema Context otherwise the
+     * operation would fail and return <code>null</code>.
+     * <br>
+     * The Revision Aware XPath MUST be specified WITHOUT the conditional statement (i.e. without [cond]) in path,
+     * because in this state the Schema Context is completely unaware of data state and will be not able to properly
+     * resolve XPath. If the XPath contains condition the method will return IllegalArgumentException.
+     * <br>
+     * In case that Schema Context or Module or Revision Aware XPath contains <code>null</code> references the method
+     * will throw IllegalArgumentException
+     * <br>
+     * If the Revision Aware XPath is correct and desired Data Schema Node is present in Yang module or in depending
+     * module in Schema Context the method will return specified Data Schema Node, otherwise the operation will fail
+     * and method will return <code>null</code>.
+     *
+     * @throws IllegalArgumentException
+     *
+     * @param context Schema Context
+     * @param module Yang Module
+     * @param nonCondXPath Non Conditional Revision Aware XPath
+     * @return Returns Data Schema Node for specified Schema Context for given Non-conditional Revision Aware XPath,
+     * or <code>null</code> if the DataSchemaNode is not present in Schema Context.
+     */
     public static DataSchemaNode findDataSchemaNode(final SchemaContext context, final Module module,
             final RevisionAwareXPath nonCondXPath) {
-        if (nonCondXPath != null) {
-            final String strXPath = nonCondXPath.toString();
+        if (context == null) {
+            throw new IllegalArgumentException("Schema Context reference cannot be NULL!");
+        }
+        if (module == null) {
+            throw new IllegalArgumentException("Module reference cannot be NULL!");
+        }
+        if (nonCondXPath == null) {
+            throw new IllegalArgumentException("Non Conditional Revision Aware XPath cannot be NULL!");
+        }
 
-            if (strXPath != null) {
-                if (strXPath.matches(".*//[.* | .*//].*")) {
-                    // TODO: function to escape conditions in path
-                }
-                if (nonCondXPath.isAbsolute()) {
-                    final Queue<QName> qnamedPath = xpathToQNamePath(context, module, strXPath);
-                    if (qnamedPath != null) {
-                        final DataSchemaNode dataNode = findSchemaNodeForGivenPath(context, module, qnamedPath);
-                        return dataNode;
-                    }
+        final String strXPath = nonCondXPath.toString();
+        if (strXPath != null) {
+            if (strXPath.contains("[")) {
+                throw new IllegalArgumentException("Revision Aware XPath cannot contains condition!");
+            }
+            if (nonCondXPath.isAbsolute()) {
+                final Queue<QName> qnamedPath = xpathToQNamePath(context, module, strXPath);
+                if (qnamedPath != null) {
+                    final DataSchemaNode dataNode = findSchemaNodeForGivenPath(context, module, qnamedPath);
+                    return dataNode;
                 }
             }
         }
         return null;
     }
 
+    /**
+     * Method attempts to find DataSchemaNode inside of provided Schema Context and Yang Module accordingly to
+     * Non-conditional relative Revision Aware XPath. The specified Module MUST be present in Schema Context otherwise
+     * the operation would fail and return <code>null</code>.
+     * <br>
+     * The relative Revision Aware XPath MUST be specified WITHOUT the conditional statement (i.e. without [cond]) in
+     * path, because in this state the Schema Context is completely unaware of data state and will be not able to
+     * properly resolve XPath. If the XPath contains condition the method will return IllegalArgumentException.
+     * <br>
+     * The Actual Schema Node MUST be specified correctly because from this Schema Node will search starts. If the
+     * Actual Schema Node is not correct the operation will simply fail, because it will be unable to find desired
+     * DataSchemaNode.
+     * <br>
+     * In case that Schema Context or Module or Actual Schema Node or relative Revision Aware XPath contains
+     * <code>null</code> references the method will throw IllegalArgumentException
+     * <br>
+     * If the Revision Aware XPath doesn't have flag <code>isAbsolute == false</code> the method will
+     * throw IllegalArgumentException.
+     * <br>
+     * If the relative Revision Aware XPath is correct and desired Data Schema Node is present in Yang module or in
+     * depending module in Schema Context the method will return specified Data Schema Node,
+     * otherwise the operation will fail
+     * and method will return <code>null</code>.
+     *
+     * @throws IllegalArgumentException
+     *
+     * @param context Schema Context
+     * @param module Yang Module
+     * @param actualSchemaNode Actual Schema Node
+     * @param relativeXPath Relative Non Conditional Revision Aware XPath
+     * @return DataSchemaNode if is present in specified Schema Context for given relative Revision Aware XPath,
+     * otherwise will return <code>null</code>.
+     */
     public static DataSchemaNode findDataSchemaNodeForRelativeXPath(final SchemaContext context, final Module module,
             final SchemaNode actualSchemaNode, final RevisionAwareXPath relativeXPath) {
-        if ((actualSchemaNode != null) && (relativeXPath != null) && !relativeXPath.isAbsolute()) {
+        if (context == null) {
+            throw new IllegalArgumentException("Schema Context reference cannot be NULL!");
+        }
+        if (module == null) {
+            throw new IllegalArgumentException("Module reference cannot be NULL!");
+        }
+        if (actualSchemaNode == null) {
+            throw new IllegalArgumentException("Actual Schema Node reference cannot be NULL!");
+        }
+        if (relativeXPath == null) {
+            throw new IllegalArgumentException("Non Conditional Revision Aware XPath cannot be NULL!");
+        }
+        if (relativeXPath.isAbsolute()) {
+            throw new IllegalArgumentException("Revision Aware XPath MUST be relative i.e. MUST contains ../, "
+                    + "for non relative Revision Aware XPath use findDataSchemaNode method!");
+        }
 
-            final SchemaPath actualNodePath = actualSchemaNode.getPath();
-            if (actualNodePath != null) {
-                final Queue<QName> qnamePath = resolveRelativeXPath(context, module, relativeXPath, actualNodePath);
+        final SchemaPath actualNodePath = actualSchemaNode.getPath();
+        if (actualNodePath != null) {
+            final Queue<QName> qnamePath = resolveRelativeXPath(context, module, relativeXPath, actualNodePath);
 
-                if (qnamePath != null) {
-                    final DataSchemaNode dataNode = findSchemaNodeForGivenPath(context, module, qnamePath);
-                    return dataNode;
-                }
+            if (qnamePath != null) {
+                final DataSchemaNode dataNode = findSchemaNodeForGivenPath(context, module, qnamePath);
+                return dataNode;
             }
         }
-
         return null;
     }
 
+    /**
+     * Retrieve information from Schema Path and returns the module reference to which Schema Node belongs. The
+     * search for correct Module is based on namespace within the last item in Schema Path. If schema context
+     * contains module with namespace specified in last item of Schema Path, then operation will returns Module
+     * reference, otherwise returns <code>null</code>
+     * <br>
+     * If Schema Context or Schema Node contains <code>null</code> references the method will throw IllegalArgumentException
+     *
+     * @throws IllegalArgumentException
+     *
+     * @param context Schema Context
+     * @param schemaPath Schema Path
+     * @return Module reference for given Schema Path if module is present in Schema Context,
+     * otherwise returns <code>null</code>
+     */
     private static Module resolveModuleFromSchemaPath(final SchemaContext context, final SchemaPath schemaPath) {
-        if ((schemaPath != null) && (schemaPath.getPath() != null)) {
-            final List<QName> path = schemaPath.getPath();
-            if (!path.isEmpty()) {
-                final QName qname = path.get(path.size() - 1);
+        if (context == null) {
+            throw new IllegalArgumentException("Schema Context reference cannot be NULL!");
+        }
+        if (schemaPath == null) {
+            throw new IllegalArgumentException("Schema Path reference cannot be NULL");
+        }
 
-                if ((qname != null) && (qname.getNamespace() != null)) {
-                    return context.findModuleByNamespace(qname.getNamespace());
-                }
+        final List<QName> path = schemaPath.getPath();
+        if (!path.isEmpty()) {
+            final QName qname = path.get(path.size() - 1);
+
+            if ((qname != null) && (qname.getNamespace() != null)) {
+                return context.findModuleByNamespace(qname.getNamespace());
             }
         }
+
         return null;
     }
 
+    /**
+     * Returns the Yang Module from specified Schema Context in which the TypeDefinition is declared. If the
+     * TypeDefinition si not present in Schema Context then the method will return <code>null</code>
+     *
+     * If Schema Context or TypeDefinition contains <code>null</code> references the method will throw IllegalArgumentException
+     *
+     * @throws IllegalArgumentException
+     *
+     * @param context Schema Context
+     * @param type Type Definition
+     * @return Yang Module in which the TypeDefinition is declared, if is not present, returns <code>null</code>.
+     */
     public static Module findParentModuleForTypeDefinition(final SchemaContext context, final TypeDefinition<?> type) {
         final SchemaPath schemaPath = type.getPath();
-        if ((schemaPath != null) && (schemaPath.getPath() != null)) {
-            if (type instanceof ExtendedType) {
-                List<QName> path = schemaPath.getPath();
-                final QName qname = path.get(path.size() - 1);
-
-                if ((qname != null) && (qname.getNamespace() != null)) {
-                    return context.findModuleByNamespace(qname.getNamespace());
-                }
-            } else {
-                List<QName> path = schemaPath.getPath();
-                final QName qname = path.get(path.size() - 2);
+        if (schemaPath == null) {
+            throw new IllegalArgumentException("Schema Path reference cannot be NULL");
+        }
+        final List<QName> qnamedPath = schemaPath.getPath();
+        if (qnamedPath == null || qnamedPath.isEmpty()) {
+            throw new IllegalStateException("Schema Path contains invalid state of path parts."
+                    + "The Schema Path MUST contain at least ONE QName which defines namespace and Local name"
+                    + "of path.");
+        }
 
-                if ((qname != null) && (qname.getNamespace() != null)) {
-                    return context.findModuleByNamespace(qname.getNamespace());
-                }
+        if (type instanceof ExtendedType) {
+            final QName qname = qnamedPath.get(qnamedPath.size() - 1);
+            if ((qname != null) && (qname.getNamespace() != null)) {
+                return context.findModuleByNamespace(qname.getNamespace());
+            }
+        } else {
+            final QName qname = qnamedPath.get(qnamedPath.size() - 2);
+            if ((qname != null) && (qname.getNamespace() != null)) {
+                return context.findModuleByNamespace(qname.getNamespace());
             }
-
         }
         return null;
     }
 
+    /**
+     * Returns parent Yang Module for specified Schema Context in which Schema Node is declared. If the Schema Node
+     * is not present in Schema Context the operation will return <code>null</code>.
+     * <br>
+     * If Schema Context or Schema Node contains <code>null</code> references the method will throw IllegalArgumentException
+     *
+     * @throws IllegalArgumentException
+     *
+     * @param context Schema Context
+     * @param schemaNode Schema Node
+     * @return Yang Module for specified Schema Context and Schema Node, if Schema Node is NOT present,
+     * the method will returns <code>null</code>
+     */
     public static Module findParentModule(final SchemaContext context, final SchemaNode schemaNode) {
         if (context == null) {
             throw new IllegalArgumentException("Schema Context reference cannot be NULL!");
@@ -132,120 +287,246 @@ public final class SchemaContextUtil {
         return context.findModuleByNamespace(qname.getNamespace());
     }
 
+    /**
+     * Method will attempt to find DataSchemaNode from specified Module and Queue of QNames through the Schema
+     * Context. The QNamed path could be defined across multiple modules in Schema Context so the method is called
+     * recursively. If the QNamed path contains QNames that are not part of any Module or Schema Context Path the
+     * operation will fail and returns <code>null</code>
+     * <br>
+     * If Schema Context, Module or Queue of QNames refers to <code>null</code> values,
+     * the method will throws IllegalArgumentException
+     *
+     * @throws IllegalArgumentException
+     *
+     * @param context Schema Context
+     * @param module Yang Module
+     * @param qnamedPath Queue of QNames
+     * @return DataSchemaNode if is present in Module(s) for specified Schema Context and given QNamed Path,
+     * otherwise will return <code>null</code>.
+     */
     private static DataSchemaNode findSchemaNodeForGivenPath(final SchemaContext context, final Module module,
             final Queue<QName> qnamedPath) {
-        if ((module != null) && (module.getNamespace() != null) && (qnamedPath != null)) {
-            DataNodeContainer nextNode = module;
-            final URI moduleNamespace = module.getNamespace();
-
-            QName childNodeQName;
-            DataSchemaNode schemaNode = null;
-            while ((nextNode != null) && !qnamedPath.isEmpty()) {
-                childNodeQName = qnamedPath.peek();
-                if (childNodeQName != null) {
-                    final URI childNodeNamespace = childNodeQName.getNamespace();
-
-                    schemaNode = nextNode.getDataChildByName(childNodeQName);
-                    if (schemaNode != null) {
-                        if (schemaNode instanceof ContainerSchemaNode) {
-                            nextNode = (ContainerSchemaNode) schemaNode;
-                        } else if (schemaNode instanceof ListSchemaNode) {
-                            nextNode = (ListSchemaNode) schemaNode;
-                        } else if (schemaNode instanceof ChoiceNode) {
-                            final ChoiceNode choice = (ChoiceNode) schemaNode;
-                            qnamedPath.poll();
-                            if (!qnamedPath.isEmpty()) {
-                                childNodeQName = qnamedPath.peek();
-                                nextNode = choice.getCaseNodeByName(childNodeQName);
-                                schemaNode = (DataSchemaNode)nextNode;
-                            }
-                        } else {
-                            nextNode = null;
+        if (context == null) {
+            throw new IllegalArgumentException("Schema Context reference cannot be NULL!");
+        }
+        if (module == null) {
+            throw new IllegalArgumentException("Module reference cannot be NULL!");
+        }
+        if (module.getNamespace() == null) {
+            throw new IllegalArgumentException("Namespace for Module cannot contains NULL reference!");
+        }
+        if (qnamedPath == null || qnamedPath.isEmpty()) {
+            throw new IllegalStateException("Schema Path contains invalid state of path parts."
+                    + "The Schema Path MUST contain at least ONE QName which defines namespace and Local name"
+                    + "of path.");
+        }
+
+        DataNodeContainer nextNode = module;
+        final URI moduleNamespace = module.getNamespace();
+
+        QName childNodeQName;
+        DataSchemaNode schemaNode = null;
+        while ((nextNode != null) && !qnamedPath.isEmpty()) {
+            childNodeQName = qnamedPath.peek();
+            if (childNodeQName != null) {
+                final URI childNodeNamespace = childNodeQName.getNamespace();
+
+                schemaNode = nextNode.getDataChildByName(childNodeQName);
+                if (schemaNode != null) {
+                    if (schemaNode instanceof ContainerSchemaNode) {
+                        nextNode = (ContainerSchemaNode) schemaNode;
+                    } else if (schemaNode instanceof ListSchemaNode) {
+                        nextNode = (ListSchemaNode) schemaNode;
+                    } else if (schemaNode instanceof ChoiceNode) {
+                        final ChoiceNode choice = (ChoiceNode) schemaNode;
+                        qnamedPath.poll();
+                        if (!qnamedPath.isEmpty()) {
+                            childNodeQName = qnamedPath.peek();
+                            nextNode = choice.getCaseNodeByName(childNodeQName);
+                            schemaNode = (DataSchemaNode) nextNode;
                         }
-                    } else if (!childNodeNamespace.equals(moduleNamespace)) {
-                        final Module nextModule = context.findModuleByNamespace(childNodeNamespace);
-                        schemaNode = findSchemaNodeForGivenPath(context, nextModule, qnamedPath);
-                        return schemaNode;
+                    } else {
+                        nextNode = null;
                     }
-                    qnamedPath.poll();
+                } else if (!childNodeNamespace.equals(moduleNamespace)) {
+                    final Module nextModule = context.findModuleByNamespace(childNodeNamespace);
+                    schemaNode = findSchemaNodeForGivenPath(context, nextModule, qnamedPath);
+                    return schemaNode;
                 }
+                qnamedPath.poll();
             }
-            return schemaNode;
         }
-        return null;
+        return schemaNode;
     }
 
+    /**
+     * Transforms string representation of XPath to Queue of QNames. The XPath is split by "/" and for each part of
+     * XPath is assigned correct module in Schema Path.
+     * <br>
+     * If Schema Context, Parent Module or XPath string contains <code>null</code> values,
+     * the method will throws IllegalArgumentException
+     *
+     * @throws IllegalArgumentException
+     *
+     * @param context Schema Context
+     * @param parentModule Parent Module
+     * @param xpath XPath String
+     * @return
+     */
     private static Queue<QName> xpathToQNamePath(final SchemaContext context, final Module parentModule,
             final String xpath) {
-        final Queue<QName> path = new LinkedList<>();
-        if (xpath != null) {
-            final String[] prefixedPath = xpath.split("/");
+        if (context == null) {
+            throw new IllegalArgumentException("Schema Context reference cannot be NULL!");
+        }
+        if (parentModule == null) {
+            throw new IllegalArgumentException("Parent Module reference cannot be NULL!");
+        }
+        if (xpath == null) {
+            throw new IllegalArgumentException("XPath string reference cannot be NULL!");
+        }
 
-            for (int i = 0; i < prefixedPath.length; ++i) {
-                if (!prefixedPath[i].isEmpty()) {
-                    path.add(stringPathPartToQName(context, parentModule, prefixedPath[i]));
-                }
+        final Queue<QName> path = new LinkedList<>();
+        final String[] prefixedPath = xpath.split("/");
+        for (int i = 0; i < prefixedPath.length; ++i) {
+            if (!prefixedPath[i].isEmpty()) {
+                path.add(stringPathPartToQName(context, parentModule, prefixedPath[i]));
             }
         }
         return path;
     }
 
+    /**
+     * Transforms part of Prefixed Path as java String to QName.
+     * <br>
+     * If the string contains module prefix separated by ":" (i.e. mod:container) this module is provided from from
+     * Parent Module list of imports. If the Prefixed module is present in Schema Context the QName can be
+     * constructed.
+     * <br>
+     * If the Prefixed Path Part does not contains prefix the Parent's Module namespace is taken for construction of
+     * QName.
+     * <br>
+     * If Schema Context, Parent Module or Prefixed Path Part refers to <code>null</code> the method will throw
+     * IllegalArgumentException
+     *
+     * @throws IllegalArgumentException
+     *
+     * @param context Schema Context
+     * @param parentModule Parent Module
+     * @param prefixedPathPart Prefixed Path Part string
+     * @return QName from prefixed Path Part String.
+     */
     private static QName stringPathPartToQName(final SchemaContext context, final Module parentModule,
             final String prefixedPathPart) {
-        if (parentModule != null && prefixedPathPart != null) {
-            if (prefixedPathPart.contains(":")) {
-                final String[] prefixedName = prefixedPathPart.split(":");
-                final Module module = resolveModuleForPrefix(context, parentModule, prefixedName[0]);
-                if (module != null) {
-                    return new QName(module.getNamespace(), module.getRevision(), prefixedName[1]);
-                }
-            } else {
-                return new QName(parentModule.getNamespace(), parentModule.getRevision(), prefixedPathPart);
+        if (context == null) {
+            throw new IllegalArgumentException("Schema Context reference cannot be NULL!");
+        }
+        if (parentModule == null) {
+            throw new IllegalArgumentException("Parent Module reference cannot be NULL!");
+        }
+        if (prefixedPathPart == null) {
+            throw new IllegalArgumentException("Prefixed Path Part cannot be NULL!");
+        }
+
+        if (prefixedPathPart.contains(":")) {
+            final String[] prefixedName = prefixedPathPart.split(":");
+            final Module module = resolveModuleForPrefix(context, parentModule, prefixedName[0]);
+            if (module != null) {
+                return new QName(module.getNamespace(), module.getRevision(), prefixedName[1]);
             }
+        } else {
+            return new QName(parentModule.getNamespace(), parentModule.getRevision(), prefixedPathPart);
         }
         return null;
     }
 
+    /**
+     * Method will attempt to resolve and provide Module reference for specified module prefix. Each Yang module
+     * could contains multiple imports which MUST be associated with corresponding module prefix. The method simply
+     * looks into module imports and returns the module that is bounded with specified prefix. If the prefix is not
+     * present in module or the prefixed module is not present in specified Schema Context,
+     * the method will return <code>null</code>.
+     * <br>
+     * If String prefix is the same as prefix of the specified Module the reference to this module is returned.
+     * <br>
+     * If Schema Context, Module or Prefix are referring to <code>null</code> the method will return
+     * IllegalArgumentException
+     *
+     * @throws IllegalArgumentException
+     *
+     * @param context Schema Context
+     * @param module Yang Module
+     * @param prefix Module Prefix
+     * @return Module for given prefix in specified Schema Context if is present, otherwise returns <code>null</code>
+     */
     private static Module resolveModuleForPrefix(final SchemaContext context, final Module module, final String prefix) {
-        if ((module != null) && (prefix != null)) {
-            if (prefix.equals(module.getPrefix())) {
-                return module;
-            }
+        if (context == null) {
+            throw new IllegalArgumentException("Schema Context reference cannot be NULL!");
+        }
+        if (module == null) {
+            throw new IllegalArgumentException("Module reference cannot be NULL!");
+        }
+        if (prefix == null) {
+            throw new IllegalArgumentException("Prefix string cannot be NULL!");
+        }
 
-            final Set<ModuleImport> imports = module.getImports();
+        if (prefix.equals(module.getPrefix())) {
+            return module;
+        }
 
-            for (final ModuleImport mi : imports) {
-                if (prefix.equals(mi.getPrefix())) {
-                    return context.findModuleByName(mi.getModuleName(), mi.getRevision());
-                }
+        final Set<ModuleImport> imports = module.getImports();
+        for (final ModuleImport mi : imports) {
+            if (prefix.equals(mi.getPrefix())) {
+                return context.findModuleByName(mi.getModuleName(), mi.getRevision());
             }
         }
         return null;
     }
 
+    /**
+     * @throws IllegalArgumentException
+     *
+     * @param context Schema Context
+     * @param module Yang Module
+     * @param relativeXPath Non conditional Revision Aware Relative XPath
+     * @param leafrefSchemaPath Schema Path for Leafref
+     * @return
+     */
     private static Queue<QName> resolveRelativeXPath(final SchemaContext context, final Module module,
             final RevisionAwareXPath relativeXPath, final SchemaPath leafrefSchemaPath) {
         final Queue<QName> absolutePath = new LinkedList<>();
+        if (context == null) {
+            throw new IllegalArgumentException("Schema Context reference cannot be NULL!");
+        }
+        if (module == null) {
+            throw new IllegalArgumentException("Module reference cannot be NULL!");
+        }
+        if (relativeXPath == null) {
+            throw new IllegalArgumentException("Non Conditional Revision Aware XPath cannot be NULL!");
+        }
+        if (relativeXPath.isAbsolute()) {
+            throw new IllegalArgumentException("Revision Aware XPath MUST be relative i.e. MUST contains ../, "
+                    + "for non relative Revision Aware XPath use findDataSchemaNode method!");
+        }
+        if (leafrefSchemaPath == null) {
+            throw new IllegalArgumentException("Schema Path reference for Leafref cannot be NULL!");
+        }
 
-        if ((module != null) && (relativeXPath != null) && !relativeXPath.isAbsolute() && (leafrefSchemaPath != null)) {
-            final String strXPath = relativeXPath.toString();
-            if (strXPath != null) {
-                final String[] xpaths = strXPath.split("/");
-
-                if (xpaths != null) {
-                    int colCount = 0;
-                    while (xpaths[colCount].contains("..")) {
-                        ++colCount;
+        final String strXPath = relativeXPath.toString();
+        if (strXPath != null) {
+            final String[] xpaths = strXPath.split("/");
+            if (xpaths != null) {
+                int colCount = 0;
+                while (xpaths[colCount].contains("..")) {
+                    ++colCount;
+                }
+                final List<QName> path = leafrefSchemaPath.getPath();
+                if (path != null) {
+                    int lenght = path.size() - colCount - 1;
+                    for (int i = 0; i < lenght; ++i) {
+                        absolutePath.add(path.get(i));
                     }
-                    final List<QName> path = leafrefSchemaPath.getPath();
-                    if (path != null) {
-                        int lenght = path.size() - colCount - 1;
-                        for (int i = 0; i < lenght; ++i) {
-                            absolutePath.add(path.get(i));
-                        }
-                        for (int i = colCount; i < xpaths.length; ++i) {
-                            absolutePath.add(stringPathPartToQName(context, module, xpaths[i]));
-                        }
+                    for (int i = colCount; i < xpaths.length; ++i) {
+                        absolutePath.add(stringPathPartToQName(context, module, xpaths[i]));
                     }
                 }
             }