ci.println("\nNo Clustering services available");
return;
}
- String containerName = ci.nextArgument();
+ String containerName = ci.nextArgument().toLowerCase();
if (containerName == null) {
ci.println("containerName not supplied");
return;
public void _dumper(CommandInterpreter ci) {
ConcurrentMap<Object, Object> c;
- String containerName = ci.nextArgument();
+ String containerName = ci.nextArgument().toLowerCase();
if (containerName == null) {
ci.println("containerName not supplied");
return;
}
class DoListenRoleChanged implements IListenRoleChange {
+ @Override
public void newActiveAvailable() {
logger.debug("New Active is available");
}
public class FlowConfig implements Serializable {
private static final long serialVersionUID = 1L;
private static final Logger log = LoggerFactory.getLogger(FlowConfig.class);
- public static final String staticFlowsGroup = "**StaticFlows";
- public static final String internalStaticFlowsGroup = "**InternalStaticFlows";
- public static final String internalStaticFlowBegin = "**";
+ private static final String NAMEREGEX = "^[a-zA-Z0-9]+$";
+ private static final String STATICFLOWGROUP = "__StaticFlows__";
+ public static final String INTERNALSTATICFLOWGROUP = "__InternalStaticFlows__";
+ public static final String INTERNALSTATICFLOWBEGIN = "__";
+ public static final String INTERNALSTATICFLOWEND = "__";
private boolean dynamic;
private String status;
}
public boolean isInternalFlow() {
- // Controller generated static flows have name starting with "**"
- return (this.name != null && this.name.startsWith(FlowConfig.internalStaticFlowBegin));
+ return (this.name != null &&
+ this.name.startsWith(FlowConfig.INTERNALSTATICFLOWBEGIN) &&
+ this.name.endsWith(FlowConfig.INTERNALSTATICFLOWEND));
}
public String getName() {
Switch sw = null;
try {
- if (name == null || name.trim().isEmpty()) {
+ if (name == null || name.trim().isEmpty() || !name.matches(FlowConfig.NAMEREGEX)) {
return new Status(StatusCode.BADREQUEST, "Invalid name");
}
}
public FlowEntry getFlowEntry() {
- return new FlowEntry(FlowConfig.staticFlowsGroup, this.name, this.getFlow(), this.getNode());
+ String group = this.isInternalFlow() ? FlowConfig.INTERNALSTATICFLOWGROUP : FlowConfig.STATICFLOWGROUP;
+ return new FlowEntry(group, this.name, this.getFlow(), this.getNode());
}
public Flow getFlow() {
* @return true if internal generated static flow, false otherwise
*/
public boolean isInternal() {
- return flowName.startsWith(FlowConfig.internalStaticFlowBegin);
+ return flowName.startsWith(FlowConfig.INTERNALSTATICFLOWBEGIN)
+ && flowName.endsWith(FlowConfig.INTERNALSTATICFLOWEND);
}
}
*
* @param config
* the {@code FlowConfig} object representing the static flow
- * @param restore
- * if set to true, the config object validation will be skipped.
- * Used only internally, always set it to false.
* @return the {@code Status} object indicating the result of this action.
*/
- public Status addStaticFlow(FlowConfig config, boolean restore);
+ public Status addStaticFlow(FlowConfig config);
/**
* Remove a flow specified by the {@code FlowConfig} object on the current
public void testInternalFlow() {
FlowConfig flowConfig = new FlowConfig();
Assert.assertFalse(flowConfig.isInternalFlow());
- flowConfig.setName("**Internal");
+ flowConfig.setName("__Internal__");
+ Status status = flowConfig.validate(null);
+ Assert.assertFalse(status.isSuccess());
+ Assert.assertTrue(status.getDescription().contains("name"));
Assert.assertTrue(flowConfig.isInternalFlow());
flowConfig.setName("External");
Assert.assertFalse(flowConfig.isInternalFlow());
import org.opendaylight.controller.clustering.services.ICacheUpdateAware;
import org.opendaylight.controller.clustering.services.IClusterContainerServices;
-import org.opendaylight.controller.hosttracker.IfIptoHost;
public class Activator extends ComponentActivatorAbstractBase {
protected static final Logger logger = LoggerFactory.getLogger(Activator.class);
c.add(createContainerServiceDependency(containerName).setService(IFlowProgrammerService.class)
.setCallbacks("setFlowProgrammerService", "unsetFlowProgrammerService").setRequired(true));
-
c.add(createContainerServiceDependency(containerName).setService(IClusterContainerServices.class)
.setCallbacks("setClusterContainerService", "unsetClusterContainerService").setRequired(true));
c.add(createContainerServiceDependency(containerName).setService(ISwitchManager.class)
.setCallbacks("setSwitchManager", "unsetSwitchManager").setRequired(true));
c.add(createContainerServiceDependency(containerName).setService(IForwardingRulesManagerAware.class)
.setCallbacks("setFrmAware", "unsetFrmAware").setRequired(false));
- c.add(createContainerServiceDependency(containerName).setService(IfIptoHost.class)
- .setCallbacks("setHostFinder", "unsetHostFinder").setRequired(true));
c.add(createContainerServiceDependency(containerName).setService(IContainer.class)
.setCallbacks("setIContainer", "unsetIContainer").setRequired(true));
}
import org.opendaylight.controller.forwardingrulesmanager.PortGroupChangeListener;
import org.opendaylight.controller.forwardingrulesmanager.PortGroupConfig;
import org.opendaylight.controller.forwardingrulesmanager.PortGroupProvider;
-import org.opendaylight.controller.hosttracker.IfIptoHost;
import org.opendaylight.controller.sal.action.Action;
import org.opendaylight.controller.sal.action.ActionType;
import org.opendaylight.controller.sal.action.Controller;
* contain all the flow entries which were installed on the global container
* when the first container is created.
*/
- private List<FlowEntry> inactiveFlows;
+ private ConcurrentMap<FlowEntry, FlowEntry> inactiveFlows;
- private IfIptoHost hostFinder;
private IContainer container;
private Set<IForwardingRulesManagerAware> frmAware;
private PortGroupProvider portGroupProvider;
@Override
public Status installFlowEntry(FlowEntry flowEntry) {
Status status;
- if (inContainerMode) {
+ if (isContainerModeAllowed(flowEntry)) {
+ status = addEntry(flowEntry, false);
+ } else {
String msg = "Controller in container mode: Install Refused";
String logMsg = msg + ": {}";
status = new Status(StatusCode.NOTACCEPTABLE, msg);
log.warn(logMsg, flowEntry);
- } else {
- status = addEntry(flowEntry, false);
}
return status;
}
@Override
public Status installFlowEntryAsync(FlowEntry flowEntry) {
Status status;
- if (inContainerMode) {
+ if (isContainerModeAllowed(flowEntry)) {
+ status = addEntry(flowEntry, true);
+ } else {
String msg = "Controller in container mode: Install Refused";
status = new Status(StatusCode.NOTACCEPTABLE, msg);
log.warn(msg);
- } else {
- status = addEntry(flowEntry, true);
}
return status;
}
@Override
- public Status uninstallFlowEntry(FlowEntry entry) {
+ public Status uninstallFlowEntry(FlowEntry flowEntry) {
Status status;
- if (inContainerMode) {
+ if (isContainerModeAllowed(flowEntry)) {
+ status = removeEntry(flowEntry, false);
+ } else {
String msg = "Controller in container mode: Uninstall Refused";
String logMsg = msg + ": {}";
status = new Status(StatusCode.NOTACCEPTABLE, msg);
- log.warn(logMsg, entry);
- } else {
- status = removeEntry(entry, false);
+ log.warn(logMsg, flowEntry);
}
return status;
}
@Override
public Status uninstallFlowEntryAsync(FlowEntry flowEntry) {
Status status;
- if (inContainerMode) {
+ if (isContainerModeAllowed(flowEntry)) {
+ status = removeEntry(flowEntry, true);
+ } else {
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 status = null;
- if (inContainerMode) {
+ if (isContainerModeAllowed(currentFlowEntry)) {
+ status = modifyEntry(currentFlowEntry, newFlowEntry, false);
+ } else {
String msg = "Controller in container mode: Modify Refused";
String logMsg = msg + ": {}";
status = new Status(StatusCode.NOTACCEPTABLE, msg);
log.warn(logMsg, newFlowEntry);
- } else {
- status = modifyEntry(currentFlowEntry, newFlowEntry, false);
}
return status;
}
@Override
- public Status modifyFlowEntryAsync(FlowEntry current, FlowEntry newone) {
+ public Status modifyFlowEntryAsync(FlowEntry currentFlowEntry, FlowEntry newFlowEntry) {
Status status = null;
- if (inContainerMode) {
+ if (isContainerModeAllowed(currentFlowEntry)) {
+ status = modifyEntry(currentFlowEntry, newFlowEntry, true);
+ } else {
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;
}
+ /**
+ * Returns whether the specified flow entry is allowed to be
+ * installed/removed/modified based on the current container mode status.
+ * This call always returns true in the container instance of forwarding
+ * rules manager. It is meant for the global instance only (default
+ * container) of forwarding rules manager. Idea is that for assuring
+ * container isolation of traffic, flow installation in default container is
+ * blocked when in container mode (containers are present). The only flows
+ * that are allowed in container mode in the default container are the
+ * proactive flows, the ones automatically installed on the network node
+ * which forwarding mode has been configured to "proactive". These flows are
+ * needed by controller to discover the nodes topology and to discover the
+ * attached hosts for some SDN switches.
+ *
+ * @param flowEntry
+ * The flow entry to be installed/removed/modified
+ * @return true if not in container mode or if flowEntry is internally
+ * generated
+ */
+ private boolean isContainerModeAllowed(FlowEntry flowEntry) {
+ return (!inContainerMode) ? true : flowEntry.isInternal();
+ }
+
@Override
public Status modifyOrAddFlowEntry(FlowEntry newFlowEntry) {
/*
if (groupName == null || groupName.isEmpty()) {
return new Status(StatusCode.BADREQUEST, "Invalid group name");
}
- if (groupName.equals(FlowConfig.internalStaticFlowsGroup)) {
- return new Status(StatusCode.BADREQUEST, "Static flows group cannot be deleted through this api");
+ if (groupName.equals(FlowConfig.INTERNALSTATICFLOWGROUP)) {
+ return new Status(StatusCode.BADREQUEST, "Internal static flows group cannot be deleted through this api");
}
if (inContainerMode) {
String msg = "Controller in container mode: Group Uninstall Refused";
if (groupName == null || groupName.isEmpty()) {
return new Status(StatusCode.BADREQUEST, "Invalid group name");
}
- if (groupName.equals(FlowConfig.internalStaticFlowsGroup)) {
+ if (groupName.equals(FlowConfig.INTERNALSTATICFLOWGROUP)) {
return new Status(StatusCode.BADREQUEST, "Static flows group cannot be deleted through this api");
}
if (inContainerMode) {
}
}
- public void nonClusterObjectCreate() {
+ private void nonClusterObjectCreate() {
originalSwView = new ConcurrentHashMap<FlowEntry, FlowEntry>();
installedSwView = new ConcurrentHashMap<FlowEntryInstall, FlowEntryInstall>();
nodeFlows = new ConcurrentHashMap<Node, List<FlowEntryInstall>>();
portGroupData = new ConcurrentHashMap<PortGroupConfig, Map<Node, PortGroup>>();
staticFlows = new ConcurrentHashMap<Integer, FlowConfig>();
flowsSaveEvent = new HashMap<Long, String>();
- inactiveFlows = new ArrayList<FlowEntry>(1);
+ inactiveFlows = new ConcurrentHashMap<FlowEntry, FlowEntry>();
}
private void registerWithOSGIConsole() {
clusterContainerService.createCache("frm.installedSwView",
EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
+ clusterContainerService.createCache("frm.inactiveFlows",
+ EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
+
clusterContainerService.createCache("frm.nodeFlows",
EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
if (this.clusterContainerService == null) {
log.warn("un-initialized clusterContainerService, can't retrieve cache");
+ nonClusterObjectCreate();
return;
}
log.error("Retrieval of frm.installedSwView cache failed for Container {}", container.getName());
}
+ map = clusterContainerService.getCache("frm.inactiveFlows");
+ if (map != null) {
+ inactiveFlows = (ConcurrentMap<FlowEntry, FlowEntry>) map;
+ } else {
+ log.error("Retrieval of frm.inactiveFlows cache failed for Container {}", container.getName());
+ }
+
map = clusterContainerService.getCache("frm.nodeFlows");
if (map != null) {
nodeFlows = (ConcurrentMap<Node, List<FlowEntryInstall>>) map;
}
@Override
- public Status addStaticFlow(FlowConfig config, boolean restore) {
- boolean multipleFlowPush = false;
- String error;
- Status status;
- config.setStatus(SUCCESS);
-
- // Skip validation check if we are trying to restore a saved config
- if (!restore && !(status = config.validate(container)).isSuccess()) {
+ public Status addStaticFlow(FlowConfig config) {
+ // Configuration object validation
+ Status status = config.validate(container);
+ if (!status.isSuccess()) {
log.warn("Invalid Configuration for flow {}. The failure is {}", config, status.getDescription());
- error = "Invalid Configuration (" + status.getDescription() + ")";
+ String error = "Invalid Configuration (" + status.getDescription() + ")";
config.setStatus(error);
return new Status(StatusCode.BADREQUEST, error);
}
+ return addStaticFlowInternal(config, false);
+ }
+
+ /**
+ * Private method to add a static flow configuration which does not run any
+ * validation on the passed FlowConfig object. If restore is set to true,
+ * configuration is stored in configuration database regardless the
+ * installation on the network node was successful. This is useful at boot
+ * when static flows are present in startup configuration and are read
+ * before the switches connects.
+ *
+ * @param config
+ * The static flow configuration
+ * @param restore
+ * if true, the configuration is stored regardless the
+ * installation on the network node was successful
+ * @return The status of this request
+ */
+ private Status addStaticFlowInternal(FlowConfig config, boolean restore) {
+ boolean multipleFlowPush = false;
+ String error;
+ Status status;
+ config.setStatus(SUCCESS);
// Presence check
if (flowConfigExists(config)) {
FlowEntryInstall flowEntries = mapEntry.getValue();
// Skip internal generated static flows
if (!flowEntries.isInternal()) {
- inactiveFlows.add(flowEntries.getOriginal());
+ inactiveFlows.put(flowEntries.getOriginal(), null);
}
}
// Now remove the entries
- for (FlowEntry flowEntry : inactiveFlows) {
+ for (FlowEntry flowEntry : inactiveFlows.keySet()) {
Status status = this.removeEntry(flowEntry, false);
if (!status.isSuccess()) {
log.warn("Failed to remove entry: {}. The failure is: {}", flowEntry, status.getDescription());
private void reinstallAllFlowEntries() {
log.info("Reinstalling all inactive flows");
- for (FlowEntry flowEntry : this.inactiveFlows) {
+ for (FlowEntry flowEntry : this.inactiveFlows.keySet()) {
this.addEntry(flowEntry, false);
}
}
for (FlowConfig conf : getStaticFlowsOrderedList(confList, maxKey)) {
- addStaticFlow(conf, true);
+ addStaticFlowInternal(conf, true);
}
}
FlowConfig allowARP = new FlowConfig();
allowARP.setInstallInHw(true);
- allowARP.setName("**Punt ARP Reply");
+ allowARP.setName(FlowConfig.INTERNALSTATICFLOWBEGIN + "Punt ARP Reply" + FlowConfig.INTERNALSTATICFLOWEND);
allowARP.setPriority("500");
allowARP.setNode(node);
allowARP.setEtherType("0x" + Integer.toHexString(EtherTypes.ARP.intValue()).toUpperCase());
allowARP.setDstMac(HexEncode.bytesToHexString(switchManager.getControllerMAC()));
allowARP.setActions(puntAction);
- addStaticFlow(allowARP, false);
+ addStaticFlowInternal(allowARP, true); // skip validation on internal static flow name
}
@Override
FlowConfig allowARP = new FlowConfig();
allowARP.setInstallInHw(true);
- allowARP.setName("**Punt ARP");
+ allowARP.setName(FlowConfig.INTERNALSTATICFLOWBEGIN + "Punt ARP" + FlowConfig.INTERNALSTATICFLOWEND);
allowARP.setPriority("1");
allowARP.setNode(node);
allowARP.setEtherType("0x" + Integer.toHexString(EtherTypes.ARP.intValue()).toUpperCase());
FlowConfig allowLLDP = new FlowConfig();
allowLLDP.setInstallInHw(true);
- allowLLDP.setName("**Punt LLDP");
+ allowLLDP.setName(FlowConfig.INTERNALSTATICFLOWBEGIN + "Punt LLDP" + FlowConfig.INTERNALSTATICFLOWEND);
allowLLDP.setPriority("1");
allowLLDP.setNode(node);
allowLLDP.setEtherType("0x" + Integer.toHexString(EtherTypes.LLDP.intValue()).toUpperCase());
FlowConfig dropAllConfig = new FlowConfig();
dropAllConfig.setInstallInHw(true);
- dropAllConfig.setName("**Catch-All Drop");
+ dropAllConfig.setName(FlowConfig.INTERNALSTATICFLOWBEGIN + "Catch-All Drop" + FlowConfig.INTERNALSTATICFLOWEND);
dropAllConfig.setPriority("0");
dropAllConfig.setNode(node);
dropAllConfig.setActions(dropAction);
defaultConfigs.add(dropAllConfig);
+ log.info("Forwarding mode for node {} set to {}", node, (proactive ? "proactive" : "reactive"));
for (FlowConfig fc : defaultConfigs) {
- if (proactive) {
- addStaticFlow(fc, false);
+ Status status = (proactive) ? addStaticFlowInternal(fc, true) : removeStaticFlow(fc);
+ if (status.isSuccess()) {
+ log.info("{} Proactive Static flow: {}", (proactive ? "Installed" : "Removed"), fc.getName());
} else {
- removeStaticFlow(fc);
+ log.warn("Failed to {} Proactive Static flow: {}", (proactive ? "install" : "remove"), fc.getName());
}
}
-
- log.info("Set Switch {} Mode to {}", node, (proactive ? "proactive" : "reactive"));
}
/**
if ((staticFlow.getNode().equals(node)) && (staticFlow.getPortGroup().equals(config.getName()))) {
for (Short port : data.getPorts()) {
FlowConfig derivedFlow = getDerivedFlowConfig(staticFlow, config.getName(), port);
- addStaticFlow(derivedFlow, false);
+ addStaticFlowInternal(derivedFlow, false);
}
}
}
}
}
- public void setHostFinder(IfIptoHost hostFinder) {
- this.hostFinder = hostFinder;
- }
-
- public void unsetHostFinder(IfIptoHost hostFinder) {
- if (this.hostFinder == hostFinder) {
- this.hostFinder = null;
- }
- }
-
public void setFrmAware(IForwardingRulesManagerAware obj) {
this.frmAware.add(obj);
}
portGroupProvider.registerPortGroupChange(this);
}
- nonClusterObjectCreate();
-
cacheStartup();
registerWithOSGIConsole();
}
@Override
- public void containerFlowUpdated(String containerName, ContainerFlow previous, ContainerFlow current,
- UpdateType t) {
+ public void containerFlowUpdated(String containerName, ContainerFlow previous, ContainerFlow current, UpdateType t) {
if (!container.getName().equals(containerName)) {
return;
}
log.trace("Received flow removed notification on {} for {}", node, flow);
// For flow entry identification, only node, match and priority matter
- FlowEntryInstall test = new FlowEntryInstall(new FlowEntry("","",flow, node), null);
+ FlowEntryInstall test = new FlowEntryInstall(new FlowEntry("", "", flow, node), null);
FlowEntryInstall installedEntry = this.installedSwView.get(test);
if (installedEntry == null) {
log.trace("Entry is not known to us");
+ RestMessages.RESOURCECONFLICT.toString());
}
- Status status = frm.addStaticFlow(flowConfig.getValue(), false);
+ Status status = frm.addStaticFlow(flowConfig.getValue());
if (status.isSuccess()) {
return Response.status(Response.Status.CREATED).build();
}
Dictionary<String, Object> props = new Hashtable<String, Object>();
// Set the protocolPluginType property which will be used
// by SAL
- props.put("protocolPluginType", Node.NodeIDType.OPENFLOW);
+ props.put(GlobalConstants.PROTOCOLPLUGINTYPE.toString(), Node.NodeIDType.OPENFLOW);
c.setInterface(IPluginInDataPacketService.class.getName(), props);
// Hook the services coming in from SAL, as optional in
// case SAL is not yet there, could happen
Dictionary<String, Object> props = new Hashtable<String, Object>();
// Set the protocolPluginType property which will be used
// by SAL
- props.put("protocolPluginType", Node.NodeIDType.OPENFLOW);
+ props.put(GlobalConstants.PROTOCOLPLUGINTYPE.toString(), Node.NodeIDType.OPENFLOW);
c.setInterface(IPluginInReadService.class.getName(), props);
c.add(createServiceDependency()
.setService(IPluginReadServiceFilter.class)
Dictionary<String, Object> props = new Hashtable<String, Object>();
// Set the protocolPluginType property which will be used
// by SAL
- props.put("protocolPluginType", Node.NodeIDType.OPENFLOW);
+ props.put(GlobalConstants.PROTOCOLPLUGINTYPE.toString(), Node.NodeIDType.OPENFLOW);
c.setInterface(IFlowProgrammerNotifier.class.getName(), props);
c.add(createContainerServiceDependency(containerName)
Dictionary<String, Object> props = new Hashtable<String, Object>();
// Set the protocolPluginType property which will be used
// by SAL
- props.put("protocolPluginType", Node.NodeIDType.OPENFLOW);
+ props.put(GlobalConstants.PROTOCOLPLUGINTYPE.toString(), Node.NodeIDType.OPENFLOW);
c.setInterface(
new String[] {
IPluginInFlowProgrammerService.class.getName(),
Dictionary<String, Object> props = new Hashtable<String, Object>();
// Set the protocolPluginType property which will be used
// by SAL
- props.put("protocolPluginType", "STUB");
+ props.put(GlobalConstants.PROTOCOLPLUGINTYPE.toString(), "STUB");
c.setInterface(IPluginInReadService.class.getName(), props);
}
Dictionary<String, Object> props = new Hashtable<String, Object>();
// Set the protocolPluginType property which will be used
// by SAL
- props.put("protocolPluginType", "STUB");
+ props.put(GlobalConstants.PROTOCOLPLUGINTYPE.toString(), "STUB");
c.setInterface(IPluginInInventoryService.class.getName(), props);
}
}
Dictionary<String, Object> props = new Hashtable<String, Object>();
// Set the protocolPluginType property which will be used
// by SAL
- props.put("protocolPluginType", "STUB");
+ props.put(GlobalConstants.PROTOCOLPLUGINTYPE.toString(), "STUB");
c.setInterface(IPluginInFlowProgrammerService.class.getName(), props);
}
if (imp.equals(StubNodeFactory.class)) {
Dictionary<String, Object> props = new Hashtable<String, Object>();
// Set the protocolPluginType property which will be used
// by SAL
- props.put("protocolPluginType", "STUB");
+ props.put(GlobalConstants.PROTOCOLPLUGINTYPE.toString(), "STUB");
props.put("protocolName", "STUB");
c.setInterface(INodeFactory.class.getName(), props);
}
Dictionary<String, Object> props = new Hashtable<String, Object>();
// Set the protocolPluginType property which will be used
// by SAL
- props.put("protocolPluginType", "STUB");
+ props.put(GlobalConstants.PROTOCOLPLUGINTYPE.toString(), "STUB");
props.put("protocolName", "STUB");
c.setInterface(INodeConnectorFactory.class.getName(), props);
}
CONTAINERNAME("name"),
STATICVLAN("staticvlan"),
CLUSTERINGSERVICES("clusteringservices"),
- STARTUPHOME("configuration/startup/");
+ STARTUPHOME("configuration/startup/"),
+ PROTOCOLPLUGINTYPE("protocolPluginType");
private GlobalConstants(String name) {
this.name = name;
package org.opendaylight.controller.sal.implementation.internal;
+import org.apache.felix.dm.Component;
import org.opendaylight.controller.sal.core.ComponentActivatorAbstractBase;
import org.opendaylight.controller.sal.flowprogrammer.IFlowProgrammerListener;
import org.opendaylight.controller.sal.flowprogrammer.IFlowProgrammerService;
import org.opendaylight.controller.sal.topology.ITopologyService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.apache.felix.dm.Component;
public class Activator extends ComponentActivatorAbstractBase {
protected static final Logger logger = LoggerFactory
* are done by the ComponentActivatorAbstractBase.
*
*/
+ @Override
public void init() {
}
* ComponentActivatorAbstractBase
*
*/
+ @Override
public void destroy() {
}
* instantiated in order to get an fully working implementation
* Object
*/
+ @Override
public Object[] getImplementations() {
Object[] res = { Topology.class, Inventory.class,
FlowProgrammerService.class, ReadService.class,
* per-container different behavior if needed, usually should not
* be the case though.
*/
+ @Override
public void configureInstance(Component c, Object imp, String containerName) {
if (imp.equals(Topology.class)) {
// export the service for Apps and Plugins
c.add(createContainerServiceDependency(containerName)
.setService(IPluginInInventoryService.class)
.setCallbacks("setPluginService", "unsetPluginService")
- .setRequired(true));
+ .setRequired(false));
}
if (imp.equals(FlowProgrammerService.class)) {
.setService(IPluginInFlowProgrammerService.class)
.setCallbacks("setService", "unsetService")
.setRequired(false));
- c.add(createServiceDependency()
+ c.add(createContainerServiceDependency(containerName)
.setService(IFlowProgrammerListener.class)
.setCallbacks("setListener", "unsetListener")
.setRequired(false));
import org.opendaylight.controller.sal.packet.Packet;
import org.opendaylight.controller.sal.packet.PacketResult;
import org.opendaylight.controller.sal.packet.RawPacket;
+import org.opendaylight.controller.sal.utils.GlobalConstants;
import org.opendaylight.controller.sal.utils.NetUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
logger.trace("Prop key:({}) value:({})",entry.getKey(), entry.getValue());
}
- Object value = props.get("protocolPluginType");
+ Object value = props.get(GlobalConstants.PROTOCOLPLUGINTYPE.toString());
if (value instanceof String) {
type = (String) value;
}
logger.trace("Prop key:({}) value:({})",entry.getKey(), entry.getValue());
}
- Object value = props.get("protocoloPluginType");
+ Object value = props.get(GlobalConstants.PROTOCOLPLUGINTYPE.toString());
if (value instanceof String) {
type = (String) value;
}
import org.opendaylight.controller.sal.match.Match;
import org.opendaylight.controller.sal.match.MatchType;
import org.opendaylight.controller.sal.utils.EtherTypes;
+import org.opendaylight.controller.sal.utils.GlobalConstants;
import org.opendaylight.controller.sal.utils.IPProtocols;
import org.opendaylight.controller.sal.utils.NodeConnectorCreator;
import org.opendaylight.controller.sal.utils.Status;
entry.getValue());
}
- Object value = props.get("protocolPluginType");
+ Object value = props.get(GlobalConstants.PROTOCOLPLUGINTYPE.toString());
if (value instanceof String) {
type = (String) value;
}
entry.getValue());
}
- Object value = props.get("protocoloPluginType");
+ Object value = props.get(GlobalConstants.PROTOCOLPLUGINTYPE.toString());
if (value instanceof String) {
type = (String) value;
}
import org.opendaylight.controller.sal.reader.NodeDescription;
import org.opendaylight.controller.sal.reader.NodeTableStatistics;
import org.opendaylight.controller.sal.utils.EtherTypes;
+import org.opendaylight.controller.sal.utils.GlobalConstants;
import org.opendaylight.controller.sal.utils.IPProtocols;
import org.opendaylight.controller.sal.utils.NodeConnectorCreator;
import org.opendaylight.controller.sal.utils.NodeCreator;
entry.getValue());
}
- Object value = props.get("protocolPluginType");
+ Object value = props.get(GlobalConstants.PROTOCOLPLUGINTYPE.toString());
if (value instanceof String) {
type = (String) value;
}
entry.getValue());
}
- Object value = props.get("protocoloPluginType");
+ Object value = props.get(GlobalConstants.PROTOCOLPLUGINTYPE.toString());
if (value instanceof String) {
type = (String) value;
}
import org.apache.maven.project.MavenProject;
import org.opendaylight.controller.sal.binding.generator.api.BindingGenerator;
import org.opendaylight.controller.sal.binding.generator.impl.BindingGeneratorImpl;
-import org.opendaylight.controller.sal.binding.model.api.GeneratedTransferObject;
import org.opendaylight.controller.sal.binding.model.api.Enumeration;
+import org.opendaylight.controller.sal.binding.model.api.GeneratedTransferObject;
import org.opendaylight.controller.sal.binding.model.api.GeneratedType;
import org.opendaylight.controller.sal.binding.model.api.Type;
import org.opendaylight.controller.sal.java.api.generator.GeneratorJavaFile;
public final class CodeGeneratorImpl implements CodeGenerator {
- @Override
- public Collection<File> generateSources(SchemaContext context,
- File outputBaseDir, Set<Module> yangModules) throws IOException {
+ @Override
+ public Collection<File> generateSources(SchemaContext context, File outputBaseDir, Set<Module> yangModules)
+ throws IOException {
+ if (outputBaseDir == null) {
+ outputBaseDir = new File("target" + File.separator + "generated-sources" + File.separator + "maven-sal-api-gen");
+ }
- final BindingGenerator bindingGenerator = new BindingGeneratorImpl();
- final List<Type> types = bindingGenerator.generateTypes(context,yangModules);
- final Set<GeneratedType> typesToGenerate = new HashSet<>();
- final Set<GeneratedTransferObject> tosToGenerate = new HashSet<>();
- final Set<Enumeration> enumsToGenerate = new HashSet<>();
+ final BindingGenerator bindingGenerator = new BindingGeneratorImpl();
+ final List<Type> types = bindingGenerator.generateTypes(context, yangModules);
+ final Set<GeneratedType> typesToGenerate = new HashSet<>();
+ final Set<GeneratedTransferObject> tosToGenerate = new HashSet<>();
+ final Set<Enumeration> enumsToGenerate = new HashSet<>();
- for (Type type : types) {
- if (type instanceof GeneratedTransferObject) {
- tosToGenerate.add((GeneratedTransferObject) type);
- } else if (type instanceof GeneratedType) {
- typesToGenerate.add((GeneratedType) type);
- } else if (type instanceof Enumeration) {
- enumsToGenerate.add((Enumeration) type);
- }
+ for (Type type : types) {
+ if (type instanceof GeneratedTransferObject) {
+ tosToGenerate.add((GeneratedTransferObject) type);
+ } else if (type instanceof GeneratedType) {
+ typesToGenerate.add((GeneratedType) type);
+ } else if (type instanceof Enumeration) {
+ enumsToGenerate.add((Enumeration) type);
+ }
}
- final GeneratorJavaFile generator = new GeneratorJavaFile(
- typesToGenerate, tosToGenerate, enumsToGenerate);
+ final GeneratorJavaFile generator = new GeneratorJavaFile(typesToGenerate, tosToGenerate, enumsToGenerate);
return generator.generateToFile(outputBaseDir);
}
@Override
public void setMavenProject(MavenProject project) {
// no additional information needed
- }
+ }
}
v.verifyTextInLog("[DEBUG] yang-to-sources: Additional configuration picked up for : org.opendaylight.controller.yang2sources.spi.CodeGeneratorTestImpl: {nm1=abcd=a.b.c.d, nm2=abcd2=a.b.c.d.2}");
v.verifyTextInLog("[DEBUG] yang-to-sources: Additional configuration picked up for : org.opendaylight.controller.yang2sources.spi.CodeGeneratorTestImpl: {c1=config}");
v.verifyTextInLog(File.separator
- + "files marked as resources: META-INF" + File.separator
- + "yang");
+ + "files marked as resources: META-INF/yang");
v.verifyTextInLog("target"
+ File.separator
+ "generated-resources marked as resources for generator: org.opendaylight.controller.yang2sources.spi.CodeGeneratorTestImpl");
private final File outputBaseDir;
public ConfigArg(String outputBaseDir) {
- this.outputBaseDir = new File(outputBaseDir);
+ this.outputBaseDir = outputBaseDir == null ? null : new File(outputBaseDir);
}
public File getOutputBaseDir(MavenProject project) {
+ if (outputBaseDir == null) {
+ return null;
+ }
if (outputBaseDir.isAbsolute()) {
return outputBaseDir;
} else {
* Configuration argument for code generator class and output directory.
*/
public static final class CodeGeneratorArg extends ConfigArg {
- private static final String CODE_GEN_DEFAULT_DIR = "target"
- + File.separator + "generated-sources";
- private static final String CODE_GEN_DEFAULT_RESOURCE_DIR = "target"
- + File.separator + "generated-resources";
+ private static final String CODE_GEN_DEFAULT_RESOURCE_DIR = "target" + File.separator + "generated-resources";
+
private String codeGeneratorClass;
private File resourceBaseDir = new File(CODE_GEN_DEFAULT_RESOURCE_DIR);
private Map<String, String> additionalConfiguration = Maps.newHashMap();
public CodeGeneratorArg() {
- super(CODE_GEN_DEFAULT_DIR);
+ super(null);
}
public CodeGeneratorArg(String codeGeneratorClass) {
- this(codeGeneratorClass, CODE_GEN_DEFAULT_DIR);
+ this(codeGeneratorClass, null);
}
public CodeGeneratorArg(String codeGeneratorClass, String outputBaseDir) {
this.codeGeneratorClass = codeGeneratorClass;
}
- public CodeGeneratorArg(String codeGeneratorClass,
- String outputBaseDir, String resourceBaseDir) {
+ public CodeGeneratorArg(String codeGeneratorClass, String outputBaseDir, String resourceBaseDir) {
super(outputBaseDir);
this.codeGeneratorClass = codeGeneratorClass;
this.resourceBaseDir = new File(resourceBaseDir);
@Override
public void check() {
- Preconditions.checkNotNull(codeGeneratorClass,
- "codeGeneratorClass for CodeGenerator cannot be null");
+ Preconditions.checkNotNull(codeGeneratorClass, "codeGeneratorClass for CodeGenerator cannot be null");
}
public String getCodeGeneratorClass() {
throw new MojoFailureException(message, e);
}
- setResource(targetYangDir, META_INF_YANG_DIR.getPath(), project);
+ setResource(targetYangDir, META_INF_YANG_STRING_JAR, project);
log.debug(Util.message(
"Yang files from: %s marked as resources: %s", LOG_PREFIX,
- yangFilesRootDir, META_INF_YANG_DIR.getPath()));
+ yangFilesRootDir, META_INF_YANG_STRING_JAR));
}
private static void setResource(File targetYangDir, String targetPath,
codeGeneratorCfg.getCodeGeneratorClass(),
codeGeneratorCfg.getAdditionalConfiguration()));
- project.addCompileSourceRoot(outputDir.getAbsolutePath());
+ if(outputDir != null) {
+ project.addCompileSourceRoot(outputDir.getAbsolutePath());
+ }
g.setLog(log);
g.setMavenProject(project);
g.setAdditionalConfig(codeGeneratorCfg.getAdditionalConfiguration());
*/
package org.opendaylight.controller.yang.parser.builder.api;
+import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import org.opendaylight.controller.yang.common.QName;
import org.opendaylight.controller.yang.model.api.DataSchemaNode;
import org.opendaylight.controller.yang.model.api.GroupingDefinition;
+import org.opendaylight.controller.yang.parser.util.YangParseException;
public abstract class AbstractDataNodeContainerBuilder implements DataNodeContainerBuilder {
protected final int line;
@Override
public Set<DataSchemaNode> getChildNodes() {
+ if (childNodes == null) {
+ return Collections.emptySet();
+ }
return childNodes;
}
}
@Override
- public void addChildNode(DataSchemaNodeBuilder childNode) {
- addedChildNodes.add(childNode);
+ public DataSchemaNodeBuilder getDataChildByName(final String name) {
+ for (DataSchemaNodeBuilder child : addedChildNodes) {
+ if (child.getQName().getLocalName().equals(name)) {
+ return child;
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public void addChildNode(DataSchemaNodeBuilder child) {
+ for (DataSchemaNodeBuilder childNode : addedChildNodes) {
+ if (childNode.getQName().getLocalName().equals(child.getQName().getLocalName())) {
+ throw new YangParseException(child.getLine(), "Duplicate node found at line " + childNode.getLine());
+ }
+ }
+ addedChildNodes.add(child);
}
@Override
public Set<GroupingDefinition> getGroupings() {
+ if (groupings == null) {
+ return Collections.emptySet();
+ }
return groupings;
}
}
@Override
- public void addGrouping(GroupingBuilder grouping) {
- addedGroupings.add(grouping);
+ public void addGrouping(GroupingBuilder groupingBuilder) {
+ for (GroupingBuilder gb : addedGroupings) {
+ if (gb.getQName().getLocalName().equals(groupingBuilder.getQName().getLocalName())) {
+ throw new YangParseException(groupingBuilder.getLine(), "Duplicate node found at line " + gb.getLine());
+ }
+ }
+ addedGroupings.add(groupingBuilder);
}
}
import org.opendaylight.controller.yang.common.QName;\r
import org.opendaylight.controller.yang.model.api.SchemaPath;\r
import org.opendaylight.controller.yang.model.api.Status;\r
+import org.opendaylight.controller.yang.model.api.UnknownSchemaNode;\r
import org.opendaylight.controller.yang.parser.builder.impl.UnknownSchemaNodeBuilder;\r
\r
/**\r
protected String description;\r
protected String reference;\r
protected Status status = Status.CURRENT;\r
+ protected List<UnknownSchemaNode> unknownNodes;\r
protected final List<UnknownSchemaNodeBuilder> addedUnknownNodes = new ArrayList<UnknownSchemaNodeBuilder>();\r
\r
protected AbstractSchemaNodeBuilder(final int line, final QName qname) {\r
this.parent = parent;\r
}\r
\r
+ @Override\r
public SchemaPath getPath() {\r
return schemaPath;\r
}\r
\r
+ @Override\r
public void setPath(SchemaPath schemaPath) {\r
this.schemaPath = schemaPath;\r
}\r
\r
+ @Override\r
public String getDescription() {\r
return description;\r
}\r
\r
+ @Override\r
public void setDescription(String description) {\r
this.description = description;\r
}\r
\r
+ @Override\r
public String getReference() {\r
return reference;\r
}\r
\r
+ @Override\r
public void setReference(String reference) {\r
this.reference = reference;\r
}\r
\r
+ @Override\r
public Status getStatus() {\r
return status;\r
}\r
\r
+ @Override\r
public void setStatus(Status status) {\r
if (status != null) {\r
this.status = status;\r
addedUnknownNodes.add(unknownNode);\r
}\r
\r
+ public void setUnknownNodes(List<UnknownSchemaNode> unknownNodes) {\r
+ this.unknownNodes = unknownNodes;\r
+ }\r
+\r
}\r
Set<DataSchemaNodeBuilder> getChildNodeBuilders();
+ DataSchemaNodeBuilder getDataChildByName(String name);
+
void addChildNode(DataSchemaNodeBuilder childNode);
Set<GroupingDefinition> getGroupings();
private boolean built;
private final AnyXmlSchemaNodeImpl instance;
private final ConstraintsBuilder constraints;
- private List<UnknownSchemaNode> unknownNodes;
private Boolean configuration;
private boolean augmenting;
return addedUnknownNodes;
}
- public void setUnknownNodes(List<UnknownSchemaNode> unknownNodes) {
- this.unknownNodes = unknownNodes;
- }
-
@Override
public boolean isAugmenting() {
return augmenting;
import org.opendaylight.controller.yang.model.api.UnknownSchemaNode;
import org.opendaylight.controller.yang.model.api.UsesNode;
import org.opendaylight.controller.yang.model.util.RevisionAwareXPathImpl;
+import org.opendaylight.controller.yang.parser.builder.api.AbstractDataNodeContainerBuilder;
import org.opendaylight.controller.yang.parser.builder.api.AugmentationSchemaBuilder;
-import org.opendaylight.controller.yang.parser.builder.api.Builder;
import org.opendaylight.controller.yang.parser.builder.api.DataSchemaNodeBuilder;
import org.opendaylight.controller.yang.parser.builder.api.GroupingBuilder;
import org.opendaylight.controller.yang.parser.builder.api.TypeDefinitionBuilder;
import org.opendaylight.controller.yang.parser.builder.api.UsesNodeBuilder;
import org.opendaylight.controller.yang.parser.util.Comparators;
-import org.opendaylight.controller.yang.parser.util.YangModelBuilderUtil;
+import org.opendaylight.controller.yang.parser.util.ParserListenerUtils;
import org.opendaylight.controller.yang.parser.util.YangParseException;
-public final class AugmentationSchemaBuilderImpl implements AugmentationSchemaBuilder {
+public final class AugmentationSchemaBuilderImpl extends AbstractDataNodeContainerBuilder implements
+ AugmentationSchemaBuilder {
private boolean built;
private final AugmentationSchemaImpl instance;
- private final int line;
- private Builder parent;
private String whenCondition;
private String description;
private SchemaPath dirtyAugmentTarget;
private SchemaPath finalAugmentTarget;
- private final Set<DataSchemaNodeBuilder> childNodes = new HashSet<DataSchemaNodeBuilder>();
- private final Set<GroupingBuilder> groupings = new HashSet<GroupingBuilder>();
private final Set<UsesNodeBuilder> usesNodes = new HashSet<UsesNodeBuilder>();
private final List<UnknownSchemaNodeBuilder> addedUnknownNodes = new ArrayList<UnknownSchemaNodeBuilder>();
private boolean resolved;
AugmentationSchemaBuilderImpl(final int line, final String augmentTargetStr) {
+ super(line, null);
this.augmentTargetStr = augmentTargetStr;
- this.line = line;
- final SchemaPath targetPath = YangModelBuilderUtil.parseAugmentPath(augmentTargetStr);
+ final SchemaPath targetPath = ParserListenerUtils.parseAugmentPath(augmentTargetStr);
dirtyAugmentTarget = targetPath;
instance = new AugmentationSchemaImpl(targetPath);
}
- @Override
- public int getLine() {
- return line;
- }
-
- @Override
- public Builder getParent() {
- return parent;
- }
-
- @Override
- public void setParent(final Builder parent) {
- this.parent = parent;
- }
-
- @Override
- public void addChildNode(DataSchemaNodeBuilder childNode) {
- childNodes.add(childNode);
- }
-
- @Override
- public Set<DataSchemaNode> getChildNodes() {
- return Collections.emptySet();
- }
-
- @Override
- public Set<DataSchemaNodeBuilder> getChildNodeBuilders() {
- return childNodes;
- }
-
@Override
public Set<GroupingDefinition> getGroupings() {
return Collections.emptySet();
@Override
public Set<GroupingBuilder> getGroupingBuilders() {
- return groupings;
+ return Collections.emptySet();
}
@Override
public void addGrouping(GroupingBuilder grouping) {
- groupings.add(grouping);
+ throw new YangParseException(line, "augment can not contains grouping statement");
}
@Override
usesNodes.add(usesBuilder);
}
- /**
- * Always returns null.
- */
- @Override
- public QName getQName() {
- return null;
- }
-
/**
* Always returns null.
*/
// CHILD NODES
final Map<QName, DataSchemaNode> childs = new TreeMap<QName, DataSchemaNode>(Comparators.QNAME_COMP);
- for (DataSchemaNodeBuilder node : childNodes) {
+ for (DataSchemaNodeBuilder node : addedChildNodes) {
childs.put(node.getQName(), node.build());
}
instance.setChildNodes(childs);
- // GROUPINGS
- final Set<GroupingDefinition> groupingDefinitions = new TreeSet<GroupingDefinition>(
- Comparators.SCHEMA_NODE_COMP);
- for (GroupingBuilder builder : groupings) {
- groupingDefinitions.add(builder.build());
- }
- instance.setGroupings(groupingDefinitions);
-
// USES
final Set<UsesNode> usesNodeDefinitions = new HashSet<UsesNode>();
for (UsesNodeBuilder builder : usesNodes) {
private SchemaPath targetPath;
private RevisionAwareXPath whenCondition;
private Map<QName, DataSchemaNode> childNodes = Collections.emptyMap();
- private Set<GroupingDefinition> groupings = Collections.emptySet();
private Set<UsesNode> uses = Collections.emptySet();
private String description;
private String reference;
}
}
+ /**
+ * Always returns an empty set, because augment can not contains
+ * grouping statement.
+ */
@Override
public Set<GroupingDefinition> getGroupings() {
- return groupings;
- }
-
- private void setGroupings(Set<GroupingDefinition> groupings) {
- if (groupings != null) {
- this.groupings = groupings;
- }
+ return Collections.emptySet();
}
@Override
}
/**
- * Always returns an empty set, because augmentation can not contains
- * type definitions.
+ * Always returns an empty set, because augment can not contains type
+ * definitions.
*/
@Override
public Set<TypeDefinition<?>> getTypeDefinitions() {
AugmentationTargetBuilder, GroupingMember, ConfigNode {
private boolean isBuilt;
private final ChoiceNodeImpl instance;
- // SchemaNode args
- private List<UnknownSchemaNode> unknownNodes;
// DataSchemaNode args
private boolean augmenting;
private boolean addedByUses;
return addedUnknownNodes;
}
- public void setUnknownNodes(List<UnknownSchemaNode> unknownNodes) {
- this.unknownNodes = unknownNodes;
- }
-
public String getDefaultCase() {
return defaultCase;
}
import org.opendaylight.controller.yang.model.api.UnknownSchemaNode;
import org.opendaylight.controller.yang.parser.builder.api.Builder;
import org.opendaylight.controller.yang.parser.util.Comparators;
-import org.opendaylight.controller.yang.parser.util.YangModelBuilderUtil;
+import org.opendaylight.controller.yang.parser.util.ParserListenerUtils;
import org.opendaylight.controller.yang.parser.util.YangParseException;
public final class DeviationBuilder implements Builder {
private final int line;
private Builder parent;
+ private boolean isBuilt;
private final DeviationImpl instance;
+
+ private SchemaPath targetPath;
+ private String reference;
private final List<UnknownSchemaNodeBuilder> addedUnknownNodes = new ArrayList<UnknownSchemaNodeBuilder>();
- DeviationBuilder(final String targetPathStr, final int line) {
+ DeviationBuilder(final int line, final String targetPathStr) {
+ if(!targetPathStr.startsWith("/")) {
+ throw new YangParseException(line, "Deviation argument string must be an absolute schema node identifier.");
+ }
this.line = line;
- final SchemaPath targetPath = YangModelBuilderUtil
- .parseAugmentPath(targetPathStr);
- instance = new DeviationImpl(targetPath);
+ this.targetPath = ParserListenerUtils.parseAugmentPath(targetPathStr);
+ instance = new DeviationImpl();
}
@Override
public Deviation build() {
- // UNKNOWN NODES
- List<UnknownSchemaNode> unknownNodes = new ArrayList<UnknownSchemaNode>();
- for (UnknownSchemaNodeBuilder b : addedUnknownNodes) {
- unknownNodes.add(b.build());
+ if(targetPath == null) {
+ throw new YangParseException(line, "Unresolved deviation target");
+ }
+
+ if(!isBuilt) {
+ instance.setTargetPath(targetPath);
+ instance.setReference(reference);
+
+ // UNKNOWN NODES
+ List<UnknownSchemaNode> unknownNodes = new ArrayList<UnknownSchemaNode>();
+ for (UnknownSchemaNodeBuilder b : addedUnknownNodes) {
+ unknownNodes.add(b.build());
+ }
+ Collections.sort(unknownNodes, Comparators.SCHEMA_NODE_COMP);
+ instance.setUnknownSchemaNodes(unknownNodes);
+
+ isBuilt = true;
}
- Collections.sort(unknownNodes, Comparators.SCHEMA_NODE_COMP);
- instance.setUnknownSchemaNodes(unknownNodes);
return instance;
}
addedUnknownNodes.add(unknownNode);
}
+ public SchemaPath getTargetPath() {
+ return targetPath;
+ }
+
+ public void setTargetPath(final SchemaPath targetPath) {
+ this.targetPath = targetPath;
+ }
+
public void setDeviate(final String deviate) {
if ("not-supported".equals(deviate)) {
instance.setDeviate(Deviate.NOT_SUPPORTED);
}
public void setReference(final String reference) {
- instance.setReference(reference);
+ this.reference = reference;
}
private final class DeviationImpl implements Deviation {
- private final SchemaPath targetPath;
+ private SchemaPath targetPath;
private Deviate deviate;
private String reference;
private List<UnknownSchemaNode> unknownNodes = Collections.emptyList();
- private DeviationImpl(final SchemaPath targetPath) {
- this.targetPath = targetPath;
+ private DeviationImpl() {
}
@Override
return targetPath;
}
+ private void setTargetPath(final SchemaPath targetPath) {
+ this.targetPath = targetPath;
+ }
+
@Override
public Deviate getDeviate() {
return deviate;
this.reference = reference;
}
+ @Override
public List<UnknownSchemaNode> getUnknownSchemaNodes() {
return unknownNodes;
}
instance.setStatus(status);
// UNKNOWN NODES
- final List<UnknownSchemaNode> unknownNodes = new ArrayList<UnknownSchemaNode>();
- for (UnknownSchemaNodeBuilder un : addedUnknownNodes) {
- unknownNodes.add(un.build());
+ if (unknownNodes == null) {
+ unknownNodes = new ArrayList<UnknownSchemaNode>();
+ for (UnknownSchemaNodeBuilder un : addedUnknownNodes) {
+ unknownNodes.add(un.build());
+ }
+ Collections.sort(unknownNodes, Comparators.SCHEMA_NODE_COMP);
}
- Collections.sort(unknownNodes, Comparators.SCHEMA_NODE_COMP);
instance.setUnknownSchemaNodes(unknownNodes);
isBuilt = true;
instance.setStatus(status);
// UNKNOWN NODES
- final List<UnknownSchemaNode> unknownNodes = new ArrayList<UnknownSchemaNode>();
- for (UnknownSchemaNodeBuilder b : addedUnknownNodes) {
- unknownNodes.add(b.build());
+ if (unknownNodes == null) {
+ unknownNodes = new ArrayList<UnknownSchemaNode>();
+ for (UnknownSchemaNodeBuilder b : addedUnknownNodes) {
+ unknownNodes.add(b.build());
+ }
+ Collections.sort(unknownNodes, Comparators.SCHEMA_NODE_COMP);
}
- Collections.sort(unknownNodes, Comparators.SCHEMA_NODE_COMP);
instance.setUnknownSchemaNodes(unknownNodes);
isBuilt = true;
return addedChildNodes;
}
+ @Override
+ public DataSchemaNodeBuilder getDataChildByName(final String name) {
+ for(DataSchemaNodeBuilder child : addedChildNodes) {
+ if(child.getQName().getLocalName().equals(name)) {
+ return child;
+ }
+ }
+ return null;
+ }
+
public void setChildNodes(final Set<DataSchemaNode> childNodes) {
this.childNodes = childNodes;
}
}
// UNKNOWN NODES
- final List<UnknownSchemaNode> unknownNodes = new ArrayList<UnknownSchemaNode>();
- for (UnknownSchemaNodeBuilder b : addedUnknownNodes) {
- unknownNodes.add(b.build());
+ if (unknownNodes == null) {
+ unknownNodes = new ArrayList<UnknownSchemaNode>();
+ for (UnknownSchemaNodeBuilder b : addedUnknownNodes) {
+ unknownNodes.add(b.build());
+ }
+ Collections.sort(unknownNodes, Comparators.SCHEMA_NODE_COMP);
}
- Collections.sort(unknownNodes, Comparators.SCHEMA_NODE_COMP);
instance.setUnknownSchemaNodes(unknownNodes);
isBuilt = true;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
-import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import org.opendaylight.controller.yang.model.api.TypeDefinition;
import org.opendaylight.controller.yang.model.api.UnknownSchemaNode;
import org.opendaylight.controller.yang.model.api.UsesNode;
+import org.opendaylight.controller.yang.parser.builder.api.AbstractDataNodeContainerBuilder;
import org.opendaylight.controller.yang.parser.builder.api.AugmentationSchemaBuilder;
import org.opendaylight.controller.yang.parser.builder.api.Builder;
import org.opendaylight.controller.yang.parser.builder.api.DataNodeContainerBuilder;
import org.opendaylight.controller.yang.parser.util.YangParseException;
/**
- * This builder builds Module object. If this module is dependent on external
+ * Builder of Module object. If this module is dependent on external
* module/modules, these dependencies must be resolved before module is built,
* otherwise result may not be valid.
*/
-public class ModuleBuilder implements DataNodeContainerBuilder {
+public class ModuleBuilder extends AbstractDataNodeContainerBuilder {
private final ModuleImpl instance;
private final String name;
private URI namespace;
private int augmentsResolved;
- private final Set<ModuleImport> imports = new HashSet<ModuleImport>();
-
- /**
- * Holds all child (DataSchemaNode) nodes: anyxml, choice, case, container,
- * list, leaf, leaf-list.
- */
- private final Set<DataSchemaNodeBuilder> childNodes = new HashSet<DataSchemaNodeBuilder>();
+ private final LinkedList<Builder> actualPath = new LinkedList<Builder>();
+ private final Set<TypeAwareBuilder> dirtyNodes = new HashSet<TypeAwareBuilder>();
- private final Set<GroupingBuilder> addedGroupings = new HashSet<GroupingBuilder>();
+ private final Set<ModuleImport> imports = new HashSet<ModuleImport>();
private final List<AugmentationSchemaBuilder> addedAugments = new ArrayList<AugmentationSchemaBuilder>();
private final List<AugmentationSchemaBuilder> allAugments = new ArrayList<AugmentationSchemaBuilder>();
private final Set<UsesNodeBuilder> addedUsesNodes = new HashSet<UsesNodeBuilder>();
private final Set<NotificationBuilder> addedNotifications = new HashSet<NotificationBuilder>();
private final Set<IdentitySchemaNodeBuilder> addedIdentities = new HashSet<IdentitySchemaNodeBuilder>();
private final Set<FeatureBuilder> addedFeatures = new HashSet<FeatureBuilder>();
- private final Map<List<String>, DeviationBuilder> addedDeviations = new HashMap<List<String>, DeviationBuilder>();
+ private final Set<DeviationBuilder> addedDeviations = new HashSet<DeviationBuilder>();
private final Set<TypeDefinitionBuilder> addedTypedefs = new HashSet<TypeDefinitionBuilder>();
- private final Map<List<String>, UnionTypeBuilder> addedUnionTypes = new HashMap<List<String>, UnionTypeBuilder>();
private final List<ExtensionBuilder> addedExtensions = new ArrayList<ExtensionBuilder>();
- private final Map<List<String>, List<UnknownSchemaNodeBuilder>> addedUnknownNodes = new HashMap<List<String>, List<UnknownSchemaNodeBuilder>>();
-
- private final Map<List<String>, TypeAwareBuilder> dirtyNodes = new HashMap<List<String>, TypeAwareBuilder>();
-
- private final LinkedList<Builder> actualPath = new LinkedList<Builder>();
+ private final List<UnknownSchemaNodeBuilder> addedUnknownNodes = new ArrayList<UnknownSchemaNodeBuilder>();
+ private final List<UnknownSchemaNodeBuilder> allUnknownNodes = new ArrayList<UnknownSchemaNodeBuilder>();
public ModuleBuilder(final String name) {
+ super(0, null);
this.name = name;
instance = new ModuleImpl(name);
}
// CHILD NODES
final Map<QName, DataSchemaNode> children = new TreeMap<QName, DataSchemaNode>(Comparators.QNAME_COMP);
- for (DataSchemaNodeBuilder child : childNodes) {
+ for (DataSchemaNodeBuilder child : addedChildNodes) {
children.put(child.getQName(), child.build());
}
instance.setChildNodes(children);
// DEVIATIONS
final Set<Deviation> deviations = new HashSet<Deviation>();
- for (Map.Entry<List<String>, DeviationBuilder> entry : addedDeviations.entrySet()) {
- deviations.add(entry.getValue().build());
+ for (DeviationBuilder entry : addedDeviations) {
+ deviations.add(entry.build());
}
instance.setDeviations(deviations);
instance.setIdentities(identities);
// UNKNOWN NODES
- final List<UnknownSchemaNode> unknownNodes = buildModuleUnknownNodes(addedUnknownNodes);
+ final List<UnknownSchemaNode> unknownNodes = new ArrayList<UnknownSchemaNode>();
+ for (UnknownSchemaNodeBuilder unb : addedUnknownNodes) {
+ unknownNodes.add(unb.build());
+ }
instance.setUnknownSchemaNodes(unknownNodes);
return instance;
}
- @Override
- public int getLine() {
- return 0;
- }
-
- @Override
- public Builder getParent() {
- return null;
- }
-
@Override
public void setParent(Builder parent) {
throw new YangParseException(name, 0, "Can not set parent to module");
}
- @Override
- public QName getQName() {
- return new QName(namespace, revision, prefix, name);
- }
-
@Override
public SchemaPath getPath() {
return null;
}
}
- @Override
- public Set<GroupingDefinition> getGroupings() {
- return Collections.emptySet();
- }
-
- @Override
- public Set<GroupingBuilder> getGroupingBuilders() {
- return addedGroupings;
- }
-
- @Override
- public Set<DataSchemaNode> getChildNodes() {
- return Collections.emptySet();
- }
-
- public Set<DataSchemaNodeBuilder> getChildNodeBuilders() {
- return childNodes;
- }
-
- public Map<List<String>, TypeAwareBuilder> getDirtyNodes() {
+ public Set<TypeAwareBuilder> getDirtyNodes() {
return dirtyNodes;
}
return allUsesNodes;
}
- public List<UnknownSchemaNodeBuilder> getUnknownNodes() {
- List<UnknownSchemaNodeBuilder> result = new ArrayList<UnknownSchemaNodeBuilder>();
- for (List<UnknownSchemaNodeBuilder> entry : addedUnknownNodes.values()) {
- result.addAll(entry);
- }
- return result;
+ public Set<DeviationBuilder> getDeviations() {
+ return addedDeviations;
+ }
+
+ public List<UnknownSchemaNodeBuilder> getAllUnknownNodes() {
+ return allUnknownNodes;
}
public String getName() {
augmentsResolved++;
}
- public void addDirtyNode(final List<String> path) {
- final List<String> dirtyNodePath = new ArrayList<String>(path);
- final TypeAwareBuilder nodeBuilder = (TypeAwareBuilder) actualPath.getFirst();
- dirtyNodes.put(dirtyNodePath, nodeBuilder);
+ public void markActualNodeDirty() {
+ final TypeAwareBuilder nodeBuilder = (TypeAwareBuilder) getActualNode();
+ dirtyNodes.add(nodeBuilder);
}
public void setRevision(final Date revision) {
return builder;
}
- @Override
- public void addChildNode(DataSchemaNodeBuilder child) {
- for (DataSchemaNodeBuilder childNode : childNodes) {
- if (childNode.getQName().getLocalName().equals(child.getQName().getLocalName())) {
- throw new YangParseException(name, child.getLine(), "Duplicate node found at line "
- + childNode.getLine());
- }
- }
- childNodes.add(child);
- }
-
public ContainerSchemaNodeBuilder addContainerNode(final int line, final QName containerName,
final SchemaPath schemaPath) {
final ContainerSchemaNodeBuilder builder = new ContainerSchemaNodeBuilder(line, containerName, schemaPath);
return builder;
}
- @Override
- public void addGrouping(GroupingBuilder groupingBuilder) {
- for (GroupingBuilder gb : addedGroupings) {
- if (gb.getQName().getLocalName().equals(groupingBuilder.getQName().getLocalName())) {
- throw new YangParseException(name, groupingBuilder.getLine(), "Duplicate node found at line "
- + gb.getLine());
- }
- }
- addedGroupings.add(groupingBuilder);
- }
-
public GroupingBuilder addGrouping(final int line, final QName qname) {
final GroupingBuilder builder = new GroupingBuilderImpl(qname, line);
Builder parent = getActualNode();
if (parent == null || !(parent instanceof TypeAwareBuilder)) {
throw new YangParseException("Failed to set type '" + type.getQName().getLocalName()
- + "'. Unknown parent node: " + parent);
+ + "'. Invalid parent node: " + parent);
}
((TypeAwareBuilder) parent).setType(type);
}
- public UnionTypeBuilder addUnionType(final List<String> currentPath, final URI namespace, final Date revision,
- final int line) {
- final List<String> pathToUnion = new ArrayList<String>(currentPath);
- final UnionTypeBuilder union = new UnionTypeBuilder(line);
-
- if (actualPath.isEmpty()) {
- throw new YangParseException(line, "union error");
+ public UnionTypeBuilder addUnionType(final int line, final URI namespace, final Date revision) {
+ final Builder parent = getActualNode();
+ if (parent == null) {
+ throw new YangParseException(line, "Error while parsing union type");
} else {
- final Builder parent = actualPath.getFirst();
+ final UnionTypeBuilder union = new UnionTypeBuilder(line);
if (parent instanceof TypeAwareBuilder) {
-
((TypeAwareBuilder) parent).setTypedef(union);
-
- final List<String> path = new ArrayList<String>(pathToUnion);
- path.add("union");
-
- addedUnionTypes.put(path, union);
return union;
} else {
- throw new YangParseException(name, line, "Unresolved parent of union type.");
+ throw new YangParseException(name, line, "Invalid parent of union type.");
}
}
}
- public void addIdentityrefType(final String baseString, final List<String> parentPath, final SchemaPath schemaPath,
- final int line) {
- final List<String> pathToIdentityref = new ArrayList<String>(parentPath);
+ public void addIdentityrefType(final int line, final SchemaPath schemaPath, final String baseString) {
final IdentityrefTypeBuilder identityref = new IdentityrefTypeBuilder(baseString, schemaPath, line);
- if (actualPath.isEmpty()) {
- throw new YangParseException(line, "identityref error");
+ final Builder parent = getActualNode();
+ if (parent == null) {
+ throw new YangParseException(line, "Error while parsing identityref type.");
} else {
- final Builder parent = actualPath.getFirst();
if (parent instanceof TypeAwareBuilder) {
final TypeAwareBuilder typeParent = (TypeAwareBuilder) parent;
typeParent.setTypedef(identityref);
- dirtyNodes.put(pathToIdentityref, typeParent);
+ dirtyNodes.add(typeParent);
} else {
- throw new YangParseException(name, line, "Unresolved parent of identityref type.");
+ throw new YangParseException(name, line, "Invalid parent of identityref type.");
}
}
}
- public DeviationBuilder addDeviation(final String targetPath, final List<String> parentPath, final int line) {
+ public DeviationBuilder addDeviation(final int line, final String targetPath) {
Builder parent = getActualNode();
if (parent != null) {
throw new YangParseException(name, line, "deviation can be defined only in module or submodule");
}
- final List<String> pathToDeviation = new ArrayList<String>(parentPath);
- pathToDeviation.add(targetPath);
- final DeviationBuilder builder = new DeviationBuilder(targetPath, line);
- addedDeviations.put(pathToDeviation, builder);
+ final DeviationBuilder builder = new DeviationBuilder(line, targetPath);
+ addedDeviations.add(builder);
return builder;
}
}
@Override
- public void addUnknownSchemaNode(UnknownSchemaNodeBuilder builder) {
- final List<String> unPath = new ArrayList<String>();
- for (QName name : builder.getPath().getPath()) {
- unPath.add(name.getLocalName());
- }
- if (addedUnknownNodes.containsKey(unPath)) {
- addedUnknownNodes.get(unPath).add(builder);
- } else {
- List<UnknownSchemaNodeBuilder> nodes = new ArrayList<UnknownSchemaNodeBuilder>();
- nodes.add(builder);
- addedUnknownNodes.put(unPath, nodes);
- }
+ public void addUnknownSchemaNode(final UnknownSchemaNodeBuilder builder) {
+ addedUnknownNodes.add(builder);
+ allUnknownNodes.add(builder);
}
- public UnknownSchemaNodeBuilder addUnknownSchemaNode(final QName qname, final List<String> parentPath,
- final int line) {
+ public UnknownSchemaNodeBuilder addUnknownSchemaNode(final int line, final QName qname) {
final Builder parent = getActualNode();
final UnknownSchemaNodeBuilder builder = new UnknownSchemaNodeBuilder(line, qname);
builder.setParent(parent);
+ allUnknownNodes.add(builder);
- if (parent != null) {
+ if (parent == null) {
+ addedUnknownNodes.add(builder);
+ } else {
if (parent instanceof SchemaNodeBuilder) {
((SchemaNodeBuilder) parent).addUnknownSchemaNode(builder);
+ } else if (parent instanceof DataNodeContainerBuilder) {
+ ((DataNodeContainerBuilder) parent).addUnknownSchemaNode(builder);
} else if (parent instanceof RefineHolder) {
((RefineHolder) parent).addUnknownSchemaNode(builder);
} else {
+ "'");
}
}
- final List<String> unPath = new ArrayList<String>(parentPath);
- unPath.add(qname.getLocalName());
- if (addedUnknownNodes.containsKey(unPath)) {
- addedUnknownNodes.get(unPath).add(builder);
- } else {
- List<UnknownSchemaNodeBuilder> nodes = new ArrayList<UnknownSchemaNodeBuilder>();
- nodes.add(builder);
- addedUnknownNodes.put(unPath, nodes);
- }
return builder;
}
@Override
public String toString() {
- return ModuleBuilder.class.getSimpleName() + "[" + name + "]";
+ return "module " + name;
}
private final class ModuleImpl implements Module {
// notifications, and anyxmls defined within a parent node or at the
// top level of the module or its submodules share the same
// identifier namespace.
- for (DataSchemaNodeBuilder childNode : childNodes) {
+ for (DataSchemaNodeBuilder childNode : addedChildNodes) {
if (childNode.getQName().getLocalName().equals(childLocalName)) {
throw new YangParseException(name, line, "Duplicate node found at line " + childNode.getLine());
}
throw new YangParseException(name, line, "Duplicate node found at line " + notification.getLine());
}
}
- childNodes.add(child);
+ addedChildNodes.add(child);
} else {
// no need for checking rpc and notification because they can be
// defined only under module or submodule
return moduleImport;
}
- /**
- * Traverse through given addedUnknownNodes and add only unknown nodes
- * defined under module statement.
- *
- * @param addedUnknownNodes
- * unknown node builders
- * @return list of all unknown nodes defined in module in lexicographical
- * order
- */
- private List<UnknownSchemaNode> buildModuleUnknownNodes(
- final Map<List<String>, List<UnknownSchemaNodeBuilder>> addedUnknownNodes) {
- final List<UnknownSchemaNode> result = new ArrayList<UnknownSchemaNode>();
- for (Map.Entry<List<String>, List<UnknownSchemaNodeBuilder>> entry : addedUnknownNodes.entrySet()) {
- final List<String> path = entry.getKey();
- final List<UnknownSchemaNodeBuilder> child = entry.getValue();
-
- if (path.size() == 2) {
- for (UnknownSchemaNodeBuilder node : child) {
- result.add(node.build());
- }
- }
- }
- Collections.sort(result, Comparators.SCHEMA_NODE_COMP);
- return result;
- }
-
}
AugmentationTargetBuilder {
private boolean isBuilt;
private final NotificationDefinitionImpl instance;
- private final int line;
private SchemaPath schemaPath;
private String description;
private String reference;
NotificationBuilder(final int line, final QName qname) {
super(line, qname);
- this.line = line;
instance = new NotificationDefinitionImpl(qname);
}
instance.setGroupings(groupings);
// UNKNOWN NODES
- final List<UnknownSchemaNode> unknownNodes = new ArrayList<UnknownSchemaNode>();
- for (UnknownSchemaNodeBuilder b : addedUnknownNodes) {
- unknownNodes.add(b.build());
+ if (unknownNodes == null) {
+ unknownNodes = new ArrayList<UnknownSchemaNode>();
+ for (UnknownSchemaNodeBuilder b : addedUnknownNodes) {
+ unknownNodes.add(b.build());
+ }
+ Collections.sort(unknownNodes, Comparators.SCHEMA_NODE_COMP);
}
- Collections.sort(unknownNodes, Comparators.SCHEMA_NODE_COMP);
instance.setUnknownSchemaNodes(unknownNodes);
isBuilt = true;
return true;
}
+ @Override
+ public String toString() {
+ return "rpc " + qname.getLocalName();
+ }
+
private final class RpcDefinitionImpl implements RpcDefinition {
private final QName qname;
private SchemaPath path;
private boolean isBuilt;
private final UnknownSchemaNodeImpl instance;
private boolean addedByUses;
- private List<UnknownSchemaNode> unknownNodes;
private QName nodeType;
private String nodeParameter;
this.addedByUses = addedByUses;
}
- public void setUnknownNodes(final List<UnknownSchemaNode> unknownNodes) {
- this.unknownNodes = unknownNodes;
- }
-
public QName getNodeType() {
return nodeType;
}
import org.opendaylight.controller.yang.model.api.AnyXmlSchemaNode;
import org.opendaylight.controller.yang.model.api.ChoiceNode;
import org.opendaylight.controller.yang.model.api.ContainerSchemaNode;
+import org.opendaylight.controller.yang.model.api.DataNodeContainer;
import org.opendaylight.controller.yang.model.api.DataSchemaNode;
import org.opendaylight.controller.yang.model.api.GroupingDefinition;
import org.opendaylight.controller.yang.model.api.IdentitySchemaNode;
import org.opendaylight.controller.yang.model.api.ListSchemaNode;
import org.opendaylight.controller.yang.model.api.Module;
import org.opendaylight.controller.yang.model.api.SchemaContext;
+import org.opendaylight.controller.yang.model.api.SchemaNode;
import org.opendaylight.controller.yang.model.api.SchemaPath;
import org.opendaylight.controller.yang.model.api.TypeDefinition;
import org.opendaylight.controller.yang.model.api.UnknownSchemaNode;
import org.opendaylight.controller.yang.parser.builder.impl.AnyXmlBuilder;
import org.opendaylight.controller.yang.parser.builder.impl.ChoiceBuilder;
import org.opendaylight.controller.yang.parser.builder.impl.ContainerSchemaNodeBuilder;
+import org.opendaylight.controller.yang.parser.builder.impl.DeviationBuilder;
import org.opendaylight.controller.yang.parser.builder.impl.GroupingBuilderImpl;
import org.opendaylight.controller.yang.parser.builder.impl.IdentitySchemaNodeBuilder;
import org.opendaylight.controller.yang.parser.builder.impl.IdentityrefTypeBuilder;
}
}
resolveAugments(modules);
+ resolveDeviations(modules);
// build
// LinkedHashMap MUST be used otherwise the values will not maintain
}
}
resolveAugmentsWithContext(modules, context);
+ resolveDeviationsWithContext(modules, context);
// build
// LinkedHashMap MUST be used otherwise the values will not maintain
* current module
*/
private void resolveDirtyNodes(final Map<String, TreeMap<Date, ModuleBuilder>> modules, final ModuleBuilder module) {
- final Map<List<String>, TypeAwareBuilder> dirtyNodes = module.getDirtyNodes();
+ final Set<TypeAwareBuilder> dirtyNodes = module.getDirtyNodes();
if (!dirtyNodes.isEmpty()) {
- for (Map.Entry<List<String>, TypeAwareBuilder> entry : dirtyNodes.entrySet()) {
- final TypeAwareBuilder nodeToResolve = entry.getValue();
-
+ for (TypeAwareBuilder nodeToResolve : dirtyNodes) {
if (nodeToResolve instanceof UnionTypeBuilder) {
// special handling for union types
resolveTypeUnion((UnionTypeBuilder) nodeToResolve, modules, module);
private void resolveDirtyNodesWithContext(final Map<String, TreeMap<Date, ModuleBuilder>> modules,
final ModuleBuilder module, SchemaContext context) {
- final Map<List<String>, TypeAwareBuilder> dirtyNodes = module.getDirtyNodes();
+ final Set<TypeAwareBuilder> dirtyNodes = module.getDirtyNodes();
if (!dirtyNodes.isEmpty()) {
- for (Map.Entry<List<String>, TypeAwareBuilder> entry : dirtyNodes.entrySet()) {
- final TypeAwareBuilder nodeToResolve = entry.getValue();
-
+ for (TypeAwareBuilder nodeToResolve : dirtyNodes) {
if (nodeToResolve instanceof UnionTypeBuilder) {
// special handling for union types
resolveTypeUnionWithContext((UnionTypeBuilder) nodeToResolve, modules, module, context);
DataNodeContainerBuilder parent = usesNode.getParent();
SchemaPath parentPath = parent.getPath();
for (DataSchemaNodeBuilder child : targetGrouping.getChildNodeBuilders()) {
- // if node is refined, take it from refined nodes and continue
- SchemaNodeBuilder refined = getRefined(child.getQName(), refineNodes);
- if (refined != null) {
- refined.setPath(createSchemaPath(parentPath, refined.getQName().getLocalName()));
- parent.addChildNode((DataSchemaNodeBuilder) refined);
- continue;
- }
+ if (child != null) {
+ // if node is refined, take it from refined nodes and continue
+ SchemaNodeBuilder refined = getRefined(child.getQName(), refineNodes);
+ if (refined != null) {
+ refined.setPath(createSchemaPath(parentPath, refined.getQName().getLocalName()));
+ parent.addChildNode((DataSchemaNodeBuilder) refined);
+ continue;
+ }
- DataSchemaNodeBuilder newChild = null;
- if (child instanceof AnyXmlBuilder) {
- newChild = new AnyXmlBuilder((AnyXmlBuilder) child);
- } else if (child instanceof ChoiceBuilder) {
- newChild = new ChoiceBuilder((ChoiceBuilder) child);
- } else if (child instanceof ContainerSchemaNodeBuilder) {
- newChild = new ContainerSchemaNodeBuilder((ContainerSchemaNodeBuilder) child);
- } else if (child instanceof LeafListSchemaNodeBuilder) {
- newChild = new LeafListSchemaNodeBuilder((LeafListSchemaNodeBuilder) child);
- } else if (child instanceof LeafSchemaNodeBuilder) {
- newChild = new LeafSchemaNodeBuilder((LeafSchemaNodeBuilder) child);
- } else if (child instanceof ListSchemaNodeBuilder) {
- newChild = new ListSchemaNodeBuilder((ListSchemaNodeBuilder) child);
- }
+ DataSchemaNodeBuilder newChild = null;
+ if (child instanceof AnyXmlBuilder) {
+ newChild = new AnyXmlBuilder((AnyXmlBuilder) child);
+ } else if (child instanceof ChoiceBuilder) {
+ newChild = new ChoiceBuilder((ChoiceBuilder) child);
+ } else if (child instanceof ContainerSchemaNodeBuilder) {
+ newChild = new ContainerSchemaNodeBuilder((ContainerSchemaNodeBuilder) child);
+ } else if (child instanceof LeafListSchemaNodeBuilder) {
+ newChild = new LeafListSchemaNodeBuilder((LeafListSchemaNodeBuilder) child);
+ } else if (child instanceof LeafSchemaNodeBuilder) {
+ newChild = new LeafSchemaNodeBuilder((LeafSchemaNodeBuilder) child);
+ } else if (child instanceof ListSchemaNodeBuilder) {
+ newChild = new ListSchemaNodeBuilder((ListSchemaNodeBuilder) child);
+ }
+
+ if (newChild == null) {
+ throw new YangParseException(usesNode.getLine(),
+ "Unknown member of target grouping while resolving uses node.");
+ }
- if (newChild instanceof GroupingMember) {
- ((GroupingMember) newChild).setAddedByUses(true);
+ if (newChild instanceof GroupingMember) {
+ ((GroupingMember) newChild).setAddedByUses(true);
+ }
+
+ newChild.setPath(createSchemaPath(parentPath, newChild.getQName().getLocalName()));
+ parent.addChildNode(newChild);
}
- newChild.setPath(createSchemaPath(parentPath, newChild.getQName().getLocalName()));
- parent.addChildNode(newChild);
}
for (GroupingBuilder g : targetGrouping.getGroupingBuilders()) {
GroupingBuilder newGrouping = new GroupingBuilderImpl(g);
DataNodeContainerBuilder parent = usesNode.getParent();
SchemaPath parentPath = parent.getPath();
for (DataSchemaNode child : targetGrouping.getChildNodes()) {
- // if node is refined, take it from refined nodes and continue
- SchemaNodeBuilder refined = getRefined(child.getQName(), refineNodes);
- if (refined != null) {
- refined.setPath(createSchemaPath(parentPath, refined.getQName().getLocalName()));
- parent.addChildNode((DataSchemaNodeBuilder) refined);
- continue;
- }
+ if (child != null) {
+ // if node is refined, take it from refined nodes and continue
+ SchemaNodeBuilder refined = getRefined(child.getQName(), refineNodes);
+ if (refined != null) {
+ refined.setPath(createSchemaPath(parentPath, refined.getQName().getLocalName()));
+ parent.addChildNode((DataSchemaNodeBuilder) refined);
+ continue;
+ }
- DataSchemaNodeBuilder newChild = null;
- if (child instanceof AnyXmlSchemaNode) {
- newChild = createAnyXml((AnyXmlSchemaNode) child, line);
- } else if (child instanceof ChoiceNode) {
- newChild = createChoice((ChoiceNode) child, line);
- } else if (child instanceof ContainerSchemaNode) {
- newChild = createContainer((ContainerSchemaNode) child, line);
- } else if (child instanceof LeafListSchemaNode) {
- newChild = createLeafList((LeafListSchemaNode) child, line);
- } else if (child instanceof LeafSchemaNode) {
- newChild = createLeafBuilder((LeafSchemaNode) child, line);
- } else if (child instanceof ListSchemaNode) {
- newChild = createList((ListSchemaNode) child, line);
- }
+ DataSchemaNodeBuilder newChild = null;
+ if (child instanceof AnyXmlSchemaNode) {
+ newChild = createAnyXml((AnyXmlSchemaNode) child, line);
+ } else if (child instanceof ChoiceNode) {
+ newChild = createChoice((ChoiceNode) child, line);
+ } else if (child instanceof ContainerSchemaNode) {
+ newChild = createContainer((ContainerSchemaNode) child, line);
+ } else if (child instanceof LeafListSchemaNode) {
+ newChild = createLeafList((LeafListSchemaNode) child, line);
+ } else if (child instanceof LeafSchemaNode) {
+ newChild = createLeafBuilder((LeafSchemaNode) child, line);
+ } else if (child instanceof ListSchemaNode) {
+ newChild = createList((ListSchemaNode) child, line);
+ }
+
+ if (newChild == null) {
+ throw new YangParseException(usesNode.getLine(),
+ "Unknown member of target grouping while resolving uses node.");
+ }
- if (newChild instanceof GroupingMember) {
- ((GroupingMember) newChild).setAddedByUses(true);
+ if (newChild instanceof GroupingMember) {
+ ((GroupingMember) newChild).setAddedByUses(true);
+ }
+ newChild.setPath(createSchemaPath(parentPath, newChild.getQName().getLocalName()));
+ parent.addChildNode(newChild);
}
- newChild.setPath(createSchemaPath(parentPath, newChild.getQName().getLocalName()));
- parent.addChildNode(newChild);
}
for (GroupingDefinition g : targetGrouping.getGroupings()) {
GroupingBuilder newGrouping = createGrouping(g, line);
}
private void resolveUnknownNodes(final Map<String, TreeMap<Date, ModuleBuilder>> modules, final ModuleBuilder module) {
- for (UnknownSchemaNodeBuilder usnb : module.getUnknownNodes()) {
+ for (UnknownSchemaNodeBuilder usnb : module.getAllUnknownNodes()) {
QName nodeType = usnb.getNodeType();
if (nodeType.getNamespace() == null || nodeType.getRevision() == null) {
try {
}
private void resolveUnknownNodesWithContext(final Map<String, TreeMap<Date, ModuleBuilder>> modules,
- final ModuleBuilder module, SchemaContext context) {
- for (UnknownSchemaNodeBuilder unknownNodeBuilder : module.getUnknownNodes()) {
+ final ModuleBuilder module, final SchemaContext context) {
+ for (UnknownSchemaNodeBuilder unknownNodeBuilder : module.getAllUnknownNodes()) {
QName nodeType = unknownNodeBuilder.getNodeType();
if (nodeType.getNamespace() == null || nodeType.getRevision() == null) {
try {
}
}
+ private void resolveDeviations(final Map<String, TreeMap<Date, ModuleBuilder>> modules) {
+ for (Map.Entry<String, TreeMap<Date, ModuleBuilder>> entry : modules.entrySet()) {
+ for (Map.Entry<Date, ModuleBuilder> inner : entry.getValue().entrySet()) {
+ ModuleBuilder b = inner.getValue();
+ resolveDeviation(modules, b);
+ }
+ }
+ }
+
+ private void resolveDeviation(final Map<String, TreeMap<Date, ModuleBuilder>> modules, final ModuleBuilder module) {
+ for (DeviationBuilder dev : module.getDeviations()) {
+ int line = dev.getLine();
+ SchemaPath targetPath = dev.getTargetPath();
+ List<QName> path = targetPath.getPath();
+ QName q0 = path.get(0);
+ String prefix = q0.getPrefix();
+ if (prefix == null) {
+ prefix = module.getPrefix();
+ }
+
+ ModuleBuilder dependentModuleBuilder = findDependentModuleBuilder(modules, module, prefix, line);
+ processDeviation(dev, dependentModuleBuilder, path, module);
+ }
+ }
+
+ private void resolveDeviationsWithContext(final Map<String, TreeMap<Date, ModuleBuilder>> modules,
+ final SchemaContext context) {
+ for (Map.Entry<String, TreeMap<Date, ModuleBuilder>> entry : modules.entrySet()) {
+ for (Map.Entry<Date, ModuleBuilder> inner : entry.getValue().entrySet()) {
+ ModuleBuilder b = inner.getValue();
+ resolveDeviationWithContext(modules, b, context);
+ }
+ }
+ }
+
+ private void resolveDeviationWithContext(final Map<String, TreeMap<Date, ModuleBuilder>> modules,
+ final ModuleBuilder module, final SchemaContext context) {
+ for (DeviationBuilder dev : module.getDeviations()) {
+ int line = dev.getLine();
+ SchemaPath targetPath = dev.getTargetPath();
+ List<QName> path = targetPath.getPath();
+ QName q0 = path.get(0);
+ String prefix = q0.getPrefix();
+ if (prefix == null) {
+ prefix = module.getPrefix();
+ }
+ String name = null;
+
+ ModuleBuilder dependentModuleBuilder = findDependentModuleBuilder(modules, module, prefix, line);
+ if (dependentModuleBuilder == null) {
+ Module dependentModule = findModuleFromContext(context, module, prefix, line);
+ Object currentParent = dependentModule;
+
+ for (int i = 0; i < path.size(); i++) {
+ if (currentParent == null) {
+ throw new YangParseException(module.getName(), line, "Failed to find deviation target.");
+ }
+ QName q = path.get(i);
+ name = q.getLocalName();
+ if (currentParent instanceof DataNodeContainer) {
+ currentParent = ((DataNodeContainer) currentParent).getDataChildByName(name);
+ }
+ }
+
+ if (currentParent == null) {
+ throw new YangParseException(module.getName(), line, "Failed to find deviation target.");
+ }
+ if (currentParent instanceof SchemaNode) {
+ dev.setTargetPath(((SchemaNode) currentParent).getPath());
+ }
+
+ } else {
+ processDeviation(dev, dependentModuleBuilder, path, module);
+ }
+ }
+ }
+
+ /**
+ * Correct deviation target path in deviation builder.
+ *
+ * @param dev
+ * deviation
+ * @param dependentModuleBuilder
+ * module containing deviation target
+ * @param path
+ * current deviation target path
+ * @param module
+ * current module
+ */
+ private void processDeviation(final DeviationBuilder dev, final ModuleBuilder dependentModuleBuilder,
+ final List<QName> path, final ModuleBuilder module) {
+ final int line = dev.getLine();
+ Builder currentParent = dependentModuleBuilder;
+
+ for (int i = 0; i < path.size(); i++) {
+ if (currentParent == null) {
+ throw new YangParseException(module.getName(), line, "Failed to find deviation target.");
+ }
+ QName q = path.get(i);
+ String name = q.getLocalName();
+ if (currentParent instanceof DataNodeContainerBuilder) {
+ currentParent = ((DataNodeContainerBuilder) currentParent).getDataChildByName(name);
+ }
+ }
+
+ if (currentParent == null || !(currentParent instanceof SchemaNodeBuilder)) {
+ throw new YangParseException(module.getName(), line, "Failed to find deviation target.");
+ }
+ dev.setTargetPath(((SchemaNodeBuilder) currentParent).getPath());
+ }
+
}
*/
package org.opendaylight.controller.yang.parser.impl;
-import static org.opendaylight.controller.yang.parser.util.YangModelBuilderUtil.*;
+import static org.opendaylight.controller.yang.parser.util.ParserListenerUtils.*;
import java.net.URI;
import java.text.DateFormat;
@Override
public void enterRevision_stmts(Revision_stmtsContext ctx) {
enterLog("revisions", "", ctx.getStart().getLine());
- if (ctx != null) {
- for (int i = 0; i < ctx.getChildCount(); ++i) {
- final ParseTree treeNode = ctx.getChild(i);
- if (treeNode instanceof Revision_stmtContext) {
- updateRevisionForRevisionStatement(treeNode);
- }
+ for (int i = 0; i < ctx.getChildCount(); ++i) {
+ final ParseTree treeNode = ctx.getChild(i);
+ if (treeNode instanceof Revision_stmtContext) {
+ updateRevisionForRevisionStatement(treeNode);
}
}
}
builder.setPath(createActualSchemaPath(actualPath, namespace, revision, yangModelPrefix));
parseSchemaNodeArgs(ctx, builder);
builder.setUnits(parseUnits(ctx));
+ builder.setDefaultValue(parseDefault(ctx));
}
@Override
} else {
if ("union".equals(typeName)) {
SchemaPath p = createActualSchemaPath(actualPath, namespace, revision, yangModelPrefix, typeName);
- UnionTypeBuilder unionBuilder = moduleBuilder.addUnionType(actualPath, namespace, revision, line);
+ UnionTypeBuilder unionBuilder = moduleBuilder.addUnionType(line, namespace, revision);
moduleBuilder.enterNode(unionBuilder);
unionBuilder.setPath(p);
} else if ("identityref".equals(typeName)) {
SchemaPath path = createActualSchemaPath(actualPath, namespace, revision, yangModelPrefix, typeName);
- moduleBuilder.addIdentityrefType(getIdentityrefBase(typeBody), actualPath, path, line);
+ moduleBuilder.addIdentityrefType(line, path, getIdentityrefBase(typeBody));
} else {
type = parseTypeWithBody(moduleName, typeName, typeBody, actualPath, namespace, revision,
yangModelPrefix, moduleBuilder.getActualNode());
type = parseUnknownTypeWithBody(typeQName, typeBody, actualPath, namespace, revision, yangModelPrefix,
moduleBuilder.getActualNode());
// add parent node of this type statement to dirty nodes
- moduleBuilder.addDirtyNode(actualPath);
+ moduleBuilder.markActualNodeDirty();
moduleBuilder.setType(type);
}
qname = new QName(namespace, revision, yangModelPrefix, nodeParameter);
}
- UnknownSchemaNodeBuilder builder = moduleBuilder.addUnknownSchemaNode(qname, actualPath, line);
+ UnknownSchemaNodeBuilder builder = moduleBuilder.addUnknownSchemaNode(line, qname);
builder.setNodeType(nodeType);
builder.setNodeParameter(nodeParameter);
actualPath.push(nodeParameter);
String reference = null;
String deviate = null;
- DeviationBuilder builder = moduleBuilder.addDeviation(targetPath, actualPath, line);
+ DeviationBuilder builder = moduleBuilder.addDeviation(line, targetPath);
moduleBuilder.enterNode(builder);
actualPath.push(targetPath);
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-public final class YangModelBuilderUtil {
- private static final Logger logger = LoggerFactory.getLogger(YangModelBuilderUtil.class);
+public final class ParserListenerUtils {
+ private static final Logger logger = LoggerFactory.getLogger(ParserListenerUtils.class);
- private YangModelBuilderUtil() {
+ private ParserListenerUtils() {
}
/**
return units;
}
+ /**
+ * Parse given tree and returns default statement as string.
+ *
+ * @param ctx
+ * context to parse
+ * @return value of default statement as string or null if there is no
+ * default statement
+ */
+ public static String parseDefault(final ParseTree ctx) {
+ String defaultValue = null;
+ for (int i = 0; i < ctx.getChildCount(); i++) {
+ ParseTree child = ctx.getChild(i);
+ if (child instanceof Default_stmtContext) {
+ defaultValue = stringFromNode(child);
+ break;
+ }
+ }
+ return defaultValue;
+ }
+
/**
* Create SchemaPath from actualPath and names.
*
ChoiceCaseBuilder choiceCase = (ChoiceCaseBuilder) parent;
Builder choice = choiceCase.getParent();
Boolean parentConfig = null;
- if(choice instanceof ChoiceBuilder) {
- parentConfig = ((ChoiceBuilder)choice).isConfiguration();
+ if (choice instanceof ChoiceBuilder) {
+ parentConfig = ((ChoiceBuilder) choice).isConfiguration();
} else {
parentConfig = true;
}
TypeDefinition<?> baseType = unknownType.build();
TypeDefinition<?> result = null;
QName qname = new QName(namespace, revision, prefix, typeName);
- ExtendedType.Builder typeBuilder = null;
-
SchemaPath schemaPath = createTypeSchemaPath(actualPath, namespace, revision, prefix, typeName, false,
false);
- typeBuilder = new ExtendedType.Builder(qname, baseType, "", "", schemaPath);
+ ExtendedType.Builder typeBuilder = new ExtendedType.Builder(qname, baseType, null, null, schemaPath);
typeBuilder.ranges(rangeStatements);
typeBuilder.lengths(lengthStatements);
typeBuilder.patterns(patternStatements);
typeBuilder.fractionDigits(fractionDigits);
-
result = typeBuilder.build();
return result;
public static TypeDefinition<?> parseTypeWithBody(final String moduleName, final String typeName,
final Type_body_stmtsContext typeBody, final List<String> actualPath, final URI namespace,
final Date revision, final String prefix, final Builder parent) {
+ final int line = typeBody.getStart().getLine();
TypeDefinition<?> baseType = null;
Integer fractionDigits = getFractionDigits(typeBody);
List<PatternConstraint> patternStatements = getPatternConstraint(typeBody);
List<RangeConstraint> rangeStatements = getRangeConstraints(typeBody);
- TypeConstraints constraints = new TypeConstraints(moduleName, typeBody.getStart().getLine());
+ TypeConstraints constraints = new TypeConstraints(moduleName, line);
constraints.addFractionDigits(fractionDigits);
constraints.addLengths(lengthStatements);
constraints.addPatterns(patternStatements);
} else if ("int64".equals(typeName)) {
intType = new Int64(baseTypePath);
}
+ if(intType == null) {
+ throw new YangParseException(moduleName, line, "Unknown yang type "+ typeName);
+ }
constraints.addRanges(intType.getRangeStatements());
baseType = intType;
} else if (typeName.startsWith("uint")) {
} else if ("uint64".equals(typeName)) {
uintType = new Uint64(baseTypePath);
}
+ if(uintType == null) {
+ throw new YangParseException(moduleName, line, "Unknown yang type "+ typeName);
+ }
constraints.addRanges(uintType.getRangeStatements());
baseType = uintType;
} else if ("enumeration".equals(typeName)) {
}
// set correct path for all cases
- if(childNode instanceof ChoiceBuilder) {
+ if (childNode instanceof ChoiceBuilder) {
ChoiceBuilder choiceBuilder = (ChoiceBuilder) childNode;
for (ChoiceCaseBuilder choiceCaseBuilder : choiceBuilder.getCases()) {
correctAugmentChildPath(choiceCaseBuilder, childNode.getPath());
private static TypeDefinition<?> createCorrectTypeDefinition(SchemaPath parentSchemaPath, QName nodeQName,
TypeDefinition<?> nodeType) {
- QName nodeTypeQName = nodeType.getQName();
- SchemaPath newSchemaPath = createNewSchemaPath(parentSchemaPath, nodeQName, nodeTypeQName);
TypeDefinition<?> result = null;
if (nodeType != null) {
+ QName nodeTypeQName = nodeType.getQName();
+ SchemaPath newSchemaPath = createNewSchemaPath(parentSchemaPath, nodeQName, nodeTypeQName);
+
if (nodeType instanceof BinaryTypeDefinition) {
BinaryTypeDefinition binType = (BinaryTypeDefinition) nodeType;
private final int line;
private final List<List<RangeConstraint>> ranges = new ArrayList<List<RangeConstraint>>();
private final List<List<LengthConstraint>> lengths = new ArrayList<List<LengthConstraint>>();
- private final List<PatternConstraint> patterns = new ArrayList<PatternConstraint>();
+ private final List<List<PatternConstraint>> patterns = new ArrayList<List<PatternConstraint>>();
private final List<Integer> fractionDigits = new ArrayList<Integer>();
public TypeConstraints(final String moduleName, final int line) {
}
public List<PatternConstraint> getPatterns() {
- return patterns;
+ if(patterns.isEmpty()) {
+ return Collections.emptyList();
+ }
+ return patterns.get(0);
}
public void addPatterns(final List<PatternConstraint> patterns) {
- this.patterns.addAll(patterns);
+ this.patterns.add(patterns);
}
public Integer getFractionDigits() {
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.parser.util.YangModelBuilderUtil;
+import org.opendaylight.controller.yang.parser.util.ParserListenerUtils;
import org.opendaylight.controller.yang.parser.util.YangValidationException;
/**
}
static String getName(ParseTree child) {
- return YangModelBuilderUtil.stringFromNode(child);
+ return ParserListenerUtils.stringFromNode(child);
}
static String f(String base, Object... args) {
--- /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.parser.impl;
+
+import static org.junit.Assert.*;
+
+import java.io.FileNotFoundException;
+import java.net.URI;
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.List;
+import java.util.Set;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.controller.yang.common.QName;
+import org.opendaylight.controller.yang.model.api.AugmentationSchema;
+import org.opendaylight.controller.yang.model.api.ChoiceCaseNode;
+import org.opendaylight.controller.yang.model.api.ChoiceNode;
+import org.opendaylight.controller.yang.model.api.ContainerSchemaNode;
+import org.opendaylight.controller.yang.model.api.DataSchemaNode;
+import org.opendaylight.controller.yang.model.api.LeafSchemaNode;
+import org.opendaylight.controller.yang.model.api.ListSchemaNode;
+import org.opendaylight.controller.yang.model.api.Module;
+import org.opendaylight.controller.yang.model.api.SchemaPath;
+import org.opendaylight.controller.yang.model.api.TypeDefinition;
+import org.opendaylight.controller.yang.model.util.ExtendedType;
+import org.opendaylight.controller.yang.model.util.Leafref;
+
+import com.google.common.collect.Lists;
+
+public class AugmentTest {
+
+ private final URI types1NS = URI.create("urn:simple.nodes.test");
+ private final URI types2NS = URI.create("urn:simple.types.test");
+ private final URI types3NS = URI.create("urn:custom.nodes.test");
+ private Date types1Rev;
+ private Date types2Rev;
+ private Date types3Rev;
+ private final String t1 = "n";
+ private final String t2 = "t";
+ private final String t3 = "c";
+ private QName q0;
+ private QName q1;
+ private QName q2;
+
+ private final DateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
+ private Set<Module> modules;
+
+ @Before
+ public void init() throws FileNotFoundException, ParseException {
+ types1Rev = simpleDateFormat.parse("2013-02-27");
+ types2Rev = simpleDateFormat.parse("2013-07-03");
+ types3Rev = simpleDateFormat.parse("2013-02-27");
+
+ q0 = new QName(types2NS, types2Rev, t2, "interfaces");
+ q1 = new QName(types2NS, types2Rev, t2, "ifEntry");
+ q2 = new QName(types3NS, types3Rev, t3, "augment-holder");
+
+ modules = TestUtils.loadModules(getClass().getResource("/model").getPath());
+ assertEquals(3, modules.size());
+ }
+
+ @Test
+ public void testAugmentParsing() {
+ SchemaPath expectedPath = null;
+ QName[] qnames = null;
+
+ // testfile1
+ Module module1 = TestUtils.findModule(modules, "nodes");
+ Set<AugmentationSchema> augmentations = module1.getAugmentations();
+ assertEquals(1, augmentations.size());
+ AugmentationSchema augment = augmentations.iterator().next();
+
+ Set<DataSchemaNode> augmentChildren = augment.getChildNodes();
+ assertEquals(5, augmentChildren.size());
+ for(DataSchemaNode dsn : augmentChildren) {
+ assertTrue(dsn.isAugmenting());
+ }
+
+ LeafSchemaNode ds0ChannelNumber = (LeafSchemaNode) augment.getDataChildByName("ds0ChannelNumber");
+ LeafSchemaNode interfaceId = (LeafSchemaNode) augment.getDataChildByName("interface-id");
+ LeafSchemaNode myType = (LeafSchemaNode) augment.getDataChildByName("my-type");
+ ContainerSchemaNode schemas = (ContainerSchemaNode) augment.getDataChildByName("schemas");
+ ChoiceNode odl = (ChoiceNode)augment.getDataChildByName("odl");
+
+ assertNotNull(ds0ChannelNumber);
+ assertNotNull(interfaceId);
+ assertNotNull(myType);
+ assertNotNull(schemas);
+ assertNotNull(odl);
+
+ qnames = new QName[4];
+ qnames[0] = q0;
+ qnames[1] = q1;
+ qnames[2] = q2;
+
+ // leaf ds0ChannelNumber
+ qnames[3] = new QName(types1NS, types1Rev, t1, "ds0ChannelNumber");
+ expectedPath = new SchemaPath(Lists.newArrayList(qnames), true);
+ assertEquals(expectedPath, ds0ChannelNumber.getPath());
+
+ // leaf interface-id
+ qnames[3] = new QName(types1NS, types1Rev, t1, "interface-id");
+ expectedPath = new SchemaPath(Lists.newArrayList(qnames), true);
+ assertEquals(expectedPath, interfaceId.getPath());
+
+ // leaf my-type
+ qnames[3] = new QName(types1NS, types1Rev, t1, "my-type");
+ expectedPath = new SchemaPath(Lists.newArrayList(qnames), true);
+ assertEquals(expectedPath, myType.getPath());
+
+ // container schemas
+ qnames[3] = new QName(types1NS, types1Rev, t1, "schemas");
+ expectedPath = new SchemaPath(Lists.newArrayList(qnames), true);
+ assertEquals(expectedPath, schemas.getPath());
+
+ // choice odl
+ qnames[3] = new QName(types1NS, types1Rev, t1, "odl");
+ expectedPath = new SchemaPath(Lists.newArrayList(qnames), true);
+ assertEquals(expectedPath, odl.getPath());
+
+
+ // testfile3
+ Module module3 = TestUtils.findModule(modules, "custom");
+ augmentations = module3.getAugmentations();
+ assertEquals(3, augmentations.size());
+ AugmentationSchema augment1 = null;
+ AugmentationSchema augment2 = null;
+ AugmentationSchema augment3 = null;
+ for (AugmentationSchema as : augmentations) {
+ if("if:ifType='ds0'".equals(as.getWhenCondition().toString())) {
+ augment1 = as;
+ } else if("if:ifType='ds2'".equals(as.getWhenCondition().toString())) {
+ augment2 = as;
+ } else if ("if:leafType='ds1'".equals(as.getWhenCondition().toString())) {
+ augment3 = as;
+ }
+ }
+ assertNotNull(augment1);
+ assertNotNull(augment2);
+ assertNotNull(augment3);
+
+ assertEquals(1, augment1.getChildNodes().size());
+ ContainerSchemaNode augmentHolder = (ContainerSchemaNode) augment1.getDataChildByName("augment-holder");
+ assertTrue(augmentHolder.isAugmenting());
+
+ assertEquals(1, augment2.getChildNodes().size());
+ ContainerSchemaNode augmentHolder2 = (ContainerSchemaNode) augment2.getDataChildByName("augment-holder2");
+ assertTrue(augmentHolder2.isAugmenting());
+
+ assertEquals(1, augment3.getChildNodes().size());
+ LeafSchemaNode linkleaf = (LeafSchemaNode) augment3.getDataChildByName("linkleaf");
+ assertTrue(linkleaf.isAugmenting());
+ }
+
+ @Test
+ public void testAugmentResolving() throws ParseException {
+ SchemaPath expectedPath = null;
+ QName[] qnames = null;
+
+ Module module2 = TestUtils.findModule(modules, "types");
+ ContainerSchemaNode interfaces = (ContainerSchemaNode) module2.getDataChildByName("interfaces");
+ ListSchemaNode ifEntry = (ListSchemaNode) interfaces.getDataChildByName("ifEntry");
+ ContainerSchemaNode augmentedContainer = (ContainerSchemaNode) ifEntry.getDataChildByName("augment-holder");
+
+ // testfile1.yang
+ // augment "/data:interfaces/data:ifEntry/t3:augment-holder"
+ LeafSchemaNode ds0ChannelNumber = (LeafSchemaNode) augmentedContainer.getDataChildByName("ds0ChannelNumber");
+ LeafSchemaNode interfaceId = (LeafSchemaNode) augmentedContainer.getDataChildByName("interface-id");
+ LeafSchemaNode myType = (LeafSchemaNode) augmentedContainer.getDataChildByName("my-type");
+ ContainerSchemaNode schemas = (ContainerSchemaNode) augmentedContainer.getDataChildByName("schemas");
+ ChoiceNode odl = (ChoiceNode)augmentedContainer.getDataChildByName("odl");
+
+ assertNotNull(ds0ChannelNumber);
+ assertNotNull(interfaceId);
+ assertNotNull(myType);
+ assertNotNull(schemas);
+ assertNotNull(odl);
+
+ qnames = new QName[4];
+ qnames[0] = q0;
+ qnames[1] = q1;
+ qnames[2] = q2;
+
+ // leaf ds0ChannelNumber
+ qnames[3] = new QName(types1NS, types1Rev, t1, "ds0ChannelNumber");
+ expectedPath = new SchemaPath(Lists.newArrayList(qnames), true);
+ assertEquals(expectedPath, ds0ChannelNumber.getPath());
+
+ // leaf interface-id
+ qnames[3] = new QName(types1NS, types1Rev, t1, "interface-id");
+ expectedPath = new SchemaPath(Lists.newArrayList(qnames), true);
+ assertEquals(expectedPath, interfaceId.getPath());
+
+ // leaf my-type
+ qnames[3] = new QName(types1NS, types1Rev, t1, "my-type");
+ expectedPath = new SchemaPath(Lists.newArrayList(qnames), true);
+ assertEquals(expectedPath, myType.getPath());
+
+ // container schemas
+ qnames[3] = new QName(types1NS, types1Rev, t1, "schemas");
+ expectedPath = new SchemaPath(Lists.newArrayList(qnames), true);
+ assertEquals(expectedPath, schemas.getPath());
+
+ // choice odl
+ qnames[3] = new QName(types1NS, types1Rev, t1, "odl");
+ expectedPath = new SchemaPath(Lists.newArrayList(qnames), true);
+ assertEquals(expectedPath, odl.getPath());
+
+ // testfile3.yang
+ // augment "/data:interfaces/data:ifEntry/t3:augment-holder/t1:schemas"
+ LeafSchemaNode linkleaf = (LeafSchemaNode) schemas.getDataChildByName("linkleaf");
+ assertNotNull(linkleaf);
+
+ qnames = new QName[5];
+ qnames[0] = q0;
+ qnames[1] = q1;
+ qnames[2] = q2;
+ qnames[3] = new QName(types1NS, types1Rev, t1, "schemas");
+ qnames[4] = new QName(types3NS, types3Rev, t3, "linkleaf");
+ expectedPath = new SchemaPath(Arrays.asList(qnames), true);
+ assertEquals(expectedPath, linkleaf.getPath());
+ }
+
+ @Test
+ public void testAugmentChoice() throws ParseException {
+ SchemaPath expectedPath = null;
+ QName[] qnames = null;
+
+ Module module2 = TestUtils.findModule(modules, "types");
+ ContainerSchemaNode interfaces = (ContainerSchemaNode) module2.getDataChildByName("interfaces");
+ ListSchemaNode ifEntry = (ListSchemaNode) interfaces.getDataChildByName("ifEntry");
+ ContainerSchemaNode augmentedContainer = (ContainerSchemaNode) ifEntry.getDataChildByName("augment-holder");
+
+ // testfile1.yang
+ // augment "/data:interfaces/data:ifEntry/t3:augment-holder"
+ ChoiceNode odl = (ChoiceNode)augmentedContainer.getDataChildByName("odl");
+ assertNotNull(odl);
+ Set<ChoiceCaseNode> cases = odl.getCases();
+ assertEquals(4, cases.size());
+
+ ChoiceCaseNode id = null;
+ ChoiceCaseNode node1 = null;
+ ChoiceCaseNode node2 = null;
+ ChoiceCaseNode node3 = null;
+
+ for(ChoiceCaseNode ccn : cases) {
+ if("id".equals(ccn.getQName().getLocalName())) {
+ id = ccn;
+ } else if("node1".equals(ccn.getQName().getLocalName())) {
+ node1 = ccn;
+ } else if("node2".equals(ccn.getQName().getLocalName())) {
+ node2 = ccn;
+ } else if("node3".equals(ccn.getQName().getLocalName())) {
+ node3 = ccn;
+ }
+ }
+
+ assertNotNull(id);
+ assertNotNull(node1);
+ assertNotNull(node2);
+ assertNotNull(node3);
+
+ qnames = new QName[5];
+ qnames[0] = q0;
+ qnames[1] = q1;
+ qnames[2] = q2;
+ qnames[3] = new QName(types1NS, types1Rev, t1, "odl");
+
+ // case id
+ qnames[4] = new QName(types1NS, types1Rev, t1, "id");
+ expectedPath = new SchemaPath(Lists.newArrayList(qnames), true);
+ assertEquals(expectedPath, id.getPath());
+ Set<DataSchemaNode> idChildren = id.getChildNodes();
+ assertEquals(1, idChildren.size());
+
+ // case node1
+ qnames[4] = new QName(types1NS, types1Rev, t1, "node1");
+ expectedPath = new SchemaPath(Lists.newArrayList(qnames), true);
+ assertEquals(expectedPath, node1.getPath());
+ Set<DataSchemaNode> node1Children = node1.getChildNodes();
+ assertTrue(node1Children.isEmpty());
+
+ // case node2
+ qnames[4] = new QName(types1NS, types1Rev, t1, "node2");
+ expectedPath = new SchemaPath(Lists.newArrayList(qnames), true);
+ assertEquals(expectedPath, node2.getPath());
+ Set<DataSchemaNode> node2Children = node2.getChildNodes();
+ assertTrue(node2Children.isEmpty());
+
+ // case node3
+ qnames[4] = new QName(types1NS, types1Rev, t1, "node3");
+ expectedPath = new SchemaPath(Lists.newArrayList(qnames), true);
+ assertEquals(expectedPath, node3.getPath());
+ Set<DataSchemaNode> node3Children = node3.getChildNodes();
+ assertEquals(1, node3Children.size());
+
+ // test cases
+ qnames = new QName[6];
+ qnames[0] = q0;
+ qnames[1] = q1;
+ qnames[2] = q2;
+ qnames[3] = new QName(types1NS, types1Rev, t1, "odl");
+
+ // case id child
+ qnames[4] = new QName(types1NS, types1Rev, t1, "id");
+ qnames[5] = new QName(types1NS, types1Rev, t1, "id");
+ LeafSchemaNode caseIdChild = (LeafSchemaNode)idChildren.iterator().next();
+ assertNotNull(caseIdChild);
+ expectedPath = new SchemaPath(Lists.newArrayList(qnames), true);
+ assertEquals(expectedPath, caseIdChild.getPath());
+
+ // case node3 child
+ qnames[4] = new QName(types1NS, types1Rev, t1, "node3");
+ qnames[5] = new QName(types1NS, types1Rev, t1, "node3");
+ ContainerSchemaNode caseNode3Child = (ContainerSchemaNode)node3Children.iterator().next();
+ assertNotNull(caseNode3Child);
+ expectedPath = new SchemaPath(Lists.newArrayList(qnames), true);
+ assertEquals(expectedPath, caseNode3Child.getPath());
+ }
+
+ @Test
+ public void testAugmentNodesTypeSchemaPath() throws Exception {
+ Module testModule = TestUtils.findModule(modules, "nodes");
+ Set<AugmentationSchema> augments = testModule.getAugmentations();
+ assertEquals(1, augments.size());
+ AugmentationSchema augment = augments.iterator().next();
+
+ LeafSchemaNode ifcId = (LeafSchemaNode) augment.getDataChildByName("interface-id");
+ Leafref ifcIdType = (Leafref) ifcId.getType();
+ SchemaPath ifcIdTypeSchemaPath = ifcIdType.getPath();
+ List<QName> ifcIdTypePath = ifcIdTypeSchemaPath.getPath();
+
+ Date expectedDate = simpleDateFormat.parse("2013-02-27");
+
+ QName q3 = new QName(types1NS, expectedDate, "data", "interface-id");
+ assertEquals(q0, ifcIdTypePath.get(0));
+ assertEquals(q1, ifcIdTypePath.get(1));
+ assertEquals(q2, ifcIdTypePath.get(2));
+ assertEquals(q3, ifcIdTypePath.get(3));
+
+ LeafSchemaNode myType = (LeafSchemaNode) augment.getDataChildByName("my-type");
+ ExtendedType leafType = (ExtendedType) myType.getType();
+
+ testModule = TestUtils.findModule(modules, "types");
+ TypeDefinition<?> typedef = TestUtils.findTypedef(testModule.getTypeDefinitions(), "int32-ext2");
+
+ assertEquals(typedef, leafType);
+ }
+
+}
@Test
public void testRefine() {
- Module testModule = TestUtils.findModule(modules, "types2");
+ Module testModule = TestUtils.findModule(modules, "nodes");
ContainerSchemaNode peer = (ContainerSchemaNode) testModule.getDataChildByName("peer");
ContainerSchemaNode destination = (ContainerSchemaNode) peer.getDataChildByName("destination");
@Test
public void testGrouping() {
- Module testModule = TestUtils.findModule(modules, "types2");
+ Module testModule = TestUtils.findModule(modules, "custom");
Set<GroupingDefinition> groupings = testModule.getGroupings();
assertEquals(1, groupings.size());
GroupingDefinition grouping = groupings.iterator().next();
// suffix _u = added by uses
// suffix _g = defined in grouping
- Module testModule = TestUtils.findModule(modules, "types2");
+ Module testModule = TestUtils.findModule(modules, "custom");
// get grouping
Set<GroupingDefinition> groupings = testModule.getGroupings();
assertEquals(1, groupings.size());
GroupingDefinition grouping = groupings.iterator().next();
+ testModule = TestUtils.findModule(modules, "nodes");
+
// get node containing uses
ContainerSchemaNode peer = (ContainerSchemaNode) testModule.getDataChildByName("peer");
ContainerSchemaNode destination = (ContainerSchemaNode) peer.getDataChildByName("destination");
import org.opendaylight.controller.yang.model.api.ExtensionDefinition;
import org.opendaylight.controller.yang.model.api.FeatureDefinition;
import org.opendaylight.controller.yang.model.api.GroupingDefinition;
-import org.opendaylight.controller.yang.model.api.LeafListSchemaNode;
import org.opendaylight.controller.yang.model.api.LeafSchemaNode;
import org.opendaylight.controller.yang.model.api.ListSchemaNode;
import org.opendaylight.controller.yang.model.api.Module;
import org.opendaylight.controller.yang.model.util.ExtendedType;
import org.opendaylight.controller.yang.model.util.Int16;
import org.opendaylight.controller.yang.model.util.Int32;
-import org.opendaylight.controller.yang.model.util.Int8;
-import org.opendaylight.controller.yang.model.util.Leafref;
import org.opendaylight.controller.yang.model.util.StringType;
import org.opendaylight.controller.yang.model.util.Uint32;
import org.opendaylight.controller.yang.model.util.UnionType;
public class YangParserTest {
+
+ private final URI nodesNS = URI.create("urn:simple.nodes.test");
+ private final URI typesNS = URI.create("urn:simple.types.test");
+ private final URI customNS = URI.create("urn:custom.nodes.test");
+ private Date nodesRev;
+ private Date typesRev;
+ private Date customRev;
+
private final DateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
private Set<Module> modules;
@Before
- public void init() throws FileNotFoundException {
+ public void init() throws FileNotFoundException, ParseException {
+ nodesRev = simpleDateFormat.parse("2013-02-27");
+ typesRev = simpleDateFormat.parse("2013-07-03");
+ customRev = simpleDateFormat.parse("2013-02-27");
+
modules = TestUtils.loadModules(getClass().getResource("/model").getPath());
assertEquals(3, modules.size());
}
@Test
- public void testHeaders() {
- Module test = TestUtils.findModule(modules, "types1");
+ public void testHeaders() throws ParseException {
+ Module test = TestUtils.findModule(modules, "nodes");
- assertEquals("types1", test.getName());
+ assertEquals("nodes", test.getName());
assertEquals("1", test.getYangVersion());
- URI expectedNamespace = URI.create("urn:simple.container.demo");
- assertEquals(expectedNamespace, test.getNamespace());
- assertEquals("t1", test.getPrefix());
+ assertEquals(nodesNS, test.getNamespace());
+ assertEquals("n", test.getPrefix());
Set<ModuleImport> imports = test.getImports();
assertEquals(2, imports.size());
- ModuleImport import2 = TestUtils.findImport(imports, "data");
- assertEquals("types2", import2.getModuleName());
- assertEquals(TestUtils.createDate("2013-02-27"), import2.getRevision());
+ ModuleImport import2 = TestUtils.findImport(imports, "t");
+ assertEquals("types", import2.getModuleName());
+ assertEquals(typesRev, import2.getRevision());
- ModuleImport import3 = TestUtils.findImport(imports, "t3");
- assertEquals("types3", import3.getModuleName());
- assertEquals(TestUtils.createDate("2013-02-27"), import3.getRevision());
+ ModuleImport import3 = TestUtils.findImport(imports, "c");
+ assertEquals("custom", import3.getModuleName());
+ assertEquals(customRev, import3.getRevision());
assertEquals("opendaylight", test.getOrganization());
assertEquals("http://www.opendaylight.org/", test.getContact());
@Test
public void testOrderingTypedef() {
- Module test = TestUtils.findModule(modules, "types2");
+ Module test = TestUtils.findModule(modules, "types");
Set<TypeDefinition<?>> typedefs = test.getTypeDefinitions();
- String[] expectedOrder = new String[] { "my-base-int32-type", "my-custom-string", "my-decimal-type",
- "my-decimal-type-ext", "my-int-type", "my-int-type-ext", "my-int-type2", "my-string-type",
- "my-string-type-ext", "my-string-type2", "my-type1", "my-union", "my-union-ext", "nested-union1",
- "nested-union2" };
+ String[] expectedOrder = new String[] { "int32-ext1", "int32-ext2", "my-decimal-type", "my-union",
+ "my-union-ext", "nested-union2", "string-ext1", "string-ext2", "string-ext3", "string-ext4" };
String[] actualOrder = new String[typedefs.size()];
int i = 0;
@Test
public void testOrderingChildNodes() {
- Module test = TestUtils.findModule(modules, "types2");
- Set<DataSchemaNode> childNodes = test.getChildNodes();
- String[] expectedOrder = new String[] { "count", "if-name", "interfaces", "name", "nested-type-leaf", "peer",
- "system" };
- String[] actualOrder = new String[childNodes.size()];
+ Module test = TestUtils.findModule(modules, "nodes");
+ AugmentationSchema augment1 = null;
+ for (AugmentationSchema as : test.getAugmentations()) {
+ if ("if:ifType='ds0'".equals(as.getWhenCondition().toString())) {
+ augment1 = as;
+ break;
+ }
+ }
+ assertNotNull(augment1);
+
+ String[] expectedOrder = new String[] { "ds0ChannelNumber", "interface-id", "my-type", "odl", "schemas" };
+ String[] actualOrder = new String[expectedOrder.length];
int i = 0;
- for (DataSchemaNode child : childNodes) {
- actualOrder[i] = child.getQName().getLocalName();
+ for (DataSchemaNode augmentChild : augment1.getChildNodes()) {
+ actualOrder[i] = augmentChild.getQName().getLocalName();
i++;
}
+
assertArrayEquals(expectedOrder, actualOrder);
}
@Test
public void testOrderingNestedChildNodes() {
- Module test = TestUtils.findModule(modules, "types2");
+ Module test = TestUtils.findModule(modules, "custom");
Set<GroupingDefinition> groupings = test.getGroupings();
assertEquals(1, groupings.size());
GroupingDefinition target = groupings.iterator().next();
@Test
public void testParseContainer() {
- Module test = TestUtils.findModule(modules, "types2");
- URI expectedNamespace = URI.create("urn:simple.types.data.demo");
- String expectedPrefix = "t2";
- Date expectedRevision = TestUtils.createDate("2013-02-27");
+ Module test = TestUtils.findModule(modules, "types");
+ URI expectedNamespace = URI.create("urn:simple.types.test");
+ String expectedPrefix = "t";
ContainerSchemaNode interfaces = (ContainerSchemaNode) test.getDataChildByName("interfaces");
// test SchemaNode args
- QName expectedQName = new QName(expectedNamespace, expectedRevision, expectedPrefix, "interfaces");
+ QName expectedQName = new QName(expectedNamespace, typesRev, expectedPrefix, "interfaces");
assertEquals(expectedQName, interfaces.getQName());
- SchemaPath expectedPath = TestUtils.createPath(true, expectedNamespace, expectedRevision, expectedPrefix,
- "interfaces");
+ SchemaPath expectedPath = TestUtils.createPath(true, expectedNamespace, typesRev, expectedPrefix, "interfaces");
assertEquals(expectedPath, interfaces.getPath());
assertNull(interfaces.getDescription());
assertNull(interfaces.getReference());
@Test
public void testParseList() {
- Module test = TestUtils.findModule(modules, "types2");
- URI expectedNamespace = URI.create("urn:simple.types.data.demo");
- String expectedPrefix = "t2";
- Date expectedRevision = TestUtils.createDate("2013-02-27");
+ Module test = TestUtils.findModule(modules, "types");
+ URI expectedNamespace = URI.create("urn:simple.types.test");
+ String expectedPrefix = "t";
ContainerSchemaNode interfaces = (ContainerSchemaNode) test.getDataChildByName("interfaces");
ListSchemaNode ifEntry = (ListSchemaNode) interfaces.getDataChildByName("ifEntry");
// test SchemaNode args
- QName expectedQName = new QName(expectedNamespace, expectedRevision, expectedPrefix, "ifEntry");
+ QName expectedQName = new QName(expectedNamespace, typesRev, expectedPrefix, "ifEntry");
assertEquals(expectedQName, ifEntry.getQName());
- SchemaPath expectedPath = TestUtils.createPath(true, expectedNamespace, expectedRevision, expectedPrefix,
- "interfaces", "ifEntry");
+ SchemaPath expectedPath = TestUtils.createPath(true, expectedNamespace, typesRev, expectedPrefix, "interfaces",
+ "ifEntry");
assertEquals(expectedPath, ifEntry.getPath());
assertNull(ifEntry.getDescription());
assertNull(ifEntry.getReference());
assertEquals(2, availableAugmentations.size());
// test ListSchemaNode args
List<QName> expectedKey = new ArrayList<QName>();
- expectedKey.add(new QName(expectedNamespace, expectedRevision, expectedPrefix, "ifIndex"));
+ expectedKey.add(new QName(expectedNamespace, typesRev, expectedPrefix, "ifIndex"));
assertEquals(expectedKey, ifEntry.getKeyDefinition());
assertFalse(ifEntry.isUserOrdered());
// test DataNodeContainer args
assertTrue(ifMtu.getType() instanceof Int32);
}
- @Test
- public void testParseLeaf() throws ParseException {
- Module test = TestUtils.findModule(modules, "types2");
-
- // leaf if-name
- LeafSchemaNode ifName = (LeafSchemaNode) test.getDataChildByName("if-name");
- Leafref ifNameType = (Leafref) ifName.getType();
- QName qname = ifNameType.getQName();
-
- URI baseYangTypeNS = URI.create("urn:ietf:params:xml:ns:yang:1");
- assertEquals(baseYangTypeNS, qname.getNamespace());
- assertNull(qname.getRevision());
- assertEquals("", qname.getPrefix());
- assertEquals("leafref", qname.getLocalName());
-
- // leaf name
- LeafSchemaNode name = (LeafSchemaNode) test.getDataChildByName("name");
- StringType nameType = (StringType) name.getType();
- QName nameQName = nameType.getQName();
-
- assertEquals(baseYangTypeNS, nameQName.getNamespace());
- assertNull(nameQName.getRevision());
- assertEquals("", nameQName.getPrefix());
- assertEquals("string", nameQName.getLocalName());
-
- // leaf count
- LeafSchemaNode count = (LeafSchemaNode) test.getDataChildByName("count");
- ExtendedType countType = (ExtendedType) count.getType();
- QName countTypeQName = countType.getQName();
-
- URI expectedNS = URI.create("urn:simple.types.data.demo");
- Date expectedDate = simpleDateFormat.parse("2013-02-27");
- assertEquals(expectedNS, countTypeQName.getNamespace());
- assertEquals(expectedDate, countTypeQName.getRevision());
- assertEquals("t2", countTypeQName.getPrefix());
- assertEquals("int8", countTypeQName.getLocalName());
-
- Int8 countTypeBase = (Int8) countType.getBaseType();
- QName countTypeBaseQName = countTypeBase.getQName();
-
- assertEquals(baseYangTypeNS, countTypeBaseQName.getNamespace());
- assertNull(countTypeBaseQName.getRevision());
- assertEquals("", countTypeBaseQName.getPrefix());
- assertEquals("int8", countTypeBaseQName.getLocalName());
- }
-
- @Test
- public void testAugmentResolving() {
- // testfile1
- Module module1 = TestUtils.findModule(modules, "types1");
-
- Set<AugmentationSchema> module1Augmentations = module1.getAugmentations();
- AugmentationSchema augment1 = module1Augmentations.iterator().next();
- LeafSchemaNode augmentedLeafDefinition = (LeafSchemaNode) augment1.getDataChildByName("ds0ChannelNumber");
- assertTrue(augmentedLeafDefinition.isAugmenting());
-
- // testfile2
- Module module2 = TestUtils.findModule(modules, "types2");
-
- ContainerSchemaNode interfaces = (ContainerSchemaNode) module2.getDataChildByName("interfaces");
- ListSchemaNode ifEntry = (ListSchemaNode) interfaces.getDataChildByName("ifEntry");
- ContainerSchemaNode augmentedContainer = (ContainerSchemaNode) ifEntry.getDataChildByName("augment-holder");
-
- ContainerSchemaNode schemas = (ContainerSchemaNode) augmentedContainer.getDataChildByName("schemas");
- LeafSchemaNode linkleaf = (LeafSchemaNode) schemas.getDataChildByName("linkleaf");
- assertNotNull(linkleaf);
-
- // augmentation defined in testfile1 and augmentation returned from
- // augmented container have to be same
- Set<AugmentationSchema> augmentedContainerAugments = augmentedContainer.getAvailableAugmentations();
- AugmentationSchema augmentDefinition = augmentedContainerAugments.iterator().next();
- assertEquals(augment1, augmentDefinition);
-
- LeafSchemaNode augmentedLeaf = (LeafSchemaNode) augmentedContainer.getDataChildByName("ds0ChannelNumber");
- assertTrue(augmentedLeaf.isAugmenting());
- assertEquals(augmentedLeafDefinition, augmentedLeaf);
-
- Set<AugmentationSchema> ifEntryAugments = ifEntry.getAvailableAugmentations();
- assertEquals(2, ifEntryAugments.size());
-
- // testfile3
- Module module3 = TestUtils.findModule(modules, "types3");
-
- Set<AugmentationSchema> module3Augmentations = module3.getAugmentations();
- assertEquals(3, module3Augmentations.size());
- AugmentationSchema augment3 = null;
- for (AugmentationSchema as : module3Augmentations) {
- if ("if:ifType='ds0'".equals(as.getWhenCondition().toString())) {
- augment3 = as;
- }
- }
- ContainerSchemaNode augmentedContainerDefinition = (ContainerSchemaNode) augment3
- .getDataChildByName("augment-holder");
- assertTrue(augmentedContainerDefinition.isAugmenting());
-
- // check
- assertEquals(augmentedContainer, augmentedContainerDefinition);
- assertEquals(augmentedLeaf, augmentedLeafDefinition);
- }
-
- @Test
- public void testAugmentTarget() {
- Module test = TestUtils.findModule(modules, "types2");
-
- ContainerSchemaNode interfaces = (ContainerSchemaNode) test.getDataChildByName("interfaces");
- ListSchemaNode ifEntry = (ListSchemaNode) interfaces.getDataChildByName("ifEntry");
- Set<AugmentationSchema> augmentations = ifEntry.getAvailableAugmentations();
- assertEquals(2, augmentations.size());
-
- AugmentationSchema augment = null;
- for (AugmentationSchema as : augmentations) {
- if ("if:ifType='ds0'".equals(as.getWhenCondition().toString())) {
- augment = as;
- }
- }
- ContainerSchemaNode augmentHolder = (ContainerSchemaNode) augment.getDataChildByName("augment-holder");
- assertNotNull(augmentHolder);
- assertTrue(augmentHolder.isAugmenting());
- QName augmentHolderQName = augmentHolder.getQName();
- assertEquals("augment-holder", augmentHolderQName.getLocalName());
- assertEquals("t3", augmentHolderQName.getPrefix());
- assertEquals("Description for augment holder", augmentHolder.getDescription());
- }
-
@Test
public void testTypedefRangesResolving() throws ParseException {
- Module testModule = TestUtils.findModule(modules, "types1");
+ Module testModule = TestUtils.findModule(modules, "nodes");
+ LeafSchemaNode int32Leaf = (LeafSchemaNode) testModule.getDataChildByName("int32-leaf");
- LeafSchemaNode testleaf = (LeafSchemaNode) testModule.getDataChildByName("testleaf");
- ExtendedType leafType = (ExtendedType) testleaf.getType();
+ ExtendedType leafType = (ExtendedType) int32Leaf.getType();
QName leafTypeQName = leafType.getQName();
- assertEquals("my-type1", leafTypeQName.getLocalName());
- assertEquals("t1", leafTypeQName.getPrefix());
- assertEquals(URI.create("urn:simple.container.demo"), leafTypeQName.getNamespace());
- Date expectedDate = simpleDateFormat.parse("2013-02-27");
- assertEquals(expectedDate, leafTypeQName.getRevision());
- assertEquals(1, leafType.getRanges().size());
-
- ExtendedType baseType = (ExtendedType) leafType.getBaseType();
- QName baseTypeQName = baseType.getQName();
- assertEquals("my-type1", baseTypeQName.getLocalName());
- assertEquals("t2", baseTypeQName.getPrefix());
- assertEquals(URI.create("urn:simple.types.data.demo"), baseTypeQName.getNamespace());
- assertEquals(expectedDate, baseTypeQName.getRevision());
- assertEquals(2, baseType.getRanges().size());
-
+ assertEquals("int32-ext2", leafTypeQName.getLocalName());
+ assertEquals("n", leafTypeQName.getPrefix());
+ assertEquals(nodesNS, leafTypeQName.getNamespace());
+ assertEquals(nodesRev, leafTypeQName.getRevision());
+ assertNull(leafType.getUnits());
+ assertNull(leafType.getDefaultValue());
+ assertTrue(leafType.getLengths().isEmpty());
+ assertTrue(leafType.getPatterns().isEmpty());
List<RangeConstraint> ranges = leafType.getRanges();
assertEquals(1, ranges.size());
RangeConstraint range = ranges.get(0);
assertEquals(12L, range.getMin());
assertEquals(20L, range.getMax());
+
+ ExtendedType baseType = (ExtendedType) leafType.getBaseType();
+ QName baseTypeQName = baseType.getQName();
+ assertEquals("int32-ext2", baseTypeQName.getLocalName());
+ assertEquals("t", baseTypeQName.getPrefix());
+ assertEquals(typesNS, baseTypeQName.getNamespace());
+ assertEquals(typesRev, baseTypeQName.getRevision());
+ assertEquals("mile", baseType.getUnits());
+ assertEquals("11", baseType.getDefaultValue());
+ assertTrue(leafType.getLengths().isEmpty());
+ assertTrue(leafType.getPatterns().isEmpty());
+ List<RangeConstraint> baseTypeRanges = baseType.getRanges();
+ assertEquals(2, baseTypeRanges.size());
+ RangeConstraint baseTypeRange1 = baseTypeRanges.get(0);
+ assertEquals(3L, baseTypeRange1.getMin());
+ assertEquals(9L, baseTypeRange1.getMax());
+ RangeConstraint baseTypeRange2 = baseTypeRanges.get(1);
+ assertEquals(11L, baseTypeRange2.getMin());
+ assertEquals(20L, baseTypeRange2.getMax());
+
+ ExtendedType base = (ExtendedType) baseType.getBaseType();
+ QName baseQName = base.getQName();
+ assertEquals("int32-ext1", baseQName.getLocalName());
+ assertEquals("t", baseQName.getPrefix());
+ assertEquals(typesNS, baseQName.getNamespace());
+ assertEquals(typesRev, baseQName.getRevision());
+ assertNull(base.getUnits());
+ assertNull(base.getDefaultValue());
+ assertTrue(leafType.getLengths().isEmpty());
+ assertTrue(leafType.getPatterns().isEmpty());
+ List<RangeConstraint> baseRanges = base.getRanges();
+ assertEquals(1, baseRanges.size());
+ RangeConstraint baseRange = baseRanges.get(0);
+ assertEquals(2L, baseRange.getMin());
+ assertEquals(20L, baseRange.getMax());
+
+ assertTrue(base.getBaseType() instanceof Int32);
}
@Test
public void testTypedefPatternsResolving() {
- Module testModule = TestUtils.findModule(modules, "types1");
-
- LeafSchemaNode testleaf = (LeafSchemaNode) testModule.getDataChildByName("test-string-leaf");
- ExtendedType testleafType = (ExtendedType) testleaf.getType();
- QName testleafTypeQName = testleafType.getQName();
- assertEquals("my-string-type-ext", testleafTypeQName.getLocalName());
- assertEquals("t2", testleafTypeQName.getPrefix());
-
- List<PatternConstraint> patterns = testleafType.getPatterns();
+ Module testModule = TestUtils.findModule(modules, "nodes");
+ LeafSchemaNode stringleaf = (LeafSchemaNode) testModule.getDataChildByName("string-leaf");
+
+ ExtendedType type = (ExtendedType) stringleaf.getType();
+ QName typeQName = type.getQName();
+ assertEquals("string-ext4", typeQName.getLocalName());
+ assertEquals("t", typeQName.getPrefix());
+ assertEquals(typesNS, typeQName.getNamespace());
+ assertEquals(typesRev, typeQName.getRevision());
+ assertNull(type.getUnits());
+ assertNull(type.getDefaultValue());
+ List<PatternConstraint> patterns = type.getPatterns();
assertEquals(1, patterns.size());
PatternConstraint pattern = patterns.iterator().next();
assertEquals("[e-z]*", pattern.getRegularExpression());
-
- ExtendedType baseType = (ExtendedType) testleafType.getBaseType();
- assertEquals("my-string-type2", baseType.getQName().getLocalName());
-
- patterns = baseType.getPatterns();
+ assertTrue(type.getLengths().isEmpty());
+ assertTrue(type.getRanges().isEmpty());
+
+ ExtendedType baseType1 = (ExtendedType) type.getBaseType();
+ QName baseType1QName = baseType1.getQName();
+ assertEquals("string-ext3", baseType1QName.getLocalName());
+ assertEquals("t", baseType1QName.getPrefix());
+ assertEquals(typesNS, baseType1QName.getNamespace());
+ assertEquals(typesRev, baseType1QName.getRevision());
+ assertNull(baseType1.getUnits());
+ assertNull(baseType1.getDefaultValue());
+ patterns = baseType1.getPatterns();
assertEquals(1, patterns.size());
pattern = patterns.iterator().next();
assertEquals("[b-u]*", pattern.getRegularExpression());
-
- List<LengthConstraint> lengths = testleafType.getLengths();
- assertTrue(lengths.isEmpty());
+ assertTrue(baseType1.getLengths().isEmpty());
+ assertTrue(baseType1.getRanges().isEmpty());
+
+ ExtendedType baseType2 = (ExtendedType) baseType1.getBaseType();
+ QName baseType2QName = baseType2.getQName();
+ assertEquals("string-ext2", baseType2QName.getLocalName());
+ assertEquals("t", baseType2QName.getPrefix());
+ assertEquals(typesNS, baseType2QName.getNamespace());
+ assertEquals(typesRev, baseType2QName.getRevision());
+ assertNull(baseType2.getUnits());
+ assertNull(baseType2.getDefaultValue());
+ assertTrue(baseType2.getPatterns().isEmpty());
+ List<LengthConstraint> baseType2Lengths = baseType2.getLengths();
+ assertEquals(1, baseType2Lengths.size());
+ LengthConstraint length = baseType2Lengths.get(0);
+ assertEquals(6L, length.getMin());
+ assertEquals(10L, length.getMax());
+ assertTrue(baseType2.getRanges().isEmpty());
+
+ ExtendedType baseType3 = (ExtendedType) baseType2.getBaseType();
+ QName baseType3QName = baseType3.getQName();
+ assertEquals("string-ext1", baseType3QName.getLocalName());
+ assertEquals("t", baseType3QName.getPrefix());
+ assertEquals(typesNS, baseType3QName.getNamespace());
+ assertEquals(typesRev, baseType3QName.getRevision());
+ assertNull(baseType3.getUnits());
+ assertNull(baseType3.getDefaultValue());
+ patterns = baseType3.getPatterns();
+ assertEquals(1, patterns.size());
+ pattern = patterns.iterator().next();
+ assertEquals("[a-k]*", pattern.getRegularExpression());
+ List<LengthConstraint> baseType3Lengths = baseType3.getLengths();
+ assertEquals(1, baseType3Lengths.size());
+ length = baseType3Lengths.get(0);
+ assertEquals(5L, length.getMin());
+ assertEquals(11L, length.getMax());
+ assertTrue(baseType3.getRanges().isEmpty());
+
+ assertTrue(baseType3.getBaseType() instanceof StringType);
}
@Test
public void testTypedefLengthsResolving() {
- Module testModule = TestUtils.findModule(modules, "types1");
-
- LeafSchemaNode testleaf = (LeafSchemaNode) testModule.getDataChildByName("leaf-with-length");
- ExtendedType testleafType = (ExtendedType) testleaf.getType();
- assertEquals("my-string-type", testleafType.getQName().getLocalName());
-
- List<LengthConstraint> lengths = testleafType.getLengths();
- assertEquals(1, lengths.size());
-
- LengthConstraint length = lengths.get(0);
+ Module testModule = TestUtils.findModule(modules, "nodes");
+
+ LeafSchemaNode lengthLeaf = (LeafSchemaNode) testModule.getDataChildByName("length-leaf");
+ ExtendedType type = (ExtendedType) lengthLeaf.getType();
+
+ QName typeQName = type.getQName();
+ assertEquals("string-ext2", typeQName.getLocalName());
+ assertEquals("n", typeQName.getPrefix());
+ assertEquals(nodesNS, typeQName.getNamespace());
+ assertEquals(nodesRev, typeQName.getRevision());
+ assertNull(type.getUnits());
+ assertNull(type.getDefaultValue());
+ assertTrue(type.getPatterns().isEmpty());
+ List<LengthConstraint> typeLengths = type.getLengths();
+ assertEquals(1, typeLengths.size());
+ LengthConstraint length = typeLengths.get(0);
assertEquals(7L, length.getMin());
assertEquals(10L, length.getMax());
- }
-
- @Test
- public void testTypeDef() {
- Module testModule = TestUtils.findModule(modules, "types2");
-
- LeafSchemaNode testleaf = (LeafSchemaNode) testModule.getDataChildByName("nested-type-leaf");
- ExtendedType testleafType = (ExtendedType) testleaf.getType();
- assertEquals("my-type1", testleafType.getQName().getLocalName());
-
- ExtendedType baseType = (ExtendedType) testleafType.getBaseType();
- assertEquals("my-base-int32-type", baseType.getQName().getLocalName());
-
- Int32 int32Type = (Int32) baseType.getBaseType();
- QName qname = int32Type.getQName();
- assertEquals(URI.create("urn:ietf:params:xml:ns:yang:1"), qname.getNamespace());
- assertNull(qname.getRevision());
- assertEquals("", qname.getPrefix());
- assertEquals("int32", qname.getLocalName());
- List<RangeConstraint> ranges = baseType.getRanges();
- assertEquals(1, ranges.size());
- RangeConstraint range = ranges.get(0);
- assertEquals(2L, range.getMin());
- assertEquals(20L, range.getMax());
+ assertTrue(type.getRanges().isEmpty());
+
+ ExtendedType baseType1 = (ExtendedType) type.getBaseType();
+ QName baseType1QName = baseType1.getQName();
+ assertEquals("string-ext2", baseType1QName.getLocalName());
+ assertEquals("t", baseType1QName.getPrefix());
+ assertEquals(typesNS, baseType1QName.getNamespace());
+ assertEquals(typesRev, baseType1QName.getRevision());
+ assertNull(baseType1.getUnits());
+ assertNull(baseType1.getDefaultValue());
+ assertTrue(baseType1.getPatterns().isEmpty());
+ List<LengthConstraint> baseType2Lengths = baseType1.getLengths();
+ assertEquals(1, baseType2Lengths.size());
+ length = baseType2Lengths.get(0);
+ assertEquals(6L, length.getMin());
+ assertEquals(10L, length.getMax());
+ assertTrue(baseType1.getRanges().isEmpty());
+
+ ExtendedType baseType2 = (ExtendedType) baseType1.getBaseType();
+ QName baseType2QName = baseType2.getQName();
+ assertEquals("string-ext1", baseType2QName.getLocalName());
+ assertEquals("t", baseType2QName.getPrefix());
+ assertEquals(typesNS, baseType2QName.getNamespace());
+ assertEquals(typesRev, baseType2QName.getRevision());
+ assertNull(baseType2.getUnits());
+ assertNull(baseType2.getDefaultValue());
+ List<PatternConstraint> patterns = baseType2.getPatterns();
+ assertEquals(1, patterns.size());
+ PatternConstraint pattern = patterns.iterator().next();
+ assertEquals("[a-k]*", pattern.getRegularExpression());
+ List<LengthConstraint> baseType3Lengths = baseType2.getLengths();
+ assertEquals(1, baseType3Lengths.size());
+ length = baseType3Lengths.get(0);
+ assertEquals(5L, length.getMin());
+ assertEquals(11L, length.getMax());
+ assertTrue(baseType2.getRanges().isEmpty());
+
+ assertTrue(baseType2.getBaseType() instanceof StringType);
}
@Test
public void testTypedefDecimal1() {
- Module testModule = TestUtils.findModule(modules, "types1");
+ Module testModule = TestUtils.findModule(modules, "nodes");
+ LeafSchemaNode testleaf = (LeafSchemaNode) testModule.getDataChildByName("decimal-leaf");
- LeafSchemaNode testleaf = (LeafSchemaNode) testModule.getDataChildByName("test-decimal-leaf");
ExtendedType type = (ExtendedType) testleaf.getType();
+ QName typeQName = type.getQName();
+ assertEquals("my-decimal-type", typeQName.getLocalName());
+ assertEquals("n", typeQName.getPrefix());
+ assertEquals(nodesNS, typeQName.getNamespace());
+ assertEquals(nodesRev, typeQName.getRevision());
+ assertNull(type.getUnits());
+ assertNull(type.getDefaultValue());
assertEquals(4, (int) type.getFractionDigits());
+ assertTrue(type.getLengths().isEmpty());
+ assertTrue(type.getPatterns().isEmpty());
+ assertTrue(type.getRanges().isEmpty());
ExtendedType typeBase = (ExtendedType) type.getBaseType();
- assertEquals("my-decimal-type", typeBase.getQName().getLocalName());
+ QName typeBaseQName = typeBase.getQName();
+ assertEquals("my-decimal-type", typeBaseQName.getLocalName());
+ assertEquals("t", typeBaseQName.getPrefix());
+ assertEquals(typesNS, typeBaseQName.getNamespace());
+ assertEquals(typesRev, typeBaseQName.getRevision());
+ assertNull(typeBase.getUnits());
+ assertNull(typeBase.getDefaultValue());
assertNull(typeBase.getFractionDigits());
+ assertTrue(typeBase.getLengths().isEmpty());
+ assertTrue(typeBase.getPatterns().isEmpty());
+ assertTrue(typeBase.getRanges().isEmpty());
Decimal64 decimal = (Decimal64) typeBase.getBaseType();
assertEquals(6, (int) decimal.getFractionDigits());
@Test
public void testTypedefDecimal2() {
- Module testModule = TestUtils.findModule(modules, "types1");
+ Module testModule = TestUtils.findModule(modules, "nodes");
+ LeafSchemaNode testleaf = (LeafSchemaNode) testModule.getDataChildByName("decimal-leaf2");
- LeafSchemaNode testleaf = (LeafSchemaNode) testModule.getDataChildByName("test-decimal-leaf2");
- TypeDefinition<?> baseType = testleaf.getType().getBaseType();
- assertTrue(testleaf.getType().getBaseType() instanceof Decimal64);
- Decimal64 baseTypeCast = (Decimal64) baseType;
- assertEquals(5, (int) baseTypeCast.getFractionDigits());
+ ExtendedType type = (ExtendedType) testleaf.getType();
+ QName typeQName = type.getQName();
+ assertEquals("my-decimal-type", typeQName.getLocalName());
+ assertEquals("t", typeQName.getPrefix());
+ assertEquals(typesNS, typeQName.getNamespace());
+ assertEquals(typesRev, typeQName.getRevision());
+ assertNull(type.getUnits());
+ assertNull(type.getDefaultValue());
+ assertNull(type.getFractionDigits());
+ assertTrue(type.getLengths().isEmpty());
+ assertTrue(type.getPatterns().isEmpty());
+ assertTrue(type.getRanges().isEmpty());
+
+ Decimal64 baseTypeDecimal = (Decimal64) type.getBaseType();
+ assertEquals(6, (int) baseTypeDecimal.getFractionDigits());
}
@Test
public void testTypedefUnion() {
- Module testModule = TestUtils.findModule(modules, "types1");
-
- LeafSchemaNode testleaf = (LeafSchemaNode) testModule.getDataChildByName("union-leaf");
- ExtendedType testleafType = (ExtendedType) testleaf.getType();
- assertEquals("my-union-ext", testleafType.getQName().getLocalName());
-
- ExtendedType baseType = (ExtendedType) testleafType.getBaseType();
- assertEquals("my-union", baseType.getQName().getLocalName());
-
- UnionType unionBase = (UnionType) baseType.getBaseType();
+ Module testModule = TestUtils.findModule(modules, "nodes");
+ LeafSchemaNode unionleaf = (LeafSchemaNode) testModule.getDataChildByName("union-leaf");
+
+ ExtendedType type = (ExtendedType) unionleaf.getType();
+ QName typeQName = type.getQName();
+ assertEquals("my-union-ext", typeQName.getLocalName());
+ assertEquals("t", typeQName.getPrefix());
+ assertEquals(typesNS, typeQName.getNamespace());
+ assertEquals(typesRev, typeQName.getRevision());
+ assertNull(type.getUnits());
+ assertNull(type.getDefaultValue());
+ assertNull(type.getFractionDigits());
+ assertTrue(type.getLengths().isEmpty());
+ assertTrue(type.getPatterns().isEmpty());
+ assertTrue(type.getRanges().isEmpty());
+
+ ExtendedType baseType = (ExtendedType) type.getBaseType();
+ QName baseTypeQName = baseType.getQName();
+ assertEquals("my-union", baseTypeQName.getLocalName());
+ assertEquals("t", baseTypeQName.getPrefix());
+ assertEquals(typesNS, baseTypeQName.getNamespace());
+ assertEquals(typesRev, baseTypeQName.getRevision());
+ assertNull(baseType.getUnits());
+ assertNull(baseType.getDefaultValue());
+ assertNull(baseType.getFractionDigits());
+ assertTrue(baseType.getLengths().isEmpty());
+ assertTrue(baseType.getPatterns().isEmpty());
+ assertTrue(baseType.getRanges().isEmpty());
+
+ UnionType unionType = (UnionType) baseType.getBaseType();
+ List<TypeDefinition<?>> unionTypes = unionType.getTypes();
+ assertEquals(2, unionTypes.size());
- List<TypeDefinition<?>> unionTypes = unionBase.getTypes();
ExtendedType unionType1 = (ExtendedType) unionTypes.get(0);
+ QName unionType1QName = baseType.getQName();
+ assertEquals("my-union", unionType1QName.getLocalName());
+ assertEquals("t", unionType1QName.getPrefix());
+ assertEquals(typesNS, unionType1QName.getNamespace());
+ assertEquals(typesRev, unionType1QName.getRevision());
+ assertNull(unionType1.getUnits());
+ assertNull(unionType1.getDefaultValue());
+ assertNull(unionType1.getFractionDigits());
+ assertTrue(unionType1.getLengths().isEmpty());
+ assertTrue(unionType1.getPatterns().isEmpty());
List<RangeConstraint> ranges = unionType1.getRanges();
assertEquals(1, ranges.size());
RangeConstraint range = ranges.get(0);
assertEquals(1L, range.getMin());
assertEquals(100L, range.getMax());
-
assertTrue(unionType1.getBaseType() instanceof Int16);
- assertTrue(unionTypes.get(1) instanceof Int32);
- }
-
- @Test
- public void testNestedUnionResolving1() {
- Module testModule = TestUtils.findModule(modules, "types1");
-
- LeafSchemaNode testleaf = (LeafSchemaNode) testModule.getDataChildByName("nested-union-leaf");
-
- ExtendedType nestedUnion1 = (ExtendedType) testleaf.getType();
- assertEquals("nested-union1", nestedUnion1.getQName().getLocalName());
-
- ExtendedType nestedUnion2 = (ExtendedType) nestedUnion1.getBaseType();
- assertEquals("nested-union2", nestedUnion2.getQName().getLocalName());
-
- UnionType unionType1 = (UnionType) nestedUnion2.getBaseType();
- List<TypeDefinition<?>> unionTypes = unionType1.getTypes();
- assertEquals(2, unionTypes.size());
- assertTrue(unionTypes.get(0) instanceof StringType);
- assertTrue(unionTypes.get(1) instanceof ExtendedType);
-
- ExtendedType extendedUnion = (ExtendedType) unionTypes.get(1);
- ExtendedType extendedUnionBase = (ExtendedType) extendedUnion.getBaseType();
- assertEquals("my-union", extendedUnionBase.getQName().getLocalName());
- UnionType extendedTargetUnion = (UnionType) extendedUnionBase.getBaseType();
- List<TypeDefinition<?>> extendedTargetTypes = extendedTargetUnion.getTypes();
- assertTrue(extendedTargetTypes.get(0).getBaseType() instanceof Int16);
- assertTrue(extendedTargetTypes.get(1) instanceof Int32);
-
- ExtendedType int16 = (ExtendedType) extendedTargetTypes.get(0);
- assertTrue(int16.getBaseType() instanceof Int16);
- List<RangeConstraint> ranges = int16.getRanges();
- assertEquals(1, ranges.size());
- RangeConstraint range = ranges.get(0);
- assertEquals(1L, range.getMin());
- assertEquals(100L, range.getMax());
+ assertTrue(unionTypes.get(1) instanceof Int32);
}
@Test
- public void testNestedUnionResolving2() {
- Module testModule = TestUtils.findModule(modules, "types1");
-
+ public void testNestedUnionResolving() {
+ Module testModule = TestUtils.findModule(modules, "nodes");
LeafSchemaNode testleaf = (LeafSchemaNode) testModule.getDataChildByName("custom-union-leaf");
- ExtendedType testleafType = (ExtendedType) testleaf.getType();
- QName testleafTypeQName = testleafType.getQName();
- assertEquals(URI.create("urn:simple.container.demo.test"), testleafTypeQName.getNamespace());
- assertEquals(TestUtils.createDate("2013-02-27"), testleafTypeQName.getRevision());
- assertEquals("t3", testleafTypeQName.getPrefix());
+ ExtendedType type = (ExtendedType) testleaf.getType();
+ QName testleafTypeQName = type.getQName();
+ assertEquals(customNS, testleafTypeQName.getNamespace());
+ assertEquals(customRev, testleafTypeQName.getRevision());
+ assertEquals("c", testleafTypeQName.getPrefix());
assertEquals("union1", testleafTypeQName.getLocalName());
+ assertNull(type.getUnits());
+ assertNull(type.getDefaultValue());
+ assertNull(type.getFractionDigits());
+ assertTrue(type.getLengths().isEmpty());
+ assertTrue(type.getPatterns().isEmpty());
+ assertTrue(type.getRanges().isEmpty());
- ExtendedType union2 = (ExtendedType) testleafType.getBaseType();
- QName union2QName = union2.getQName();
- assertEquals(URI.create("urn:simple.container.demo.test"), union2QName.getNamespace());
- assertEquals(TestUtils.createDate("2013-02-27"), union2QName.getRevision());
- assertEquals("t3", union2QName.getPrefix());
- assertEquals("union2", union2QName.getLocalName());
+ ExtendedType typeBase = (ExtendedType) type.getBaseType();
+ QName typeBaseQName = typeBase.getQName();
+ assertEquals(customNS, typeBaseQName.getNamespace());
+ assertEquals(customRev, typeBaseQName.getRevision());
+ assertEquals("c", typeBaseQName.getPrefix());
+ assertEquals("union2", typeBaseQName.getLocalName());
+ assertNull(typeBase.getUnits());
+ assertNull(typeBase.getDefaultValue());
+ assertNull(typeBase.getFractionDigits());
+ assertTrue(typeBase.getLengths().isEmpty());
+ assertTrue(typeBase.getPatterns().isEmpty());
+ assertTrue(typeBase.getRanges().isEmpty());
- UnionType union2Base = (UnionType) union2.getBaseType();
- List<TypeDefinition<?>> unionTypes = union2Base.getTypes();
+ UnionType union = (UnionType) typeBase.getBaseType();
+ List<TypeDefinition<?>> unionTypes = union.getTypes();
assertEquals(2, unionTypes.size());
assertTrue(unionTypes.get(0) instanceof Int32);
assertTrue(unionTypes.get(1) instanceof ExtendedType);
- ExtendedType nestedUnion2 = (ExtendedType) unionTypes.get(1);
- QName nestedUnion2QName = nestedUnion2.getQName();
- assertEquals(URI.create("urn:simple.types.data.demo"), nestedUnion2QName.getNamespace());
- assertEquals(TestUtils.createDate("2013-02-27"), nestedUnion2QName.getRevision());
- assertEquals("t2", nestedUnion2QName.getPrefix());
- assertEquals("nested-union2", nestedUnion2QName.getLocalName());
-
- UnionType nestedUnion2Base = (UnionType) nestedUnion2.getBaseType();
- List<TypeDefinition<?>> nestedUnion2Types = nestedUnion2Base.getTypes();
+ ExtendedType unionType1 = (ExtendedType) unionTypes.get(1);
+ QName uniontType1QName = unionType1.getQName();
+ assertEquals(typesNS, uniontType1QName.getNamespace());
+ assertEquals(typesRev, uniontType1QName.getRevision());
+ assertEquals("t", uniontType1QName.getPrefix());
+ assertEquals("nested-union2", uniontType1QName.getLocalName());
+ assertNull(unionType1.getUnits());
+ assertNull(unionType1.getDefaultValue());
+ assertNull(unionType1.getFractionDigits());
+ assertTrue(unionType1.getLengths().isEmpty());
+ assertTrue(unionType1.getPatterns().isEmpty());
+ assertTrue(unionType1.getRanges().isEmpty());
+
+ UnionType nestedUnion = (UnionType) unionType1.getBaseType();
+ List<TypeDefinition<?>> nestedUnion2Types = nestedUnion.getTypes();
assertEquals(2, nestedUnion2Types.size());
assertTrue(nestedUnion2Types.get(0) instanceof StringType);
assertTrue(nestedUnion2Types.get(1) instanceof ExtendedType);
ExtendedType myUnionExt = (ExtendedType) nestedUnion2Types.get(1);
QName myUnionExtQName = myUnionExt.getQName();
- assertEquals(URI.create("urn:simple.types.data.demo"), myUnionExtQName.getNamespace());
- assertEquals(TestUtils.createDate("2013-02-27"), myUnionExtQName.getRevision());
- assertEquals("t2", myUnionExtQName.getPrefix());
+ assertEquals(typesNS, myUnionExtQName.getNamespace());
+ assertEquals(typesRev, myUnionExtQName.getRevision());
+ assertEquals("t", myUnionExtQName.getPrefix());
assertEquals("my-union-ext", myUnionExtQName.getLocalName());
+ assertNull(myUnionExt.getUnits());
+ assertNull(myUnionExt.getDefaultValue());
+ assertNull(myUnionExt.getFractionDigits());
+ assertTrue(myUnionExt.getLengths().isEmpty());
+ assertTrue(myUnionExt.getPatterns().isEmpty());
+ assertTrue(myUnionExt.getRanges().isEmpty());
ExtendedType myUnion = (ExtendedType) myUnionExt.getBaseType();
QName myUnionQName = myUnion.getQName();
- assertEquals(URI.create("urn:simple.types.data.demo"), myUnionQName.getNamespace());
- assertEquals(TestUtils.createDate("2013-02-27"), myUnionQName.getRevision());
- assertEquals("t2", myUnionQName.getPrefix());
+ assertEquals(typesNS, myUnionQName.getNamespace());
+ assertEquals(typesRev, myUnionQName.getRevision());
+ assertEquals("t", myUnionQName.getPrefix());
assertEquals("my-union", myUnionQName.getLocalName());
+ assertNull(myUnion.getUnits());
+ assertNull(myUnion.getDefaultValue());
+ assertNull(myUnion.getFractionDigits());
+ assertTrue(myUnion.getLengths().isEmpty());
+ assertTrue(myUnion.getPatterns().isEmpty());
+ assertTrue(myUnion.getRanges().isEmpty());
UnionType myUnionBase = (UnionType) myUnion.getBaseType();
List<TypeDefinition<?>> myUnionBaseTypes = myUnionBase.getTypes();
assertEquals(2, myUnionBaseTypes.size());
- assertTrue(myUnionBaseTypes.get(0).getBaseType() instanceof Int16);
+ assertTrue(myUnionBaseTypes.get(0) instanceof ExtendedType);
assertTrue(myUnionBaseTypes.get(1) instanceof Int32);
- ExtendedType int16 = (ExtendedType) myUnionBaseTypes.get(0);
- List<RangeConstraint> ranges = int16.getRanges();
+
+ ExtendedType int16Ext = (ExtendedType) myUnionBaseTypes.get(0);
+ QName int16ExtQName = int16Ext.getQName();
+ assertEquals(typesNS, int16ExtQName.getNamespace());
+ assertEquals(typesRev, int16ExtQName.getRevision());
+ assertEquals("t", int16ExtQName.getPrefix());
+ assertEquals("int16", int16ExtQName.getLocalName());
+ assertNull(int16Ext.getUnits());
+ assertNull(int16Ext.getDefaultValue());
+ assertNull(int16Ext.getFractionDigits());
+ assertTrue(int16Ext.getLengths().isEmpty());
+ assertTrue(int16Ext.getPatterns().isEmpty());
+ List<RangeConstraint> ranges = int16Ext.getRanges();
assertEquals(1, ranges.size());
RangeConstraint range = ranges.get(0);
assertEquals(1L, range.getMin());
assertEquals(100L, range.getMax());
+
+ assertTrue(int16Ext.getBaseType() instanceof Int16);
}
@Test
public void testChoice() {
- Module testModule = TestUtils.findModule(modules, "types1");
- ContainerSchemaNode peer = (ContainerSchemaNode) testModule.getDataChildByName("transfer");
- ChoiceNode how = (ChoiceNode) peer.getDataChildByName("how");
+ Module testModule = TestUtils.findModule(modules, "nodes");
+ ContainerSchemaNode transfer = (ContainerSchemaNode) testModule.getDataChildByName("transfer");
+ ChoiceNode how = (ChoiceNode) transfer.getDataChildByName("how");
Set<ChoiceCaseNode> cases = how.getCases();
assertEquals(5, cases.size());
ChoiceCaseNode input = null;
@Test
public void testAnyXml() {
- Module testModule = TestUtils.findModule(modules, "types1");
+ Module testModule = TestUtils.findModule(modules, "nodes");
AnyXmlSchemaNode data = (AnyXmlSchemaNode) testModule.getDataChildByName("data");
- assertNotNull(data);
+ assertNotNull("anyxml data not found", data);
+
+ // test SchemaNode args
+ QName qname = data.getQName();
+ assertEquals("data", qname.getLocalName());
+ assertEquals("n", qname.getPrefix());
+ assertEquals(nodesNS, qname.getNamespace());
+ assertEquals(nodesRev, qname.getRevision());
+ assertTrue(data.getDescription().contains("Copy of the source typesstore subset that matched"));
+ assertNull(data.getReference());
+ assertEquals(Status.OBSOLETE, data.getStatus());
+ assertEquals(0, data.getUnknownSchemaNodes().size());
+ // test DataSchemaNode args
+ assertFalse(data.isAugmenting());
+ assertTrue(data.isConfiguration());
+ ConstraintDefinition constraints = data.getConstraints();
+ assertNull(constraints.getWhenCondition());
+ assertEquals(0, constraints.getMustConstraints().size());
+ assertFalse(constraints.isMandatory());
+ assertNull(constraints.getMinElements());
+ assertNull(constraints.getMaxElements());
}
@Test
public void testDeviation() {
- Module testModule = TestUtils.findModule(modules, "types1");
+ Module testModule = TestUtils.findModule(modules, "nodes");
Set<Deviation> deviations = testModule.getDeviations();
assertEquals(1, deviations.size());
-
Deviation dev = deviations.iterator().next();
- SchemaPath expectedPath = TestUtils.createPath(true, null, null, "data", "system", "user");
+
+ assertEquals("system/user ref", dev.getReference());
+
+ List<QName> path = new ArrayList<QName>();
+ path.add(new QName(typesNS, typesRev, "t", "interfaces"));
+ path.add(new QName(typesNS, typesRev, "t", "ifEntry"));
+ SchemaPath expectedPath = new SchemaPath(path, true);
+
assertEquals(expectedPath, dev.getTargetPath());
assertEquals(Deviate.ADD, dev.getDeviate());
}
@Test
public void testUnknownNode() {
- Module testModule = TestUtils.findModule(modules, "types3");
+ Module testModule = TestUtils.findModule(modules, "custom");
ContainerSchemaNode network = (ContainerSchemaNode) testModule.getDataChildByName("network");
List<UnknownSchemaNode> unknownNodes = network.getUnknownSchemaNodes();
assertEquals(1, unknownNodes.size());
@Test
public void testFeature() {
- Module testModule = TestUtils.findModule(modules, "types3");
+ Module testModule = TestUtils.findModule(modules, "custom");
Set<FeatureDefinition> features = testModule.getFeatures();
assertEquals(1, features.size());
}
@Test
public void testExtension() {
- Module testModule = TestUtils.findModule(modules, "types3");
+ Module testModule = TestUtils.findModule(modules, "custom");
List<ExtensionDefinition> extensions = testModule.getExtensionSchemaNodes();
assertEquals(1, extensions.size());
ExtensionDefinition extension = extensions.get(0);
assertEquals("name", extension.getArgument());
- assertFalse(extension.isYinElement());
+ assertTrue(extension.isYinElement());
}
@Test
public void testNotification() {
- Module testModule = TestUtils.findModule(modules, "types3");
- URI expectedNamespace = URI.create("urn:simple.container.demo.test");
- String expectedPrefix = "t3";
- Date expectedRevision = TestUtils.createDate("2013-02-27");
+ Module testModule = TestUtils.findModule(modules, "custom");
+ String expectedPrefix = "c";
Set<NotificationDefinition> notifications = testModule.getNotifications();
assertEquals(1, notifications.size());
NotificationDefinition notification = notifications.iterator().next();
// test SchemaNode args
- QName expectedQName = new QName(expectedNamespace, expectedRevision, expectedPrefix, "event");
+ QName expectedQName = new QName(customNS, customRev, expectedPrefix, "event");
assertEquals(expectedQName, notification.getQName());
- SchemaPath expectedPath = TestUtils.createPath(true, expectedNamespace, expectedRevision, expectedPrefix,
- "event");
+ SchemaPath expectedPath = TestUtils.createPath(true, customNS, customRev, expectedPrefix, "event");
assertEquals(expectedPath, notification.getPath());
assertNull(notification.getDescription());
assertNull(notification.getReference());
@Test
public void testRpc() {
- Module testModule = TestUtils.findModule(modules, "types3");
+ Module testModule = TestUtils.findModule(modules, "custom");
Set<RpcDefinition> rpcs = testModule.getRpcs();
assertEquals(1, rpcs.size());
assertNotNull(output.getDataChildByName("data"));
}
- @Test
- public void testAugmentNodesTypesSchemaPath() throws Exception {
- Module testModule = TestUtils.findModule(modules, "types1");
- Set<AugmentationSchema> augments = testModule.getAugmentations();
- assertEquals(1, augments.size());
- AugmentationSchema augment = augments.iterator().next();
-
- LeafSchemaNode ifcId = (LeafSchemaNode) augment.getDataChildByName("interface-id");
- Leafref ifcIdType = (Leafref) ifcId.getType();
- SchemaPath ifcIdTypeSchemaPath = ifcIdType.getPath();
- List<QName> ifcIdTypePath = ifcIdTypeSchemaPath.getPath();
-
- URI types1URI = URI.create("urn:simple.container.demo");
- URI types2URI = URI.create("urn:simple.types.data.demo");
- URI types3URI = URI.create("urn:simple.container.demo.test");
- Date expectedDate = simpleDateFormat.parse("2013-02-27");
-
- QName q0 = new QName(types2URI, expectedDate, "data", "interfaces");
- QName q1 = new QName(types2URI, expectedDate, "data", "ifEntry");
- QName q2 = new QName(types3URI, expectedDate, "data", "augment-holder");
- QName q3 = new QName(types1URI, expectedDate, "data", "interface-id");
- assertEquals(q0, ifcIdTypePath.get(0));
- assertEquals(q1, ifcIdTypePath.get(1));
- assertEquals(q2, ifcIdTypePath.get(2));
- assertEquals(q3, ifcIdTypePath.get(3));
-
- LeafListSchemaNode higherLayer = (LeafListSchemaNode) augment.getDataChildByName("higher-layer-if");
- Leafref higherLayerType = (Leafref) higherLayer.getType();
- SchemaPath higherLayerTypeSchemaPath = higherLayerType.getPath();
- List<QName> higherLayerTypePath = higherLayerTypeSchemaPath.getPath();
- assertEquals(q0, higherLayerTypePath.get(0));
- assertEquals(q1, higherLayerTypePath.get(1));
- assertEquals(q2, higherLayerTypePath.get(2));
- q3 = new QName(types1URI, expectedDate, "data", "higher-layer-if");
- assertEquals(q3, higherLayerTypePath.get(3));
-
- LeafSchemaNode myType = (LeafSchemaNode) augment.getDataChildByName("my-type");
- ExtendedType leafType = (ExtendedType) myType.getType();
-
- testModule = TestUtils.findModule(modules, "types2");
- TypeDefinition<?> typedef = TestUtils.findTypedef(testModule.getTypeDefinitions(), "my-type1");
-
- assertEquals(typedef, leafType);
- }
-
@Test
public void testTypePath() throws ParseException {
- Module test = TestUtils.findModule(modules, "types2");
+ Module test = TestUtils.findModule(modules, "types");
Set<TypeDefinition<?>> types = test.getTypeDefinitions();
// my-base-int32-type
- ExtendedType int32Typedef = (ExtendedType) TestUtils.findTypedef(types, "my-base-int32-type");
+ ExtendedType int32Typedef = (ExtendedType) TestUtils.findTypedef(types, "int32-ext1");
QName int32TypedefQName = int32Typedef.getQName();
- URI expectedNS = URI.create("urn:simple.types.data.demo");
- Date expectedDate = simpleDateFormat.parse("2013-02-27");
- assertEquals(expectedNS, int32TypedefQName.getNamespace());
- assertEquals(expectedDate, int32TypedefQName.getRevision());
- assertEquals("t2", int32TypedefQName.getPrefix());
- assertEquals("my-base-int32-type", int32TypedefQName.getLocalName());
+ assertEquals(typesNS, int32TypedefQName.getNamespace());
+ assertEquals(typesRev, int32TypedefQName.getRevision());
+ assertEquals("t", int32TypedefQName.getPrefix());
+ assertEquals("int32-ext1", int32TypedefQName.getLocalName());
SchemaPath typeSchemaPath = int32Typedef.getPath();
List<QName> typePath = typeSchemaPath.getPath();
@Test
public void testTypePath2() throws ParseException {
- Module test = TestUtils.findModule(modules, "types2");
+ Module test = TestUtils.findModule(modules, "types");
Set<TypeDefinition<?>> types = test.getTypeDefinitions();
// my-base-int32-type
ExtendedType myDecType = (ExtendedType) TestUtils.findTypedef(types, "my-decimal-type");
QName myDecTypeQName = myDecType.getQName();
- URI expectedNS = URI.create("urn:simple.types.data.demo");
- Date expectedDate = simpleDateFormat.parse("2013-02-27");
- assertEquals(expectedNS, myDecTypeQName.getNamespace());
- assertEquals(expectedDate, myDecTypeQName.getRevision());
- assertEquals("t2", myDecTypeQName.getPrefix());
+ assertEquals(typesNS, myDecTypeQName.getNamespace());
+ assertEquals(typesRev, myDecTypeQName.getRevision());
+ assertEquals("t", myDecTypeQName.getPrefix());
assertEquals("my-decimal-type", myDecTypeQName.getLocalName());
SchemaPath typeSchemaPath = myDecType.getPath();
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
+import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.opendaylight.controller.yang.model.api.ChoiceNode;
import org.opendaylight.controller.yang.model.api.ContainerSchemaNode;
import org.opendaylight.controller.yang.model.api.DataSchemaNode;
+import org.opendaylight.controller.yang.model.api.Deviation;
+import org.opendaylight.controller.yang.model.api.Deviation.Deviate;
import org.opendaylight.controller.yang.model.api.GroupingDefinition;
import org.opendaylight.controller.yang.model.api.IdentitySchemaNode;
import org.opendaylight.controller.yang.model.api.LeafSchemaNode;
assertEquals("inet", qname.getPrefix());
assertEquals("port-number", qname.getLocalName());
- ExtendedType dscpExt = (ExtendedType)TestUtils.findTypedef(module.getTypeDefinitions(), "dscp-ext");
+ ExtendedType dscpExt = (ExtendedType) TestUtils.findTypedef(module.getTypeDefinitions(), "dscp-ext");
List<RangeConstraint> ranges = dscpExt.getRanges();
assertEquals(1, ranges.size());
RangeConstraint range = ranges.get(0);
@Test
public void testUsesFromContext() throws Exception {
SchemaContext context = null;
- try (InputStream stream = new FileInputStream(getClass().getResource("/model/testfile2.yang").getPath())) {
- context = parser.resolveSchemaContext(TestUtils.loadModules(Lists.newArrayList(stream)));
+ try (InputStream stream1 = new FileInputStream(getClass().getResource("/model/custom.yang").getPath());
+ InputStream stream2 = new FileInputStream(getClass().getResource("/model/types.yang").getPath());
+ InputStream stream3 = new FileInputStream(getClass().getResource("/model/nodes.yang").getPath())) {
+ context = parser.resolveSchemaContext(TestUtils.loadModules(Lists.newArrayList(stream1, stream2, stream3)));
}
Module testModule = null;
try (InputStream stream = new FileInputStream(getClass().getResource("/context-test/test2.yang").getPath())) {
// suffix _g = defined in grouping from context
// get grouping
- Module contextModule = context.findModuleByNamespace(URI.create("urn:simple.types.data.demo"));
+ Module contextModule = context.findModuleByNamespace(URI.create("urn:custom.nodes.test"));
assertNotNull(contextModule);
Set<GroupingDefinition> groupings = contextModule.getGroupings();
assertEquals(1, groupings.size());
GroupingDefinition grouping = groupings.iterator().next();
// get node containing uses
- ContainerSchemaNode peer = (ContainerSchemaNode)testModule.getDataChildByName("peer");
- ContainerSchemaNode destination = (ContainerSchemaNode)peer.getDataChildByName("destination");
+ ContainerSchemaNode peer = (ContainerSchemaNode) testModule.getDataChildByName("peer");
+ ContainerSchemaNode destination = (ContainerSchemaNode) peer.getDataChildByName("destination");
// check uses
Set<UsesNode> uses = destination.getUses();
assertEquals(1, uses.size());
// check uses process
- AnyXmlSchemaNode data_u = (AnyXmlSchemaNode)destination.getDataChildByName("data");
+ AnyXmlSchemaNode data_u = (AnyXmlSchemaNode) destination.getDataChildByName("data");
assertNotNull(data_u);
assertTrue(data_u.isAddedByUses());
- AnyXmlSchemaNode data_g = (AnyXmlSchemaNode)grouping.getDataChildByName("data");
+ AnyXmlSchemaNode data_g = (AnyXmlSchemaNode) grouping.getDataChildByName("data");
assertNotNull(data_g);
assertFalse(data_g.isAddedByUses());
assertFalse(data_u.equals(data_g));
- ChoiceNode how_u = (ChoiceNode)destination.getDataChildByName("how");
+ ChoiceNode how_u = (ChoiceNode) destination.getDataChildByName("how");
assertNotNull(how_u);
assertTrue(how_u.isAddedByUses());
- ChoiceNode how_g = (ChoiceNode)grouping.getDataChildByName("how");
+ ChoiceNode how_g = (ChoiceNode) grouping.getDataChildByName("how");
assertNotNull(how_g);
assertFalse(how_g.isAddedByUses());
assertFalse(how_u.equals(how_g));
- LeafSchemaNode address_u = (LeafSchemaNode)destination.getDataChildByName("address");
+ LeafSchemaNode address_u = (LeafSchemaNode) destination.getDataChildByName("address");
assertNotNull(address_u);
assertTrue(address_u.isAddedByUses());
- LeafSchemaNode address_g = (LeafSchemaNode)grouping.getDataChildByName("address");
+ LeafSchemaNode address_g = (LeafSchemaNode) grouping.getDataChildByName("address");
assertNotNull(address_g);
assertFalse(address_g.isAddedByUses());
assertFalse(address_u.equals(address_g));
- ContainerSchemaNode port_u = (ContainerSchemaNode)destination.getDataChildByName("port");
+ ContainerSchemaNode port_u = (ContainerSchemaNode) destination.getDataChildByName("port");
assertNotNull(port_u);
assertTrue(port_u.isAddedByUses());
- ContainerSchemaNode port_g = (ContainerSchemaNode)grouping.getDataChildByName("port");
+ ContainerSchemaNode port_g = (ContainerSchemaNode) grouping.getDataChildByName("port");
assertNotNull(port_g);
assertFalse(port_g.isAddedByUses());
assertFalse(port_u.equals(port_g));
- ListSchemaNode addresses_u = (ListSchemaNode)destination.getDataChildByName("addresses");
+ ListSchemaNode addresses_u = (ListSchemaNode) destination.getDataChildByName("addresses");
assertNotNull(addresses_u);
assertTrue(addresses_u.isAddedByUses());
- ListSchemaNode addresses_g = (ListSchemaNode)grouping.getDataChildByName("addresses");
+ ListSchemaNode addresses_g = (ListSchemaNode) grouping.getDataChildByName("addresses");
assertNotNull(addresses_g);
assertFalse(addresses_g.isAddedByUses());
assertFalse(addresses_u.equals(addresses_g));
@Test
public void testUsesRefineFromContext() throws Exception {
SchemaContext context = null;
- try (InputStream stream = new FileInputStream(getClass().getResource("/model/testfile2.yang").getPath())) {
- context = parser.resolveSchemaContext(TestUtils.loadModules(Lists.newArrayList(stream)));
+ try (InputStream stream1 = new FileInputStream(getClass().getResource("/model/custom.yang").getPath());
+ InputStream stream2 = new FileInputStream(getClass().getResource("/model/types.yang").getPath());
+ InputStream stream3 = new FileInputStream(getClass().getResource("/model/nodes.yang").getPath())) {
+ context = parser.resolveSchemaContext(TestUtils.loadModules(Lists.newArrayList(stream1, stream2, stream3)));
}
Module module = null;
try (InputStream stream = new FileInputStream(getClass().getResource("/context-test/test2.yang").getPath())) {
// test grouping path
List<QName> path = new ArrayList<QName>();
- QName qname = new QName(URI.create("urn:simple.types.data.demo"), simpleDateFormat.parse("2013-02-27"), "t2",
+ QName qname = new QName(URI.create("urn:custom.nodes.test"), simpleDateFormat.parse("2013-02-27"), "c",
"target");
path.add(qname);
SchemaPath expectedPath = new SchemaPath(path, true);
@Test
public void testUnknownNodes() throws Exception {
SchemaContext context = null;
- try (InputStream stream = new FileInputStream(getClass().getResource("/types/custom-types-test@2012-4-4.yang").getPath())) {
+ try (InputStream stream = new FileInputStream(getClass().getResource("/types/custom-types-test@2012-4-4.yang")
+ .getPath())) {
context = parser.resolveSchemaContext(TestUtils.loadModules(Lists.newArrayList(stream)));
}
List<UnknownSchemaNode> unknownNodes = network.getUnknownSchemaNodes();
assertEquals(1, unknownNodes.size());
- UnknownSchemaNode un = unknownNodes.iterator().next();
+ UnknownSchemaNode un = unknownNodes.get(0);
QName unType = un.getNodeType();
assertEquals(URI.create("urn:simple.container.demo"), unType.getNamespace());
assertEquals(simpleDateFormat.parse("2012-04-16"), unType.getRevision());
assertTrue(ifEntry == ifEntryAfterAugment);
}
+ @Test
+ public void testDeviation() throws Exception {
+ // load first module
+ SchemaContext context = null;
+ String resource = "/model/types.yang";
+
+ try (InputStream stream = new FileInputStream(getClass().getResource(resource).getPath())) {
+ context = parser.resolveSchemaContext(TestUtils.loadModules(Lists.newArrayList(stream)));
+ }
+
+ // load another modules and parse them against already existing context
+ Set<Module> modules = null;
+ try (InputStream stream = new FileInputStream(getClass().getResource("/context-test/deviation-test.yang")
+ .getPath())) {
+ List<InputStream> input = Lists.newArrayList(stream);
+ modules = TestUtils.loadModulesWithContext(input, context);
+ }
+ assertNotNull(modules);
+
+ // test deviation
+ Module testModule = TestUtils.findModule(modules, "deviation-test");
+ Set<Deviation> deviations = testModule.getDeviations();
+ assertEquals(1, deviations.size());
+ Deviation dev = deviations.iterator().next();
+
+ assertEquals("system/user ref", dev.getReference());
+
+ URI expectedNS = URI.create("urn:simple.types.test");
+ DateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
+ Date expectedRev = simpleDateFormat.parse("2013-07-03");
+ List<QName> path = new ArrayList<QName>();
+ path.add(new QName(expectedNS, expectedRev, "t", "interfaces"));
+ path.add(new QName(expectedNS, expectedRev, "t", "ifEntry"));
+ SchemaPath expectedPath = new SchemaPath(path, true);
+
+ assertEquals(expectedPath, dev.getTargetPath());
+ assertEquals(Deviate.ADD, dev.getDeviate());
+ }
+
}
--- /dev/null
+module deviation-test {
+ yang-version 1;
+ namespace "urn:simple.deviation.test";
+ prefix "dev";
+
+ import types {
+ prefix "t";
+ revision-date 2013-07-03;
+ }
+
+ organization "opendaylight";
+ contact "http://www.opendaylight.org/";
+
+ revision "2013-02-27" {
+ reference " WILL BE DEFINED LATER";
+ }
+
+
+ deviation /t:interfaces/t:ifEntry {
+ deviate add {
+ default "admin"; // new users are 'admin' by default
+ config "true";
+ }
+ reference "system/user ref";
+ }
+
+}
namespace "urn:simple.demo.test2";
prefix "t2";
- import types2 {
+ import custom {
prefix "data";
}
-module types3 {
+module custom {
yang-version 1;
- namespace "urn:simple.container.demo.test";
- prefix "t3";
+ namespace "urn:custom.nodes.test";
+ prefix "c";
- import types2 {
- prefix "data";
- revision-date 2013-02-27;
+ import types {
+ prefix "types";
+ revision-date 2013-07-03;
}
organization "opendaylight";
typedef union2 {
type union {
type int32;
- type data:nested-union2;
+ type types:nested-union2;
}
}
- augment "/data:interfaces/data:ifEntry" {
+ augment "/types:interfaces/types:ifEntry" {
when "if:ifType='ds0'";
container augment-holder {
description "Description for augment holder";
}
}
- augment "/data:interfaces/data:ifEntry" {
+ augment "/types:interfaces/types:ifEntry" {
when "if:ifType='ds2'";
container augment-holder2 {
description "Description for augment holder";
}
}
- augment "/data:interfaces/data:ifEntry/t3:augment-holder/t1:schemas" {
+ augment "/types:interfaces/types:ifEntry/t3:augment-holder/t1:schemas" {
when "if:leafType='ds1'";
leaf linkleaf {
type binary;
extension c-define {
description
- "Takes as argument a name string.
- Makes the code generator use the given name in the
- #define.";
- argument "name";
+ "Takes as argument a name string. Makes the code generator use the given name in the #define.";
+ argument "name" {
+ yin-element "true";
+ }
}
notification event {
}
}
+ grouping target {
+ anyxml data {
+ config true;
+ description "Copy of the source datastore subset.";
+ mandatory false;
+ must "test-condition-text";
+ reference "test-no-reference";
+ status "obsolete";
+ when "test-when-text";
+ }
+ choice how {
+ description "test choice description";
+ default interval;
+ case interval {
+ leaf interval {
+ type uint16;
+ default 30;
+ units minutes;
+ }
+ }
+ case daily {
+ leaf daily {
+ type empty;
+ }
+ leaf time-of-day {
+ type string;
+ units 24-hour-clock;
+ default 1am;
+ }
+ }
+ }
+ leaf address {
+ type string;
+ description "Target IP address";
+ }
+ container port {
+ description "Target port container";
+ }
+ list addresses {
+ key "id";
+ leaf id {
+ type int8;
+ }
+ }
+ grouping target-inner {
+ description "target-inner default description";
+ leaf inner-grouping-id {
+ type int8;
+ }
+ }
+ typedef group-type {
+ type types:my-decimal-type;
+ }
+
+ opendaylight;
+ }
+
}
--- /dev/null
+module nodes {
+ yang-version 1;
+ namespace "urn:simple.nodes.test";
+ prefix "n";
+
+ import types {
+ prefix "t";
+ revision-date 2013-07-03;
+ }
+
+ import custom {
+ prefix "c";
+ revision-date 2013-02-27;
+ }
+
+ organization "opendaylight";
+ contact "http://www.opendaylight.org/";
+
+ revision "2013-02-27" {
+ reference " WILL BE DEFINED LATER";
+ }
+
+ leaf int32-leaf {
+ type t:int32-ext2 {
+ range "12..max";
+ }
+ }
+
+ leaf string-leaf {
+ type t:string-ext4;
+ }
+
+ leaf length-leaf {
+ type t:string-ext2 {
+ length "7..max";
+ }
+ }
+
+ leaf decimal-leaf {
+ type t:my-decimal-type {
+ fraction-digits 4;
+ }
+ }
+
+ leaf decimal-leaf2 {
+ type t:my-decimal-type;
+ }
+
+ container ext {
+ types:c-define "MY_INTERFACES";
+ }
+
+ leaf union-leaf {
+ type t:my-union-ext;
+ }
+
+ deviation /t:interfaces/t:ifEntry {
+ deviate add {
+ default "admin"; // new users are 'admin' by default
+ config "true";
+ }
+ reference "system/user ref";
+ }
+
+ leaf custom-union-leaf {
+ type c:union1;
+ }
+
+ container transfer {
+ choice how {
+ default interval;
+ container input {
+ }
+ list output {
+ leaf id {
+ type string;
+ }
+ }
+ case interval {
+ leaf interval {
+ type uint16;
+ default 30;
+ units minutes;
+ }
+ }
+ case daily {
+ leaf daily {
+ type empty;
+ }
+ leaf time-of-day {
+ type string;
+ units 24-hour-clock;
+ default 1am;
+ }
+ }
+ case manual {
+ leaf manual {
+ type empty;
+ }
+ }
+ }
+ }
+
+ anyxml data {
+ description
+ "Copy of the source typesstore subset that matched
+ the filter criteria (if any). An empty types container
+ indicates that the request did not produce any results.";
+ status obsolete;
+ }
+
+ augment "/t:interfaces/t:ifEntry/c:augment-holder" {
+ when "if:ifType='ds0'";
+ leaf ds0ChannelNumber {
+ type string;
+ }
+ leaf interface-id {
+ type leafref {
+ path "/if:interfaces/if:interface/if:name";
+ }
+ }
+ leaf my-type {
+ type t:int32-ext2;
+ }
+ container schemas {
+ }
+ choice odl {
+ leaf id {
+ type int8;
+ }
+ case node1 {
+ description "node1";
+ }
+ case node2 {
+ description "node2";
+ }
+ container node3 {
+ description "node3";
+ }
+ }
+ }
+
+ container mycont {
+ container innercont {
+ typedef mytype {
+ type string;
+ }
+ leaf myleaf {
+ type mytype;
+ }
+ }
+ }
+
+ container peer {
+ container destination {
+ uses c:target {
+ refine address {
+ default "1.2.3.4";
+ description "IP address of target node";
+ reference "address reference added by refine";
+ config false;
+ mandatory true;
+ must "ifType != 'ethernet' or " +
+ "(ifType = 'ethernet' and ifMTU = 1500)" {
+ error-message "An ethernet MTU must be 1500";
+ }
+ }
+ refine port {
+ description "description of port defined by refine";
+ reference "port reference added by refine";
+ config false;
+ presence "presence is required";
+ }
+ refine addresses {
+ description "description of addresses defined by refine";
+ reference "addresses reference added by refine";
+ config false;
+ min-elements 2;
+ max-elements 12;
+ }
+ refine target-inner {
+ description "new target-inner grouping description";
+ }
+ refine group-type {
+ description "new group-type description";
+ reference "new group-type reference";
+ }
+ }
+ }
+ }
+
+}
+++ /dev/null
-module types1 {
- yang-version 1;
- namespace "urn:simple.container.demo";
- prefix "t1";
-
- import types2 {
- prefix "data";
- revision-date 2013-02-27;
- }
-
- import types3 {
- prefix "t3";
- revision-date 2013-02-27;
- }
-
- organization "opendaylight";
- contact "http://www.opendaylight.org/";
-
- revision "2013-02-27" {
- reference " WILL BE DEFINED LATER";
- }
-
- leaf testleaf {
- type data:my-type1 {
- range "12..max";
- }
- }
-
- leaf test-string-leaf {
- type data:my-string-type-ext;
- }
-
- leaf leaf-with-length {
- type data:my-string-type {
- length "7..max";
- }
- }
-
- leaf test-int-leaf {
- type data:my-int-type-ext;
- }
-
- leaf test-decimal-leaf {
- type data:my-decimal-type {
- fraction-digits 4;
- }
- }
-
- leaf test-decimal-leaf2 {
- type data:my-decimal-type-ext;
- }
-
- container ext {
- data:c-define "MY_INTERFACES";
- }
-
- leaf union-leaf {
- type data:my-union-ext;
- }
-
- deviation /data:system/data:user {
- deviate add {
- default "admin"; // new users are 'admin' by default
- config "true";
- }
- }
-
- leaf nested-union-leaf {
- type data:nested-union1;
- }
-
- leaf custom-union-leaf {
- type t3:union1;
- }
-
- container transfer {
- choice how {
- default interval;
- container input {
- }
- list output {
- leaf id {
- type string;
- }
- }
- case interval {
- leaf interval {
- type uint16;
- default 30;
- units minutes;
- }
- }
- case daily {
- leaf daily {
- type empty;
- }
- leaf time-of-day {
- type string;
- units 24-hour-clock;
- default 1am;
- }
- }
- case manual {
- leaf manual {
- type empty;
- }
- }
- }
- }
-
- anyxml data {
- description
- "Copy of the source datastore subset that matched
- the filter criteria (if any). An empty data container
- indicates that the request did not produce any results.";
- }
-
- augment "/data:interfaces/data:ifEntry/t3:augment-holder" {
- when "if:ifType='ds0'";
- leaf ds0ChannelNumber {
- type string;
- }
- leaf interface-id {
- type leafref {
- path "/if:interfaces/if:interface/if:name";
- }
- }
- leaf-list higher-layer-if {
- type leafref {
- path "/if:interfaces/if:interface/if:higher-layer-if";
- }
- }
- leaf my-type {
- type data:my-type1;
- }
- container schemas {
- }
- choice odl {
- leaf id {
- type int8;
- }
- }
- }
-
- container mycont {
- container innercont {
- typedef mytype {
- type string;
- }
-
- leaf myleaf {
- type mytype;
- }
- }
- }
-
-}
+++ /dev/null
-module types2 {
- yang-version 1;
- namespace "urn:simple.types.data.demo";
- prefix "t2";
-
- organization "opendaylight";
- contact "http://www.opendaylight.org/";
-
- description "This is types-data test description";
-
- revision "2013-02-27" {
- reference " WILL BE DEFINED LATER";
- }
-
- typedef my-base-int32-type {
- type int32 {
- range "2..20";
- }
- }
-
- typedef my-type1 {
- type my-base-int32-type {
- range "3..9|11..max";
- }
- units "mile";
- default "11";
- }
-
- typedef my-custom-string {
- type string {
- pattern "[a-k]*";
- length "5..11";
- }
- }
-
- typedef my-string-type {
- type my-custom-string {
- length "6..10";
- }
- }
-
- typedef my-string-type2 {
- type my-string-type {
- pattern "[b-u]*";
- }
- }
-
- typedef my-string-type-ext {
- type my-string-type2 {
- pattern "[e-z]*";
- }
- }
-
- typedef my-int-type {
- type int32 {
- range "10..20";
- }
- }
-
- typedef my-int-type2 {
- type my-int-type {
- range "12..18";
- }
- }
-
- typedef my-int-type-ext {
- type my-int-type2 {
- range "14..16";
- }
- }
-
- typedef my-decimal-type {
- type decimal64 {
- fraction-digits 6;
- }
- }
-
- typedef my-decimal-type-ext {
- type decimal64 {
- fraction-digits 5;
- }
- }
-
- typedef my-union {
- type union {
- type int16 {
- range "1..100";
- }
- type int32;
- }
- }
-
- typedef my-union-ext {
- type my-union;
- }
-
- typedef nested-union1 {
- type nested-union2;
- }
-
- typedef nested-union2 {
- type union {
- type my-union-ext;
- type string;
- }
- }
-
- leaf if-name {
- type leafref {
- path "/interface/name";
- }
- }
-
- leaf name {
- type string;
- }
-
- leaf count {
- type int8 {
- range "1..10";
- }
- }
-
- leaf nested-type-leaf {
- type my-type1;
- }
-
- extension c-define {
- description
- "Takes as argument a name string.
- Makes the code generator use the given name in the
- #define.";
- argument "name" {
- yin-element "true";
- }
- }
-
- container system {
- leaf user {
- type string;
- }
- }
-
- grouping target {
- anyxml data {
- config true;
- description "Copy of the source datastore subset.";
- mandatory false;
- must "test-condition-text";
- reference "test-no-reference";
- status "obsolete";
- when "test-when-text";
- }
- choice how {
- description "test choice description";
- default interval;
- case interval {
- leaf interval {
- type uint16;
- default 30;
- units minutes;
- }
- }
- case daily {
- leaf daily {
- type empty;
- }
- leaf time-of-day {
- type string;
- units 24-hour-clock;
- default 1am;
- }
- }
- }
- leaf address {
- type string;
- description "Target IP address";
- }
- container port {
- description "Target port container";
- }
- list addresses {
- key "id";
- leaf id {
- type int8;
- }
- }
- grouping target-inner {
- description "target-inner default description";
- leaf inner-grouping-id {
- type int8;
- }
- }
- typedef group-type {
- type my-decimal-type;
- }
-
- opendaylight;
- }
-
- container peer {
- container destination {
- uses target {
- refine address {
- default "1.2.3.4";
- description "IP address of target node";
- reference "address reference added by refine";
- config false;
- mandatory true;
- must "ifType != 'ethernet' or " +
- "(ifType = 'ethernet' and ifMTU = 1500)" {
- error-message "An ethernet MTU must be 1500";
- }
- }
- refine port {
- description "description of port defined by refine";
- reference "port reference added by refine";
- config false;
- presence "presence is required";
- }
- refine addresses {
- description "description of addresses defined by refine";
- reference "addresses reference added by refine";
- config false;
- min-elements 2;
- max-elements 12;
- }
- refine target-inner {
- description "new target-inner grouping description";
- }
- refine group-type {
- description "new group-type description";
- reference "new group-type reference";
- }
- }
- }
- }
-
- container interfaces {
- list ifEntry {
- key "ifIndex";
-
- leaf ifIndex {
- type uint32;
- units minutes;
- }
-
- leaf ifMtu {
- type int32;
- }
-
- min-elements 1;
- max-elements 11;
- }
- }
-
-}
--- /dev/null
+module types {
+ yang-version 1;
+ namespace "urn:simple.types.test";
+ prefix "t";
+
+ organization "opendaylight";
+ contact "http://www.opendaylight.org/";
+ description "This is types-data test description";
+
+ revision "2013-07-03" {
+ reference " WILL BE DEFINED LATER";
+ }
+
+ typedef int32-ext1 {
+ type int32 {
+ range "2..20";
+ }
+ }
+
+ typedef int32-ext2 {
+ type int32-ext1 {
+ range "3..9|11..max";
+ }
+ units "mile";
+ default "11";
+ }
+
+ typedef string-ext1 {
+ type string {
+ pattern "[a-k]*";
+ length "5..11";
+ }
+ }
+
+ typedef string-ext2 {
+ type string-ext1 {
+ length "6..10";
+ }
+ }
+
+ typedef string-ext3 {
+ type string-ext2 {
+ pattern "[b-u]*";
+ }
+ }
+
+ typedef string-ext4 {
+ type string-ext3 {
+ pattern "[e-z]*";
+ }
+ }
+
+ typedef my-decimal-type {
+ type decimal64 {
+ fraction-digits 6;
+ }
+ }
+
+ typedef my-union {
+ type union {
+ type int16 {
+ range "1..100";
+ }
+ type int32;
+ }
+ }
+
+ typedef my-union-ext {
+ type my-union;
+ }
+
+ typedef nested-union2 {
+ type union {
+ type my-union-ext;
+ type string;
+ }
+ }
+
+ container interfaces {
+ list ifEntry {
+ key "ifIndex";
+
+ leaf ifIndex {
+ type uint32;
+ units minutes;
+ }
+
+ leaf ifMtu {
+ type int32;
+ }
+
+ min-elements 1;
+ max-elements 11;
+ }
+ }
+
+}
<module>yang-common</module>
<module>yang-data-api</module>
<module>yang-data-util</module>
+ <module>yang-data-impl</module>
<module>yang-model-api</module>
<module>yang-model-util</module>
<module>yang-binding</module>
+++ /dev/null
-/*\r
- * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.\r
- *\r
- * This program and the accompanying materials are made available under the\r
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
- * and is available at http://www.eclipse.org/legal/epl-v10.html\r
- */\r
-package org.opendaylight.controller.yang.data.api;\r
-\r
-import org.opendaylight.controller.yang.common.QName;\r
-\r
-/**\r
- * For the use cases of changing the state data, the node modifications are\r
- * modeled as part of additional metadata in data tree. The modification types\r
- * are based on Netconf edit-config RPCs. In order to modify the configuration\r
- * or state data tree the user must create a tree representing the modification\r
- * of the data and apply that modification to the target tree.\r
- * \r
- * \r
- * @see <a href="http://tools.ietf.org/html/rfc6241">Network Configuration\r
- * Protocol (NETCONF)</a>\r
- * \r
- */\r
-public interface CompositeNodeModification extends CompositeNode {\r
-\r
- ModifyAction getModificationAction();\r
-\r
- // Container Modification\r
-\r
- /**\r
- * The data identified by the node containing this modification is merged\r
- * with the data at the corresponding level in the data tree\r
- * \r
- * @param node\r
- * in data tree\r
- */\r
- void mergeChild(CompositeNode node);\r
-\r
- /**\r
- * The data identified by the node containing this modification replaces any\r
- * related data in the target data tree If no such data exists in the target\r
- * data tree, the child node is created.\r
- * \r
- * @param node\r
- * composite node\r
- */\r
- void replaceChild(CompositeNode node);\r
-\r
- /**\r
- * Adds new composite node into data tree\r
- * \r
- * @param node\r
- * composite node\r
- */\r
- void addChild(CompositeNode node);\r
-\r
- /**\r
- * The data identified by the node containing this modification is deleted\r
- * from the target data tree if and only if the data currently exists in the\r
- * target data tree. If the data does not exist, an error is returned with\r
- * an error value of "data-missing".\r
- * \r
- * @param node\r
- */\r
- void deleteChild(CompositeNode node);\r
-\r
- /**\r
- * The data identified by the node containing this attribute is deleted from\r
- * the target data tree if the data currently exists in the target data\r
- * tree. If the data does not exist, the modification is silently ignored.\r
- * \r
- * @param node\r
- * composite node\r
- */\r
- void removeChild(CompositeNode node);\r
-\r
- // Leaf Modifications\r
-\r
- /**\r
- * The data identified by the node containing this modification replaces any\r
- * related data in the target data tree If no such data exists in the target\r
- * data tree, it is created.\r
- * \r
- * @param leaf\r
- */\r
- void replaceSimpleNode(SimpleNode<?> leaf);\r
-\r
- /**\r
- * The data identified by the node containing this modification is deleted\r
- * from the target data tree if and only if the data currently exists in the\r
- * target data tree. If the data does not exist, an error is returned with\r
- * an error value of "data-missing".\r
- * \r
- * @param leaf\r
- */\r
- void deleteSimpleNode(SimpleNode<?> leaf);\r
-\r
- /**\r
- * The data identified by the node containing this attribute is deleted from\r
- * the target data tree if the data currently exists in the target data\r
- * tree. If the data does not exist, the modification is silently ignored.\r
- * \r
- * @param leaf\r
- */\r
- void removeSimpleNode(SimpleNode<?> leaf);\r
-\r
- void removeLeaf(SimpleNode<?> leaf);\r
-\r
- void removeLeaf(QName leaf);\r
-}\r
--- /dev/null
+/*\r
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.\r
+ *\r
+ * This program and the accompanying materials are made available under the\r
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
+ * and is available at http://www.eclipse.org/legal/epl-v10.html\r
+ */\r
+package org.opendaylight.controller.yang.data.api;\r
+\r
+import java.util.List;\r
+\r
+\r
+/**\r
+ * @author michal.rehak\r
+ *\r
+ */\r
+public interface MutableCompositeNode extends MutableNode<List<Node<?>>>, CompositeNode {\r
+ \r
+ /**\r
+ * update internal map\r
+ */\r
+ public void init();\r
+}\r
--- /dev/null
+/*\r
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.\r
+ *\r
+ * This program and the accompanying materials are made available under the\r
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
+ * and is available at http://www.eclipse.org/legal/epl-v10.html\r
+ */\r
+package org.opendaylight.controller.yang.data.api;\r
+\r
+\r
+/**\r
+ * Base representation of node in the data tree, defines basic parameters of\r
+ * node such as a QName.\r
+ * \r
+ * \r
+ * @param <T>\r
+ */\r
+public interface MutableNode<T> extends Node<T> {\r
+\r
+ /**\r
+ * @param parent value to set\r
+ */\r
+ void setParent(CompositeNode parent);\r
+ \r
+ /**\r
+ * @param value value to set (children list or leaf value)\r
+ */\r
+ void setValue(T value);\r
+ \r
+ /**\r
+ * @param action value to set\r
+ */\r
+ void setModifyAction(ModifyAction action);\r
+}\r
--- /dev/null
+/*\r
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.\r
+ *\r
+ * This program and the accompanying materials are made available under the\r
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
+ * and is available at http://www.eclipse.org/legal/epl-v10.html\r
+ */\r
+package org.opendaylight.controller.yang.data.api;\r
+\r
+\r
+/**\r
+ * @author michal.rehak\r
+ * @param <T> node value type\r
+ *\r
+ */\r
+public interface MutableSimpleNode<T> extends MutableNode<T>, SimpleNode<T> {\r
+ \r
+ // nothing\r
+ \r
+}\r
/**\r
* Returns the name of the Node\r
* \r
- * @return\r
+ * @return qName of node\r
*/\r
QName getNodeType();\r
\r
--- /dev/null
+/*\r
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.\r
+ *\r
+ * This program and the accompanying materials are made available under the\r
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
+ * and is available at http://www.eclipse.org/legal/epl-v10.html\r
+ */\r
+package org.opendaylight.controller.yang.data.api;\r
+\r
+/**\r
+ * @author michal.rehak\r
+ * \r
+ */\r
+public interface NodeModification {\r
+\r
+ /**\r
+ * @return modify action\r
+ */\r
+ ModifyAction getModificationAction();\r
+\r
+}\r
--- /dev/null
+/*\r
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.\r
+ *\r
+ * This program and the accompanying materials are made available under the\r
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
+ * and is available at http://www.eclipse.org/legal/epl-v10.html\r
+ */\r
+package org.opendaylight.controller.yang.data.api;\r
+\r
+\r
+/**\r
+ * @author michal.rehak\r
+ *\r
+ */\r
+public interface NodeModificationBuilder {\r
+\r
+ public abstract Node<?> getMutableEquivalent(Node<?> originalNode);\r
+\r
+ public abstract CompositeNode buildDiffTree();\r
+\r
+ public abstract void mergeNode(MutableCompositeNode alteredNode);\r
+\r
+ public abstract void removeNode(MutableCompositeNode deadNode);\r
+\r
+ public abstract void removeNode(MutableSimpleNode<?> deadNode);\r
+\r
+ public abstract void deleteNode(MutableSimpleNode<?> deadNode);\r
+\r
+ public abstract void deleteNode(MutableCompositeNode deadNode);\r
+\r
+ public abstract void replaceNode(MutableCompositeNode replacementNode);\r
+\r
+ public abstract void replaceNode(MutableSimpleNode<?> replacementNode);\r
+\r
+ public abstract void addNode(MutableCompositeNode newNode);\r
+\r
+ public abstract void addNode(MutableSimpleNode<?> newNode);\r
+\r
+}\r
--- /dev/null
+<project xmlns="http://maven.apache.org/POM/4.0.0"\r
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\r
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">\r
+ <modelVersion>4.0.0</modelVersion>\r
+ <parent>\r
+ <groupId>org.opendaylight.controller</groupId>\r
+ <artifactId>yang</artifactId>\r
+ <version>0.5.3-SNAPSHOT</version>\r
+ </parent>\r
+ <artifactId>yang-data-impl</artifactId>\r
+\r
+ <properties>\r
+ <groovy.version>2.1.5</groovy.version>\r
+ </properties>\r
+\r
+ <build>\r
+ <plugins>\r
+ <plugin>\r
+ <groupId>org.apache.maven.plugins</groupId>\r
+ <artifactId>maven-surefire-plugin</artifactId>\r
+ <configuration>\r
+ <argLine>-Dlog4j.configuration=log4j-test.xml</argLine>\r
+ <redirectTestOutputToFile>true</redirectTestOutputToFile>\r
+ </configuration>\r
+ </plugin>\r
+ </plugins>\r
+ </build>\r
+\r
+\r
+ <dependencies>\r
+ <dependency>\r
+ <groupId>org.opendaylight.controller</groupId>\r
+ <artifactId>yang-common</artifactId>\r
+ </dependency>\r
+ <dependency>\r
+ <groupId>org.opendaylight.controller</groupId>\r
+ <artifactId>yang-data-api</artifactId>\r
+ </dependency>\r
+ <dependency>\r
+ <groupId>org.opendaylight.controller</groupId>\r
+ <artifactId>yang-model-parser-impl</artifactId>\r
+ </dependency>\r
+ <dependency>\r
+ <groupId>com.google.guava</groupId>\r
+ <artifactId>guava</artifactId>\r
+ <version>14.0.1</version>\r
+ </dependency>\r
+ <dependency>\r
+ <groupId>junit</groupId>\r
+ <artifactId>junit</artifactId>\r
+ <scope>test</scope>\r
+ </dependency>\r
+ <dependency>\r
+ <groupId>org.slf4j</groupId>\r
+ <artifactId>slf4j-log4j12</artifactId>\r
+ <version>${slf4j.version}</version>\r
+ <scope>test</scope>\r
+ </dependency>\r
+ <dependency>\r
+ <groupId>org.codehaus.groovy</groupId>\r
+ <artifactId>groovy</artifactId>\r
+ <version>${groovy.version}</version>\r
+ <scope>test</scope>\r
+ </dependency>\r
+ <dependency>\r
+ <groupId>org.codehaus.groovy</groupId>\r
+ <artifactId>groovy-xml</artifactId>\r
+ <version>${groovy.version}</version>\r
+ <scope>test</scope>\r
+ </dependency>\r
+ </dependencies>\r
+</project>
\ No newline at end of file
--- /dev/null
+/*\r
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.\r
+ *\r
+ * This program and the accompanying materials are made available under the\r
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
+ * and is available at http://www.eclipse.org/legal/epl-v10.html\r
+ */\r
+package org.opendaylight.controller.yang.data.impl;\r
+\r
+import org.opendaylight.controller.yang.common.QName;\r
+import org.opendaylight.controller.yang.data.api.CompositeNode;\r
+import org.opendaylight.controller.yang.data.api.Node;\r
+\r
+/**\r
+ * @author michal.rehak\r
+ * @param <T>\r
+ * type of node value\r
+ * \r
+ */\r
+public abstract class AbstractNodeTO<T> implements Node<T> {\r
+\r
+ private QName qName;\r
+ private CompositeNode parent;\r
+ private T value;\r
+\r
+ /**\r
+ * @param qname\r
+ * @param parent\r
+ * @param value\r
+ */\r
+ public AbstractNodeTO(QName qname, CompositeNode parent, T value) {\r
+ this.qName = qname;\r
+ this.parent = parent;\r
+ this.value = value;\r
+ }\r
+\r
+ @Override\r
+ public QName getNodeType() {\r
+ return qName;\r
+ }\r
+\r
+ /**\r
+ * @return the qName\r
+ */\r
+ protected QName getQName() {\r
+ return qName;\r
+ }\r
+\r
+ @Override\r
+ public CompositeNode getParent() {\r
+ return parent;\r
+ }\r
+ \r
+ /**\r
+ * @param parent the parent to set\r
+ */\r
+ public void setParent(CompositeNode parent) {\r
+ this.parent = parent;\r
+ }\r
+ \r
+ /**\r
+ * @param value the value to set\r
+ */\r
+ protected void setValue(T value) {\r
+ this.value = value;\r
+ }\r
+\r
+ @Override\r
+ public T getValue() {\r
+ return value;\r
+ }\r
+}\r
--- /dev/null
+/**\r
+ * \r
+ */\r
+package org.opendaylight.controller.yang.data.impl;\r
+\r
+import java.util.List;\r
+\r
+import org.opendaylight.controller.yang.common.QName;\r
+import org.opendaylight.controller.yang.data.api.CompositeNode;\r
+import org.opendaylight.controller.yang.data.api.ModifyAction;\r
+import org.opendaylight.controller.yang.data.api.Node;\r
+import org.opendaylight.controller.yang.data.api.NodeModification;\r
+\r
+/**\r
+ * @author michal.rehak\r
+ * \r
+ */\r
+public class CompositeNodeModificationTOImpl extends CompositeNodeTOImpl\r
+ implements NodeModification {\r
+\r
+ private ModifyAction modifyAction;\r
+\r
+ /**\r
+ * @param qname\r
+ * @param parent\r
+ * @param value\r
+ * @param modifyAction\r
+ */\r
+ public CompositeNodeModificationTOImpl(QName qname, CompositeNode parent,\r
+ List<Node<?>> value, ModifyAction modifyAction) {\r
+ super(qname, parent, value);\r
+ this.modifyAction = modifyAction;\r
+ }\r
+\r
+ /**\r
+ * @return modification action\r
+ * @see org.opendaylight.controller.yang.data.impl.NodeModificationSupport#getModificationAction()\r
+ */\r
+ @Override\r
+ public ModifyAction getModificationAction() {\r
+ return modifyAction;\r
+ }\r
+\r
+ /**\r
+ * @param modifyAction\r
+ * the modifyAction to set\r
+ */\r
+ protected void setModificationAction(ModifyAction modifyAction) {\r
+ this.modifyAction = modifyAction;\r
+ }\r
+\r
+}\r
--- /dev/null
+/*\r
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.\r
+ *\r
+ * This program and the accompanying materials are made available under the\r
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
+ * and is available at http://www.eclipse.org/legal/epl-v10.html\r
+ */\r
+package org.opendaylight.controller.yang.data.impl;\r
+\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+import java.util.Map;\r
+\r
+import org.opendaylight.controller.yang.common.QName;\r
+import org.opendaylight.controller.yang.data.api.CompositeNode;\r
+import org.opendaylight.controller.yang.data.api.Node;\r
+import org.opendaylight.controller.yang.data.api.SimpleNode;\r
+\r
+/**\r
+ * @author michal.rehak\r
+ * \r
+ */\r
+public class CompositeNodeTOImpl extends AbstractNodeTO<List<Node<?>>>\r
+ implements CompositeNode {\r
+\r
+ private Map<QName, List<Node<?>>> nodeMap;\r
+\r
+ /**\r
+ * @param qname\r
+ * @param parent use null to create top composite node (without parent)\r
+ * @param value\r
+ */\r
+ public CompositeNodeTOImpl(QName qname, CompositeNode parent,\r
+ List<Node<?>> value) {\r
+ super(qname, parent, value);\r
+ if (value != null) {\r
+ nodeMap = NodeUtils.buildNodeMap(getValue());\r
+ }\r
+ }\r
+ \r
+\r
+ /**\r
+ * @return the nodeMap\r
+ */\r
+ protected Map<QName, List<Node<?>>> getNodeMap() {\r
+ return nodeMap;\r
+ }\r
+ \r
+ @Override\r
+ public List<Node<?>> getChildren() {\r
+ return getValue();\r
+ }\r
+\r
+ @Override\r
+ public SimpleNode<?> getFirstSimpleByName(QName leafQName) {\r
+ List<SimpleNode<?>> list = getSimpleNodesByName(leafQName);\r
+ if (list.isEmpty())\r
+ return null;\r
+ return list.get(0);\r
+ }\r
+\r
+ @Override\r
+ public List<CompositeNode> getCompositesByName(QName children) {\r
+ List<Node<?>> toFilter = getNodeMap().get(children);\r
+ List<CompositeNode> list = new ArrayList<CompositeNode>();\r
+ for (Node<?> node : toFilter) {\r
+ if (node instanceof CompositeNode)\r
+ list.add((CompositeNode) node);\r
+ }\r
+ return list;\r
+ }\r
+\r
+ @Override\r
+ public List<SimpleNode<?>> getSimpleNodesByName(QName children) {\r
+ List<Node<?>> toFilter = getNodeMap().get(children);\r
+ List<SimpleNode<?>> list = new ArrayList<SimpleNode<?>>();\r
+\r
+ for (Node<?> node : toFilter) {\r
+ if (node instanceof SimpleNode<?>)\r
+ list.add((SimpleNode<?>) node);\r
+ }\r
+ return list;\r
+ }\r
+\r
+ @Override\r
+ public CompositeNode getFirstCompositeByName(QName container) {\r
+ List<CompositeNode> list = getCompositesByName(container);\r
+ if (list.isEmpty()) {\r
+ return null;\r
+ }\r
+ return list.get(0);\r
+ }\r
+\r
+ /**\r
+ * @param leaf\r
+ * @return TODO:: do we need this method?\r
+ */\r
+ public SimpleNode<?> getFirstLeafByName(QName leaf) {\r
+ List<SimpleNode<?>> list = getSimpleNodesByName(leaf);\r
+ if (list.isEmpty()) {\r
+ return null;\r
+ }\r
+ return list.get(0);\r
+ }\r
+\r
+ @Override\r
+ public List<CompositeNode> getCompositesByName(String children) {\r
+ return getCompositesByName(localQName(children));\r
+ }\r
+ \r
+ @Override\r
+ public List<SimpleNode<?>> getSimpleNodesByName(String children) {\r
+ return getSimpleNodesByName(localQName(children));\r
+ }\r
+\r
+ private QName localQName(String str) {\r
+ return new QName(getNodeType(), str);\r
+ }\r
+\r
+}\r
--- /dev/null
+/*\r
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.\r
+ *\r
+ * This program and the accompanying materials are made available under the\r
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
+ * and is available at http://www.eclipse.org/legal/epl-v10.html\r
+ */\r
+package org.opendaylight.controller.yang.data.impl;\r
+\r
+import java.util.List;\r
+import java.util.Map;\r
+\r
+import org.opendaylight.controller.yang.common.QName;\r
+import org.opendaylight.controller.yang.data.api.CompositeNode;\r
+import org.opendaylight.controller.yang.data.api.ModifyAction;\r
+import org.opendaylight.controller.yang.data.api.MutableCompositeNode;\r
+import org.opendaylight.controller.yang.data.api.Node;\r
+\r
+/**\r
+ * @author michal.rehak\r
+ * \r
+ */\r
+public class MutableCompositeNodeTOImpl extends CompositeNodeModificationTOImpl\r
+ implements MutableCompositeNode {\r
+\r
+ private Map<QName, List<Node<?>>> nodeMap;\r
+\r
+ /**\r
+ * @param qname\r
+ * @param parent\r
+ * @param value\r
+ * @param modifyAction\r
+ */\r
+ public MutableCompositeNodeTOImpl(QName qname, CompositeNode parent,\r
+ List<Node<?>> value, ModifyAction modifyAction) {\r
+ super(qname, parent, value, modifyAction);\r
+ }\r
+ \r
+ /**\r
+ * update nodeMap\r
+ */\r
+ @Override\r
+ public void init() {\r
+ nodeMap = NodeUtils.buildNodeMap(getChildren());\r
+ }\r
+\r
+ @Override\r
+ public void setValue(List<Node<?>> value) {\r
+ super.setValue(value);\r
+ }\r
+ \r
+ @Override\r
+ public void setModifyAction(ModifyAction action) {\r
+ super.setModificationAction(action);\r
+ }\r
+ \r
+ @Override\r
+ protected Map<QName, List<Node<?>>> getNodeMap() {\r
+ return nodeMap;\r
+ }\r
+}\r
--- /dev/null
+/*\r
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.\r
+ *\r
+ * This program and the accompanying materials are made available under the\r
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
+ * and is available at http://www.eclipse.org/legal/epl-v10.html\r
+ */\r
+package org.opendaylight.controller.yang.data.impl;\r
+\r
+import org.opendaylight.controller.yang.common.QName;\r
+import org.opendaylight.controller.yang.data.api.CompositeNode;\r
+import org.opendaylight.controller.yang.data.api.ModifyAction;\r
+import org.opendaylight.controller.yang.data.api.MutableSimpleNode;\r
+\r
+/**\r
+ * @author michal.rehak\r
+ * @param <T> type of simple node value\r
+ * \r
+ */\r
+public class MutableSimpleNodeTOImpl<T> extends SimpleNodeModificationTOImpl<T> \r
+ implements MutableSimpleNode<T> {\r
+\r
+ /**\r
+ * @param qname\r
+ * @param parent\r
+ * @param value\r
+ * @param modifyAction\r
+ */\r
+ public MutableSimpleNodeTOImpl(QName qname, CompositeNode parent, T value,\r
+ ModifyAction modifyAction) {\r
+ super(qname, parent, value, modifyAction);\r
+ }\r
+\r
+ @Override\r
+ public void setValue(T value) {\r
+ super.setValue(value);\r
+ }\r
+ \r
+ @Override\r
+ public void setModifyAction(ModifyAction action) {\r
+ super.setModificationAction(action);\r
+ }\r
+}\r
--- /dev/null
+/*\r
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.\r
+ *\r
+ * This program and the accompanying materials are made available under the\r
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
+ * and is available at http://www.eclipse.org/legal/epl-v10.html\r
+ */\r
+package org.opendaylight.controller.yang.data.impl;\r
+\r
+import java.util.AbstractMap.SimpleEntry;\r
+import java.util.ArrayList;\r
+import java.util.Arrays;\r
+import java.util.List;\r
+import java.util.Map;\r
+import java.util.Stack;\r
+\r
+import org.opendaylight.controller.yang.common.QName;\r
+import org.opendaylight.controller.yang.data.api.CompositeNode;\r
+import org.opendaylight.controller.yang.data.api.ModifyAction;\r
+import org.opendaylight.controller.yang.data.api.MutableCompositeNode;\r
+import org.opendaylight.controller.yang.data.api.MutableSimpleNode;\r
+import org.opendaylight.controller.yang.data.api.Node;\r
+import org.opendaylight.controller.yang.data.api.SimpleNode;\r
+\r
+/**\r
+ * @author michal.rehak\r
+ * \r
+ */\r
+public abstract class NodeFactory {\r
+\r
+ /**\r
+ * @param qName\r
+ * @param parent\r
+ * @param value\r
+ * @return simple node modification, based on given qname, value and parent\r
+ */\r
+ public static <T> SimpleNode<T> createSimpleNode(QName qName,\r
+ CompositeNode parent, T value) {\r
+ SimpleNodeTOImpl<T> simpleNodeTOImpl = new SimpleNodeTOImpl<T>(qName, parent, value);\r
+ return simpleNodeTOImpl;\r
+ }\r
+ \r
+ /**\r
+ * @param qName\r
+ * @param parent\r
+ * @param value\r
+ * @return simple node modification, based on given qname, value and parent\r
+ */\r
+ public static <T> MutableSimpleNode<T> createMutableSimpleNode(QName qName,\r
+ CompositeNode parent, T value) {\r
+ MutableSimpleNodeTOImpl<T> simpleNodeTOImpl = \r
+ new MutableSimpleNodeTOImpl<T>(qName, parent, value, null);\r
+ return simpleNodeTOImpl;\r
+ }\r
+\r
+ /**\r
+ * @param qName\r
+ * @param parent\r
+ * @param value\r
+ * @return composite node modification, based on given qname, value (children), parent and modifyAction\r
+ */\r
+ public static CompositeNode createCompositeNode(QName qName,\r
+ CompositeNode parent, List<Node<?>> value) {\r
+ CompositeNode compositeNodeTOImpl = new CompositeNodeTOImpl(qName, parent, value);\r
+ return compositeNodeTOImpl;\r
+ }\r
+ \r
+ /**\r
+ * @param qName\r
+ * @param parent\r
+ * @param value\r
+ * @return composite node modification, based on given qname, value (children), parent and modifyAction\r
+ */\r
+ public static MutableCompositeNode createMutableCompositeNode(QName qName,\r
+ CompositeNode parent, List<Node<?>> value) {\r
+ MutableCompositeNodeTOImpl compositeNodeTOImpl = \r
+ new MutableCompositeNodeTOImpl(qName, parent, value, null);\r
+ return compositeNodeTOImpl;\r
+ }\r
+ \r
+ \r
+ /**\r
+ * @param qName\r
+ * @param parent\r
+ * @param value\r
+ * @param modifyAction\r
+ * @return simple node modification, based on given qname, value, parent and modifyAction\r
+ */\r
+ public static <T> SimpleNodeModificationTOImpl<T> createSimpleNodeModification(QName qName,\r
+ CompositeNode parent, T value, ModifyAction modifyAction) {\r
+ SimpleNodeModificationTOImpl<T> simpleNodeModTOImpl = \r
+ new SimpleNodeModificationTOImpl<T>(qName, parent, value, modifyAction);\r
+ return simpleNodeModTOImpl;\r
+ }\r
+\r
+ /**\r
+ * @param qName\r
+ * @param parent\r
+ * @param value\r
+ * @param modifyAction \r
+ * @return composite node modification, based on given qname, value (children), parent and modifyAction\r
+ */\r
+ public static CompositeNodeModificationTOImpl createCompositeNodeModification(QName qName,\r
+ CompositeNode parent, List<Node<?>> value, ModifyAction modifyAction) {\r
+ CompositeNodeModificationTOImpl compositeNodeModTOImpl = \r
+ new CompositeNodeModificationTOImpl(qName, parent, value, modifyAction);\r
+ return compositeNodeModTOImpl;\r
+ }\r
+\r
+ /**\r
+ * @param node\r
+ * @return copy of given node, parent and value are the same, but parent \r
+ * has no reference to this copy \r
+ */\r
+ public static <T> SimpleNode<T> copyNode(SimpleNode<T> node) {\r
+ SimpleNode<T> twinNode = createSimpleNode(\r
+ node.getNodeType(), node.getParent(), node.getValue());\r
+ return twinNode;\r
+ }\r
+ \r
+ /**\r
+ * @param node\r
+ * @return copy of given node, parent and value are the same, but parent \r
+ * has no reference to this copy \r
+ */\r
+ public static <T> SimpleNode<T> copyNodeAsMutable(SimpleNode<T> node) {\r
+ SimpleNode<T> twinNode = createMutableSimpleNode(\r
+ node.getNodeType(), node.getParent(), node.getValue());\r
+ return twinNode;\r
+ }\r
+\r
+ /**\r
+ * @param node\r
+ * @param children \r
+ * @return copy of given node, parent and children are the same, but parent and children \r
+ * have no reference to this copy\r
+ */\r
+ public static CompositeNode copyNode(CompositeNode node, Node<?>... children) {\r
+ CompositeNode twinNode = createCompositeNode(\r
+ node.getNodeType(), node.getParent(), Arrays.asList(children));\r
+ return twinNode;\r
+ }\r
+ \r
+ /**\r
+ * @param node\r
+ * @return copy of given node, parent and children are the same, but parent and children \r
+ * have no reference to this copy\r
+ */\r
+ public static CompositeNode copyNode(CompositeNode node) {\r
+ return copyNode(node, node.getChildren().toArray(new Node<?>[0]));\r
+ }\r
+ \r
+ /**\r
+ * @param node root of original tree\r
+ * @param originalToMutable (optional) empty map, where binding between original and copy \r
+ * will be stored\r
+ * @return copy of given node, parent and children are the same, but parent and children \r
+ * have no reference to this copy\r
+ */\r
+ public static MutableCompositeNode copyDeepNode(CompositeNode node, \r
+ Map<Node<?>, Node<?>> originalToMutable) {\r
+ \r
+ MutableCompositeNode mutableRoot = \r
+ createMutableCompositeNode(node.getNodeType(), null, null);\r
+ Stack<SimpleEntry<CompositeNode, MutableCompositeNode>> jobQueue = new Stack<>();\r
+ jobQueue.push(new SimpleEntry<CompositeNode, MutableCompositeNode>(node, mutableRoot));\r
+ if (originalToMutable != null) {\r
+ originalToMutable.put(node, mutableRoot);\r
+ }\r
+ \r
+ while (!jobQueue.isEmpty()) {\r
+ SimpleEntry<CompositeNode, MutableCompositeNode> job = jobQueue.pop();\r
+ CompositeNode originalNode = job.getKey();\r
+ MutableCompositeNode mutableNode = job.getValue();\r
+ mutableNode.setValue(new ArrayList<Node<?>>());\r
+ \r
+ for (Node<?> child : originalNode.getChildren()) {\r
+ Node<?> mutableAscendant = null;\r
+ if (child instanceof CompositeNode) {\r
+ MutableCompositeNode newMutable = \r
+ createMutableCompositeNode(child.getNodeType(), mutableNode, null);\r
+ jobQueue.push(new SimpleEntry<CompositeNode, MutableCompositeNode>(\r
+ (CompositeNode) child, newMutable));\r
+ mutableAscendant = newMutable;\r
+ } else if (child instanceof SimpleNode<?>) {\r
+ mutableAscendant = \r
+ createMutableSimpleNode(child.getNodeType(), mutableNode, child.getValue());\r
+ } else {\r
+ throw new IllegalStateException("Node class deep copy not supported: "\r
+ +child.getClass().getName());\r
+ }\r
+ \r
+ mutableNode.getChildren().add(mutableAscendant);\r
+ if (originalToMutable != null) {\r
+ originalToMutable.put(child, mutableAscendant);\r
+ }\r
+ }\r
+ mutableNode.init();\r
+ }\r
+ \r
+ return mutableRoot;\r
+ }\r
+ \r
+}\r
--- /dev/null
+/**\r
+ * \r
+ */\r
+package org.opendaylight.controller.yang.data.impl;\r
+\r
+import java.util.HashMap;\r
+import java.util.HashSet;\r
+import java.util.List;\r
+import java.util.Map;\r
+import java.util.Set;\r
+import java.util.Stack;\r
+\r
+import org.opendaylight.controller.yang.common.QName;\r
+import org.opendaylight.controller.yang.data.api.CompositeNode;\r
+import org.opendaylight.controller.yang.data.api.ModifyAction;\r
+import org.opendaylight.controller.yang.data.api.MutableCompositeNode;\r
+import org.opendaylight.controller.yang.data.api.MutableNode;\r
+import org.opendaylight.controller.yang.data.api.MutableSimpleNode;\r
+import org.opendaylight.controller.yang.data.api.Node;\r
+import org.opendaylight.controller.yang.data.api.NodeModificationBuilder;\r
+import org.opendaylight.controller.yang.model.api.ListSchemaNode;\r
+import org.opendaylight.controller.yang.model.api.SchemaContext;\r
+\r
+/**\r
+ * @author michal.rehak\r
+ *\r
+ */\r
+public class NodeModificationBuilderImpl implements NodeModificationBuilder {\r
+ \r
+ private SchemaContext context;\r
+ \r
+ private Set<MutableNode<?>> changeLog;\r
+ private Map<Node<?>, Node<?>> originalToMutable;\r
+\r
+ private MutableCompositeNode mutableRoot;\r
+\r
+ /**\r
+ * @param originalTreeRootNode \r
+ * @param context\r
+ */\r
+ public NodeModificationBuilderImpl(CompositeNode originalTreeRootNode, SchemaContext context) {\r
+ this.context = context;\r
+ originalToMutable = new HashMap<>();\r
+ mutableRoot = NodeFactory.copyDeepNode(originalTreeRootNode, originalToMutable);\r
+ changeLog = new HashSet<>();\r
+ }\r
+\r
+ /**\r
+ * add given node to it's parent's list of children\r
+ * @param newNode\r
+ */\r
+ private static void fixParentRelation(Node<?> newNode) {\r
+ if (newNode.getParent() != null) {\r
+ List<Node<?>> siblings = newNode.getParent().getChildren();\r
+ if (!siblings.contains(newNode)) {\r
+ siblings.add(newNode);\r
+ }\r
+ }\r
+ }\r
+\r
+ /**\r
+ * @param modNode\r
+ * @param action \r
+ */\r
+ private void addModificationToLog(MutableNode<?> modNode, ModifyAction action) {\r
+ modNode.setModifyAction(action);\r
+ changeLog.add(modNode);\r
+ }\r
+\r
+ @Override\r
+ public void addNode(MutableSimpleNode<?> newNode) {\r
+ fixParentRelation(newNode);\r
+ addModificationToLog(newNode, ModifyAction.CREATE);\r
+ }\r
+ \r
+ @Override\r
+ public void addNode(MutableCompositeNode newNode) {\r
+ fixParentRelation(newNode);\r
+ addModificationToLog(newNode, ModifyAction.CREATE);\r
+ }\r
+ \r
+ @Override\r
+ public void replaceNode(MutableSimpleNode<?> replacementNode) {\r
+ addModificationToLog(replacementNode, ModifyAction.REPLACE);\r
+ }\r
+ \r
+ @Override\r
+ public void replaceNode(MutableCompositeNode replacementNode) {\r
+ addModificationToLog(replacementNode, ModifyAction.REPLACE);\r
+ }\r
+\r
+ @Override\r
+ public void deleteNode(MutableCompositeNode deadNode) {\r
+ addModificationToLog(deadNode, ModifyAction.DELETE);\r
+ }\r
+ \r
+ @Override\r
+ public void deleteNode(MutableSimpleNode<?> deadNode) {\r
+ addModificationToLog(deadNode, ModifyAction.DELETE);\r
+ }\r
+\r
+ @Override\r
+ public void removeNode(MutableSimpleNode<?> deadNode) {\r
+ addModificationToLog(deadNode, ModifyAction.REMOVE);\r
+ }\r
+ \r
+ @Override\r
+ public void removeNode(MutableCompositeNode deadNode) {\r
+ addModificationToLog(deadNode, ModifyAction.REMOVE);\r
+ }\r
+ \r
+ @Override\r
+ public void mergeNode(MutableCompositeNode alteredNode) {\r
+ addModificationToLog(alteredNode, ModifyAction.MERGE);\r
+ }\r
+\r
+ /**\r
+ * @return minimalistic tree containing diffs only\r
+ */\r
+ @Override\r
+ public CompositeNode buildDiffTree() {\r
+ Set<Node<?>> wanted = new HashSet<>();\r
+ \r
+ // walk changeLog, collect all required nodes\r
+ for (MutableNode<?> mutant : changeLog) {\r
+ wanted.addAll(collectSelfAndAllParents(mutant));\r
+ }\r
+ \r
+ // TODO:: walk wanted and add relevant keys\r
+ Map<String, ListSchemaNode> mapOfLists = NodeUtils.buildMapOfListNodes(context);\r
+ Set<Node<?>> wantedKeys = new HashSet<>();\r
+ for (Node<?> outlaw : wanted) {\r
+ if (outlaw instanceof CompositeNode) {\r
+ String path = NodeUtils.buildPath(outlaw);\r
+ if (mapOfLists.containsKey(path)) {\r
+ ListSchemaNode listSchema = mapOfLists.get(path);\r
+ if (listSchema.getQName().equals(outlaw.getNodeType())) {\r
+ // try to add key subnode to wanted list\r
+ List<QName> supportedKeys = listSchema.getKeyDefinition();\r
+ for (Node<?> outlawChildren : ((CompositeNode) outlaw).getChildren()) {\r
+ if (supportedKeys.contains(outlawChildren.getNodeType())) {\r
+ wantedKeys.add(outlawChildren);\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+ wanted.addAll(wantedKeys);\r
+ \r
+ // remove all unwanted nodes from tree\r
+ removeUnrelevantNodes(mutableRoot, wanted);\r
+ \r
+ return mutableRoot;\r
+ }\r
+\r
+ /**\r
+ * @param mutableRoot2\r
+ * @param wanted\r
+ */\r
+ private static void removeUnrelevantNodes(MutableCompositeNode mutRoot,\r
+ Set<Node<?>> wanted) {\r
+ Stack<MutableNode<?>> jobQueue = new Stack<>();\r
+ jobQueue.push(mutRoot);\r
+ while (!jobQueue.isEmpty()) {\r
+ MutableNode<?> mutNode = jobQueue.pop();\r
+ if (!wanted.contains(mutNode)) {\r
+ if (mutNode.getParent() != null) {\r
+ mutNode.getParent().getChildren().remove(mutNode);\r
+ }\r
+ } else {\r
+ if (mutNode instanceof MutableCompositeNode) {\r
+ for (Node<?> mutChild : ((MutableCompositeNode) mutNode).getChildren()) {\r
+ jobQueue.push((MutableNode<?>) mutChild);\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ /**\r
+ * @param focusedAncestor\r
+ * @return set of parents and focusedAncestor itself\r
+ */\r
+ private static Set<Node<?>> collectSelfAndAllParents(Node<?> focusedAncestor) {\r
+ Set<Node<?>> family = new HashSet<>();\r
+ Node<?> tmpNode = focusedAncestor;\r
+ while (tmpNode != null) {\r
+ family.add(tmpNode);\r
+ tmpNode = tmpNode.getParent();\r
+ }\r
+ return family;\r
+ }\r
+\r
+ /**\r
+ * @param originalNode\r
+ * @return mutable version of given node\r
+ */\r
+ @Override\r
+ public Node<?> getMutableEquivalent(Node<?> originalNode) {\r
+ return originalToMutable.get(originalNode);\r
+ }\r
+\r
+}\r
--- /dev/null
+/*\r
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.\r
+ *\r
+ * This program and the accompanying materials are made available under the\r
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
+ * and is available at http://www.eclipse.org/legal/epl-v10.html\r
+ */\r
+package org.opendaylight.controller.yang.data.impl;\r
+\r
+import java.util.AbstractMap.SimpleEntry;\r
+import java.util.ArrayList;\r
+import java.util.HashMap;\r
+import java.util.List;\r
+import java.util.Map;\r
+import java.util.Stack;\r
+import java.util.Vector;\r
+\r
+import javax.xml.parsers.DocumentBuilder;\r
+import javax.xml.parsers.DocumentBuilderFactory;\r
+import javax.xml.parsers.ParserConfigurationException;\r
+import javax.xml.xpath.XPath;\r
+import javax.xml.xpath.XPathConstants;\r
+import javax.xml.xpath.XPathExpression;\r
+import javax.xml.xpath.XPathExpressionException;\r
+import javax.xml.xpath.XPathFactory;\r
+\r
+import org.opendaylight.controller.yang.common.QName;\r
+import org.opendaylight.controller.yang.data.api.CompositeNode;\r
+import org.opendaylight.controller.yang.data.api.ModifyAction;\r
+import org.opendaylight.controller.yang.data.api.Node;\r
+import org.opendaylight.controller.yang.data.api.NodeModification;\r
+import org.opendaylight.controller.yang.data.api.SimpleNode;\r
+import org.opendaylight.controller.yang.model.api.DataNodeContainer;\r
+import org.opendaylight.controller.yang.model.api.DataSchemaNode;\r
+import org.opendaylight.controller.yang.model.api.ListSchemaNode;\r
+import org.opendaylight.controller.yang.model.api.SchemaContext;\r
+import org.slf4j.Logger;\r
+import org.slf4j.LoggerFactory;\r
+import org.w3c.dom.Document;\r
+import org.w3c.dom.Element;\r
+\r
+import com.google.common.base.Joiner;\r
+\r
+\r
+/**\r
+ * @author michal.rehak\r
+ *\r
+ */\r
+public abstract class NodeUtils {\r
+ \r
+ /**\r
+ * \r
+ */\r
+ private static final String USER_KEY_NODE = "node";\r
+ private static final Logger LOG = LoggerFactory.getLogger(NodeUtils.class);\r
+ \r
+ /**\r
+ * @param node\r
+ * @return node path up till root node\r
+ */\r
+ public static String buildPath(Node<?> node) {\r
+ Vector<String> breadCrumbs = new Vector<>();\r
+ Node<?> tmpNode = node;\r
+ while (tmpNode != null) {\r
+ breadCrumbs.insertElementAt(tmpNode.getNodeType().getLocalName(), 0);\r
+ tmpNode = tmpNode.getParent();\r
+ }\r
+ \r
+ return Joiner.on(".").join(breadCrumbs);\r
+ }\r
+\r
+ \r
+ /**\r
+ * @param treeRootNode\r
+ * @return dom tree, containing same node structure, yang nodes are associated \r
+ * to dom nodes as user data\r
+ */\r
+ public static Document buildShadowDomTree(CompositeNode treeRootNode) {\r
+ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();\r
+ Document doc = null;\r
+ try {\r
+ DocumentBuilder bob = dbf.newDocumentBuilder();\r
+ doc = bob.newDocument();\r
+ } catch (ParserConfigurationException e) {\r
+ LOG.error("documentBuilder problem", e);\r
+ return null;\r
+ }\r
+ \r
+ Stack<SimpleEntry<org.w3c.dom.Node, Node<?>>> jobQueue = new Stack<>();\r
+ jobQueue.push(new SimpleEntry<org.w3c.dom.Node, Node<?>>(doc, treeRootNode));\r
+ \r
+ while (!jobQueue.isEmpty()) {\r
+ SimpleEntry<org.w3c.dom.Node, Node<?>> job = jobQueue.pop();\r
+ org.w3c.dom.Node jointPlace = job.getKey();\r
+ Node<?> item = job.getValue();\r
+ Element itemEl = doc.createElement(item.getNodeType().getLocalName());\r
+ itemEl.setUserData(USER_KEY_NODE, item, null);\r
+ if (item instanceof SimpleNode<?>) {\r
+ Object value = ((SimpleNode<?>) item).getValue();\r
+ itemEl.setTextContent(String.valueOf(value));\r
+ itemEl.setAttribute("type", value.getClass().getSimpleName());\r
+ }\r
+ if (item instanceof NodeModification) {\r
+ ModifyAction modificationAction = ((NodeModification) item).getModificationAction();\r
+ if (modificationAction != null) {\r
+ itemEl.setAttribute("modifyAction", modificationAction.toString());\r
+ }\r
+ }\r
+ \r
+ jointPlace.appendChild(itemEl);\r
+ \r
+ if (item instanceof CompositeNode) {\r
+ for (Node<?> child : ((CompositeNode) item).getChildren()) {\r
+ jobQueue.push(new SimpleEntry<org.w3c.dom.Node, Node<?>>(itemEl, child));\r
+ }\r
+ }\r
+ }\r
+ \r
+ return doc;\r
+ }\r
+ \r
+ /**\r
+ * @param doc\r
+ * @param xpathEx\r
+ * @return user data value on found node\r
+ * @throws XPathExpressionException\r
+ */\r
+ @SuppressWarnings("unchecked")\r
+ public static <T> T findNodeByXpath(Document doc, String xpathEx) \r
+ throws XPathExpressionException {\r
+ T userNode = null;\r
+ XPathFactory xPathfactory = XPathFactory.newInstance();\r
+ XPath xpath = xPathfactory.newXPath();\r
+ XPathExpression expr = xpath.compile(xpathEx);\r
+ \r
+ org.w3c.dom.Node result = (org.w3c.dom.Node) expr.evaluate(doc, XPathConstants.NODE);\r
+ if (result != null) {\r
+ userNode = (T) result.getUserData(USER_KEY_NODE);\r
+ } \r
+ \r
+ return userNode;\r
+ }\r
+\r
+\r
+ /**\r
+ * build NodeMap, where key = qName; value = node\r
+ * \r
+ * @param value\r
+ * @return map of children, where key = qName and value is list of children groupped by qName \r
+ */\r
+ public static Map<QName, List<Node<?>>> buildNodeMap(List<Node<?>> value) {\r
+ Map<QName, List<Node<?>>> nodeMapTmp = new HashMap<>();\r
+ if (value == null || value.isEmpty()) {\r
+ throw new IllegalStateException(\r
+ "nodeList should not be null or empty");\r
+ }\r
+ for (Node<?> node : value) {\r
+ List<Node<?>> qList = nodeMapTmp.get(node.getNodeType());\r
+ if (qList == null) {\r
+ qList = new ArrayList<>();\r
+ nodeMapTmp.put(node.getNodeType(), qList);\r
+ }\r
+ qList.add(node);\r
+ }\r
+ return nodeMapTmp;\r
+ }\r
+\r
+\r
+ /**\r
+ * @param context\r
+ * @return map of lists, where key = path; value = {@link DataSchemaNode}\r
+ */\r
+ public static Map<String, ListSchemaNode> buildMapOfListNodes(\r
+ SchemaContext context) {\r
+ Map<String, ListSchemaNode> mapOfLists = new HashMap<>();\r
+ \r
+ Stack<DataSchemaNode> jobQueue = new Stack<>();\r
+ jobQueue.addAll(context.getDataDefinitions());\r
+ \r
+ while (!jobQueue.isEmpty()) {\r
+ DataSchemaNode dataSchema = jobQueue.pop();\r
+ if (dataSchema instanceof ListSchemaNode) {\r
+ mapOfLists.put(schemaPathToPath(dataSchema.getPath().getPath()), (ListSchemaNode) dataSchema);\r
+ }\r
+ \r
+ if (dataSchema instanceof DataNodeContainer) {\r
+ jobQueue.addAll(((DataNodeContainer) dataSchema).getChildNodes());\r
+ }\r
+ }\r
+ \r
+ return mapOfLists;\r
+ }\r
+\r
+\r
+ /**\r
+ * @param path\r
+ * @return\r
+ */\r
+ private static String schemaPathToPath(List<QName> qNamesPath) {\r
+ List<String> pathSeed = new ArrayList<>();\r
+ for (QName qNameItem : qNamesPath) {\r
+ pathSeed.add(qNameItem.getLocalName());\r
+ }\r
+ return Joiner.on(".").join(pathSeed);\r
+ }\r
+}\r
--- /dev/null
+/**\r
+ * \r
+ */\r
+package org.opendaylight.controller.yang.data.impl;\r
+\r
+import org.opendaylight.controller.yang.common.QName;\r
+import org.opendaylight.controller.yang.data.api.CompositeNode;\r
+import org.opendaylight.controller.yang.data.api.ModifyAction;\r
+import org.opendaylight.controller.yang.data.api.NodeModification;\r
+\r
+/**\r
+ * @author michal.rehak\r
+ * @param <T> type of node value\r
+ * \r
+ */\r
+public class SimpleNodeModificationTOImpl<T> extends SimpleNodeTOImpl<T>\r
+ implements NodeModification {\r
+\r
+ private ModifyAction modifyAction;\r
+\r
+ /**\r
+ * @param qname\r
+ * @param parent\r
+ * @param value\r
+ * @param modifyAction \r
+ */\r
+ public SimpleNodeModificationTOImpl(QName qname, CompositeNode parent,\r
+ T value, ModifyAction modifyAction) {\r
+ super(qname, parent, value);\r
+ this.modifyAction = modifyAction;\r
+ }\r
+\r
+ /**\r
+ * @return modification action\r
+ * @see org.opendaylight.controller.yang.data.impl.NodeModificationSupport#getModificationAction()\r
+ */\r
+ @Override\r
+ public ModifyAction getModificationAction() {\r
+ return modifyAction;\r
+ }\r
+\r
+ /**\r
+ * @param modifyAction\r
+ * the modifyAction to set\r
+ */\r
+ protected void setModificationAction(ModifyAction modifyAction) {\r
+ this.modifyAction = modifyAction;\r
+ }\r
+}\r
--- /dev/null
+/*\r
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.\r
+ *\r
+ * This program and the accompanying materials are made available under the\r
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
+ * and is available at http://www.eclipse.org/legal/epl-v10.html\r
+ */\r
+package org.opendaylight.controller.yang.data.impl;\r
+\r
+import org.opendaylight.controller.yang.common.QName;\r
+import org.opendaylight.controller.yang.data.api.CompositeNode;\r
+import org.opendaylight.controller.yang.data.api.SimpleNode;\r
+\r
+/**\r
+ * @author michal.rehak\r
+ * @param <T> type of simple node value\r
+ * \r
+ */\r
+public class SimpleNodeTOImpl<T> extends AbstractNodeTO<T> implements\r
+ SimpleNode<T> {\r
+\r
+ /**\r
+ * @param qname\r
+ * @param parent\r
+ * @param value\r
+ */\r
+ public SimpleNodeTOImpl(QName qname, CompositeNode parent, T value) {\r
+ super(qname, parent, value);\r
+ }\r
+\r
+}\r
--- /dev/null
+/*\r
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.\r
+ *\r
+ * This program and the accompanying materials are made available under the\r
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
+ * and is available at http://www.eclipse.org/legal/epl-v10.html\r
+ */\r
+package org.opendaylight.controller.yang.data.impl;\r
+\r
+import java.io.ByteArrayOutputStream;\r
+import java.io.PrintStream;\r
+import java.net.URI;\r
+import java.util.ArrayList;\r
+import java.util.Date;\r
+import java.util.HashMap;\r
+import java.util.List;\r
+import java.util.Map;\r
+\r
+import org.junit.Assert;\r
+import org.junit.Test;\r
+import org.opendaylight.controller.yang.common.QName;\r
+import org.opendaylight.controller.yang.data.api.CompositeNode;\r
+import org.opendaylight.controller.yang.data.api.ModifyAction;\r
+import org.opendaylight.controller.yang.data.api.MutableCompositeNode;\r
+import org.opendaylight.controller.yang.data.api.Node;\r
+import org.opendaylight.controller.yang.data.api.NodeModification;\r
+import org.w3c.dom.Document;\r
+\r
+/**\r
+ * @author michal.rehak\r
+ * \r
+ */\r
+public class NodeFactoryTest {\r
+\r
+ /**\r
+ * Test method for methods creating immutable nodes in\r
+ * {@link org.opendaylight.controller.yang.data.impl.NodeFactory}.\r
+ * @throws Exception \r
+ */\r
+ @Test\r
+ public void testImmutableNodes() throws Exception {\r
+ QName qName = new QName(\r
+ new URI("urn:opendaylight:controller:network"), \r
+ new Date(42), "yang-data-impl-immutableTest_", null);\r
+ \r
+ CompositeNode network = NodeHelper.buildTestConfigTree(qName);\r
+ \r
+ \r
+ Assert.assertEquals(1, network.getChildren().size());\r
+ Document domTree = NodeUtils.buildShadowDomTree(network);\r
+ NodeHelper.dumpDoc(domTree, System.out);\r
+ \r
+ CompositeNode tpList = NodeUtils.findNodeByXpath(domTree, \r
+ "//node[node-id/text()='nodeId_19']/termination-points");\r
+ \r
+ \r
+ Assert.assertEquals(2, tpList.getCompositesByName("termination-point").size());\r
+// Assert.assertEquals(1, topologies.getCompositesByName("topology").size());\r
+// Assert.assertEquals(2, destination.getChildren().size());\r
+ }\r
+\r
+ /**\r
+ * Test method for methods creating immutable nodes in\r
+ * {@link org.opendaylight.controller.yang.data.impl.NodeFactory}.\r
+ * @throws Exception \r
+ */\r
+ @Test\r
+ public void testMutableNodes() throws Exception {\r
+ // <config>\r
+ // <top xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">\r
+ // <interface xc:operation="delete">\r
+ // <name>Ethernet0/0</name>\r
+ // <mtu>1500</mtu>\r
+ // </interface>\r
+ // <interface>\r
+ // <name>Ethernet0/1</name>\r
+ // <mtu>1501</mtu>\r
+ // </interface>\r
+ // </top>\r
+ // </config>\r
+ \r
+ QName qName = new QName(\r
+ new URI("urn:ietf:params:xml:ns:netconf:base:1.0"), \r
+ new Date(42), "yang-data-impl-mutableTest");\r
+ \r
+ List<Node<?>> value = new ArrayList<Node<?>>(); \r
+ value.add(NodeFactory.createSimpleNode(new QName(qName, "name"), null, "Ethernet0/0"));\r
+ value.add(NodeFactory.createSimpleNode(new QName(qName, "mtu"), null, 1500));\r
+ \r
+ CompositeNodeModificationTOImpl ifNode = NodeFactory.createCompositeNodeModification(\r
+ new QName(qName, "interface"), null, value, ModifyAction.DELETE);\r
+ NodeHelper.assignParentToChildren(ifNode);\r
+ \r
+ value = new ArrayList<Node<?>>(); \r
+ value.add(NodeFactory.createSimpleNode(new QName(qName, "name"), null, "Ethernet1/0"));\r
+ value.add(NodeFactory.createSimpleNode(new QName(qName, "mtu"), null, 1501));\r
+ \r
+ CompositeNode ifNode2 = NodeFactory.createCompositeNode(new QName(qName, "interface"), null, value);\r
+ NodeHelper.assignParentToChildren(ifNode2);\r
+\r
+ value = new ArrayList<Node<?>>(); \r
+ value.add(ifNode);\r
+ value.add(ifNode2);\r
+ \r
+ CompositeNode topNode = NodeFactory.createCompositeNode(new QName(qName, "top"), null, value);\r
+ NodeHelper.assignParentToChildren(topNode);\r
+ value = new ArrayList<Node<?>>(); \r
+ value.add(topNode);\r
+ \r
+ CompositeNode root = NodeFactory.createCompositeNode(new QName(qName, "config"), null, value);\r
+ \r
+ \r
+ Assert.assertEquals(1, root.getChildren().size());\r
+ Assert.assertEquals(1, ifNode.getSimpleNodesByName("name").size());\r
+ Assert.assertEquals(1, ifNode.getSimpleNodesByName("mtu").size());\r
+ Assert.assertEquals(2, topNode.getCompositesByName("interface").size());\r
+ NodeModification interfaceMod = (NodeModification) \r
+ topNode.getCompositesByName("interface").get(0);\r
+ Assert.assertEquals(ModifyAction.DELETE, interfaceMod.getModificationAction());\r
+ }\r
+\r
+ /**\r
+ * test modifications builder\r
+ * @throws Exception \r
+ */\r
+ @Test\r
+ public void testCopyDeepNode() throws Exception {\r
+ QName qName = new QName(\r
+ new URI("urn:opendaylight:controller:network"), \r
+ new Date(42), "yang-data-impl-immutableTest_", null);\r
+ \r
+ CompositeNode network = NodeHelper.buildTestConfigTree(qName);\r
+ Map<Node<?>, Node<?>> mutableToOrig = new HashMap<>();\r
+ MutableCompositeNode mutableNetwork = NodeFactory.copyDeepNode(network, mutableToOrig );\r
+\r
+ Document networkShadow = NodeUtils.buildShadowDomTree(network);\r
+ ByteArrayOutputStream expected = new ByteArrayOutputStream();\r
+ NodeHelper.dumpDoc(networkShadow, new PrintStream(expected));\r
+ \r
+ Document mutableNetworkShadow = NodeUtils.buildShadowDomTree(mutableNetwork);\r
+ ByteArrayOutputStream actual = new ByteArrayOutputStream();\r
+ NodeHelper.dumpDoc(mutableNetworkShadow, new PrintStream(actual));\r
+ \r
+ Assert.assertEquals(new String(expected.toByteArray()), new String(actual.toByteArray()));\r
+ }\r
+\r
+}\r
--- /dev/null
+/*\r
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.\r
+ *\r
+ * This program and the accompanying materials are made available under the\r
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
+ * and is available at http://www.eclipse.org/legal/epl-v10.html\r
+ */\r
+package org.opendaylight.controller.yang.data.impl;\r
+\r
+import java.io.InputStream;\r
+import java.io.PrintStream;\r
+import java.io.StringWriter;\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+import java.util.Set;\r
+\r
+import javax.xml.transform.OutputKeys;\r
+import javax.xml.transform.Transformer;\r
+import javax.xml.transform.TransformerFactory;\r
+import javax.xml.transform.dom.DOMSource;\r
+import javax.xml.transform.stream.StreamResult;\r
+\r
+import org.opendaylight.controller.yang.common.QName;\r
+import org.opendaylight.controller.yang.data.api.CompositeNode;\r
+import org.opendaylight.controller.yang.data.api.Node;\r
+import org.opendaylight.controller.yang.model.api.Module;\r
+import org.opendaylight.controller.yang.model.api.SchemaContext;\r
+import org.opendaylight.controller.yang.model.parser.api.YangModelParser;\r
+import org.opendaylight.controller.yang.parser.impl.YangParserImpl;\r
+import org.w3c.dom.Document;\r
+\r
+/**\r
+ * @author michal.rehak\r
+ *\r
+ */\r
+public abstract class NodeHelper {\r
+ \r
+ /** xml source of example network configuration */\r
+ public static final String NETWORK_XML = \r
+ "<network xmlns=\"urn:opendaylight:controller:network\">\n" +\r
+ //"<network>\n" +\r
+ " <topologies>\n" +\r
+ " <topology>\n" +\r
+ " <topology-id>topId_01</topology-id>\n" +\r
+ " <nodes>\n" +\r
+ " <node>\n" +\r
+ " <node-id>nodeId_02</node-id>\n" +\r
+ " <supporting-ne>networkId_02</supporting-ne>\n" +\r
+ " <termination-points>\n" +\r
+ " <termination-point>\n" +\r
+ " <tp-id>tpId_03</tp-id>\n" +\r
+ " </termination-point>\n" +\r
+ " </termination-points>\n" +\r
+ " </node>\n" +\r
+ " <node>\n" +\r
+ " <node-id>nodeId_16</node-id>\n" +\r
+ " <supporting-ne>networkId_17</supporting-ne>\n" +\r
+ " <termination-points>\n" +\r
+ " <termination-point>\n" +\r
+ " <tp-id>tpId_18</tp-id>\n" +\r
+ " </termination-point>\n" +\r
+ " </termination-points>\n" +\r
+ " </node>\n" +\r
+ " <node>\n" +\r
+ " <node-id>nodeId_19</node-id>\n" +\r
+ " <supporting-ne>networkId_20</supporting-ne>\n" +\r
+ " <termination-points>\n" +\r
+ " <termination-point>\n" +\r
+ " <tp-id>tpId_18</tp-id>\n" +\r
+ " </termination-point>\n" +\r
+ " <termination-point>\n" +\r
+ " <tp-id>tpId_19</tp-id>\n" +\r
+ " </termination-point>\n" +\r
+ " </termination-points>\n" +\r
+ " </node>\n" +\r
+ " </nodes>\n" +\r
+ " <links>\n" +\r
+ " <link>\n" +\r
+ " <link-id>linkId_04</link-id>\n" +\r
+ " <source>\n" +\r
+ " <source-node>nodeId_05</source-node>\n" +\r
+ " <source-tp>tpId_06</source-tp>\n" +\r
+ " </source>\n" +\r
+ " <destination>\n" +\r
+ " <dest-node>nodeId_07</dest-node>\n" +\r
+ " <dest-tp>tpId_08</dest-tp>\n" +\r
+ " </destination>\n" +\r
+ " </link>\n" +\r
+ " <link>\n" +\r
+ " <link-id>linkId_11</link-id>\n" +\r
+ " <source>\n" +\r
+ " <source-node>nodeId_12</source-node>\n" +\r
+ " <source-tp>tpId_13</source-tp>\n" +\r
+ " </source>\n" +\r
+ " <destination>\n" +\r
+ " <dest-node>nodeId_14</dest-node>\n" +\r
+ " <dest-tp>tpId_15</dest-tp>\n" +\r
+ " </destination>\n" +\r
+ " </link>\n" +\r
+ " </links>\n" +\r
+ " </topology>\n" +\r
+ " </topologies>\n" +\r
+ " <network-elements>\n" +\r
+ " <network-element>\n" +\r
+ " <element-id>ntElementId_09</element-id>\n" +\r
+ " </network-element>\n" +\r
+ " <network-element>\n" +\r
+ " <element-id>ntElementId_10</element-id>\n" +\r
+ " </network-element>\n" +\r
+ " </network-elements>\n" +\r
+ "</network>";\r
+\r
+ /**\r
+ * @param domTree\r
+ * @param out\r
+ * @throws Exception \r
+ */\r
+ public static void dumpDoc(Document domTree, PrintStream out) throws Exception {\r
+ TransformerFactory transformerFact = TransformerFactory.newInstance();\r
+ transformerFact.setAttribute("indent-number", 4);\r
+ Transformer transformer = transformerFact.newTransformer();\r
+ transformer.setOutputProperty(OutputKeys.INDENT, "yes");\r
+ //initialize StreamResult with File object to save to file\r
+ StreamResult result = new StreamResult(new StringWriter());\r
+ DOMSource source = new DOMSource(domTree);\r
+ transformer.transform(source, result);\r
+ String xmlString = result.getWriter().toString();\r
+ out.println(xmlString);\r
+ }\r
+\r
+ /**\r
+ * @param qName\r
+ * @return example tree, see {@link #NETWORK_XML}\r
+ */\r
+ public static CompositeNode buildTestConfigTree(QName qName) {\r
+ List<Node<?>> value = new ArrayList<Node<?>>(); \r
+ value.add(NodeFactory.createSimpleNode(new QName(qName, "element-id"), null, "ntElementId_09"));\r
+ CompositeNode ntElementNode1 = NodeFactory.createCompositeNode(new QName(qName, "network-element"), null, value);\r
+ assignParentToChildren(ntElementNode1);\r
+ \r
+ value = new ArrayList<Node<?>>(); \r
+ value.add(NodeFactory.createSimpleNode(new QName(qName, "element-id"), null, "ntElementId_10"));\r
+ CompositeNode ntElementNode2 = NodeFactory.createCompositeNode(new QName(qName, "network-element"), null, value);\r
+ assignParentToChildren(ntElementNode2);\r
+ \r
+ value = new ArrayList<Node<?>>();\r
+ value.add(ntElementNode1);\r
+ value.add(ntElementNode2);\r
+ CompositeNode ntElementsNode = NodeFactory.createCompositeNode(\r
+ new QName(qName, "network-elements"), null, value);\r
+ assignParentToChildren(ntElementsNode);\r
+ \r
+ value = new ArrayList<Node<?>>(); \r
+ value.add(NodeFactory.createSimpleNode(new QName(qName, "dest-node"), null, "nodeId_07"));\r
+ value.add(NodeFactory.createSimpleNode(new QName(qName, "dest-tp"), null, "tpId_08"));\r
+ CompositeNode destination = NodeFactory.createCompositeNode(\r
+ new QName(qName, "destination"), null, value);\r
+ assignParentToChildren(destination);\r
+ \r
+ value = new ArrayList<Node<?>>(); \r
+ value.add(NodeFactory.createSimpleNode(new QName(qName, "source-node"), null, "nodeId_05"));\r
+ value.add(NodeFactory.createSimpleNode(new QName(qName, "source-tp"), null, "tpId_06"));\r
+ CompositeNode source = NodeFactory.createCompositeNode(\r
+ new QName(qName, "source"), null, value);\r
+ assignParentToChildren(source);\r
+ \r
+ value = new ArrayList<Node<?>>(); \r
+ value.add(NodeFactory.createSimpleNode(new QName(qName, "link-id"), null, "linkId_04"));\r
+ value.add(source);\r
+ value.add(destination);\r
+ CompositeNode link1 = NodeFactory.createCompositeNode(\r
+ new QName(qName, "link"), null, value);\r
+ assignParentToChildren(link1);\r
+ \r
+ value = new ArrayList<Node<?>>(); \r
+ value.add(NodeFactory.createSimpleNode(new QName(qName, "dest-node"), null, "nodeId_14"));\r
+ value.add(NodeFactory.createSimpleNode(new QName(qName, "dest-tp"), null, "tpId_15"));\r
+ destination = NodeFactory.createCompositeNode(\r
+ new QName(qName, "destination"), null, value);\r
+ assignParentToChildren(destination);\r
+ \r
+ value = new ArrayList<Node<?>>(); \r
+ value.add(NodeFactory.createSimpleNode(new QName(qName, "source-node"), null, "nodeId_12"));\r
+ value.add(NodeFactory.createSimpleNode(new QName(qName, "source-tp"), null, "tpId_13"));\r
+ source = NodeFactory.createCompositeNode(\r
+ new QName(qName, "source"), null, value);\r
+ assignParentToChildren(source);\r
+ \r
+ value = new ArrayList<Node<?>>(); \r
+ value.add(NodeFactory.createSimpleNode(new QName(qName, "link-id"), null, "linkId_11"));\r
+ value.add(source);\r
+ value.add(destination);\r
+ CompositeNode link2 = NodeFactory.createCompositeNode(\r
+ new QName(qName, "link"), null, value);\r
+ assignParentToChildren(link2);\r
+ \r
+ value = new ArrayList<Node<?>>(); \r
+ value.add(link1);\r
+ value.add(link2);\r
+ CompositeNode links = NodeFactory.createCompositeNode(\r
+ new QName(qName, "links"), null, value);\r
+ assignParentToChildren(links);\r
+ \r
+ \r
+ value = new ArrayList<Node<?>>(); \r
+ value.add(NodeFactory.createSimpleNode(new QName(qName, "tp-id"), null, "tpId_03"));\r
+ CompositeNode terminationPointNode1 = NodeFactory.createCompositeNode(\r
+ new QName(qName, "termination-point"), null, value);\r
+ assignParentToChildren(terminationPointNode1);\r
+ \r
+ value = new ArrayList<Node<?>>(); \r
+ value.add(terminationPointNode1);\r
+ CompositeNode terminationPointsNode = NodeFactory.createCompositeNode(\r
+ new QName(qName, "termination-points"), null, value);\r
+ assignParentToChildren(terminationPointsNode);\r
+ \r
+ value = new ArrayList<Node<?>>(); \r
+ value.add(NodeFactory.createSimpleNode(new QName(qName, "node-id"), null, "nodeId_02"));\r
+ value.add(NodeFactory.createSimpleNode(new QName(qName, "supporting-ne"), null, "networkId_02"));\r
+ value.add(terminationPointsNode);\r
+ CompositeNode node1Node = NodeFactory.createCompositeNode(\r
+ new QName(qName, "node"), null, value);\r
+ assignParentToChildren(node1Node);\r
+ \r
+ value = new ArrayList<Node<?>>(); \r
+ value.add(NodeFactory.createSimpleNode(new QName(qName, "tp-id"), null, "tpId_18"));\r
+ terminationPointNode1 = NodeFactory.createCompositeNode(\r
+ new QName(qName, "termination-point"), null, value);\r
+ assignParentToChildren(terminationPointNode1);\r
+ \r
+ value = new ArrayList<Node<?>>(); \r
+ value.add(terminationPointNode1);\r
+ terminationPointsNode = NodeFactory.createCompositeNode(\r
+ new QName(qName, "termination-points"), null, value);\r
+ assignParentToChildren(terminationPointsNode);\r
+ \r
+ value = new ArrayList<Node<?>>(); \r
+ value.add(NodeFactory.createSimpleNode(new QName(qName, "node-id"), null, "nodeId_16"));\r
+ value.add(NodeFactory.createSimpleNode(new QName(qName, "supporting-ne"), null, "networkId_17"));\r
+ value.add(terminationPointsNode);\r
+ CompositeNode node2Node = NodeFactory.createCompositeNode(\r
+ new QName(qName, "node"), null, value);\r
+ assignParentToChildren(node2Node);\r
+ \r
+ value = new ArrayList<Node<?>>(); \r
+ value.add(NodeFactory.createSimpleNode(new QName(qName, "tp-id"), null, "tpId_18"));\r
+ terminationPointNode1 = NodeFactory.createCompositeNode(\r
+ new QName(qName, "termination-point"), null, value);\r
+ assignParentToChildren(terminationPointNode1);\r
+ \r
+ value = new ArrayList<Node<?>>(); \r
+ value.add(NodeFactory.createSimpleNode(new QName(qName, "tp-id"), null, "tpId_19"));\r
+ CompositeNode terminationPointNode2 = NodeFactory.createCompositeNode(\r
+ new QName(qName, "termination-point"), null, value);\r
+ assignParentToChildren(terminationPointNode2);\r
+ \r
+ value = new ArrayList<Node<?>>(); \r
+ value.add(terminationPointNode1);\r
+ value.add(terminationPointNode2);\r
+ terminationPointsNode = NodeFactory.createCompositeNode(\r
+ new QName(qName, "termination-points"), null, value);\r
+ assignParentToChildren(terminationPointsNode);\r
+ \r
+ value = new ArrayList<Node<?>>(); \r
+ value.add(NodeFactory.createSimpleNode(new QName(qName, "node-id"), null, "nodeId_19"));\r
+ value.add(NodeFactory.createSimpleNode(new QName(qName, "supporting-ne"), null, "networkId_20"));\r
+ value.add(terminationPointsNode);\r
+ CompositeNode node3Node = NodeFactory.createCompositeNode(\r
+ new QName(qName, "node"), null, value);\r
+ assignParentToChildren(node3Node);\r
+ \r
+ value = new ArrayList<Node<?>>(); \r
+ value.add(node1Node);\r
+ value.add(node2Node);\r
+ value.add(node3Node);\r
+ CompositeNode nodesNode = NodeFactory.createCompositeNode(\r
+ new QName(qName, "nodes"), null, value);\r
+ assignParentToChildren(nodesNode);\r
+ \r
+ value = new ArrayList<Node<?>>();\r
+ value.add(links);\r
+ value.add(nodesNode);\r
+ value.add(NodeFactory.createSimpleNode(new QName(qName, "topology-id"), null, "topId_01"));\r
+ CompositeNode topology = NodeFactory.createCompositeNode(\r
+ new QName(qName, "topology"), null, value);\r
+ assignParentToChildren(topology);\r
+ \r
+ value = new ArrayList<Node<?>>();\r
+ value.add(topology);\r
+ CompositeNode topologies = NodeFactory.createCompositeNode(\r
+ new QName(qName, "topologies"), null, value);\r
+ assignParentToChildren(topologies);\r
+ \r
+ value = new ArrayList<Node<?>>();\r
+ value.add(topologies);\r
+ CompositeNode network = NodeFactory.createCompositeNode(\r
+ new QName(qName, "network"), null, value);\r
+ assignParentToChildren(network);\r
+ \r
+ return network;\r
+ }\r
+\r
+ /**\r
+ * @param parentNode\r
+ */\r
+ public static void assignParentToChildren(CompositeNode parentNode) {\r
+ for (Node<?> child : parentNode.getChildren()) {\r
+ ((AbstractNodeTO<?>) child).setParent(parentNode);\r
+ }\r
+ }\r
+\r
+ /**\r
+ * @return schema context of controller-network.yang\r
+ */\r
+ public static SchemaContext loadSchemaContext() {\r
+ YangModelParser yParser = new YangParserImpl();\r
+ List<InputStream> yangInputStreams = new ArrayList<>();\r
+ yangInputStreams.add(NodeHelper.class.getResourceAsStream(\r
+ "/controller-network.yang"));\r
+ yangInputStreams.add(NodeHelper.class.getResourceAsStream(\r
+ "/ietf-inet-types@2010-09-24.yang"));\r
+ Set<Module> modules = yParser\r
+ .parseYangModelsFromStreams(yangInputStreams);\r
+ return yParser.resolveSchemaContext(modules);\r
+ }\r
+\r
+}\r
--- /dev/null
+/*\r
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.\r
+ *\r
+ * This program and the accompanying materials are made available under the\r
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
+ * and is available at http://www.eclipse.org/legal/epl-v10.html\r
+ */\r
+package org.opendaylight.controller.yang.data.impl;\r
+\r
+import java.net.URI;\r
+import java.util.Date;\r
+\r
+import junit.framework.Assert;\r
+\r
+import org.junit.Before;\r
+import org.junit.Test;\r
+import org.opendaylight.controller.yang.common.QName;\r
+import org.opendaylight.controller.yang.data.api.CompositeNode;\r
+import org.opendaylight.controller.yang.data.api.MutableCompositeNode;\r
+import org.opendaylight.controller.yang.data.api.MutableSimpleNode;\r
+import org.opendaylight.controller.yang.data.api.SimpleNode;\r
+import org.opendaylight.controller.yang.model.api.SchemaContext;\r
+import org.w3c.dom.Document;\r
+\r
+/**\r
+ * @author michal.rehak\r
+ * \r
+ */\r
+public class NodeModificationBuilderImplTest {\r
+\r
+ private SchemaContext schemaCtx;\r
+ private QName qName;\r
+ private CompositeNode network;\r
+ private NodeModificationBuilderImpl nodeModificationBuilder;\r
+\r
+ /**\r
+ * prepare schemaContext\r
+ * @throws Exception \r
+ */\r
+ @Before\r
+ public void setUp() throws Exception {\r
+ schemaCtx = NodeHelper.loadSchemaContext();\r
+\r
+ qName = new QName(\r
+ new URI("urn:opendaylight:controller:network"), \r
+ new Date(1369000800000L), "topos");\r
+ network = NodeHelper.buildTestConfigTree(qName);\r
+ \r
+ nodeModificationBuilder = new NodeModificationBuilderImpl(network, schemaCtx);\r
+ }\r
+\r
+ /**\r
+ * Test method for\r
+ * {@link org.opendaylight.controller.yang.data.impl.NodeModificationBuilderImpl#buildDiffTree()}\r
+ * .\r
+ * @throws Exception \r
+ */\r
+ @Test\r
+ public void testBuildDiffTree() throws Exception {\r
+ Document networkShadow = NodeUtils.buildShadowDomTree(network);\r
+ SimpleNode<String> needle = NodeUtils.findNodeByXpath(networkShadow, \r
+ "//node[node-id='nodeId_19']//termination-point[2]/tp-id");\r
+ \r
+ @SuppressWarnings("unchecked")\r
+ MutableSimpleNode<String> mutableNeedle = (MutableSimpleNode<String>) \r
+ nodeModificationBuilder.getMutableEquivalent(needle);\r
+ \r
+ mutableNeedle.setValue("tpId_18x");\r
+ nodeModificationBuilder.replaceNode(mutableNeedle);\r
+ CompositeNode diffTree = nodeModificationBuilder.buildDiffTree();\r
+ \r
+ Document diffShadow = NodeUtils.buildShadowDomTree(diffTree);\r
+ NodeHelper.dumpDoc(diffShadow, System.out);\r
+ }\r
+\r
+ /**\r
+ * Test method for\r
+ * {@link org.opendaylight.controller.yang.data.impl.NodeModificationBuilderImpl#getMutableEquivalent(org.opendaylight.controller.yang.data.api.Node)}\r
+ * .\r
+ */\r
+ @Test\r
+ public void testGetMutableEquivalent() {\r
+ MutableCompositeNode rootMutable = (MutableCompositeNode) \r
+ nodeModificationBuilder.getMutableEquivalent(network);\r
+ \r
+ CompositeNode topologies = network.getCompositesByName("topologies").iterator().next();\r
+ CompositeNode topologiesMutable = rootMutable.getCompositesByName("topologies").iterator().next();\r
+ \r
+ Assert.assertSame(topologiesMutable, nodeModificationBuilder.getMutableEquivalent(topologies));\r
+ }\r
+\r
+}\r
--- /dev/null
+/*\r
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.\r
+ *\r
+ * This program and the accompanying materials are made available under the\r
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
+ * and is available at http://www.eclipse.org/legal/epl-v10.html\r
+ */\r
+package org.opendaylight.controller.yang.data.impl;\r
+\r
+import java.io.ByteArrayOutputStream;\r
+import java.io.PrintStream;\r
+import java.net.URI;\r
+import java.util.Date;\r
+import java.util.List;\r
+import java.util.Map;\r
+\r
+import org.junit.Assert;\r
+import org.junit.Before;\r
+import org.junit.Test;\r
+import org.opendaylight.controller.yang.common.QName;\r
+import org.opendaylight.controller.yang.data.api.CompositeNode;\r
+import org.opendaylight.controller.yang.data.api.Node;\r
+import org.opendaylight.controller.yang.data.api.SimpleNode;\r
+import org.opendaylight.controller.yang.model.api.ListSchemaNode;\r
+import org.opendaylight.controller.yang.model.api.SchemaContext;\r
+import org.w3c.dom.Document;\r
+\r
+/**\r
+ * @author michal.rehak\r
+ *\r
+ */\r
+public class NodeUtilsTest {\r
+ \r
+ private QName qName;\r
+ private CompositeNode network;\r
+\r
+ /**\r
+ * @throws Exception\r
+ */\r
+ @Before\r
+ public void setUp() throws Exception {\r
+ qName = new QName(\r
+ new URI("urn:ietf:params:xml:ns:netconf:base:1.0"), \r
+ new Date(42), "yang-data-impl-mutableTest");\r
+ network = NodeHelper.buildTestConfigTree(qName);\r
+ }\r
+\r
+ /**\r
+ * Test method for {@link org.opendaylight.controller.yang.data.impl.NodeUtils#buildPath(org.opendaylight.controller.yang.data.api.Node)}.\r
+ * @throws Exception \r
+ */\r
+ @Test\r
+ public void testBuildPath() throws Exception {\r
+ SimpleNode<?> needle = network.getCompositesByName("topologies").iterator().next()\r
+ .getCompositesByName("topology").iterator().next()\r
+ .getSimpleNodesByName("topology-id").iterator().next();\r
+ String breadCrumbs = NodeUtils.buildPath(needle);\r
+ \r
+ Assert.assertEquals("network.topologies.topology.topology-id", breadCrumbs);\r
+ }\r
+\r
+ /**\r
+ * Test method for {@link org.opendaylight.controller.yang.data.impl.NodeUtils#buildShadowDomTree(org.opendaylight.controller.yang.data.api.CompositeNode)}.\r
+ * @throws Exception \r
+ */\r
+ @Test\r
+ public void testBuildShadowDomTree() throws Exception {\r
+ Document networkShadow = NodeUtils.buildShadowDomTree(network);\r
+ ByteArrayOutputStream actual = new ByteArrayOutputStream();\r
+ NodeHelper.dumpDoc(networkShadow, new PrintStream(actual));\r
+ \r
+ Assert.assertEquals(2760, new String(actual.toByteArray()).length());\r
+ }\r
+\r
+ /**\r
+ * Test method for {@link org.opendaylight.controller.yang.data.impl.NodeUtils#findNodeByXpath(org.w3c.dom.Document, java.lang.String)}.\r
+ * @throws Exception \r
+ */\r
+ @Test\r
+ public void testFindNodeByXpath() throws Exception {\r
+ Document networkShadow = NodeUtils.buildShadowDomTree(network);\r
+ SimpleNode<String> needle = NodeUtils.findNodeByXpath(networkShadow, \r
+ "//node[node-id='nodeId_19']//termination-point[2]/tp-id");\r
+ Assert.assertNotNull(needle);\r
+ Assert.assertEquals("tpId_18", needle.getValue());\r
+ }\r
+\r
+ /**\r
+ * Test method for {@link org.opendaylight.controller.yang.data.impl.NodeUtils#buildNodeMap(java.util.List)}.\r
+ */\r
+ @Test\r
+ public void testBuildNodeMap() {\r
+ CompositeNode topology = network.getCompositesByName("topologies").iterator().next()\r
+ .getCompositesByName("topology").iterator().next();\r
+ \r
+ Map<QName, List<Node<?>>> nodeMap = NodeUtils.buildNodeMap(topology.getChildren());\r
+ Assert.assertEquals(3, nodeMap.size());\r
+ }\r
+ \r
+ /**\r
+ * Test method for {@link org.opendaylight.controller.yang.data.impl.NodeUtils#buildMapOfListNodes(org.opendaylight.controller.yang.model.api.SchemaContext)}.\r
+ */\r
+ @Test\r
+ public void testBuildMapOfListNodes() {\r
+ SchemaContext schemaCtx = NodeHelper.loadSchemaContext();\r
+ Map<String, ListSchemaNode> mapOfLists = NodeUtils.buildMapOfListNodes(schemaCtx);\r
+ Assert.assertEquals(5, mapOfLists.size());\r
+ }\r
+\r
+}\r
--- /dev/null
+<?xml version="1.0" encoding="ISO-8859-1"?>\r
+<rpc message-id="101" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">\r
+ <edit-config>\r
+ <target>\r
+ <running />\r
+ </target>\r
+ <config>\r
+ <top xmlns="http://example.com/schema/1.2/config">\r
+ <interface>\r
+ <name>Ethernet0/0</name>\r
+ <mtu>1500</mtu>\r
+ </interface>\r
+ </top>\r
+ </config>\r
+ </edit-config>\r
+</rpc>\r
+
\ No newline at end of file
--- /dev/null
+xmlDoc.network(xmlns: 'urn:opendaylight:controller:network') {\r
+ topologies {\r
+ topology {\r
+ 'topology-id'('topId_'+cnt.get())\r
+ \r
+ types()\r
+ nodes {\r
+ node {\r
+ 'node-id'('nodeId_'+cnt.get())\r
+ 'supporting-ne'('networkId_'+cnt.get())\r
+ 'termination-points' {\r
+ 'termination-point' {\r
+ 'tp-id'('tpId_'+cnt.get())\r
+ }\r
+ }\r
+ }\r
+ node {\r
+ 'node-id'('nodeId_'+cnt.get())\r
+ 'supporting-ne'('networkId_'+cnt.get())\r
+ 'termination-points' {\r
+ 'termination-point' {\r
+ 'tp-id'('tpId_'+cnt.get())\r
+ }\r
+ }\r
+ }\r
+ node {\r
+ 'node-id'('nodeId_'+cnt.get())\r
+ 'supporting-ne'('networkId_'+cnt.get())\r
+ 'termination-points' {\r
+ 'termination-point' {\r
+ 'tp-id'('tpId_'+cnt.get())\r
+ }\r
+ 'termination-point' {\r
+ 'tp-id'('tpId_'+cnt.get())\r
+ }\r
+ }\r
+ }\r
+ }\r
+ links {\r
+ link {\r
+ 'link-id'('linkId_'+cnt.get())\r
+ source {\r
+ 'source-node'('nodeId_'+cnt.get())\r
+ 'source-tp'('tpId_'+cnt.get(false))\r
+ }\r
+ destination {\r
+ 'dest-node'('nodeId_'+cnt.get())\r
+ 'dest-tp'('tpId_'+cnt.get(false))\r
+ }\r
+ }\r
+ link {\r
+ 'link-id'('linkId_'+cnt.get())\r
+ source {\r
+ 'source-node'('nodeId_'+cnt.get())\r
+ 'source-tp'('tpId_'+cnt.get(false))\r
+ }\r
+ destination {\r
+ 'dest-node'('nodeId_'+cnt.get())\r
+ 'dest-tp'('tpId_'+cnt.get(false))\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+ 'network-elements' {\r
+ 'network-element' {\r
+ 'element-id'('ntElementId_'+cnt.get())\r
+ }\r
+ 'network-element' {\r
+ 'element-id'('ntElementId_'+cnt.get())\r
+ }\r
+ }\r
+ }
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<network xmlns="urn:opendaylight:controller:network">\r
+ <topologies>\r
+ <topology>\r
+ <topology-id>topId_01</topology-id>\r
+ <types></types>\r
+ <nodes>\r
+ <node>\r
+ <node-id>nodeId_02</node-id>\r
+ <supporting-ne>networkId_02</supporting-ne>\r
+ <termination-points>\r
+ <termination-point>\r
+ <tp-id>tpId_03</tp-id>\r
+ </termination-point>\r
+ </termination-points>\r
+ </node>\r
+ <node>\r
+ <node-id>nodeId_16</node-id>\r
+ <supporting-ne>networkId_17</supporting-ne>\r
+ <termination-points>\r
+ <termination-point>\r
+ <tp-id>tpId_18</tp-id>\r
+ </termination-point>\r
+ </termination-points>\r
+ </node>\r
+ <node>\r
+ <node-id>nodeId_19</node-id>\r
+ <supporting-ne>networkId_20</supporting-ne>\r
+ <termination-points>\r
+ <termination-point>\r
+ <tp-id>tpId_18</tp-id>\r
+ </termination-point>\r
+ <termination-point>\r
+ <tp-id>tpId_19</tp-id>\r
+ </termination-point>\r
+ </termination-points>\r
+ </node>\r
+ </nodes>\r
+ <links>\r
+ <link>\r
+ <link-id>linkId_04</link-id>\r
+ <source>\r
+ <source-node>nodeId_05</source-node>\r
+ <source-tp>tpId_06</source-tp>\r
+ </source>\r
+ <destination>\r
+ <dest-node>nodeId_07</dest-node>\r
+ <dest-tp>tpId_08</dest-tp>\r
+ </destination>\r
+ </link>\r
+ <link>\r
+ <link-id>linkId_11</link-id>\r
+ <source>\r
+ <source-node>nodeId_12</source-node>\r
+ <source-tp>tpId_13</source-tp>\r
+ </source>\r
+ <destination>\r
+ <dest-node>nodeId_14</dest-node>\r
+ <dest-tp>tpId_15</dest-tp>\r
+ </destination>\r
+ </link>\r
+ </links>\r
+ </topology>\r
+ </topologies>\r
+ <network-elements>\r
+ <network-element>\r
+ <element-id>ntElementId_09</element-id>\r
+ </network-element>\r
+ <network-element>\r
+ <element-id>ntElementId_10</element-id>\r
+ </network-element>\r
+ </network-elements>\r
+</network>\r
+\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<network xmlns="urn:opendaylight:controller:network">
+ <topologies>
+ <topology>
+ <topology-id>topId_01</topology-id>
+ <types />
+ <nodes>
+ <node>
+ <node-id>nodeId_02</node-id>
+ <supporting-ne>networkId_03</supporting-ne>
+ <termination-points>
+ <termination-point>
+ <tp-id>tpId_04</tp-id>
+ </termination-point>
+ </termination-points>
+ </node>
+ <node>
+ <node-id>nodeId_05</node-id>
+ <supporting-ne>networkId_06</supporting-ne>
+ <termination-points>
+ <termination-point>
+ <tp-id>tpId_07</tp-id>
+ </termination-point>
+ </termination-points>
+ </node>
+ <node>
+ <node-id>nodeId_08</node-id>
+ <supporting-ne>networkId_09</supporting-ne>
+ <termination-points>
+ <termination-point>
+ <tp-id>tpId_10</tp-id>
+ </termination-point>
+ <termination-point>
+ <tp-id>tpId_11</tp-id>
+ </termination-point>
+ </termination-points>
+ </node>
+ </nodes>
+ <links>
+ <link>
+ <link-id>linkId_12</link-id>
+ <source>
+ <source-node>nodeId_13</source-node>
+ <source-tp>tpId_13</source-tp>
+ </source>
+ <destination>
+ <dest-node>nodeId_14</dest-node>
+ <dest-tp>tpId_14</dest-tp>
+ </destination>
+ </link>
+ <link>
+ <link-id>linkId_15</link-id>
+ <source>
+ <source-node>nodeId_16</source-node>
+ <source-tp>tpId_16</source-tp>
+ </source>
+ <destination>
+ <dest-node>nodeId_17</dest-node>
+ <dest-tp>tpId_17</dest-tp>
+ </destination>
+ </link>
+ </links>
+ </topology>
+ </topologies>
+ <network-elements>
+ <network-element>
+ <element-id>ntElementId_18</element-id>
+ </network-element>
+ <network-element>
+ <element-id>ntElementId_19</element-id>
+ </network-element>
+ </network-elements>
+</network>\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ xmlns:yin="urn:ietf:params:xml:schema:yang:yin:1"
+ targetNamespace="urn:opendaylight:controller:network"
+ xmlns="urn:opendaylight:controller:network"
+ elementFormDefault="qualified"
+ attributeFormDefault="unqualified"
+ version="2013-05-20"
+ xml:lang="en"
+ xmlns:topos="urn:opendaylight:controller:network"
+ xmlns:inet="urn:ietf:params:xml:ns:yang:ietf-inet-types">
+
+ <xs:import namespace="urn:ietf:params:xml:ns:yang:ietf-inet-types"
+ schemaLocation="ietf-inet-types@2010-09-24.xsd"/>
+
+ <xs:annotation>
+ <xs:documentation>
+ This schema was generated from the YANG module controller-network
+ by pyang version 1.2.
+
+ The schema describes an instance document consisting
+ of the entire configuration data store, operational
+ data, rpc operations, and notifications.
+ This schema can thus NOT be used as-is to
+ validate NETCONF PDUs.
+ </xs:documentation>
+ </xs:annotation>
+
+
+ <!-- YANG typedefs -->
+ <xs:simpleType name="topology-id">
+ <xs:restriction base="xs:string">
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="node-id">
+ <xs:restriction base="xs:string">
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="link-id">
+ <xs:restriction base="xs:string">
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="tp-id">
+ <xs:annotation>
+ <xs:documentation>
+ identifier for termination points on a port
+ </xs:documentation>
+ </xs:annotation>
+
+ <xs:restriction base="xs:string">
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="tp-ref">
+ <xs:restriction base="tp-id">
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="topology-ref">
+ <xs:annotation>
+ <xs:documentation>
+ This type is used for leafs that reference topology identifier instance.
+ </xs:documentation>
+ </xs:annotation>
+
+ <xs:restriction base="topology-id">
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="node-ref">
+ <xs:annotation>
+ <xs:documentation>
+ This type is used for leafs that reference a node instance.
+ </xs:documentation>
+ </xs:annotation>
+
+ <xs:restriction base="node-id">
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="link-ref">
+ <xs:annotation>
+ <xs:documentation>
+ This type is used for leafs that reference a link instance.
+ </xs:documentation>
+ </xs:annotation>
+
+ <xs:restriction base="link-id">
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="network-element-ref">
+ <xs:restriction base="element-id">
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="element-id">
+ <xs:restriction base="xs:string">
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:element name="network">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="topologies" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="topology" minOccurs="0" maxOccurs="unbounded">
+ <xs:annotation>
+ <xs:documentation>
+
+ This is the model of abstract topology which contains only Network
+ Nodes and Network Links. Each topology MUST be identified by
+ unique topology-id for reason that the store could contain many
+ topologies.
+
+ </xs:documentation>
+ </xs:annotation>
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="topology-id" type="topology-id">
+ <xs:annotation>
+ <xs:documentation>
+
+ It is presumed that datastore will contain many topologies. To
+ distinguish between topologies it is vital to have UNIQUE
+ topology identifier.
+
+ </xs:documentation>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="types" minOccurs="0">
+ <xs:annotation>
+ <xs:documentation>
+
+ The container for definition of topology types.
+ The augmenting modules should add empty optional leaf
+ to this container to signalize topology type.
+
+ </xs:documentation>
+ </xs:annotation>
+ <xs:complexType>
+ <xs:sequence>
+ <xs:any minOccurs="0" maxOccurs="unbounded"
+ namespace="##other" processContents="lax"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="nodes" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="node" minOccurs="0" maxOccurs="unbounded">
+ <xs:annotation>
+ <xs:documentation>
+ The list of network nodes defined for topology.
+ </xs:documentation>
+ </xs:annotation>
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="node-id" type="node-id">
+ <xs:annotation>
+ <xs:documentation>
+ The Topology identifier of network-node.
+ </xs:documentation>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="supporting-ne" minOccurs="0" type="network-element-ref">
+ </xs:element>
+ <xs:element name="termination-points" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="termination-point" minOccurs="0" maxOccurs="unbounded">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="tp-id" type="tp-id">
+ </xs:element>
+ <xs:any minOccurs="0" maxOccurs="unbounded"
+ namespace="##other" processContents="lax"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:any minOccurs="0" maxOccurs="unbounded"
+ namespace="##other" processContents="lax"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:key name="key_termination-points_node_nodes_topology_topologies_network_termination-point">
+ <xs:selector xpath="topos:termination-point"/>
+ <xs:field xpath="topos:tp-id"/>
+ </xs:key>
+ </xs:element>
+ <xs:any minOccurs="0" maxOccurs="unbounded"
+ namespace="##other" processContents="lax"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:any minOccurs="0" maxOccurs="unbounded"
+ namespace="##other" processContents="lax"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:key name="key_nodes_topology_topologies_network_node">
+ <xs:selector xpath="topos:node"/>
+ <xs:field xpath="topos:node-id"/>
+ </xs:key>
+ </xs:element>
+ <xs:element name="links" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="link" minOccurs="0" maxOccurs="unbounded">
+ <xs:annotation>
+ <xs:documentation>
+
+ The Network Link which is defined by Local (Source) and
+ Remote (Destination) Network Nodes. Every link MUST be
+ defined either by identifier and his local and remote
+ Network Nodes (in real applications it is common that many
+ links are originated from one node and end up in same
+ remote node). To ensure that we would always know to
+ distinguish between links, every link SHOULD have
+ identifier.
+
+ </xs:documentation>
+ </xs:annotation>
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="link-id" type="link-id">
+ </xs:element>
+ <xs:element name="source" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="source-node" minOccurs="0" type="node-ref">
+ <xs:annotation>
+ <xs:documentation>
+ Source node identifier.
+ </xs:documentation>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="source-tp" minOccurs="0" type="tp-ref">
+ </xs:element>
+ <xs:any minOccurs="0" maxOccurs="unbounded"
+ namespace="##other" processContents="lax"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="destination" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="dest-node" minOccurs="0" type="node-ref">
+ <xs:annotation>
+ <xs:documentation>
+ Destination node identifier.
+ </xs:documentation>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="dest-tp" minOccurs="0" type="tp-ref">
+ </xs:element>
+ <xs:any minOccurs="0" maxOccurs="unbounded"
+ namespace="##other" processContents="lax"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:any minOccurs="0" maxOccurs="unbounded"
+ namespace="##other" processContents="lax"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:any minOccurs="0" maxOccurs="unbounded"
+ namespace="##other" processContents="lax"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:key name="key_links_topology_topologies_network_link">
+ <xs:selector xpath="topos:link"/>
+ <xs:field xpath="topos:link-id"/>
+ </xs:key>
+ </xs:element>
+ <xs:any minOccurs="0" maxOccurs="unbounded"
+ namespace="##other" processContents="lax"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:any minOccurs="0" maxOccurs="unbounded"
+ namespace="##other" processContents="lax"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:key name="key_topologies_network_topology">
+ <xs:selector xpath="topos:topology"/>
+ <xs:field xpath="topos:topology-id"/>
+ </xs:key>
+ </xs:element>
+ <xs:element name="network-elements" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="network-element" minOccurs="0" maxOccurs="unbounded">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="element-id" type="element-id">
+ </xs:element>
+ <xs:any minOccurs="0" maxOccurs="unbounded"
+ namespace="##other" processContents="lax"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:any minOccurs="0" maxOccurs="unbounded"
+ namespace="##other" processContents="lax"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:key name="key_network-elements_network_network-element">
+ <xs:selector xpath="topos:network-element"/>
+ <xs:field xpath="topos:element-id"/>
+ </xs:key>
+ </xs:element>
+ <xs:any minOccurs="0" maxOccurs="unbounded"
+ namespace="##other" processContents="lax"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+</xs:schema>
--- /dev/null
+module controller-network {
+ yang-version 1;
+ namespace "urn:opendaylight:controller:network";
+ prefix "topos";
+
+ import ietf-inet-types { prefix "inet"; }
+
+ revision 2013-05-20 {
+ description "Initial demo";
+ }
+
+
+
+
+ typedef topology-id {
+ type string;
+ }
+
+ typedef node-id {
+ type string;
+ }
+
+ typedef link-id {
+ type string;
+ }
+
+ typedef tp-id {
+ type string;
+ description "identifier for termination points on a port";
+ }
+
+ typedef tp-ref {
+ type leafref {
+ path "/network/topologies/topology/nodes/node/termination-points/termination-point/tp-id";
+ }
+ }
+ typedef topology-ref {
+ type leafref {
+ path "/network/topologies/topology/topology-id";
+ }
+ description "This type is used for leafs that reference topology identifier instance.";
+ // currently not used
+ }
+
+ typedef node-ref {
+ type leafref {
+ path "/network/topologies/topology/nodes/node/node-id";
+ }
+ description "This type is used for leafs that reference a node instance.";
+ }
+
+ typedef link-ref {
+ type leafref {
+ path "/network/topologies/topology/links/link/link-id";
+ }
+ description "This type is used for leafs that reference a link instance.";
+ // currently not used
+ }
+
+ typedef network-element-ref {
+ type leafref {
+ path "/network/network-elements/network-element/element-id";
+ }
+ }
+
+
+ typedef element-id {
+ type string;
+ }
+
+ container network {
+ container topologies {
+ list topology {
+ description "
+ This is the model of abstract topology which contains only Network
+ Nodes and Network Links. Each topology MUST be identified by
+ unique topology-id for reason that the store could contain many
+ topologies.
+ ";
+ key "topology-id";
+ leaf topology-id {
+ type topology-id;
+ description "
+ It is presumed that datastore will contain many topologies. To
+ distinguish between topologies it is vital to have UNIQUE
+ topology identifier.
+ ";
+ }
+
+ container types {
+ description "
+ The container for definition of topology types.
+ The augmenting modules should add empty optional leaf
+ to this container to signalize topology type.
+ ";
+ }
+
+ container nodes {
+ list node {
+ description "The list of network nodes defined for topology.";
+
+ key "node-id";
+ leaf node-id {
+ type node-id;
+ description "The Topology identifier of network-node.";
+ }
+
+ leaf supporting-ne {
+ type network-element-ref;
+ }
+
+ container termination-points {
+ list termination-point {
+ key "tp-id";
+ leaf tp-id {
+ type tp-id;
+ }
+ }
+ }
+ }
+ }
+
+ container links {
+ list link {
+ description "
+ The Network Link which is defined by Local (Source) and
+ Remote (Destination) Network Nodes. Every link MUST be
+ defined either by identifier and his local and remote
+ Network Nodes (in real applications it is common that many
+ links are originated from one node and end up in same
+ remote node). To ensure that we would always know to
+ distinguish between links, every link SHOULD have
+ identifier.
+ ";
+ key "link-id";
+
+ leaf link-id {
+ type link-id;
+ }
+ container source {
+ leaf source-node {
+ type node-ref;
+ description "Source node identifier.";
+ }
+ leaf source-tp {
+ type tp-ref;
+ }
+ }
+ container destination {
+ leaf dest-node {
+ type node-ref;
+ description "Destination node identifier.";
+ }
+ leaf dest-tp {
+ type tp-ref;
+ }
+ }
+ }
+ }
+ }
+ }
+ container network-elements {
+ config true;
+ list network-element {
+ key "element-id";
+ leaf element-id {
+ type element-id;
+ }
+ }
+ }
+ }
+}
--- /dev/null
+//import groovy.xml.StreamingMarkupBuilder
+import groovy.xml.MarkupBuilder
+import groovy.xml.XmlUtil
+
+class Counter {
+ def counter = 0
+ def get() {
+ return get(true)
+ }
+ def get(isInc) {
+ if (isInc) {
+ counter++
+ }
+ return String.format('%02d', counter)
+ }
+}
+
+
+cnt = new Counter()
+def writer = new StringWriter()
+xmlDoc = new MarkupBuilder(writer)
+xmlDoc.setDoubleQuotes(true)
+xmlDoc.getMkp().xmlDeclaration(version:'1.0', encoding: 'UTF-8')
+
+//def data = {
+// mkp.xmlDeclaration()
+// network(xmlns: 'urn:opendaylight:controller:network') {
+dataFile = new File(args[0])
+evaluate(dataFile)
+// xmlDoc.network(xmlns: 'urn:opendaylight:controller:network') {
+ // topologies {
+ // topology {
+ // 'topology-id'('topId_'+cnt.get())
+ // types()
+ // nodes {
+ // node {
+ // 'node-id'('nodeId_'+cnt.get())
+ // 'supporting-ne'('networkId_'+cnt.get())
+ // 'termination-points' {
+ // 'termination-point' {
+ // 'tp-id'('tpId_'+cnt.get())
+ // }
+ // }
+ // }
+ // node {
+ // 'node-id'('nodeId_'+cnt.get())
+ // 'supporting-ne'('networkId_'+cnt.get())
+ // 'termination-points' {
+ // 'termination-point' {
+ // 'tp-id'('tpId_'+cnt.get())
+ // }
+ // }
+ // }
+ // node {
+ // 'node-id'('nodeId_'+cnt.get())
+ // 'supporting-ne'('networkId_'+cnt.get())
+ // 'termination-points' {
+ // 'termination-point' {
+ // 'tp-id'('tpId_'+cnt.get())
+ // }
+ // 'termination-point' {
+ // 'tp-id'('tpId_'+cnt.get())
+ // }
+ // }
+ // }
+ // }
+ // links {
+ // link {
+ // 'link-id'('linkId_'+cnt.get())
+ // source {
+ // 'source-node'('nodeId_'+cnt.get())
+ // 'source-tp'('tpId_'+cnt.get(false))
+ // }
+ // destination {
+ // 'dest-node'('nodeId_'+cnt.get())
+ // 'dest-tp'('tpId_'+cnt.get(false))
+ // }
+ // }
+ // link {
+ // 'link-id'('linkId_'+cnt.get())
+ // source {
+ // 'source-node'('nodeId_'+cnt.get())
+ // 'source-tp'('tpId_'+cnt.get(false))
+ // }
+ // destination {
+ // 'dest-node'('nodeId_'+cnt.get())
+ // 'dest-tp'('tpId_'+cnt.get(false))
+ // }
+ // }
+ // }
+ // }
+ // }
+ // 'network-elements' {
+ // 'network-element' {
+ // 'element-id'('ntElementId_'+cnt.get())
+ // }
+ // 'network-element' {
+ // 'element-id'('ntElementId_'+cnt.get())
+ // }
+ // }
+ // }
+
+//}
+
+
+// def xmlDoc = new StreamingMarkupBuilder()
+// xmlDoc.encoding = 'UTF'
+//println XmlUtil.serialize(xmlDoc.bind(data))
+
+println writer
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ xmlns:yin="urn:ietf:params:xml:schema:yang:yin:1"
+ targetNamespace="urn:ietf:params:xml:ns:yang:ietf-inet-types"
+ xmlns="urn:ietf:params:xml:ns:yang:ietf-inet-types"
+ elementFormDefault="qualified"
+ attributeFormDefault="unqualified"
+ version="2010-09-24"
+ xml:lang="en"
+ xmlns:inet="urn:ietf:params:xml:ns:yang:ietf-inet-types">
+
+ <xs:annotation>
+ <xs:documentation>
+ This schema was generated from the YANG module ietf-inet-types
+ by pyang version 1.2.
+
+ The schema describes an instance document consisting
+ of the entire configuration data store, operational
+ data, rpc operations, and notifications.
+ This schema can thus NOT be used as-is to
+ validate NETCONF PDUs.
+ </xs:documentation>
+ </xs:annotation>
+
+ <xs:annotation>
+ <xs:documentation>
+ This module contains a collection of generally useful derived
+ YANG data types for Internet addresses and related things.
+
+ Copyright (c) 2010 IETF Trust and the persons identified as
+ authors of the code. All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, is permitted pursuant to, and subject to the license
+ terms contained in, the Simplified BSD License set forth in Section
+ 4.c of the IETF Trust's Legal Provisions Relating to IETF Documents
+ (http://trustee.ietf.org/license-info).
+
+ This version of this YANG module is part of RFC 6021; see
+ the RFC itself for full legal notices.
+ </xs:documentation>
+ </xs:annotation>
+
+ <!-- YANG typedefs -->
+ <xs:simpleType name="ip-version">
+ <xs:annotation>
+ <xs:documentation>
+ This value represents the version of the IP protocol.
+
+ In the value set and its semantics, this type is equivalent
+ to the InetVersion textual convention of the SMIv2.
+ </xs:documentation>
+ </xs:annotation>
+
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="unknown"/>
+ <xs:enumeration value="ipv4"/>
+ <xs:enumeration value="ipv6"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="dscp">
+ <xs:annotation>
+ <xs:documentation>
+ The dscp type represents a Differentiated Services Code-Point
+ that may be used for marking packets in a traffic stream.
+
+ In the value set and its semantics, this type is equivalent
+ to the Dscp textual convention of the SMIv2.
+ </xs:documentation>
+ </xs:annotation>
+
+ <xs:restriction base="xs:unsignedByte">
+ <xs:minInclusive value="0"/>
+ <xs:maxInclusive value="63"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="ipv6-flow-label">
+ <xs:annotation>
+ <xs:documentation>
+ The flow-label type represents flow identifier or Flow Label
+ in an IPv6 packet header that may be used to discriminate
+ traffic flows.
+
+ In the value set and its semantics, this type is equivalent
+ to the IPv6FlowLabel textual convention of the SMIv2.
+ </xs:documentation>
+ </xs:annotation>
+
+ <xs:restriction base="xs:unsignedInt">
+ <xs:minInclusive value="0"/>
+ <xs:maxInclusive value="1048575"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="port-number">
+ <xs:annotation>
+ <xs:documentation>
+ The port-number type represents a 16-bit port number of an
+ Internet transport layer protocol such as UDP, TCP, DCCP, or
+ SCTP. Port numbers are assigned by IANA. A current list of
+ all assignments is available from <http://www.iana.org/>.
+
+ Note that the port number value zero is reserved by IANA. In
+ situations where the value zero does not make sense, it can
+ be excluded by subtyping the port-number type.
+
+ In the value set and its semantics, this type is equivalent
+ to the InetPortNumber textual convention of the SMIv2.
+ </xs:documentation>
+ </xs:annotation>
+
+ <xs:restriction base="xs:unsignedShort">
+ <xs:minInclusive value="0"/>
+ <xs:maxInclusive value="65535"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="as-number">
+ <xs:annotation>
+ <xs:documentation>
+ The as-number type represents autonomous system numbers
+ which identify an Autonomous System (AS). An AS is a set
+ of routers under a single technical administration, using
+ an interior gateway protocol and common metrics to route
+ packets within the AS, and using an exterior gateway
+ protocol to route packets to other ASs'. IANA maintains
+ the AS number space and has delegated large parts to the
+ regional registries.
+
+ Autonomous system numbers were originally limited to 16
+ bits. BGP extensions have enlarged the autonomous system
+ number space to 32 bits. This type therefore uses an uint32
+ base type without a range restriction in order to support
+ a larger autonomous system number space.
+
+ In the value set and its semantics, this type is equivalent
+ to the InetAutonomousSystemNumber textual convention of
+ the SMIv2.
+ </xs:documentation>
+ </xs:annotation>
+
+ <xs:restriction base="xs:unsignedInt">
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="ip-address">
+ <xs:annotation>
+ <xs:documentation>
+ The ip-address type represents an IP address and is IP
+ version neutral. The format of the textual representations
+ implies the IP version.
+ </xs:documentation>
+ </xs:annotation>
+
+ <xs:union>
+ <xs:simpleType>
+ <xs:restriction base="ipv4-address">
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType>
+ <xs:restriction base="ipv6-address">
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:union>
+ </xs:simpleType>
+ <xs:simpleType name="ipv4-address">
+ <xs:annotation>
+ <xs:documentation>
+ The ipv4-address type represents an IPv4 address in
+ dotted-quad notation. The IPv4 address may include a zone
+ index, separated by a % sign.
+
+ The zone index is used to disambiguate identical address
+ values. For link-local addresses, the zone index will
+ typically be the interface index number or the name of an
+ interface. If the zone index is not present, the default
+ zone of the device will be used.
+
+ The canonical format for the zone index is the numerical
+ format
+ </xs:documentation>
+ </xs:annotation>
+
+ <xs:restriction base="xs:string">
+ <xs:pattern value="(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])(%[\p{N}\p{L}]+)?"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="ipv6-address">
+ <xs:annotation>
+ <xs:documentation>
+ The ipv6-address type represents an IPv6 address in full,
+ mixed, shortened, and shortened-mixed notation. The IPv6
+ address may include a zone index, separated by a % sign.
+
+ The zone index is used to disambiguate identical address
+ values. For link-local addresses, the zone index will
+ typically be the interface index number or the name of an
+ interface. If the zone index is not present, the default
+ zone of the device will be used.
+
+ The canonical format of IPv6 addresses uses the compressed
+ format described in RFC 4291, Section 2.2, item 2 with the
+ following additional rules: the :: substitution must be
+ applied to the longest sequence of all-zero 16-bit chunks
+ in an IPv6 address. If there is a tie, the first sequence
+ of all-zero 16-bit chunks is replaced by ::. Single
+ all-zero 16-bit chunks are not compressed. The canonical
+ format uses lowercase characters and leading zeros are
+ not allowed. The canonical format for the zone index is
+ the numerical format as described in RFC 4007, Section
+ 11.2.
+ </xs:documentation>
+ </xs:annotation>
+
+ <xs:restriction base="xs:string">
+ <xs:pattern value="(((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))(%[\p{N}\p{L}]+)?)|((([^:]+:){6}(([^:]+:[^:]+)|(.*\..*)))|((([^:]+:)*[^:]+)?::(([^:]+:)*[^:]+)?)(%.+)?)"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="ip-prefix">
+ <xs:annotation>
+ <xs:documentation>
+ The ip-prefix type represents an IP prefix and is IP
+ version neutral. The format of the textual representations
+ implies the IP version.
+ </xs:documentation>
+ </xs:annotation>
+
+ <xs:union>
+ <xs:simpleType>
+ <xs:restriction base="ipv4-prefix">
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType>
+ <xs:restriction base="ipv6-prefix">
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:union>
+ </xs:simpleType>
+ <xs:simpleType name="ipv4-prefix">
+ <xs:annotation>
+ <xs:documentation>
+ The ipv4-prefix type represents an IPv4 address prefix.
+ The prefix length is given by the number following the
+ slash character and must be less than or equal to 32.
+
+ A prefix length value of n corresponds to an IP address
+ mask that has n contiguous 1-bits from the most
+ significant bit (MSB) and all other bits set to 0.
+
+ The canonical format of an IPv4 prefix has all bits of
+ the IPv4 address set to zero that are not part of the
+ IPv4 prefix.
+ </xs:documentation>
+ </xs:annotation>
+
+ <xs:restriction base="xs:string">
+ <xs:pattern value="(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])/(([0-9])|([1-2][0-9])|(3[0-2]))"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="ipv6-prefix">
+ <xs:annotation>
+ <xs:documentation>
+ The ipv6-prefix type represents an IPv6 address prefix.
+ The prefix length is given by the number following the
+ slash character and must be less than or equal 128.
+
+ A prefix length value of n corresponds to an IP address
+ mask that has n contiguous 1-bits from the most
+ significant bit (MSB) and all other bits set to 0.
+
+ The IPv6 address should have all bits that do not belong
+ to the prefix set to zero.
+
+ The canonical format of an IPv6 prefix has all bits of
+ the IPv6 address set to zero that are not part of the
+ IPv6 prefix. Furthermore, IPv6 address is represented
+ in the compressed format described in RFC 4291, Section
+ 2.2, item 2 with the following additional rules: the ::
+ substitution must be applied to the longest sequence of
+ all-zero 16-bit chunks in an IPv6 address. If there is
+ a tie, the first sequence of all-zero 16-bit chunks is
+ replaced by ::. Single all-zero 16-bit chunks are not
+ compressed. The canonical format uses lowercase
+ characters and leading zeros are not allowed.
+ </xs:documentation>
+ </xs:annotation>
+
+ <xs:restriction base="xs:string">
+ <xs:pattern value="(((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))(/(([0-9])|([0-9]{2})|(1[0-1][0-9])|(12[0-8]))))|((([^:]+:){6}(([^:]+:[^:]+)|(.*\..*)))|((([^:]+:)*[^:]+)?::(([^:]+:)*[^:]+)?)(/.+))"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="domain-name">
+ <xs:annotation>
+ <xs:documentation>
+ The domain-name type represents a DNS domain name. The
+ name SHOULD be fully qualified whenever possible.
+
+ Internet domain names are only loosely specified. Section
+ 3.5 of RFC 1034 recommends a syntax (modified in Section
+ 2.1 of RFC 1123). The pattern above is intended to allow
+ for current practice in domain name use, and some possible
+ future expansion. It is designed to hold various types of
+ domain names, including names used for A or AAAA records
+ (host names) and other records, such as SRV records. Note
+ that Internet host names have a stricter syntax (described
+ in RFC 952) than the DNS recommendations in RFCs 1034 and
+ 1123, and that systems that want to store host names in
+ schema nodes using the domain-name type are recommended to
+ adhere to this stricter standard to ensure interoperability.
+
+ The encoding of DNS names in the DNS protocol is limited
+ to 255 characters. Since the encoding consists of labels
+ prefixed by a length bytes and there is a trailing NULL
+ byte, only 253 characters can appear in the textual dotted
+ notation.
+
+ The description clause of schema nodes using the domain-name
+ type MUST describe when and how these names are resolved to
+ IP addresses. Note that the resolution of a domain-name value
+ may require to query multiple DNS records (e.g., A for IPv4
+ and AAAA for IPv6). The order of the resolution process and
+ which DNS record takes precedence can either be defined
+ explicitely or it may depend on the configuration of the
+ resolver.
+
+ Domain-name values use the US-ASCII encoding. Their canonical
+ format uses lowercase US-ASCII characters. Internationalized
+ domain names MUST be encoded in punycode as described in RFC
+ 3492
+ </xs:documentation>
+ </xs:annotation>
+
+ <xs:restriction base="t0">
+ <xs:minLength value="1"/>
+ <xs:maxLength value="253"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="host">
+ <xs:annotation>
+ <xs:documentation>
+ The host type represents either an IP address or a DNS
+ domain name.
+ </xs:documentation>
+ </xs:annotation>
+
+ <xs:union>
+ <xs:simpleType>
+ <xs:restriction base="ip-address">
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType>
+ <xs:restriction base="domain-name">
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:union>
+ </xs:simpleType>
+ <xs:simpleType name="uri">
+ <xs:annotation>
+ <xs:documentation>
+ The uri type represents a Uniform Resource Identifier
+ (URI) as defined by STD 66.
+
+ Objects using the uri type MUST be in US-ASCII encoding,
+ and MUST be normalized as described by RFC 3986 Sections
+ 6.2.1, 6.2.2.1, and 6.2.2.2. All unnecessary
+ percent-encoding is removed, and all case-insensitive
+ characters are set to lowercase except for hexadecimal
+ digits, which are normalized to uppercase as described in
+ Section 6.2.2.1.
+
+ The purpose of this normalization is to help provide
+ unique URIs. Note that this normalization is not
+ sufficient to provide uniqueness. Two URIs that are
+ textually distinct after this normalization may still be
+ equivalent.
+
+ Objects using the uri type may restrict the schemes that
+ they permit. For example, 'data:' and 'urn:' schemes
+ might not be appropriate.
+
+ A zero-length URI is not a valid URI. This can be used to
+ express 'URI absent' where required.
+
+ In the value set and its semantics, this type is equivalent
+ to the Uri SMIv2 textual convention defined in RFC 5017.
+ </xs:documentation>
+ </xs:annotation>
+
+ <xs:restriction base="xs:string">
+ </xs:restriction>
+ </xs:simpleType>
+
+
+ <!-- locally generated simpleType helpers -->
+
+ <xs:simpleType name="t0">
+ <xs:restriction base="xs:string">
+ <xs:pattern value="((([a-zA-Z0-9_]([a-zA-Z0-9\-_]){0,61})?[a-zA-Z0-9]\.)*([a-zA-Z0-9_]([a-zA-Z0-9\-_]){0,61})?[a-zA-Z0-9]\.?)|\."/>
+ </xs:restriction>
+ </xs:simpleType>
+
+</xs:schema>
--- /dev/null
+ module ietf-inet-types {
+
+ namespace "urn:ietf:params:xml:ns:yang:ietf-inet-types";
+ prefix "inet";
+
+ organization
+ "IETF NETMOD (NETCONF Data Modeling Language) Working Group";
+
+ contact
+ "WG Web: <http://tools.ietf.org/wg/netmod/>
+ WG List: <mailto:netmod@ietf.org>
+
+ WG Chair: David Partain
+ <mailto:david.partain@ericsson.com>
+
+ WG Chair: David Kessens
+ <mailto:david.kessens@nsn.com>
+
+ Editor: Juergen Schoenwaelder
+ <mailto:j.schoenwaelder@jacobs-university.de>";
+
+ description
+ "This module contains a collection of generally useful derived
+ YANG data types for Internet addresses and related things.
+
+ Copyright (c) 2010 IETF Trust and the persons identified as
+ authors of the code. All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, is permitted pursuant to, and subject to the license
+ terms contained in, the Simplified BSD License set forth in Section
+ 4.c of the IETF Trust's Legal Provisions Relating to IETF Documents
+ (http://trustee.ietf.org/license-info).
+
+ This version of this YANG module is part of RFC 6021; see
+ the RFC itself for full legal notices.";
+
+ revision 2010-09-24 {
+ description
+ "Initial revision.";
+ reference
+ "RFC 6021: Common YANG Data Types";
+ }
+
+ /*** collection of protocol field related types ***/
+
+ typedef ip-version {
+ type enumeration {
+ enum unknown {
+ value "0";
+ description
+ "An unknown or unspecified version of the Internet protocol.";
+ }
+ enum ipv4 {
+ value "1";
+ description
+ "The IPv4 protocol as defined in RFC 791.";
+ }
+ enum ipv6 {
+ value "2";
+ description
+ "The IPv6 protocol as defined in RFC 2460.";
+ }
+ }
+ description
+ "This value represents the version of the IP protocol.
+
+ In the value set and its semantics, this type is equivalent
+ to the InetVersion textual convention of the SMIv2.";
+ reference
+ "RFC 791: Internet Protocol
+ RFC 2460: Internet Protocol, Version 6 (IPv6) Specification
+ RFC 4001: Textual Conventions for Internet Network Addresses";
+ }
+
+ typedef dscp {
+ type uint8 {
+ range "0..63";
+ }
+ description
+ "The dscp type represents a Differentiated Services Code-Point
+ that may be used for marking packets in a traffic stream.
+
+ In the value set and its semantics, this type is equivalent
+ to the Dscp textual convention of the SMIv2.";
+ reference
+ "RFC 3289: Management Information Base for the Differentiated
+ Services Architecture
+ RFC 2474: Definition of the Differentiated Services Field
+ (DS Field) in the IPv4 and IPv6 Headers
+ RFC 2780: IANA Allocation Guidelines For Values In
+ the Internet Protocol and Related Headers";
+ }
+
+ typedef ipv6-flow-label {
+ type uint32 {
+ range "0..1048575";
+ }
+ description
+ "The flow-label type represents flow identifier or Flow Label
+ in an IPv6 packet header that may be used to discriminate
+ traffic flows.
+
+ In the value set and its semantics, this type is equivalent
+ to the IPv6FlowLabel textual convention of the SMIv2.";
+ reference
+ "RFC 3595: Textual Conventions for IPv6 Flow Label
+ RFC 2460: Internet Protocol, Version 6 (IPv6) Specification";
+ }
+
+ typedef port-number {
+ type uint16 {
+ range "0..65535";
+ }
+ description
+ "The port-number type represents a 16-bit port number of an
+ Internet transport layer protocol such as UDP, TCP, DCCP, or
+ SCTP. Port numbers are assigned by IANA. A current list of
+ all assignments is available from <http://www.iana.org/>.
+
+ Note that the port number value zero is reserved by IANA. In
+ situations where the value zero does not make sense, it can
+ be excluded by subtyping the port-number type.
+
+ In the value set and its semantics, this type is equivalent
+ to the InetPortNumber textual convention of the SMIv2.";
+ reference
+ "RFC 768: User Datagram Protocol
+ RFC 793: Transmission Control Protocol
+ RFC 4960: Stream Control Transmission Protocol
+ RFC 4340: Datagram Congestion Control Protocol (DCCP)
+ RFC 4001: Textual Conventions for Internet Network Addresses";
+ }
+
+ /*** collection of autonomous system related types ***/
+
+ typedef as-number {
+ type uint32;
+ description
+ "The as-number type represents autonomous system numbers
+ which identify an Autonomous System (AS). An AS is a set
+ of routers under a single technical administration, using
+ an interior gateway protocol and common metrics to route
+ packets within the AS, and using an exterior gateway
+ protocol to route packets to other ASs'. IANA maintains
+ the AS number space and has delegated large parts to the
+ regional registries.
+
+ Autonomous system numbers were originally limited to 16
+ bits. BGP extensions have enlarged the autonomous system
+ number space to 32 bits. This type therefore uses an uint32
+ base type without a range restriction in order to support
+ a larger autonomous system number space.
+
+ In the value set and its semantics, this type is equivalent
+ to the InetAutonomousSystemNumber textual convention of
+ the SMIv2.";
+ reference
+ "RFC 1930: Guidelines for creation, selection, and registration
+ of an Autonomous System (AS)
+ RFC 4271: A Border Gateway Protocol 4 (BGP-4)
+ RFC 4893: BGP Support for Four-octet AS Number Space
+ RFC 4001: Textual Conventions for Internet Network Addresses";
+ }
+
+ /*** collection of IP address and hostname related types ***/
+
+ typedef ip-address {
+ type union {
+ type inet:ipv4-address;
+ type inet:ipv6-address;
+ }
+ description
+ "The ip-address type represents an IP address and is IP
+ version neutral. The format of the textual representations
+ implies the IP version.";
+ }
+
+ typedef ipv4-address {
+ type string {
+ pattern
+ '(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}'
+ + '([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])'
+ + '(%[\p{N}\p{L}]+)?';
+ }
+ description
+ "The ipv4-address type represents an IPv4 address in
+ dotted-quad notation. The IPv4 address may include a zone
+ index, separated by a % sign.
+
+ The zone index is used to disambiguate identical address
+ values. For link-local addresses, the zone index will
+ typically be the interface index number or the name of an
+ interface. If the zone index is not present, the default
+ zone of the device will be used.
+
+ The canonical format for the zone index is the numerical
+ format";
+ }
+
+ typedef ipv6-address {
+ type string {
+ pattern '((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}'
+ + '((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|'
+ + '(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\.){3}'
+ + '(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))'
+ + '(%[\p{N}\p{L}]+)?';
+ pattern '(([^:]+:){6}(([^:]+:[^:]+)|(.*\..*)))|'
+ + '((([^:]+:)*[^:]+)?::(([^:]+:)*[^:]+)?)'
+ + '(%.+)?';
+ }
+ description
+ "The ipv6-address type represents an IPv6 address in full,
+ mixed, shortened, and shortened-mixed notation. The IPv6
+ address may include a zone index, separated by a % sign.
+
+ The zone index is used to disambiguate identical address
+ values. For link-local addresses, the zone index will
+ typically be the interface index number or the name of an
+ interface. If the zone index is not present, the default
+ zone of the device will be used.
+
+ The canonical format of IPv6 addresses uses the compressed
+ format described in RFC 4291, Section 2.2, item 2 with the
+ following additional rules: the :: substitution must be
+ applied to the longest sequence of all-zero 16-bit chunks
+ in an IPv6 address. If there is a tie, the first sequence
+ of all-zero 16-bit chunks is replaced by ::. Single
+ all-zero 16-bit chunks are not compressed. The canonical
+ format uses lowercase characters and leading zeros are
+ not allowed. The canonical format for the zone index is
+ the numerical format as described in RFC 4007, Section
+ 11.2.";
+ reference
+ "RFC 4291: IP Version 6 Addressing Architecture
+ RFC 4007: IPv6 Scoped Address Architecture
+ RFC 5952: A Recommendation for IPv6 Address Text Representation";
+ }
+
+ typedef ip-prefix {
+ type union {
+ type inet:ipv4-prefix;
+ type inet:ipv6-prefix;
+ }
+ description
+ "The ip-prefix type represents an IP prefix and is IP
+ version neutral. The format of the textual representations
+ implies the IP version.";
+ }
+
+ typedef ipv4-prefix {
+ type string {
+ pattern
+ '(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}'
+ + '([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])'
+ + '/(([0-9])|([1-2][0-9])|(3[0-2]))';
+ }
+ description
+ "The ipv4-prefix type represents an IPv4 address prefix.
+ The prefix length is given by the number following the
+ slash character and must be less than or equal to 32.
+
+ A prefix length value of n corresponds to an IP address
+ mask that has n contiguous 1-bits from the most
+ significant bit (MSB) and all other bits set to 0.
+
+ The canonical format of an IPv4 prefix has all bits of
+ the IPv4 address set to zero that are not part of the
+ IPv4 prefix.";
+ }
+
+ typedef ipv6-prefix {
+ type string {
+ pattern '((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}'
+ + '((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|'
+ + '(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\.){3}'
+ + '(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))'
+ + '(/(([0-9])|([0-9]{2})|(1[0-1][0-9])|(12[0-8])))';
+ pattern '(([^:]+:){6}(([^:]+:[^:]+)|(.*\..*)))|'
+ + '((([^:]+:)*[^:]+)?::(([^:]+:)*[^:]+)?)'
+ + '(/.+)';
+ }
+ description
+ "The ipv6-prefix type represents an IPv6 address prefix.
+ The prefix length is given by the number following the
+ slash character and must be less than or equal 128.
+
+ A prefix length value of n corresponds to an IP address
+ mask that has n contiguous 1-bits from the most
+ significant bit (MSB) and all other bits set to 0.
+
+ The IPv6 address should have all bits that do not belong
+ to the prefix set to zero.
+
+ The canonical format of an IPv6 prefix has all bits of
+ the IPv6 address set to zero that are not part of the
+ IPv6 prefix. Furthermore, IPv6 address is represented
+ in the compressed format described in RFC 4291, Section
+ 2.2, item 2 with the following additional rules: the ::
+ substitution must be applied to the longest sequence of
+ all-zero 16-bit chunks in an IPv6 address. If there is
+ a tie, the first sequence of all-zero 16-bit chunks is
+ replaced by ::. Single all-zero 16-bit chunks are not
+ compressed. The canonical format uses lowercase
+ characters and leading zeros are not allowed.";
+ reference
+ "RFC 4291: IP Version 6 Addressing Architecture";
+ }
+
+ /*** collection of domain name and URI types ***/
+
+ typedef domain-name {
+ type string {
+ pattern '((([a-zA-Z0-9_]([a-zA-Z0-9\-_]){0,61})?[a-zA-Z0-9]\.)*'
+ + '([a-zA-Z0-9_]([a-zA-Z0-9\-_]){0,61})?[a-zA-Z0-9]\.?)'
+ + '|\.';
+ length "1..253";
+ }
+ description
+ "The domain-name type represents a DNS domain name. The
+ name SHOULD be fully qualified whenever possible.
+
+ Internet domain names are only loosely specified. Section
+ 3.5 of RFC 1034 recommends a syntax (modified in Section
+ 2.1 of RFC 1123). The pattern above is intended to allow
+ for current practice in domain name use, and some possible
+ future expansion. It is designed to hold various types of
+ domain names, including names used for A or AAAA records
+ (host names) and other records, such as SRV records. Note
+ that Internet host names have a stricter syntax (described
+ in RFC 952) than the DNS recommendations in RFCs 1034 and
+ 1123, and that systems that want to store host names in
+ schema nodes using the domain-name type are recommended to
+ adhere to this stricter standard to ensure interoperability.
+
+ The encoding of DNS names in the DNS protocol is limited
+ to 255 characters. Since the encoding consists of labels
+ prefixed by a length bytes and there is a trailing NULL
+ byte, only 253 characters can appear in the textual dotted
+ notation.
+
+ The description clause of schema nodes using the domain-name
+ type MUST describe when and how these names are resolved to
+ IP addresses. Note that the resolution of a domain-name value
+ may require to query multiple DNS records (e.g., A for IPv4
+ and AAAA for IPv6). The order of the resolution process and
+ which DNS record takes precedence can either be defined
+ explicitely or it may depend on the configuration of the
+ resolver.
+
+ Domain-name values use the US-ASCII encoding. Their canonical
+ format uses lowercase US-ASCII characters. Internationalized
+ domain names MUST be encoded in punycode as described in RFC
+ 3492";
+ reference
+ "RFC 952: DoD Internet Host Table Specification
+ RFC 1034: Domain Names - Concepts and Facilities
+ RFC 1123: Requirements for Internet Hosts -- Application
+ and Support
+ RFC 2782: A DNS RR for specifying the location of services
+ (DNS SRV)
+ RFC 3492: Punycode: A Bootstring encoding of Unicode for
+ Internationalized Domain Names in Applications
+ (IDNA)
+ RFC 5891: Internationalizing Domain Names in Applications
+ (IDNA): Protocol";
+ }
+
+ typedef host {
+ type union {
+ type inet:ip-address;
+ type inet:domain-name;
+ }
+ description
+ "The host type represents either an IP address or a DNS
+ domain name.";
+ }
+
+ typedef uri {
+ type string;
+ description
+ "The uri type represents a Uniform Resource Identifier
+ (URI) as defined by STD 66.
+
+ Objects using the uri type MUST be in US-ASCII encoding,
+ and MUST be normalized as described by RFC 3986 Sections
+ 6.2.1, 6.2.2.1, and 6.2.2.2. All unnecessary
+ percent-encoding is removed, and all case-insensitive
+ characters are set to lowercase except for hexadecimal
+ digits, which are normalized to uppercase as described in
+ Section 6.2.2.1.
+
+ The purpose of this normalization is to help provide
+ unique URIs. Note that this normalization is not
+ sufficient to provide uniqueness. Two URIs that are
+ textually distinct after this normalization may still be
+ equivalent.
+
+ Objects using the uri type may restrict the schemes that
+ they permit. For example, 'data:' and 'urn:' schemes
+ might not be appropriate.
+
+ A zero-length URI is not a valid URI. This can be used to
+ express 'URI absent' where required.
+
+ In the value set and its semantics, this type is equivalent
+ to the Uri SMIv2 textual convention defined in RFC 5017.";
+ reference
+ "RFC 3986: Uniform Resource Identifier (URI): Generic Syntax
+ RFC 3305: Report from the Joint W3C/IETF URI Planning Interest
+ Group: Uniform Resource Identifiers (URIs), URLs,
+ and Uniform Resource Names (URNs): Clarifications
+ and Recommendations
+ RFC 5017: MIB Textual Conventions for Uniform Resource
+ Identifiers (URIs)";
+ }
+
+ }
*/\r
package org.opendaylight.controller.yang.model.api;\r
\r
+import java.util.List;\r
+\r
/**\r
* Interface describing YANG 'deviation' statement.\r
* <p>\r
*/\r
String getReference();\r
\r
+ /**\r
+ * @return collection of all unknown nodes defined under this schema node.\r
+ */\r
+ public List<UnknownSchemaNode> getUnknownSchemaNodes();\r
+\r
}\r
private List<UnknownSchemaNode> unknownSchemaNodes = Collections
.emptyList();
private Status status = Status.CURRENT;
- private String units = "";
+ private String units = null;
private Object defaultValue = null;
private boolean addedByUses;
@Override
public String toString() {
- return ("Span Config [nodeId=" + nodeId + " spanPort=" + spanPort + "]");
+ return ("SpanConfig [nodeId=" + nodeId + ", spanPort=" + spanPort + "]");
}
}
* The class describes subnet information including L3 address, vlan and set of
* ports associated with the subnet.
*/
-public class Subnet implements Serializable {
+public class Subnet implements Cloneable, Serializable {
private static final long serialVersionUID = 1L;
// Key fields
private InetAddress networkAddress;
private short subnetMaskLength;
// Property fields
private short vlan;
- private Set<NodeConnector> nodeConnectors;
+ private final Set<NodeConnector> nodeConnectors;
public Subnet(InetAddress ip, short maskLen, short vlan) {
this.networkAddress = ip;
nodeConnectors = conf.getSubnetNodeConnectors();
}
+ public Subnet(Subnet subnet) {
+ networkAddress = subnet.networkAddress;
+ subnetMaskLength = subnet.subnetMaskLength;
+ vlan = subnet.vlan;
+ nodeConnectors = new HashSet<NodeConnector>(subnet.nodeConnectors);
+ }
+
/**
* Add NodeConnectors to a subnet
*
public String toString() {
return ("Subnet [networkAddress=" + networkAddress.getHostAddress()
+ "/" + subnetMaskLength
- + ((vlan == 0) ? "" : (" vlan=" + vlan)) + " "
+ + ((vlan == 0) ? "" : (", vlan=" + vlan)) + ", "
+ ((isFlatLayer2()) ? "{[*, *]}" : nodeConnectors.toString()) + "]");
}
}
return true;
}
+
+ /**
+ * Implement clonable interface
+ */
+ @Override
+ public Subnet clone() {
+ return new Subnet(this);
+ }
+
}
*/
@XmlRootElement
@XmlAccessorType(XmlAccessType.NONE)
-public class SubnetConfig implements Serializable {
+public class SubnetConfig implements Cloneable, Serializable {
//static fields are by default excluded by Gson parser
private static final long serialVersionUID = 1L;
private static final String prettyFields[] = { GUIField.NAME.toString(),
nodePorts = sp;
}
+ public SubnetConfig(SubnetConfig subnetConfig) {
+ name = subnetConfig.name;
+ subnet = subnetConfig.subnet;
+ nodePorts = new ArrayList<String>(subnetConfig.nodePorts);
+ }
+
public String getName() {
return name;
}
@Override
public String toString() {
- return ("Subnet Config [Description=" + name + " Subnet=" + subnet
- + " NodeConnectors=" + nodePorts + "]");
+ return ("SubnetConfig [Description=" + name + ", Subnet=" + subnet
+ + ", NodeConnectors=" + nodePorts + "]");
+ }
+
+ /**
+ * Implement clonable interface
+ */
+ @Override
+ public SubnetConfig clone() {
+ return new SubnetConfig(this);
}
+
}
@Override
public String toString() {
- return ("Switch Config [Node=" + nodeId + " Description=" + description +
- " Tier=" + tier + " Mode=" + mode + "]");
+ return ("SwitchConfig [Node=" + nodeId + ", Description=" + description +
+ ", Tier=" + tier + ", Mode=" + mode + "]");
}
}
import org.opendaylight.controller.configuration.IConfigurationContainerAware;
import org.opendaylight.controller.sal.core.Bandwidth;
import org.opendaylight.controller.sal.core.Config;
+import org.opendaylight.controller.sal.core.ConstructionException;
import org.opendaylight.controller.sal.core.Description;
import org.opendaylight.controller.sal.core.MacAddress;
import org.opendaylight.controller.sal.core.Name;
private final List<NodeConnector> spanNodeConnectors = new CopyOnWriteArrayList<NodeConnector>();
private ConcurrentMap<InetAddress, Subnet> subnets; // set of Subnets keyed by the InetAddress
private ConcurrentMap<String, SubnetConfig> subnetsConfigList;
- private ConcurrentMap<Integer, SpanConfig> spanConfigList;
+ private ConcurrentMap<SpanConfig, SpanConfig> spanConfigList;
private ConcurrentMap<String, SwitchConfig> nodeConfigList; // manually configured parameters for the node like name and tier
private ConcurrentMap<Long, String> configSaveEvent;
private ConcurrentMap<Node, Map<String, Property>> nodeProps; // properties are maintained in global container only
private IClusterContainerServices clusterContainerService = null;
private String containerName = null;
private boolean isDefaultContainer = true;
+ private static final int REPLACE_RETRY = 1;
public enum ReasonCode {
SUCCESS("Success"), FAILURE("Failure"), INVALID_CONF(
@SuppressWarnings("deprecation")
private void allocateCaches() {
if (this.clusterContainerService == null) {
+ this.nonClusterObjectCreate();
log.warn("un-initialized clusterContainerService, can't create cache");
return;
}
log.error("\nFailed to get cache for subnetsConfigList");
}
- spanConfigList = (ConcurrentMap<Integer, SpanConfig>) clusterContainerService
+ spanConfigList = (ConcurrentMap<SpanConfig, SpanConfig>) clusterContainerService
.getCache("switchmanager.spanConfigList");
if (spanConfigList == null) {
log.error("\nFailed to get cache for spanConfigList");
}
}
- void nonClusterObjectCreate() {
+ private void nonClusterObjectCreate() {
subnetsConfigList = new ConcurrentHashMap<String, SubnetConfig>();
- spanConfigList = new ConcurrentHashMap<Integer, SpanConfig>();
+ spanConfigList = new ConcurrentHashMap<SpanConfig, SpanConfig>();
nodeConfigList = new ConcurrentHashMap<String, SwitchConfig>();
subnets = new ConcurrentHashMap<InetAddress, Subnet>();
configSaveEvent = new ConcurrentHashMap<Long, String>();
nodeConnectorNames = new ConcurrentHashMap<Node, Map<String, NodeConnector>>();
}
- @SuppressWarnings("deprecation")
- private void destroyCaches(String container) {
- if (this.clusterContainerService == null) {
- log.info("un-initialized clusterContainerService, can't create cache");
- return;
- }
-
- clusterContainerService.destroyCache("switchmanager.subnetsConfigList");
- clusterContainerService.destroyCache("switchmanager.spanConfigList");
- clusterContainerService.destroyCache("switchmanager.nodeConfigList");
- clusterContainerService.destroyCache("switchmanager.subnets");
- clusterContainerService.destroyCache("switchmanager.configSaveEvent");
- clusterContainerService.destroyCache("switchmanager.nodeProps");
- clusterContainerService
- .destroyCache("switchmanager.nodeConnectorProps");
- clusterContainerService
- .destroyCache("switchmanager.nodeConnectorNames");
- nonClusterObjectCreate();
- }
-
@Override
public List<SubnetConfig> getSubnetsConfigList() {
return new ArrayList<SubnetConfig>(subnetsConfigList.values());
return swList;
}
- private void updateConfig(SubnetConfig conf, boolean add) {
+ private Status updateConfig(SubnetConfig conf, boolean add) {
if (add) {
- subnetsConfigList.put(conf.getName(), conf);
+ if(subnetsConfigList.putIfAbsent(conf.getName(), conf) != null) {
+ String msg = "Cluster conflict: Subnet with name " + conf.getName() + "already exists.";
+ return new Status(StatusCode.CONFLICT, msg);
+ }
} else {
subnetsConfigList.remove(conf.getName());
}
+ return new Status(StatusCode.SUCCESS);
}
- private void updateDatabase(SubnetConfig conf, boolean add) {
- Subnet subnet = subnets.get(conf.getIPnum());
+ private Status updateDatabase(SubnetConfig conf, boolean add) {
if (add) {
- if (subnet == null) {
+ Subnet subnetCurr = subnets.get(conf.getIPnum());
+ Subnet subnet;
+ if (subnetCurr == null) {
subnet = new Subnet(conf);
+ } else {
+ subnet = subnetCurr.clone();
}
// In case of API3 call we may receive the ports along with the
// subnet creation
Set<NodeConnector> sp = conf.getSubnetNodeConnectors();
subnet.addNodeConnectors(sp);
}
- subnets.put(conf.getIPnum(), subnet);
- } else { // This is the deletion of the whole subnet
- if (subnet == null) {
- return;
+ boolean result = false;
+ if(subnetCurr == null) {
+ if(subnets.putIfAbsent(conf.getIPnum(), subnet) == null) {
+ result = true;
+ }
+ } else {
+ result = subnets.replace(conf.getIPnum(), subnetCurr, subnet);
+ }
+ if(!result) {
+ String msg = "Cluster conflict: Conflict while adding the subnet " + conf.getIPnum();
+ return new Status(StatusCode.CONFLICT, msg);
}
+ } else { // This is the deletion of the whole subnet
subnets.remove(conf.getIPnum());
}
+ return new Status(StatusCode.SUCCESS);
}
private Status semanticCheck(SubnetConfig conf) {
Subnet newSubnet = new Subnet(conf);
Set<InetAddress> IPs = subnets.keySet();
if (IPs == null) {
- return new Status(StatusCode.SUCCESS, null);
+ return new Status(StatusCode.SUCCESS);
}
for (InetAddress i : IPs) {
Subnet existingSubnet = subnets.get(i);
if ((existingSubnet != null)
&& !existingSubnet.isMutualExclusive(newSubnet)) {
- return new Status(StatusCode.CONFLICT, null);
+ return new Status(StatusCode.CONFLICT);
}
}
- return new Status(StatusCode.SUCCESS, null);
+ return new Status(StatusCode.SUCCESS);
}
private Status addRemoveSubnet(SubnetConfig conf, boolean add) {
return rc;
}
}
- // Update Configuration
- updateConfig(conf, add);
// Update Database
- updateDatabase(conf, add);
+ Status rc = updateDatabase(conf, add);
+
+ if (rc.isSuccess()) {
+ // Update Configuration
+ rc = updateConfig(conf, add);
+ if(!rc.isSuccess()) {
+ updateDatabase(conf, (!add));
+ }
+ }
- return new Status(StatusCode.SUCCESS, null);
+ return rc;
}
/**
@Override
public Status addPortsToSubnet(String name, String switchPorts) {
- // Update Configuration
- SubnetConfig conf = subnetsConfigList.get(name);
- if (conf == null) {
+ SubnetConfig confCurr = subnetsConfigList.get(name);
+ if (confCurr == null) {
return new Status(StatusCode.NOTFOUND, "Subnet does not exist");
}
- if (!conf.isValidSwitchPort(switchPorts)) {
+ if (!confCurr.isValidSwitchPort(switchPorts)) {
return new Status(StatusCode.BADREQUEST, "Invalid switchports");
}
- conf.addNodeConnectors(switchPorts);
- subnetsConfigList.put(name, conf);
+ Subnet subCurr = subnets.get(confCurr.getIPnum());
+ if (subCurr == null) {
+ log.debug("Cluster conflict: Subnet entry {} is not present in the subnets cache.", confCurr.getIPnum());
+ return new Status(StatusCode.NOTFOUND, "Subnet does not exist");
+ }
// Update Database
- Subnet sub = subnets.get(conf.getIPnum());
- Set<NodeConnector> sp = conf.getNodeConnectors(switchPorts);
+ Subnet sub = subCurr.clone();
+ Set<NodeConnector> sp = confCurr.getNodeConnectors(switchPorts);
sub.addNodeConnectors(sp);
- subnets.put(conf.getIPnum(), sub);
- return new Status(StatusCode.SUCCESS, null);
+ boolean subnetsReplace = subnets.replace(confCurr.getIPnum(), subCurr, sub);
+ if (!subnetsReplace) {
+ String msg = "Cluster conflict: Conflict while adding ports to the subnet " + name;
+ return new Status(StatusCode.CONFLICT, msg);
+ }
+
+ // Update Configuration
+ SubnetConfig conf = confCurr.clone();
+ conf.addNodeConnectors(switchPorts);
+ boolean result = subnetsConfigList.replace(name, confCurr, conf);
+ if (!result) {
+ // TODO: recovery using Transactionality
+ String msg = "Cluster conflict: Conflict while adding ports to the subnet " + name;
+ return new Status(StatusCode.CONFLICT, msg);
+ }
+
+ return new Status(StatusCode.SUCCESS);
}
@Override
public Status removePortsFromSubnet(String name, String switchPorts) {
- // Update Configuration
- SubnetConfig conf = subnetsConfigList.get(name);
- if (conf == null) {
+ SubnetConfig confCurr = subnetsConfigList.get(name);
+ if (confCurr == null) {
+ return new Status(StatusCode.NOTFOUND, "Subnet does not exist");
+ }
+
+ Subnet subCurr = subnets.get(confCurr.getIPnum());
+ if (subCurr == null) {
+ log.debug("Cluster conflict: Subnet entry {} is not present in the subnets cache.", confCurr.getIPnum());
return new Status(StatusCode.NOTFOUND, "Subnet does not exist");
}
- conf.removeNodeConnectors(switchPorts);
- subnetsConfigList.put(name, conf);
// Update Database
- Subnet sub = subnets.get(conf.getIPnum());
- Set<NodeConnector> sp = conf.getNodeConnectors(switchPorts);
+ Subnet sub = subCurr.clone();
+ Set<NodeConnector> sp = confCurr.getNodeConnectors(switchPorts);
sub.deleteNodeConnectors(sp);
- subnets.put(conf.getIPnum(), sub);
- return new Status(StatusCode.SUCCESS, null);
+ boolean subnetsReplace = subnets.replace(confCurr.getIPnum(), subCurr, sub);
+ if (!subnetsReplace) {
+ String msg = "Cluster conflict: Conflict while removing ports from the subnet " + name;
+ return new Status(StatusCode.CONFLICT, msg);
+ }
+
+ // Update Configuration
+ SubnetConfig conf = confCurr.clone();
+ conf.removeNodeConnectors(switchPorts);
+ boolean result = subnetsConfigList.replace(name, confCurr, conf);
+ if (!result) {
+ // TODO: recovery using Transactionality
+ String msg = "Cluster conflict: Conflict while removing ports from " + conf;
+ return new Status(StatusCode.CONFLICT, msg);
+ }
+
+ return new Status(StatusCode.SUCCESS);
}
public String getContainerName() {
return;
}
+ SwitchConfig sc = nodeConfigList.get(cfgObject.getNodeId());
+ if (sc == null) {
+ if (nodeConfigList.putIfAbsent(cfgObject.getNodeId(), cfgObject) != null) {
+ return;
+ }
+ } else {
+ if (!nodeConfigList.replace(cfgObject.getNodeId(), sc, cfgObject)) {
+ return;
+ }
+ }
+
boolean modeChange = false;
- SwitchConfig sc = nodeConfigList.get(cfgObject.getNodeId());
if ((sc == null) || !cfgObject.getMode().equals(sc.getMode())) {
modeChange = true;
}
- nodeConfigList.put(cfgObject.getNodeId(), cfgObject);
try {
String nodeId = cfgObject.getNodeId();
Node node = Node.fromString(nodeId);
- Map<String, Property> propMap;
- if (nodeProps.get(node) != null) {
- propMap = nodeProps.get(node);
- } else {
- propMap = new HashMap<String, Property>();
+ Map<String, Property> propMapCurr = nodeProps.get(node);
+ Map<String, Property> propMap = new HashMap<String, Property>();
+ if (propMapCurr != null) {
+ for (String s : propMapCurr.keySet()) {
+ propMap.put(s, propMapCurr.get(s).clone());
+ }
}
Property desc = new Description(cfgObject.getNodeDescription());
propMap.put(desc.getName(), desc);
Property tier = new Tier(Integer.parseInt(cfgObject.getTier()));
propMap.put(tier.getName(), tier);
- addNodeProps(node, propMap);
- log.info("Set Node {}'s Mode to {}", nodeId,
- cfgObject.getMode());
+ if (propMapCurr == null) {
+ if (nodeProps.putIfAbsent(node, propMap) != null) {
+ // TODO rollback using Transactionality
+ return;
+ }
+ } else {
+ if (!nodeProps.replace(node, propMapCurr, propMap)) {
+ // TODO rollback using Transactionality
+ return;
+ }
+ }
+
+ log.info("Set Node {}'s Mode to {}", nodeId, cfgObject.getMode());
if (modeChange) {
notifyModeChange(node, cfgObject.isProactive());
retS = objWriter.write(new ConcurrentHashMap<String, SubnetConfig>(
subnetsConfigList), subnetFileName);
- retP = objWriter.write(new ConcurrentHashMap<Integer, SpanConfig>(
+ retP = objWriter.write(new ConcurrentHashMap<SpanConfig, SpanConfig>(
spanConfigList), spanFileName);
retS = objWriter.write(new ConcurrentHashMap<String, SwitchConfig>(
nodeConfigList), switchConfigFileName);
}
// Presence check
- if (spanConfigList.containsKey(conf.hashCode())) {
+ if (spanConfigList.containsKey(conf)) {
return new Status(StatusCode.CONFLICT, "Same span config exists");
}
- // Update database and notify clients
- addSpanPorts(conf.getNode(), conf.getPortArrayList());
-
// Update configuration
- spanConfigList.put(conf.hashCode(), conf);
+ if (spanConfigList.putIfAbsent(conf, conf) == null) {
+ // Update database and notify clients
+ addSpanPorts(conf.getNode(), conf.getPortArrayList());
+ }
- return new Status(StatusCode.SUCCESS, null);
+ return new Status(StatusCode.SUCCESS);
}
@Override
removeSpanPorts(conf.getNode(), conf.getPortArrayList());
// Update configuration
- spanConfigList.remove(conf.hashCode());
+ spanConfigList.remove(conf);
- return new Status(StatusCode.SUCCESS, null);
+ return new Status(StatusCode.SUCCESS);
}
@Override
return;
}
- Map<String, Property> propMap;
- if (nodeProps.get(node) != null) {
- propMap = nodeProps.get(node);
- } else {
- propMap = new HashMap<String, Property>();
+ Map<String, Property> propMapCurr = nodeProps.get(node);
+ Map<String, Property> propMap = new HashMap<String, Property>();
+ if (propMapCurr != null) {
+ for (String s : propMapCurr.keySet()) {
+ propMap.put(s, propMapCurr.get(s).clone());
+ }
}
// copy node properties from plugin
String nodeId = node.toString();
for (SwitchConfig conf : nodeConfigList.values()) {
if (conf.getNodeId().equals(nodeId)) {
- Property description = new Description(
- conf.getNodeDescription());
+ Property description = new Description(conf.getNodeDescription());
propMap.put(description.getName(), description);
Property tier = new Tier(Integer.parseInt(conf.getTier()));
propMap.put(tier.getName(), tier);
}
}
}
- addNodeProps(node, propMap);
+
+ boolean result = false;
+ if (propMapCurr == null) {
+ if (nodeProps.putIfAbsent(node, propMap) == null) {
+ result = true;
+ }
+ } else {
+ result = nodeProps.replace(node, propMapCurr, propMap);
+ }
+
+ if (!result) {
+ log.debug(
+ "Cluster conflict: Conflict while adding the node properties. Node: {} Properties: {}",
+ node.getID(), props);
+ addNodeProps(node, propMap);
+ }
// check if span ports are configed
addSpanPorts(node);
return;
}
- Map<String, Property> propMap;
- if (nodeProps.get(node) != null) {
- propMap = nodeProps.get(node);
- } else {
- propMap = new HashMap<String, Property>();
+ Map<String, Property> propMapCurr = nodeProps.get(node);
+ Map<String, Property> propMap = new HashMap<String, Property>();
+ if (propMapCurr != null) {
+ for (String s : propMapCurr.keySet()) {
+ propMap.put(s, propMapCurr.get(s).clone());
+ }
}
// copy node properties from plugin
propMap.put(prop.getName(), prop);
}
}
- addNodeProps(node, propMap);
+
+ if (propMapCurr == null) {
+ if (nodeProps.putIfAbsent(node, propMap) != null) {
+ log.debug("Cluster conflict: Conflict while updating the node. Node: {} Properties: {}",
+ node.getID(), props);
+ addNodeProps(node, propMap);
+ }
+ } else {
+ if (!nodeProps.replace(node, propMapCurr, propMap)) {
+ log.debug("Cluster conflict: Conflict while updating the node. Node: {} Properties: {}",
+ node.getID(), props);
+ addNodeProps(node, propMap);
+ }
+ }
/* notify node listeners */
notifyNode(node, UpdateType.CHANGED, propMap);
@Override
public void setNodeProp(Node node, Property prop) {
- /* Get a copy of the property map */
- Map<String, Property> propMap = getNodeProps(node);
- if (propMap == null) {
- return;
- }
- propMap.put(prop.getName(), prop);
- this.nodeProps.put(node, propMap);
+ for (int i = 0; i <= REPLACE_RETRY; i++) {
+ /* Get a copy of the property map */
+ Map<String, Property> propMapCurr = getNodeProps(node);
+ if (propMapCurr == null) {
+ return;
+ }
+
+ Map<String, Property> propMap = new HashMap<String, Property>();
+ for (String s : propMapCurr.keySet()) {
+ propMap.put(s, propMapCurr.get(s).clone());
+ }
+
+ propMap.put(prop.getName(), prop);
+
+ if (nodeProps.replace(node, propMapCurr, propMap)) {
+ return;
+ }
+ if (!propMapCurr.get(prop.getName()).equals(nodeProps.get(node).get(prop.getName()))) {
+ log.warn("Cluster conflict: Unable to add property {} to node {}.", prop.getName(), node.getID());
+ return;
+ }
+ }
+ log.warn("Cluster conflict: Unable to add property {} to node {}.", prop.getName(), node.getID());
}
@Override
public Status removeNodeProp(Node node, String propName) {
- Map<String, Property> propMap = getNodeProps(node);
- if (propMap != null) {
- propMap.remove(propName);
- this.nodeProps.put(node, propMap);
+ for (int i = 0; i <= REPLACE_RETRY; i++) {
+ Map<String, Property> propMapCurr = getNodeProps(node);
+ if (propMapCurr != null) {
+ if (!propMapCurr.containsKey(propName)) {
+ return new Status(StatusCode.SUCCESS);
+ }
+ Map<String, Property> propMap = new HashMap<String, Property>();
+ for (String s : propMapCurr.keySet()) {
+ propMap.put(s, propMapCurr.get(s).clone());
+ }
+
+ propMap.remove(propName);
+ if (nodeProps.replace(node, propMapCurr, propMap)) {
+ return new Status(StatusCode.SUCCESS);
+ }
+ if (!propMapCurr.get(propName).equals(nodeProps.get(node).get(propName))) {
+ String msg = "Cluster conflict: Unable to remove property " + propName + " for node "
+ + node.getID();
+ return new Status(StatusCode.CONFLICT, msg);
+ }
+
+ } else {
+ return new Status(StatusCode.SUCCESS);
+ }
}
- return new Status(StatusCode.SUCCESS, null);
+ String msg = "Cluster conflict: Unable to remove property " + propName + " for node " + node.getID();
+ return new Status(StatusCode.CONFLICT, msg);
}
@Override
public Status removeNodeAllProps(Node node) {
this.nodeProps.remove(node);
- return new Status(StatusCode.SUCCESS, null);
+ return new Status(StatusCode.SUCCESS);
}
@Override
@Override
public Status addNodeConnectorProp(NodeConnector nodeConnector,
Property prop) {
- Map<String, Property> propMap = getNodeConnectorProps(nodeConnector);
+ Map<String, Property> propMapCurr = getNodeConnectorProps(nodeConnector);
+ Map<String, Property> propMap = new HashMap<String, Property>();
- if (propMap == null) {
- propMap = new HashMap<String, Property>();
+ if (propMapCurr != null) {
+ for (String s : propMapCurr.keySet()) {
+ propMap.put(s, propMapCurr.get(s).clone());
+ }
}
+ String msg = "Cluster conflict: Unable to add NodeConnector Property.";
// Just add the nodeConnector if prop is not available (in a non-default
// container)
if (prop == null) {
- nodeConnectorProps.put(nodeConnector, propMap);
- return new Status(StatusCode.SUCCESS, null);
+ if (propMapCurr == null) {
+ if (nodeConnectorProps.putIfAbsent(nodeConnector, propMap) != null) {
+ return new Status(StatusCode.CONFLICT, msg);
+ }
+ } else {
+ if (!nodeConnectorProps.replace(nodeConnector, propMapCurr, propMap)) {
+ return new Status(StatusCode.CONFLICT, msg);
+ }
+ }
+ return new Status(StatusCode.SUCCESS);
}
propMap.put(prop.getName(), prop);
- nodeConnectorProps.put(nodeConnector, propMap);
+ if (propMapCurr == null) {
+ if (nodeConnectorProps.putIfAbsent(nodeConnector, propMap) != null) {
+ return new Status(StatusCode.CONFLICT, msg);
+ }
+ } else {
+ if (!nodeConnectorProps.replace(nodeConnector, propMapCurr, propMap)) {
+ return new Status(StatusCode.CONFLICT, msg);
+ }
+ }
if (prop.getName().equals(Name.NamePropName)) {
if (nodeConnectorNames != null) {
Node node = nodeConnector.getNode();
- Map<String, NodeConnector> map = nodeConnectorNames.get(node);
- if (map == null) {
- map = new HashMap<String, NodeConnector>();
+ Map<String, NodeConnector> mapCurr = nodeConnectorNames.get(node);
+ Map<String, NodeConnector> map = new HashMap<String, NodeConnector>();
+ if (mapCurr != null) {
+ for (String s : mapCurr.keySet()) {
+ try {
+ map.put(s, new NodeConnector(mapCurr.get(s)));
+ } catch (ConstructionException e) {
+ e.printStackTrace();
+ }
+ }
}
map.put(((Name) prop).getValue(), nodeConnector);
- nodeConnectorNames.put(node, map);
+ if (mapCurr == null) {
+ if (nodeConnectorNames.putIfAbsent(node, map) != null) {
+ // TODO: recovery using Transactionality
+ return new Status(StatusCode.CONFLICT, msg);
+ }
+ } else {
+ if (!nodeConnectorNames.replace(node, mapCurr, map)) {
+ // TODO: recovery using Transactionality
+ return new Status(StatusCode.CONFLICT, msg);
+ }
+ }
}
}
- return new Status(StatusCode.SUCCESS, null);
+ return new Status(StatusCode.SUCCESS);
}
/**
* @return success or failed reason
*/
@Override
- public Status removeNodeConnectorProp(NodeConnector nodeConnector,
- String propName) {
- Map<String, Property> propMap = getNodeConnectorProps(nodeConnector);
+ public Status removeNodeConnectorProp(NodeConnector nodeConnector, String propName) {
+ Map<String, Property> propMapCurr = getNodeConnectorProps(nodeConnector);
- if (propMap == null) {
+ if (propMapCurr == null) {
/* Nothing to remove */
- return new Status(StatusCode.SUCCESS, null);
+ return new Status(StatusCode.SUCCESS);
+ }
+
+ Map<String, Property> propMap = new HashMap<String, Property>();
+
+ for (String s : propMapCurr.keySet()) {
+ propMap.put(s, propMapCurr.get(s).clone());
}
propMap.remove(propName);
- nodeConnectorProps.put(nodeConnector, propMap);
+ boolean result = nodeConnectorProps.replace(nodeConnector, propMapCurr, propMap);
+ String msg = "Cluster conflict: Unable to remove NodeConnector property.";
+ if (!result) {
+ return new Status(StatusCode.CONFLICT, msg);
+ }
- if (nodeConnectorNames != null) {
- Name name = ((Name) getNodeConnectorProp(nodeConnector,
- Name.NamePropName));
- if (name != null) {
- Node node = nodeConnector.getNode();
- Map<String, NodeConnector> map = nodeConnectorNames.get(node);
- if (map != null) {
- map.remove(name.getValue());
- nodeConnectorNames.put(node, map);
+ if (propName.equals(Name.NamePropName)) {
+ if (nodeConnectorNames != null) {
+ Name name = ((Name) getNodeConnectorProp(nodeConnector, Name.NamePropName));
+ if (name != null) {
+ Node node = nodeConnector.getNode();
+ Map<String, NodeConnector> mapCurr = nodeConnectorNames.get(node);
+ if (mapCurr != null) {
+ Map<String, NodeConnector> map = new HashMap<String, NodeConnector>();
+ for (String s : mapCurr.keySet()) {
+ try {
+ map.put(s, new NodeConnector(mapCurr.get(s)));
+ } catch (ConstructionException e) {
+ e.printStackTrace();
+ }
+ }
+ map.remove(name.getValue());
+ if (!nodeConnectorNames.replace(node, mapCurr, map)) {
+ // TODO: recovery using Transactionality
+ return new Status(StatusCode.CONFLICT, msg);
+ }
+ }
}
}
}
- return new Status(StatusCode.SUCCESS, null);
+ return new Status(StatusCode.SUCCESS);
}
/**
@Override
public Status removeNodeConnectorAllProps(NodeConnector nodeConnector) {
if (nodeConnectorNames != null) {
- Name name = ((Name) getNodeConnectorProp(nodeConnector,
- Name.NamePropName));
+ Name name = ((Name) getNodeConnectorProp(nodeConnector, Name.NamePropName));
if (name != null) {
Node node = nodeConnector.getNode();
- Map<String, NodeConnector> map = nodeConnectorNames.get(node);
- if (map != null) {
+ Map<String, NodeConnector> mapCurr = nodeConnectorNames.get(node);
+ if (mapCurr != null) {
+ Map<String, NodeConnector> map = new HashMap<String, NodeConnector>();
+ for (String s : mapCurr.keySet()) {
+ try {
+ map.put(s, new NodeConnector(mapCurr.get(s)));
+ } catch (ConstructionException e) {
+ e.printStackTrace();
+ }
+ }
map.remove(name.getValue());
- nodeConnectorNames.put(node, map);
+ if (!nodeConnectorNames.replace(node, mapCurr, map)) {
+ log.warn("Cluster conflict: Unable remove Name property of nodeconnector {}, skip.",
+ nodeConnector.getID());
+ }
}
+
}
}
nodeConnectorProps.remove(nodeConnector);
- return new Status(StatusCode.SUCCESS, null);
+ return new Status(StatusCode.SUCCESS);
}
/**
}
Map<Node, Map<String, Property>> nodeProp = this.inventoryService.getNodeProps();
- for(Map.Entry<Node, Map<String, Property>> entry : nodeProp.entrySet()) {
+ for (Map.Entry<Node, Map<String, Property>> entry : nodeProp.entrySet()) {
Node node = entry.getKey();
- log.debug("getInventories: {} added for container {}",
- new Object[] { node, containerName });
+ log.debug("getInventories: {} added for container {}", new Object[] { node, containerName });
Map<String, Property> propMap = entry.getValue();
Set<Property> props = new HashSet<Property>();
- for(Property property : propMap.values()) {
+ for (Property property : propMap.values()) {
props.add(property);
}
addNode(node, props);
}
Map<NodeConnector, Map<String, Property>> nodeConnectorProp = this.inventoryService.getNodeConnectorProps();
- for(Map.Entry<NodeConnector, Map<String, Property>> entry : nodeConnectorProp.entrySet()) {
+ for (Map.Entry<NodeConnector, Map<String, Property>> entry : nodeConnectorProp.entrySet()) {
Map<String, Property> propMap = entry.getValue();
- for(Property property : propMap.values()) {
+ for (Property property : propMap.values()) {
addNodeConnectorProp(entry.getKey(), property);
}
}
@Test
public void testSwitchManagerAddRemoveSubnet() {
SwitchManagerImpl switchmgr = new SwitchManagerImpl();
- switchmgr.nonClusterObjectCreate();
+ switchmgr.startUp();
ArrayList<String> portList = new ArrayList<String>();
portList.add("1/1");
@Test
public void testSwitchManagerNodeConnectors() {
SwitchManagerImpl switchmgr = new SwitchManagerImpl();
- switchmgr.nonClusterObjectCreate();
+ switchmgr.startUp();
State state;
Bandwidth bw;
package org.opendaylight.controller.switchmanager.internal;
-import java.net.InetAddress;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.ops4j.pax.exam.CoreOptions.junitBundles;
+import static org.ops4j.pax.exam.CoreOptions.mavenBundle;
+import static org.ops4j.pax.exam.CoreOptions.options;
+import static org.ops4j.pax.exam.CoreOptions.systemPackages;
+import static org.ops4j.pax.exam.CoreOptions.systemProperty;
+
import java.net.UnknownHostException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
import java.util.Map;
-import java.util.Set;
-import java.util.Map.Entry;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.osgi.framework.ServiceReference;
-import org.osgi.framework.Bundle;
import javax.inject.Inject;
-import org.eclipse.osgi.framework.console.CommandProvider;
import org.junit.Assert;
-import org.junit.Test;
import org.junit.Before;
-import org.junit.After;
+import org.junit.Test;
import org.junit.runner.RunWith;
import org.opendaylight.controller.sal.core.Actions;
import org.opendaylight.controller.sal.core.Bandwidth;
import org.opendaylight.controller.sal.core.Buffers;
import org.opendaylight.controller.sal.core.Capabilities;
+import org.opendaylight.controller.sal.core.Capabilities.CapabilitiesType;
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.Property;
import org.opendaylight.controller.sal.core.State;
import org.opendaylight.controller.sal.core.TimeStamp;
-import org.opendaylight.controller.sal.core.UpdateType;
-import org.opendaylight.controller.sal.core.Property;
-import org.opendaylight.controller.sal.core.Capabilities.CapabilitiesType;
-import org.opendaylight.controller.sal.utils.NodeConnectorCreator;
-import org.opendaylight.controller.sal.utils.NodeCreator;
-import org.opendaylight.controller.sal.utils.Status;
-import org.opendaylight.controller.sal.inventory.IListenInventoryUpdates;
-import org.opendaylight.controller.switchmanager.*;
-import org.opendaylight.controller.configuration.IConfigurationContainerAware;
-import org.opendaylight.controller.clustering.services.ICacheUpdateAware;
import org.opendaylight.controller.switchmanager.ISwitchManager;
-
-import org.ops4j.pax.exam.junit.PaxExam;
-import org.ops4j.pax.exam.util.Filter;
-import org.osgi.framework.BundleContext;
-import static org.junit.Assert.*;
-import org.ops4j.pax.exam.junit.Configuration;
-import static org.ops4j.pax.exam.CoreOptions.*;
-
import org.ops4j.pax.exam.Option;
+import org.ops4j.pax.exam.junit.Configuration;
+import org.ops4j.pax.exam.junit.PaxExam;
import org.ops4j.pax.exam.util.PathUtils;
-import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy;
-import org.ops4j.pax.exam.spi.reactors.PerClass;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
@RunWith(PaxExam.class)
public class SwitchManagerIT {
- private Logger log = LoggerFactory.getLogger(SwitchManagerIT.class);
+ private final Logger log = LoggerFactory.getLogger(SwitchManagerIT.class);
// get the OSGI bundle context
@Inject
private BundleContext bc;
.versionAsInProject(),
mavenBundle("ch.qos.logback", "logback-classic")
.versionAsInProject(),
-
- mavenBundle("org.opendaylight.controller", "switchmanager")
- .versionAsInProject(),
- mavenBundle("org.opendaylight.controller",
- "switchmanager.implementation").versionAsInProject(),
- mavenBundle("org.opendaylight.controller", "sal")
+ mavenBundle("org.opendaylight.controller", "clustering.stub")
.versionAsInProject(),
- mavenBundle("org.opendaylight.controller", "sal.implementation")
+ mavenBundle("org.opendaylight.controller", "configuration")
.versionAsInProject(),
+ mavenBundle("org.opendaylight.controller",
+ "configuration.implementation").versionAsInProject(),
mavenBundle("org.opendaylight.controller", "containermanager")
.versionAsInProject(),
mavenBundle("org.opendaylight.controller",
"containermanager.implementation").versionAsInProject(),
mavenBundle("org.opendaylight.controller",
"clustering.services").versionAsInProject(),
- mavenBundle("org.opendaylight.controller", "clustering.stub")
+ mavenBundle("org.opendaylight.controller", "sal")
.versionAsInProject(),
- mavenBundle("org.opendaylight.controller", "configuration")
+ mavenBundle("org.opendaylight.controller", "sal.implementation")
.versionAsInProject(),
mavenBundle("org.opendaylight.controller",
- "configuration.implementation").versionAsInProject(),
+ "protocol_plugins.stub").versionAsInProject(),
+ mavenBundle("org.opendaylight.controller", "switchmanager")
+ .versionAsInProject(),
mavenBundle("org.opendaylight.controller",
- "protocol_plugins.stub").versionAsInProject(),
+ "switchmanager.implementation").versionAsInProject(),
mavenBundle("org.jboss.spec.javax.transaction",
"jboss-transaction-api_1.1_spec").versionAsInProject(),
mavenBundle("org.apache.commons", "commons-lang3")
Assert.assertTrue(this.switchManager.getNodeProp(node,
Capabilities.CapabilitiesPropName).equals(
- new Capabilities((int) 3)));
+ new Capabilities(3)));
Assert.assertTrue(this.switchManager.getNodeProp(node,
- Actions.ActionsPropName).equals(new Actions((int) 2)));
+ Actions.ActionsPropName).equals(new Actions(2)));
Assert.assertTrue(this.switchManager.getNodeProp(node,
- Buffers.BuffersPropName).equals(new Buffers((int) 1)));
+ Buffers.BuffersPropName).equals(new Buffers(1)));
Assert.assertTrue(this.switchManager.getNodeProp(node,
TimeStamp.TimeStampPropName).equals(
new TimeStamp(100000L, "connectedSince")));
import java.util.Set;
import java.util.TreeMap;
import java.util.concurrent.ConcurrentMap;
+
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.codehaus.jackson.map.ObjectMapper;
-import org.opendaylight.controller.web.DaylightWebUtil;
-import org.opendaylight.controller.web.IDaylightWeb;
-import org.springframework.stereotype.Controller;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestMethod;
-import org.springframework.web.bind.annotation.RequestParam;
-import org.springframework.web.bind.annotation.ResponseBody;
import org.opendaylight.controller.forwarding.staticrouting.IForwardingStaticRouting;
import org.opendaylight.controller.forwarding.staticrouting.StaticRouteConfig;
import org.opendaylight.controller.sal.authorization.Privilege;
import org.opendaylight.controller.switchmanager.SubnetConfig;
import org.opendaylight.controller.switchmanager.Switch;
import org.opendaylight.controller.switchmanager.SwitchConfig;
+import org.opendaylight.controller.web.DaylightWebUtil;
+import org.opendaylight.controller.web.IDaylightWeb;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.ResponseBody;
import com.google.gson.Gson;
flow.setNode(node);
Status result = new Status(StatusCode.BADREQUEST, "Invalid request");
if (action.equals("add")) {
- result = frm.addStaticFlow(flow, false);
+ result = frm.addStaticFlow(flow);
}
return (result.isSuccess()) ? StatusCode.SUCCESS.toString() : result
@Override
public void writeTo(ByteBuffer data) {
super.writeTo(data);
- data.put(this.dataLayerAddress);
+ data.put(this.dataLayerAddress, 0, OFPhysicalPort.OFP_ETH_ALEN);
data.putInt(0);
data.putShort((short) 0);
}
}
return true;
}
-}
\ No newline at end of file
+}