/*
* Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. 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.ovsdb.hwvtepsouthbound.transact;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.ovsdb.hwvtepsouthbound.HwvtepDeviceInfo;
import org.opendaylight.ovsdb.utils.mdsal.utils.MdsalUtils;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.LogicalSwitches;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.Identifiable;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Utility class to retrieve the unmet dependencies (config/operational) of the given object
* @param <T>
*/
public abstract class UnMetDependencyGetter<T extends Identifiable> {
private final ConfigDependencyGetter configDependencyGetter = new ConfigDependencyGetter();
private final InTransitDependencyGetter inTransitDependencyGetter = new InTransitDependencyGetter();
/**
* Returns the iids this data depends upon
* which are already intransit in the previous transaction if any
* @param opState The operatonal state
* @param data The data object
* @return The depenencies
*/
public Map<Class<? extends Identifiable>, List<InstanceIdentifier>> getInTransitDependencies(
HwvtepOperationalState opState, T data) {
return inTransitDependencyGetter.retrieveUnMetDependencies(opState, opState.getDeviceInfo(), data);
}
/**
* Returns the iids this data depends upon
* which are not yet present in the config data store if any
* @param opState The operatonal state
* @param data The data object
* @return the depenencies
*/
public Map<Class<? extends Identifiable>, List<InstanceIdentifier>> getUnMetConfigDependencies(
HwvtepOperationalState opState, T data) {
return configDependencyGetter.retrieveUnMetDependencies(opState, opState.getDeviceInfo(), data);
}
abstract class DependencyGetter {
Map<Class<? extends Identifiable>, List<InstanceIdentifier>> retrieveUnMetDependencies(
HwvtepOperationalState opState, HwvtepDeviceInfo deviceInfo, T data) {
Map<Class<? extends Identifiable>, List<InstanceIdentifier>> result = new HashMap<>();
Map<Class<? extends Identifiable>, List<InstanceIdentifier<?>>> allKeys = new HashMap<>();
allKeys.put(LogicalSwitches.class, getLogicalSwitchDependencies(data));
allKeys.put(TerminationPoint.class, getTerminationPointDependencies(data));
for (Class<? extends Identifiable> cls : allKeys.keySet()) {
List<InstanceIdentifier<? extends DataObject>> keysToCheck = allKeys.get(cls);
for (InstanceIdentifier<? extends DataObject> key : keysToCheck) {
if (!isDependencyMet(opState, deviceInfo, cls, key)) {
result = addToResultMap(result, cls, key);
}
}
}
return result;
}
Map<Class<? extends Identifiable>, List<InstanceIdentifier>> addToResultMap(
Map<Class<? extends Identifiable>, List<InstanceIdentifier>> result,
Class<? extends Identifiable> cls, InstanceIdentifier<? extends DataObject> key) {
if (null == result) {
result = new HashMap<>();
}
if (!result.containsKey(cls)) {
result.put(cls, new ArrayList<>());
}
result.get(cls).add(key);
return result;
}
abstract boolean isDependencyMet(HwvtepOperationalState opState, HwvtepDeviceInfo deviceInfo,
Class<? extends Identifiable> cls, InstanceIdentifier<? extends DataObject> key);
}
class ConfigDependencyGetter extends DependencyGetter {
boolean isDependencyMet(HwvtepOperationalState opState, HwvtepDeviceInfo deviceInfo,
Class<? extends Identifiable> cls, InstanceIdentifier<? extends DataObject> key) {
return deviceInfo.isConfigDataAvailable(cls, key) || isConfigDataAvailable(opState, key);
}
boolean isConfigDataAvailable(HwvtepOperationalState opState, InstanceIdentifier<? extends DataObject> key) {
DataBroker db = opState.getConnectionInstance().getDataBroker();
MdsalUtils mdsalUtils = new MdsalUtils(db);
return mdsalUtils.read(LogicalDatastoreType.CONFIGURATION, key) != null;
}
}
class InTransitDependencyGetter extends DependencyGetter {
boolean isDependencyMet(HwvtepOperationalState opState, HwvtepDeviceInfo deviceInfo,
Class<? extends Identifiable> cls, InstanceIdentifier<? extends DataObject> key) {
return opState.isKeyPartOfCurrentTx(cls, key) || !deviceInfo.isKeyInTransit(cls, key);
}
}
public abstract List<InstanceIdentifier<?>> getLogicalSwitchDependencies(T data);
public abstract List<InstanceIdentifier<?>> getTerminationPointDependencies(T data);
}