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());
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
@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;
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 {
}
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);
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());
}
}
}
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
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);
}
}
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);
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
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="
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;
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;
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;
* @author readams
*/
public class DeviceManagerImpl implements IDeviceService, IEntityClassListener,
- IListenDataPacket, ITopologyManagerAware, IfIptoHost {
+ IListenDataPacket, ITopologyManagerAware, IfIptoHost,
+ IInventoryListener {
protected static Logger logger = LoggerFactory
.getLogger(DeviceManagerImpl.class);
*/
protected ConcurrentHashMap<Long, Device> deviceMap;
+ protected ConcurrentHashMap<NodeConnector, Entity> inactiveStaticDevices;
/**
* Counter used to generate device keys
*/
/**
* 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
*/
// 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);
}
secondaryIndexMap = new HashMap<EnumSet<DeviceField>, DeviceIndex>();
deviceMap = new ConcurrentHashMap<Long, Device>();
+ inactiveStaticDevices = new ConcurrentHashMap<NodeConnector, Entity>();
classStateMap = new ConcurrentHashMap<String, ClassState>();
apComparator = new AttachmentPointComparator();
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;
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);
} catch (ConstructionException ce) {
p = null;
h = null;
- } catch (UnknownHostException ue){
+ } catch (UnknownHostException ue) {
p = null;
h = null;
}
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:
}
}
}
}
+
/**
- * 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 -
return mac;
}
- /**
+ /**
* Accepts an IPv4 address in a byte array and returns the corresponding
* 32-bit integer value.
*
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;
@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);
}
}
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
*/
-
/*
* Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
*
* 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.
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;
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;
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;
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;
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;
}
}
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;
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;
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;
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) {
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();
}
}
/**
- * 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 {
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")) {
}
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")) {
}
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]));
}
/*
- * 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);
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
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) {
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
}
}
}
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)) {
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;
}
}
+ HexEncode.bytesToHexStringFormat(dataLayerSourceMask)
+ ", dataLayerDestinationMask="
+ HexEncode.bytesToHexStringFormat(dataLayerDestinationMask)
- + ", dataLayerVirtualLanMask=" + dataLayerVirtualLanMask
- + ", dataLayerVirtualLanPriorityCodePointMask="
- + dataLayerVirtualLanPriorityCodePointMask
+ + ", dataLayerVirtualLanTCIMask=" + dataLayerVirtualLanTCIMask
+ ", dataLayerTypeMask=" + dataLayerTypeMask
+ ", networkTypeOfServiceMask=" + networkTypeOfServiceMask
+ ", networkProtocolMask=" + networkProtocolMask
+ ", dstIPv6SubnetMaskbits=" + dstIPv6SubnetMaskbits
+ ", inputPortState=" + inputPortState + ", dlSourceState="
+ dlSourceState + ", dlDestState=" + dlDestState
- + ", dlVlanState=" + dlVlanState + ", ethTypeState="
+ + ", dlVlanTCIState=" + dlVlanTCIState + ", ethTypeState="
+ ethTypeState + ", nwTosState=" + nwTosState
+ ", nwProtoState=" + nwProtoState + ", nwSrcState="
+ nwSrcState + ", nwDstState=" + nwDstState + ", tpSrcState="
/**
* 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
/*
* 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;
}
/*
// 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 {
}
}
- 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) {
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;
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;
}
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 {
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");
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
/.settings
+/binding-java-api-generator/src/main/xtend-gen
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);
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;
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);
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)) {
gtTunnel = (GeneratedType) type;
} else if ("TunnelKey".equals(name)) {
gtTunnelKey = (GeneratedTransferObject) type;
+ } else if ("Topology".equals(name)) {
+ gtTopology = (GeneratedType) type;
}
}
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();
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();
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();
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();
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();
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();
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();
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
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()) {
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();
}
}
- 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()) {
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
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()) {
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();
}
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()) {
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();
}
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
assertNotNull(genTypes);
assertEquals(6, genTypes.size());
- int genTypesCount = 0;
- int genTOsCount = 0;
-
int listParentContainerMethodsCount = 0;
int simpleListMethodsCount = 0;
int listChildContainerMethodsCount = 0;
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();
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();
module demo-topology {
yang-version 1;
- namespace "";
+ namespace "urn:model.1demo-275topology.4.5.my";
prefix "tp";
organization "OPEN DAYLIGHT";
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";
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(".");
<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
--- /dev/null
+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;
+ }
+
+}
--- /dev/null
+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;
+ }
+
+}
--- /dev/null
+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»'''
+
+}
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 = " ";
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;
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,
this.interfaceGenerator = new InterfaceGenerator();
this.classGenerator = new ClassCodeGenerator();
this.enumGenerator = new EnumGenerator();
+ this.builderGenerator = new BuilderGenerator();
this.genTypes = types;
this.genTransferObjects = genTransferObjects;
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);
}
for (Enumeration enumeration : enumerations) {
- final File genFile = generateTypeToJavaFile(parentDirectory, enumeration, enumGenerator);
+ final File genFile = generateTypeToJavaFile(parentDirectory, enumeration, enumGenerator, "");
if (genFile != null) {
result.add(genFile);
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 "
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();
+ "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
+++ /dev/null
-<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
+++ /dev/null
-/*
- * 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());
- }
-}
+++ /dev/null
-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;
- }
- }
- }
-
-}
+++ /dev/null
-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";
-// }
-
-}
+++ /dev/null
-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.";
- }
-
-}
+++ /dev/null
-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";
- }
-
-}
augment "/cn:network/cn:network-elements/cn:network-element" {
- container flow-tables {
+ container flow-tables2 {
list flow-table {
key "id";
-// 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 "
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 {
";
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
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;
+ }
}
}
}
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
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!");
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]));
}
}
}