/*
* Copyright (c) 2016 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.groupbasedpolicy.renderer;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import javax.annotation.Nullable;
import com.google.common.annotations.VisibleForTesting;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.CommonEndpointFields;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.NatAddress;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoint.locations.AddressEndpointLocation;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoint.locations.ContainmentEndpointLocation;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.address.endpoints.AddressEndpoint;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.address.endpoints.AddressEndpointKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.containment.endpoints.ContainmentEndpoint;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.containment.endpoints.ContainmentEndpointKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.relative.location.RelativeLocations;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.Forwarding;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.forwarding.ForwardingByTenant;
import com.google.common.base.Equivalence;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.MapDifference;
import com.google.common.collect.Maps;
class DtoEquivalenceUtils {
private static final Function<ForwardingByTenant, TenantId> FORWARDING_BY_TENANT_TO_TENANT_ID =
new Function<ForwardingByTenant, TenantId>() {
@Override
public TenantId apply(ForwardingByTenant input) {
return input.getTenantId();
}
};
@VisibleForTesting
static final Equivalence<AddressEndpoint> ADDR_EP_EQ = new Equivalence<AddressEndpoint>() {
@Override
protected boolean doEquivalent(AddressEndpoint a, AddressEndpoint b) {
if (!Objects.equals(a.getKey(), b.getKey())) {
return false;
}
if (!Objects.equals(a.getParentEndpointChoice(), b.getParentEndpointChoice())) {
return false;
}
if (!equalsDtoLists(a.getChildEndpoint(), b.getChildEndpoint())) {
return false;
}
if (!equalsCommonEndpointFields(a, b)) {
return false;
}
if (!equalsAugmentations(a, b)) {
return false;
}
return true;
}
@Override
protected int doHash(AddressEndpoint t) {
return t.hashCode();
}
};
@VisibleForTesting
static final Equivalence<ContainmentEndpoint> CONT_EP_EQ = new Equivalence<ContainmentEndpoint>() {
@Override
protected boolean doEquivalent(ContainmentEndpoint a, ContainmentEndpoint b) {
if (!Objects.equals(a.getKey(), b.getKey())) {
return false;
}
if (!equalsDtoLists(a.getChildEndpoint(), b.getChildEndpoint())) {
return false;
}
if (!equalsCommonEndpointFields(a, b)) {
return false;
}
return true;
}
@Override
protected int doHash(ContainmentEndpoint t) {
return t.hashCode();
}
};
@VisibleForTesting
static final Equivalence<AddressEndpointLocation> ADDR_EP_LOC_EQ =
new Equivalence<AddressEndpointLocation>() {
@Override
protected boolean doEquivalent(AddressEndpointLocation a, AddressEndpointLocation b) {
if (!Objects.equals(a.getKey(), b.getKey())) {
return false;
}
if (!Objects.equals(a.getAbsoluteLocation(), b.getAbsoluteLocation())) {
return false;
}
if (!equalsRelativeLocations(a.getRelativeLocations(), b.getRelativeLocations())) {
return false;
}
return true;
}
@Override
protected int doHash(AddressEndpointLocation t) {
return t.hashCode();
}
};
@VisibleForTesting
static final Equivalence<ContainmentEndpointLocation> CONT_EP_LOC_EQ =
new Equivalence<ContainmentEndpointLocation>() {
@Override
protected boolean doEquivalent(ContainmentEndpointLocation a, ContainmentEndpointLocation b) {
if (!Objects.equals(a.getKey(), b.getKey())) {
return false;
}
if (!equalsRelativeLocations(a.getRelativeLocations(), b.getRelativeLocations())) {
return false;
}
return true;
}
@Override
protected int doHash(ContainmentEndpointLocation t) {
return t.hashCode();
}
};
@VisibleForTesting
static final Equivalence<ForwardingByTenant> FWD_BY_TENANT_EQ = new Equivalence<ForwardingByTenant>() {
@Override
protected boolean doEquivalent(ForwardingByTenant x, ForwardingByTenant y) {
if (!Objects.equals(x.getKey(), y.getKey())) {
return false;
}
if (!equalsDtoLists(x.getForwardingContext(), y.getForwardingContext())) {
return false;
}
if (!equalsDtoLists(x.getNetworkDomain(), y.getNetworkDomain())) {
return false;
}
return true;
}
@Override
protected int doHash(ForwardingByTenant t) {
return t.hashCode();
}
};
private DtoEquivalenceUtils() {}
private static boolean equalsAugmentations(AddressEndpoint a, AddressEndpoint b) {
if (a.getAugmentation(NatAddress.class) != null && b.getAugmentation(NatAddress.class) != null) {
if (!a.getAugmentation(NatAddress.class)
.getNatAddress()
.equals(b.getAugmentation(NatAddress.class).getNatAddress())) {
return false;
}
} else if (a.getAugmentation(NatAddress.class) != null || b.getAugmentation(NatAddress.class) != null) {
return false;
}
return true;
}
static boolean equalsAddressEpByKey(@Nullable Map<AddressEndpointKey, AddressEndpoint> o1,
@Nullable Map<AddressEndpointKey, AddressEndpoint> o2) {
return equalsDtoMapsByEquivalence(o1, o2, ADDR_EP_EQ);
}
static boolean equalsContainmentEpByKey(@Nullable Map<ContainmentEndpointKey, ContainmentEndpoint> o1,
@Nullable Map<ContainmentEndpointKey, ContainmentEndpoint> o2) {
return equalsDtoMapsByEquivalence(o1, o2, CONT_EP_EQ);
}
static boolean equalsAddrEpLocByAddrEpKey(Map<AddressEndpointKey, AddressEndpointLocation> o1,
Map<AddressEndpointKey, AddressEndpointLocation> o2) {
return equalsDtoMapsByEquivalence(o1, o2, ADDR_EP_LOC_EQ);
}
static boolean equalsContEpLocByContEpKey(Map<ContainmentEndpointKey, ContainmentEndpointLocation> o1,
Map<ContainmentEndpointKey, ContainmentEndpointLocation> o2) {
return equalsDtoMapsByEquivalence(o1, o2, CONT_EP_LOC_EQ);
}
static boolean equalsForwarding(@Nullable Forwarding a, @Nullable Forwarding b) {
if ((a == null && b != null) || (a != null && b == null)) {
return false;
}
if (a == null && b == null) {
return true;
}
return equalsForwardingByTenantLists(a.getForwardingByTenant(), b.getForwardingByTenant());
}
private static boolean equalsCommonEndpointFields(CommonEndpointFields a, CommonEndpointFields b) {
if (!Objects.equals(a.getNetworkContainment(), b.getNetworkContainment())) {
return false;
}
if (!Objects.equals(a.getTenant(), b.getTenant())) {
return false;
}
if (!Objects.equals(a.getTimestamp(), b.getTimestamp())) {
return false;
}
if (!equalsDtoLists(a.getCondition(), b.getCondition())) {
return false;
}
if (!equalsDtoLists(a.getEndpointGroup(), b.getEndpointGroup())) {
return false;
}
return true;
}
private static boolean equalsRelativeLocations(RelativeLocations a, RelativeLocations b) {
if ((a == null && b != null) || (a != null && b == null)) {
return false;
}
if (a == null && b == null) {
return true;
}
if (!equalsDtoLists(a.getExternalLocation(), b.getExternalLocation())) {
return false;
}
if (!equalsDtoLists(a.getInternalLocation(), b.getInternalLocation())) {
return false;
}
return true;
}
private static boolean equalsForwardingByTenantLists(List<ForwardingByTenant> a, List<ForwardingByTenant> b) {
if ((a == null && b != null) || (a != null && b == null)) {
return false;
}
if (a == null && b == null) {
return true;
}
if (a.size() != b.size()) {
return false;
}
ImmutableMap<TenantId, ForwardingByTenant> aMap = Maps.uniqueIndex(a, FORWARDING_BY_TENANT_TO_TENANT_ID);
ImmutableMap<TenantId, ForwardingByTenant> bMap = Maps.uniqueIndex(b, FORWARDING_BY_TENANT_TO_TENANT_ID);
return equalsDtoMapsByEquivalence(aMap, bMap, FWD_BY_TENANT_EQ);
}
private static <K, V> boolean equalsDtoMapsByEquivalence(@Nullable Map<K, V> o1, @Nullable Map<K, V> o2,
Equivalence<V> eq) {
if ((o1 == null && o2 != null) || (o1 != null && o2 == null)) {
return false;
}
if (o1 == null && o2 == null) {
return true;
}
if (o1.size() != o2.size()) {
return false;
}
MapDifference<K, V> diff = Maps.difference(o1, o2, eq);
if (!diff.entriesOnlyOnLeft().isEmpty() || !diff.entriesOnlyOnRight().isEmpty()) {
return false;
}
if (!diff.entriesDiffering().isEmpty()) {
return false;
}
return true;
}
private static <T> boolean equalsDtoLists(@Nullable List<T> a, @Nullable List<T> b) {
if ((a == null && b != null) || (a != null && b == null)) {
return false;
}
if (a == null && b == null) {
return true;
}
return a.size() == b.size() && a.containsAll(b);
}
}