return null;
}
- private void blankTransaction() {
+ private synchronized void blankTransaction() {
// create transaction
ObjectName tx = configRegistry.beginConfig();
CommitStatus commitStatus = configRegistry.commitConfig(tx);
@Override
public final boolean isModuleImplementingServiceInterface(Class<? extends ${abstractServiceInterfaceType}> serviceInterface) {
- return serviceIfcs.contains(serviceInterface);
+ for (Class<?> ifc: serviceIfcs) {
+ if (serviceInterface.isAssignableFrom(ifc)){
+ return true;
+ }
+ }
+ return false;
}
@Override
// available if source level is 5.0
if (c.getID() == 1610613329)
continue;
+ if (c.getID() == 1610613328) // 'for each' statements are only available if source level is 5.0
+ continue;
fail("Error in generated source code " + file + ":"
- + c.getSourceLineNumber() + " " + c.toString());
+ + c.getSourceLineNumber() + " id: " + c.getID() + " message:" + c.toString());
}
ASTVisitor visitor = verifiers.get(file.getName());
}
} else if (action instanceof OutputAction) {
Integer length = ((OutputAction) action).getMaxLength();
- List<Uri> outputnodeconnector = ((OutputAction) action).getOutputNodeConnector();
+ Uri outputnodeconnector = ((OutputAction) action).getOutputNodeConnector();
if (length < 0 || length > 65294) {
logger.error("OutputAction: MaxLength is not valid");
return false;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowAdded;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowRemoved;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowUpdated;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.NodeErrorNotification;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.NodeExperimenterErrorNotification;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.NodeFlow;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.RemoveFlowInputBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowListener;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SwitchFlowRemoved;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.UpdateFlowInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.flow.update.UpdatedFlowBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-public class FlowConsumerImpl {
+public class FlowConsumerImpl implements IForwardingRulesManager {
protected static final Logger logger = LoggerFactory.getLogger(FlowConsumerImpl.class);
- private FlowEventListener flowEventListener = new FlowEventListener();
+ private final FlowEventListener flowEventListener = new FlowEventListener();
private Registration<NotificationListener> listener1Reg;
private SalFlowService flowService;
// private FlowDataListener listener;
// updating the staticflow cache
Integer ordinal = staticFlowsOrdinal.get(0);
staticFlowsOrdinal.put(0, ++ordinal);
- staticFlows.put(ordinal, (Flow) dataObject);
+ staticFlows.put(ordinal, dataObject);
// We send flow to the sounthbound plugin
flowService.addFlow(input.build());
updateLocalDatabase((NodeFlow) dataObject, false);
}
+ /**
+ * Update flow to the southbound plugin and our internal database
+ *
+ * @param path
+ * @param dataObject
+ */
+ private void updateFlow(InstanceIdentifier<?> path, Flow dataObject) {
+
+ UpdateFlowInputBuilder input = new UpdateFlowInputBuilder();
+ UpdatedFlowBuilder updatedflowbuilder = new UpdatedFlowBuilder();
+ updatedflowbuilder.fieldsFrom(dataObject);
+ input.setUpdatedFlow(updatedflowbuilder.build());
+
+ // updating the staticflow cache
+ Integer ordinal = staticFlowsOrdinal.get(0);
+ staticFlowsOrdinal.put(0, ++ordinal);
+ staticFlows.put(ordinal, dataObject);
+
+ // We send flow to the sounthbound plugin
+ flowService.updateFlow(input.build());
+ updateLocalDatabase((NodeFlow) dataObject, true);
+ }
+
@SuppressWarnings("unchecked")
private void commitToPlugin(internalTransaction transaction) {
for (Entry<InstanceIdentifier<?>, Flow> entry : transaction.additions.entrySet()) {
for (@SuppressWarnings("unused")
Entry<InstanceIdentifier<?>, Flow> entry : transaction.updates.entrySet()) {
System.out.println("Coming update cc in FlowDatacommitHandler");
- // updateFlow(entry.getKey(),entry.getValue());
+ updateFlow(entry.getKey(), entry.getValue());
}
for (Entry<InstanceIdentifier<?>, Flow> entry : transaction.removals.entrySet()) {
logger.error(error);
return;
}
- if (originalSwView.containsKey((FlowKey) entry)) {
+ if (originalSwView.containsKey(entry)) {
logger.warn("Operation Rejected: A flow with same match and priority exists on the target node");
logger.trace("Aborting to install {}", entry);
continue;
public void onFlowUpdated(FlowUpdated notification) {
updatedFlows.add(notification);
}
-
+
@Override
public void onSwitchFlowRemoved(SwitchFlowRemoved notification) {
- //TODO
+ // TODO
+ }
+
+ @Override
+ public void onNodeErrorNotification(NodeErrorNotification notification) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void onNodeExperimenterErrorNotification(
+ NodeExperimenterErrorNotification notification) {
+ // TODO Auto-generated method stub
+
};
}
FlowConsumerImpl.originalSwView.put((FlowKey) entry, (Flow) entry);
installedSwView.put((FlowKey) entry, (Flow) entry);
} else {
- originalSwView.remove((Flow) entry);
- installedSwView.remove((FlowKey) entry);
+ originalSwView.remove(entry);
+ installedSwView.remove(entry);
+
+ }
+ }
+ @Override
+ public List<DataObject> get() {
+
+ List<DataObject> orderedList = new ArrayList<DataObject>();
+ ConcurrentMap<Integer, Flow> flowMap = staticFlows;
+ int maxKey = staticFlowsOrdinal.get(0).intValue();
+ for (int i = 0; i <= maxKey; i++) {
+ Flow entry = flowMap.get(i);
+ if (entry != null) {
+ orderedList.add(entry);
+ }
+ }
+ return orderedList;
+ }
+
+ @Override
+ public DataObject getWithName(String name, org.opendaylight.controller.sal.core.Node n) {
+ if (this instanceof FlowConsumerImpl) {
+ for (ConcurrentMap.Entry<Integer, Flow> flowEntry : staticFlows.entrySet()) {
+ Flow flow = flowEntry.getValue();
+ if (flow.getNode().equals(n) && flow.getFlowName().equals(name)) {
+
+ return flowEntry.getValue();
+ }
+ }
}
+ return null;
}
/*
if (add) {
nodeIndeces.add((Flow) entry);
} else {
- nodeIndeces.remove((Flow) entry);
+ nodeIndeces.remove(entry);
}
// Update cache across cluster
package org.opendaylight.controller.forwardingrulesmanager_mdsal.consumer.impl;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.EnumSet;
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 java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import org.opendaylight.controller.clustering.services.IClusterContainerServices;
import org.opendaylight.controller.clustering.services.IClusterServices;
import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler;
-import org.opendaylight.controller.md.sal.common.api.data.DataModification;
import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.DataModification;
import org.opendaylight.controller.sal.common.util.Rpcs;
import org.opendaylight.controller.sal.core.IContainer;
import org.opendaylight.controller.sal.core.Node;
import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.SalGroupListener;
import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.SalGroupService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.UpdateGroupInputBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.UpdateGroupOutput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.UpdateGroupOutputBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.group.update.UpdatedGroupBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupTypes.GroupType;
import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.Buckets;
import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.buckets.Bucket;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.meter.update.UpdatedMeterBuilder;
import org.opendaylight.yangtools.concepts.Registration;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.slf4j.LoggerFactory;
@SuppressWarnings("unused")
-public class GroupConsumerImpl {
+public class GroupConsumerImpl implements IForwardingRulesManager {
protected static final Logger logger = LoggerFactory.getLogger(GroupConsumerImpl.class);
- private GroupEventListener groupEventListener = new GroupEventListener();
+ private final GroupEventListener groupEventListener = new GroupEventListener();
private Registration<NotificationListener> groupListener;
private SalGroupService groupService;
private GroupDataCommitHandler commitHandler;
private IContainer container;
public GroupConsumerImpl() {
-
- InstanceIdentifier<? extends DataObject> path = InstanceIdentifier.builder().node(Groups.class).node(Group.class).toInstance();
+
+ InstanceIdentifier<? extends DataObject> path = InstanceIdentifier.builder().node(Groups.class)
+ .node(Group.class).toInstance();
groupService = FRMConsumerImpl.getProviderSession().getRpcService(SalGroupService.class);
clusterGroupContainerService = FRMConsumerImpl.getClusterContainerService();
clusterGroupContainerService.createCache("frm.nodeGroups",
EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL));
-
-//TODO for cluster mode
- /* clusterGroupContainerService.createCache(WORK_STATUS_CACHE,
- EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL, IClusterServices.cacheMode.ASYNC));
-
- clusterGroupContainerService.createCache(WORK_ORDER_CACHE,
- EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL, IClusterServices.cacheMode.ASYNC));*/
-
- } catch (CacheConfigException cce) {
+
+ // TODO for cluster mode
+ /*
+ * clusterGroupContainerService.createCache(WORK_STATUS_CACHE,
+ * EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL,
+ * IClusterServices.cacheMode.ASYNC));
+ *
+ * clusterGroupContainerService.createCache(WORK_ORDER_CACHE,
+ * EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL,
+ * IClusterServices.cacheMode.ASYNC));
+ */
+
+ } catch (CacheConfigException cce) {
logger.error("Group CacheConfigException");
return false;
-
+
} catch (CacheExistException cce) {
- logger.error(" Group CacheExistException");
+ logger.error(" Group CacheExistException");
}
-
+
return true;
}
-
+
private void nonClusterGroupObjectCreate() {
originalSwGroupView = new ConcurrentHashMap<GroupKey, Group>();
installedSwGroupView = new ConcurrentHashMap<GroupKey, Group>();
- nodeGroups = new ConcurrentHashMap<Node, List<Group>>();
+ nodeGroups = new ConcurrentHashMap<Node, List<Group>>();
inactiveGroups = new ConcurrentHashMap<GroupKey, Group>();
}
-
+
@SuppressWarnings({ "unchecked" })
private boolean retrieveGroupCaches() {
ConcurrentMap<?, ?> map;
logger.warn("Group: un-initialized clusterGroupContainerService, can't retrieve cache");
nonClusterGroupObjectCreate();
return false;
- }
+ }
map = clusterGroupContainerService.getCache("frm.originalSwGroupView");
if (map != null) {
logger.error("Group record does not exist");
return new Status(StatusCode.BADREQUEST, "Group record does not exist");
}
-
- if (!(group.getGroupType().getIntValue() >= GroupType.GroupAll.getIntValue() &&
- group.getGroupType().getIntValue() <= GroupType.GroupFf.getIntValue())) {
+
+ if (!(group.getGroupType().getIntValue() >= GroupType.GroupAll.getIntValue() && group.getGroupType()
+ .getIntValue() <= GroupType.GroupFf.getIntValue())) {
logger.error("Invalid Group type %d" + group.getGroupType().getIntValue());
- return new Status(StatusCode.BADREQUEST, "Invalid Group type");
+ return new Status(StatusCode.BADREQUEST, "Invalid Group type");
}
groupBuckets = group.getBuckets();
* @param dataObject
*/
private Status updateGroup(InstanceIdentifier<?> path, Group groupUpdateDataObject) {
- GroupKey groupKey = groupUpdateDataObject.getKey();
+ GroupKey groupKey = groupUpdateDataObject.getKey();
UpdatedGroupBuilder updateGroupBuilder = null;
-
+
Status groupOperationStatus = validateGroup(groupUpdateDataObject, FRMUtil.operation.UPDATE);
-
+
if (!groupOperationStatus.isSuccess()) {
logger.error("Group data object validation failed %s" + groupUpdateDataObject.getGroupName());
return groupOperationStatus;
}
-
+
if (originalSwGroupView.containsKey(groupKey)) {
originalSwGroupView.remove(groupKey);
originalSwGroupView.put(groupKey, groupUpdateDataObject);
}
-
+
if (groupUpdateDataObject.isInstall()) {
UpdateGroupInputBuilder groupData = new UpdateGroupInputBuilder();
updateGroupBuilder = new UpdatedGroupBuilder();
updateGroupBuilder.fieldsFrom(groupUpdateDataObject);
groupData.setUpdatedGroup(updateGroupBuilder.build());
- //TODO how to get original group and modified group.
-
+ // TODO how to get original group and modified group.
+
if (installedSwGroupView.containsKey(groupKey)) {
installedSwGroupView.remove(groupKey);
installedSwGroupView.put(groupKey, groupUpdateDataObject);
}
-
+
groupService.updateGroup(groupData.build());
}
-
+
return groupOperationStatus;
}
-
+
/**
* Adds Group to the southbound plugin and our internal database
*
return groupOperationStatus;
}
-
- private RpcResult<Void> commitToPlugin(internalTransaction transaction) {
- for(Entry<InstanceIdentifier<?>, Group> entry :transaction.additions.entrySet()) {
-
- if (!addGroup(entry.getKey(),entry.getValue()).isSuccess()) {
+
+ private RpcResult<Void> commitToPlugin(internalTransaction transaction) {
+ for (Entry<InstanceIdentifier<?>, Group> entry : transaction.additions.entrySet()) {
+
+ if (!addGroup(entry.getKey(), entry.getValue()).isSuccess()) {
transaction.additions.remove(entry.getKey());
return Rpcs.getRpcResult(false, null, null);
}
}
-
- for(Entry<InstanceIdentifier<?>, Group> entry :transaction.updates.entrySet()) {
-
- if (!updateGroup(entry.getKey(),entry.getValue()).isSuccess()) {
+
+ for (Entry<InstanceIdentifier<?>, Group> entry : transaction.updates.entrySet()) {
+
+ if (!updateGroup(entry.getKey(), entry.getValue()).isSuccess()) {
transaction.updates.remove(entry.getKey());
return Rpcs.getRpcResult(false, null, null);
}
}
-
- for(InstanceIdentifier<?> removal : transaction.removals) {
- // removeFlow(removal);
+
+ for (InstanceIdentifier<?> removal : transaction.removals) {
+ // removeFlow(removal);
}
return Rpcs.getRpcResult(true, null, null);
@SuppressWarnings("unchecked")
@Override
- public DataCommitTransaction<InstanceIdentifier<?>, DataObject> requestCommit(DataModification<InstanceIdentifier<?>, DataObject> modification) {
+ public DataCommitTransaction<InstanceIdentifier<?>, DataObject> requestCommit(
+ DataModification<InstanceIdentifier<?>, DataObject> modification) {
// We should verify transaction
System.out.println("Coming in GroupDatacommitHandler");
internalTransaction transaction = new internalTransaction(modification);
}
}
+
+ @Override
+ public List<DataObject> get() {
+
+ List<DataObject> orderedList = new ArrayList<DataObject>();
+ Collection<Group> groupList = originalSwGroupView.values();
+ for (Iterator<Group> iterator = groupList.iterator(); iterator.hasNext();) {
+ orderedList.add(iterator.next());
+ }
+ return orderedList;
+ }
+
+ @Override
+ public DataObject getWithName(String name, Node n) {
+
+ if (this instanceof GroupConsumerImpl) {
+ Collection<Group> groupList = originalSwGroupView.values();
+ for (Iterator<Group> iterator = groupList.iterator(); iterator.hasNext();) {
+ Group group = iterator.next();
+ if (group.getNode().equals(n) && group.getGroupName().equals(name)) {
+
+ return group;
+ }
+ }
+ }
+ return null;
+ }
}
--- /dev/null
+package org.opendaylight.controller.forwardingrulesmanager_mdsal.consumer.impl;
+
+import java.util.List;
+
+import org.opendaylight.controller.sal.core.Node;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+
+/**
+ * Interface that describes methods for accessing the flows database.
+ */
+public interface IForwardingRulesManager {
+
+ /**
+ * Returns the specifications of all the flows configured for all the
+ * switches on the current container
+ *
+ * @return the list of flow configurations present in the database
+ */
+ public List<DataObject> get();
+
+ /**
+ * Returns the specification of the flow configured for the given network
+ * node on the current container
+ *
+ * @param name
+ * the flow name
+ * @param n
+ * the network node identifier
+ * @return the {@code FlowConfig} object
+ */
+ public DataObject getWithName(String name, Node n);
+
+}
package org.opendaylight.controller.forwardingrulesmanager_mdsal.consumer.impl;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.EnumSet;
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 java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import org.opendaylight.controller.clustering.services.IClusterContainerServices;
import org.opendaylight.controller.clustering.services.IClusterServices;
import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler;
-import org.opendaylight.controller.md.sal.common.api.data.DataModification;
import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.DataModification;
import org.opendaylight.controller.sal.common.util.Rpcs;
import org.opendaylight.controller.sal.core.IContainer;
import org.opendaylight.controller.sal.core.Node;
import org.opendaylight.controller.sal.utils.Status;
import org.opendaylight.controller.sal.utils.StatusCode;
import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.config.rev131024.Meters;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.config.rev131024.meters.Meter;
import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.config.rev131024.meters.MeterKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.AddMeterInputBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.MeterAdded;
import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.band.type.band.type.Drop;
import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.band.type.band.type.DscpRemark;
import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.band.type.band.type.Experimenter;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.config.rev131024.meters.Meter;
import org.opendaylight.yangtools.concepts.Registration;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-public class MeterConsumerImpl {
+public class MeterConsumerImpl implements IForwardingRulesManager {
protected static final Logger logger = LoggerFactory.getLogger(MeterConsumerImpl.class);
- private MeterEventListener meterEventListener = new MeterEventListener();
+ private final MeterEventListener meterEventListener = new MeterEventListener();
private Registration<NotificationListener> meterListener;
private SalMeterService meterService;
private MeterDataCommitHandler commitHandler;
private IContainer container;
public MeterConsumerImpl() {
- InstanceIdentifier<? extends DataObject> path = InstanceIdentifier.builder().node(Meters.class).node(Meter.class).toInstance();
- meterService = FRMConsumerImpl.getProviderSession().getRpcService(SalMeterService.class);
+ InstanceIdentifier<? extends DataObject> path = InstanceIdentifier.builder().node(Meters.class)
+ .node(Meter.class).toInstance();
+ meterService = FRMConsumerImpl.getProviderSession().getRpcService(SalMeterService.class);
clusterMeterContainerService = FRMConsumerImpl.getClusterContainerService();
container = FRMConsumerImpl.getContainer();
originalSwMeterView.put(meterKey, meterAddDataObject);
meterService.addMeter(meterBuilder.build());
}
-
- originalSwMeterView.put(meterKey, meterAddDataObject);
- }
- else {
+
+ originalSwMeterView.put(meterKey, meterAddDataObject);
+ } else {
return new Status(StatusCode.BADREQUEST, "Meter Key or attribute validation failed");
}
*
* @param dataObject
*/
- private Status updateMeter(InstanceIdentifier<?> path, Meter meterUpdateDataObject) {
+ private Status updateMeter(InstanceIdentifier<?> path, Meter meterUpdateDataObject) {
MeterKey meterKey = meterUpdateDataObject.getKey();
UpdatedMeterBuilder updateMeterBuilder = null;
-
-
- if (null != meterKey &&
- validateMeter(meterUpdateDataObject, FRMUtil.operation.UPDATE).isSuccess()) {
-
+
+ if (null != meterKey && validateMeter(meterUpdateDataObject, FRMUtil.operation.UPDATE).isSuccess()) {
+
if (originalSwMeterView.containsKey(meterKey)) {
originalSwMeterView.remove(meterKey);
originalSwMeterView.put(meterKey, meterUpdateDataObject);
}
-
+
if (meterUpdateDataObject.isInstall()) {
- UpdateMeterInputBuilder updateMeterInputBuilder = new UpdateMeterInputBuilder();
+ UpdateMeterInputBuilder updateMeterInputBuilder = new UpdateMeterInputBuilder();
updateMeterBuilder = new UpdatedMeterBuilder();
updateMeterBuilder.fieldsFrom(meterUpdateDataObject);
updateMeterInputBuilder.setUpdatedMeter(updateMeterBuilder.build());
-
+
if (installedSwMeterView.containsKey(meterKey)) {
installedSwMeterView.remove(meterKey);
installedSwMeterView.put(meterKey, meterUpdateDataObject);
}
-
+
meterService.updateMeter(updateMeterInputBuilder.build());
}
-
- }
- else {
+
+ } else {
return new Status(StatusCode.BADREQUEST, "Meter Key or attribute validation failed");
}
*
* @param dataObject
*/
- private Status RemoveMeter(InstanceIdentifier<?> path, Meter meterUpdateDataObject) {
+ private Status RemoveMeter(InstanceIdentifier<?> path, Meter meterUpdateDataObject) {
MeterKey meterKey = meterUpdateDataObject.getKey();
-
- if (null != meterKey &&
- validateMeter(meterUpdateDataObject, FRMUtil.operation.ADD).isSuccess()) {
+
+ if (null != meterKey && validateMeter(meterUpdateDataObject, FRMUtil.operation.ADD).isSuccess()) {
if (meterUpdateDataObject.isInstall()) {
- UpdateMeterInputBuilder updateMeterBuilder = new UpdateMeterInputBuilder();
-
+ UpdateMeterInputBuilder updateMeterBuilder = new UpdateMeterInputBuilder();
+
installedSwMeterView.put(meterKey, meterUpdateDataObject);
meterService.updateMeter(updateMeterBuilder.build());
}
-
- originalSwMeterView.put(meterKey, meterUpdateDataObject);
- }
- else {
+
+ originalSwMeterView.put(meterKey, meterUpdateDataObject);
+ } else {
return new Status(StatusCode.BADREQUEST, "Meter Key or attribute validation failed");
}
}
}
+
+ @Override
+ public List<DataObject> get() {
+
+ List<DataObject> orderedList = new ArrayList<DataObject>();
+ Collection<Meter> meterList = originalSwMeterView.values();
+ for (Iterator<Meter> iterator = meterList.iterator(); iterator.hasNext();) {
+ orderedList.add(iterator.next());
+ }
+ return orderedList;
+ }
+
+ @Override
+ public DataObject getWithName(String name, Node n) {
+ if (this instanceof MeterConsumerImpl) {
+ Collection<Meter> meterList = originalSwMeterView.values();
+ for (Iterator<Meter> iterator = meterList.iterator(); iterator.hasNext();) {
+ Meter meter = iterator.next();
+ if (meter.getNode().equals(n) && meter.getMeterName().equals(name)) {
+
+ return meter;
+ }
+ }
+ }
+ return null;
+ }
}
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowUpdated
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowListener
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.NodeErrorNotification
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.NodeExperimenterErrorNotification
import org.opendaylight.yangtools.yang.common.RpcResult
import org.slf4j.LoggerFactory
// NOOP : Not supported by AD SAL
}
+ override onNodeErrorNotification(NodeErrorNotification notification) {
+ // NOOP : Not supported by AD SAL
+ }
+
+ override onNodeExperimenterErrorNotification(
+ NodeExperimenterErrorNotification notification) {
+ // NOOP : Not supported by AD SAL
+ }
}
public static dispatch def toAction(Output sourceAction) {
val actionBuilder = new ActionBuilder();
val it = new OutputActionBuilder();
- outputNodeConnector = sourceAction.port.toUriList;
+ outputNodeConnector = sourceAction.port.toUri;
actionBuilder.action = it.build();
return actionBuilder.build();
return it.build()
}
- public static def List<Uri> toUriList(NodeConnector connector) {
+ public static def Uri toUri(NodeConnector connector) {
throw new UnsupportedOperationException("TODO: auto-generated method stub")
}
targetAction.add(new Controller());
} else if (sourceAction instanceof OutputAction) {
- List<Uri> nodeConnectors = ((OutputAction) sourceAction).getOutputNodeConnector();
- if (nodeConnectors != null) {
- for (Uri uri : nodeConnectors) {
- targetAction.add(new Output(fromNodeConnectorRef(uri)));
- }
+ Uri nodeConnector = ((OutputAction) sourceAction).getOutputNodeConnector();
+ if (nodeConnector != null) {
+ //for (Uri uri : nodeConnectors) {
+ targetAction.add(new Output(fromNodeConnectorRef(nodeConnector)));
+ //}
}
} else if (sourceAction instanceof PopMplsAction) {
// TODO: define maping
checkSalAction(actions, FloodAll.class, 1);
checkSalAction(actions, HwPath.class, 1);
checkSalAction(actions, Loopback.class, 1);
- checkSalAction(actions, Output.class, 2, true);
+ checkSalAction(actions, Output.class, 1, true);
checkSalAction(actions, PopVlan.class, 1);
checkSalAction(actions, PushVlan.class, 1, true);
checkSalAction(actions, SetDlDst.class, 1, true);
pushVlanActionBuilder.setTag(0x8100); // 12 bit
}
- private void prepareActionOutput(OutputActionBuilder outputActionBuilder) {
- List<Uri> uris = new ArrayList<>();
- uris.add(new Uri("uri1"));
- uris.add(new Uri("uri2"));
- outputActionBuilder.setOutputNodeConnector(uris);
+ private void prepareActionOutput(OutputActionBuilder outputActionBuilder) {
+ outputActionBuilder.setOutputNodeConnector(new Uri("uri1"));
}
private Match prepOdMatch(MtchType mt) {
import ietf-inet-types {prefix inet; revision-date "2010-09-24";}
import ietf-yang-types {prefix yang; revision-date "2010-09-24";}
import opendaylight-l2-types {prefix l2t; revision-date "2013-08-27";}
+ import opendaylight-match-types {prefix match; revision-date 2013-10-26";}
revision "2013-11-12" {
description "Initial revision of action service";
grouping action {
choice action {
case output-action {
- leaf-list output-node-connector {
+ leaf output-node-connector {
type inet:uri;
}
}
}
}
-
+
+ case set-field {
+ container match {
+ uses match:match;
+ }
+ }
+
case set-queue-action {
leaf queue {
type string;
}
+
+ leaf queue-id {
+ type uint32;
+ }
}
case pop-mpls-action {
leaf group {
type string;
}
+
+ leaf group-id {
+ type uint32;
+ }
}
case set-dl-type-action {
leaf meter {
type string;
}
+
+ leaf meter-id {
+ type uint32;
+ }
}
}
}
}
}
- grouping group-statistics-request {
- list group-stats {
- key "group-id";
-
- leaf group-id {
- type int32;
- }
- }
- }
-
grouping group-statistics {
leaf group-id {
}
}
+ grouping group-features {
+ uses group-types;
+
+ leaf capabilities {
+ type enumeration {
+ enum select-weight;
+ enum select-liveness;
+ enum chaining;
+ enum chaining-checks;
+ }
+ }
+
+ leaf-list max-groups {
+ type uint32;
+ description "Maximum number of groups for each type";
+ max-elements 4;
+ }
+
+ leaf-list actions {
+ type uint32;
+ description "Bitmap number OFPAT_* that are supported";
+ max-elements 4;
+ }
+ }
+
+ grouping group-statistics-request {
+ list group-stats {
+ key "group-id";
+
+ leaf group-id {
+ type int32;
+ }
+ }
+ }
+
+
grouping group-statistics-reply {
+
list group-stats {
key "group-stats-order";
leaf group-stats-order {
}
}
- grouping group-desc-stats {
+ grouping group-desc-stats-reply {
+
list group-desc-stats {
key "order-id";
-
leaf order-id {
type int32;
}
}
}
- grouping group-features {
- list group-features {
- key "order";
- leaf order {
- type int32;
- }
-
- uses group-types;
-
- leaf capabilities {
- type enumeration {
- enum select-weight;
- enum select-liveness;
- enum chaining;
- enum chaining-checks;
- }
- }
-
- leaf-list max-groups {
- type uint32;
- description "Maximum number of groups for each type";
- max-elements 4;
- }
-
- leaf-list actions {
- type uint32;
- description "Bitmap number OFPAT_* that are supported";
- max-elements 4;
- }
- }
- }
+ grouping group-features-reply {
+ uses group-features;
+ }
+
}
\ No newline at end of file
}
}
- grouping meter-stats-config-request {
- list meter-stats {
- key "meter-id";
-
- leaf meter-id {
- type int32;
- }
- }
- }
-
grouping meter-statistics {
leaf meter-id {
}
}
+ grouping meter-features {
+
+ leaf max_meter {
+ type yang:counter32;
+ }
+
+ leaf band_types {
+ type yang:counter32;
+ }
+
+ leaf capabilities {
+ type yang:counter32;
+ }
+
+ leaf max_bands {
+ type uint8;
+ }
+
+ leaf max_color {
+ type uint8;
+ }
+ }
+
+ grouping meter-stats-config-request {
+ list meter-stats {
+ key "meter-id";
+
+ leaf meter-id {
+ type int32;
+ }
+ }
+ }
+
grouping meter-statistics-reply {
list meter-stats {
key "meter-stats-order";
}
}
- grouping meter-config-stats {
+ grouping meter-config-stats-reply {
list meter-config-stats {
key "meter-config-order";
-
leaf meter-config-order {
type int32;
}
}
}
- grouping meter-features {
- list meter-features {
- key "meter-feature-order";
-
- leaf meter-feature-order {
- type yang:counter32;
- }
-
- leaf max_meter {
- type yang:counter32;
- }
-
- leaf band_types {
- type yang:counter32;
- }
-
- leaf capabilities {
- type yang:counter32;
- }
-
- leaf max_bands {
- type uint8;
- }
-
- leaf max_color {
- type uint8;
- }
- }
- }
+ grouping meter-features-reply {
+ uses meter-features;
+ }
+
}
\ No newline at end of file
--- /dev/null
+module flow-errors {
+ namespace "urn:opendaylight:flow:errors";
+ prefix error;
+
+ revision "2013-11-16" {
+ description "Initial revision of error";
+ }
+
+ typedef error-type {
+ type enumeration {
+ enum hello-failed;
+ enum bad-request;
+ enum bad-action;
+ enum bad-instruction;
+ enum bad-match;
+ enum flow-mod-failed;
+ enum group-mod-failed;
+ enum port-mod-failed;
+ enum table-mod-failed;
+ enum meter-mod-failed;
+ enum queue-op-failed;
+ enum switch-config-failed;
+ enum role-request-failed;
+ enum table-features-failed;
+ enum experimenter;
+ }
+ }
+
+ grouping error-message {
+ leaf type {
+ type error-type;
+ }
+
+ leaf code {
+ type uint16;
+ }
+
+ leaf data {
+ type string;
+ }
+ }
+
+ grouping experimenter-error-message {
+ leaf type {
+ type error-type;
+ }
+
+ leaf exp-type {
+ type uint16;
+ }
+
+ leaf experimenter-id {
+ type uint32;
+ }
+
+ leaf data {
+ type string;
+ }
+ }
+}
\ No newline at end of file
import ietf-inet-types {prefix inet; revision-date "2010-09-24";}
import opendaylight-flow-types {prefix types;revision-date "2013-10-26";}
import flow-capable-transaction {prefix tr;}
+ import flow-errors {prefix error;}
revision "2013-08-19" {
description "Initial revision of flow service";
notification switch-flow-removed {
uses node-flow-removed;
}
+
+ notification node-error-notification {
+ uses error:error-message;
+ }
+
+ notification node-experimenter-error-notification {
+ uses error:experimenter-error-message;
+ }
}
\ No newline at end of file
import opendaylight-group-types {prefix group-types;revision-date "2013-10-18";}
import flow-capable-transaction {prefix tr;}
+ contact
+ "Anilkumar Vishnoi
+ Email: avishnoi@in.ibm.com";
+
revision "2013-11-11" {
description "Initial revision of group statistics service";
}
- typedef group-stats-ref {
- type instance-identifier;
- }
-
- grouping group-stats-response {
- uses "inv:node-context-ref";
-
- leaf group-stats-id {
- type group-stats-ref;
+ augment "/inv:nodes/inv:node" {
+ ext:augment-identifier "node-group-statistics";
+ container group-statistics {
+ //config "false";
+ uses group-types:group-statistics-reply;
}
- uses group-types:group-statistics;
}
- typedef group-features-ref {
- type instance-identifier;
- }
-
- grouping group-features-response {
- uses "inv:node-context-ref";
-
- leaf group-features-id {
- type group-features-ref;
+ augment "/inv:nodes/inv:node" {
+ ext:augment-identifier "node-group-desc-stats";
+ container group-desc {
+ //config "false";
+ uses group-types:group-desc-stats-reply;
}
- uses group-types:group-features;
}
-
- typedef group-desc-ref {
- type instance-identifier;
- }
-
- grouping group-desc-response {
- uses "inv:node-context-ref";
-
- leaf group-desc-id {
- type group-desc-ref;
+
+ augment "/inv:nodes/inv:node" {
+ ext:augment-identifier "node-group-features";
+ container group-features {
+ //config "false";
+ uses group-types:group-features-reply;
}
- uses group-types:group-desc-stats;
}
// RPC calls
rpc get-all-group-statistics {
input {
- uses inv:node-context-ref;
+ uses inv:node;
}
output {
- list group-statistics {
- uses group-stats-response;
- }
+ uses group-types:group-statistics-reply;
uses tr:transaction-aware;
}
rpc get-group-statistics {
input {
- uses inv:node-context-ref;
- leaf group-id{
- type group-types:group-id;
- }
+ uses inv:node;
}
output {
- uses group-stats-response;
+ uses group-types:group-statistics-reply;
uses tr:transaction-aware;
}
rpc get-group-description {
input {
- uses inv:node-context-ref;
- leaf group-id{
- type group-types:group-id;
- }
+ uses inv:node;
}
output {
- uses group-desc-response;
+ uses group-types:group-desc-stats-reply;
uses tr:transaction-aware;
}
}
rpc get-group-features {
input {
- uses inv:node-context-ref;
- leaf group-id{
- type group-types:group-id;
- }
+ uses inv:node;
}
output {
- uses group-features-response;
+ uses group-types:group-features-reply;
uses tr:transaction-aware;
}
}
//Notification calls
notification group-statistics-updated {
- uses group-stats-response;
+ leaf moreReplies {
+ type boolean;
+ }
+ uses inv:node;
+ uses group-types:group-statistics-reply;
uses tr:transaction-aware;
}
notification group-desc-stats-updated {
- uses group-desc-response;
+ leaf moreReplies {
+ type boolean;
+ }
+ uses inv:node;
+ uses group-types:group-desc-stats-reply;
uses tr:transaction-aware;
}
notification group-features-updated {
- uses group-features-response;
+ leaf moreReplies {
+ type boolean;
+ }
+ uses inv:node;
+ uses group-types:group-features-reply;
uses tr:transaction-aware;
}
}
import opendaylight-meter-types {prefix meter-types;revision-date "2013-09-18";}
import flow-capable-transaction {prefix tr;}
+ contact
+ "Anilkumar Vishnoi
+ Email: avishnoi@in.ibm.com";
revision "2013-11-11" {
description "Initial revision of meter statistics service";
}
- typedef meter-stats-ref {
- type instance-identifier;
- }
-
- grouping meter-stats-response {
- uses "inv:node-context-ref";
-
- leaf meter-stats-id {
- type meter-stats-ref;
+ augment "/inv:nodes/inv:node" {
+ ext:augment-identifier "node-meter-statistics";
+ container meter-statistics {
+ //config "false";
+ uses meter-types:meter-statistics-reply;
}
- uses meter-types:meter-statistics;
}
- typedef meter-config-ref {
- type instance-identifier;
- }
-
- grouping meter-config-response {
- uses "inv:node-context-ref";
-
- leaf meter-config-id {
- type meter-config-ref;
+ augment "/inv:nodes/inv:node" {
+ ext:augment-identifier "node-meter-config-stats";
+ container meter-config-stats {
+ //config "false";
+ uses meter-types:meter-config-stats-reply;
}
- uses meter-types:meter-config-stats;
- }
-
- typedef meter-features-ref {
- type instance-identifier;
}
-
- grouping meter-features-response {
- uses "inv:node-context-ref";
-
- leaf meter-features-id {
- type meter-features-ref;
+
+ augment "/inv:nodes/inv:node" {
+ ext:augment-identifier "node-meter-features";
+ container meter-features {
+ //config "false";
+ uses meter-types:meter-features-reply;
}
- uses meter-types:meter-features;
}
// RPC calls
rpc get-all-meter-statistics {
input {
- uses inv:node-context-ref;
+ uses inv:node;
}
output {
- list meter-statistics {
- uses meter-stats-response;
- uses tr:transaction-aware;
- }
+ uses meter-types:meter-statistics-reply;
+ uses tr:transaction-aware;
}
}
rpc get-meter-statistics {
- description "RPC Method to send meter statistics request to the give switch for specific meter";
input {
- uses inv:node-context-ref;
+ uses inv:node;
leaf meter-id{
type meter-types:meter-id;
}
}
output {
- uses meter-stats-response;
+ uses meter-types:meter-statistics-reply;
uses tr:transaction-aware;
}
}
- rpc get-meter-config-statistics {
+ rpc get-all-meter-config-statistics {
input {
- uses inv:node-context-ref;
- leaf meter-id{
- type meter-types:meter-id;
- }
+ uses inv:node;
}
output {
- uses meter-config-response;
+ uses meter-types:meter-config-stats-reply;
uses tr:transaction-aware;
}
}
rpc get-meter-features {
input {
- uses inv:node-context-ref;
- leaf meter-id{
- type meter-types:meter-id;
- }
+ uses inv:node;
}
output {
- uses meter-features-response;
+ uses meter-types:meter-features-reply;
uses tr:transaction-aware;
}
}
//Notification calls
notification meter-statistics-updated {
- uses meter-stats-response;
+ leaf moreReplies {
+ type boolean;
+ }
+
+ uses inv:node;
+ uses meter-types:meter-statistics-reply;
uses tr:transaction-aware;
}
notification meter-config-stats-updated {
- uses meter-config-response;
- uses tr:transaction-aware;
+ leaf moreReplies {
+ type boolean;
+ }
+
+ uses inv:node;
+ uses meter-types:meter-config-stats-reply;
+ uses tr:transaction-aware;
}
notification meter-features-updated {
- uses meter-features-response;
+ leaf moreReplies {
+ type boolean;
+ }
+
+ uses inv:node;
+ uses meter-types:meter-features-reply;
uses tr:transaction-aware;
}
}
<version>1.0-SNAPSHOT</version>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller.model</groupId>
+ <artifactId>model-flow-management</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ <scope>test</scope>
+ </dependency>
<dependency>
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>yang-data-impl</artifactId>
<version>${slf4j.version}</version>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.reflections</groupId>
+ <artifactId>reflections</artifactId>
+ <version>0.9.9-RC1</version>
+ <scope>test</scope>
+ </dependency>
</dependencies>
</project>
--- /dev/null
+package org.opendaylight.controller.sal.binding.codegen;
+
+public class CodeGenerationException extends RuntimeException{
+
+ public CodeGenerationException() {
+ super();
+ }
+
+ public CodeGenerationException(String message, Throwable cause, boolean enableSuppression,
+ boolean writableStackTrace) {
+ super(message, cause, enableSuppression, writableStackTrace);
+ }
+
+ public CodeGenerationException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public CodeGenerationException(String message) {
+ super(message);
+ }
+
+ public CodeGenerationException(Throwable cause) {
+ super(cause);
+ }
+}
import org.opendaylight.yangtools.yang.binding.BindingSerializer
import org.opendaylight.yangtools.yang.binding.BindingCodec
import org.slf4j.LoggerFactory
+import org.opendaylight.controller.sal.binding.codegen.CodeGenerationException
+import org.opendaylight.yangtools.yang.model.api.ChoiceNode
+import java.security.ProtectionDomain
+import java.io.File
class TransformerGenerator {
CtClass ctQName
+ @Property
+ var File classFileCapturePath;
+
+
@Property
var Map<Type, Type> typeDefinitions;
]
}
- def Class<?> keyTransformerFor(Class<?> inputType, GeneratedType type, ListSchemaNode schema) {
+ private def Class<?> keyTransformerFor(Class<?> inputType, GeneratedType type, ListSchemaNode schema) {
return withClassLoader(inputType.classLoader) [ |
val transformer = generatedClasses.get(inputType);
if (transformer != null) {
}
- def Class<?> getValueSerializer(GeneratedTransferObject type) {
+ private def Class<?> getValueSerializer(GeneratedTransferObject type) {
val cls = loadClassWithTCCL(type.resolvedName);
val transformer = generatedClasses.get(cls);
if (transformer !== null) {
'''
]
]
- val ret = ctCls.toClass(inputType.classLoader, inputType.protectionDomain)
+ val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)
log.info("DOM Codec for {} was generated {}",inputType,ret)
return ret as Class<? extends BindingCodec<Map<QName,Object>, ?>>;
} catch (Exception e) {
- log.error("Cannot compile DOM Codec for {}. Exception {}",inputType,e);
- val exception = new IllegalStateException("Cannot compile Transformator for " + inputType);
- exception.addSuppressed(e);
- throw exception;
+ processException(inputType,e);
+ return null;
}
}
- private def <D> Class<? extends BindingCodec<Map<QName, Object>, D>> generateTransformerFor(Class<D> inputType,
+ private def dispatch Class<? extends BindingCodec<Map<QName, Object>, Object>> generateTransformerFor(Class inputType,
GeneratedType typeSpec, SchemaNode node) {
try {
log.info("Generating DOM Codec for {} with {}",inputType,inputType.classLoader)
]
]
- val ret = ctCls.toClass(inputType.classLoader, inputType.protectionDomain)
- return ret as Class<? extends BindingCodec<Map<QName,Object>, D>>;
+ val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)
+ return ret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
} catch (Exception e) {
- log.error("Cannot compile DOM Codec for {}. Exception {}",inputType,e);
- val exception = new IllegalStateException("Cannot compile Transformator for " + inputType);
- exception.addSuppressed(e);
- throw exception;
+ processException(inputType,e);
+ return null;
}
}
+
+
+ private def dispatch Class<? extends BindingCodec<Map<QName, Object>, Object>> generateTransformerFor(Class inputType,
+ GeneratedType typeSpec, ChoiceNode node) {
+ try {
+ log.info("Generating DOM Codec for {} with {}",inputType,inputType.classLoader)
+ val ctCls = createClass(typeSpec.transformatorFqn) [
+ //staticField(Map,"AUGMENTATION_SERIALIZERS");
+ //staticQNameField(inputType);
+ implementsType(ctTransformator)
+ method(Object, "toDomStatic", QName, Object) [
+ modifiers = PUBLIC + FINAL + STATIC
+ body = '''
+ return null;
+ '''
+ ]
+ method(Object, "serialize", Object) [
+ body = '''
+ return null;
+ '''
+ ]
+ method(Object, "fromDomStatic", QName, Object) [
+ modifiers = PUBLIC + FINAL + STATIC
+ body = '''
+ return null;
+ '''
+ ]
+ method(Object, "deserialize", Object) [
+ body = '''
+ return null;
+ '''
+ ]
+ ]
+
+ val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)
+ return ret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
+ } catch (Exception e) {
+ processException(inputType,e);
+ return null;
+ }
+ }
+
private def keyConstructorList(List<QName> qnames) {
val names = new TreeSet<String>()
DataNodeContainer node) {
val ret = '''
«FOR child : node.childNodes.filter[!augmenting]»
- «val signature = properties.get(child.getterName)»
+ «val signature = properties.getFor(child)»
«deserializeProperty(child, signature.returnType, signature)»
_builder.«signature.name.toSetter»(«signature.name»);
«ENDFOR»
if (returnType == null) {
val ctCls = createDummyImplementation(inputType, typeSpec);
- val ret = ctCls.toClass(inputType.classLoader, inputType.protectionDomain)
+ val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)
return ret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
}
val ctCls = createClass(typeSpec.transformatorFqn) [
if($1 == null) {
return null;
}
- «returnType.name» _simpleValue = «deserializeValue(returnType, "$1")»;
+ «returnType.resolvedName» _simpleValue = «deserializeValue(returnType, "$1")»;
«typeSpec.resolvedName» _value = new «typeSpec.resolvedName»(_simpleValue);
return _value;
}
]
]
- val ret = ctCls.toClass(inputType.classLoader, inputType.protectionDomain)
+ val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)
log.info("DOM Codec for {} was generated {}",inputType,ret)
return ret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
} catch (Exception e) {
- log.error("Cannot compile DOM Codec for {}. Exception {}",inputType,e);
- val exception = new IllegalStateException("Cannot compile Transformator for " + inputType);
+ log.error("Cannot compile DOM Codec for {}",inputType,e);
+ val exception = new CodeGenerationException("Cannot compile Transformator for " + inputType);
exception.addSuppressed(e);
throw exception;
}
]
}
- def Type getValueReturnType(GeneratedTransferObject object) {
+ private def Type getValueReturnType(GeneratedTransferObject object) {
for (prop : object.properties) {
if (prop.name == "value") {
return prop.returnType;
]
]
- val ret = ctCls.toClass(inputType.classLoader, inputType.protectionDomain)
+ val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain)
log.info("DOM Codec for {} was generated {}",inputType,ret)
return ret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
+ } catch (CodeGenerationException e) {
+ throw new CodeGenerationException("Cannot compile Transformator for " + inputType,e);
} catch (Exception e) {
- log.error("Cannot compile DOM Codec for {}. Exception {}",inputType,e);
- val exception = new IllegalStateException("Cannot compile Transformator for " + inputType);
+ log.error("Cannot compile DOM Codec for {}",inputType,e);
+ val exception = new CodeGenerationException("Cannot compile Transformator for " + inputType);
exception.addSuppressed(e);
throw exception;
}
+ }
+
+ def Class<?> toClassImpl(CtClass newClass, ClassLoader loader, ProtectionDomain domain) {
+ val cls = newClass.toClass(loader,domain);
+ if(classFileCapturePath !== null) {
+ newClass.writeFile(classFileCapturePath.absolutePath);
+ }
+ return cls;
+ }
+
+ def debugWriteClass(CtClass class1) {
+ val path = class1.name.replace(".","/")+".class"
+
+ val captureFile = new File(classFileCapturePath,path);
+ captureFile.createNewFile
+
+
}
private def dispatch String deserializeValue(Type type, String domParameter) '''(«type.resolvedName») «domParameter»'''
}
'''
+ private def dispatch String serializeBody(GeneratedType type, ChoiceCaseNode node) '''
+ {
+ «QName.name» resultName = «QName.name».create($1,QNAME.getLocalName());
+ java.util.List childNodes = new java.util.ArrayList();
+ «type.resolvedName» value = («type.resolvedName») $2;
+ «transformDataContainerBody(type.allProperties, node)»
+ return ($r) java.util.Collections.singletonMap(resultName,childNodes);
+ }
+ '''
+
+ private def dispatch String serializeBody(GeneratedType type, SchemaNode node) '''
+ {
+ «QName.name» resultName = «QName.name».create($1,QNAME.getLocalName());
+ java.util.List childNodes = new java.util.ArrayList();
+ «type.resolvedName» value = («type.resolvedName») $2;
+ return ($r) java.util.Collections.singletonMap(resultName,childNodes);
+ }
+ '''
+
+
private def transformDataContainerBody(Map<String, MethodSignature> properties, DataNodeContainer node) {
val ret = '''
«FOR child : node.childNodes.filter[!augmenting]»
- «val signature = properties.get(child.getterName)»
+ «var signature = properties.getFor(child)»
«serializeProperty(child, signature.returnType, signature)»
«ENDFOR»
'''
return ret;
}
+
+ def MethodSignature getFor(Map<String,MethodSignature> map, DataSchemaNode node) {
+ val sig = map.get(node.getterName);
+ if(sig == null) {
+ return map.get(node.booleanGetterName);
+ }
+ return sig;
+ }
+
+ private static def String getBooleanGetterName(DataSchemaNode node) {
+ return "is" + BindingGeneratorUtil.parseToClassName(node.QName.localName);
+ }
private static def String getGetterName(DataSchemaNode node) {
return "get" + BindingGeneratorUtil.parseToClassName(node.QName.localName);
MethodSignature property) '''
«property.returnType.resolvedName» «property.name» = value.«property.name»();
if(«property.name» != null) {
- Object domValue = «type.serializer».toDomStatic(QNAME,«property.name»);
+ Object domValue = «type.serializer.name».toDomStatic(QNAME,«property.name»);
childNodes.add(domValue);
}
'''
- private def dispatch String serializeBody(GeneratedType type, SchemaNode node) '''
- {
- return ($r) java.util.Collections.singletonMap(this.QNAME,null);
- }
- '''
+
private def transformatorFqn(GeneratedType typeSpec) {
return '''«typeSpec.resolvedName»$Broker$Codec$DOM'''
val cls = loadClassWithTCCL(type.fullyQualifiedName)
return cls.asCtClass;
}
+
+
+
+ private def dispatch processException(Class<?> inputType,CodeGenerationException e){
+ log.error("Cannot compile DOM Codec for {}. One of it's prerequisites was not generated.",inputType);
+ throw e;
+ }
+
+ private def dispatch processException(Class<?> inputType,Exception e){
+ log.error("Cannot compile DOM Codec for {}",inputType,e);
+ val exception = new CodeGenerationException("Cannot compile Transformator for " + inputType,e);
+ throw exception;
+ }
}
class BindingMapping {
-
-
@Property
val Map<Type, GeneratedTypeBuilder> typeToDefinition = new HashMap();
public static Class<?> loadClassWithTCCL(String name) throws ClassNotFoundException {
+ if("byte[]".equals(name)) {
+ return byte[].class;
+ }
+
return Thread.currentThread().getContextClassLoader().loadClass(name);
}
}
\ No newline at end of file
--- /dev/null
+package org.opendaylight.controller.sal.binding.test;
+
+import java.io.File;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+import org.junit.Before;
+import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
+import org.opendaylight.controller.sal.binding.impl.DataBrokerImpl;
+import org.opendaylight.controller.sal.binding.impl.connect.dom.BindingIndependentDataServiceConnector;
+import org.opendaylight.controller.sal.binding.impl.connect.dom.BindingIndependentMappingService;
+import org.opendaylight.controller.sal.binding.impl.connect.dom.RuntimeGeneratedMappingServiceImpl;
+import org.opendaylight.controller.sal.binding.test.connect.dom.MappingServiceTest;
+import org.opendaylight.controller.sal.core.api.data.DataBrokerService;
+import org.opendaylight.controller.sal.dom.broker.impl.HashMapDataStore;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
+import org.reflections.Reflections;
+import org.reflections.scanners.ResourcesScanner;
+
+import com.google.common.base.Predicate;
+import com.google.common.util.concurrent.ListeningExecutorService;
+import com.google.common.util.concurrent.MoreExecutors;
+
+public abstract class AbstractDataServiceTest {
+ protected DataBrokerService biDataService;
+ protected DataProviderService baDataService;
+
+ protected RuntimeGeneratedMappingServiceImpl mappingServiceImpl;
+ protected BindingIndependentMappingService mappingService;
+ protected DataBrokerImpl baDataImpl;
+ protected org.opendaylight.controller.sal.dom.broker.DataBrokerImpl biDataImpl;
+ protected ListeningExecutorService executor;
+ protected BindingIndependentDataServiceConnector connectorServiceImpl;
+ protected HashMapDataStore dataStore;
+
+
+ @Before
+ public void setUp() {
+ executor = MoreExecutors.sameThreadExecutor();
+ baDataImpl = new DataBrokerImpl();
+ baDataService = baDataImpl;
+ baDataImpl.setExecutor(executor);
+
+ biDataImpl = new org.opendaylight.controller.sal.dom.broker.DataBrokerImpl();
+ biDataService = biDataImpl;
+ biDataImpl.setExecutor(executor);
+
+ dataStore = new HashMapDataStore();
+ org.opendaylight.yangtools.yang.data.api.InstanceIdentifier treeRoot = org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.builder().toInstance();
+ biDataImpl.registerConfigurationReader(treeRoot, dataStore);
+ biDataImpl.registerOperationalReader(treeRoot, dataStore);
+ biDataImpl.registerCommitHandler(treeRoot, dataStore);
+
+ mappingServiceImpl = new RuntimeGeneratedMappingServiceImpl();
+ mappingService = mappingServiceImpl;
+ File pathname = new File("target/gen-classes-debug");
+ //System.out.println("Generated classes are captured in " + pathname.getAbsolutePath());
+ mappingServiceImpl.start();
+ //mappingServiceImpl.getBinding().setClassFileCapturePath(pathname);
+
+ connectorServiceImpl = new BindingIndependentDataServiceConnector();
+ connectorServiceImpl.setBaDataService(baDataService);
+ connectorServiceImpl.setBiDataService(biDataService);
+ connectorServiceImpl.setMappingService(mappingServiceImpl);
+ connectorServiceImpl.start();
+
+ String[] yangFiles= getModelFilenames();
+ mappingServiceImpl.onGlobalContextUpdated(getContext(yangFiles));
+ }
+
+
+ protected String[] getModelFilenames() {
+ return getModelFilenamesImpl();
+ }
+
+ public static String[] getModelFilenamesImpl() {
+ Predicate<String> predicate = new Predicate<String>() {
+ @Override
+ public boolean apply(String input) {
+ return input.endsWith(".yang");
+ }
+ };
+ Reflections reflection= new Reflections("META-INF.yang", new ResourcesScanner());
+ Set<String> result = reflection.getResources(predicate);
+ return (String[]) result.toArray(new String[result.size()]);
+ }
+
+ public static SchemaContext getContext(String[] yangFiles) {
+
+ ClassLoader loader = AbstractDataServiceTest.class.getClassLoader();
+
+ List<InputStream> streams = new ArrayList<>();
+ for (String string : yangFiles) {
+ InputStream stream = loader.getResourceAsStream(string);
+ streams.add(stream);
+
+ }
+ YangParserImpl parser = new YangParserImpl();
+
+ Set<Module> modules = parser.parseYangModelsFromStreams(streams);
+ return parser.resolveSchemaContext(modules);
+ }
+}
--- /dev/null
+package org.opendaylight.controller.sal.binding.test.bugfix;
+
+import java.util.Collections;
+import java.util.Map;
+
+import org.junit.Test;
+import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
+import org.opendaylight.controller.sal.binding.test.AbstractDataServiceTest;
+import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.Flows;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.Flow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.FlowBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.FlowKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.VlanMatchBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.vlan.match.fields.VlanIdBuilder;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+
+import com.google.common.collect.ImmutableMap;
+
+import static org.junit.Assert.*;
+
+/**
+ *
+ * Testcase for https://bugs.opendaylight.org/show_bug.cgi?id=144
+ *
+ * Cannot compile CoDec for org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.Flow
+ *
+ * @author ttkacik
+ *
+ */
+public class DOMCodecBug01Test extends AbstractDataServiceTest {
+
+ private static final QName NODE_ID_QNAME = QName.create(Node.QNAME, "id");
+ private static final QName FLOW_ID_QNAME = QName.create(Flow.QNAME, "id");
+ private static final QName FLOW_NODE_QNAME = QName.create(Flow.QNAME, "node");
+
+ private static final String FLOW_ID = "foo";
+ private static final String NODE_ID = "node:1";
+
+ private static final NodeKey NODE_KEY = new NodeKey(new NodeId(NODE_ID));
+ private static final InstanceIdentifier<Node> NODE_INSTANCE_ID_BA = InstanceIdentifier.builder().node(Nodes.class)
+ .node(Node.class, NODE_KEY).toInstance();
+
+
+ private static final Map<QName, Object> NODE_KEY_BI = Collections.<QName, Object> singletonMap(NODE_ID_QNAME,
+ NODE_ID);
+
+ private static final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier NODE_INSTANCE_ID_BI = //
+ org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.builder() //
+ .node(Nodes.QNAME) //
+ .nodeWithKey(Node.QNAME, NODE_KEY_BI) //
+ .toInstance();
+ private static final NodeRef NODE_REF = new NodeRef(NODE_INSTANCE_ID_BA);
+
+ private static final FlowKey FLOW_KEY = new FlowKey(FLOW_ID, NODE_REF);
+
+ private static final Map<QName, Object> FLOW_KEY_BI = //
+ ImmutableMap.<QName,Object>of(FLOW_ID_QNAME, FLOW_ID, FLOW_NODE_QNAME, NODE_REF);
+
+
+
+
+ private static final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier FLOW_INSTANCE_ID_BI = //
+ org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.builder() //
+ .node(Flows.QNAME) //
+ .nodeWithKey(Flow.QNAME, FLOW_KEY_BI) //
+ .toInstance();
+ private static final InstanceIdentifier<? extends DataObject> FLOW_INSTANCE_ID_BA = //
+ InstanceIdentifier.builder() //
+ .node(Flows.class) //
+ .node(Flow.class, FLOW_KEY) //
+ .toInstance();
+ /**
+ *
+ * When invoking following code in the consumer, user got an
+ * IllegalStateException during creation of mapping between Java DTOs and
+ * data-dom.
+ *
+ * Exception was compilation error which was caused by incorect generation
+ * of code.
+ *
+ *
+ */
+ @Test
+ public void testIndirectGeneration() throws Exception {
+
+ DataModificationTransaction modification = baDataService.beginTransaction();
+
+ FlowBuilder flow = new FlowBuilder();
+ MatchBuilder match = new MatchBuilder();
+ VlanMatchBuilder vlanBuilder = new VlanMatchBuilder();
+ VlanIdBuilder vlanIdBuilder = new VlanIdBuilder();
+ VlanId vlanId = new VlanId(10);
+ vlanBuilder.setVlanId(vlanIdBuilder.setVlanId(vlanId).build());
+ match.setVlanMatch(vlanBuilder.build());
+
+ flow.setKey(FLOW_KEY);
+ flow.setMatch(match.build());
+ flow.setNode(NODE_REF);
+
+ modification.putConfigurationData(FLOW_INSTANCE_ID_BA, flow.build());
+ RpcResult<TransactionStatus> ret = modification.commit().get();
+ assertNotNull(ret);
+ assertEquals(TransactionStatus.COMMITED, ret.getResult());
+
+ verifyDataAreStoredProperly();
+
+
+ DataModificationTransaction modification2 = baDataService.beginTransaction();
+ modification2.removeConfigurationData(FLOW_INSTANCE_ID_BA);
+
+ DataObject originalData = modification2.getOriginalConfigurationData().get(FLOW_INSTANCE_ID_BA);
+ assertNotNull(originalData);
+ RpcResult<TransactionStatus> ret2 = modification2.commit().get();
+
+ assertNotNull(ret2);
+ assertEquals(TransactionStatus.COMMITED, ret2.getResult());
+
+
+ // Data are not in the store.
+ assertNull(baDataService.readOperationalData(FLOW_INSTANCE_ID_BA));
+
+
+ }
+
+ private void verifyDataAreStoredProperly() {
+ CompositeNode biFlow = biDataService.readConfigurationData(FLOW_INSTANCE_ID_BI);
+ assertNotNull(biFlow);
+ CompositeNode biMatch = biFlow.getFirstCompositeByName(QName.create(Flow.QNAME,Match.QNAME.getLocalName()));
+ assertNotNull(biMatch);
+ }
+}
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
-import java.util.concurrent.Executors;
+
import java.util.concurrent.Future;
-import org.junit.Before;
+
import org.junit.Test;
import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
-import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
-import org.opendaylight.controller.sal.binding.impl.DataBrokerImpl;
-import org.opendaylight.controller.sal.binding.impl.connect.dom.BindingIndependentDataServiceConnector;
-import org.opendaylight.controller.sal.binding.impl.connect.dom.BindingIndependentMappingService;
-import org.opendaylight.controller.sal.binding.impl.connect.dom.MappingServiceImpl;
-import org.opendaylight.controller.sal.binding.impl.connect.dom.RuntimeGeneratedMappingServiceImpl;
-import org.opendaylight.controller.sal.core.api.data.DataBrokerService;
-import org.opendaylight.controller.sal.dom.broker.impl.HashMapDataStore;
+
+import org.opendaylight.controller.sal.binding.test.AbstractDataServiceTest;
+
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.opendaylight.yangtools.yang.common.RpcResult;
-import com.google.common.util.concurrent.ListeningExecutorService;
-import com.google.common.util.concurrent.MoreExecutors;
-
-public class BrokerIntegrationTest {
-
- DataBrokerService biDataService;
- DataProviderService baDataService;
- private RuntimeGeneratedMappingServiceImpl mappingServiceImpl;
- private BindingIndependentMappingService mappingService;
- private DataBrokerImpl baDataImpl;
- private org.opendaylight.controller.sal.dom.broker.DataBrokerImpl biDataImpl;
- private ListeningExecutorService executor;
- private BindingIndependentDataServiceConnector connectorServiceImpl;
- private HashMapDataStore dataStore;
-
-
- @Before
- public void setUp() {
- executor = MoreExecutors.sameThreadExecutor();
- baDataImpl = new DataBrokerImpl();
- baDataService = baDataImpl;
- baDataImpl.setExecutor(executor);
-
- biDataImpl = new org.opendaylight.controller.sal.dom.broker.DataBrokerImpl();
- biDataService = biDataImpl;
- biDataImpl.setExecutor(executor);
-
- dataStore = new HashMapDataStore();
- org.opendaylight.yangtools.yang.data.api.InstanceIdentifier treeRoot = org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.builder().toInstance();
- biDataImpl.registerConfigurationReader(treeRoot, dataStore);
- biDataImpl.registerOperationalReader(treeRoot, dataStore);
- biDataImpl.registerCommitHandler(treeRoot, dataStore);
-
- mappingServiceImpl = new RuntimeGeneratedMappingServiceImpl();
- mappingService = mappingServiceImpl;
- mappingServiceImpl.start();
-
- connectorServiceImpl = new BindingIndependentDataServiceConnector();
- connectorServiceImpl.setBaDataService(baDataService);
- connectorServiceImpl.setBiDataService(biDataService);
- connectorServiceImpl.setMappingService(mappingServiceImpl);
- connectorServiceImpl.start();
-
- String[] yangFiles = new String[] { "yang-ext.yang", "ietf-inet-types.yang", "ietf-yang-types.yang",
- "node-inventory.yang" };
-
- mappingServiceImpl.onGlobalContextUpdated(MappingServiceTest.getContext(yangFiles));
-
- }
-
+public class BrokerIntegrationTest extends AbstractDataServiceTest {
+
@Test
public void simpleModifyOperation() throws Exception {
-
-
+
NodeRef node1 = createNodeRef("0");
- DataObject node = baDataService.readConfigurationData(node1.getValue());
+ DataObject node = baDataService.readConfigurationData(node1.getValue());
assertNull(node);
Node nodeData1 = createNode("0");
-
-
+
DataModificationTransaction transaction = baDataService.beginTransaction();
transaction.putConfigurationData(node1.getValue(), nodeData1);
Future<RpcResult<TransactionStatus>> commitResult = transaction.commit();
assertNotNull(commitResult);
-
+
RpcResult<TransactionStatus> result = commitResult.get();
-
+
assertNotNull(result);
assertNotNull(result.getResult());
assertEquals(TransactionStatus.COMMITED, result.getResult());
-
+
Node readedData = (Node) baDataService.readConfigurationData(node1.getValue());
assertNotNull(readedData);
assertEquals(nodeData1.getKey(), readedData.getKey());
-
-
+
NodeRef nodeFoo = createNodeRef("foo");
NodeRef nodeBar = createNodeRef("bar");
Node nodeFooData = createNode("foo");
Node nodeBarData = createNode("bar");
-
-
+
DataModificationTransaction insertMoreTr = baDataService.beginTransaction();
insertMoreTr.putConfigurationData(nodeFoo.getValue(), nodeFooData);
insertMoreTr.putConfigurationData(nodeBar.getValue(), nodeBarData);
RpcResult<TransactionStatus> result2 = insertMoreTr.commit().get();
-
+
assertNotNull(result2);
assertNotNull(result2.getResult());
assertEquals(TransactionStatus.COMMITED, result.getResult());
-
- Nodes allNodes = (Nodes) baDataService.readConfigurationData(InstanceIdentifier.builder().node(Nodes.class).toInstance());
+
+ Nodes allNodes = (Nodes) baDataService.readConfigurationData(InstanceIdentifier.builder().node(Nodes.class)
+ .toInstance());
assertNotNull(allNodes);
assertNotNull(allNodes.getNode());
assertEquals(3, allNodes.getNode().size());
-
-
+
/**
* We create transaction no 2
*
*/
DataModificationTransaction removalTransaction = baDataService.beginTransaction();
assertNotNull(transaction);
-
+
/**
* We remove node 1
*
*/
removalTransaction.removeConfigurationData(node1.getValue());
-
+
/**
* We commit transaction
*/
Future<RpcResult<TransactionStatus>> commitResult2 = removalTransaction.commit();
assertNotNull(commitResult2);
-
+
RpcResult<TransactionStatus> result3 = commitResult2.get();
-
+
assertNotNull(result3);
assertNotNull(result3.getResult());
assertEquals(TransactionStatus.COMMITED, result2.getResult());
-
+
DataObject readedData2 = baDataService.readConfigurationData(node1.getValue());
assertNull(readedData2);
}
-
+
private static NodeRef createNodeRef(String string) {
NodeKey key = new NodeKey(new NodeId(string));
InstanceIdentifier<Node> path = InstanceIdentifier.builder().node(Nodes.class).node(Node.class, key)
.toInstance();
return new NodeRef(path);
}
-
+
private static Node createNode(String string) {
NodeBuilder ret = new NodeBuilder();
ret.setId(new NodeId(string));
import org.junit.Test;
import org.opendaylight.controller.sal.binding.impl.connect.dom.BindingIndependentMappingService;
import org.opendaylight.controller.sal.binding.impl.connect.dom.MappingServiceImpl;
+import org.opendaylight.controller.sal.binding.test.AbstractDataServiceTest;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodesBuilder;
@Test
public void baDataToBiData() throws Exception {
- String[] yangFiles = new String[] { "yang-ext.yang", "ietf-inet-types.yang", "ietf-yang-types.yang",
- "node-inventory.yang" };
+ String[] yangFiles = AbstractDataServiceTest.getModelFilenamesImpl();
- SchemaContext ctx = getContext(yangFiles);
+ SchemaContext ctx = AbstractDataServiceTest.getContext(yangFiles);
impl.onGlobalContextUpdated(ctx);
@Test
public void instanceIdentifierTest() throws Exception {
- String[] yangFiles = new String[] { "yang-ext.yang", "ietf-inet-types.yang", "ietf-yang-types.yang",
- "node-inventory.yang" };
- SchemaContext ctx = getContext(yangFiles);
+ String[] yangFiles = AbstractDataServiceTest.getModelFilenamesImpl();
+ SchemaContext ctx = AbstractDataServiceTest.getContext(yangFiles);
impl.onGlobalContextUpdated(ctx);
NodeKey nodeKey = new NodeKey(new NodeId("foo"));
assertEquals(2, result.getPath().size());
}
- public static SchemaContext getContext(String[] yangFiles) {
-
- ClassLoader loader = MappingServiceTest.class.getClassLoader();
-
- List<InputStream> streams = new ArrayList<>();
- for (String string : yangFiles) {
- InputStream stream = loader.getResourceAsStream("META-INF/yang/" + string);
- streams.add(stream);
-
- }
- YangParserImpl parser = new YangParserImpl();
-
- Set<Module> modules = parser.parseYangModelsFromStreams(streams);
- return parser.resolveSchemaContext(modules);
- }
-
private Node createChildNode(String id) {
NodeBuilder node = new NodeBuilder();
NodeId nodeId = new NodeId(id);
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowAddedBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowRemoved;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowUpdated;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.NodeErrorNotification;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.NodeExperimenterErrorNotification;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowListener;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SwitchFlowRemoved;
import org.opendaylight.yangtools.concepts.Registration;
}
+ @Override
+ public void onNodeErrorNotification(NodeErrorNotification notification) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void onNodeExperimenterErrorNotification(
+ NodeExperimenterErrorNotification notification) {
+ // TODO Auto-generated method stub
+
+ }
+
}
}
import java.io.InputStream;
import java.io.InputStreamReader;
+import java.net.URI;
import java.util.Map.Entry;
import java.util.Set;
}
private CompositeNodeWrapper createStructureWithRoot(String rootObjectName, JsonObject rootObject) {
- CompositeNodeWrapper firstNode = new CompositeNodeWrapper(rootObjectName);
+ CompositeNodeWrapper firstNode = new CompositeNodeWrapper(getNamespaceFrom(rootObjectName),
+ getLocalNameFrom(rootObjectName));
for (Entry<String, JsonElement> childOfFirstNode : rootObject.entrySet()) {
addChildToParent(childOfFirstNode.getKey(), childOfFirstNode.getValue(), firstNode);
}
private void addChildToParent(String childName, JsonElement childType, CompositeNodeWrapper parent) {
if (childType.isJsonObject()) {
- CompositeNodeWrapper child = new CompositeNodeWrapper(childName);
+ CompositeNodeWrapper child = new CompositeNodeWrapper(getNamespaceFrom(childName),
+ getLocalNameFrom(childName));
parent.addValue(child);
for (Entry<String, JsonElement> childOfChild : childType.getAsJsonObject().entrySet()) {
addChildToParent(childOfChild.getKey(), childOfChild.getValue(), child);
String value = childPrimitive.getAsString();
SimpleNodeWrapper child = null;
if (value.equals("[null]")) {
- child = new SimpleNodeWrapper(childName, null);
+ child = new SimpleNodeWrapper(getNamespaceFrom(childName), getLocalNameFrom(childName), null);
} else {
- child = new SimpleNodeWrapper(childName, value);
+ child = new SimpleNodeWrapper(getNamespaceFrom(childName), getLocalNameFrom(childName), value);
}
parent.addValue(child);
}
}
+
+ private URI getNamespaceFrom(String jsonElementName) {
+ int indexOfDelimeter = jsonElementName.lastIndexOf(':');
+ if (indexOfDelimeter == -1) {
+ return null;
+ }
+ return URI.create(jsonElementName.substring(0, indexOfDelimeter));
+ }
+
+ private String getLocalNameFrom(String jsonElementName) {
+ int indexOfDelimeter = jsonElementName.lastIndexOf(':');
+ if (indexOfDelimeter == -1) {
+ return jsonElementName;
+ }
+ return jsonElementName.substring(indexOfDelimeter + 1, jsonElementName.length());
+ }
+
}
public CompositeNodeWrapper(String localName) {
this.localName = Preconditions.checkNotNull(localName);
}
+
+ public CompositeNodeWrapper(URI namespace, String localName) {
+ this(localName);
+ this.namespace = namespace;
+ }
@Override
public String getLocalName() {
this.value = value;
}
+ public SimpleNodeWrapper(URI namespace, String localName, String value) {
+ this(localName, value);
+ this.namespace = namespace;
+ }
+
@Override
public String getLocalName() {
if (simpleNode != null) {
import static org.junit.Assert.assertNotNull;
import java.io.*;
+import java.net.*;
+import java.sql.Date;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import org.opendaylight.controller.sal.rest.impl.*;
import org.opendaylight.controller.sal.restconf.impl.StructuredData;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.data.api.Node;
-import org.opendaylight.yangtools.yang.data.api.SimpleNode;
-import org.opendaylight.yangtools.yang.data.impl.XmlTreeBuilder;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.*;
+import org.opendaylight.yangtools.yang.data.impl.*;
import org.opendaylight.yangtools.yang.model.api.*;
import org.opendaylight.yangtools.yang.model.parser.api.YangModelParser;
import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
}
- static String convertXmlDataAndYangToJson(String xmlDataPath, String yangPath, String outputPath) {
+ static String convertCompositeNodeDataAndYangToJson(CompositeNode compositeNode, String yangPath, String outputPath) {
String jsonResult = null;
Set<Module> modules = null;
try {
- modules = TestUtils.loadModules(YangAndXmlToJsonBasicDataTypesTest.class.getResource(yangPath).getPath());
+ modules = TestUtils.loadModules(ToJsonBasicDataTypesTest.class.getResource(yangPath).getPath());
} catch (FileNotFoundException e) {
e.printStackTrace();
}
assertNotNull("modules can't be null.", modules);
- InputStream xmlStream = YangAndXmlToJsonBasicDataTypesTest.class.getResourceAsStream(xmlDataPath);
- CompositeNode compositeNode = null;
- try {
- compositeNode = TestUtils.loadCompositeNode(xmlStream);
- } catch (FileNotFoundException e) {
- e.printStackTrace();
- }
assertNotNull("Composite node can't be null", compositeNode);
StructuredDataToJsonProvider structuredDataToJsonProvider = StructuredDataToJsonProvider.INSTANCE;
return jsonResult;
}
+ static CompositeNode loadCompositeNode(String xmlDataPath) {
+ InputStream xmlStream = ToJsonBasicDataTypesTest.class.getResourceAsStream(xmlDataPath);
+ CompositeNode compositeNode = null;
+ try {
+ compositeNode = TestUtils.loadCompositeNode(xmlStream);
+ } catch (FileNotFoundException e) {
+ e.printStackTrace();
+ }
+ return compositeNode;
+ }
+
static void outputToFile(ByteArrayOutputStream outputStream, String outputDir) throws IOException {
FileOutputStream fileOS = null;
try {
- String path = YangAndXmlToJsonBasicDataTypesTest.class.getResource(outputDir).getPath();
+ String path = ToJsonBasicDataTypesTest.class.getResource(outputDir).getPath();
File outFile = new File(path + "/data.json");
fileOS = new FileOutputStream(outFile);
try {
}
private static FileReader getFileReader(String path) {
- String fullPath = YangAndXmlToJsonBasicDataTypesTest.class.getResource(path).getPath();
+ String fullPath = ToJsonBasicDataTypesTest.class.getResource(path).getPath();
assertNotNull("Path to file can't be null.", fullPath);
File file = new File(fullPath);
assertNotNull("File can't be null", file);
return strBuilder.toString();
}
+ static QName buildQName(String name, String uri, String date) {
+ try {
+ URI u = new URI(uri);
+ Date dt = null;
+ if (date != null) {
+ dt = Date.valueOf(date);
+ }
+ return new QName(u, dt, name);
+ } catch (URISyntaxException e) {
+ return null;
+ }
+ }
+
+ static QName buildQName(String name) {
+ return buildQName(name, "", null);
+ }
}
import java.util.*;
import org.junit.Test;
+
import com.google.gson.stream.*;
-public class YangAndXmlToJsonBasicDataTypesTest {
+public class ToJsonBasicDataTypesTest {
@Test
public void simpleYangDataTest() {
// TestUtils.readJsonFromFile("/yang-to-json-conversion/simple-yang-types/xml/awaited_output.json",
// false);
- jsonOutput = TestUtils.convertXmlDataAndYangToJson("/yang-to-json-conversion/simple-data-types/xml/data.xml",
+ jsonOutput = TestUtils.convertCompositeNodeDataAndYangToJson(
+ TestUtils.loadCompositeNode("/yang-to-json-conversion/simple-data-types/xml/data.xml"),
"/yang-to-json-conversion/simple-data-types", "/yang-to-json-conversion/simple-data-types/xml");
verifyJsonOutput(jsonOutput);
}
package org.opendaylight.controller.sal.restconf.impl.test;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.assertFalse;
import java.io.*;
import java.util.*;
-import javax.validation.constraints.AssertFalse;
-
import org.junit.Test;
import org.opendaylight.controller.sal.restconf.impl.test.structures.*;
+import org.opendaylight.yangtools.yang.data.api.*;
+import org.opendaylight.yangtools.yang.data.impl.NodeFactory;
-import com.google.gson.stream.JsonReader;
+import com.google.gson.stream.*;
-public class YangAndXmlToJsonBasicYangTypesTest {
+public class ToJsonBasicYangTypesTest {
+ /**
+ * Test of json output when as input are specified composite node with empty
+ * data + YANG file
+ */
@Test
- public void simpleYangTypesWithJsonReaderTest() {
- String jsonOutput;
- // jsonOutput =
- // TestUtils.readJsonFromFile("/yang-to-json-conversion/simple-yang-types/xml/awaited_output.json",
- // false);
-
- jsonOutput = TestUtils.convertXmlDataAndYangToJson("/yang-to-json-conversion/simple-yang-types/xml/data.xml",
+ public void compositeNodeAndYangWithJsonReaderEmptyDataTest() {
+ String jsonOutput = TestUtils.convertCompositeNodeDataAndYangToJson(prepareCompositeNodeWithEmpties(),
"/yang-to-json-conversion/simple-yang-types", "/yang-to-json-conversion/simple-yang-types/xml");
+ verifyJsonOutputForEmpty(jsonOutput);
+ }
+ /**
+ * Test of json output when as input are specified xml file (no empty
+ * elements)and YANG file
+ */
+ @Test
+ public void xmlAndYangTypesWithJsonReaderTest() {
+ String jsonOutput = TestUtils.convertCompositeNodeDataAndYangToJson(
+ TestUtils.loadCompositeNode("/yang-to-json-conversion/simple-yang-types/xml/data.xml"),
+ "/yang-to-json-conversion/simple-yang-types", "/yang-to-json-conversion/simple-yang-types/xml");
verifyJsonOutput(jsonOutput);
+ }
+
+ private void verifyJsonOutputForEmpty(String jsonOutput) {
+ StringReader strReader = new StringReader(jsonOutput);
+ JsonReader jReader = new JsonReader(strReader);
+ String exception = null;
+ Cont dataFromJson = null;
+ try {
+ dataFromJson = jsonReadCont1(jReader);
+ } catch (IOException e) {
+ exception = e.getMessage();
+ }
+
+ assertNotNull("Data structures from json are missing.", dataFromJson);
+ checkDataFromJsonEmpty(dataFromJson);
+
+ assertNull("Error during reading Json output: " + exception, exception);
}
private void verifyJsonOutput(String jsonOutput) {
while (jReader.hasNext()) {
String keyName = jReader.nextName();
if (keyName.equals("lf11")) {
- redData.addLf(new Lf(keyName, jReader.nextString()));
+ redData.addLf(new Lf(keyName, nextValue(jReader)));
} else if (keyName.equals("lflst11")) {
LfLst lfLst = new LfLst(keyName);
lfLst = jsonReadLflstValues(jReader, lfLst);
while (jReader.hasNext()) {
String keyName = jReader.nextName();
if (keyName.equals("lf111")) {
- lstItem.addLf(new Lf(keyName, jReader.nextString()));
+ lstItem.addLf(new Lf(keyName, nextValue(jReader)));
} else if (keyName.equals("lf112")) {
- lstItem.addLf(new Lf(keyName, jReader.nextString()));
+ lstItem.addLf(new Lf(keyName, nextValue(jReader)));
} else if (keyName.equals("cont111")) {
Cont cont = new Cont(keyName);
cont = jsonReadCont111(jReader, cont);
if (jReader.hasNext()) {
String keyName = jReader.nextName();
if (keyName.equals("lf1121")) {
- lstItem.addLf(new Lf(keyName, jReader.nextString()));
+ lstItem.addLf(new Lf(keyName, nextValue(jReader)));
}
}
jReader.endObject();
if (jReader.hasNext()) {
String keyName = jReader.nextName();
if (keyName.equals("lf1111")) {
- lstItem.addLf(new Lf(keyName, jReader.nextString()));
+ lstItem.addLf(new Lf(keyName, nextValue(jReader)));
}
}
jReader.endObject();
return lstItem;
}
+ private String nextValue(JsonReader jReader) throws IOException {
+ if (jReader.peek().equals(JsonToken.NULL)) {
+ jReader.nextNull();
+ return null;
+ } else {
+ return jReader.nextString();
+ }
+ }
+
private Cont jsonReadCont111(JsonReader jReader, Cont cont) throws IOException {
jReader.beginObject();
cont = jsonReadCont111Elements(jReader, cont);
while (jReader.hasNext()) {
String keyName = jReader.nextName();
if (keyName.equals("lf1111")) {
- cont.addLf(new Lf(keyName, jReader.nextString()));
+ cont.addLf(new Lf(keyName, nextValue(jReader)));
} else if (keyName.equals("lflst1111")) {
LfLst lfLst = new LfLst(keyName);
lfLst = jsonReadLflstValues(jReader, lfLst);
while (jReader.hasNext()) {
String keyName = jReader.nextName();
if (keyName.equals("lf1111A") || keyName.equals("lf1111B")) {
- lstItem.addLf(new Lf(keyName, jReader.nextString()));
+ lstItem.addLf(new Lf(keyName, nextValue(jReader)));
}
}
jReader.endObject();
private LfLst jsonReadLflstValues(JsonReader jReader, LfLst lfLst) throws IOException {
jReader.beginArray();
while (jReader.hasNext()) {
- lfLst.addLf(new Lf(jReader.nextString()));
+ lfLst.addLf(new Lf(nextValue(jReader)));
}
jReader.endArray();
return lfLst;
}
+ private void checkDataFromJsonEmpty(Cont dataFromJson) {
+ assertTrue(dataFromJson.getLfs().isEmpty());
+ assertTrue(dataFromJson.getLfLsts().isEmpty());
+ assertTrue(dataFromJson.getConts().isEmpty());
+
+ Map<String, Lst> lsts = dataFromJson.getLsts();
+ assertEquals(1, lsts.size());
+ Lst lst11 = lsts.get("lst11");
+ assertNotNull(lst11);
+ Set<LstItem> lstItems = lst11.getLstItems();
+ assertNotNull(lstItems);
+
+ LstItem lst11_1 = null;
+ LstItem lst11_2 = null;
+ LstItem lst11_3 = null;
+ for (LstItem lstItem : lstItems) {
+ if (lstItem.getLfs().get("lf111").getValue().equals("1")) {
+ lst11_1 = lstItem;
+ } else if (lstItem.getLfs().get("lf111").getValue().equals("2")) {
+ lst11_2 = lstItem;
+ } else if (lstItem.getLfs().get("lf111").getValue().equals("3")) {
+ lst11_3 = lstItem;
+ }
+ }
+
+ assertNotNull(lst11_1);
+ assertNotNull(lst11_2);
+ assertNotNull(lst11_3);
+
+ // lst11_1
+ assertTrue(lst11_1.getLfLsts().isEmpty());
+ assertEquals(1, lst11_1.getLfs().size());
+ assertEquals(1, lst11_1.getConts().size());
+ assertEquals(1, lst11_1.getLsts().size());
+ assertEquals(lst11_1.getLsts().get("lst111"), new Lst("lst111").addLstItem(new LstItem().addLf("lf1111", "35"))
+ .addLstItem(new LstItem().addLf("lf1111", "34")).addLstItem(new LstItem()).addLstItem(new LstItem()));
+ assertEquals(lst11_1.getConts().get("cont111"), new Cont("cont111"));
+ // : lst11_1
+
+ // lst11_2
+ assertTrue(lst11_2.getLfLsts().isEmpty());
+ assertEquals(1, lst11_2.getLfs().size());
+ assertEquals(1, lst11_2.getConts().size());
+ assertEquals(1, lst11_2.getLsts().size());
+
+ Cont lst11_2_cont111 = lst11_2.getConts().get("cont111");
+
+ // -cont111
+ assertNotNull(lst11_2_cont111);
+ assertTrue(lst11_2_cont111.getLfs().isEmpty());
+ assertEquals(1, lst11_2_cont111.getLfLsts().size());
+ assertEquals(1, lst11_2_cont111.getLsts().size());
+ assertTrue(lst11_2_cont111.getConts().isEmpty());
+
+ assertEquals(new LfLst("lflst1111").addLf("1024").addLf("4096"), lst11_2_cont111.getLfLsts().get("lflst1111"));
+ assertEquals(
+ new Lst("lst1111").addLstItem(new LstItem().addLf("lf1111B", "4")).addLstItem(
+ new LstItem().addLf("lf1111A", "lf1111A str12")), lst11_2_cont111.getLsts().get("lst1111"));
+ // :-cont111
+ assertEquals(lst11_2.getLsts().get("lst112"), new Lst("lst112").addLstItem(new LstItem()));
+ // : lst11_2
+
+ // lst11_3
+ assertEquals(1, lst11_3.getLfs().size());
+ assertTrue(lst11_3.getLfLsts().isEmpty());
+ assertTrue(lst11_3.getLsts().isEmpty());
+ assertTrue(lst11_3.getLsts().isEmpty());
+
+ // -cont111
+ Cont lst11_3_cont111 = lst11_3.getConts().get("cont111");
+ assertEquals(0, lst11_3_cont111.getLfs().size());
+ assertEquals(0, lst11_3_cont111.getLfLsts().size());
+ assertEquals(1, lst11_3_cont111.getLsts().size());
+ assertTrue(lst11_3_cont111.getConts().isEmpty());
+
+ assertEquals(new Lst("lst1111").addLstItem(new LstItem()).addLstItem(new LstItem()), lst11_3_cont111.getLsts()
+ .get("lst1111"));
+ // :-cont111
+ // : lst11_3
+
+ }
+
private void checkDataFromJson(Cont dataFromJson) {
assertNotNull(dataFromJson.getLfs().get("lf11"));
assertEquals(dataFromJson.getLfs().get("lf11"), new Lf("lf11", "lf"));
assertNotNull(lst11_1_cont_lst1111_2);
}
+ private CompositeNode prepareCompositeNodeWithEmpties() {
+ MutableCompositeNode cont1 = NodeFactory.createMutableCompositeNode(
+ TestUtils.buildQName("cont1", "simple:yang:types", "2013-11-5"), null, null, ModifyAction.CREATE, null);
+
+ // lst11_1
+ MutableCompositeNode lst11_1 = NodeFactory.createMutableCompositeNode(TestUtils.buildQName("lst11"), cont1,
+ null, ModifyAction.CREATE, null);
+ cont1.getChildren().add(lst11_1);
+
+ MutableSimpleNode<?> lf111_1 = NodeFactory.createMutableSimpleNode(TestUtils.buildQName("lf111"), lst11_1, "1",
+ ModifyAction.CREATE, null);
+ lst11_1.getChildren().add(lf111_1);
+
+ // lst111_1_1
+ MutableCompositeNode lst111_1_1 = NodeFactory.createMutableCompositeNode(TestUtils.buildQName("lst111"),
+ lst11_1, null, ModifyAction.CREATE, null);
+ lst11_1.getChildren().add(lst111_1_1);
+ MutableSimpleNode<?> lf1111_1_1 = NodeFactory.createMutableSimpleNode(TestUtils.buildQName("lf1111"),
+ lst111_1_1, "34", ModifyAction.CREATE, null);
+ lst111_1_1.getChildren().add(lf1111_1_1);
+ lst111_1_1.init();
+ // :lst111_1_1
+
+ // lst111_1_2
+ MutableCompositeNode lst111_1_2 = NodeFactory.createMutableCompositeNode(TestUtils.buildQName("lst111"),
+ lst11_1, null, ModifyAction.CREATE, null);
+ lst11_1.getChildren().add(lst111_1_2);
+ MutableSimpleNode<?> lf1111_1_2 = NodeFactory.createMutableSimpleNode(TestUtils.buildQName("lf1111"),
+ lst111_1_2, "35", ModifyAction.CREATE, null);
+ lst111_1_2.getChildren().add(lf1111_1_2);
+ lst111_1_2.init();
+ // :lst111_1_2
+
+ // lst111_1_3
+ MutableCompositeNode lst111_1_3 = NodeFactory.createMutableCompositeNode(TestUtils.buildQName("lst111"),
+ lst11_1, null, ModifyAction.CREATE, null);
+ lst11_1.getChildren().add(lst111_1_3);
+ lst111_1_2.init();
+ // :lst111_1_3
+
+ // lst111_1_4
+ MutableCompositeNode lst111_1_4 = NodeFactory.createMutableCompositeNode(TestUtils.buildQName("lst111"),
+ lst11_1, null, ModifyAction.CREATE, null);
+ lst11_1.getChildren().add(lst111_1_4);
+ lst111_1_2.init();
+ // :lst111_1_4
+
+ MutableCompositeNode cont111_1 = NodeFactory.createMutableCompositeNode(TestUtils.buildQName("cont111"),
+ lst11_1, null, ModifyAction.CREATE, null);
+ lst11_1.getChildren().add(cont111_1);
+
+ lst11_1.init();
+ // :lst11_1
+
+ // lst11_2
+ MutableCompositeNode lst11_2 = NodeFactory.createMutableCompositeNode(TestUtils.buildQName("lst11"), cont1,
+ null, ModifyAction.CREATE, null);
+ cont1.getChildren().add(lst11_2);
+
+ MutableSimpleNode<?> lf111_2 = NodeFactory.createMutableSimpleNode(TestUtils.buildQName("lf111"), lst11_2, "2",
+ ModifyAction.CREATE, null);
+ lst11_2.getChildren().add(lf111_2);
+
+ // cont111_2
+ MutableCompositeNode cont111_2 = NodeFactory.createMutableCompositeNode(TestUtils.buildQName("cont111"),
+ lst11_2, null, ModifyAction.CREATE, null);
+ lst11_2.getChildren().add(cont111_2);
+
+ MutableSimpleNode<?> lflst1111_2_2 = NodeFactory.createMutableSimpleNode(TestUtils.buildQName("lflst1111"),
+ cont111_2, "1024", ModifyAction.CREATE, null);
+ cont111_2.getChildren().add(lflst1111_2_2);
+ MutableSimpleNode<?> lflst1111_2_3 = NodeFactory.createMutableSimpleNode(TestUtils.buildQName("lflst1111"),
+ cont111_2, "4096", ModifyAction.CREATE, null);
+ cont111_2.getChildren().add(lflst1111_2_3);
+
+ // lst1111_2
+ MutableCompositeNode lst1111_2_1 = NodeFactory.createMutableCompositeNode(TestUtils.buildQName("lst1111"),
+ cont111_2, null, ModifyAction.CREATE, null);
+ cont111_2.getChildren().add(lst1111_2_1);
+ MutableSimpleNode<?> lf1111B_2_1 = NodeFactory.createMutableSimpleNode(TestUtils.buildQName("lf1111B"),
+ lst1111_2_1, "4", ModifyAction.CREATE, null);
+ lst1111_2_1.getChildren().add(lf1111B_2_1);
+ lst1111_2_1.init();
+
+ MutableCompositeNode lst1111_2_2 = NodeFactory.createMutableCompositeNode(TestUtils.buildQName("lst1111"),
+ cont111_2, null, ModifyAction.CREATE, null);
+ cont111_2.getChildren().add(lst1111_2_2);
+ MutableSimpleNode<?> lf1111B_2_2 = NodeFactory.createMutableSimpleNode(TestUtils.buildQName("lf1111A"),
+ lst1111_2_2, "lf1111A str12", ModifyAction.CREATE, null);
+ lst1111_2_2.getChildren().add(lf1111B_2_2);
+ lst1111_2_2.init();
+ // :lst1111_2
+
+ cont111_2.init();
+ // :cont111_2
+
+ MutableCompositeNode lst112_2 = NodeFactory.createMutableCompositeNode(TestUtils.buildQName("lst112"), lst11_2,
+ null, ModifyAction.CREATE, null);
+ lst11_2.getChildren().add(lst112_2);
+ lst112_2.init();
+ lst11_2.init();
+
+ // :lst11_2
+
+ // lst11_3
+ MutableCompositeNode lst11_3 = NodeFactory.createMutableCompositeNode(TestUtils.buildQName("lst11"), cont1,
+ null, ModifyAction.CREATE, null);
+ cont1.getChildren().add(lst11_3);
+
+ MutableSimpleNode<?> lf111_3 = NodeFactory.createMutableSimpleNode(TestUtils.buildQName("lf111"), lst11_3, "3",
+ ModifyAction.CREATE, null);
+ lst11_3.getChildren().add(lf111_3);
+
+ // cont111_3
+ MutableCompositeNode cont111_3 = NodeFactory.createMutableCompositeNode(TestUtils.buildQName("cont111"),
+ lst11_3, null, ModifyAction.CREATE, null);
+ lst11_3.getChildren().add(cont111_3);
+
+ MutableCompositeNode lst1111_3_1 = NodeFactory.createMutableCompositeNode(TestUtils.buildQName("lst1111"),
+ cont111_3, null, ModifyAction.CREATE, null);
+ cont111_3.getChildren().add(lst1111_3_1);
+ lst1111_3_1.init();
+
+ MutableCompositeNode lst1111_3_2 = NodeFactory.createMutableCompositeNode(TestUtils.buildQName("lst1111"),
+ cont111_3, null, ModifyAction.CREATE, null);
+ cont111_3.getChildren().add(lst1111_3_2);
+ lst1111_3_2.init();
+
+ cont111_3.init();
+ // :cont111_3
+
+ lst11_3.init();
+ // :lst11_3
+
+ cont1.init();
+ return cont1;
+ }
+
}
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
+import org.glassfish.jersey.client.ClientConfig;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.test.JerseyTest;
import org.glassfish.jersey.test.TestProperties;
Entity.entity("<SimpleNode>", new MediaType("application", "vnd.yang.api+xml")));
assertEquals(400, response.getStatus());
}
+
+ @Test
+ public void testXmlToCompositeNode404NotFound() {
+ URI uri = null;
+ try {
+ uri = new URI("/datastore/" + URLEncoder.encode("ietf-interfaces:interfaces/interface/eth0", Charsets.US_ASCII.name()).toString());
+ } catch (UnsupportedEncodingException | URISyntaxException e) {
+ e.printStackTrace();
+ }
+
+ when(brokerFacade.readOperationalData(any(InstanceIdentifier.class))).thenReturn(null);
+
+ Response response = target(uri.toASCIIString()).request(MediaTypes.API+RestconfService.XML).get();
+ assertEquals(404, response.getStatus());
+ }
@Override
protected Application configure() {
return false;
}
Cont cont = (Cont) obj;
- if (!this.name.equals(cont.name)) {
+ if (this.name == null) {
+ if (cont.name != null) {
+ return false;
+ }
+ } else if (!this.name.equals(cont.name)) {
return false;
}
return true;
public class Lf extends YangElement {
private String value;
+ private int numOfEqualItems = 0;
+
public Lf(String name, String value) {
super(name);
return false;
}
Lf lf = (Lf) obj;
- if (!this.value.equals(lf.value)) {
+ if (this.value == null) {
+ if (lf.value != null) {
+ return false;
+ }
+ } else if (!this.value.equals(lf.value)) {
+ return false;
+ }
+ if (this.numOfEqualItems != lf.numOfEqualItems) {
return false;
}
return true;
}
+
+ public void incNumOfEqualItems() {
+ this.numOfEqualItems++;
+ }
+
@Override
public int hashCode() {
final int prime = 31;
int result = super.hashCode();
result = prime * result + ((value == null) ? 0 : value.hashCode());
+ result = prime * result + numOfEqualItems;
return result;
}
lfs = new HashSet<>();
}
+ public LfLst addLf(String value) {
+ return addLf(new Lf(value));
+ }
+
+
public LfLst addLf(Lf lf) {
- lfs.add(lf);
+ while (this.lfs.contains(lf)) {
+ lf.incNumOfEqualItems();
+ }
+ this.lfs.add(lf);
return this;
}
return false;
}
LfLst lfLst = (LfLst) obj;
- if (!this.lfs.equals(lfLst.lfs)) {
+ if (this.lfs == null) {
+ if (lfLst.lfs != null) {
+ return false;
+ }
+ } else if (!this.lfs.equals(lfLst.lfs)) {
return false;
}
return true;
lstItems = new HashSet<>();
}
- public void addLstItem(LstItem lstItem) {
+ public Lst addLstItem(LstItem lstItem) {
lstItem.setLstName(name);
+ while (this.lstItems.contains(lstItem)) {
+ lstItem.incNumOfEqualItems();
+ }
this.lstItems.add(lstItem);
+ return this;
}
public Set<LstItem> getLstItems() {
return false;
}
Lst lst = (Lst) obj;
- if (!this.lstItems.equals(lst.lstItems)) {
+ if (this.lstItems == null) {
+ if (lst.lstItems != null) {
+ return false;
+ }
+ } else if (!this.lstItems.equals(lst.lstItems)) {
return false;
}
return true;
Map<String, LfLst> lfLsts;
Map<String, Lst> lsts;
Map<String, Cont> conts;
+ private int numOfEqualItems = 0;
public LstItem() {
lfs = new HashMap<>();
return this;
}
+ public LstItem addLf(String name, String value) {
+ lfs.put(name, new Lf(name, value));
+ return this;
+ }
+
public void addLfLst(LfLst lfLst) {
lfLsts.put(lfLst.getName(), lfLst);
}
conts.put(cont.getName(), cont);
}
+ public void incNumOfEqualItems() {
+ this.numOfEqualItems++;
+ }
+
@Override
public boolean equals(Object obj) {
if (this == obj) {
return false;
}
LstItem lstItem = (LstItem) obj;
- if (!this.conts.equals(lstItem.conts)) {
+ if (this.conts == null) {
+ if (lstItem.conts != null) {
+ return false;
+ }
+ } else if (!this.conts.equals(lstItem.conts)) {
+ return false;
+ }
+ if (this.lfs == null) {
+ if (lstItem.lfs != null) {
+ return false;
+ }
+ } else if (!this.lfs.equals(lstItem.lfs)) {
return false;
}
- if (!this.lfs.equals(lstItem.lfs)) {
+ if (this.lfLsts == null) {
+ if (lstItem.lfLsts != null) {
+ return false;
+ }
+ } else if (!this.lfLsts.equals(lstItem.lfLsts)) {
return false;
}
- if (!this.lfLsts.equals(lstItem.lfLsts)) {
+ if (this.lsts == null) {
+ if (lstItem.lsts != null) {
+ return false;
+ }
+ } else if (!this.lsts.equals(lstItem.lsts)) {
return false;
}
- if (!this.lsts.equals(lstItem.lsts)) {
+ if (this.numOfEqualItems != lstItem.numOfEqualItems) {
return false;
}
return true;
result = prime * result + ((lfLsts == null) ? 0 : lfLsts.hashCode());
result = prime * result + ((lsts == null) ? 0 : lsts.hashCode());
result = prime * result + ((conts == null) ? 0 : conts.hashCode());
+ result = prime * result + numOfEqualItems;
return result;
}
protected YangElement(String name) {
this.name = name;
}
-
+
public String getName() {
return name;
}
return false;
}
YangElement yangElement = (YangElement) obj;
- if (!this.name.equals(yangElement.name)) {
+ if (this.name == null) {
+ if (yangElement.name != null) {
+ return false;
+ }
+ } else if (!this.name.equals(yangElement.name)) {
return false;
}
return true;
--- /dev/null
+{
+ "cont1": {
+ "lst11": [
+ {
+ "lf111": 1,
+ "lst111": [
+ {
+ "lf1111": 34
+ },
+ {
+ "lf1111": 35
+ },
+ {},
+ {}
+ ],
+ "cont111": {}
+ },
+ {
+ "lf111": 2,
+ "cont111": {
+ "lflst1111": [
+ 1024,
+ 4096
+ ],
+ "lst1111": [
+ {
+ "lf1111B": 4
+ },
+ {
+ "lf1111A": "lf1111A str12"
+ }
+ ]
+ },
+ "lst112": [
+ {}
+ ]
+ },
+ {
+ "lf111": 3,
+ "cont111": {
+ "lst1111": [
+ {},
+ {}
+ ]
+ }
+ }
+ ]
+ }
+}
\ No newline at end of file
--- /dev/null
+<cont1>
+ <lst11>
+ <lf111>1</lf111>
+ <lst111></lst111>
+ <lst111></lst111>
+ <lst111>
+ <lf1111></lf1111>
+ </lst111>
+ <lst111>
+ <lf1111>35</lf1111>
+ </lst111>
+ <cont111></cont111>
+ </lst11>
+ <lst11>
+ <lf111>2</lf111>
+ <cont111>
+ <lf1111></lf1111>
+ <lflst1111></lflst1111>
+ <lflst1111>1024</lflst1111>
+ <lflst1111>4096</lflst1111>
+ <lst1111>
+ <lf1111B>4</lf1111B>
+ </lst1111>
+ <lst1111>
+ <lf1111A>lf1111A str12</lf1111A>
+ </lst1111>
+ </cont111>
+ <lst112></lst112>
+ </lst11>
+ <lst11>
+ <lf111>3</lf111>
+ <cont111>
+ <lf1111></lf1111>
+ <lflst1111></lflst1111>
+ <lflst1111></lflst1111>
+ <lst1111></lst1111>
+ <lst1111></lst1111>
+ </cont111>
+ </lst11>
+</cont1>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
- <version>${bundle.plugin.version}</version>
<extensions>true</extensions>
<configuration>
<instructions>
</instructions>
</configuration>
</plugin>
- <plugin>
- <groupId>org.eclipse.xtend</groupId>
- <artifactId>xtend-maven-plugin</artifactId>
- </plugin>
<plugin>
<artifactId>maven-clean-plugin</artifactId>
</plugin>
--- /dev/null
+/*
+ * Copyright IBM Corporation, 2013. 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.md.statistics.manager;
+
+import java.util.List;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.nodes.node.GroupFeatures;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.desc.stats.reply.GroupDescStats;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.statistics.reply.GroupStats;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.nodes.node.MeterFeatures;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.meter.config.stats.reply.MeterConfigStats;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.meter.statistics.reply.MeterStats;
+
+public class NodeStatistics {
+
+ private NodeRef targetNode;
+
+ private List<GroupStats> groupStatistics;
+
+ private List<MeterStats> meterStatistics;
+
+ private List<GroupDescStats> groupDescStats;
+
+ private List<MeterConfigStats> meterConfigStats;
+
+ private GroupFeatures groupFeatures;
+
+ private MeterFeatures meterFeatures;
+
+ public NodeStatistics(){
+
+ }
+
+ public NodeRef getTargetNode() {
+ return targetNode;
+ }
+
+ public void setTargetNode(NodeRef targetNode) {
+ this.targetNode = targetNode;
+ }
+
+ public List<GroupStats> getGroupStatistics() {
+ return groupStatistics;
+ }
+
+ public void setGroupStatistics(List<GroupStats> groupStatistics) {
+ this.groupStatistics = groupStatistics;
+ }
+
+ public List<MeterStats> getMeterStatistics() {
+ return meterStatistics;
+ }
+
+ public void setMeterStatistics(List<MeterStats> meterStatistics) {
+ this.meterStatistics = meterStatistics;
+ }
+
+ public List<GroupDescStats> getGroupDescStats() {
+ return groupDescStats;
+ }
+
+ public void setGroupDescStats(List<GroupDescStats> groupDescStats) {
+ this.groupDescStats = groupDescStats;
+ }
+
+ public List<MeterConfigStats> getMeterConfigStats() {
+ return meterConfigStats;
+ }
+
+ public void setMeterConfigStats(List<MeterConfigStats> meterConfigStats) {
+ this.meterConfigStats = meterConfigStats;
+ }
+
+ public GroupFeatures getGroupFeatures() {
+ return groupFeatures;
+ }
+
+ public void setGroupFeatures(GroupFeatures groupFeatures) {
+ this.groupFeatures = groupFeatures;
+ }
+
+ public MeterFeatures getMeterFeatures() {
+ return meterFeatures;
+ }
+
+ public void setMeterFeatures(MeterFeatures meterFeatures) {
+ this.meterFeatures = meterFeatures;
+ }
+
+}
+/*
+ * Copyright IBM Corporation, 2013. 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
+ */
+/*
+ * TODO: Handle multipart messages with following flag true
+ * OFPMPF_REPLY_MORE = 1 << 0
+ * Better accumulate all the messages and update local cache
+ * and configurational data store
+ */
package org.opendaylight.controller.md.statistics.manager;
import org.opendaylight.controller.sal.binding.api.AbstractBindingAwareProvider;
+/*
+ * Copyright IBM Corporation, 2013. 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.md.statistics.manager;
+import java.util.List;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.Future;
+
import org.eclipse.xtext.xbase.lib.Exceptions;
import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.GetAllGroupStatisticsInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.GetAllGroupStatisticsOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.GetGroupDescriptionInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.GetGroupDescriptionOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.GetGroupFeaturesInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.GetGroupFeaturesOutput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.OpendaylightGroupStatisticsService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.GetAllMeterConfigStatisticsInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.GetAllMeterConfigStatisticsOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.GetAllMeterStatisticsInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.GetAllMeterStatisticsOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.GetMeterFeaturesInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.GetMeterFeaturesOutput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.OpendaylightMeterStatisticsService;
import org.opendaylight.yangtools.concepts.Registration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.opendaylight.yangtools.yang.binding.NotificationListener;
+import org.opendaylight.yangtools.yang.common.RpcResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private OpendaylightMeterStatisticsService meterStatsService;
+ private Thread statisticsRequesterThread;
+
+ private final InstanceIdentifier<Nodes> nodesIdentifier = InstanceIdentifier.builder().node(Nodes.class).toInstance();
+
+ //Local caching of stats
+
+ private final ConcurrentMap<NodeId,NodeStatistics> statisticsCache =
+ new ConcurrentHashMap<NodeId,NodeStatistics>();
+
public DataProviderService getDataService() {
return this.dps;
}
this.listenerRegistration = registerNotificationListener;
// Get Group/Meter statistics service instance
- groupStatsService = StatisticsManagerActivator.getProviderContext().getRpcService(OpendaylightGroupStatisticsService.class);
+ groupStatsService = StatisticsManagerActivator.getProviderContext().
+ getRpcService(OpendaylightGroupStatisticsService.class);
- meterStatsService = StatisticsManagerActivator.getProviderContext().getRpcService(OpendaylightMeterStatisticsService.class);
+ meterStatsService = StatisticsManagerActivator.getProviderContext().
+ getRpcService(OpendaylightMeterStatisticsService.class);
+
+ statisticsRequesterThread = new Thread( new Runnable(){
+ @Override
+ public void run() {
+ while(true){
+ try {
+ spLogger.info("Statistics requester thread started with timer interval : {}",5000);
+
+ statsRequestSender();
+
+ Thread.sleep(5000);
+ }catch (Exception e){
+ spLogger.error("Exception occurred while sending stats request : {}",e);
+ }
+ }
+ }
+ });
spLogger.info("Statistics Provider started.");
}
return dps.beginTransaction();
}
+ private void statsRequestSender(){
+
+ //Need to call API to receive all the nodes connected to controller.
+ List<Node> targetNodes = getAllConnectedNodes();
+
+ for (Node targetNode : targetNodes){
+ spLogger.info("Send request for stats collection to node : {})",targetNode.getId());
+
+ //We need to add check, so see if groups/meters are supported
+ //by the target node. Below check doesn't look good.
+ if(targetNode.getId().getValue().contains("openflow:")){
+ sendAllGroupStatisticsRequest(targetNode);
+
+ sendAllMeterStatisticsRequest(targetNode);
+
+ sendGroupDescriptionRequest(targetNode);
+
+ sendGroupFeaturesRequest(targetNode);
+
+ sendMeterConfigStatisticsRequest(targetNode);
+
+ sendMeterFeaturesRequest(targetNode);
+ }
+ }
+ }
+
+ private void sendAllGroupStatisticsRequest(Node targetNode){
+
+ final GetAllGroupStatisticsInputBuilder input = new GetAllGroupStatisticsInputBuilder();
+
+ input.setId(targetNode.getId());
+
+ Future<RpcResult<GetAllGroupStatisticsOutput>> response =
+ groupStatsService.getAllGroupStatistics(input.build());
+ }
+
+ private void sendGroupDescriptionRequest(Node targetNode){
+ final GetGroupDescriptionInputBuilder input = new GetGroupDescriptionInputBuilder();
+
+ input.setId(targetNode.getId());
+
+ Future<RpcResult<GetGroupDescriptionOutput>> response =
+ groupStatsService.getGroupDescription(input.build());
+ }
+
+ private void sendGroupFeaturesRequest(Node targetNode){
+
+ GetGroupFeaturesInputBuilder input = new GetGroupFeaturesInputBuilder();
+
+ input.setId(targetNode.getId());
+
+ Future<RpcResult<GetGroupFeaturesOutput>> response =
+ groupStatsService.getGroupFeatures(input.build());
+ }
+
+ private void sendAllMeterStatisticsRequest(Node targetNode){
+
+ GetAllMeterStatisticsInputBuilder input = new GetAllMeterStatisticsInputBuilder();
+
+ input.setId(targetNode.getId());
+
+ Future<RpcResult<GetAllMeterStatisticsOutput>> response =
+ meterStatsService.getAllMeterStatistics(input.build());
+ }
+
+ private void sendMeterConfigStatisticsRequest(Node targetNode){
+
+ GetAllMeterConfigStatisticsInputBuilder input = new GetAllMeterConfigStatisticsInputBuilder();
+
+ input.setId(targetNode.getId());
+
+ Future<RpcResult<GetAllMeterConfigStatisticsOutput>> response =
+ meterStatsService.getAllMeterConfigStatistics(input.build());
+
+ }
+ private void sendMeterFeaturesRequest(Node targetNode){
+
+ GetMeterFeaturesInputBuilder input = new GetMeterFeaturesInputBuilder();
+
+ input.setId(targetNode.getId());
+
+ Future<RpcResult<GetMeterFeaturesOutput>> response =
+ meterStatsService.getMeterFeatures(input.build());
+ }
+
+ public ConcurrentMap<NodeId, NodeStatistics> getStatisticsCache() {
+ return statisticsCache;
+ }
+
+ private List<Node> getAllConnectedNodes(){
+
+ Nodes nodes = (Nodes) dps.readOperationalData(nodesIdentifier);
+ spLogger.info("Number of connected nodes : {}",nodes.getNode().size());
+ return nodes.getNode();
+ }
+
+ @SuppressWarnings("deprecation")
@Override
public void close(){
if (this.listenerRegistration != null) {
this.listenerRegistration.close();
+
+ this.statisticsRequesterThread.destroy();
}
} catch (Throwable e) {
+/*
+ * Copyright IBM Corporation, 2013. 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.md.statistics.manager;
+import java.util.concurrent.ConcurrentMap;
+
+import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.GroupDescStatsUpdated;
import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.GroupFeaturesUpdated;
import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.GroupStatisticsUpdated;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.NodeGroupDescStats;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.NodeGroupDescStatsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.NodeGroupFeatures;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.NodeGroupFeaturesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.NodeGroupStatistics;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.NodeGroupStatisticsBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.OpendaylightGroupStatisticsListener;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.nodes.node.GroupDescBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.nodes.node.GroupFeaturesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.nodes.node.GroupStatisticsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.MeterConfigStatsUpdated;
import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.MeterFeaturesUpdated;
import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.MeterStatisticsUpdated;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.NodeMeterConfigStats;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.NodeMeterConfigStatsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.NodeMeterFeatures;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.NodeMeterFeaturesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.NodeMeterStatistics;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.NodeMeterStatisticsBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.OpendaylightMeterStatisticsListener;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.nodes.node.MeterConfigStatsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.nodes.node.MeterFeaturesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.nodes.node.MeterStatisticsBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
public class StatisticsUpdateCommiter implements OpendaylightGroupStatisticsListener,
OpendaylightMeterStatisticsListener {
this.statisticsManager = manager;
}
+
public StatisticsProvider getStatisticsManager(){
return statisticsManager;
}
+
@Override
public void onMeterConfigStatsUpdated(MeterConfigStatsUpdated notification) {
- // TODO Auto-generated method stub
+
+ //Add statistics to local cache
+ ConcurrentMap<NodeId, NodeStatistics> cache = this.statisticsManager.getStatisticsCache();
+ if(!cache.containsKey(notification.getId())){
+ cache.put(notification.getId(), new NodeStatistics());
+ }
+ cache.get(notification.getId()).setMeterConfigStats(notification.getMeterConfigStats());
+
+ //Publish data to configuration data store
+ DataModificationTransaction it = this.statisticsManager.startChange();
+ NodeKey key = new NodeKey(notification.getId());
+ NodeRef ref = getNodeRef(key);
+
+ final NodeBuilder nodeData = new NodeBuilder();
+ nodeData.setKey(key);
+
+ NodeMeterConfigStatsBuilder meterConfig= new NodeMeterConfigStatsBuilder();
+ MeterConfigStatsBuilder stats = new MeterConfigStatsBuilder();
+ stats.setMeterConfigStats(notification.getMeterConfigStats());
+ meterConfig.setMeterConfigStats(stats.build());
+
+ //Update augmented data
+ nodeData.addAugmentation(NodeMeterConfigStats.class, meterConfig.build());
+
+ InstanceIdentifier<? extends Object> refValue = ref.getValue();
+ it.putRuntimeData(refValue, nodeData.build());
+ it.commit();
+
}
@Override
public void onMeterStatisticsUpdated(MeterStatisticsUpdated notification) {
- // TODO Auto-generated method stub
+ //Add statistics to local cache
+ ConcurrentMap<NodeId, NodeStatistics> cache = this.statisticsManager.getStatisticsCache();
+ if(!cache.containsKey(notification.getId())){
+ cache.put(notification.getId(), new NodeStatistics());
+ }
+ cache.get(notification.getId()).setMeterStatistics(notification.getMeterStats());
+
+ //Publish data to configuration data store
+ DataModificationTransaction it = this.statisticsManager.startChange();
+ NodeKey key = new NodeKey(notification.getId());
+ NodeRef ref = getNodeRef(key);
+
+ final NodeBuilder nodeData = new NodeBuilder();
+ nodeData.setKey(key);
+
+ NodeMeterStatisticsBuilder meterStats= new NodeMeterStatisticsBuilder();
+ MeterStatisticsBuilder stats = new MeterStatisticsBuilder();
+ stats.setMeterStats(notification.getMeterStats());
+ meterStats.setMeterStatistics(stats.build());
+
+ //Update augmented data
+ nodeData.addAugmentation(NodeMeterStatistics.class, meterStats.build());
+
+ InstanceIdentifier<? extends Object> refValue = ref.getValue();
+ it.putRuntimeData(refValue, nodeData.build());
+ it.commit();
}
@Override
public void onGroupDescStatsUpdated(GroupDescStatsUpdated notification) {
- // TODO Auto-generated method stub
+ //Add statistics to local cache
+ ConcurrentMap<NodeId, NodeStatistics> cache = this.statisticsManager.getStatisticsCache();
+ if(!cache.containsKey(notification.getId())){
+ cache.put(notification.getId(), new NodeStatistics());
+ }
+ cache.get(notification.getId()).setGroupDescStats(notification.getGroupDescStats());
+
+ //Publish data to configuration data store
+ DataModificationTransaction it = this.statisticsManager.startChange();
+ NodeKey key = new NodeKey(notification.getId());
+ NodeRef ref = getNodeRef(key);
+
+ final NodeBuilder nodeData = new NodeBuilder();
+ nodeData.setKey(key);
+
+ NodeGroupDescStatsBuilder groupDesc= new NodeGroupDescStatsBuilder();
+ GroupDescBuilder stats = new GroupDescBuilder();
+ stats.setGroupDescStats(notification.getGroupDescStats());
+ groupDesc.setGroupDesc(stats.build());
+
+ //Update augmented data
+ nodeData.addAugmentation(NodeGroupDescStats.class, groupDesc.build());
+
+ InstanceIdentifier<? extends Object> refValue = ref.getValue();
+ it.putRuntimeData(refValue, nodeData.build());
+ it.commit();
}
@Override
public void onGroupStatisticsUpdated(GroupStatisticsUpdated notification) {
- // TODO Auto-generated method stub
-
+
+ //Add statistics to local cache
+ ConcurrentMap<NodeId, NodeStatistics> cache = this.statisticsManager.getStatisticsCache();
+ if(!cache.containsKey(notification.getId())){
+ cache.put(notification.getId(), new NodeStatistics());
+ }
+ cache.get(notification.getId()).setGroupStatistics(notification.getGroupStats());
+
+ //Publish data to configuration data store
+
+ DataModificationTransaction it = this.statisticsManager.startChange();
+ NodeKey key = new NodeKey(notification.getId());
+ NodeRef ref = getNodeRef(key);
+
+ final NodeBuilder nodeData = new NodeBuilder();
+ nodeData.setKey(key);
+
+ NodeGroupStatisticsBuilder groupStats = new NodeGroupStatisticsBuilder();
+ GroupStatisticsBuilder stats = new GroupStatisticsBuilder();
+ stats.setGroupStats(notification.getGroupStats());
+ groupStats.setGroupStatistics(stats.build());
+
+ //Update augmented data
+ nodeData.addAugmentation(NodeGroupStatistics.class, groupStats.build());
+
+ InstanceIdentifier<? extends Object> refValue = ref.getValue();
+ it.putRuntimeData(refValue, nodeData.build());
+ it.commit();
}
+
@Override
public void onMeterFeaturesUpdated(MeterFeaturesUpdated notification) {
- // TODO Auto-generated method stub
+
+ //Add statistics to local cache
+ ConcurrentMap<NodeId, NodeStatistics> cache = this.statisticsManager.getStatisticsCache();
+ if(!cache.containsKey(notification.getId())){
+ cache.put(notification.getId(), new NodeStatistics());
+ }
+ MeterFeaturesBuilder meterFeature = new MeterFeaturesBuilder();
+ meterFeature.setBandTypes(notification.getBandTypes());
+ meterFeature.setCapabilities(notification.getCapabilities());
+ meterFeature.setMaxBands(notification.getMaxBands());
+ meterFeature.setMaxColor(notification.getMaxColor());
+ meterFeature.setMaxMeter(notification.getMaxMeter());
+
+ cache.get(notification.getId()).setMeterFeatures(meterFeature.build());
+
+ //Publish data to configuration data store
+ DataModificationTransaction it = this.statisticsManager.startChange();
+ NodeKey key = new NodeKey(notification.getId());
+ NodeRef ref = getNodeRef(key);
+
+ final NodeBuilder nodeData = new NodeBuilder();
+ nodeData.setKey(key);
+ NodeMeterFeaturesBuilder nodeMeterFeatures= new NodeMeterFeaturesBuilder();
+ nodeMeterFeatures.setMeterFeatures(meterFeature.build());
+
+ //Update augmented data
+ nodeData.addAugmentation(NodeMeterFeatures.class, nodeMeterFeatures.build());
+
+ InstanceIdentifier<? extends Object> refValue = ref.getValue();
+ it.putRuntimeData(refValue, nodeData.build());
+ it.commit();
}
+
@Override
public void onGroupFeaturesUpdated(GroupFeaturesUpdated notification) {
- // TODO Auto-generated method stub
+ //Add statistics to local cache
+ ConcurrentMap<NodeId, NodeStatistics> cache = this.statisticsManager.getStatisticsCache();
+ if(!cache.containsKey(notification.getId())){
+ cache.put(notification.getId(), new NodeStatistics());
+ }
+
+ GroupFeaturesBuilder groupFeatures = new GroupFeaturesBuilder();
+ groupFeatures.setActions(notification.getActions());
+ groupFeatures.setCapabilities(notification.getCapabilities());
+ groupFeatures.setGroupType(notification.getGroupType());
+ groupFeatures.setMaxGroups(notification.getMaxGroups());
+ cache.get(notification.getId()).setGroupFeatures(groupFeatures.build());
+
+ //Publish data to configuration data store
+ DataModificationTransaction it = this.statisticsManager.startChange();
+ NodeKey key = new NodeKey(notification.getId());
+ NodeRef ref = getNodeRef(key);
+ final NodeBuilder nodeData = new NodeBuilder();
+ nodeData.setKey(key);
+
+ NodeGroupFeaturesBuilder nodeGroupFeatures= new NodeGroupFeaturesBuilder();
+ nodeGroupFeatures.setGroupFeatures(groupFeatures.build());
+
+ //Update augmented data
+ nodeData.addAugmentation(NodeGroupFeatures.class, nodeGroupFeatures.build());
+
+ InstanceIdentifier<? extends Object> refValue = ref.getValue();
+ it.putRuntimeData(refValue, nodeData.build());
+ it.commit();
+ }
+
+ private NodeRef getNodeRef(NodeKey nodeKey){
+ InstanceIdentifierBuilder<?> builder = InstanceIdentifier.builder().node(Nodes.class);
+ return new NodeRef(builder.node(Node.class,nodeKey).toInstance());
}
}
private static Set<Capability> setupCapabilities(YangStoreSnapshot yangStoreSnapshot) {
Set<Capability> capabilities = Sets.newHashSet();
+ // [RFC6241] 8.3. Candidate Configuration Capability
capabilities.add(new BasicCapability("urn:ietf:params:netconf:capability:candidate:1.0"));
+ // [RFC6241] 8.5. Rollback-on-Error Capability
capabilities.add(new BasicCapability("urn:ietf:params:netconf:capability:rollback-on-error:1.0"));
- capabilities.add(new BasicCapability("urn:ietf:params:netconf:capability:operations:1.0"));
- capabilities.add(new BasicCapability("urn:ietf:params:netconf:capability:operations:1.1"));
- capabilities
- .add(new BasicCapability(
- "urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring?module=ietf-netconf-monitoring&revision=2010-10-04"));
+ // [RFC6022] get-schema RPC. TODO: implement rest of the RFC
+ capabilities.add(new BasicCapability("urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring?module=ietf-netconf-monitoring&revision=2010-10-04"));
final Collection<Map.Entry<Module, String>> modulesAndContents = yangStoreSnapshot.getModuleMap().values();
for (Map.Entry<Module, String> moduleAndContent : modulesAndContents) {
<version>1.5</version>
<executions>
<execution>
- <phase>install</phase>
+ <phase>package</phase>
<goals>
- <goal>run</goal>
+ <goal>run</goal>
</goals>
</execution>
</executions>
<!-- generate index.html -->
<!-- append header -->
<echo file="${docs.output.dir}/index.html" append="true">
-<![CDATA[
-<html>
- <head>
- <title> OpenDaylight REST API Documentation </title>
- </head>
- <body>
- <h2>OpenDaylight REST API Documentation</h2>
- <p> OpenDaylight supports the following <a href="http://en.wikipedia.org/wiki/Representational_State_Transfer">Representational State Transfer (REST)</a> APIs: </p>
- <h4>
-]]>
+ <![CDATA[
+ <html>
+ <head>
+ <title> OpenDaylight REST API Documentation </title>
+ </head>
+ <body>
+ <h2>OpenDaylight REST API Documentation</h2>
+ <p> OpenDaylight supports the following <a href="http://en.wikipedia.org/wiki/Representational_State_Transfer">Representational State Transfer (REST)</a> APIs: </p>
+ <h4>
+ ]]>
</echo>
<dirset id="nbset" dir="${docs.output.dir}">
<include name="*"/>
<!-- append footer -->
<echo file="${docs.output.dir}/index.html" append="true">
-<![CDATA[
- </h4>
- <i>---</i>
- </body>
-</html>
-]]>
+ <![CDATA[
+ </h4>
+ <i>---</i>
+ </body>
+ </html>
+ ]]>
</echo>
<!-- archive all the docs excluding whatever is not needed -->
<echo message="======== Archiving enunciate docs ========"/>
</plugin>
<plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-install-plugin</artifactId>
- <version>2.5</version>
- <configuration>
- <packaging>jar</packaging>
- <groupId>${project.groupId}</groupId>
- <version>${project.version}</version>
- </configuration>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>build-helper-maven-plugin</artifactId>
+ <version>1.8</version>
<executions>
<execution>
- <!-- skip default install -->
- <id>default-install</id>
- <phase>install</phase>
- <goals>
- <goal>install</goal>
- </goals>
- <configuration>
- <skip>true</skip>
- </configuration>
- </execution>
- <execution>
- <!-- install full java client -->
- <id>install-full-client</id>
- <phase>install</phase>
- <goals>
- <goal>install-file</goal>
- </goals>
- <configuration>
- <artifactId>${project.artifactId}.full-client</artifactId>
- <file>${java-client}</file>
- <sources>${java-client-sources}</sources>
- </configuration>
- </execution>
- <execution>
- <!-- install full java json client -->
- <id>install-full-json-client</id>
- <phase>install</phase>
+ <id>attach-artifacts</id>
+ <phase>package</phase>
<goals>
- <goal>install-file</goal>
+ <goal>attach-artifact</goal>
</goals>
<configuration>
- <artifactId>${project.artifactId}.full-json-client</artifactId>
- <file>${json-client}</file>
- <sources>${json-client-sources}</sources>
+ <artifacts>
+ <artifact>
+ <file>${java-client}</file>
+ <type>jar</type>
+ <classifier>full-java-client</classifier>
+ </artifact>
+ <artifact>
+ <file>${java-client-sources}</file>
+ <type>jar</type>
+ <classifier>full-java-client-sources</classifier>
+ </artifact>
+ <artifact>
+ <file>${json-client}</file>
+ <type>jar</type>
+ <classifier>full-json-client</classifier>
+ </artifact>
+ <artifact>
+ <file>${json-client-sources}</file>
+ <type>jar</type>
+ <classifier>full-json-client-sources</classifier>
+ </artifact>
+ </artifacts>
</configuration>
</execution>
</executions>
</plugin>
-
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-deploy-plugin</artifactId>
- <version>2.5</version>
- <configuration>
- <packaging>jar</packaging>
- <generatePom>true</generatePom>
- <groupId>${project.groupId}</groupId>
- <version>${project.version}</version>
- <url>${project.distributionManagement.repository.url}</url>
- </configuration>
- <executions>
- <execution>
- <!-- skip default deploy -->
- <id>default-deploy</id>
- <phase>deploy</phase>
- <goals>
- <goal>deploy</goal>
- </goals>
- <configuration>
- <skip>true</skip>
- </configuration>
- </execution>
- <execution>
- <!-- deploy full java client -->
- <id>deploy-full-client</id>
- <phase>deploy</phase>
- <goals>
- <goal>deploy-file</goal>
- </goals>
- <configuration>
- <artifactId>${project.artifactId}.full-client</artifactId>
- <file>${java-client}</file>
- <sources>${java-client-sources}</sources>
- </configuration>
- </execution>
- <execution>
- <!-- deploy full java json client -->
- <id>deploy-full-json-client</id>
- <phase>deploy</phase>
- <goals>
- <goal>deploy-file</goal>
- </goals>
- <configuration>
- <artifactId>${project.artifactId}.full-json-client</artifactId>
- <file>${json-client}</file>
- <sources>${json-client-sources}</sources>
- </configuration>
- </execution>
- </executions>
- </plugin>
-
</plugins>
</build>
<dependencies>
import org.opendaylight.controller.sal.topology.TopoEdgeUpdate;
import org.opendaylight.controller.sal.utils.GlobalConstants;
import org.opendaylight.controller.sal.utils.IObjectReader;
+import org.opendaylight.controller.sal.utils.NodeConnectorCreator;
import org.opendaylight.controller.sal.utils.ObjectReader;
import org.opendaylight.controller.sal.utils.ObjectWriter;
import org.opendaylight.controller.sal.utils.Status;
|| e.getTailNodeConnector().getType().equals(NodeConnector.NodeConnectorIDType.PRODUCTION));
}
+ /**
+ * This method cross checks the determination of nodeConnector type by Discovery Service
+ * against the information in SwitchManager and updates it accordingly.
+ * @param e
+ * The edge
+ */
+ private void crossCheckNodeConnectors(Edge e) {
+ NodeConnector nc;
+ if (e.getHeadNodeConnector().getType().equals(NodeConnector.NodeConnectorIDType.PRODUCTION)) {
+ nc = updateNCTypeFromSwitchMgr(e.getHeadNodeConnector());
+ if (nc != null) {
+ e.setHeadNodeConnector(nc);
+ }
+ }
+ if (e.getTailNodeConnector().getType().equals(NodeConnector.NodeConnectorIDType.PRODUCTION)) {
+ nc = updateNCTypeFromSwitchMgr(e.getTailNodeConnector());
+ if (nc != null) {
+ e.setTailNodeConnector(nc);
+ }
+ }
+ }
+
+ /**
+ * A NodeConnector may have been categorized as of type Production by Discovery Service.
+ * But at the time when this determination was made, only OF nodes were known to Discovery
+ * Service. This method checks if the node of nodeConnector is known to SwitchManager. If
+ * so, then it returns a new NodeConnector with correct type.
+ *
+ * @param nc
+ * NodeConnector as passed on in the edge
+ * @return
+ * If Node of the NodeConnector is in SwitchManager, then return a new NodeConnector
+ * with correct type, null otherwise
+ */
+
+ private NodeConnector updateNCTypeFromSwitchMgr(NodeConnector nc) {
+
+ for (Node node : switchManager.getNodes()) {
+ String nodeName = node.getNodeIDString();
+ log.trace("Switch Manager Node Name: {}, NodeConnector Node Name: {}", nodeName,
+ nc.getNode().getNodeIDString());
+ if (nodeName.equals(nc.getNode().getNodeIDString())) {
+ NodeConnector nodeConnector = NodeConnectorCreator
+ .createNodeConnector(node.getType(), nc.getID(), node);
+ return nodeConnector;
+ }
+ }
+ return null;
+ }
+
/**
* The Map returned is a copy of the current topology hence if the topology
* changes the copy doesn't
return null;
}
+ // Check if nodeConnectors of the edge were correctly categorized
+ // by OF plugin
+ crossCheckNodeConnectors(e);
+
// Make sure the props are non-null
if (props == null) {
props = new HashSet<Property>();