logger.info("Starting the ClusterManager");
try {
//FIXME keeps throwing FileNotFoundException
- this.cm = new DefaultCacheManager("/config/infinispan-config.xml");
+ this.cm = new DefaultCacheManager("config/infinispan-config.xml");
logger.debug("Allocated ClusterManager");
if (this.cm != null) {
this.cm.start();
<global>
<transport>
<properties>
- <property name="configurationFile" value="/config/jgroups.xml"/>
+ <property name="configurationFile" value="config/jgroups.xml"/>
</properties>
</transport>
<!-- Enable JMX statistics -->
--- /dev/null
+package org.opendaylight.controller.clustering.services_implementation.internal;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.net.InetAddress;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Properties;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+import org.infinispan.CacheImpl;
+import org.junit.Assert;
+import org.junit.Test;
+import org.opendaylight.controller.clustering.services.CacheConfigException;
+import org.opendaylight.controller.clustering.services.CacheExistException;
+import org.opendaylight.controller.clustering.services.IClusterServices;
+import org.opendaylight.controller.clustering.services.IClusterServices.cacheMode;
+
+public class ClusterManagerTest {
+
+ @Test
+ public void NoManagerSetTest() throws CacheExistException,
+ CacheConfigException {
+ ClusterManager cm = new ClusterManager();
+ CacheImpl<String, Integer> c1 = null;
+ CacheImpl<String, Integer> c2 = null;
+ Assert.assertNull(cm.createCache("Container", "Cache", null));
+ Assert.assertNull(cm.getCacheProperties("Container", "Cache"));
+ Assert.assertNull(cm.getCache("Container", "Cache"));
+ Assert.assertFalse(cm.existCache("Container", "Cache"));
+ Assert.assertNull(cm.getCacheList("Container"));
+ Assert.assertTrue(cm.amIStandby());
+ Assert.assertNull(cm.getActiveAddress());
+ Assert.assertNull(cm.getMyAddress());
+ Assert.assertNull(cm.getClusteredControllers());
+ }
+
+ @Test
+ public void WithManagerTest() throws CacheExistException,
+ CacheConfigException {
+
+ ClusterManager cm = new ClusterManager();
+ CacheImpl<String, Integer> c1 = null;
+ CacheImpl<String, Integer> c2 = null;
+
+ cm.start();
+
+ // Check no cache created yet
+ assertFalse(cm.existCache("NonExistantContainerName",
+ "NonExistantCacheName"));
+
+ // Create cache with no cacheMode set, expecting it to fail
+ HashSet<cacheMode> cacheModeSet = new HashSet<cacheMode>();
+ Assert.assertNull(cm.createCache("Container1", "Cache1", cacheModeSet));
+
+ // Create first cache as transactional
+ cacheModeSet.add(cacheMode.TRANSACTIONAL);
+ try {
+ c1 = (CacheImpl<String, Integer>) cm.createCache("Container1",
+ "Cache1", cacheModeSet);
+ } catch (CacheExistException cee) {
+ Assert.assertTrue(false);
+ } catch (CacheConfigException cce) {
+ Assert.assertTrue(false);
+ }
+
+ // Try creating exact same cache again
+ try {
+ c1 = (CacheImpl<String, Integer>) cm.createCache("Container1",
+ "Cache1", cacheModeSet);
+ } catch (CacheExistException cee) {
+ Assert.assertTrue(true);
+ } catch (CacheConfigException cce) {
+ Assert.assertTrue(false);
+ }
+
+ // Create second cache with both types of cacheMode, expecting it to
+ // complain
+ cacheModeSet.add(cacheMode.NON_TRANSACTIONAL);
+ try {
+ c2 = (CacheImpl<String, Integer>) cm.createCache("Container1",
+ "Cache2", cacheModeSet);
+ } catch (CacheExistException cee) {
+ Assert.assertTrue(false);
+ } catch (CacheConfigException cce) {
+ Assert.assertTrue(true);
+ }
+
+ // Create second cache properly this time, as non_transactional
+ cacheModeSet.remove(cacheMode.TRANSACTIONAL);
+ try {
+ c2 = (CacheImpl<String, Integer>) cm.createCache("Container1",
+ "Cache2", cacheModeSet);
+ } catch (CacheExistException cee) {
+ Assert.assertTrue(false);
+ } catch (CacheConfigException cce) {
+ Assert.assertTrue(false);
+ }
+
+ // Make sure correct caches exists
+ Assert.assertTrue(cm.existCache("Container1", "Cache1"));
+ c1 = (CacheImpl<String, Integer>) cm.getCache("Container1", "Cache1");
+ Assert.assertTrue(c1 != null);
+
+ Assert.assertTrue(cm.existCache("Container1", "Cache2"));
+ c2 = (CacheImpl<String, Integer>) cm.getCache("Container1", "Cache2");
+ Assert.assertTrue(c2 != null);
+
+ Assert.assertNull(cm.getCache("Container1", "Cache3"));
+
+ // Get CacheList
+ HashSet<String> cacheList = (HashSet<String>) cm
+ .getCacheList("Container2");
+ Assert.assertEquals(0, cacheList.size());
+
+ cacheList = (HashSet<String>) cm.getCacheList("Container1");
+ Assert.assertEquals(2, cacheList.size());
+ Assert.assertTrue(cacheList.contains("Cache1"));
+ Assert.assertTrue(cacheList.contains("Cache2"));
+
+ // Get CacheProperties
+ Assert.assertNull(cm.getCacheProperties("Container1", ""));
+ Properties p = cm.getCacheProperties("Container1", "Cache1");
+ Assert.assertEquals(3, p.size());
+ Assert.assertNotNull(p
+ .getProperty(IClusterServices.cacheProps.TRANSACTION_PROP
+ .toString()));
+ Assert.assertNotNull(p
+ .getProperty(IClusterServices.cacheProps.CLUSTERING_PROP
+ .toString()));
+ Assert.assertNotNull(p
+ .getProperty(IClusterServices.cacheProps.LOCKING_PROP
+ .toString()));
+
+ // Destroy cache1 and make sure it's gone
+ cm.destroyCache("Container1", "Cache1");
+ cm.destroyCache("Container1", "Cache3");
+ Assert.assertFalse(cm.existCache("Container1", "Cache1"));
+ Assert.assertTrue(cm.existCache("Container1", "Cache2"));
+
+ // Check amIStandBy()
+ boolean standby = cm.amIStandby();
+ Assert.assertFalse(standby);
+
+ // Check addresses, which are all loopback
+ InetAddress activeAddress = cm.getActiveAddress();
+ Assert.assertEquals("/127.0.0.1", activeAddress.toString());
+ InetAddress myAddress = cm.getMyAddress();
+ Assert.assertEquals("/127.0.0.1", myAddress.toString());
+
+ List<InetAddress> cc = cm.getClusteredControllers();
+ Assert.assertEquals(0, cc.size());
+
+ cm.stop();
+ }
+
+}
private FlowEntry original;
private ContainerFlow cFlow;
private FlowEntry install;
+ transient private long requestId; // async request id
transient private boolean deletePending;
public FlowEntryInstall(FlowEntry original, ContainerFlow cFlow) {
this.install = (cFlow == null) ? original.clone() : original
.mergeWith(cFlow);
deletePending = false;
+ requestId = 0;
}
@Override
this.deletePending = true;
}
+ public void setRequestId(long rid) {
+ this.requestId = rid;
+ }
+
+ public long getRequestId() {
+ return requestId;
+ }
+
@Override
public String toString() {
- return "[Install = " + install + " Original: " + original + " cFlow: "
- + cFlow + "]";
+ return "[Install = " + install + " Original = " + original + " cFlow = "
+ + cFlow + " rid = " + requestId + "]";
}
}
* not valid an error code is returned. If the existing flow is equal to the
* passed one it will be a no op and success code is returned.
*
+ *
* @param newone
* the new flow entry to install
* @return the {@code Status} object indicating the result of this action
*/
public Status modifyOrAddFlowEntry(FlowEntry newone);
+ /**
+ * It requests FRM to install the passed Flow Entry through an asynchronous
+ * call. A unique request id is returned to the caller. FRM will request the
+ * SDN protocol plugin to install the flow on the network node. As immediate
+ * result of this asynchronous call, FRM will update its flow database as if
+ * the flow was successfully installed.
+ *
+ * @param flow
+ * the flow entry to install
+ * @return the status of this request containing the request id associated
+ * to this asynchronous request
+ */
+ public Status installFlowEntryAsync(FlowEntry flow);
+
+ /**
+ * It requests FRM to remove the passed Flow Entry through an asynchronous
+ * call. A unique request id is returned to the caller. FRM will request the
+ * SDN protocol plugin to uninstall the flow from the network node. As
+ * immediate result of this asynchronous call, FRM will update its flow
+ * database as if the flow was successfully installed.
+ *
+ * @param flow
+ * the flow entry to uninstall
+ * @return the status of this request containing the unique id associated to
+ * this asynchronous request
+ */
+ public Status uninstallFlowEntryAsync(FlowEntry flow);
+
+ /**
+ * It requests FRM to replace the currently installed Flow Entry with the
+ * new one through an asynchronous call. A unique request id is returned to
+ * the caller. It is up to the SDN protocol plugin to decide how to convey
+ * this message to the network node. It could be a delete + add or a single
+ * modify message depending on the SDN protocol specifications. If the
+ * current flow is equal to the new one it will be a no op.
+ *
+ * @param current
+ * the current flow entry to modify
+ * @param newone
+ * the new flow entry which will replace the current one
+ * @return the status of this request containing the request id associated
+ * to this asynchronous request
+ */
+ public Status modifyFlowEntryAsync(FlowEntry current, FlowEntry newone);
+
+ /**
+ * It requests the FRM to replace the currently installed Flow Entry with
+ * the new one through an asynchronous call. A unique request id is returned
+ * to the caller. The currently installed entry is derived by the Match
+ * portion of the passed Flow. FRM looks in its database for a previously
+ * installed FlowEntry which Match equals the Match of the passed Flow. If
+ * it finds it, it will request the SDN protocol plugin to replace the
+ * existing flow with the new one on the network node. If it does not find
+ * it, it will request plugin to add the new flow. If the passed entry is
+ * not valid a zero request id is returned. If the existing flow is equal to
+ * the passed one it will be a no op.
+ *
+ * @param newone
+ * the new flow entry to install
+ * @return the unique id associated to this request. In case of not
+ * acceptable request -1 will be returned.
+ */
+ public Status modifyOrAddFlowEntryAsync(FlowEntry newone);
+
+ /**
+ * Requests ForwardingRulesManager to solicit the network node to inform
+ * us about the status of his execution on the asynchronous requests that
+ * were sent to it so far. It is a way for an application to poke the
+ * network node in order to get a feedback asap on the asynchronous
+ * requests generated by the application. It is a non-blocking call
+ * and does not guarantee the node will respond in any given time.
+ *
+ * @param node
+ * The network node to solicit a response
+ */
+ public void solicitStatusResponse(Node node);
+
/**
* Check whether the passed flow entry conflicts with the Container flows
*
* @param name
* the flow name
* @param n
- * the netwrok node identifier
+ * the network node identifier
* @return the {@code FlowConfig} object
*/
public FlowConfig getStaticFlow(String name, Node n);
* otherwise
*/
public void policyUpdate(String policyName, boolean add);
+
+ /**
+ * Inform listeners that the network node has notified us about a failure in
+ * executing the controller generated asynchronous request identified by the
+ * passed unique id.
+ *
+ * @param requestId
+ * the unique id associated with the request which failed to be
+ * executed on the network node
+ * @param error
+ * the string describing the error reported by the network node
+ */
+ public void requestFailed(long requestId, String error);
+
}
*
* @param flowEntry
* the original flow entry application requested to add
- * @return
+ * @param async
+ * the flag indicating if this is a asynchronous request
+ * @return the status of this request. In case of asynchronous call, it
+ * will contain the unique id assigned to this request
*/
- private Status addEntry(FlowEntry flowEntry) {
+ private Status addEntry(FlowEntry flowEntry, boolean async) {
+
// Sanity Check
if (flowEntry == null || flowEntry.getNode() == null) {
String msg = "Invalid FlowEntry";
// Try to install an entry at the time
Status error = new Status(null, null);
+ Status succeded = null;
boolean oneSucceded = false;
- for (FlowEntryInstall installEntry : toInstallList) {
+ for (FlowEntryInstall installEntry : toInstallSafe) {
// Install and update database
- Status ret = addEntriesInternal(installEntry);
+ Status ret = addEntriesInternal(installEntry, async);
if (ret.isSuccess()) {
oneSucceded = true;
+ /*
+ * The first successful status response will be returned
+ * For the asynchronous call, we can discard the container flow
+ * complication for now and assume we will always deal with
+ * one flow only per request
+ */
+ succeded = ret;
} else {
error = ret;
log.warn("Failed to install the entry: {}. The failure is: {}",
}
}
- return (oneSucceded) ? new Status(StatusCode.SUCCESS, null) : error;
+ return (oneSucceded) ? succeded : error;
}
/**
*
* @param currentFlowEntry
* @param newFlowEntry
- * @return Success or error string
+ * @param async
+ * the flag indicating if this is a asynchronous request
+ * @return the status of this request. In case of asynchronous call, it
+ * will contain the unique id assigned to this request
*/
private Status modifyEntry(FlowEntry currentFlowEntry,
- FlowEntry newFlowEntry) {
+ FlowEntry newFlowEntry, boolean async) {
+
Status retExt;
// Sanity checks
* So, for the above two cases, to simplify, let's decouple the modify
* in: 1) remove current entries 2) install new entries
*/
+ Status succeeded = null;
boolean decouple = false;
if (installedList.size() != toInstallList.size()) {
log.info("Modify: New flow entry does not satisfy the same "
if (decouple) {
// Remove current entries
for (FlowEntryInstall currEntry : installedList) {
- this.removeEntryInternal(currEntry);
+ this.removeEntryInternal(currEntry, async);
}
// Install new entries
for (FlowEntryInstall newEntry : toInstallSafe) {
- this.addEntriesInternal(newEntry);
+ succeeded = this.addEntriesInternal(newEntry, async);
}
} else {
/*
* fails, we need to stop, restore the already modified entries, and
* declare failure.
*/
- Status retModify;
+ Status retModify = null;
int i = 0;
int size = toInstallList.size();
while (i < size) {
// Modify and update database
retModify = modifyEntryInternal(installedList.get(i),
- toInstallList.get(i));
+ toInstallList.get(i), async);
if (retModify.isSuccess()) {
i++;
} else {
while (j < i) {
log.info("Attempting to restore initial entries");
retExt = modifyEntryInternal(toInstallList.get(i),
- installedList.get(i));
+ installedList.get(i), async);
if (retExt.isSuccess()) {
j++;
} else {
return new Status(StatusCode.INTERNALERROR, msg);
}
}
+ succeeded = retModify;
}
- return new Status(StatusCode.SUCCESS, null);
+ /*
+ * The first successful status response will be returned.
+ * For the asynchronous call, we can discard the container flow
+ * complication for now and assume we will always deal with
+ * one flow only per request
+ */
+ return succeeded;
}
/**
*
* @param currentEntries
* @param newEntries
- * @return
+ * @param async
+ * the flag indicating if this is a asynchronous request
+ * @return the status of this request. In case of asynchronous call, it
+ * will contain the unique id assigned to this request
*/
private Status modifyEntryInternal(FlowEntryInstall currentEntries,
- FlowEntryInstall newEntries) {
+ FlowEntryInstall newEntries, boolean async) {
// Modify the flow on the network node
- Status status = programmer.modifyFlow(currentEntries.getNode(),
- currentEntries.getInstall().getFlow(), newEntries.getInstall()
- .getFlow());
+ Status status = (async)?
+ programmer.modifyFlowAsync(currentEntries.getNode(),
+ currentEntries.getInstall().getFlow(), newEntries.getInstall()
+ .getFlow()) :
+ programmer.modifyFlow(currentEntries.getNode(),
+ currentEntries.getInstall().getFlow(), newEntries.getInstall()
+ .getFlow());
+
if (!status.isSuccess()) {
log.warn(
newEntries.getInstall());
// Update DB
+ newEntries.setRequestId(status.getRequestId());
updateLocalDatabase(currentEntries, false);
updateLocalDatabase(newEntries, true);
* (entry or node not present), it return successfully
*
* @param flowEntry
- * @return
+ * the flow entry to remove
+ * @param async
+ * the flag indicating if this is a asynchronous request
+ * @return the status of this request. In case of asynchronous call, it
+ * will contain the unique id assigned to this request
*/
- private Status removeEntry(FlowEntry flowEntry) {
+ private Status removeEntry(FlowEntry flowEntry, boolean async) {
Status error = new Status(null, null);
// Sanity Check
flowEntry.clone(), container.getContainerFlows());
Set<FlowEntryInstall> flowsOnNode = nodeFlows.get(flowEntry.getNode());
+ Status succeeded = null;
boolean atLeastOneRemoved = false;
for (FlowEntryInstall entry : installedList) {
if (flowsOnNode == null) {
log.debug(logMsg, flowEntry);
if (installedList.size() == 1) {
// If we had only one entry to remove, we are done
- return new Status(StatusCode.SUCCESS, null);
+ return new Status(StatusCode.SUCCESS);
} else {
continue;
}
}
// Remove and update DB
- Status ret = removeEntryInternal(entry);
+ Status ret = removeEntryInternal(entry, async);
if (!ret.isSuccess()) {
error = ret;
return error;
}
} else {
+ succeeded = ret;
atLeastOneRemoved = true;
}
}
* of removing the stale entries later, or adjusting the software
* database if not in sync with hardware
*/
- return (atLeastOneRemoved) ? new Status(StatusCode.SUCCESS, null)
- : error;
+ return (atLeastOneRemoved) ? succeeded : error;
}
/**
* validity checks are passed
*
* @param entry
- * the FlowEntryInstall
- * @return "Success" or error string
+ * the flow entry to remove
+ * @param async
+ * the flag indicating if this is a asynchronous request
+ * @return the status of this request. In case of asynchronous call, it
+ * will contain the unique id assigned to this request
*/
- private Status removeEntryInternal(FlowEntryInstall entry) {
+ private Status removeEntryInternal(FlowEntryInstall entry, boolean async) {
// Mark the entry to be deleted (for CC just in case we fail)
entry.toBeDeleted();
// Remove from node
- Status status = programmer.removeFlow(entry.getNode(), entry
- .getInstall().getFlow());
+ Status status = (async)?
+ programmer.removeFlowAsync(entry.getNode(), entry
+ .getInstall().getFlow()) :
+ programmer.removeFlow(entry.getNode(), entry
+ .getInstall().getFlow());
+
if (!status.isSuccess()) {
log.warn(
entry.getInstall(), status.getDescription());
return status;
}
- log.info("Removed {}", entry.getInstall());
+ log.trace("Removed {}", entry.getInstall());
// Update DB
updateLocalDatabase(entry, false);
* whether this flow would conflict or overwrite an existing one.
*
* @param entry
- * the FlowEntryInstall
- * @return "Success" or error string
+ * the flow entry to install
+ * @param async
+ * the flag indicating if this is a asynchronous request
+ * @return the status of this request. In case of asynchronous call, it
+ * will contain the unique id assigned to this request
*/
- private Status addEntriesInternal(FlowEntryInstall entry) {
+ private Status addEntriesInternal(FlowEntryInstall entry, boolean async) {
// Install the flow on the network node
- Status status = programmer.addFlow(entry.getNode(), entry.getInstall()
- .getFlow());
+ Status status = (async)?
+ programmer.addFlow(entry.getNode(), entry.getInstall()
+ .getFlow()) :
+ programmer.addFlowAsync(entry.getNode(), entry.getInstall()
+ .getFlow());
+
if (!status.isSuccess()) {
log.warn(
return status;
}
- log.info("Added {}", entry.getInstall());
+ log.trace("Added {}", entry.getInstall());
// Update DB
+ entry.setRequestId(status.getRequestId());
updateLocalDatabase(entry, true);
return status;
status = new Status(StatusCode.NOTACCEPTABLE, msg);
log.warn(logMsg, flowEntry);
} else {
- status = addEntry(flowEntry);
+ status = addEntry(flowEntry, false);
+ }
+ return status;
+ }
+
+ @Override
+ public Status installFlowEntryAsync(FlowEntry flowEntry) {
+ Status status;
+ if (inContainerMode) {
+ String msg = "Controller in container mode: Install Refused";
+ status = new Status(StatusCode.NOTACCEPTABLE, msg);
+ log.warn(msg);
+ } else {
+ status = addEntry(flowEntry, true);
}
return status;
}
status = new Status(StatusCode.NOTACCEPTABLE, msg);
log.warn(logMsg, entry);
} else {
- status = removeEntry(entry);
+ status = removeEntry(entry, false);
}
return status;
}
+ @Override
+ public Status uninstallFlowEntryAsync(FlowEntry flowEntry) {
+ Status status;
+ if (inContainerMode) {
+ String msg = "Controller in container mode: Uninstall Refused";
+ status = new Status(StatusCode.NOTACCEPTABLE, msg);
+ log.warn(msg);
+ } else {
+ status = removeEntry(flowEntry, true);
+ }
+ return status;
+ }
+
@Override
public Status modifyFlowEntry(FlowEntry currentFlowEntry,
FlowEntry newFlowEntry) {
status = new Status(StatusCode.NOTACCEPTABLE, msg);
log.warn(logMsg, newFlowEntry);
} else {
- status = modifyEntry(currentFlowEntry, newFlowEntry);
+ status = modifyEntry(currentFlowEntry, newFlowEntry, false);
+ }
+ return status;
+ }
+
+ @Override
+ public Status modifyFlowEntryAsync(FlowEntry current, FlowEntry newone) {
+ Status status = null;
+ if (inContainerMode) {
+ String msg = "Controller in container mode: Modify Refused";
+ status = new Status(StatusCode.NOTACCEPTABLE, msg);
+ log.warn(msg);
+ } else {
+ status = modifyEntry(current, newone, true);
}
return status;
}
}
}
+ @Override
+ public Status modifyOrAddFlowEntryAsync(FlowEntry newone) {
+ /*
+ * Run a loose check on the installed entries to decide whether to go
+ * with a add or modify method. A loose check means only check against
+ * the original flow entry requests and not against the installed flow
+ * entries which are the result of the original entry merged with the
+ * container flow(s) (if any). The modifyFlowEntry method in presence of
+ * conflicts with the Container flows (if any) would revert back to a
+ * delete + add pattern
+ */
+ FlowEntryInstall currentFlowEntries = findMatch(newone, true);
+
+ if (currentFlowEntries != null) {
+ return modifyFlowEntryAsync(currentFlowEntries.getOriginal(),
+ newone);
+ } else {
+ return installFlowEntry(newone);
+ }
+ }
+
+
/**
* Try to find in the database if a Flow with the same Match and priority of
* the passed one already exists for the specified network node. Flow,
// Remove the old couples. No validity checks to be run, use the
// internal remove
for (FlowEntryInstall oldCouple : oldCouples) {
- this.removeEntryInternal(oldCouple);
+ this.removeEntryInternal(oldCouple, false);
}
// Reinstall the original flow entries, via the regular path: new
// cFlow merge + validations
for (NodeConnector dstPort : portList) {
newFlowEntry.getFlow().addAction(new Output(dstPort));
}
- Status error = modifyEntry(currentFlowEntry, newFlowEntry);
+ Status error = modifyEntry(currentFlowEntry, newFlowEntry, false);
if (error.isSuccess()) {
log.info("Ports {} added to FlowEntry {}", portList,
flowName);
Action action = new Output(dstPort);
newFlowEntry.getFlow().removeAction(action);
}
- Status status = modifyEntry(currentFlowEntry, newFlowEntry);
+ Status status = modifyEntry(currentFlowEntry, newFlowEntry, false);
if (status.isSuccess()) {
log.info("Ports {} removed from FlowEntry {}", portList,
flowName);
newFlowEntry.getFlow().addAction(new Output(outPort));
// Modify on network node
- Status status = modifyEntry(currentFlowEntry, newFlowEntry);
+ Status status = modifyEntry(currentFlowEntry, newFlowEntry, false);
if (status.isSuccess()) {
log.info("Output port replaced with {} for flow {} on node {}",
// Program hw
if (config.installInHw()) {
FlowEntry entry = config.getFlowEntry();
- status = this.addEntry(entry);
+ status = this.addEntry(entry, false);
if (!status.isSuccess()) {
config.setStatus(status.getDescription());
if (!restore) {
portGroupChanged(pgconfig, existingData, true);
}
}
- return new Status(StatusCode.SUCCESS, null);
+ return new Status(StatusCode.SUCCESS);
}
private void addStaticFlowsToSwitch(Node node) {
if (config.installInHw()
&& !config.getStatus().equals(
StatusCode.SUCCESS.toString())) {
- Status status = this.addEntry(config.getFlowEntry());
+ Status status = this.addEntry(config.getFlowEntry(), false);
config.setStatus(status.getDescription());
}
}
for (Map.Entry<Integer, FlowConfig> entry : staticFlows.entrySet()) {
if (entry.getValue().isByNameAndNodeIdEqual(config)) {
// Program the network node
- Status status = this.removeEntry(config.getFlowEntry());
+ Status status = this.removeEntry(config.getFlowEntry(), false);
// Update configuration database if programming was successful
if (status.isSuccess()) {
staticFlows.remove(entry.getKey());
}
if (!entry.isPortGroupEnabled()) {
// Program the network node
- status = this.removeEntry(entry.getFlowEntry());
+ status = this.removeEntry(entry.getFlowEntry(), false);
}
// Update configuration database if programming was successful
if (status.isSuccess()) {
Status status = new Status(StatusCode.SUCCESS, "Saved in config");
if (oldFlowConfig.installInHw()) {
status = this.modifyEntry(oldFlowConfig.getFlowEntry(),
- newFlowConfig.getFlowEntry());
+ newFlowConfig.getFlowEntry(), false);
}
// Update configuration database if programming was successful
FlowConfig conf = entry.getValue();
if (conf.isByNameAndNodeIdEqual(config)) {
// Program the network node
- Status status = new Status(StatusCode.SUCCESS, null);
+ Status status = new Status(StatusCode.SUCCESS);
if (conf.installInHw()) {
- status = this.removeEntry(conf.getFlowEntry());
+ status = this.removeEntry(conf.getFlowEntry(), false);
} else {
- status = this.addEntry(conf.getFlowEntry());
+ status = this.addEntry(conf.getFlowEntry(), false);
}
if (!status.isSuccess()) {
conf.setStatus(status.getDescription());
// Now remove the entries
for (FlowEntry flowEntry : inactiveFlows) {
- Status status = this.removeEntry(flowEntry);
+ Status status = this.removeEntry(flowEntry, false);
if (!status.isSuccess()) {
- log.warn("Failed to remove entry: {}. The failure is: {}"
- + flowEntry, status.getDescription());
+ log.warn("Failed to remove entry: {}. The failure is: {}",
+ flowEntry, status.getDescription());
}
}
}
log.info("Reinstalling all inactive flows");
for (FlowEntry flowEntry : this.inactiveFlows) {
- Status status = this.addEntry(flowEntry);
+ Status status = this.addEntry(flowEntry, false);
if (!status.isSuccess()) {
- log.warn("Failed to install entry: {}. The failure is: {}"
- + flowEntry, status.getDescription());
+ log.warn("Failed to install entry: {}. The failure is: {}",
+ flowEntry, status.getDescription());
}
}
@Override
public void portGroupChanged(PortGroupConfig config,
Map<Node, PortGroup> data, boolean add) {
- log.info("PortGroup Changed for :" + config + " Data: " + portGroupData);
+ log.info("PortGroup Changed for: {} Data: {}", config, portGroupData);
Map<Node, PortGroup> existingData = portGroupData.get(config);
if (existingData != null) {
for (Map.Entry<Node, PortGroup> entry : data.entrySet()) {
@Override
public void flowErrorReported(Node node, long rid, Object err) {
- log.error("Got error {} for message rid {} from node {}", new Object[] {
- err, rid, node });
+ log.trace("Got error {} for message rid {} from node {}",
+ new Object[] {err, rid, node });
+ /*
+ * If this was for a flow install, remove the corresponding entry
+ * from the software view. If it was a Looking for the rid going through the
+ * software database.
+ * TODO: A more efficient rid <-> FlowEntryInstall mapping will
+ * have to be added in future
+ */
+ Set<FlowEntryInstall> entries = nodeFlows.get(node);
+ if (entries != null) {
+ FlowEntryInstall target = null;
+ for (FlowEntryInstall entry : entries) {
+ if (entry.getRequestId() == rid) {
+ target = entry;
+ break;
+ }
+ }
+ if (target != null) {
+ // This was a flow install, update database
+ this.updateLocalDatabase(target, false);
+ }
+ }
+
+ // Notify listeners
+ if (frmAware != null) {
+ synchronized (frmAware) {
+ for (IForwardingRulesManagerAware frma : frmAware) {
+ try {
+ frma.requestFailed(rid, err.toString());
+ } catch (Exception e) {
+ log.warn("Failed to notify {}", frma);
+ }
+ }
+ }
+ }
+ }
+
+ @Override
+ public void solicitStatusResponse(Node node) {
+ if (this.programmer != null) {
+ programmer.sendBarrierMessage(node);
+ }
}
+
}
import org.osgi.service.log.LogEntry;
import java.util.Enumeration;
import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleException;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.ServiceRegistration;
import org.osgi.framework.ServiceReference;
*/
Thread.setDefaultUncaughtExceptionHandler(new org.opendaylight.
controller.logging.bridge.internal.UncaughtExceptionHandler());
+
+ /*
+ * Install the Shutdown handler. This will intercept SIGTERM signal and
+ * close the system bundle. This allows for a graceful closing of OSGI
+ * framework.
+ */
+
+ Runtime.getRuntime().addShutdownHook(new shutdownHandler(context));
} else {
this.log.error("Cannot register the LogListener because "
+ "cannot retrieve LogReaderService");
this.listener = null;
this.log = null;
}
+
+ private class shutdownHandler extends Thread {
+ BundleContext bundlecontext;
+ public shutdownHandler(BundleContext ctxt) {
+ this.bundlecontext = ctxt;
+ }
+
+ public void run () {
+ try {
+ this.bundlecontext.getBundle(0).stop();
+ log.debug("shutdown handler thread called");
+ } catch (BundleException e) {
+ log.debug("Bundle couldn't be stopped");
+ }
+ }
+ }
+
}
-
/*
* Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
*
private AtomicInteger switchInstanceNumber;
/*
- * this thread monitors the switchEvents queue for new incoming events from switch
+ * this thread monitors the switchEvents queue for new incoming events from
+ * switch
*/
private class EventHandler implements Runnable {
@Override
SwitchEvent ev = switchEvents.take();
SwitchEvent.SwitchEventType eType = ev.getEventType();
ISwitch sw = ev.getSwitch();
- if (eType != SwitchEvent.SwitchEventType.SWITCH_MESSAGE) {
- //logger.debug("Received " + ev.toString() + " from " + sw.toString());
- }
switch (eType) {
case SWITCH_ADD:
Long sid = sw.getId();
ISwitch existingSwitch = switches.get(sid);
if (existingSwitch != null) {
- logger.info(" Replacing existing "
- + existingSwitch.toString() + " with New "
- + sw.toString());
+ logger.info("Replacing existing {} with New {}",
+ existingSwitch.toString(), sw.toString());
disconnectSwitch(existingSwitch);
}
switches.put(sid, sw);
}
break;
default:
- logger.error("unknow switch event " + eType.ordinal());
+ logger.error("Unknown switch event {}", eType.ordinal());
}
} catch (InterruptedException e) {
switchEvents.clear();
/**
* Function called by the dependency manager when all the required
* dependencies are satisfied
- *
+ *
*/
public void init() {
- logger.debug("OpenFlowCore init");
+ logger.debug("Initializing!");
this.switches = new ConcurrentHashMap<Long, ISwitch>();
this.switchEvents = new LinkedBlockingQueue<SwitchEvent>();
this.messageListeners = new ConcurrentHashMap<OFType, IMessageListener>();
}
/**
- * Function called by dependency manager after "init ()" is called
- * and after the services provided by the class are registered in
- * the service registry
- *
+ * Function called by dependency manager after "init ()" is called and after
+ * the services provided by the class are registered in the service registry
+ *
*/
public void start() {
- logger.debug("OpenFlowCore start() is called");
+ logger.debug("Starting!");
/*
* start a thread to handle event coming from the switch
*/
try {
controllerIO.start();
} catch (IOException ex) {
- logger.error("Caught exception: " + ex + " during start");
+ logger.error("Caught exception while starting:", ex);
}
}
-
+
/**
- * Function called by the dependency manager before the services
- * exported by the component are unregistered, this will be
- * followed by a "destroy ()" calls
- *
+ * Function called by the dependency manager before the services exported by
+ * the component are unregistered, this will be followed by a "destroy ()"
+ * calls
+ *
*/
public void stop() {
for (Iterator<Entry<Long, ISwitch>> it = switches.entrySet().iterator(); it
}
switchEventThread.interrupt();
try {
- controllerIO.shutDown();
+ controllerIO.shutDown();
} catch (IOException ex) {
- logger.error("Caught exception: " + ex + " during stop");
+ logger.error("Caught exception while stopping:", ex);
}
}
/**
- * Function called by the dependency manager when at least one
- * dependency become unsatisfied or when the component is shutting
- * down because for example bundle is being stopped.
- *
+ * Function called by the dependency manager when at least one dependency
+ * become unsatisfied or when the component is shutting down because for
+ * example bundle is being stopped.
+ *
*/
public void destroy() {
}
public void addMessageListener(OFType type, IMessageListener listener) {
IMessageListener currentListener = this.messageListeners.get(type);
if (currentListener != null) {
- logger.warn(type.toString() + " already listened by "
- + currentListener.toString());
+ logger.warn("{} is already listened by {}", type.toString(),
+ currentListener.toString());
}
this.messageListeners.put(type, listener);
- logger.debug(type.toString() + " is now listened by "
- + listener.toString());
+ logger.debug("{} is now listened by {}", type.toString(),
+ listener.toString());
}
@Override
public void removeMessageListener(OFType type, IMessageListener listener) {
IMessageListener currentListener = this.messageListeners.get(type);
if ((currentListener != null) && (currentListener == listener)) {
+ logger.debug("{} listener {} is Removed", type.toString(),
+ listener.toString());
this.messageListeners.remove(type);
}
}
@Override
public void addSwitchStateListener(ISwitchStateListener listener) {
if (this.switchStateListener != null) {
- logger.warn(this.switchStateListener.toString()
- + "already listened to switch events");
+ logger.warn("Switch events are already listened by {}",
+ this.switchStateListener.toString());
}
this.switchStateListener = listener;
- logger.debug(listener.toString() + " now listens to switch events");
+ logger.debug("Switch events are now listened by {}",
+ listener.toString());
}
@Override
public void removeSwitchStateListener(ISwitchStateListener listener) {
if ((this.switchStateListener != null)
&& (this.switchStateListener == listener)) {
+ logger.debug("SwitchStateListener {} is Removed",
+ listener.toString());
this.switchStateListener = null;
}
}
SwitchHandler switchHandler = new SwitchHandler(this, sc,
instanceName);
switchHandler.start();
- logger.info(instanceName + " connected: " + sc.toString());
+ if (sc.isConnected()) {
+ logger.info("Switch:{} is connected to the Controller",
+ sc.socket().getRemoteSocketAddress()
+ .toString().split("/")[1]);
+ }
+
} catch (IOException e) {
return;
}
if (((SwitchHandler) sw).isOperational()) {
Long sid = sw.getId();
if (this.switches.remove(sid, sw)) {
- logger.warn(sw.toString() + " is disconnected");
+ logger.warn("{} is Disconnected", sw.toString());
notifySwitchDeleted(sw);
- } else {
- //logger.warn(sw.toString() + " has been replaced by " +
- // this.switches.get(sid));
}
}
((SwitchHandler) sw).stop();
}
}
- public void takeSwtichEventAdd(ISwitch sw) {
+ public void takeSwitchEventAdd(ISwitch sw) {
SwitchEvent ev = new SwitchEvent(
SwitchEvent.SwitchEventType.SWITCH_ADD, sw, null);
addSwitchEvent(ev);
while (iter.hasNext()) {
Long sid = iter.next();
Date date = switches.get(sid).getConnectedDate();
- String switchInstanceName = ((SwitchHandler) switches.get(sid)).getInstanceName();
+ String switchInstanceName = ((SwitchHandler) switches.get(sid))
+ .getInstanceName();
s.append(switchInstanceName + "/" + HexString.toHexString(sid)
+ " connected since " + date.toString() + "\n");
}
@Override
public String getHelp() {
StringBuffer help = new StringBuffer();
- help.append("-- Open Flow Controller --\n");
+ help.append("---Open Flow Controller---\n");
help.append("\t controllerShowSwitches\n");
help.append("\t controllerReset\n");
help.append("\t controllerShowConnConfig\n");
-
/*
* Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
*
try {
openFlowPort = Short.decode(portString).shortValue();
} catch (NumberFormatException e) {
- logger.warn("Invalid port:" + portString + ", use default("
- + openFlowPort + ")");
+ logger.warn("Invalid port:{}, use default({})", portString,
+ openFlowPort);
}
}
}
SelectionKey skey = selectedKeys.next();
selectedKeys.remove();
if (skey.isValid() && skey.isAcceptable()) {
- ((Controller) listener).handleNewConnection(selector,
- serverSelectionKey);
+ ((Controller) listener).handleNewConnection(
+ selector, serverSelectionKey);
}
}
} catch (Exception e) {
}
}, "ControllerI/O Thread");
controllerIOThread.start();
- logger.info("Controller is now listening on port " + openFlowPort);
+ logger.info("Controller is now listening on port {}", openFlowPort);
}
public void shutDown() throws IOException {
}
for (OFMessage msg : msgs) {
logger.trace("Message received: {}", msg.toString());
- /*
- * if ((msg.getType() != OFType.ECHO_REQUEST) && (msg.getType() !=
- * OFType.ECHO_REPLY)) { logger.debug(msg.getType().toString() +
- * " received from sw " + toString()); }
- */
this.lastMsgReceivedTimeStamp = System.currentTimeMillis();
OFType type = msg.getType();
switch (type) {
}
private void processPortStatusMsg(OFPortStatus msg) {
- // short portNumber = msg.getDesc().getPortNumber();
OFPhysicalPort port = msg.getDesc();
if (msg.getReason() == (byte) OFPortReason.OFPPR_MODIFY.ordinal()) {
updatePhysicalPort(port);
- // logger.debug("Port " + portNumber + " on " + toString() +
- // " modified");
} else if (msg.getReason() == (byte) OFPortReason.OFPPR_ADD.ordinal()) {
updatePhysicalPort(port);
- // logger.debug("Port " + portNumber + " on " + toString() +
- // " added");
} else if (msg.getReason() == (byte) OFPortReason.OFPPR_DELETE
.ordinal()) {
deletePhysicalPort(port);
- // logger.debug("Port " + portNumber + " on " + toString() +
- // " deleted");
}
}
reportSwitchStateChange(false);
} else {
// send a probe to see if the switch is still alive
- // logger.debug("Send idle probe (Echo Request) to "
- // + switchName());
+ logger.debug(
+ "Send idle probe (Echo Request) to {}",
+ toString());
probeSent = true;
OFMessage echo = factory
.getMessage(OFType.ECHO_REQUEST);
private void reportError(Exception e) {
if (e instanceof AsynchronousCloseException
|| e instanceof InterruptedException
- || e instanceof SocketException
- || e instanceof IOException) {
+ || e instanceof SocketException || e instanceof IOException) {
logger.debug("Caught exception {}", e.getMessage());
} else {
logger.warn("Caught exception ", e);
private void reportSwitchStateChange(boolean added) {
if (added) {
- ((Controller) core).takeSwtichEventAdd(this);
+ ((Controller) core).takeSwitchEventAdd(this);
} else {
((Controller) core).takeSwitchEventDelete(this);
}
.getValue()
| OFPortFeatures.OFPPF_1GB_HD
.getValue() | OFPortFeatures.OFPPF_10GB_FD
- .getValue()));
+ .getValue()));
}
private void deletePhysicalPort(OFPhysicalPort port) {
@Override
public String toString() {
- return ("["
- + this.socket.toString()
- + " SWID "
- + (isOperational() ? HexString.toHexString(this.sid)
- : "unkbown") + "]");
+ try {
+ return ("Switch:"
+ + socket.socket().getRemoteSocketAddress().toString().split("/")[1]
+ + " SWID:" + (isOperational() ? HexString
+ .toHexString(this.sid) : "unknown"));
+ } catch (Exception e) {
+ return (isOperational() ? HexString.toHexString(this.sid)
+ : "unknown");
+ }
+
}
@Override
}
/**
- * Sends synchronous Barrier message
+ * Sends synchronous Barrier message
*/
@Override
public Object sendBarrierMessage() {
OFBarrierRequest barrierMsg = new OFBarrierRequest();
- return syncSend(barrierMsg);
+ return syncSend(barrierMsg);
}
-
+
/**
* This method returns the switch liveness timeout value. If controller did
* not receive any message from the switch for such a long period,
-
/*
* Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
*
import java.util.List;
+import org.opendaylight.controller.sal.reader.NodeDescription;
import org.openflow.protocol.statistics.OFDescriptionStatistics;
import org.openflow.protocol.statistics.OFStatistics;
-
-import org.opendaylight.controller.sal.reader.NodeDescription;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
- * Utility class for converting openflow description statistics
- * into SAL NodeDescription object
- *
- *
- *
+ * Utility class for converting openflow description statistics into SAL
+ * NodeDescription object
+ *
+ *
+ *
*/
public class DescStatisticsConverter {
+ private static final Logger log = LoggerFactory
+ .getLogger(DescStatisticsConverter.class);
NodeDescription hwDesc;
OFDescriptionStatistics ofDesc;
hwDesc.setDescription(ofDesc.getDatapathDescription());
hwDesc.setSerialNumber(ofDesc.getSerialNumber());
}
+ log.trace("OFDescriptionStatistics: {}", ofDesc);
+ log.trace("NodeDescription: {}", hwDesc);
return hwDesc;
}
import org.opendaylight.controller.protocol_plugin.openflow.vendorextension.v6extension.V6FlowMod;
import org.opendaylight.controller.protocol_plugin.openflow.vendorextension.v6extension.V6Match;
-import org.openflow.protocol.OFFlowMod;
-import org.openflow.protocol.OFMatch;
-import org.openflow.protocol.OFMessage;
-import org.openflow.protocol.OFPacketOut;
-import org.openflow.protocol.OFPort;
-import org.openflow.protocol.OFVendor;
-import org.openflow.protocol.action.OFAction;
-import org.openflow.protocol.action.OFActionDataLayerDestination;
-import org.openflow.protocol.action.OFActionDataLayerSource;
-import org.openflow.protocol.action.OFActionNetworkLayerAddress;
-import org.openflow.protocol.action.OFActionNetworkLayerDestination;
-import org.openflow.protocol.action.OFActionNetworkLayerSource;
-import org.openflow.protocol.action.OFActionNetworkTypeOfService;
-import org.openflow.protocol.action.OFActionOutput;
-import org.openflow.protocol.action.OFActionStripVirtualLan;
-import org.openflow.protocol.action.OFActionTransportLayer;
-import org.openflow.protocol.action.OFActionTransportLayerDestination;
-import org.openflow.protocol.action.OFActionTransportLayerSource;
-import org.openflow.protocol.action.OFActionVirtualLanIdentifier;
-import org.openflow.protocol.action.OFActionVirtualLanPriorityCodePoint;
-import org.openflow.util.U16;
-import org.openflow.util.U32;
-
import org.opendaylight.controller.sal.action.Action;
import org.opendaylight.controller.sal.action.ActionType;
import org.opendaylight.controller.sal.action.Controller;
import org.opendaylight.controller.sal.match.MatchType;
import org.opendaylight.controller.sal.utils.NetUtils;
import org.opendaylight.controller.sal.utils.NodeConnectorCreator;
+import org.openflow.protocol.OFFlowMod;
+import org.openflow.protocol.OFMatch;
+import org.openflow.protocol.OFMessage;
+import org.openflow.protocol.OFPacketOut;
+import org.openflow.protocol.OFPort;
+import org.openflow.protocol.OFVendor;
+import org.openflow.protocol.action.OFAction;
+import org.openflow.protocol.action.OFActionDataLayerDestination;
+import org.openflow.protocol.action.OFActionDataLayerSource;
+import org.openflow.protocol.action.OFActionNetworkLayerAddress;
+import org.openflow.protocol.action.OFActionNetworkLayerDestination;
+import org.openflow.protocol.action.OFActionNetworkLayerSource;
+import org.openflow.protocol.action.OFActionNetworkTypeOfService;
+import org.openflow.protocol.action.OFActionOutput;
+import org.openflow.protocol.action.OFActionStripVirtualLan;
+import org.openflow.protocol.action.OFActionTransportLayer;
+import org.openflow.protocol.action.OFActionTransportLayerDestination;
+import org.openflow.protocol.action.OFActionTransportLayerSource;
+import org.openflow.protocol.action.OFActionVirtualLanIdentifier;
+import org.openflow.protocol.action.OFActionVirtualLanPriorityCodePoint;
+import org.openflow.util.U16;
+import org.openflow.util.U32;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
*/
public class FlowConverter {
protected static final Logger logger = LoggerFactory
- .getLogger(FlowConverter.class);
+ .getLogger(FlowConverter.class);
private Flow flow; // SAL Flow
private OFMatch ofMatch; // OF 1.0 match or OF 1.0 + IPv6 extension match
private List<OFAction> actionsList; // OF 1.0 actions
ofMatch.setWildcards(U32.t(Long.valueOf(wildcards)));
}
}
-
+ logger.trace("SAL Match: {} Openflow Match: {}", flow.getMatch(),
+ ofMatch);
return ofMatch;
}
}
}
}
+ logger.trace("SAL Actions: {} Openflow Actions: {}", flow.getActions(),
+ actionsList);
return actionsList;
}
}
}
}
+ logger.trace("Openflow Match: {} Openflow Actions: {}", ofMatch,
+ actionsList);
+ logger.trace("Openflow Mod Message: {}", fm);
return fm;
}
try {
ip = InetAddress.getByAddress(addr);
} catch (UnknownHostException e) {
- logger.error("",e);
+ logger.error("", e);
}
salAction = new SetNwSrc(ip);
} else if (ofAction instanceof OFActionNetworkLayerDestination) {
try {
ip = InetAddress.getByAddress(addr);
} catch (UnknownHostException e) {
- logger.error("",e);
+ logger.error("", e);
}
salAction = new SetNwDst(ip);
} else if (ofAction instanceof OFActionNetworkTypeOfService) {
// Create Flow
flow = new Flow(salMatch, salActionList);
}
+ logger.trace("Openflow Match: {} Openflow Actions: {}", ofMatch,
+ actionsList);
+ logger.trace("SAL Flow: {}", flow);
return flow;
}
package org.opendaylight.controller.protocol_plugin.openflow.internal;
-import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import org.opendaylight.controller.protocol_plugin.openflow.core.IController;
import org.opendaylight.controller.protocol_plugin.openflow.core.IMessageListener;
import org.opendaylight.controller.protocol_plugin.openflow.core.ISwitch;
-import org.opendaylight.controller.protocol_plugin.openflow.vendorextension.v6extension.V6Error;
-import org.openflow.protocol.OFError;
-import org.openflow.protocol.OFFlowMod;
-import org.openflow.protocol.OFFlowRemoved;
-import org.openflow.protocol.OFMessage;
-import org.openflow.protocol.OFPort;
-import org.openflow.protocol.OFType;
-import org.openflow.protocol.action.OFAction;
-
import org.opendaylight.controller.sal.core.ContainerFlow;
import org.opendaylight.controller.sal.core.IContainerListener;
import org.opendaylight.controller.sal.core.Node;
import org.opendaylight.controller.sal.utils.GlobalConstants;
import org.opendaylight.controller.sal.utils.HexEncode;
import org.opendaylight.controller.sal.utils.NodeCreator;
-import org.opendaylight.controller.sal.utils.StatusCode;
import org.opendaylight.controller.sal.utils.Status;
+import org.opendaylight.controller.sal.utils.StatusCode;
+import org.openflow.protocol.OFError;
+import org.openflow.protocol.OFFlowMod;
+import org.openflow.protocol.OFFlowRemoved;
+import org.openflow.protocol.OFMessage;
+import org.openflow.protocol.OFPort;
+import org.openflow.protocol.OFType;
+import org.openflow.protocol.action.OFAction;
import org.osgi.framework.BundleContext;
import org.osgi.framework.FrameworkUtil;
import org.slf4j.Logger;
}
if (result instanceof Boolean) {
return ((Boolean) result == Boolean.TRUE) ? new Status(
- StatusCode.SUCCESS, null) : new Status(
+ StatusCode.SUCCESS, rid) : new Status(
StatusCode.TIMEOUT, errorString(null, action,
"Request Timed Out"));
} else if (result instanceof OFError) {
OFError res = (OFError) result;
- if (res.getErrorType() == V6Error.NICIRA_VENDOR_ERRORTYPE) {
- V6Error er = new V6Error(res);
- byte[] b = res.getError();
- ByteBuffer bb = ByteBuffer.allocate(b.length);
- bb.put(b);
- bb.rewind();
- er.readFrom(bb);
- return new Status(StatusCode.INTERNALERROR,
- errorString("program", action,
- "Vendor Extension Internal Error"));
- }
return new Status(StatusCode.INTERNALERROR, errorString(
"program", action, Utils.getOFErrorString(res)));
} else {
return new Status(StatusCode.TIMEOUT, errorString(null,
action, "Request Timed Out"));
} else if (msg2 == null) {
- return new Status(StatusCode.SUCCESS, null);
+ return new Status(StatusCode.SUCCESS, rid);
}
} else if (result instanceof OFError) {
return new Status(StatusCode.INTERNALERROR, errorString(
}
if (result instanceof Boolean) {
return ((Boolean) result == Boolean.TRUE) ? new Status(
- StatusCode.SUCCESS, null) : new Status(
+ StatusCode.SUCCESS, rid) : new Status(
StatusCode.TIMEOUT, errorString(null, action,
"Request Timed Out"));
} else if (result instanceof OFError) {
}
if (result instanceof Boolean) {
return ((Boolean) result == Boolean.TRUE) ? new Status(
- StatusCode.SUCCESS, null) : new Status(
+ StatusCode.SUCCESS, rid) : new Status(
StatusCode.TIMEOUT, errorString(null, action,
"Request Timed Out"));
} else if (result instanceof OFError) {
xid = errorMsg.getXid();
}
- long rid = getMessageRid(sw.getId(), xid);
+ Long rid = getMessageRid(sw.getId(), xid);
+ /*
+ * Null or zero requestId indicates that the error message is meant for
+ * a sync message. It will be handled by the sync message worker thread.
+ * Hence we are done here.
+ */
+ if ((rid == null) || (rid == 0)) {
+ return;
+ }
+
+ /*
+ * Notifies the caller that error has been reported for a previous flow
+ * programming request
+ */
for (Map.Entry<String, IFlowProgrammerNotifier> containerNotifier : flowProgrammerNotifiers
.entrySet()) {
IFlowProgrammerNotifier notifier = containerNotifier.getValue();
* The OF message xid
* @return The Request ID
*/
- public long getMessageRid(long swid, int xid) {
+ private Long getMessageRid(long swid, Integer xid) {
+ Long rid = null;
+
+ if (xid == null) {
+ return rid;
+ }
+
Map<Integer, Long> swxid2rid = this.xid2rid.get(swid);
- long rid = 0;
-
if (swxid2rid != null) {
rid = swxid2rid.get(xid);
}
-
/*
* Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
*
import java.util.List;
import org.opendaylight.controller.protocol_plugin.openflow.vendorextension.v6extension.V6StatsReply;
-import org.openflow.protocol.statistics.OFFlowStatisticsReply;
-import org.openflow.protocol.statistics.OFStatistics;
-
import org.opendaylight.controller.sal.core.Node;
import org.opendaylight.controller.sal.flowprogrammer.Flow;
import org.opendaylight.controller.sal.reader.FlowOnNode;
+import org.openflow.protocol.statistics.OFFlowStatisticsReply;
+import org.openflow.protocol.statistics.OFStatistics;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
- * Converts an openflow list of flow statistics in a SAL list of FlowOnNode objects
- *
- *
- *
+ * Converts an openflow list of flow statistics in a SAL list of FlowOnNode
+ * objects
+ *
+ *
+ *
*/
public class FlowStatisticsConverter {
+ private static final Logger log = LoggerFactory
+ .getLogger(FlowStatisticsConverter.class);
private List<OFStatistics> ofStatsList;
private List<FlowOnNode> flowOnNodeList;
if (statsList == null) {// || statsList.isEmpty()) {
this.ofStatsList = new ArrayList<OFStatistics>(1); // dummy list
} else {
- this.ofStatsList = statsList; //new ArrayList<OFStatistics>(statsList);
+ this.ofStatsList = statsList; // new
+ // ArrayList<OFStatistics>(statsList);
}
this.flowOnNodeList = null;
}
flowOnNodeList.add(flowOnNode);
}
}
+ log.trace("OFStatistics: {} FlowOnNode: {}", ofStatsList,
+ flowOnNodeList);
return flowOnNodeList;
}
}
-
/*
* Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
*
import org.slf4j.LoggerFactory;
/**
- * It periodically polls the different OF statistics from the OF switches
- * and caches them for quick retrieval for the above layers' modules
- * It also provides an API to directly query the switch about the statistics
+ * It periodically polls the different OF statistics from the OF switches and
+ * caches them for quick retrieval for the above layers' modules It also
+ * provides an API to directly query the switch about the statistics
*/
public class OFStatisticsManager implements IOFStatisticsManager,
IInventoryShimExternalListener, CommandProvider {
private Timer statisticsTimer;
private TimerTask statisticsTimerTask;
private ConcurrentMap<Long, Boolean> switchSupportsVendorExtStats;
- private Map<Long, Map<Short, TxRates>> txRates; // Per port sampled (every portStatsPeriod) transmit rate
+ private Map<Long, Map<Short, TxRates>> txRates; // Per port sampled (every
+ // portStatsPeriod) transmit
+ // rate
private Set<IStatisticsListener> descriptionListeners;
/**
- * The object containing the latest factoredSamples tx rate samples
- * for a given switch port
+ * The object containing the latest factoredSamples tx rate samples for a
+ * given switch port
*/
protected class TxRates {
- Deque<Long> sampledTxBytes; // contains the latest factoredSamples sampled transmitted bytes
+ Deque<Long> sampledTxBytes; // contains the latest factoredSamples
+ // sampled transmitted bytes
public TxRates() {
sampledTxBytes = new LinkedBlockingDeque<Long>();
public void update(Long txBytes) {
/*
- * Based on how many samples our average works on,
- * we might have to remove the oldest sample
+ * Based on how many samples our average works on, we might have to
+ * remove the oldest sample
*/
if (sampledTxBytes.size() == factoredSamples) {
sampledTxBytes.removeLast();
/**
* Returns the average transmit rate in bps
+ *
* @return the average transmit rate [bps]
*/
public long getAverageTxRate() {
/**
* Function called by the dependency manager when all the required
* dependencies are satisfied
- *
+ *
*/
void init() {
- flowStatistics = new ConcurrentHashMap<Long, List<OFStatistics>>();
+ flowStatistics = new ConcurrentHashMap<Long, List<OFStatistics>>();
descStatistics = new ConcurrentHashMap<Long, List<OFStatistics>>();
portStatistics = new ConcurrentHashMap<Long, List<OFStatistics>>();
dummyList = new ArrayList<OFStatistics>(1);
StatsRequest req = pendingStatsRequests.take();
acquireStatistics(req.switchId, req.type);
} catch (InterruptedException e) {
- log.warn("Flow Statistics Collector thread " +
- "interrupted");
+ log.warn("Flow Statistics Collector thread "
+ + "interrupted", e);
}
}
}
long switchId = switchPortStatsUpdated.take();
updatePortsTxRate(switchId);
} catch (InterruptedException e) {
- log.warn("TX Rate Updater thread interrupted");
+ log.warn("TX Rate Updater thread interrupted", e);
}
}
}
}
/**
- * Function called by the dependency manager when at least one
- * dependency become unsatisfied or when the component is shutting
- * down because for example bundle is being stopped.
- *
+ * Function called by the dependency manager when at least one dependency
+ * become unsatisfied or when the component is shutting down because for
+ * example bundle is being stopped.
+ *
*/
void destroy() {
}
/**
- * Function called by dependency manager after "init ()" is called
- * and after the services provided by the class are registered in
- * the service registry
- *
+ * Function called by dependency manager after "init ()" is called and after
+ * the services provided by the class are registered in the service registry
+ *
*/
void start() {
// Start managed timers
}
/**
- * Function called by the dependency manager before the services
- * exported by the component are unregistered, this will be
- * followed by a "destroy ()" calls
- *
+ * Function called by the dependency manager before the services exported by
+ * the component are unregistered, this will be followed by a "destroy ()"
+ * calls
+ *
*/
void stop() {
// Stop managed timers
}
public void setStatisticsListener(IStatisticsListener s) {
- this.descriptionListeners.add(s);
+ this.descriptionListeners.add(s);
}
-
+
public void unsetStatisticsListener(IStatisticsListener s) {
- if (s != null) {
- this.descriptionListeners.remove(s);
- }
+ if (s != null) {
+ this.descriptionListeners.remove(s);
+ }
}
-
+
private void registerWithOSGIConsole() {
BundleContext bundleContext = FrameworkUtil.getBundle(this.getClass())
.getBundleContext();
}
private void addStatisticsTicks(Long switchId) {
- switchSupportsVendorExtStats.put(switchId, Boolean.TRUE); // Assume switch supports Vendor extension stats
+ switchSupportsVendorExtStats.put(switchId, Boolean.TRUE); // Assume
+ // switch
+ // supports
+ // Vendor
+ // extension
+ // stats
statisticsTimerTicks.put(switchId, new StatisticsTicks(true));
- log.info("Added Switch {} to target pool", HexString
- .toHexString(switchId.longValue()));
+ log.info("Added Switch {} to target pool",
+ HexString.toHexString(switchId.longValue()));
}
protected static class StatisticsTicks {
}
public boolean decrementFlowTicksIsZero() {
- // Please ensure no code is inserted between the if check and the flowStatisticsTicks reset
+ // Please ensure no code is inserted between the if check and the
+ // flowStatisticsTicks reset
if (--flowStatisticsTicks == 0) {
flowStatisticsTicks = statisticsTickNumber;
return true;
}
public boolean decrementDescTicksIsZero() {
- // Please ensure no code is inserted between the if check and the descriptionTicks reset
+ // Please ensure no code is inserted between the if check and the
+ // descriptionTicks reset
if (--descriptionTicks == 0) {
descriptionTicks = descriptionTickNumber;
return true;
}
public boolean decrementPortTicksIsZero() {
- // Please ensure no code is inserted between the if check and the descriptionTicks reset
+ // Please ensure no code is inserted between the if check and the
+ // descriptionTicks reset
if (--portStatisticsTicks == 0) {
portStatisticsTicks = portTickNumber;
return true;
}
private void printInfoMessage(String type, StatsRequest request) {
- log
- .info(
- type
- + " stats request not inserted for switch: {}. Queue size: {}. Collector state: {}.",
- new Object[] { HexString.toHexString(request.switchId),
- pendingStatsRequests.size(),
- statisticsCollector.getState().toString() });
+ log.info(
+ "{} stats request not inserted for switch: {}. Queue size: {}. Collector state: {}.",
+ new Object[] { type, HexString.toHexString(request.switchId),
+ pendingStatsRequests.size(),
+ statisticsCollector.getState().toString() });
}
protected void decrementTicks() {
Long switchId = entry.getKey();
if (clock.decrementFlowTicksIsZero() == true) {
request = (switchSupportsVendorExtStats.get(switchId) == Boolean.TRUE) ? new StatsRequest(
- switchId, OFStatisticsType.VENDOR)
- : new StatsRequest(switchId, OFStatisticsType.FLOW);
- // If a request for this switch is already in the queue, skip to add this new request
+ switchId, OFStatisticsType.VENDOR) : new StatsRequest(
+ switchId, OFStatisticsType.FLOW);
+ // If a request for this switch is already in the queue, skip to
+ // add this new request
if (!pendingStatsRequests.contains(request)
&& false == pendingStatsRequests.offer(request)) {
printInfoMessage("Flow", request);
if (clock.decrementDescTicksIsZero() == true) {
request = new StatsRequest(switchId, OFStatisticsType.DESC);
- // If a request for this switch is already in the queue, skip to add this new request
+ // If a request for this switch is already in the queue, skip to
+ // add this new request
if (!pendingStatsRequests.contains(request)
&& false == pendingStatsRequests.offer(request)) {
printInfoMessage("Description", request);
if (clock.decrementPortTicksIsZero() == true) {
request = new StatsRequest(switchId, OFStatisticsType.PORT);
- // If a request for this switch is already in the queue, skip to add this new request
+ // If a request for this switch is already in the queue, skip to
+ // add this new request
if (!pendingStatsRequests.contains(request)
&& false == pendingStatsRequests.offer(request)) {
printInfoMessage("Port", request);
}
private void removeStatsRequestTasks(Long switchId) {
- log.info("Cleaning Statistics database for switch "
- + HexEncode.longToHexString(switchId));
- // To be safe, let's attempt removal of both VENDOR and FLOW request. It does not hurt
+ log.info("Cleaning Statistics database for switch {}",
+ HexEncode.longToHexString(switchId));
+ // To be safe, let's attempt removal of both VENDOR and FLOW request. It
+ // does not hurt
pendingStatsRequests.remove(new StatsRequest(switchId,
OFStatisticsType.VENDOR));
pendingStatsRequests.remove(new StatsRequest(switchId,
statisticsTimerTicks.remove(switchId);
removeStatsRequestTasks(switchId);
flowStatistics.remove(switchId);
- log.info("Statistics removed for switch "
- + HexString.toHexString(switchId));
+ log.info("Statistics removed for switch {}",
+ HexString.toHexString(switchId));
}
private void acquireStatistics(Long switchId, OFStatisticsType statType) {
|| (statType == OFStatisticsType.VENDOR)) {
flowStatistics.put(switchId, values);
} else if (statType == OFStatisticsType.DESC) {
- // Notify who may be interested in a description change
- notifyDescriptionListeners(switchId, values);
-
+ // Notify who may be interested in a description change
+ notifyDescriptionListeners(switchId, values);
+
// Overwrite cache
descStatistics.put(switchId, values);
} else if (statType == OFStatisticsType.PORT) {
// Overwrite cache with new port statistics for this switch
portStatistics.put(switchId, values);
- // Wake up the thread which maintains the TX byte counters for each port
+ // Wake up the thread which maintains the TX byte counters for
+ // each port
switchPortStatsUpdated.offer(switchId);
}
}
}
private void notifyDescriptionListeners(Long switchId,
- List<OFStatistics> values) {
- for (IStatisticsListener l : this.descriptionListeners) {
- l.descriptionRefreshed(switchId,
- ((OFDescriptionStatistics)values.get(0)));
- }
+ List<OFStatistics> values) {
+ for (IStatisticsListener l : this.descriptionListeners) {
+ l.descriptionRefreshed(switchId,
+ ((OFDescriptionStatistics) values.get(0)));
+ }
}
-
+
/*
* Generic function to get the statistics form a OF switch
*/
match.setWildcards(0xffffffff);
} else if (!(target instanceof OFMatch)) {
// Malformed request
- log.warn("Invalid target type for Flow stats request: "
- + target.getClass());
+ log.warn("Invalid target type for Flow stats request: {}",
+ target.getClass());
return null;
} else {
// Specific flow request
targetPort = (short) OFPort.OFPP_NONE.getValue();
} else if (!(target instanceof Short)) {
// Malformed request
- log.warn("Invalid target type for Port stats request: "
- + target.getClass());
+ log.warn("Invalid target type for Port stats request: {}",
+ target.getClass());
return null;
} else {
// Specific port request
log.warn("Request Timed Out for ({}) from switch {}", type,
HexString.toHexString(switchId));
} else if (result instanceof OFError) {
- log.warn("Switch {} failed to handle ({}) stats request: "
- + Utils.getOFErrorString((OFError) result), HexString
- .toHexString(switchId), type);
+ log.warn("Switch {} failed to handle ({}) stats request: {}",
+ new Object[] { HexString.toHexString(switchId), type,
+ Utils.getOFErrorString((OFError) result) });
if (this.switchSupportsVendorExtStats.get(switchId) == Boolean.TRUE) {
- log
- .warn(
- "Switching back to regular Flow stats requests for switch {}",
- HexString.toHexString(switchId));
+ log.warn(
+ "Switching back to regular Flow stats requests for switch {}",
+ HexString.toHexString(switchId));
this.switchSupportsVendorExtStats.put(switchId,
Boolean.FALSE);
}
List<OFStatistics> list = flowStatistics.get(switchId);
/*
- * Check on emptiness as interference between add and get is still
- * possible on the inner list (the concurrentMap entry's value)
+ * Check on emptiness as interference between add and get is still
+ * possible on the inner list (the concurrentMap entry's value)
*/
return (list == null || list.isEmpty()) ? this.dummyList
: (list.get(0) instanceof OFVendorStatistics) ? this
List<OFStatistics> statsList = flowStatistics.get(switchId);
/*
- * Check on emptiness as interference between add and get is still
- * possible on the inner list (the concurrentMap entry's value)
+ * Check on emptiness as interference between add and get is still
+ * possible on the inner list (the concurrentMap entry's value)
*/
if (statsList == null || statsList.isEmpty()) {
return this.dummyList;
if (statsList.get(0) instanceof OFVendorStatistics) {
/*
- * Caller could provide regular OF match when we
- * instead pull the vendor statistics from this node
- * Caller is not supposed to know whether this switch supports
- * vendor extensions statistics requests
+ * Caller could provide regular OF match when we instead pull the
+ * vendor statistics from this node Caller is not supposed to know
+ * whether this switch supports vendor extensions statistics
+ * requests
*/
V6Match targetMatch = (ofMatch instanceof V6Match) ? (V6Match) ofMatch
: new V6Match(ofMatch);
ByteBuffer data = ByteBuffer.allocate(length);
stat.writeTo(data);
data.rewind();
- log.trace("getV6ReplyStatistics: Buffer BYTES ARE {}", HexString
- .toHexString(data.array()));
+ log.trace("getV6ReplyStatistics: Buffer BYTES ARE {}",
+ HexString.toHexString(data.array()));
- int vendor = data.getInt(); //first 4 bytes is vendor id.
+ int vendor = data.getInt(); // first 4 bytes is vendor id.
if (vendor != V6StatsRequest.NICIRA_VENDOR_ID) {
- log
- .debug("Unexpected vendor id: 0x{}", Integer
- .toHexString(vendor));
+ log.warn("Unexpected vendor id: 0x{}", Integer.toHexString(vendor));
return null;
} else {
- //go ahead by 8 bytes which is 8 bytes of 0
- data.getLong(); //should be all 0's
- length -= 12; // 4 bytes Nicira Hdr + 8 bytes from above line have been consumed
+ // go ahead by 8 bytes which is 8 bytes of 0
+ data.getLong(); // should be all 0's
+ length -= 12; // 4 bytes Nicira Hdr + 8 bytes from above line have
+ // been consumed
}
V6StatsReply v6statsreply;
public List<OFStatistics> queryStatistics(Long switchId,
OFStatisticsType statType, Object target) {
/*
- * Caller does not know and it is not supposed to know whether
- * this switch supports vendor extension. We adjust the target for him
+ * Caller does not know and it is not supposed to know whether this
+ * switch supports vendor extension. We adjust the target for him
*/
if (statType == OFStatisticsType.FLOW) {
if (switchSupportsVendorExtStats.get(switchId) == Boolean.TRUE) {
}
/*
- * InventoryShim replay for us all the switch addition which happened before we were brought up
+ * InventoryShim replay for us all the switch addition which happened before
+ * we were brought up
*/
@Override
public void updateNode(Node node, UpdateType type, Set<Property> props) {
}
/**
- * Update the cached port rates for this switch with the latest
- * retrieved port transmit byte count
+ * Update the cached port rates for this switch with the latest retrieved
+ * port transmit byte count
+ *
* @param switchId
*/
private synchronized void updatePortsTxRate(long switchId) {
public String getHelp() {
StringBuffer help = new StringBuffer();
help.append("---OF Statistics Manager utilities---\n");
- help.append("\t ofdumpstatsmgr - " +
- "Print Internal Stats Mgr db\n");
+ help.append("\t ofdumpstatsmgr - "
+ + "Print Internal Stats Mgr db\n");
return help.toString();
}
public void _ofdumpstatsmgr(CommandInterpreter ci) {
ci.println("Global Counter: " + counter);
- ci
- .println("Timer Ticks: "
- + prettyPrintSwitchMap(statisticsTimerTicks));
+ ci.println("Timer Ticks: " + prettyPrintSwitchMap(statisticsTimerTicks));
ci.println("PendingStatsQueue: " + pendingStatsRequests);
ci.println("PendingStatsQueue size: " + pendingStatsRequests.size());
ci.println("Stats Collector alive: " + statisticsCollector.isAlive());
String averageWindow = ci.nextArgument();
short seconds = 0;
if (averageWindow == null) {
- ci.println("Insert the length in seconds of the median " +
- "window for tx rate");
- ci.println("Current: " + factoredSamples * portTickNumber
- + " secs");
+ ci.println("Insert the length in seconds of the median "
+ + "window for tx rate");
+ ci.println("Current: " + factoredSamples * portTickNumber + " secs");
return;
}
try {
} catch (NumberFormatException e) {
ci.println("Invalid period.");
}
- OFStatisticsManager.factoredSamples = (short) (seconds/portTickNumber);
+ OFStatisticsManager.factoredSamples = (short) (seconds / portTickNumber);
ci.println("New: " + factoredSamples * portTickNumber + " secs");
}
public void _ofstatsmgrintervals(CommandInterpreter ci) {
String flowStatsInterv = ci.nextArgument();
String portStatsInterv = ci.nextArgument();
-
+
if (flowStatsInterv == null || portStatsInterv == null) {
ci.println("Usage: ostatsmgrintervals <fP> <pP> (in seconds)");
- ci.println("Current Values: fP=" + statisticsTickNumber +
- "s pP=" + portTickNumber + "s");
+ ci.println("Current Values: fP=" + statisticsTickNumber + "s pP="
+ + portTickNumber + "s");
return;
}
Short fP, pP;
try {
- fP = Short.parseShort(flowStatsInterv);
- pP = Short.parseShort(portStatsInterv);
+ fP = Short.parseShort(flowStatsInterv);
+ pP = Short.parseShort(portStatsInterv);
} catch (Exception e) {
- ci.println("Invalid format values: " + e.getMessage());
- return;
+ ci.println("Invalid format values: " + e.getMessage());
+ return;
}
- if (pP <= 1 || fP <=1) {
- ci.println("Invalid values. fP and pP have to be greater than 1.");
- return;
+ if (pP <= 1 || fP <= 1) {
+ ci.println("Invalid values. fP and pP have to be greater than 1.");
+ return;
}
-
+
statisticsTickNumber = fP;
portTickNumber = pP;
-
- ci.println("New Values: fP=" + statisticsTickNumber +
- "s pP=" + portTickNumber + "s");
+
+ ci.println("New Values: fP=" + statisticsTickNumber + "s pP="
+ + portTickNumber + "s");
}
}
-
/*
* Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
*
package org.opendaylight.controller.protocol_plugin.openflow.internal;
-import org.openflow.protocol.OFPort;
-
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.utils.NetUtils;
import org.opendaylight.controller.sal.utils.NodeConnectorCreator;
+import org.openflow.protocol.OFPort;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
- * Abstract class which provides the utilities for converting
- * the Openflow port number to the equivalent NodeConnector and vice versa
- *
- *
- *
+ * Abstract class which provides the utilities for converting the Openflow port
+ * number to the equivalent NodeConnector and vice versa
+ *
+ *
+ *
*/
public abstract class PortConverter {
- private static final int maxOFPhysicalPort =
- NetUtils.getUnsignedShort(OFPort.OFPP_MAX.getValue());
+ private static final Logger log = LoggerFactory
+ .getLogger(PortConverter.class);
+ private static final int maxOFPhysicalPort = NetUtils
+ .getUnsignedShort(OFPort.OFPP_MAX.getValue());
/**
* Converts the Openflow port number to the equivalent NodeConnector.
public static NodeConnector toNodeConnector(short ofPort, Node node) {
// Restore original OF unsigned 16 bits value for the comparison
int unsignedOFPort = NetUtils.getUnsignedShort(ofPort);
-
+ log.trace("Openflow port number signed: {} unsigned: {}", ofPort,
+ unsignedOFPort);
if (unsignedOFPort > maxOFPhysicalPort) {
if (ofPort == OFPort.OFPP_LOCAL.getValue()) {
return NodeConnectorCreator.createNodeConnector(
* Converts the NodeConnector to the equivalent Openflow port number
*/
public static short toOFPort(NodeConnector salPort) {
+ log.trace("SAL Port", salPort);
if (salPort.getType().equals(NodeConnectorIDType.SWSTACK)) {
return OFPort.OFPP_LOCAL.getValue();
- } else if (salPort.getType().equals(
- NodeConnectorIDType.HWPATH)) {
+ } else if (salPort.getType().equals(NodeConnectorIDType.HWPATH)) {
return OFPort.OFPP_NORMAL.getValue();
- } else if (salPort.getType().equals(
- NodeConnectorIDType.CONTROLLER)) {
+ } else if (salPort.getType().equals(NodeConnectorIDType.CONTROLLER)) {
return OFPort.OFPP_CONTROLLER.getValue();
}
return (Short) salPort.getID();
-
/*
* Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
*
import java.util.ArrayList;
import java.util.List;
-import org.openflow.protocol.statistics.OFPortStatisticsReply;
-import org.openflow.protocol.statistics.OFStatistics;
-
import org.opendaylight.controller.sal.core.Node;
import org.opendaylight.controller.sal.reader.NodeConnectorStatistics;
import org.opendaylight.controller.sal.utils.NodeCreator;
+import org.openflow.protocol.statistics.OFPortStatisticsReply;
+import org.openflow.protocol.statistics.OFStatistics;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
* Converts an openflow list of port statistics in a SAL list of
* NodeConnectorStatistics objects
- *
- *
- *
+ *
+ *
+ *
*/
public class PortStatisticsConverter {
+ private static final Logger log = LoggerFactory
+ .getLogger(PortStatisticsConverter.class);
private long switchId;
private List<OFStatistics> ofStatsList;
private List<NodeConnectorStatistics> ncStatsList;
.getReceiveFrameErrors());
NCStat.setReceiveOverRunErrorCount(ofPortStat
.getReceiveOverrunErrors());
- NCStat
- .setReceiveCRCErrorCount(ofPortStat
- .getReceiveCRCErrors());
+ NCStat.setReceiveCRCErrorCount(ofPortStat.getReceiveCRCErrors());
NCStat.setCollisionCount(ofPortStat.getCollisions());
this.ncStatsList.add(NCStat);
}
}
+ log.trace("OFStatistics: {} NodeConnectorStatistics: {}", ofStatsList,
+ ncStatsList);
return this.ncStatsList;
}
package org.opendaylight.controller.protocol_plugin.openflow.internal;
+import java.nio.ByteBuffer;
+
+import org.opendaylight.controller.protocol_plugin.openflow.vendorextension.v6extension.V6Error;
import org.openflow.protocol.OFError;
import org.openflow.protocol.OFError.OFBadActionCode;
import org.openflow.protocol.OFError.OFBadRequestCode;
public abstract class Utils {
public static String getOFErrorString(OFError error) {
+ // Handle VENDOR extension errors here
+ if (error.getErrorType() == V6Error.NICIRA_VENDOR_ERRORTYPE) {
+ V6Error er = new V6Error(error);
+ byte[] b = error.getError();
+ ByteBuffer bb = ByteBuffer.allocate(b.length);
+ bb.put(b);
+ bb.rewind();
+ er.readFrom(bb);
+ return er.toString();
+ }
+
+ // Handle OF1.0 errors here
OFErrorType et = OFErrorType.values()[0xffff & error.getErrorType()];
String errorStr = "Error : " + et.toString();
switch (et) {
* Synchronously add a flow to the network node
*
* @param node
+ * The target network node
* @param flow
+ * The flow to install
+ * @return The status of this request
*/
Status addFlow(Node node, Flow flow);
* Synchronously modify existing flow on the switch
*
* @param node
- * @param flow
+ * The target network node
+ * @param oldFlow
+ * The existing flow to modify
+ * @param newFlow
+ * The new flow to install
+ * @return The status of this request
*/
Status modifyFlow(Node node, Flow oldFlow, Flow newFlow);
* Synchronously remove the flow from the network node
*
* @param node
+ * The target network node
* @param flow
+ * The flow to remove
+ * @return The status of this request
*/
Status removeFlow(Node node, Flow flow);
* Asynchronously add a flow to the network node
*
* @param node
+ * The target network node
* @param flow
+ * The flow to install
+ * @return The status of this request containing the unique request id
*/
Status addFlowAsync(Node node, Flow flow);
* Asynchronously modify existing flow on the switch
*
* @param node
- * @param flow
+ * The target network node
+ * @param oldFlow
+ * The existing flow to modify
+ * @param newFlow
+ * The new flow to install
+ * @return The status of this request containing the unique request id
*/
Status modifyFlowAsync(Node node, Flow oldFlow, Flow newFlow);
* Asynchronously remove the flow from the network node
*
* @param node
+ * The target network node
* @param flow
+ * The flow to remove
+ * @return The status of this request containing the unique request id
*/
Status removeFlowAsync(Node node, Flow flow);
* Remove all flows present on the network node
*
* @param node
+ * The target network node
+ * @return The status of this request containing the unique request id
*/
Status removeAllFlows(Node node);
/**
- * Send synchronous Barrier message
+ * Send synchronous Barrier message
+ *
+ * Solicit the network node to report whether all the requests sent so far
+ * are completed. When this call is done, caller knows that all past flow
+ * operations requested to the node in asynchronous fashion were satisfied
+ * by the network node and that in case of any failure, a message was sent
+ * to the controller.
*
* @param node
+ * The network node to solicit
+ * @return The status of this request containing the unique request id
*/
Status sendBarrierMessage(Node node);
}
* a string which describes a failure reason (if any) in human readable form.
*/
public class Status {
- StatusCode code;
- String description;
+ private StatusCode code;
+ private String description;
+ private long requestId;
/**
* Generates an instance of the Status class. This is used as return code
this.code = (errorCode != null) ? errorCode : StatusCode.UNDEFINED;
this.description = (description != null) ? description : this.code
.toString();
+ this.requestId = 0;
}
/**
this.code = (errorCode != null) ? errorCode : StatusCode.UNDEFINED;
this.description = (description != null) ? description : this.code
.toString();
+ this.requestId = 0;
+ }
+
+ /**
+ * Generates an instance of the Status class to be used in case of
+ * asynchronous call. It is supposed to be created by the underlying
+ * infrastructure only when it was successful in allocating the asynchronous
+ * request id, hence caller should expect StatusCode to be successful.
+ *
+ * @param errorCode
+ * The status code. If passed as null, code will be stored as
+ * {@code StatusCode.UNDEFINED}
+ * @param requestId
+ * The request id set by underlying infrastructure for this
+ * request
+ */
+ public Status(StatusCode errorCode, long requestId) {
+ this.code = (errorCode != null) ? errorCode : StatusCode.UNDEFINED;
+ this.description = (description != null) ? description : this.code
+ .toString();
+ this.requestId = requestId;
}
/**
return code == StatusCode.SUCCESS;
}
+ /**
+ * Return the request id assigned by underlying infrastructure in case of
+ * asynchronous request. In case of synchronous requests, the returned id
+ * is expected to be 0
+ *
+ * @return The request id assigned for this asynchronous request
+ */
+ public long getRequestId() {
+ return requestId;
+ }
+
@Override
public String toString() {
- return code + ": " + description;
+ return code + ": " + description + " (" + requestId + ")";
}
@Override
import org.opendaylight.controller.sal.action.SetNwDst;
import org.opendaylight.controller.sal.core.ConstructionException;
import org.opendaylight.controller.sal.core.Node;
-import org.opendaylight.controller.sal.core.NodeConnector;
import org.opendaylight.controller.sal.core.Node.NodeIDType;
+import org.opendaylight.controller.sal.core.NodeConnector;
import org.opendaylight.controller.sal.flowprogrammer.Flow;
import org.opendaylight.controller.sal.flowprogrammer.IFlowProgrammerListener;
import org.opendaylight.controller.sal.flowprogrammer.IFlowProgrammerService;
import org.opendaylight.controller.sal.flowprogrammer.IPluginOutFlowProgrammerService;
import org.opendaylight.controller.sal.match.Match;
import org.opendaylight.controller.sal.match.MatchType;
-import org.opendaylight.controller.sal.utils.StatusCode;
import org.opendaylight.controller.sal.utils.EtherTypes;
import org.opendaylight.controller.sal.utils.IPProtocols;
import org.opendaylight.controller.sal.utils.NodeConnectorCreator;
import org.opendaylight.controller.sal.utils.Status;
+import org.opendaylight.controller.sal.utils.StatusCode;
import org.osgi.framework.BundleContext;
import org.osgi.framework.FrameworkUtil;
import org.slf4j.Logger;
<groupId>org.mockito</groupId>\r
<artifactId>mockito-all</artifactId>\r
<version>1.8.4</version>\r
- </dependency>\r
+ </dependency>
+ <dependency>\r
+ <groupId>com.google.guava</groupId>\r
+ <artifactId>guava</artifactId>\r
+ <version>14.0.1</version>\r
+ </dependency>\r
+\r
</dependencies>\r
<build>\r
<plugins>\r
identifier_stmt : IDENTIFIER string? stmtend;
-stmtend : (SEMICOLON identifier_stmt?) | (LEFT_BRACE identifier_stmt? RIGHT_BRACE);
+stmtend : (SEMICOLON) | (LEFT_BRACE identifier_stmt? RIGHT_BRACE);
deviate_replace_stmt : DEVIATE_KEYWORD string /* REPLACE_KEYWORD */ (SEMICOLON | (LEFT_BRACE (identifier_stmt |type_stmt | units_stmt | default_stmt | config_stmt | mandatory_stmt | min_elements_stmt | max_elements_stmt )* RIGHT_BRACE));
deviate_delete_stmt : DEVIATE_KEYWORD string /* DELETE_KEYWORD */ (SEMICOLON | (LEFT_BRACE (identifier_stmt |units_stmt | must_stmt | unique_stmt | default_stmt )* RIGHT_BRACE));
deviate_add_stmt : DEVIATE_KEYWORD string /*ADD_KEYWORD*/ (SEMICOLON | (LEFT_BRACE (identifier_stmt |units_stmt | must_stmt | unique_stmt | default_stmt | config_stmt | mandatory_stmt | min_elements_stmt | max_elements_stmt )* RIGHT_BRACE));
path_stmt : PATH_KEYWORD string stmtend;
leafref_specification : path_stmt;
enum_stmt : ENUM_KEYWORD string (SEMICOLON | (LEFT_BRACE (identifier_stmt |value_stmt | status_stmt | description_stmt | reference_stmt )* RIGHT_BRACE));
-enum_specification : enum_stmt (identifier_stmt | enum_stmt )+;
+enum_specification : enum_stmt (identifier_stmt | enum_stmt )*;
default_stmt : DEFAULT_KEYWORD string stmtend;
pattern_stmt : PATTERN_KEYWORD string (SEMICOLON | (LEFT_BRACE (identifier_stmt |error_message_stmt | error_app_tag_stmt | description_stmt | reference_stmt )* RIGHT_BRACE));
length_stmt : LENGTH_KEYWORD string (SEMICOLON | (LEFT_BRACE (identifier_stmt |error_message_stmt | error_app_tag_stmt | description_stmt | reference_stmt )* RIGHT_BRACE));
*/
package org.opendaylight.controller.yang.model.parser.builder.impl;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
private final IdentitySchemaNodeImpl instance;
private IdentitySchemaNodeBuilder baseIdentity;
private String baseIdentityName;
+ private final List<UnknownSchemaNodeBuilder> addedUnknownNodes = new ArrayList<UnknownSchemaNodeBuilder>();
IdentitySchemaNodeBuilder(final QName qname) {
this.qname = qname;
final IdentitySchemaNode base = baseIdentity.build();
instance.setBaseIdentity(base);
}
+
+ // UNKNOWN NODES
+ final List<UnknownSchemaNode> unknownNodes = new ArrayList<UnknownSchemaNode>();
+ for (UnknownSchemaNodeBuilder b : addedUnknownNodes) {
+ unknownNodes.add(b.build());
+ }
+ instance.setUnknownSchemaNodes(unknownNodes);
+
return instance;
}
}
}
+ public List<UnknownSchemaNodeBuilder> getUnknownNodes() {
+ return addedUnknownNodes;
+ }
+
@Override
- public void addUnknownSchemaNode(final UnknownSchemaNodeBuilder unknownNode) {
- throw new IllegalStateException(
- "Can not add schema node to identity statement");
+ public void addUnknownSchemaNode(UnknownSchemaNodeBuilder unknownNode) {
+ addedUnknownNodes.add(unknownNode);
}
public String getBaseIdentityName() {
private String reference;
private Status status = Status.CURRENT;
private SchemaPath path;
+ private List<UnknownSchemaNode> unknownNodes = Collections.emptyList();
private IdentitySchemaNodeImpl(final QName qname) {
this.qname = qname;
@Override
public List<UnknownSchemaNode> getUnknownSchemaNodes() {
- return Collections.emptyList();
+ return unknownNodes;
+ }
+
+ private void setUnknownSchemaNodes(
+ List<UnknownSchemaNode> unknownSchemaNodes) {
+ if (unknownSchemaNodes != null) {
+ this.unknownNodes = unknownSchemaNodes;
+ }
}
@Override
List<String> pathToCase = new ArrayList<String>(parentPath);
ChoiceCaseBuilder builder = new ChoiceCaseBuilder(caseName);
- final ChoiceBuilder parent = (ChoiceBuilder) moduleNodes
+ final ChildNodeBuilder parent = (ChildNodeBuilder) moduleNodes
.get(pathToCase);
if (parent != null) {
if (parent instanceof AugmentationSchemaBuilder) {
}
pathToCase.add(caseName.getLocalName());
- addedChilds.put(pathToCase, builder);
moduleNodes.put(pathToCase, builder);
return builder;
}
public void addIdentityrefType(String baseString, List<String> parentPath) {
+ List<String> pathToIdentityref = new ArrayList<String>(parentPath);
TypeAwareBuilder parent = (TypeAwareBuilder) moduleNodes
- .get(parentPath);
+ .get(pathToIdentityref);
IdentityrefTypeBuilder identityref = new IdentityrefTypeBuilder(baseString);
parent.setType(identityref);
- dirtyNodes.put(parentPath, parent);
+ dirtyNodes.put(pathToIdentityref, parent);
}
public DeviationBuilder addDeviation(String targetPath,
return builder;
}
- public IdentitySchemaNodeBuilder addIdentity(QName qname) {
+ public IdentitySchemaNodeBuilder addIdentity(QName qname, List<String> parentPath) {
+ List<String> pathToIdentity = new ArrayList<String>(parentPath);
IdentitySchemaNodeBuilder builder = new IdentitySchemaNodeBuilder(qname);
+ pathToIdentity.add(qname.getLocalName());
+ moduleNodes.put(pathToIdentity, builder);
addedIdentities.add(builder);
return builder;
}
import org.opendaylight.controller.yang.model.util.ExtendedType;
import org.opendaylight.controller.yang.model.util.IdentityrefType;
import org.opendaylight.controller.yang.model.util.UnknownType;
+import org.opendaylight.controller.yang.model.validator.YangModelBasicValidator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
final List<ParseTree> trees = parseStreams(yangFiles);
final ModuleBuilder[] builders = new ModuleBuilder[trees.size()];
- // validation
- // if validation fails with any file, do not continue and throw
- // exception
- for (int i = 0; i < trees.size(); i++) {
- try {
- final YangModelValidationListener yangModelParser = new YangModelValidationListener();
- walker.walk(yangModelParser, trees.get(i));
- } catch (IllegalStateException e) {
- // wrap exception to add information about which file failed
- throw new YangValidationException(
- "Yang validation failed for file" + yangFiles[i], e);
- }
- }
+ // validate yang
+ new YangModelBasicValidator(walker).validate(trees);
YangModelParserListenerImpl yangModelParser = null;
for (int i = 0; i < trees.size(); i++) {
final QName currentQName = currentParent.getQName();
final QName lastAugmentPathElement = path.get(path.size() - 1);
-
if (currentQName.getLocalName().equals(
lastAugmentPathElement.getLocalName())) {
fillAugmentTarget(augmentBuilder,
}
}
}
-
}
/**
if(baseString.contains(":")) {
String[] splittedBase = baseString.split(":");
if(splittedBase.length > 2) {
- throw new YangParseException("Failed to parse identity base: "+ baseString);
+ throw new YangParseException("Failed to parse identityref base: "+ baseString);
}
String prefix = splittedBase[0];
String name = splittedBase[1];
if (prefix.equals(module.getPrefix())) {
dependentModule = module;
} else {
- final ModuleImport dependentModuleImport = getModuleImport(module,
+ final ModuleImport dependentModuleImport = ParserUtils.getModuleImport(module,
prefix);
if (dependentModuleImport == null) {
throw new YangParseException("No import found with prefix '"
return dependentModule;
}
- /**
- * Get module import referenced by given prefix.
- *
- * @param builder
- * module to search
- * @param prefix
- * prefix associated with import
- * @return ModuleImport based on given prefix
- */
- private ModuleImport getModuleImport(final ModuleBuilder builder,
- final String prefix) {
- ModuleImport moduleImport = null;
- for (ModuleImport mi : builder.getModuleImports()) {
- if (mi.getPrefix().equals(prefix)) {
- moduleImport = mi;
- break;
- }
- }
- return moduleImport;
- }
private static class SchemaContextImpl implements SchemaContext {
private final Set<Module> modules;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-final class YangModelParserListenerImpl extends YangParserBaseListener {
-
+public final class YangModelParserListenerImpl extends YangParserBaseListener {\r
+\r
private static final Logger logger = LoggerFactory
.getLogger(YangModelParserListenerImpl.class);
private String yangModelPrefix;
private Date revision = new Date(0L);
- final static DateFormat simpleDateFormat = new SimpleDateFormat(
+ public final static DateFormat simpleDateFormat = new SimpleDateFormat(\r
"yyyy-MM-dd");
private final Stack<String> actualPath = new Stack<String>();
if (YangTypesConverter.isBaseYangType(typeName)) {
if (typeBody == null) {
// if there are no constraints, just grab default base yang type
- type = YangTypesConverter.javaTypeForBaseYangType(typeName);
+ type = YangTypesConverter.javaTypeForBaseYangType(actualPath, namespace, revision, typeName);
moduleBuilder.setType(type, actualPath);
} else {
if ("union".equals(typeName)) {
final QName identityQName = new QName(namespace, revision,
yangModelPrefix, identityName);
IdentitySchemaNodeBuilder builder = moduleBuilder
- .addIdentity(identityQName);
+ .addIdentity(identityQName, actualPath);
updatePath(identityName);
builder.setPath(createActualSchemaPath(actualPath, namespace, revision,
+++ /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.model.parser.impl;
-
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.text.DateFormat;
-import java.text.ParseException;
-import java.util.Date;
-import java.util.HashSet;
-import java.util.Set;
-import java.util.regex.Pattern;
-
-import org.antlr.v4.runtime.tree.ParseTree;
-import org.opendaylight.controller.antlrv4.code.gen.YangParser;
-import org.opendaylight.controller.antlrv4.code.gen.YangParser.Belongs_to_stmtContext;
-import org.opendaylight.controller.antlrv4.code.gen.YangParser.Import_stmtContext;
-import org.opendaylight.controller.antlrv4.code.gen.YangParser.Include_stmtContext;
-import org.opendaylight.controller.antlrv4.code.gen.YangParser.Module_header_stmtsContext;
-import org.opendaylight.controller.antlrv4.code.gen.YangParser.Namespace_stmtContext;
-import org.opendaylight.controller.antlrv4.code.gen.YangParser.Prefix_stmtContext;
-import org.opendaylight.controller.antlrv4.code.gen.YangParser.Revision_date_stmtContext;
-import org.opendaylight.controller.antlrv4.code.gen.YangParser.Revision_stmtContext;
-import org.opendaylight.controller.antlrv4.code.gen.YangParser.Revision_stmtsContext;
-import org.opendaylight.controller.antlrv4.code.gen.YangParser.Submodule_header_stmtsContext;
-import org.opendaylight.controller.antlrv4.code.gen.YangParser.Submodule_stmtContext;
-import org.opendaylight.controller.antlrv4.code.gen.YangParser.Yang_version_stmtContext;
-import org.opendaylight.controller.antlrv4.code.gen.YangParserBaseListener;
-import org.opendaylight.controller.yang.model.parser.util.YangModelBuilderUtil;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Validation listener that validates yang statements according to RFC-6020.
- * This validator expects only one module or submodule per file.
- */
-
-/*
- * TODO is this assumption(module per file) correct ? if so, should a check be
- * performed ?
- *
- * TODO break into smaller classes e.g. class for header statements, body
- * statements...
- */
-final class YangModelValidationListener extends YangParserBaseListener {
-
- private static final Logger logger = LoggerFactory
- .getLogger(YangModelValidationListener.class);
-
- private final Set<String> uniquePrefixes;
- private final Set<String> uniqueImports;
- private final Set<String> uniqueIncludes;
-
- public YangModelValidationListener() {
- super();
- uniquePrefixes = new HashSet<String>();
- uniqueImports = new HashSet<String>();
- uniqueIncludes = new HashSet<String>();
- }
-
- /**
- * Rules:
- * <ol>
- * <li>Identifier contains only permitted characters</li>
- * <li>One revision statements present</li>
- * <li>One header statements present</li>
- * </ol>
- */
- @Override
- public void enterModule_stmt(YangParser.Module_stmtContext ctx) {
- String moduleName = getName(ctx);
-
- checkIdentifier(moduleName, "Module");
-
- checkPresentChildOfType(ctx, Revision_stmtsContext.class,
- f("Missing revision statements in module:%s", moduleName), true);
-
- checkPresentChildOfType(ctx, Module_header_stmtsContext.class,
- f("Missing header statements in module:%s", moduleName), true);
- }
-
- /**
- * Rules:
- * <ol>
- * <li>Identifier contains only permitted characters</li>
- * <li>One revision statements present</li>
- * <li>One header statements present</li>
- * </ol>
- */
- @Override
- public void enterSubmodule_stmt(Submodule_stmtContext ctx) {
- String submoduleName = getName(ctx);
-
- checkIdentifier(submoduleName, "Submodule");
-
- checkPresentChildOfType(
- ctx,
- Revision_stmtsContext.class,
- f("Missing revision statements in submodule:%s", submoduleName),
- true);
-
- checkPresentChildOfType(ctx, Submodule_header_stmtsContext.class,
- f("Missing header statements in submodule:%s", submoduleName),
- true);
- }
-
- /**
- * Rules:
- * <ol>
- * <li>One Belongs-to statement present</li>
- * </ol>
- */
- @Override
- public void enterSubmodule_header_stmts(Submodule_header_stmtsContext ctx) {
- String submoduleName = getRootParentName(ctx);
-
- checkPresentChildOfType(
- ctx,
- Belongs_to_stmtContext.class,
- f("Missing belongs-to statement in submodule:%s", submoduleName),
- true);
-
- // check Yang version present, if not issue warning
- checkYangVersion(ctx, submoduleName);
- }
-
- /**
- * Rules:
- * <ol>
- * <li>Identifier contains only permitted characters</li>
- * <li>One Prefix statement child</li>
- * </ol>
- */
- @Override
- public void enterBelongs_to_stmt(Belongs_to_stmtContext ctx) {
- String belongToName = getName(ctx);
- String rootParentName = getRootParentName(ctx);
-
- checkIdentifier(belongToName,
- f("In (sub)module:%s , Belongs-to statement", rootParentName));
-
- checkPresentChildOfType(
- ctx,
- Prefix_stmtContext.class,
- f("Missing prefix statement in belongs-to:%s, in (sub)module:%s",
- belongToName, rootParentName), true);
- }
-
- /**
- * Rules:
- * <ol>
- * <li>At least one Revision statement present</li>
- * </ol>
- */
- @Override
- public void enterRevision_stmts(Revision_stmtsContext ctx) {
- String rootParentName = getRootParentName(ctx);
-
- checkPresentChildOfType(
- ctx,
- Revision_stmtContext.class,
- f("Missing at least one revision statement in (sub)module:%s",
- rootParentName), false);
- }
-
- /**
- * Rules:
- * <ol>
- * <li>One Namespace statement present</li>
- * </ol>
- */
- @Override
- public void enterModule_header_stmts(Module_header_stmtsContext ctx) {
- String moduleName = getRootParentName(ctx);
-
- checkPresentChildOfType(ctx, Namespace_stmtContext.class,
- f("Missing namespace statement in module:%s", moduleName), true);
-
- // check Yang version present, if not issue warning
- checkYangVersion(ctx, moduleName);
- }
-
- /**
- * Rules:
- * <ol>
- * <li>Namespace string can be parsed as URI</li>
- * </ol>
- */
- @Override
- public void enterNamespace_stmt(Namespace_stmtContext ctx) {
- String namespaceName = getName(ctx);
- String rootParentName = getRootParentName(ctx);
-
- try {
- new URI(namespaceName);
- } catch (URISyntaxException e) {
- throw new YangValidationException(f(
- "Namespace:%s in module:%s cannot be parsed as URI",
- namespaceName, rootParentName));
- }
- }
-
- /**
- * Rules:
- * <ol>
- * <li>Identifier contains only permitted characters</li>
- * <li>Every import(identified by identifier) within a module/submodule is
- * present only once</li>
- * <li>One prefix statement child</li>
- * <li>One revision-date statement child</li>
- * </ol>
- */
- @Override
- public void enterImport_stmt(Import_stmtContext ctx) {
- String importName = getName(ctx);
- String rootParentName = getRootParentName(ctx);
-
- checkIdentifier(importName,
- f("In (sub)module:%s , Import statement", rootParentName));
-
- if (uniqueImports.contains(importName))
- throw new YangValidationException(f(
- "Module:%s imported twice in (sub)module:%s", importName,
- rootParentName));
- uniqueImports.add(importName);
-
- checkPresentChildOfType(
- ctx,
- Prefix_stmtContext.class,
- f("Missing prefix statement in import:%s, in (sub)module:%s",
- importName, rootParentName), true);
- //checkPresentChildOfType(
- // ctx,
- // Revision_date_stmtContext.class,
- // f("Missing revision-date statement in import:%s, in (sub)module:%s",
- // importName, rootParentName), true);
- }
-
- /**
- * Rules:
- * <ol>
- * <li>Date is in valid format</li>
- * </ol>
- */
- @Override
- public void enterRevision_date_stmt(Revision_date_stmtContext ctx) {
- String rootParentName = getRootParentName(ctx);
- String exceptionMessage = f(
- "Invalid date format for revision-date:%s in import/include statement:%s, in (sub)module:%s , expected date format is:%s",
- getName(ctx), getRootParentName(ctx), rootParentName,
- YangModelParserListenerImpl.simpleDateFormat.format(new Date()));
-
- validateDateFormat(getName(ctx),
- YangModelParserListenerImpl.simpleDateFormat, exceptionMessage);
- }
-
- /**
- * Rules:
- * <ol>
- * <li>Identifier contains only permitted characters</li>
- * <li>Every include(identified by identifier) within a module/submodule is
- * present only once</li>
- * <li>One Revision-date statement child</li>
- * </ol>
- */
- @Override
- public void enterInclude_stmt(Include_stmtContext ctx) {
- String includeName = getName(ctx);
- String rootParentName = getRootParentName(ctx);
-
- checkIdentifier(includeName,
- f("In (sub)module:%s , Include statement", rootParentName));
-
- if (uniqueIncludes.contains(includeName))
- throw new YangValidationException(f(
- "Submodule:%s included twice in (sub)module:%s",
- includeName, rootParentName));
- uniqueIncludes.add(includeName);
-
- checkPresentChildOfType(
- ctx,
- Revision_date_stmtContext.class,
- f("Missing revision-date statement in include:%s, in (sub)module:%s",
- includeName, rootParentName), true);
- }
-
- static final String SUPPORTED_YANG_VERSION = "1";
-
- /**
- * Rules:
- * <ol>
- * <li>Yang-version is specified as 1</li>
- * </ol>
- */
- @Override
- public void enterYang_version_stmt(YangParser.Yang_version_stmtContext ctx) {
- String version = getName(ctx);
- String rootParentName = getRootParentName(ctx);
- if (!version.equals(SUPPORTED_YANG_VERSION)) {
- throw new YangValidationException(
- f("Unsupported yang version:%s, in (sub)module:%s, supported version:%s",
- version, rootParentName, SUPPORTED_YANG_VERSION));
- }
- }
-
- /**
- * Rules:
- * <ol>
- * <li>Date is in valid format</li>
- * </ol>
- */
- @Override
- public void enterRevision_stmt(YangParser.Revision_stmtContext ctx) {
- String parentName = getRootParentName(ctx);
- String exceptionMessage = f(
- "Invalid date format for revision:%s in (sub)module:%s, expected date format is:%s",
- getName(ctx), parentName,
- YangModelParserListenerImpl.simpleDateFormat.format(new Date()));
-
- validateDateFormat(getName(ctx),
- YangModelParserListenerImpl.simpleDateFormat, exceptionMessage);
- }
-
- /**
- * Rules:
- * <ol>
- * <li>Identifier contains only permitted characters</li>
- * <li>Every prefix(identified by identifier) within a module/submodule is
- * presented only once</li>
- * </ol>
- */
- @Override
- public void enterPrefix_stmt(Prefix_stmtContext ctx) {
- String name = getName(ctx);
- checkIdentifier(
- name,
- f("In module or import statement:%s , Prefix",
- getRootParentName(ctx)));
-
- if (uniquePrefixes.contains(name))
- throw new YangValidationException(f(
- "Not a unique prefix:%s, in (sub)module:%s", name,
- getRootParentName(ctx)));
- uniquePrefixes.add(name);
- }
-
- private String getRootParentName(ParseTree ctx) {
- ParseTree root = ctx;
- while (root.getParent() != null) {
- root = root.getParent();
- }
- return getName(root);
- }
-
- private static String getName(ParseTree child) {
- return YangModelBuilderUtil.stringFromNode(child);
- }
-
- private static String f(String base, Object... args) {
- return String.format(base, args);
- }
-
- private static void checkYangVersion(ParseTree ctx, String moduleName) {
- if (!checkPresentChildOfType(ctx, Yang_version_stmtContext.class, true))
- logger.warn(f(
- "Yang version statement not present in module:%s, Validating as yang version:%s",
- moduleName, SUPPORTED_YANG_VERSION));
- }
-
- private static void validateDateFormat(String string, DateFormat format,
- String message) {
- try {
- format.parse(string);
- } catch (ParseException e) {
- throw new YangValidationException(message);
- }
- }
-
- private static Pattern identifierPattern = Pattern
- .compile("[a-zA-Z_][a-zA-Z0-9_.-]*");
-
- static void checkIdentifier(String name, String messagePrefix) {
- if (!identifierPattern.matcher(name).matches())
- throw new YangValidationException(f(
- "%s identifier:%s is not in required format:%s",
- messagePrefix, name, identifierPattern.toString()));
- }
-
- private static void checkPresentChildOfType(ParseTree ctx,
- Class<?> expectedChildType, String message, boolean atMostOne) {
- if (!checkPresentChildOfType(ctx, expectedChildType, atMostOne))
- throw new YangValidationException(message);
- }
-
- private static boolean checkPresentChildOfType(ParseTree ctx,
- Class<?> expectedChildType, boolean atMostOne) {
-
- int count = 0;
-
- for (int i = 0; i < ctx.getChildCount(); i++) {
- ParseTree child = ctx.getChild(i);
- if (expectedChildType.isInstance(child))
- count++;
- }
-
- return atMostOne ? count == 1 ? true : false : count != 0 ? true
- : false;
- }
-}
import java.util.List;
import org.opendaylight.controller.yang.common.QName;
+import org.opendaylight.controller.yang.model.api.ModuleImport;
import org.opendaylight.controller.yang.model.api.MustDefinition;
import org.opendaylight.controller.yang.model.api.SchemaPath;
import org.opendaylight.controller.yang.model.api.TypeDefinition;
import org.opendaylight.controller.yang.model.parser.builder.impl.LeafListSchemaNodeBuilder;
import org.opendaylight.controller.yang.model.parser.builder.impl.LeafSchemaNodeBuilder;
import org.opendaylight.controller.yang.model.parser.builder.impl.ListSchemaNodeBuilder;
+import org.opendaylight.controller.yang.model.parser.builder.impl.ModuleBuilder;
import org.opendaylight.controller.yang.model.parser.builder.impl.UnknownSchemaNodeBuilder;
public final class ParserUtils {
private ParserUtils() {
}
+ /**
+ * Get module import referenced by given prefix.
+ *
+ * @param builder
+ * module to search
+ * @param prefix
+ * prefix associated with import
+ * @return ModuleImport based on given prefix
+ */
+ public static ModuleImport getModuleImport(final ModuleBuilder builder,
+ final String prefix) {
+ ModuleImport moduleImport = null;
+ for (ModuleImport mi : builder.getModuleImports()) {
+ if (mi.getPrefix().equals(prefix)) {
+ moduleImport = mi;
+ break;
+ }
+ }
+ return moduleImport;
+ }
+
+ /**
+ * Parse uses path.
+ * @param usesPath as String
+ * @return SchemaPath from given String
+ */
public static SchemaPath parseUsesPath(final String usesPath) {
final boolean absolute = usesPath.startsWith("/");
final String[] splittedPath = usesPath.split("/");
import org.opendaylight.controller.yang.model.util.BaseConstraints;
import org.opendaylight.controller.yang.model.util.BinaryType;
import org.opendaylight.controller.yang.model.util.BitsType;
+import org.opendaylight.controller.yang.model.util.Decimal64;
import org.opendaylight.controller.yang.model.util.EnumerationType;
import org.opendaylight.controller.yang.model.util.InstanceIdentifier;
+import org.opendaylight.controller.yang.model.util.Int16;
+import org.opendaylight.controller.yang.model.util.Int32;
+import org.opendaylight.controller.yang.model.util.Int64;
+import org.opendaylight.controller.yang.model.util.Int8;
import org.opendaylight.controller.yang.model.util.Leafref;
import org.opendaylight.controller.yang.model.util.RevisionAwareXPathImpl;
import org.opendaylight.controller.yang.model.util.StringType;
+import org.opendaylight.controller.yang.model.util.Uint16;
+import org.opendaylight.controller.yang.model.util.Uint32;
+import org.opendaylight.controller.yang.model.util.Uint64;
+import org.opendaylight.controller.yang.model.util.Uint8;
import org.opendaylight.controller.yang.model.util.UnknownType;
-import org.opendaylight.controller.yang.model.util.YangTypesConverter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
typeBody, actualPath, namespace, revision, prefix);
if ("decimal64".equals(typeName)) {
- type = YangTypesConverter.javaTypeForBaseYangDecimal64Type(
- rangeStatements, fractionDigits);
+ type = new Decimal64(actualPath, namespace, revision, fractionDigits);
} else if (typeName.startsWith("int")) {
- type = YangTypesConverter.javaTypeForBaseYangSignedIntegerType(
- typeName, rangeStatements);
+ if (typeName.equals("int8")) {
+ type = new Int8(actualPath, namespace, revision, rangeStatements, null, null);
+ } else if (typeName.equals("int16")) {
+ type = new Int16(actualPath, namespace, revision, rangeStatements, null, null);
+ } else if (typeName.equals("int32")) {
+ type = new Int32(actualPath, namespace, revision, rangeStatements, null, null);
+ } else if (typeName.equals("int64")) {
+ type = new Int64(actualPath, namespace, revision, rangeStatements, null, null);
+ }
} else if (typeName.startsWith("uint")) {
- type = YangTypesConverter.javaTypeForBaseYangUnsignedIntegerType(
- typeName, rangeStatements);
+ if (typeName.equals("uint8")) {
+ type = new Uint8(actualPath, namespace, revision, rangeStatements, null, null);
+ } else if (typeName.equals("uint16")) {
+ type = new Uint16(actualPath, namespace, revision, rangeStatements, null, null);
+ } else if (typeName.equals("uint32")) {
+ type = new Uint32(actualPath, namespace, revision, rangeStatements, null, null);
+ } else if (typeName.equals("uint64")) {
+ type = new Uint64(actualPath, namespace, revision, rangeStatements, null, null);
+ }
} else if ("enumeration".equals(typeName)) {
type = new EnumerationType(actualPath, namespace, revision,
enumConstants);
} else if ("string".equals(typeName)) {
- type = new StringType(lengthStatements, patternStatements);
+ type = new StringType(actualPath, namespace, revision, lengthStatements, patternStatements);
} else if ("bits".equals(typeName)) {
type = new BitsType(getBits(typeBody, actualPath, namespace,
revision, prefix));
* 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.model.parser.impl;
+package org.opendaylight.controller.yang.model.parser.util;
/**
* Unchecked exception thrown if yang definition is not valid according to
- * {@link YangModelValidationListener}
+ * {@link YangModelBasicValidationListener}
*/
-public class YangValidationException extends RuntimeException {
+public final class YangValidationException extends RuntimeException {
private static final long serialVersionUID = 7414330400390825381L;
--- /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/eplv10.html
+ */
+package org.opendaylight.controller.yang.model.validator;
+
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.util.Date;
+import java.util.List;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.antlr.v4.runtime.tree.ParseTree;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Yang_version_stmtContext;
+import org.opendaylight.controller.yang.model.parser.impl.YangModelParserListenerImpl;
+import org.opendaylight.controller.yang.model.parser.util.YangValidationException;
+
+import com.google.common.collect.Sets;
+
+/**
+ * Reusable checks of basic constraints on yang statements
+ */
+final class BasicValidations {
+
+ static final String SUPPORTED_YANG_VERSION = "1";
+
+ static void checkNotPresentBoth(ParseTree parent,
+ Class<? extends ParseTree> childType1,
+ Class<? extends ParseTree> childType2) {
+ if (BasicValidations.checkPresentChildOfTypeSafe(parent, childType1,
+ true)
+ && BasicValidations.checkPresentChildOfTypeSafe(parent,
+ childType2, false))
+ ValidationUtil
+ .ex(ValidationUtil
+ .f("(In (sub)module:%s) Both %s and %s statement present in %s:%s",
+ ValidationUtil.getRootParentName(parent),
+ ValidationUtil
+ .getSimpleStatementName(childType1),
+ ValidationUtil
+ .getSimpleStatementName(childType2),
+ ValidationUtil
+ .getSimpleStatementName(parent
+ .getClass()),
+ ValidationUtil.getName(parent)));
+ }
+
+ static void checkOnlyPermittedValues(ParseTree ctx,
+ Set<String> permittedValues) {
+ String mandatory = ValidationUtil.getName(ctx);
+ String rootParentName = ValidationUtil.getRootParentName(ctx);
+
+ if (!permittedValues.contains(mandatory))
+ ValidationUtil
+ .ex(ValidationUtil
+ .f("(In (sub)module:%s) %s:%s, illegal value for %s statement, only permitted:%s",
+ rootParentName, ValidationUtil
+ .getSimpleStatementName(ctx
+ .getClass()), mandatory,
+ ValidationUtil.getSimpleStatementName(ctx
+ .getClass()), permittedValues));
+ }
+
+ static void checkUniquenessInNamespace(ParseTree stmt, Set<String> uniques) {
+ String name = ValidationUtil.getName(stmt);
+ String rootParentName = ValidationUtil.getRootParentName(stmt);
+
+ if (uniques.contains(name))
+ ValidationUtil.ex(ValidationUtil.f(
+ "(In (sub)module:%s) %s:%s not unique in (sub)module",
+ rootParentName,
+ ValidationUtil.getSimpleStatementName(stmt.getClass()),
+ name));
+ uniques.add(name);
+ }
+
+ /**
+ * Check if only one module or submodule is present in session(one yang
+ * file)
+ */
+ static void checkOnlyOneModulePresent(String moduleName, String globalId) {
+ if (globalId != null)
+ ValidationUtil.ex(ValidationUtil
+ .f("Multiple (sub)modules per file"));
+ }
+
+ static void checkPresentYangVersion(ParseTree ctx, String moduleName) {
+ if (!checkPresentChildOfTypeSafe(ctx, Yang_version_stmtContext.class,
+ true))
+ ValidationUtil
+ .ex(ValidationUtil
+ .f("Yang version statement not present in module:%s, Validating as yang version:%s",
+ moduleName, SUPPORTED_YANG_VERSION));
+ }
+
+ static void checkDateFormat(ParseTree stmt, DateFormat format) {
+ try {
+ format.parse(ValidationUtil.getName(stmt));
+ } catch (ParseException e) {
+ String exceptionMessage = ValidationUtil
+ .f("(In (sub)module:%s) %s:%s, invalid date format expected date format is:%s",
+ ValidationUtil.getRootParentName(stmt),
+ ValidationUtil.getSimpleStatementName(stmt
+ .getClass()), ValidationUtil.getName(stmt),
+ YangModelParserListenerImpl.simpleDateFormat
+ .format(new Date()));
+ ValidationUtil.ex(exceptionMessage);
+ }
+ }
+
+ static Pattern identifierPattern = Pattern
+ .compile("[a-zA-Z_][a-zA-Z0-9_.-]*");
+
+ static void checkIdentifier(ParseTree statement) {
+ checkIdentifierInternal(statement, ValidationUtil.getName(statement));
+ }
+
+ static void checkIdentifierInternal(ParseTree statement, String name) {
+ if (!identifierPattern.matcher(name).matches()) {
+
+ String message = ValidationUtil
+ .f("%s statement identifier:%s is not in required format:%s",
+ ValidationUtil.getSimpleStatementName(statement
+ .getClass()), name, identifierPattern
+ .toString());
+ String parent = ValidationUtil.getRootParentName(statement);
+ message = parent.equals(name) ? message : ValidationUtil.f(
+ "(In (sub)module:%s) %s", parent, message);
+
+ ValidationUtil.ex(message);
+ }
+ }
+
+ static Pattern prefixedIdentifierPattern = Pattern.compile("(.+):(.+)");
+
+ static void checkPrefixedIdentifier(ParseTree statement) {
+ checkPrefixedIdentifierInternal(statement,
+ ValidationUtil.getName(statement));
+ }
+
+ private static void checkPrefixedIdentifierInternal(ParseTree statement,
+ String id) {
+ Matcher matcher = prefixedIdentifierPattern.matcher(id);
+
+ if (matcher.matches()) {
+ try {
+ // check prefix
+ checkIdentifierInternal(statement, matcher.group(1));
+ // check ID
+ checkIdentifierInternal(statement, matcher.group(2));
+ } catch (YangValidationException e) {
+ ValidationUtil.ex(ValidationUtil.f(
+ "Prefixed id:%s not in required format, details:%s",
+ id, e.getMessage()));
+ }
+ } else
+ checkIdentifierInternal(statement, id);
+ }
+
+ static void checkSchemaNodeIdentifier(ParseTree statement) {
+ String id = ValidationUtil.getName(statement);
+
+ try {
+ for (String oneOfId : id.split("/")) {
+ if (oneOfId.isEmpty())
+ continue;
+ checkPrefixedIdentifierInternal(statement, oneOfId);
+ }
+ } catch (YangValidationException e) {
+ ValidationUtil.ex(ValidationUtil.f(
+ "Schema node id:%s not in required format, details:%s", id,
+ e.getMessage()));
+ }
+ }
+
+ private static interface MessageProvider {
+ String getMessage();
+ }
+
+ static void checkPresentChildOfTypeInternal(ParseTree parent,
+ Set<Class<? extends ParseTree>> expectedChildType,
+ MessageProvider message, boolean atMostOne) {
+ if (!checkPresentChildOfTypeSafe(parent, expectedChildType, atMostOne)) {
+ String str = atMostOne ? "(Expected exactly one statement) "
+ + message.getMessage() : message.getMessage();
+ ValidationUtil.ex(str);
+ }
+ }
+
+ static void checkPresentChildOfType(final ParseTree parent,
+ final Class<? extends ParseTree> expectedChildType,
+ boolean atMostOne) {
+
+ // Construct message in checkPresentChildOfTypeInternal only if
+ // validaiton fails, not in advance
+ MessageProvider message = new MessageProvider() {
+
+ @Override
+ public String getMessage() {
+ String message = ValidationUtil
+ .f("Missing %s statement in %s:%s", ValidationUtil
+ .getSimpleStatementName(expectedChildType),
+ ValidationUtil.getSimpleStatementName(parent
+ .getClass()), ValidationUtil
+ .getName(parent));
+
+ String root = ValidationUtil.getRootParentName(parent);
+ message = parent.equals(ValidationUtil
+ .getRootParentName(parent)) ? message : ValidationUtil
+ .f("(In (sub)module:%s) %s", root, message);
+ return message;
+ }
+ };
+
+ Set<Class<? extends ParseTree>> expectedChildTypeSet = Sets
+ .newHashSet();
+ expectedChildTypeSet.add(expectedChildType);
+
+ checkPresentChildOfTypeInternal(parent, expectedChildTypeSet, message,
+ atMostOne);
+ }
+
+ static void checkPresentChildOfTypes(final ParseTree parent,
+ final Set<Class<? extends ParseTree>> expectedChildTypes,
+ boolean atMostOne) {
+
+ // Construct message in checkPresentChildOfTypeInternal only if
+ // validaiton fails, not in advance
+ MessageProvider message = new MessageProvider() {
+
+ @Override
+ public String getMessage() {
+ StringBuilder childTypes = new StringBuilder();
+ String orStr = " OR ";
+ for (Class<? extends ParseTree> type : expectedChildTypes) {
+ childTypes.append(ValidationUtil
+ .getSimpleStatementName(type));
+ childTypes.append(orStr);
+ }
+
+ String message = ValidationUtil
+ .f("Missing %s statement in %s:%s", childTypes
+ .toString(), ValidationUtil
+ .getSimpleStatementName(parent.getClass()),
+ ValidationUtil.getName(parent));
+
+ String root = ValidationUtil.getRootParentName(parent);
+ message = parent.equals(ValidationUtil
+ .getRootParentName(parent)) ? message : ValidationUtil
+ .f("(In (sub)module:%s) %s", root, message);
+
+ return message;
+ }
+ };
+
+ checkPresentChildOfTypeInternal(parent, expectedChildTypes, message,
+ atMostOne);
+ }
+
+ static boolean checkPresentChildOfTypeSafe(ParseTree parent,
+ Set<Class<? extends ParseTree>> expectedChildType, boolean atMostOne) {
+
+ int foundChildrenOfType = ValidationUtil.countPresentChildrenOfType(
+ parent, expectedChildType);
+
+ return atMostOne ? foundChildrenOfType == 1 ? true : false
+ : foundChildrenOfType != 0 ? true : false;
+ }
+
+ static boolean checkPresentChildOfTypeSafe(ParseTree parent,
+ Class<? extends ParseTree> expectedChildType, boolean atMostOne) {
+
+ int foundChildrenOfType = ValidationUtil.countPresentChildrenOfType(
+ parent, expectedChildType);
+
+ return atMostOne ? foundChildrenOfType == 1 ? true : false
+ : foundChildrenOfType != 0 ? true : false;
+ }
+
+ static List<String> getAndCheckUniqueKeys(ParseTree ctx) {
+ String key = ValidationUtil.getName(ctx);
+ ParseTree parent = ctx.getParent();
+ String rootParentName = ValidationUtil.getRootParentName(ctx);
+
+ List<String> keyList = ValidationUtil.listKeysFromId(key);
+ Set<String> duplicates = ValidationUtil.getDuplicates(keyList);
+
+ if (duplicates.size() != 0)
+ ValidationUtil.ex(ValidationUtil.f(
+ "(In (sub)module:%s) %s:%s, %s:%s contains duplicates:%s",
+ rootParentName,
+ ValidationUtil.getSimpleStatementName(parent.getClass()),
+ ValidationUtil.getName(parent),
+ ValidationUtil.getSimpleStatementName(ctx.getClass()), key,
+ duplicates));
+ return keyList;
+ }
+}
--- /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/eplv10.html
+ */
+package org.opendaylight.controller.yang.model.validator;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.antlr.v4.runtime.tree.ParseTree;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Module_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Submodule_stmtContext;
+import org.opendaylight.controller.yang.model.parser.util.YangModelBuilderUtil;
+import org.opendaylight.controller.yang.model.parser.util.YangValidationException;
+
+/**
+ * Validation utilities
+ */
+final class ValidationUtil {
+
+ static void ex(String message) {
+ throw new YangValidationException(message);
+ }
+
+ static Set<String> getDuplicates(Collection<String> keyList) {
+ Set<String> all = new HashSet<String>();
+ Set<String> duplicates = new HashSet<String>();
+
+ for (String key : keyList) {
+ if (!all.add(key))
+ duplicates.add(key);
+ }
+ return duplicates;
+ }
+
+ static List<String> listKeysFromId(String keys) {
+ return Arrays.asList(keys.split(" "));
+ }
+
+ static String getRootParentName(ParseTree ctx) {
+ ParseTree root = getRootParent(ctx);
+ return ValidationUtil.getName(root);
+ }
+
+ private static ParseTree getRootParent(ParseTree ctx) {
+ ParseTree root = ctx;
+ while (root.getParent() != null) {
+ if (root.getClass().equals(Module_stmtContext.class)
+ || root.getClass().equals(Submodule_stmtContext.class))
+ break;
+ root = root.getParent();
+ }
+ return root;
+ }
+
+ static String getName(ParseTree child) {
+ return YangModelBuilderUtil.stringFromNode(child);
+ }
+
+ static String f(String base, Object... args) {
+ return String.format(base, args);
+ }
+
+ /**
+ * Get simple name from statement class e.g. Module from Module_stmt_context
+ */
+ static String getSimpleStatementName(
+ Class<? extends ParseTree> typeOfStatement) {
+
+ String className = typeOfStatement.getSimpleName();
+ int lastIndexOf = className.indexOf('$');
+ className = lastIndexOf == -1 ? className : className
+ .substring(lastIndexOf + 1);
+ int indexOfStmt = className.indexOf("_stmt");
+ int index = indexOfStmt == -1 ? className.indexOf("_arg") : indexOfStmt;
+ return className.substring(0, index).replace('_', '-');
+ }
+
+ static int countPresentChildrenOfType(ParseTree parent,
+ Set<Class<? extends ParseTree>> expectedChildTypes) {
+ int foundChildrenOfType = 0;
+
+ for (Class<? extends ParseTree> type : expectedChildTypes) {
+ foundChildrenOfType += countPresentChildrenOfType(parent, type);
+ }
+ return foundChildrenOfType;
+ }
+
+ static int countPresentChildrenOfType(ParseTree parent,
+ Class<? extends ParseTree> expectedChildType) {
+ int foundChildrenOfType = 0;
+
+ for (int i = 0; i < parent.getChildCount(); i++) {
+ ParseTree child = parent.getChild(i);
+ if (expectedChildType.isInstance(child))
+ foundChildrenOfType++;
+ }
+ return foundChildrenOfType;
+ }
+
+}
--- /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.model.validator;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.Set;
+
+import org.antlr.v4.runtime.tree.ParseTree;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Anyxml_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Argument_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Augment_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Base_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Belongs_to_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Case_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Choice_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Config_argContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Container_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Default_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Deviate_add_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Deviation_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Extension_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Feature_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Grouping_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Identity_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.If_feature_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Import_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Include_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Key_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Leaf_list_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Leaf_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.List_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Mandatory_argContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Mandatory_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Module_header_stmtsContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Module_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Namespace_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Notification_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Ordered_by_argContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Prefix_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Refine_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Revision_date_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Revision_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Rpc_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Status_argContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Submodule_header_stmtsContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Submodule_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Type_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Typedef_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Unique_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Uses_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Yin_element_argContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParserBaseListener;
+import org.opendaylight.controller.yang.model.parser.impl.YangModelParserListenerImpl;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.collect.Sets;
+
+/**
+ * Validation listener that validates yang statements according to RFC-6020.
+ * This validator expects only one module or submodule per file and performs
+ * only basic validation where context from all yang models is not present.
+ */
+final class YangModelBasicValidationListener extends YangParserBaseListener {
+
+ private static final Logger logger = LoggerFactory
+ .getLogger(YangModelBasicValidationListener.class);
+
+ private final Set<String> uniquePrefixes;
+ private final Set<String> uniqueImports;
+ private final Set<String> uniqueIncludes;
+
+ private String globalModuleId;
+
+ YangModelBasicValidationListener() {
+ super();
+ uniquePrefixes = Sets.newHashSet();
+ uniqueImports = Sets.newHashSet();
+ uniqueIncludes = Sets.newHashSet();
+ }
+
+ /**
+ * Constraints:
+ * <ol>
+ * <li>Identifier is in required format</li>
+ * <li>Header statements present(mandatory prefix and namespace statements
+ * are in header)</li>
+ * <li>Only one module or submodule per file</li>
+ * </ol>
+ */
+ @Override
+ public void enterModule_stmt(Module_stmtContext ctx) {
+
+ BasicValidations.checkIdentifier(ctx);
+
+ BasicValidations.checkPresentChildOfType(ctx,
+ Module_header_stmtsContext.class, true);
+
+ String moduleName = ValidationUtil.getName(ctx);
+ BasicValidations.checkOnlyOneModulePresent(moduleName, globalModuleId);
+ globalModuleId = moduleName;
+ }
+
+ /**
+ * Constraints:
+ * <ol>
+ * <li>Identifier is in required format</li>
+ * <li>Header statements present(mandatory belongs-to statement is in
+ * header)</li>
+ * <li>Only one module or submodule per file</li>
+ * </ol>
+ */
+ @Override
+ public void enterSubmodule_stmt(Submodule_stmtContext ctx) {
+
+ BasicValidations.checkIdentifier(ctx);
+
+ BasicValidations.checkPresentChildOfType(ctx,
+ Submodule_header_stmtsContext.class, true);
+
+ String submoduleName = ValidationUtil.getName(ctx);
+ BasicValidations.checkOnlyOneModulePresent(submoduleName,
+ globalModuleId);
+ globalModuleId = submoduleName;
+
+ }
+
+ /**
+ * Constraints:
+ * <ol>
+ * <li>One Belongs-to statement present</li>
+ * </ol>
+ */
+ @Override
+ public void enterSubmodule_header_stmts(Submodule_header_stmtsContext ctx) {
+ BasicValidations.checkPresentChildOfType(ctx,
+ Belongs_to_stmtContext.class, true);
+
+ // check Yang version present, if not log
+ try {
+ BasicValidations.checkPresentYangVersion(ctx,
+ ValidationUtil.getRootParentName(ctx));
+ } catch (Exception e) {
+ logger.debug(e.getMessage());
+ }
+ }
+
+ /**
+ * Constraints:
+ * <ol>
+ * <li>One Namespace statement present</li>
+ * <li>One Prefix statement present</li>
+ * </ol>
+ */
+ @Override
+ public void enterModule_header_stmts(Module_header_stmtsContext ctx) {
+ String moduleName = ValidationUtil.getRootParentName(ctx);
+
+ BasicValidations.checkPresentChildOfType(ctx,
+ Namespace_stmtContext.class, true);
+ BasicValidations.checkPresentChildOfType(ctx, Prefix_stmtContext.class,
+ true);
+
+ // check Yang version present, if not log
+ try {
+ BasicValidations.checkPresentYangVersion(ctx, moduleName);
+ } catch (Exception e) {
+ logger.debug(e.getMessage());
+ }
+ }
+
+ /**
+ * Constraints:
+ * <ol>
+ * <li>Date is in valid format</li>
+ * </ol>
+ */
+ @Override
+ public void enterRevision_stmt(Revision_stmtContext ctx) {
+ BasicValidations.checkDateFormat(ctx,
+ YangModelParserListenerImpl.simpleDateFormat);
+
+ }
+
+ /**
+ * Constraints:
+ * <ol>
+ * <li>Identifier is in required format</li>
+ * <li>One Prefix statement child</li>
+ * </ol>
+ */
+ @Override
+ public void enterBelongs_to_stmt(Belongs_to_stmtContext ctx) {
+ BasicValidations.checkIdentifier(ctx);
+
+ BasicValidations.checkPresentChildOfType(ctx, Prefix_stmtContext.class,
+ true);
+ }
+
+ /**
+ * Constraints:
+ * <ol>
+ * <li>Namespace string can be parsed as URI</li>
+ * </ol>
+ */
+ @Override
+ public void enterNamespace_stmt(Namespace_stmtContext ctx) {
+ String namespaceName = ValidationUtil.getName(ctx);
+ String rootParentName = ValidationUtil.getRootParentName(ctx);
+
+ try {
+ new URI(namespaceName);
+ } catch (URISyntaxException e) {
+ ValidationUtil.ex(ValidationUtil.f(
+ "(In module:%s) Namespace:%s cannot be parsed as URI",
+ rootParentName, namespaceName));
+ }
+ }
+
+ /**
+ * Constraints:
+ * <ol>
+ * <li>Identifier is in required format</li>
+ * <li>Every import(identified by identifier) within a module/submodule is
+ * present only once</li>
+ * <li>One prefix statement child</li>
+ * </ol>
+ */
+ @Override
+ public void enterImport_stmt(Import_stmtContext ctx) {
+
+ BasicValidations.checkIdentifier(ctx);
+
+ BasicValidations.checkUniquenessInNamespace(ctx, uniqueImports);
+
+ BasicValidations.checkPresentChildOfType(ctx, Prefix_stmtContext.class,
+ true);
+
+ }
+
+ /**
+ * Constraints:
+ * <ol>
+ * <li>Date is in valid format</li>
+ * </ol>
+ */
+ @Override
+ public void enterRevision_date_stmt(Revision_date_stmtContext ctx) {
+ BasicValidations.checkDateFormat(ctx,
+ YangModelParserListenerImpl.simpleDateFormat);
+ }
+
+ /**
+ * Constraints:
+ * <ol>
+ * <li>Identifier is in required format</li>
+ * <li>Every include(identified by identifier) within a module/submodule is
+ * present only once</li>
+ * </ol>
+ */
+ @Override
+ public void enterInclude_stmt(Include_stmtContext ctx) {
+
+ BasicValidations.checkIdentifier(ctx);
+
+ BasicValidations.checkUniquenessInNamespace(ctx, uniqueIncludes);
+ }
+
+ /**
+ * Constraints:
+ * <ol>
+ * <li>Yang-version is specified as 1</li>
+ * </ol>
+ */
+ @Override
+ public void enterYang_version_stmt(YangParser.Yang_version_stmtContext ctx) {
+ String version = ValidationUtil.getName(ctx);
+ String rootParentName = ValidationUtil.getRootParentName(ctx);
+ if (!version.equals(BasicValidations.SUPPORTED_YANG_VERSION)) {
+ ValidationUtil
+ .ex(ValidationUtil
+ .f("(In (sub)module:%s) Unsupported yang version:%s, supported version:%s",
+ rootParentName, version,
+ BasicValidations.SUPPORTED_YANG_VERSION));
+ }
+ }
+
+ /**
+ * Constraints:
+ * <ol>
+ * <li>Identifier is in required format</li>
+ * <li>Every prefix(identified by identifier) within a module/submodule is
+ * presented only once</li>
+ * </ol>
+ */
+ @Override
+ public void enterPrefix_stmt(Prefix_stmtContext ctx) {
+
+ BasicValidations.checkIdentifier(ctx);
+
+ BasicValidations.checkUniquenessInNamespace(ctx, uniquePrefixes);
+ }
+
+ /**
+ * Constraints:
+ * <ol>
+ * <li>Identifier is in required format</li>
+ * <li>One type statement child</li>
+ * </ol>
+ */
+ @Override
+ public void enterTypedef_stmt(Typedef_stmtContext ctx) {
+
+ BasicValidations.checkIdentifier(ctx);
+
+ BasicValidations.checkPresentChildOfType(ctx, Type_stmtContext.class,
+ true);
+ }
+
+ /**
+ * Constraints:
+ * <ol>
+ * <li>(Prefix):Identifier is in required format</li>
+ * </ol>
+ */
+ @Override
+ public void enterType_stmt(Type_stmtContext ctx) {
+ BasicValidations.checkPrefixedIdentifier(ctx);
+ }
+
+ /**
+ * Constraints:
+ * <ol>
+ * <li>Identifier is in required format</li>
+ * </ol>
+ */
+ @Override
+ public void enterContainer_stmt(Container_stmtContext ctx) {
+ BasicValidations.checkIdentifier(ctx);
+ }
+
+ /**
+ * Constraints:
+ * <ol>
+ * <li>Identifier is in required format</li>
+ * <li>One type statement child</li>
+ * <li>Default statement must not be present if mandatory statement is</li>
+ * </ol>
+ */
+ @Override
+ public void enterLeaf_stmt(Leaf_stmtContext ctx) {
+ BasicValidations.checkIdentifier(ctx);
+
+ BasicValidations.checkPresentChildOfType(ctx, Type_stmtContext.class,
+ true);
+
+ BasicValidations.checkNotPresentBoth(ctx, Mandatory_stmtContext.class,
+ Default_stmtContext.class);
+ }
+
+ /**
+ * Constraints:
+ * <ol>
+ * <li>Identifier is in required format</li>
+ * <li>One type statement child</li>
+ * </ol>
+ */
+ @Override
+ public void enterLeaf_list_stmt(Leaf_list_stmtContext ctx) {
+
+ BasicValidations.checkIdentifier(ctx);
+
+ BasicValidations.checkPresentChildOfType(ctx, Type_stmtContext.class,
+ true);
+ }
+
+ private static final Set<String> permittedOrderByArgs = Sets.newHashSet(
+ "system", "user");
+
+ /**
+ * Constraints:
+ * <ol>
+ * <li>Value must be one of: system, user</li>
+ * </ol>
+ */
+ @Override
+ public void enterOrdered_by_arg(Ordered_by_argContext ctx) {
+ BasicValidations.checkOnlyPermittedValues(ctx, permittedOrderByArgs);
+ }
+
+ /**
+ * Constraints:
+ * <ol>
+ * <li>Identifier is in required format</li>
+ * </ol>
+ */
+ @Override
+ public void enterList_stmt(List_stmtContext ctx) {
+ BasicValidations.checkIdentifier(ctx);
+ // TODO check: "if config==true then key must be present" could be
+ // performed
+ }
+
+ /**
+ * Constraints:
+ * <ol>
+ * <li>No duplicate keys</li>
+ * </ol>
+ */
+ @Override
+ public void enterKey_stmt(Key_stmtContext ctx) {
+ BasicValidations.getAndCheckUniqueKeys(ctx);
+ }
+
+ /**
+ * Constraints:
+ * <ol>
+ * <liNo duplicate uniques</li>
+ * </ol>
+ */
+ @Override
+ public void enterUnique_stmt(Unique_stmtContext ctx) {
+ BasicValidations.getAndCheckUniqueKeys(ctx);
+ }
+
+ /**
+ * Constraints:
+ * <ol>
+ * <li>Identifier is in required format</li>
+ * <li>Default statement must not be present if mandatory statement is</li>
+ * </ol>
+ */
+ @Override
+ public void enterChoice_stmt(Choice_stmtContext ctx) {
+ BasicValidations.checkIdentifier(ctx);
+
+ BasicValidations.checkNotPresentBoth(ctx, Mandatory_stmtContext.class,
+ Default_stmtContext.class);
+
+ }
+
+ /**
+ * Constraints:
+ * <ol>
+ * <li>Identifier is in required format</li>
+ * </ol>
+ */
+ @Override
+ public void enterCase_stmt(Case_stmtContext ctx) {
+ BasicValidations.checkIdentifier(ctx);
+ }
+
+ private static final Set<String> permittedBooleanArgs = Sets.newHashSet(
+ "true", "false");
+
+ /**
+ * Constraints:
+ * <ol>
+ * <li>Value must be one of: true, false</li>
+ * </ol>
+ */
+ @Override
+ public void enterMandatory_arg(Mandatory_argContext ctx) {
+ BasicValidations.checkOnlyPermittedValues(ctx, permittedBooleanArgs);
+ }
+
+ /**
+ * Constraints:
+ * <ol>
+ * <li>Identifier is in required format</li>
+ * </ol>
+ */
+ @Override
+ public void enterAnyxml_stmt(Anyxml_stmtContext ctx) {
+ BasicValidations.checkIdentifier(ctx);
+ }
+
+ /**
+ * Constraints:
+ * <ol>
+ * <li>Identifier is in required format</li>
+ * </ol>
+ */
+ @Override
+ public void enterGrouping_stmt(Grouping_stmtContext ctx) {
+ BasicValidations.checkIdentifier(ctx);
+ }
+
+ /**
+ * Constraints:
+ * <ol>
+ * <li>(Prefix):Identifier is in required format</li>
+ * </ol>
+ */
+ @Override
+ public void enterUses_stmt(Uses_stmtContext ctx) {
+ BasicValidations.checkPrefixedIdentifier(ctx);
+ }
+
+ /**
+ * Constraints:
+ * <ol>
+ * <li>Identifier is in required format</li>
+ * </ol>
+ */
+ @Override
+ public void enterRefine_stmt(Refine_stmtContext ctx) {
+ BasicValidations.checkIdentifier(ctx);
+ }
+
+ /**
+ * Constraints:
+ * <ol>
+ * <li>Identifier is in required format</li>
+ * </ol>
+ */
+ @Override
+ public void enterRpc_stmt(Rpc_stmtContext ctx) {
+ BasicValidations.checkIdentifier(ctx);
+ }
+
+ /**
+ * Constraints:
+ * <ol>
+ * <li>Identifier is in required format</li>
+ * </ol>
+ */
+ @Override
+ public void enterNotification_stmt(Notification_stmtContext ctx) {
+ BasicValidations.checkIdentifier(ctx);
+ }
+
+ /**
+ * Constraints:
+ * <ol>
+ * <li>Schema Node Identifier is in required format</li>
+ * </ol>
+ */
+ @Override
+ public void enterAugment_stmt(Augment_stmtContext ctx) {
+ BasicValidations.checkSchemaNodeIdentifier(ctx);
+ }
+
+ /**
+ * Constraints:
+ * <ol>
+ * <li>Identifier is in required format</li>
+ * </ol>
+ */
+ @Override
+ public void enterIdentity_stmt(Identity_stmtContext ctx) {
+ BasicValidations.checkIdentifier(ctx);
+ }
+
+ /**
+ * Constraints:
+ * <ol>
+ * <li>(Prefix):Identifier is in required format</li>
+ * </ol>
+ */
+ @Override
+ public void enterBase_stmt(Base_stmtContext ctx) {
+ BasicValidations.checkPrefixedIdentifier(ctx);
+
+ }
+
+ /**
+ * Constraints:
+ * <ol>
+ * <li>Value must be one of: true, false</li>
+ * </ol>
+ */
+ @Override
+ public void enterYin_element_arg(Yin_element_argContext ctx) {
+ BasicValidations.checkOnlyPermittedValues(ctx, permittedBooleanArgs);
+ }
+
+ /**
+ * Constraints:
+ * <ol>
+ * <li>Identifier is in required format</li>
+ * </ol>
+ */
+ @Override
+ public void enterExtension_stmt(Extension_stmtContext ctx) {
+ BasicValidations.checkIdentifier(ctx);
+ }
+
+ /**
+ * Constraints:
+ * <ol>
+ * <li>Identifier is in required format</li>
+ * </ol>
+ */
+ @Override
+ public void enterArgument_stmt(Argument_stmtContext ctx) {
+ BasicValidations.checkIdentifier(ctx);
+ }
+
+ /**
+ * Constraints:
+ * <ol>
+ * <li>Identifier is in required format</li>
+ * </ol>
+ */
+ @Override
+ public void enterFeature_stmt(Feature_stmtContext ctx) {
+ BasicValidations.checkIdentifier(ctx);
+
+ }
+
+ /**
+ * Constraints:
+ * <ol>
+ * <li>(Prefix):Identifier is in required format</li>
+ * </ol>
+ */
+ @Override
+ public void enterIf_feature_stmt(If_feature_stmtContext ctx) {
+ BasicValidations.checkPrefixedIdentifier(ctx);
+ }
+
+ /**
+ * Constraints:
+ * <ol>
+ * <li>Schema Node Identifier is in required format</li>
+ * <li>At least one deviate-* statement child</li>
+ * </ol>
+ */
+ @Override
+ public void enterDeviation_stmt(Deviation_stmtContext ctx) {
+ BasicValidations.checkSchemaNodeIdentifier(ctx);
+
+ Set<Class<? extends ParseTree>> types = Sets.newHashSet();
+ types.add(Deviate_add_stmtContext.class);
+ types.add(Deviate_add_stmtContext.class);
+ BasicValidations.checkPresentChildOfTypes(ctx, types, false);
+ }
+
+ /**
+ * Constraints:
+ * <ol>
+ * <li>Value must be one of: true, false</li>
+ * </ol>
+ */
+ @Override
+ public void enterConfig_arg(Config_argContext ctx) {
+ BasicValidations.checkOnlyPermittedValues(ctx, permittedBooleanArgs);
+ }
+
+ private static final Set<String> permittedStatusArgs = Sets.newHashSet(
+ "current", "deprecated", "obsolete");
+
+ /**
+ * Constraints:
+ * <ol>
+ * <li>Value must be one of: "current", "deprecated", "obsolete"</li>
+ * </ol>
+ */
+ @Override
+ public void enterStatus_arg(Status_argContext ctx) {
+ BasicValidations.checkOnlyPermittedValues(ctx, permittedStatusArgs);
+ }
+
+}
--- /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.model.validator;
+
+import java.util.List;
+
+import org.antlr.v4.runtime.tree.ParseTree;
+import org.antlr.v4.runtime.tree.ParseTreeWalker;
+import org.opendaylight.controller.yang.model.parser.util.YangValidationException;
+
+/**
+ * Exposed basic yang validation.
+ *
+ * Every file is validated using {@link YangModelBasicValidationListener}.
+ */
+public final class YangModelBasicValidator {
+
+ private final ParseTreeWalker walker;
+
+ public YangModelBasicValidator(ParseTreeWalker walker) {
+ this.walker = walker;
+ }
+
+ public YangModelBasicValidator() {
+ this.walker = new ParseTreeWalker();
+ }
+
+ public void validate(List<ParseTree> trees) {
+ for (int i = 0; i < trees.size(); i++) {
+ try {
+ final YangModelBasicValidationListener yangModelParser = new YangModelBasicValidationListener();
+ walker.walk(yangModelParser, trees.get(i));
+ } catch (YangValidationException e) {
+ // wrap exception to add information about which file failed
+ throw new YangValidationException(
+ "Yang validation failed for file" + e);
+ }
+ }
+ }
+
+}
LeafSchemaNode ifIndex = (LeafSchemaNode) ifEntry
.getDataChildByName("ifIndex");
- assertEquals(new Uint32(), ifIndex.getType());
+ assertTrue(ifIndex.getType() instanceof Uint32);
LeafSchemaNode ifMtu = (LeafSchemaNode) ifEntry
.getDataChildByName("ifMtu");
- assertEquals(new Int32(), ifMtu.getType());
+ assertTrue(ifMtu.getType() instanceof Int32);
}
@Test
assertNotNull(output.getDataChildByName("data"));
}
- @Test
- public void test() {
- Module testModule = TestUtils.findModule(modules, "types4");
-
- boolean flag = false;
- }
-
}
+++ /dev/null
-package org.opendaylight.controller.yang.model.parser.impl;
-
-import static org.hamcrest.core.Is.*;
-import static org.junit.Assert.*;
-import static org.junit.matchers.JUnitMatchers.*;
-import static org.mockito.Mockito.*;
-
-import java.util.Date;
-
-import org.antlr.v4.runtime.tree.ParseTree;
-import org.junit.Before;
-import org.junit.Test;
-import org.opendaylight.controller.antlrv4.code.gen.YangParser.Import_stmtContext;
-import org.opendaylight.controller.antlrv4.code.gen.YangParser.Include_stmtContext;
-import org.opendaylight.controller.antlrv4.code.gen.YangParser.Module_header_stmtsContext;
-import org.opendaylight.controller.antlrv4.code.gen.YangParser.Module_stmtContext;
-import org.opendaylight.controller.antlrv4.code.gen.YangParser.Namespace_stmtContext;
-import org.opendaylight.controller.antlrv4.code.gen.YangParser.Prefix_stmtContext;
-import org.opendaylight.controller.antlrv4.code.gen.YangParser.Revision_date_stmtContext;
-import org.opendaylight.controller.antlrv4.code.gen.YangParser.Revision_stmtContext;
-import org.opendaylight.controller.antlrv4.code.gen.YangParser.Revision_stmtsContext;
-import org.opendaylight.controller.antlrv4.code.gen.YangParser.StringContext;
-import org.opendaylight.controller.antlrv4.code.gen.YangParser.Yang_version_stmtContext;
-
-public class YangModelValidationListenerTest_Module {
-
- private YangModelValidationListener valid;
- private Module_stmtContext ctx;
-
- @Before
- public void setUp() {
- valid = new YangModelValidationListener();
- }
-
- @Test(expected = YangValidationException.class)
- public void testRevisionInvalidDateFormat() {
- Revision_stmtContext mockedRev = mockModuleWithRevision(2, "badFormat");
-
- try {
- valid.enterRevision_stmt(mockedRev);
- } catch (YangValidationException e) {
- assertThat(
- e.getMessage(),
- containsString("Invalid date format for revision:badFormat in (sub)module:module1, expected date format is:"));
- throw e;
- }
- }
-
- private Revision_stmtContext mockModuleWithRevision(int moduleChildren,
- String date) {
- Revision_stmtContext mockedRev = mock(Revision_stmtContext.class);
- doReturn(1).when(mockedRev).getChildCount();
- mockName(mockedRev, date);
-
- Revision_stmtsContext revs = mockRevisionsParent(2, mockedRev);
-
- mockModuleParent(moduleChildren, revs, "module1");
- return mockedRev;
- }
-
- @Test
- public void testRevisionValidDateFormat() {
- Revision_stmtContext mockedRev = mockModuleWithRevision(2,
- getFormattedDate());
-
- valid.enterRevision_stmt(mockedRev);
- }
-
- private String getFormattedDate() {
- return YangModelParserListenerImpl.simpleDateFormat.format(new Date());
- }
-
- @Test(expected = YangValidationException.class)
- public void testNoRevision() {
-
- Module_stmtContext ctx = mock(Module_stmtContext.class);
- doReturn(1).when(ctx).getChildCount();
- mockName(ctx, "module1");
-
- try {
- valid.enterModule_stmt(ctx);
- } catch (YangValidationException e) {
- assertThat(
- e.getMessage(),
- containsString("Missing revision statements in module:module1"));
- throw e;
- }
- }
-
- @Test(expected = YangValidationException.class)
- public void testNoHeaderStmts() {
- mockModuleWithRevision(2, "1999-4-5");
-
- try {
- valid.enterModule_stmt(ctx);
- } catch (YangValidationException e) {
- assertThat(
- e.getMessage(),
- containsString("Missing header statements in module:module1"));
- throw e;
- }
- }
-
- @Test(expected = YangValidationException.class)
- public void testNoNamespace() {
- Module_header_stmtsContext header = mock(Module_header_stmtsContext.class);
- mockModuleParent(2, header, "module1");
-
- try {
- valid.enterModule_header_stmts(header);
- } catch (YangValidationException e) {
- assertThat(
- e.getMessage(),
- containsString("Missing namespace statement in module:module1"));
- throw e;
- }
- }
-
- @Test
- public void testPrefixes() {
- Prefix_stmtContext pref = mock(Prefix_stmtContext.class);
- doReturn(1).when(pref).getChildCount();
- mockName(pref, "unique1");
- mockModuleParent(2, pref, "module1");
- valid.enterPrefix_stmt(pref);
-
- pref = mock(Prefix_stmtContext.class);
- doReturn(1).when(pref).getChildCount();
- mockName(pref, "unique1");
- mockModuleParent(2, pref, "module1");
-
- try {
- valid.enterPrefix_stmt(pref);
- } catch (Exception e) {
- return;
- }
-
- fail("Validation Exception should have occured");
- }
-
- @Test
- public void testNamespace() {
- Namespace_stmtContext namespace = mock(Namespace_stmtContext.class);
- doReturn(1).when(namespace).getChildCount();
- mockName(namespace, "http://test.parsing.uri.com");
- mockModuleParent(2, namespace, "module1");
- valid.enterNamespace_stmt(namespace);
-
- namespace = mock(Namespace_stmtContext.class);
- doReturn(1).when(namespace).getChildCount();
- mockName(namespace, "invalid uri");
- mockModuleParent(2, namespace, "module1");
- try {
- valid.enterNamespace_stmt(namespace);
- } catch (YangValidationException e) {
- assertThat(
- e.getMessage(),
- containsString("Namespace:invalid uri in module:module1 cannot be parsed as URI"));
- return;
- }
-
- fail("Validation Exception should have occured");
- }
-
- @Test
- public void testImports() {
- Import_stmtContext impor = mockImport("unique1", "p1");
- mockModuleParent(2, impor, "module1");
- valid.enterImport_stmt(impor);
-
- impor = mockImport("unique1", "p2");
- mockModuleParent(2, impor, "module1");
- mockName(impor, "unique1");
-
- try {
- valid.enterImport_stmt(impor);
- } catch (YangValidationException e) {
- assertThat(
- e.getMessage(),
- containsString("Module:unique1 imported twice in (sub)module:module1"));
- return;
- }
-
- fail("Validation Exception should have occured");
- }
-
- @Test
- public void testIncludes() {
- Include_stmtContext impor = mockInclude("unique1");
- mockModuleParent(2, impor, "module1");
- valid.enterInclude_stmt(impor);
-
- impor = mockInclude("unique1");
- mockModuleParent(2, impor, "module1");
- mockName(impor, "unique1");
-
- try {
- valid.enterInclude_stmt(impor);
- } catch (YangValidationException e) {
- assertThat(
- e.getMessage(),
- containsString("Submodule:unique1 included twice in (sub)module:module1"));
- return;
- }
-
- fail("Validation Exception should have occured");
- }
-
- private Import_stmtContext mockImport(String name, String prefixName) {
- Import_stmtContext impor = mock(Import_stmtContext.class);
- doReturn(3).when(impor).getChildCount();
- Prefix_stmtContext prefix = mock(Prefix_stmtContext.class);
- mockName(prefix, prefixName);
- doReturn(prefix).when(impor).getChild(1);
- Revision_date_stmtContext revDate = mock(Revision_date_stmtContext.class);
- mockName(revDate, getFormattedDate());
- doReturn(revDate).when(impor).getChild(2);
- mockName(impor, name);
- return impor;
- }
-
- private Include_stmtContext mockInclude(String name) {
- Include_stmtContext impor = mock(Include_stmtContext.class);
- doReturn(2).when(impor).getChildCount();
- Revision_date_stmtContext revDate = mock(Revision_date_stmtContext.class);
- mockName(revDate, getFormattedDate());
- doReturn(revDate).when(impor).getChild(1);
- mockName(impor, name);
- return impor;
- }
-
- @Test(expected = YangValidationException.class)
- public void testInvalidYangVersion() {
-
- Yang_version_stmtContext yangVersion = mock(Yang_version_stmtContext.class);
- doReturn(1).when(yangVersion).getChildCount();
- mockName(yangVersion, "55Unsup");
-
- mockModuleParent(2, yangVersion, "module1");
-
- try {
- valid.enterYang_version_stmt(yangVersion);
- } catch (YangValidationException e) {
- assertThat(
- e.getMessage(),
- containsString("Unsupported yang version:55Unsup, in (sub)module:module1, supported version:"
- + YangModelValidationListener.SUPPORTED_YANG_VERSION));
- throw e;
- }
- }
-
- private void mockModuleParent(int moduleChildren, ParseTree child,
- String moduleName) {
- ctx = mock(Module_stmtContext.class);
- doReturn(moduleChildren).when(ctx).getChildCount();
- mockName(ctx, moduleName);
- doReturn(child).when(ctx).getChild(1);
- doReturn(ctx).when(child).getParent();
- }
-
- static Revision_stmtsContext mockRevisionsParent(int moduleChildren,
- Revision_stmtContext mockedRev) {
- Revision_stmtsContext revs = mock(Revision_stmtsContext.class);
- doReturn(moduleChildren).when(revs).getChildCount();
- doReturn(mockedRev).when(revs).getChild(1);
- doReturn(revs).when(mockedRev).getParent();
- return revs;
- }
-
- @Test
- public void testValidYangVersion() {
-
- Yang_version_stmtContext ctx = mock(Yang_version_stmtContext.class);
- doReturn(1).when(ctx).getChildCount();
- mockName(ctx, "1");
-
- valid.enterYang_version_stmt(ctx);
- }
-
- @Test
- public void testIdentifierMatching() {
- YangModelValidationListener.checkIdentifier("_ok98-.87.-.8...88-asdAD",
- null);
- YangModelValidationListener.checkIdentifier("AA.bcd", null);
- YangModelValidationListener.checkIdentifier("a", null);
-
- int thrown = 0;
-
- try {
- YangModelValidationListener.checkIdentifier("9aa", null);
- } catch (YangValidationException e) {
- thrown++;
- }
- try {
- YangModelValidationListener.checkIdentifier("-", null);
- } catch (YangValidationException e) {
- thrown++;
- }
- try {
- YangModelValidationListener.checkIdentifier(".", null);
- } catch (YangValidationException e) {
- thrown++;
- }
-
- assertThat(thrown, is(3));
- }
-
- static void mockName(ParseTree mockedRev, String name) {
- StringContext nameCtx = mock(StringContext.class);
- ParseTree internalName = mock(ParseTree.class);
- doReturn(name).when(internalName).getText();
- doReturn(internalName).when(nameCtx).getChild(0);
- doReturn(nameCtx).when(mockedRev).getChild(0);
- }
-}
+++ /dev/null
-package org.opendaylight.controller.yang.model.parser.impl;
-
-import static org.junit.Assert.*;
-import static org.junit.matchers.JUnitMatchers.*;
-import static org.mockito.Mockito.*;
-
-import org.antlr.v4.runtime.tree.ParseTree;
-import org.junit.Before;
-import org.junit.Test;
-import org.opendaylight.controller.antlrv4.code.gen.YangParser.Belongs_to_stmtContext;
-import org.opendaylight.controller.antlrv4.code.gen.YangParser.Prefix_stmtContext;
-import org.opendaylight.controller.antlrv4.code.gen.YangParser.Revision_stmtContext;
-import org.opendaylight.controller.antlrv4.code.gen.YangParser.Revision_stmtsContext;
-import org.opendaylight.controller.antlrv4.code.gen.YangParser.Submodule_header_stmtsContext;
-import org.opendaylight.controller.antlrv4.code.gen.YangParser.Submodule_stmtContext;
-
-public class YangModelValidationListenerTest_SubModule {
-
- private YangModelValidationListener valid;
- private Submodule_stmtContext ctx;
-
- @Before
- public void setUp() {
- valid = new YangModelValidationListener();
- }
-
- @Test(expected = YangValidationException.class)
- public void testNoRevision() {
-
- Submodule_stmtContext ctx = mock(Submodule_stmtContext.class);
- doReturn(1).when(ctx).getChildCount();
- YangModelValidationListenerTest_Module.mockName(ctx, "submodule1");
-
- try {
- valid.enterSubmodule_stmt(ctx);
- } catch (YangValidationException e) {
- assertThat(
- e.getMessage(),
- containsString("Missing revision statements in submodule:submodule1"));
- throw e;
- }
- }
-
- @Test(expected = YangValidationException.class)
- public void testNoHeaderStmts() {
- mockSubmoduleWithRevision(2, "1999-4-5", "submodule");
-
- try {
- valid.enterSubmodule_stmt(ctx);
- } catch (YangValidationException e) {
- assertThat(
- e.getMessage(),
- containsString("Missing header statements in submodule:submodule"));
- throw e;
- }
- }
-
- @Test(expected = YangValidationException.class)
- public void testNoBelongsTo() {
- Submodule_header_stmtsContext header = mock(Submodule_header_stmtsContext.class);
- mockSubmoduleParent(2, header, "submodule");
-
- try {
- valid.enterSubmodule_header_stmts(header);
- } catch (YangValidationException e) {
- assertThat(
- e.getMessage(),
- containsString("Missing belongs-to statement in submodule:submodule"));
- throw e;
- }
- }
-
- @Test(expected = YangValidationException.class)
- public void testBelongsToNoPrefix() {
- Belongs_to_stmtContext belongsTo = mock(Belongs_to_stmtContext.class);
- doReturn(1).when(belongsTo).getChildCount();
- YangModelValidationListenerTest_Module.mockName(belongsTo,
- "supermodule");
-
- mockSubmoduleParent(2, belongsTo, "submodule");
-
- try {
- valid.enterBelongs_to_stmt(belongsTo);
- } catch (YangValidationException e) {
- assertThat(
- e.getMessage(),
- containsString("Missing prefix statement in belongs-to:supermodule, in (sub)module:submodule"));
- throw e;
- }
- }
-
- @Test
- public void testBelongsTo() {
- Belongs_to_stmtContext belongsTo = mock(Belongs_to_stmtContext.class);
- doReturn(2).when(belongsTo).getChildCount();
- YangModelValidationListenerTest_Module.mockName(belongsTo,
- "supermodule");
-
- Prefix_stmtContext prefix = mock(Prefix_stmtContext.class);
- doReturn(prefix).when(belongsTo).getChild(1);
- doReturn(belongsTo).when(prefix).getParent();
-
- mockSubmoduleParent(2, belongsTo, "submodule");
- valid.enterBelongs_to_stmt(belongsTo);
-
- }
-
- private Revision_stmtContext mockSubmoduleWithRevision(int moduleChildren,
- String date, String nameOfSubmodule) {
- Revision_stmtContext mockedRev = mock(Revision_stmtContext.class);
- doReturn(1).when(mockedRev).getChildCount();
- YangModelValidationListenerTest_Module.mockName(mockedRev, date);
-
- Revision_stmtsContext revs = YangModelValidationListenerTest_Module
- .mockRevisionsParent(2, mockedRev);
-
- mockSubmoduleParent(moduleChildren, revs, nameOfSubmodule);
- return mockedRev;
- }
-
- private void mockSubmoduleParent(int moduleChildren, ParseTree child,
- String moduleName) {
- ctx = mock(Submodule_stmtContext.class);
- doReturn(moduleChildren).when(ctx).getChildCount();
- YangModelValidationListenerTest_Module.mockName(ctx, moduleName);
- doReturn(child).when(ctx).getChild(1);
- doReturn(ctx).when(child).getParent();
- }
-}
--- /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.model.validator;
+
+import static org.junit.Assert.*;
+import static org.junit.matchers.JUnitMatchers.*;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Default_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Key_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Leaf_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.List_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Mandatory_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Ordered_by_argContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Type_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Unique_stmtContext;
+import org.opendaylight.controller.yang.model.parser.util.YangValidationException;
+
+public class YangModelValidationListTest {
+
+ private YangModelBasicValidationListener valid;
+
+ @Before
+ public void setUp() {
+ valid = new YangModelBasicValidationListener();
+ }
+
+ @Test(expected = YangValidationException.class)
+ public void testKeyValidationDuplicates() {
+
+ List_stmtContext list = YangModelValidationTest.mockStatement(
+ List_stmtContext.class, "list");
+ Key_stmtContext key = YangModelValidationTest.mockStatement(
+ Key_stmtContext.class, "leaf1 leaf2 leaf1 leaf1");
+ YangModelValidationTest.addChild(list, key);
+
+ try {
+ valid.enterKey_stmt(key);
+ } catch (YangValidationException e) {
+ assertThat(e.getMessage(),
+ containsString("contains duplicates:[leaf1]"));
+ throw e;
+ }
+ }
+
+ @Test(expected = YangValidationException.class)
+ public void testUniqueValidationDuplicates() {
+ List_stmtContext list = YangModelValidationTest.mockStatement(
+ List_stmtContext.class, "list");
+ Unique_stmtContext unique = YangModelValidationTest.mockStatement(
+ Unique_stmtContext.class, "leaf1/a leaf2/n leaf1/a leaf1");
+ YangModelValidationTest.addChild(list, unique);
+
+ try {
+ valid.enterUnique_stmt(unique);
+ } catch (YangValidationException e) {
+ assertThat(e.getMessage(),
+ containsString("contains duplicates:[leaf1/a]"));
+ throw e;
+ }
+ }
+
+ @Test(expected = YangValidationException.class)
+ public void testOrderBy() {
+ Ordered_by_argContext ctx = YangModelValidationTest.mockStatement(
+ Ordered_by_argContext.class, "unknown");
+
+ try {
+ valid.enterOrdered_by_arg(ctx);
+ } catch (YangValidationException e) {
+ assertThat(
+ e.getMessage(),
+ containsString("Ordered-by:unknown, illegal value for Ordered-by statement, only permitted:"));
+ throw e;
+ }
+ }
+
+ @Test(expected = YangValidationException.class)
+ public void testLeaf() {
+ Leaf_stmtContext ctx = YangModelValidationTest.mockStatement(
+ Leaf_stmtContext.class, "leaf1");
+ Default_stmtContext def = YangModelValidationTest.mockStatement(
+ Default_stmtContext.class, "default");
+ YangModelValidationTest.addChild(ctx, def);
+ Type_stmtContext typ = YangModelValidationTest.mockStatement(
+ Type_stmtContext.class, "type");
+ YangModelValidationTest.addChild(ctx, def);
+ YangModelValidationTest.addChild(ctx, typ);
+
+ Mandatory_stmtContext mand = YangModelValidationTest.mockStatement(
+ Mandatory_stmtContext.class, null);
+ YangModelValidationTest.addChild(ctx, mand);
+
+ try {
+ valid.enterLeaf_stmt(ctx);
+ } catch (YangValidationException e) {
+ assertThat(
+ e.getMessage(),
+ containsString("Both Mandatory and Default statement present"));
+ throw e;
+ }
+ }
+
+}
--- /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.model.validator;
+
+import static org.junit.Assert.*;
+import static org.junit.matchers.JUnitMatchers.*;
+import static org.mockito.Mockito.*;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Module_header_stmtsContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Module_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Namespace_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Revision_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Revision_stmtsContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Yang_version_stmtContext;
+import org.opendaylight.controller.yang.model.parser.util.YangValidationException;
+
+public class YangModelValidationModuleTest {
+
+ private YangModelBasicValidationListener valid;
+
+ @Before
+ public void setUp() {
+ valid = new YangModelBasicValidationListener();
+ }
+
+ @Test(expected = YangValidationException.class)
+ public void testRevisionInvalidDateFormat() {
+ Revision_stmtContext mockedRev = mockModuleWithRevision("badFormat",
+ "module1");
+
+ try {
+ valid.enterRevision_stmt(mockedRev);
+ } catch (YangValidationException e) {
+ assertThat(
+ e.getMessage(),
+ containsString("Revision:badFormat, invalid date format expected date format is:"));
+ throw e;
+ }
+ }
+
+ @Test
+ public void testRevisionValidDateFormat() {
+ Revision_stmtContext mockedRev = mockModuleWithRevision(
+ YangModelValidationTest.getFormattedDate(), "module1");
+
+ valid.enterRevision_stmt(mockedRev);
+ }
+
+ @Test(expected = YangValidationException.class)
+ public void testNoHeaderStmts() {
+ Revision_stmtContext rev = mockModuleWithRevision("1999-4-5", "module1");
+
+ try {
+ valid.enterModule_stmt((Module_stmtContext) rev.getParent()
+ .getParent());
+ } catch (YangValidationException e) {
+ assertThat(
+ e.getMessage(),
+ containsString("Missing Module-header statement in Module:module1"));
+ throw e;
+ }
+ }
+
+ @Test(expected = YangValidationException.class)
+ public void testMultipleModulesPerSession() {
+ Module_stmtContext module1 = (Module_stmtContext) mockModuleWithRevision(
+ "1999-09-10", "m1").getParent().getParent();
+ YangModelValidationTest.addChild(module1, YangModelValidationTest
+ .mockStatement(Namespace_stmtContext.class, ""));
+
+ Module_stmtContext module2 = (Module_stmtContext) mockModuleWithRevision(
+ "1999-09-10", "m2").getParent().getParent();
+ YangModelValidationTest.addChild(module1, YangModelValidationTest
+ .mockStatement(Namespace_stmtContext.class, ""));
+ valid.enterModule_stmt(module1);
+
+ try {
+ valid.enterModule_stmt(module2);
+ } catch (YangValidationException e) {
+ assertThat(e.getMessage(),
+ containsString("Multiple (sub)modules per file"));
+ throw e;
+ }
+ }
+
+ @Test(expected = YangValidationException.class)
+ public void testNoNamespace() {
+ Module_header_stmtsContext header = YangModelValidationTest
+ .mockStatement(Module_header_stmtsContext.class, null);
+ Module_stmtContext mod = YangModelValidationTest.mockStatement(
+ Module_stmtContext.class, "module1");
+ YangModelValidationTest.addChild(mod, header);
+
+ try {
+ valid.enterModule_header_stmts(header);
+ } catch (YangValidationException e) {
+ assertThat(
+ e.getMessage(),
+ containsString("Missing Namespace statement in Module-header:"));
+ throw e;
+ }
+ }
+
+ @Test(expected = YangValidationException.class)
+ public void testNoPrefix() {
+ Module_header_stmtsContext header = YangModelValidationTest
+ .mockStatement(Module_header_stmtsContext.class, null);
+ Namespace_stmtContext nmspc = YangModelValidationTest.mockStatement(
+ Namespace_stmtContext.class, "http://test");
+ Module_stmtContext mod = YangModelValidationTest.mockStatement(
+ Module_stmtContext.class, "module1");
+ YangModelValidationTest.addChild(mod, header);
+ YangModelValidationTest.addChild(header, nmspc);
+
+ try {
+ valid.enterModule_header_stmts(header);
+ } catch (YangValidationException e) {
+ assertThat(
+ e.getMessage(),
+ containsString("Missing Prefix statement in Module-header:"));
+ throw e;
+ }
+ }
+
+ @Test(expected = YangValidationException.class)
+ public void testInvalidYangVersion() {
+
+ Yang_version_stmtContext yangVersion = YangModelValidationTest
+ .mockStatement(Yang_version_stmtContext.class, "55Unsup");
+
+ Module_stmtContext mod = YangModelValidationTest.mockStatement(
+ Module_stmtContext.class, "module1");
+ YangModelValidationTest.addChild(mod, yangVersion);
+
+ try {
+ valid.enterYang_version_stmt(yangVersion);
+ } catch (YangValidationException e) {
+ assertThat(
+ e.getMessage(),
+ containsString("Unsupported yang version:55Unsup, supported version:"
+ + BasicValidations.SUPPORTED_YANG_VERSION));
+ throw e;
+ }
+ }
+
+ @Test
+ public void testValidYangVersion() {
+
+ Yang_version_stmtContext ctx = mock(Yang_version_stmtContext.class);
+ doReturn(1).when(ctx).getChildCount();
+ YangModelValidationTest.mockName(ctx, "1");
+
+ valid.enterYang_version_stmt(ctx);
+ }
+
+ private static Revision_stmtContext mockModuleWithRevision(String date,
+ String moduleName) {
+ Revision_stmtContext mockedRev = YangModelValidationTest.mockStatement(
+ Revision_stmtContext.class, date);
+ Revision_stmtsContext revs = YangModelValidationTest.mockStatement(
+ Revision_stmtsContext.class, null);
+ Module_stmtContext mod = YangModelValidationTest.mockStatement(
+ Module_stmtContext.class, moduleName);
+
+ YangModelValidationTest.addChild(revs, mockedRev);
+ YangModelValidationTest.addChild(mod, revs);
+ return mockedRev;
+ }
+}
--- /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.model.validator;
+
+import static org.junit.Assert.*;
+import static org.junit.matchers.JUnitMatchers.*;
+import static org.mockito.Mockito.*;
+
+import org.antlr.v4.runtime.tree.ParseTree;
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Belongs_to_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Submodule_header_stmtsContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Submodule_stmtContext;
+import org.opendaylight.controller.yang.model.parser.util.YangValidationException;
+
+public class YangModelValidationSubModuleTest {
+
+ private YangModelBasicValidationListener valid;
+
+ @Before
+ public void setUp() {
+ valid = new YangModelBasicValidationListener();
+ }
+
+ @Test(expected = YangValidationException.class)
+ public void testNoRevision() {
+
+ Submodule_stmtContext ctx = YangModelValidationTest.mockStatement(
+ Submodule_stmtContext.class, "submodule1");
+
+ try {
+ valid.enterSubmodule_stmt(ctx);
+ } catch (YangValidationException e) {
+ assertThat(
+ e.getMessage(),
+ containsString("Missing Submodule-header statement in Submodule:submodule"));
+ throw e;
+ }
+ }
+
+ @Test(expected = YangValidationException.class)
+ public void testNoBelongsTo() {
+ Submodule_header_stmtsContext header = mock(Submodule_header_stmtsContext.class);
+ mockSubmoduleParent(header, "submodule");
+
+ try {
+ valid.enterSubmodule_header_stmts(header);
+ } catch (YangValidationException e) {
+ assertThat(
+ e.getMessage(),
+ containsString("Missing Belongs-to statement in Submodule-header:"));
+ throw e;
+ }
+ }
+
+ @Test(expected = YangValidationException.class)
+ public void testBelongsToNoPrefix() {
+ Belongs_to_stmtContext belongsTo = YangModelValidationTest
+ .mockStatement(Belongs_to_stmtContext.class, "supermodule");
+
+ mockSubmoduleParent(belongsTo, "submodule");
+
+ try {
+ valid.enterBelongs_to_stmt(belongsTo);
+ } catch (YangValidationException e) {
+ assertThat(
+ e.getMessage(),
+ containsString("Missing Prefix statement in Belongs-to:supermodule"));
+ throw e;
+ }
+ }
+
+ private Submodule_stmtContext mockSubmoduleParent(ParseTree child,
+ String moduleName) {
+ Submodule_stmtContext ctx = YangModelValidationTest.mockStatement(
+ Submodule_stmtContext.class, moduleName);
+ YangModelValidationTest.addChild(ctx, child);
+ return ctx;
+ }
+}
--- /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.model.validator;
+
+import static org.hamcrest.core.Is.*;
+import static org.junit.Assert.*;
+import static org.junit.matchers.JUnitMatchers.*;
+import static org.mockito.Mockito.*;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.List;
+
+import org.antlr.v4.runtime.tree.ParseTree;
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Augment_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Deviate_add_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Deviate_delete_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Deviation_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Import_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Include_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Module_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Namespace_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Prefix_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Revision_date_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Status_argContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.StringContext;
+import org.opendaylight.controller.yang.model.parser.impl.YangModelParserListenerImpl;
+import org.opendaylight.controller.yang.model.parser.util.YangValidationException;
+
+import com.google.common.collect.Sets;
+
+public class YangModelValidationTest {
+
+ private YangModelBasicValidationListener valid;
+
+ @Before
+ public void setUp() {
+
+ valid = new YangModelBasicValidationListener();
+ }
+
+ @Test
+ public void testPrefixes() {
+ Prefix_stmtContext pref = mockStatement(Prefix_stmtContext.class,
+ "unique1");
+ Module_stmtContext module = mockStatement(Module_stmtContext.class,
+ "module1");
+ addChild(module, pref);
+
+ valid.enterPrefix_stmt(pref);
+
+ pref = mockStatement(Prefix_stmtContext.class, "unique1");
+ module = mockStatement(Module_stmtContext.class, "module1");
+ addChild(module, pref);
+
+ try {
+ valid.enterPrefix_stmt(pref);
+ } catch (Exception e) {
+ return;
+ }
+
+ fail("Validation Exception should have occured");
+ }
+
+ @Test
+ public void testNamespace() {
+
+ Namespace_stmtContext namespace = mockStatement(
+ Namespace_stmtContext.class, "http://test.parsing.uri.com");
+ Module_stmtContext module = mockStatement(Module_stmtContext.class,
+ "module1");
+ addChild(module, namespace);
+
+ valid.enterNamespace_stmt(namespace);
+
+ namespace = mockStatement(Namespace_stmtContext.class, "invalid uri");
+ module = mockStatement(Module_stmtContext.class, "module1");
+ addChild(module, namespace);
+
+ try {
+ valid.enterNamespace_stmt(namespace);
+ } catch (YangValidationException e) {
+ assertThat(
+ e.getMessage(),
+ containsString("Namespace:invalid uri cannot be parsed as URI"));
+ return;
+ }
+
+ fail("Validation Exception should have occured");
+ }
+
+ @Test
+ public void testImports() {
+ Import_stmtContext impor = mockImport("unique1", "p1");
+ Module_stmtContext mod = mockStatement(Module_stmtContext.class,
+ "module1");
+ addChild(mod, impor);
+
+ valid.enterImport_stmt(impor);
+
+ impor = mockImport("unique1", "p2");
+ mod = mockStatement(Module_stmtContext.class, "module1");
+ addChild(mod, impor);
+
+ try {
+ valid.enterImport_stmt(impor);
+ } catch (YangValidationException e) {
+ assertThat(e.getMessage(),
+ containsString("Import:unique1 not unique"));
+ return;
+ }
+
+ fail("Validation Exception should have occured");
+ }
+
+ @Test
+ public void testIncludes() {
+ Include_stmtContext incl = mockInclude("unique1");
+ Module_stmtContext mod = mockStatement(Module_stmtContext.class,
+ "module1");
+ addChild(mod, incl);
+ valid.enterInclude_stmt(incl);
+
+ incl = mockInclude("unique1");
+ mod = mockStatement(Module_stmtContext.class, "module1");
+ addChild(mod, incl);
+
+ try {
+ valid.enterInclude_stmt(incl);
+ } catch (YangValidationException e) {
+ assertThat(e.getMessage(),
+ containsString("Include:unique1 not unique in (sub)module"));
+ return;
+ }
+
+ fail("Validation Exception should have occured");
+ }
+
+ @Test
+ public void testIdentifierMatching() {
+ List<String> ids = new ArrayList<String>();
+ // valid
+ ids.add("_ok98-.87.-.8...88-asdAD");
+ ids.add("AA.bcd");
+ ids.add("a");
+ // invalid
+ ids.add("9aa");
+ ids.add("-");
+ ids.add(".");
+
+ int thrown = 0;
+ for (String id : ids) {
+ try {
+ BasicValidations.checkIdentifierInternal(
+ mock(Module_stmtContext.class), id);
+ } catch (YangValidationException e) {
+ thrown++;
+ }
+ }
+
+ assertThat(thrown, is(3));
+ }
+
+ @Test(expected = YangValidationException.class)
+ public void testAugument() {
+ Augment_stmtContext augument = mockStatement(Augment_stmtContext.class,
+ "/a:*abc/a:augument1");
+ Module_stmtContext mod1 = mockStatement(Module_stmtContext.class,
+ "mod1");
+ addChild(mod1, augument);
+
+ try {
+ valid.enterAugment_stmt(augument);
+ } catch (YangValidationException e) {
+ assertThat(
+ e.getMessage(),
+ containsString("Schema node id:/a:*abc/a:augument1 not in required format, details:Prefixed id:a:*abc not in required format"));
+ throw e;
+ }
+ }
+
+ @Test
+ public void testDeviate() {
+ Deviation_stmtContext ctx = mockStatement(Deviation_stmtContext.class,
+ "deviations");
+ Deviate_add_stmtContext add = mockStatement(
+ Deviate_add_stmtContext.class, "add");
+ Deviate_delete_stmtContext del = mockStatement(
+ Deviate_delete_stmtContext.class, "delete");
+
+ addChild(ctx, add);
+ addChild(ctx, del);
+
+ valid.enterDeviation_stmt(ctx);
+
+ HashSet<Class<? extends ParseTree>> types = Sets.newHashSet();
+ types.add(Deviate_add_stmtContext.class);
+ types.add(Deviate_delete_stmtContext.class);
+
+ int count = ValidationUtil.countPresentChildrenOfType(ctx, types);
+ assertThat(count, is(2));
+ }
+
+ @Test(expected = YangValidationException.class)
+ public void testStatus() throws Exception {
+ Status_argContext status = mockStatement(Status_argContext.class,
+ "unknown");
+ try {
+ valid.enterStatus_arg(status);
+ } catch (YangValidationException e) {
+ assertThat(
+ e.getMessage(),
+ containsString("illegal value for Status statement, only permitted:"));
+ throw e;
+ }
+ }
+
+ private Import_stmtContext mockImport(String name, String prefixName) {
+ Import_stmtContext impor = mockStatement(Import_stmtContext.class, name);
+
+ Prefix_stmtContext prefix = mockStatement(Prefix_stmtContext.class,
+ prefixName);
+ Revision_date_stmtContext revDate = mockStatement(
+ Revision_date_stmtContext.class, getFormattedDate());
+
+ addChild(impor, prefix);
+ addChild(impor, revDate);
+ return impor;
+ }
+
+ static String getFormattedDate() {
+ return YangModelParserListenerImpl.simpleDateFormat.format(new Date());
+ }
+
+ private Include_stmtContext mockInclude(String name) {
+ Include_stmtContext incl = mockStatement(Include_stmtContext.class,
+ name);
+
+ Revision_date_stmtContext revDate = mockStatement(
+ Revision_date_stmtContext.class, getFormattedDate());
+
+ addChild(incl, revDate);
+ return incl;
+ }
+
+ static void mockName(ParseTree stmt, String name) {
+ StringContext nameCtx = mock(StringContext.class);
+ ParseTree internalName = mock(ParseTree.class);
+ doReturn(1).when(stmt).getChildCount();
+ doReturn(name).when(internalName).getText();
+ doReturn(internalName).when(nameCtx).getChild(0);
+ doReturn(nameCtx).when(stmt).getChild(0);
+ }
+
+ static <T extends ParseTree> T mockStatement(Class<T> stmtType, String name) {
+ T stmt = stmtType.cast(mock(stmtType));
+
+ doReturn(0).when(stmt).getChildCount();
+
+ if (name != null)
+ mockName(stmt, name);
+ return stmt;
+ }
+
+ static void addChild(ParseTree parent, ParseTree child) {
+ int childCount = parent.getChildCount() + 1;
+ doReturn(childCount).when(parent).getChildCount();
+ doReturn(child).when(parent).getChild(childCount - 1);
+ doReturn(parent).when(child).getParent();
+ }
+
+}
*/
package org.opendaylight.controller.yang.model.util;
+import java.net.URI;
import java.util.ArrayList;
import java.util.Collections;
+import java.util.Date;
import java.util.List;
import org.opendaylight.controller.yang.common.QName;
* interface which represents SIGNED Integer values defined in Yang language. <br>
* The integer built-in types in Yang are int8, int16, int32, int64. They
* represent signed integers of different sizes:
- *
+ *
* <ul>
* <li>int8 - represents integer values between -128 and 127, inclusively.</li>
* <li>int16 - represents integer values between -32768 and 32767, inclusively.</li>
* <li>int64 - represents integer values between -9223372036854775808 and
* 9223372036854775807, inclusively.</li>
* </ul>
- *
+ *
*/
public abstract class AbstractSignedInteger implements IntegerTypeDefinition {
* @param maxRange
* @param units
*/
- public AbstractSignedInteger(final QName name, final String description,
- final Number minRange, final Number maxRange, final String units) {
+ public AbstractSignedInteger(final List<String> actualPath,
+ final URI namespace, final Date revision, final QName name,
+ final String description, final Number minRange,
+ final Number maxRange, final String units) {
this.name = name;
this.description = description;
- this.path = BaseTypes.schemaPath(name);
+ this.path = BaseTypes.schemaPath(actualPath, namespace, revision);
this.units = units;
this.rangeStatements = new ArrayList<RangeConstraint>();
final String rangeDescription = "Integer values between " + minRange
+ " and " + maxRange + ", inclusively.";
this.rangeStatements.add(BaseConstraints.rangeConstraint(minRange,
- maxRange, rangeDescription, "https://tools.ietf.org/html/rfc6020#section-9.2.4"));
+ maxRange, rangeDescription,
+ "https://tools.ietf.org/html/rfc6020#section-9.2.4"));
}
/**
* @param rangeStatements
* @param units
*/
- public AbstractSignedInteger(final QName name, final String description,
+ public AbstractSignedInteger(final List<String> actualPath,
+ final URI namespace, final Date revision, final QName name,
+ final String description,
final List<RangeConstraint> rangeStatements, final String units) {
this.name = name;
this.description = description;
- this.path = BaseTypes.schemaPath(name);
+ this.path = BaseTypes.schemaPath(actualPath, namespace, revision);
this.units = units;
this.rangeStatements = rangeStatements;
}
/**
- *
+ *
*/
package org.opendaylight.controller.yang.model.util;
+import java.net.URI;
import java.util.ArrayList;
import java.util.Collections;
+import java.util.Date;
import java.util.List;
import org.opendaylight.controller.yang.common.QName;
/**
* The Abstract Integer class defines implementation of IntegerTypeDefinition
* interface which represents UNSIGNED Integer values defined in Yang language. <br>
- * The integer built-in types in Yang are uint8, uint16, uint32, and uint64. They
- * represent unsigned integers of different sizes:
- *
+ * The integer built-in types in Yang are uint8, uint16, uint32, and uint64.
+ * They represent unsigned integers of different sizes:
+ *
* <ul>
* <li>uint8 - represents integer values between 0 and 255, inclusively.</li>
* <li>uint16 - represents integer values between 0 and 65535, inclusively.</li>
- * <li>uint32 - represents integer values between 0 and 4294967295,
- inclusively.</li>
+ * <li>uint32 - represents integer values between 0 and 4294967295, inclusively.
+ * </li>
* <li>uint64 - represents integer values between 0 and 18446744073709551615,
- inclusively.</li>
+ * inclusively.</li>
* </ul>
*
*/
private final String units;
private final List<RangeConstraint> rangeStatements;
-
+
/**
* @param name
* @param description
* @param maxRange
* @param units
*/
- public AbstractUnsignedInteger(final QName name, final String description,
- final Number minRange, final Number maxRange, final String units) {
+ public AbstractUnsignedInteger(final List<String> actualPath,
+ final URI namespace, final Date revision, final QName name,
+ final String description, final Number minRange,
+ final Number maxRange, final String units) {
this.name = name;
this.description = description;
- this.path = BaseTypes.schemaPath(name);
+ this.path = BaseTypes.schemaPath(actualPath, namespace, revision);
this.units = units;
this.rangeStatements = new ArrayList<RangeConstraint>();
final String rangeDescription = "Integer values between " + minRange
+ " and " + maxRange + ", inclusively.";
this.rangeStatements.add(BaseConstraints.rangeConstraint(minRange,
- maxRange, rangeDescription, "https://tools.ietf.org/html/rfc6020#section-9.2.4"));
+ maxRange, rangeDescription,
+ "https://tools.ietf.org/html/rfc6020#section-9.2.4"));
}
/**
* @param rangeStatements
* @param units
*/
- public AbstractUnsignedInteger(final QName name, final String description,
+ public AbstractUnsignedInteger(final List<String> actualPath,
+ final URI namespace, final Date revision, final QName name,
+ final String description,
final List<RangeConstraint> rangeStatements, final String units) {
this.name = name;
this.description = description;
- this.path = BaseTypes.schemaPath(name);
+ this.path = BaseTypes.schemaPath(actualPath, namespace, revision);
this.units = units;
this.rangeStatements = rangeStatements;
}
-
+
@Override
public String getUnits() {
return units;
package org.opendaylight.controller.yang.model.util;
import java.math.BigDecimal;
+import java.net.URI;
import java.util.ArrayList;
import java.util.Collections;
+import java.util.Date;
import java.util.List;
import org.opendaylight.controller.yang.common.QName;
/**
* The <code>default</code> implementation of Decimal Type Definition interface.
- *
- *
+ *
+ *
* @see DecimalTypeDefinition
*/
public class Decimal64 implements DecimalTypeDefinition {
* inclusively as defined interface {@link DecimalTypeDefinition} <br>
* If the fraction digits are not defined inner the definition boundaries
* the constructor will throw {@link IllegalArgumentException}
- *
+ *
* @param fractionDigits
* integer between 1 and 18 inclusively
- *
+ *
* @see DecimalTypeDefinition
* @exception IllegalArgumentException
*/
- public Decimal64(final Integer fractionDigits) {
+ public Decimal64(final List<String> actualPath, final URI namespace,
+ final Date revision, final Integer fractionDigits) {
super();
if (!((fractionDigits.intValue() > 1) && (fractionDigits.intValue() <= 18))) {
throw new IllegalArgumentException(
}
this.fractionDigits = fractionDigits;
rangeStatements = defaultRangeStatements();
- this.path = BaseTypes.schemaPath(name);
+ this.path = BaseTypes.schemaPath(actualPath, namespace, revision);
}
/**
* Decimal64 Type Constructor. <br>
- *
+ *
* If parameter <code>Range Statements</code> is <code>null</code> or
* defined as <code>empty List</code> the constructor automatically assigns
* the boundaries as min and max value defined for Decimal64 in <a
* inclusively as defined interface {@link DecimalTypeDefinition} <br>
* If the fraction digits are not defined inner the definition boundaries
* the constructor will throw {@link IllegalArgumentException}
- *
+ *
* @param rangeStatements
* Range Constraint Statements
* @param fractionDigits
* integer between 1 and 18 inclusively
* @exception IllegalArgumentException
*/
- public Decimal64(final List<RangeConstraint> rangeStatements,
+ public Decimal64(final List<String> actualPath, final URI namespace,
+ final Date revision, final List<RangeConstraint> rangeStatements,
Integer fractionDigits) {
super();
if (!((fractionDigits.intValue() > 1) && (fractionDigits.intValue() <= 18))) {
this.rangeStatements = Collections.unmodifiableList(rangeStatements);
}
this.fractionDigits = fractionDigits;
- this.path = BaseTypes.schemaPath(name);
+ this.path = BaseTypes.schemaPath(actualPath, namespace, revision);
}
/**
* inclusively as defined interface {@link DecimalTypeDefinition} <br>
* If the fraction digits are not defined inner the definition boundaries
* the constructor will throw {@link IllegalArgumentException}
- *
+ *
* @param units
* units associated with the type
* @param defaultValue
* Range Constraint Statements
* @param fractionDigits
* integer between 1 and 18 inclusively
- *
+ *
* @exception IllegalArgumentException
*/
- public Decimal64(final String units, final BigDecimal defaultValue,
+ public Decimal64(final List<String> actualPath, final URI namespace,
+ final Date revision, final String units, final BigDecimal defaultValue,
final List<RangeConstraint> rangeStatements,
final Integer fractionDigits) {
super();
if (rangeStatements == null || rangeStatements.isEmpty()) {
this.rangeStatements = defaultRangeStatements();
-
+
} else {
this.rangeStatements = Collections.unmodifiableList(rangeStatements);
}
/**
* Returns unmodifiable List with default definition of Range Statements.
- *
+ *
* @return unmodifiable List with default definition of Range Statements.
*/
private List<RangeConstraint> defaultRangeStatements() {
*/
package org.opendaylight.controller.yang.model.util;
+import java.net.URI;
+import java.util.Date;
import java.util.List;
import org.opendaylight.controller.yang.common.QName;
* Implementation of Yang int16 built-in type. <br>
* int16 represents integer values between -32768 and 32767, inclusively. The
* Java counterpart of Yang int16 built-in type is {@link Short}.
- *
+ *
* @see AbstractSignedInteger
*/
public class Int16 extends AbstractSignedInteger {
private static final QName name = BaseTypes.constructQName("int16");
private Short defaultValue = null;
- private static final String description =
+ private static final String description =
"int16 represents integer values between -32768 and 32767, inclusively.";
- public Int16() {
- super(name, description, Short.MIN_VALUE, Short.MAX_VALUE, "");
+ public Int16(final List<String> actualPath, final URI namespace,
+ final Date revision) {
+ super(actualPath, namespace, revision, name, description, Short.MIN_VALUE, Short.MAX_VALUE, "");
}
- public Int16(final List<RangeConstraint> rangeStatements,
+ public Int16(final List<String> actualPath, final URI namespace,
+ final Date revision, final List<RangeConstraint> rangeStatements,
final String units, final Short defaultValue) {
- super(name, description, rangeStatements, units);
+ super(actualPath, namespace, revision, name, description, rangeStatements, units);
this.defaultValue = defaultValue;
}
*/
package org.opendaylight.controller.yang.model.util;
+import java.net.URI;
+import java.util.Date;
import java.util.List;
import org.opendaylight.controller.yang.common.QName;
* int32 represents integer values between -2147483648 and 2147483647,
* inclusively. The Java counterpart of Yang int32 built-in type is
* {@link Integer}.
- *
+ *
* @see AbstractSignedInteger
- *
+ *
*/
public class Int32 extends AbstractSignedInteger {
private static final QName name = BaseTypes.constructQName("int32");
private Integer defaultValue = null;
- private static final String description =
+ private static final String description =
"int32 represents integer values between -2147483648 and 2147483647, inclusively.";
- public Int32() {
- super(name, description, Integer.MIN_VALUE, Integer.MAX_VALUE, "");
+ public Int32(final List<String> actualPath, final URI namespace,
+ final Date revision) {
+ super(actualPath, namespace, revision, name, description, Integer.MIN_VALUE, Integer.MAX_VALUE, "");
}
- public Int32(final Integer defaultValue) {
- super(name, description, Integer.MIN_VALUE, Integer.MAX_VALUE, "");
+ public Int32(final List<String> actualPath, final URI namespace,
+ final Date revision, final Integer defaultValue) {
+ super(actualPath, namespace, revision, name, description, Integer.MIN_VALUE, Integer.MAX_VALUE, "");
this.defaultValue = defaultValue;
}
- public Int32(final List<RangeConstraint> rangeStatements,
+ public Int32(final List<String> actualPath, final URI namespace,
+ final Date revision, final List<RangeConstraint> rangeStatements,
final String units, final Integer defaultValue) {
- super(name, description, rangeStatements, units);
+ super(actualPath, namespace, revision, name, description, rangeStatements, units);
this.defaultValue = defaultValue;
}
/*
* (non-Javadoc)
- *
+ *
* @see
* org.opendaylight.controller.yang.model.api.TypeDefinition#getBaseType()
*/
/*
* (non-Javadoc)
- *
+ *
* @see
* org.opendaylight.controller.yang.model.api.TypeDefinition#getDefaultValue
* ()
*/
package org.opendaylight.controller.yang.model.util;
+import java.net.URI;
+import java.util.Date;
import java.util.List;
import org.opendaylight.controller.yang.common.QName;
/**
* Implementation of Yang int64 built-in type. <br>
- * int64 represents integer values between -9223372036854775808 and 9223372036854775807, inclusively.
+ * int64 represents integer values between -9223372036854775808 and 9223372036854775807, inclusively.
* The Java counterpart of Yang int64 built-in type is
* {@link Long}.
*
private static final QName name = BaseTypes.constructQName("int64");
private Long defaultValue = null;
- private static final String description =
+ private static final String description =
"int64 represents integer values between -9223372036854775808 and 9223372036854775807, inclusively.";
- public Int64() {
- super(name, description, Integer.MIN_VALUE, Integer.MAX_VALUE, "");
+ public Int64(final List<String> actualPath, final URI namespace,
+ final Date revision) {
+ super(actualPath, namespace, revision, name, description, Integer.MIN_VALUE, Integer.MAX_VALUE, "");
}
- public Int64(final Long defaultValue) {
- super(name, description, Integer.MIN_VALUE, Integer.MAX_VALUE, "");
+ public Int64(final List<String> actualPath, final URI namespace,
+ final Date revision, final Long defaultValue) {
+ super(actualPath, namespace, revision, name, description, Integer.MIN_VALUE, Integer.MAX_VALUE, "");
this.defaultValue = defaultValue;
}
- public Int64(final List<RangeConstraint> rangeStatements,
+ public Int64(final List<String> actualPath, final URI namespace,
+ final Date revision, final List<RangeConstraint> rangeStatements,
final String units, final Long defaultValue) {
- super(name, description, rangeStatements, units);
+ super(actualPath, namespace, revision, name, description, rangeStatements, units);
this.defaultValue = defaultValue;
}
/*
* (non-Javadoc)
- *
+ *
* @see org.opendaylight.controller.yang.model.api.TypeDefinition#getBaseType()
*/
@Override
/*
* (non-Javadoc)
- *
+ *
* @see org.opendaylight.controller.yang.model.api.TypeDefinition#getDefaultValue()
*/
@Override
*/
package org.opendaylight.controller.yang.model.util;
+import java.net.URI;
+import java.util.Date;
import java.util.List;
import org.opendaylight.controller.yang.common.QName;
/**
* Implementation of Yang int8 built-in type.
* <br>
- * int8 represents integer values between -128 and 127, inclusively. The Java counterpart of
+ * int8 represents integer values between -128 and 127, inclusively. The Java counterpart of
* Yang int8 built-in type is {@link Byte}.
- *
+ *
* @see AbstractSignedInteger
*/
public class Int8 extends AbstractSignedInteger {
private static final QName name = BaseTypes.constructQName("int8");
private Byte defaultValue = null;
- private static final String description =
+ private static final String description =
"represents integer values between -128 and 127, inclusively.";
-
- public Int8() {
- super(name, description, Byte.MIN_VALUE, Byte.MAX_VALUE, "");
+
+ public Int8(final List<String> actualPath, final URI namespace,
+ final Date revision) {
+ super(actualPath, namespace, revision, name, description, Byte.MIN_VALUE, Byte.MAX_VALUE, "");
}
- public Int8(final Byte defaultValue) {
- super(name, description, Byte.MIN_VALUE, Byte.MAX_VALUE, "");
+ public Int8(final List<String> actualPath, final URI namespace,
+ final Date revision, final Byte defaultValue) {
+ super(actualPath, namespace, revision, name, description, Byte.MIN_VALUE, Byte.MAX_VALUE, "");
this.defaultValue = defaultValue;
}
- public Int8(final List<RangeConstraint> rangeStatements,
+ public Int8(final List<String> actualPath, final URI namespace,
+ final Date revision, final List<RangeConstraint> rangeStatements,
final String units, final Byte defaultValue) {
- super(name, description, rangeStatements, units);
+ super(actualPath, namespace, revision, name, description, rangeStatements, units);
this.defaultValue = defaultValue;
}
/*
* (non-Javadoc)
- *
+ *
* @see org.opendaylight.controller.yang.model.api.TypeDefinition#getBaseType()
*/
@Override
/*
* (non-Javadoc)
- *
+ *
* @see org.opendaylight.controller.yang.model.api.TypeDefinition#getDefaultValue()
*/
@Override
*/
package org.opendaylight.controller.yang.model.util;
+import java.net.URI;
import java.util.ArrayList;
import java.util.Collections;
+import java.util.Date;
import java.util.List;
import org.opendaylight.controller.yang.common.QName;
/**
* Default Constructor.
*/
- public StringType() {
+ public StringType(final List<String> actualPath,
+ final URI namespace, final Date revision) {
super();
- path = BaseTypes.schemaPath(name);
+ path = BaseTypes.schemaPath(actualPath, namespace, revision);
final List<LengthConstraint> constraints = new ArrayList<LengthConstraint>();
constraints.add(BaseConstraints.lengthConstraint(0, Long.MAX_VALUE, "", ""));
lengthStatements = Collections.unmodifiableList(constraints);
* @param lengthStatements
* @param patterns
*/
- public StringType(final List<LengthConstraint> lengthStatements,
+ public StringType(final List<String> actualPath,
+ final URI namespace, final Date revision, final List<LengthConstraint> lengthStatements,
final List<PatternConstraint> patterns) {
super();
- path = BaseTypes.schemaPath(name);
+ path = BaseTypes.schemaPath(actualPath, namespace, revision);
if(lengthStatements == null || lengthStatements.size() == 0) {
final List<LengthConstraint> constraints = new ArrayList<LengthConstraint>();
constraints.add(BaseConstraints.lengthConstraint(0, Long.MAX_VALUE, "", ""));
* @param patterns
* @param units
*/
- public StringType(final String defaultValue,
+ public StringType(final List<String> actualPath,
+ final URI namespace, final Date revision, final String defaultValue,
final List<LengthConstraint> lengthStatements,
final List<PatternConstraint> patterns, final String units) {
super();
- path = BaseTypes.schemaPath(name);
+ path = BaseTypes.schemaPath(actualPath, namespace, revision);
this.defaultValue = defaultValue;
if(lengthStatements == null || lengthStatements.size() == 0) {
final List<LengthConstraint> constraints = new ArrayList<LengthConstraint>();
*/
package org.opendaylight.controller.yang.model.util;
+import java.net.URI;
+import java.util.Date;
import java.util.List;
import org.opendaylight.controller.yang.common.QName;
* Implementation of Yang uint32 built-in type. <br>
* uint16 represents integer values between 0 and 65535, inclusively. The Java
* counterpart of Yang uint32 built-in type is {@link Integer}.
- *
+ *
*/
public class Uint16 extends AbstractUnsignedInteger {
private Integer defaultValue = null;
private static final String description = "uint16 represents integer values between 0 and 65535, inclusively.";
- public Uint16() {
- super(name, description, Short.MIN_VALUE, Short.MAX_VALUE, "");
+ public Uint16(final List<String> actualPath,
+ final URI namespace, final Date revision) {
+ super(actualPath, namespace, revision, name, description, Short.MIN_VALUE, Short.MAX_VALUE, "");
}
- public Uint16(final Integer defaultValue) {
- super(name, description, Short.MIN_VALUE, Short.MAX_VALUE, "");
+ public Uint16(final List<String> actualPath,
+ final URI namespace, final Date revision, final Integer defaultValue) {
+ super(actualPath, namespace, revision, name, description, Short.MIN_VALUE, Short.MAX_VALUE, "");
this.defaultValue = defaultValue;
}
- public Uint16(final List<RangeConstraint> rangeStatements,
+ public Uint16(final List<String> actualPath,
+ final URI namespace, final Date revision, final List<RangeConstraint> rangeStatements,
final String units, final Integer defaultValue) {
- super(name, description, rangeStatements, units);
+ super(actualPath, namespace, revision, name, description, rangeStatements, units);
this.defaultValue = defaultValue;
}
/*
* (non-Javadoc)
- *
+ *
* @see
* org.opendaylight.controller.yang.model.api.TypeDefinition#getBaseType()
*/
/*
* (non-Javadoc)
- *
+ *
* @see
* org.opendaylight.controller.yang.model.api.TypeDefinition#getDefaultValue
* ()
*/
package org.opendaylight.controller.yang.model.util;
+import java.net.URI;
+import java.util.Date;
import java.util.List;
import org.opendaylight.controller.yang.common.QName;
* Implementation of Yang uint32 built-in type. <br>
* uint32 represents integer values between 0 and 4294967295, inclusively. The
* Java counterpart of Yang uint32 built-in type is {@link Long}.
- *
+ *
*/
public class Uint32 extends AbstractUnsignedInteger {
private Long defaultValue = null;
private static final String description = "uint32 represents integer values between 0 and 4294967295, inclusively.";
- public Uint32() {
- super(name, description, Short.MIN_VALUE, Short.MAX_VALUE, "");
+ public Uint32(final List<String> actualPath,
+ final URI namespace, final Date revision) {
+ super(actualPath, namespace, revision, name, description, Short.MIN_VALUE, Short.MAX_VALUE, "");
}
- public Uint32(final Long defaultValue) {
- super(name, description, Short.MIN_VALUE, Short.MAX_VALUE, "");
+ public Uint32(final List<String> actualPath,
+ final URI namespace, final Date revision, final Long defaultValue) {
+ super(actualPath, namespace, revision, name, description, Short.MIN_VALUE, Short.MAX_VALUE, "");
this.defaultValue = defaultValue;
}
- public Uint32(final List<RangeConstraint> rangeStatements,
+ public Uint32(final List<String> actualPath,
+ final URI namespace, final Date revision, final List<RangeConstraint> rangeStatements,
final String units, final Long defaultValue) {
- super(name, description, rangeStatements, units);
+ super(actualPath, namespace, revision, name, description, rangeStatements, units);
this.defaultValue = defaultValue;
}
/*
* (non-Javadoc)
- *
+ *
* @see
* org.opendaylight.controller.yang.model.api.TypeDefinition#getBaseType()
*/
/*
* (non-Javadoc)
- *
+ *
* @see
* org.opendaylight.controller.yang.model.api.TypeDefinition#getDefaultValue
* ()
package org.opendaylight.controller.yang.model.util;
import java.math.BigInteger;
+import java.net.URI;
+import java.util.Date;
import java.util.List;
import org.opendaylight.controller.yang.common.QName;
private static final String description =
"uint64 represents integer values between 0 and 18446744073709551615, inclusively.";
- public Uint64() {
- super(name, description, Short.MIN_VALUE, Short.MAX_VALUE, "");
+ public Uint64(final List<String> actualPath,
+ final URI namespace, final Date revision) {
+ super(actualPath, namespace, revision, name, description, Short.MIN_VALUE, Short.MAX_VALUE, "");
}
- public Uint64(final BigInteger defaultValue) {
- super(name, description, Short.MIN_VALUE, Short.MAX_VALUE, "");
+ public Uint64(final List<String> actualPath,
+ final URI namespace, final Date revision, final BigInteger defaultValue) {
+ super(actualPath, namespace, revision, name, description, Short.MIN_VALUE, Short.MAX_VALUE, "");
this.defaultValue = defaultValue;
}
- public Uint64(final List<RangeConstraint> rangeStatements,
+ public Uint64(final List<String> actualPath,
+ final URI namespace, final Date revision, final List<RangeConstraint> rangeStatements,
final String units, final BigInteger defaultValue) {
- super(name, description, rangeStatements, units);
+ super(actualPath, namespace, revision, name, description, rangeStatements, units);
this.defaultValue = defaultValue;
}
*/
package org.opendaylight.controller.yang.model.util;
+import java.net.URI;
+import java.util.Date;
import java.util.List;
import org.opendaylight.controller.yang.common.QName;
/**
* Implementation of Yang uint8 built-in type.
* <br>
- * uint8 represents integer values between 0 and 255, inclusively. The Java counterpart of
+ * uint8 represents integer values between 0 and 255, inclusively. The Java counterpart of
* Yang uint8 built-in type is {@link Short}.
- *
+ *
* @see AbstractUnsignedInteger
*/
public class Uint8 extends AbstractUnsignedInteger {
private static final QName name = BaseTypes.constructQName("uint8");
private Short defaultValue = null;
- private static final String description =
+ private static final String description =
"uint8 represents integer values between 0 and 255, inclusively.";
- public Uint8() {
- super(name, description, Short.MIN_VALUE, Short.MAX_VALUE, "");
+ public Uint8(final List<String> actualPath,
+ final URI namespace, final Date revision) {
+ super(actualPath, namespace, revision, name, description, Short.MIN_VALUE, Short.MAX_VALUE, "");
}
- public Uint8(final Short defaultValue) {
- super(name, description, Short.MIN_VALUE, Short.MAX_VALUE, "");
+ public Uint8(final List<String> actualPath,
+ final URI namespace, final Date revision, final Short defaultValue) {
+ super(actualPath, namespace, revision, name, description, Short.MIN_VALUE, Short.MAX_VALUE, "");
this.defaultValue = defaultValue;
}
- public Uint8(final List<RangeConstraint> rangeStatements,
+ public Uint8(final List<String> actualPath,
+ final URI namespace, final Date revision, final List<RangeConstraint> rangeStatements,
final String units, final Short defaultValue) {
- super(name, description, rangeStatements, units);
+ super(actualPath, namespace, revision, name, description, rangeStatements, units);
this.defaultValue = defaultValue;
}
/*
* (non-Javadoc)
- *
+ *
* @see org.opendaylight.controller.yang.model.api.TypeDefinition#getBaseType()
*/
@Override
/*
* (non-Javadoc)
- *
+ *
* @see org.opendaylight.controller.yang.model.api.TypeDefinition#getDefaultValue()
*/
@Override
*/\r
package org.opendaylight.controller.yang.model.util;\r
\r
+import java.net.URI;\r
+import java.util.Date;\r
import java.util.HashMap;\r
import java.util.HashSet;\r
import java.util.List;\r
import org.opendaylight.controller.yang.model.api.type.BinaryTypeDefinition;\r
import org.opendaylight.controller.yang.model.api.type.BitsTypeDefinition;\r
import org.opendaylight.controller.yang.model.api.type.BooleanTypeDefinition;\r
-import org.opendaylight.controller.yang.model.api.type.DecimalTypeDefinition;\r
import org.opendaylight.controller.yang.model.api.type.EmptyTypeDefinition;\r
import org.opendaylight.controller.yang.model.api.type.InstanceIdentifierTypeDefinition;\r
-import org.opendaylight.controller.yang.model.api.type.IntegerTypeDefinition;\r
-import org.opendaylight.controller.yang.model.api.type.RangeConstraint;\r
-import org.opendaylight.controller.yang.model.api.type.StringTypeDefinition;\r
-import org.opendaylight.controller.yang.model.api.type.UnsignedIntegerTypeDefinition;\r
\r
public class YangTypesConverter {\r
\r
private static final TypeDefinition<BitsTypeDefinition> BITS = new BitsType();\r
private static final TypeDefinition<BooleanTypeDefinition> BOOLEAN_TYPE = new BooleanType();\r
private static final TypeDefinition<EmptyTypeDefinition> EMPTY_TYPE = new EmptyType();\r
- private static final TypeDefinition<InstanceIdentifierTypeDefinition> INST_ID_TYPE = new InstanceIdentifier(null, true);\r
- private static final TypeDefinition<IntegerTypeDefinition> INT8_TYPE = new Int8();\r
- private static final TypeDefinition<IntegerTypeDefinition> INT16_TYPE = new Int16();\r
- private static final TypeDefinition<IntegerTypeDefinition> INT32_TYPE = new Int32();\r
- private static final TypeDefinition<IntegerTypeDefinition> INT64_TYPE = new Int64();\r
- private static final TypeDefinition<StringTypeDefinition> STRING_TYPE = new StringType();\r
- private static final TypeDefinition<UnsignedIntegerTypeDefinition> UINT8_TYPE = new Uint8();\r
- private static final TypeDefinition<UnsignedIntegerTypeDefinition> UINT16_TYPE = new Uint16();\r
- private static final TypeDefinition<UnsignedIntegerTypeDefinition> UINT32_TYPE = new Uint32();\r
- private static final TypeDefinition<UnsignedIntegerTypeDefinition> UINT64_TYPE = new Uint64();\r
+ private static final TypeDefinition<InstanceIdentifierTypeDefinition> INST_ID_TYPE = new InstanceIdentifier(\r
+ null, true);\r
\r
static {\r
baseYangTypeMap.put("binary", BINARY);\r
baseYangTypeMap.put("boolean", BOOLEAN_TYPE);\r
baseYangTypeMap.put("empty", EMPTY_TYPE);\r
baseYangTypeMap.put("instance-identifier", INST_ID_TYPE);\r
- baseYangTypeMap.put("int8", INT8_TYPE);\r
- baseYangTypeMap.put("int16", INT16_TYPE);\r
- baseYangTypeMap.put("int32", INT32_TYPE);\r
- baseYangTypeMap.put("int64", INT64_TYPE);\r
- baseYangTypeMap.put("string", STRING_TYPE);\r
- baseYangTypeMap.put("uint8", UINT8_TYPE);\r
- baseYangTypeMap.put("uint16", UINT16_TYPE);\r
- baseYangTypeMap.put("uint32", UINT32_TYPE);\r
- baseYangTypeMap.put("uint64", UINT64_TYPE);\r
\r
baseYangTypes.add("binary");\r
baseYangTypes.add("bits");\r
return type;\r
}\r
\r
- public static TypeDefinition<?> javaTypeForBaseYangType(String typeName) {\r
- TypeDefinition<?> type = baseYangTypeMap.get(typeName);\r
- return type;\r
- }\r
+ public static TypeDefinition<?> javaTypeForBaseYangType(\r
+ List<String> actualPath, URI namespace, Date revision,\r
+ String typeName) {\r
\r
- public static TypeDefinition<IntegerTypeDefinition> javaTypeForBaseYangSignedIntegerType(\r
- String typeName, List<RangeConstraint> ranges) {\r
- if (typeName.equals("int8")) {\r
- return new Int8(ranges, null, null);\r
- } else if (typeName.equals("int16")) {\r
- return new Int16(ranges, null, null);\r
- } else if (typeName.equals("int32")) {\r
- return new Int32(ranges, null, null);\r
- } else if (typeName.equals("int64")) {\r
- return new Int64(ranges, null, null);\r
+ if (typeName.startsWith("int")) {\r
+ if (typeName.equals("int8")) {\r
+ return new Int8(actualPath, namespace, revision);\r
+ } else if (typeName.equals("int16")) {\r
+ return new Int16(actualPath, namespace, revision);\r
+ } else if (typeName.equals("int32")) {\r
+ return new Int32(actualPath, namespace, revision);\r
+ } else if (typeName.equals("int64")) {\r
+ return new Int64(actualPath, namespace, revision);\r
+ }\r
+ } else if (typeName.startsWith("uint")) {\r
+ if (typeName.equals("uint8")) {\r
+ return new Uint8(actualPath, namespace, revision);\r
+ } else if (typeName.equals("uint16")) {\r
+ return new Uint16(actualPath, namespace, revision);\r
+ } else if (typeName.equals("uint32")) {\r
+ return new Uint32(actualPath, namespace, revision);\r
+ } else if (typeName.equals("uint64")) {\r
+ return new Uint64(actualPath, namespace, revision);\r
+ }\r
+ } else if (typeName.equals("string")) {\r
+ return new StringType(actualPath, namespace, revision);\r
}\r
- return null;\r
- }\r
\r
- public static TypeDefinition<UnsignedIntegerTypeDefinition> javaTypeForBaseYangUnsignedIntegerType(\r
- final String typeName, List<RangeConstraint> ranges) {\r
- if (typeName.equals("uint8")) {\r
- return new Uint8(ranges, null, null);\r
- } else if (typeName.equals("uint16")) {\r
- return new Uint16(ranges, null, null);\r
- } else if (typeName.equals("uint32")) {\r
- return new Uint32(ranges, null, null);\r
- } else if (typeName.equals("uint64")) {\r
- return new Uint64(ranges, null, null);\r
- }\r
- return null;\r
- }\r
-\r
- public static TypeDefinition<DecimalTypeDefinition> javaTypeForBaseYangDecimal64Type(\r
- List<RangeConstraint> rangeStatements, int fractionDigits) {\r
- return new Decimal64(rangeStatements, fractionDigits);\r
+ TypeDefinition<?> type = baseYangTypeMap.get(typeName);\r
+ return type;\r
}\r
\r
-}
+}\r
+++ /dev/null
-***************
-*** 29,35 ****
- import org.opendaylight.controller.switchmanager.SwitchConfig;
- import org.opendaylight.controller.usermanager.IUserManager;
- import org.opendaylight.controller.web.IOneWeb;
-- import org.springframework.security.core.context.SecurityContextHolder;
- import org.springframework.stereotype.Controller;
- import org.springframework.web.bind.annotation.PathVariable;
- import org.springframework.web.bind.annotation.RequestMapping;
---- 31,36 ----
- import org.opendaylight.controller.switchmanager.SwitchConfig;
- import org.opendaylight.controller.usermanager.IUserManager;
- import org.opendaylight.controller.web.IOneWeb;
- import org.springframework.stereotype.Controller;
- import org.springframework.web.bind.annotation.PathVariable;
- import org.springframework.web.bind.annotation.RequestMapping;
-***************
-*** 182,189 ****
- @RequestMapping(value = "/flow", method = RequestMethod.POST)
- @ResponseBody
- public String actionFlow(@RequestParam(required = true) String action,
-- @RequestParam(required = false) String body, @RequestParam(required = true) String nodeId) {
-- if (!authorize(UserLevel.NETWORKADMIN)) {
- return "Operation not authorized";
- }
-
---- 183,190 ----
- @RequestMapping(value = "/flow", method = RequestMethod.POST)
- @ResponseBody
- public String actionFlow(@RequestParam(required = true) String action,
-+ @RequestParam(required = false) String body, @RequestParam(required = true) String nodeId, HttpServletRequest request) {
-+ if (!authorize(UserLevel.NETWORKADMIN, request)) {
- return "Operation not authorized";
- }
-
-***************
-*** 206,213 ****
- @RequestMapping(value = "/flow/{nodeId}/{name}", method = RequestMethod.POST)
- @ResponseBody
- public String removeFlow(@PathVariable("nodeId") String nodeId, @PathVariable("name") String name,
-- @RequestParam(required = true) String action) {
-- if (!authorize(UserLevel.NETWORKADMIN)) { return "Operation not authorized"; }
-
- IForwardingRulesManager frm = (IForwardingRulesManager) ServiceHelper
- .getInstance(IForwardingRulesManager.class, "default", this);
---- 207,214 ----
- @RequestMapping(value = "/flow/{nodeId}/{name}", method = RequestMethod.POST)
- @ResponseBody
- public String removeFlow(@PathVariable("nodeId") String nodeId, @PathVariable("name") String name,
-+ @RequestParam(required = true) String action, HttpServletRequest request) {
-+ if (!authorize(UserLevel.NETWORKADMIN, request)) { return "Operation not authorized"; }
-
- IForwardingRulesManager frm = (IForwardingRulesManager) ServiceHelper
- .getInstance(IForwardingRulesManager.class, "default", this);
-***************
-*** 235,248 ****
- *
- * @param level
- */
-- private boolean authorize(UserLevel level) {
- IUserManager userManager = (IUserManager) ServiceHelper
- .getGlobalInstance(IUserManager.class, this);
- if (userManager == null) {
- return false;
- }
-
-- String username = SecurityContextHolder.getContext().getAuthentication().getName();
- UserLevel userLevel = userManager.getUserLevel(username);
- if (userLevel.toNumber() <= level.toNumber()) {
- return true;
---- 236,249 ----
- *
- * @param level
- */
-+ private boolean authorize(UserLevel level, HttpServletRequest request) {
- IUserManager userManager = (IUserManager) ServiceHelper
- .getGlobalInstance(IUserManager.class, this);
- if (userManager == null) {
- return false;
- }
-
-+ String username = request.getUserPrincipal().getName();
- UserLevel userLevel = userManager.getUserLevel(username);
- if (userLevel.toNumber() <= level.toNumber()) {
- return true;
<!-- #menu -->
<div id="menu" class="navbar navbar-fixed-top">
<div class="navbar-inner row-fluid">
- <div class="span10">
+ <div class="span9">
<a class="brand" href="/" title="${version}">${name}</a>
<ul class="nav nav-tabs">
</ul>
</div>
- <div class="span2">
+ <div class="span3">
<div id="toolbar" class="btn-group">
<a class="btn dropdown-toggle" data-toggle="dropdown" href="#">
<div class="icon-user"></div> ${username} <span class="caret"></span>
</body>
-</html>
\ No newline at end of file
+</html>
if (body.length == 0 && !(typeof thead === 'undefined')) {
var $tr = $(document.createElement('tr'));
var $td = $(document.createElement('td'));
- $td.attr("colspan", thead.length);
- $td.text("No data available");
- $td.addClass("empty");
+ $td.attr('colspan', thead.length);
+ $td.text('No data available');
+ $td.addClass('empty');
$tr.append($td);
$tbody.append($tr);
return $tbody;
// else, populate as usual
$(body).each(function(index, value) {
var $tr = $(document.createElement('tr'));
- // data-id
- if (value['id'] != undefined) {
- $tr.attr('data-id', value['id']);
- }
- // add classes
- $(value["type"]).each(function(index, value) {
- $tr.addClass(value);
- });
- // add entries
- $(value["entry"]).each(function(index, value) {
- var $td = $(document.createElement('td'));
- $td.append(value);
- $tr.append($td);
+ $.each(value, function(key, value) {
+ if (key == 'type') {
+ // add classes
+ $(value).each(function(index, value) {
+ $tr.addClass(value);
+ });
+ } else if (key == 'entry') {
+ // add entries
+ $(value).each(function(index, value) {
+ var $td = $(document.createElement('td'));
+ $td.append(value);
+ $tr.append($td);
+ });
+ } else {
+ // data field
+ $tr.attr('data-' + key, value);
+ }
+ $tbody.append($tr);
});
- $tbody.append($tr);
});
return $tbody;
}
one.lib.registry.alert = setTimeout(function() {
$("#alert").slideUp();
}, 8000);
-}
\ No newline at end of file
+}