/**
* Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0 which accompanies this distribution,
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
package org.opendaylight.controller.frm.impl;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import org.opendaylight.controller.frm.ForwardingRulesCommiter;
import org.opendaylight.controller.frm.ForwardingRulesManager;
import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
/**
* AbstractChangeListner implemented basic {@link AsyncDataChangeEvent} processing for
* flow node subDataObject (flows, groups and meters).
*
* @author Vaclav Demcak
*
*/
public abstract class AbstractListeningCommiter implements ForwardingRulesCommiter {
protected ForwardingRulesManager provider;
protected final Class clazz;
public AbstractListeningCommiter (ForwardingRulesManager provider, Class clazz) {
this.provider = Preconditions.checkNotNull(provider, "ForwardingRulesManager can not be null!");
this.clazz = Preconditions.checkNotNull(clazz, "Class can not be null!");
}
@Override
public void onDataChanged(final AsyncDataChangeEvent, DataObject> changeEvent) {
Preconditions.checkNotNull(changeEvent,"Async ChangeEvent can not be null!");
/* All DataObjects for create */
final Map, DataObject> createdData = changeEvent.getCreatedData() != null
? changeEvent.getCreatedData() : Collections., DataObject> emptyMap();
/* All DataObjects for remove */
final Set> removeData = changeEvent.getRemovedPaths() != null
? changeEvent.getRemovedPaths() : Collections.> emptySet();
/* All DataObjects for updates */
final Map, DataObject> updateData = changeEvent.getUpdatedData() != null
? changeEvent.getUpdatedData() : Collections., DataObject> emptyMap();
/* All Original DataObjects */
final Map, DataObject> originalData = changeEvent.getOriginalData() != null
? changeEvent.getOriginalData() : Collections., DataObject> emptyMap();
this.createData(createdData);
this.updateData(updateData, originalData);
this.removeData(removeData, originalData);
}
/**
* Method return wildCardPath for Listener registration
* and for identify the correct KeyInstanceIdentifier from data;
*/
protected abstract InstanceIdentifier getWildCardPath();
@SuppressWarnings("unchecked")
private void createData(final Map, DataObject> createdData) {
final Set> keys = createdData.keySet() != null
? createdData.keySet() : Collections.> emptySet();
for (InstanceIdentifier> key : keys) {
if (clazz.equals(key.getTargetType())) {
final InstanceIdentifier nodeIdent =
key.firstIdentifierOf(FlowCapableNode.class);
if (preConfigurationCheck(nodeIdent)) {
InstanceIdentifier createKeyIdent = key.firstIdentifierOf(clazz);
final Optional value = Optional.of(createdData.get(key));
if (value.isPresent()) {
this.add(createKeyIdent, (T)value.get(), nodeIdent);
}
}
}
}
}
@SuppressWarnings("unchecked")
private void updateData(final Map, DataObject> updateData,
final Map, DataObject> originalData) {
final Set> keys = updateData.keySet() != null
? updateData.keySet() : Collections.> emptySet();
for (InstanceIdentifier> key : keys) {
if (clazz.equals(key.getTargetType())) {
final InstanceIdentifier nodeIdent =
key.firstIdentifierOf(FlowCapableNode.class);
if (preConfigurationCheck(nodeIdent)) {
InstanceIdentifier updateKeyIdent = key.firstIdentifierOf(clazz);
final Optional value = Optional.of(updateData.get(key));
final Optional original = Optional.of(originalData.get(key));
if (value.isPresent() && original.isPresent()) {
this.update(updateKeyIdent, (T)original.get(), (T)value.get(), nodeIdent);
}
}
}
}
}
@SuppressWarnings("unchecked")
private void removeData(final Set> removeData,
final Map, DataObject> originalData) {
for (InstanceIdentifier> key : removeData) {
if (clazz.equals(key.getTargetType())) {
final InstanceIdentifier nodeIdent =
key.firstIdentifierOf(FlowCapableNode.class);
if (preConfigurationCheck(nodeIdent)) {
final InstanceIdentifier ident = key.firstIdentifierOf(clazz);
final DataObject removeValue = originalData.get(key);
this.remove(ident, (T)removeValue, nodeIdent);
}
}
}
}
private boolean preConfigurationCheck(final InstanceIdentifier nodeIdent) {
Preconditions.checkNotNull(nodeIdent, "FlowCapableNode ident can not be null!");
return provider.isNodeActive(nodeIdent);
}
}