implementing routing for VPP
[groupbasedpolicy.git] / groupbasedpolicy / src / main / java / org / opendaylight / groupbasedpolicy / renderer / DtoEquivalenceUtils.java
1 /*
2  * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8
9 package org.opendaylight.groupbasedpolicy.renderer;
10
11 import java.util.List;
12 import java.util.Map;
13 import java.util.Objects;
14
15 import javax.annotation.Nullable;
16
17 import com.google.common.annotations.VisibleForTesting;
18 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.CommonEndpointFields;
19 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.NatAddress;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoint.locations.AddressEndpointLocation;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoint.locations.ContainmentEndpointLocation;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.address.endpoints.AddressEndpoint;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.address.endpoints.AddressEndpointKey;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.containment.endpoints.ContainmentEndpoint;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.containment.endpoints.ContainmentEndpointKey;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.relative.location.RelativeLocations;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.Forwarding;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.forwarding.ForwardingByTenant;
30
31 import com.google.common.base.Equivalence;
32 import com.google.common.base.Function;
33 import com.google.common.collect.ImmutableMap;
34 import com.google.common.collect.MapDifference;
35 import com.google.common.collect.Maps;
36
37 class DtoEquivalenceUtils {
38
39     private static final Function<ForwardingByTenant, TenantId> FORWARDING_BY_TENANT_TO_TENANT_ID =
40             new Function<ForwardingByTenant, TenantId>() {
41
42                 @Override
43                 public TenantId apply(ForwardingByTenant input) {
44                     return input.getTenantId();
45                 }
46             };
47
48     @VisibleForTesting
49     static final Equivalence<AddressEndpoint> ADDR_EP_EQ = new Equivalence<AddressEndpoint>() {
50
51         @Override
52         protected boolean doEquivalent(AddressEndpoint a, AddressEndpoint b) {
53             if (!Objects.equals(a.getKey(), b.getKey())) {
54                 return false;
55             }
56             if (!Objects.equals(a.getParentEndpointChoice(), b.getParentEndpointChoice())) {
57                 return false;
58             }
59             if (!equalsDtoLists(a.getChildEndpoint(), b.getChildEndpoint())) {
60                 return false;
61             }
62             if (!equalsCommonEndpointFields(a, b)) {
63                 return false;
64             }
65             if (!equalsAugmentations(a, b)) {
66                 return false;
67             }
68             return true;
69         }
70
71         @Override
72         protected int doHash(AddressEndpoint t) {
73             return t.hashCode();
74         }
75     };
76     @VisibleForTesting
77     static final Equivalence<ContainmentEndpoint> CONT_EP_EQ = new Equivalence<ContainmentEndpoint>() {
78
79         @Override
80         protected boolean doEquivalent(ContainmentEndpoint a, ContainmentEndpoint b) {
81             if (!Objects.equals(a.getKey(), b.getKey())) {
82                 return false;
83             }
84             if (!equalsDtoLists(a.getChildEndpoint(), b.getChildEndpoint())) {
85                 return false;
86             }
87             if (!equalsCommonEndpointFields(a, b)) {
88                 return false;
89             }
90             return true;
91         }
92
93         @Override
94         protected int doHash(ContainmentEndpoint t) {
95             return t.hashCode();
96         }
97     };
98     @VisibleForTesting
99     static final Equivalence<AddressEndpointLocation> ADDR_EP_LOC_EQ =
100             new Equivalence<AddressEndpointLocation>() {
101
102                 @Override
103                 protected boolean doEquivalent(AddressEndpointLocation a, AddressEndpointLocation b) {
104                     if (!Objects.equals(a.getKey(), b.getKey())) {
105                         return false;
106                     }
107                     if (!Objects.equals(a.getAbsoluteLocation(), b.getAbsoluteLocation())) {
108                         return false;
109                     }
110                     if (!equalsRelativeLocations(a.getRelativeLocations(), b.getRelativeLocations())) {
111                         return false;
112                     }
113                     return true;
114                 }
115
116                 @Override
117                 protected int doHash(AddressEndpointLocation t) {
118                     return t.hashCode();
119                 }
120             };
121     @VisibleForTesting
122     static final Equivalence<ContainmentEndpointLocation> CONT_EP_LOC_EQ =
123             new Equivalence<ContainmentEndpointLocation>() {
124
125                 @Override
126                 protected boolean doEquivalent(ContainmentEndpointLocation a, ContainmentEndpointLocation b) {
127                     if (!Objects.equals(a.getKey(), b.getKey())) {
128                         return false;
129                     }
130                     if (!equalsRelativeLocations(a.getRelativeLocations(), b.getRelativeLocations())) {
131                         return false;
132                     }
133                     return true;
134                 }
135
136                 @Override
137                 protected int doHash(ContainmentEndpointLocation t) {
138                     return t.hashCode();
139                 }
140             };
141     @VisibleForTesting
142     static final Equivalence<ForwardingByTenant> FWD_BY_TENANT_EQ = new Equivalence<ForwardingByTenant>() {
143
144         @Override
145         protected boolean doEquivalent(ForwardingByTenant x, ForwardingByTenant y) {
146             if (!Objects.equals(x.getKey(), y.getKey())) {
147                 return false;
148             }
149             if (!equalsDtoLists(x.getForwardingContext(), y.getForwardingContext())) {
150                 return false;
151             }
152             if (!equalsDtoLists(x.getNetworkDomain(), y.getNetworkDomain())) {
153                 return false;
154             }
155             return true;
156         }
157
158         @Override
159         protected int doHash(ForwardingByTenant t) {
160             return t.hashCode();
161         }
162     };
163
164     private DtoEquivalenceUtils() {}
165
166     private static boolean equalsAugmentations(AddressEndpoint a, AddressEndpoint b) {
167         if (a.getAugmentation(NatAddress.class) != null && b.getAugmentation(NatAddress.class) != null) {
168             if (!a.getAugmentation(NatAddress.class)
169                 .getNatAddress()
170                 .equals(b.getAugmentation(NatAddress.class).getNatAddress())) {
171                 return false;
172             }
173         } else if (a.getAugmentation(NatAddress.class) != null || b.getAugmentation(NatAddress.class) != null) {
174             return false;
175         }
176         return true;
177     }
178
179     static boolean equalsAddressEpByKey(@Nullable Map<AddressEndpointKey, AddressEndpoint> o1,
180             @Nullable Map<AddressEndpointKey, AddressEndpoint> o2) {
181         return equalsDtoMapsByEquivalence(o1, o2, ADDR_EP_EQ);
182     }
183
184     static boolean equalsContainmentEpByKey(@Nullable Map<ContainmentEndpointKey, ContainmentEndpoint> o1,
185             @Nullable Map<ContainmentEndpointKey, ContainmentEndpoint> o2) {
186         return equalsDtoMapsByEquivalence(o1, o2, CONT_EP_EQ);
187     }
188
189     static boolean equalsAddrEpLocByAddrEpKey(Map<AddressEndpointKey, AddressEndpointLocation> o1,
190             Map<AddressEndpointKey, AddressEndpointLocation> o2) {
191         return equalsDtoMapsByEquivalence(o1, o2, ADDR_EP_LOC_EQ);
192     }
193
194     static boolean equalsContEpLocByContEpKey(Map<ContainmentEndpointKey, ContainmentEndpointLocation> o1,
195             Map<ContainmentEndpointKey, ContainmentEndpointLocation> o2) {
196         return equalsDtoMapsByEquivalence(o1, o2, CONT_EP_LOC_EQ);
197     }
198
199     static boolean equalsForwarding(@Nullable Forwarding a, @Nullable Forwarding b) {
200         if ((a == null && b != null) || (a != null && b == null)) {
201             return false;
202         }
203         if (a == null && b == null) {
204             return true;
205         }
206         return equalsForwardingByTenantLists(a.getForwardingByTenant(), b.getForwardingByTenant());
207     }
208
209     private static boolean equalsCommonEndpointFields(CommonEndpointFields a, CommonEndpointFields b) {
210         if (!Objects.equals(a.getNetworkContainment(), b.getNetworkContainment())) {
211             return false;
212         }
213         if (!Objects.equals(a.getTenant(), b.getTenant())) {
214             return false;
215         }
216         if (!Objects.equals(a.getTimestamp(), b.getTimestamp())) {
217             return false;
218         }
219         if (!equalsDtoLists(a.getCondition(), b.getCondition())) {
220             return false;
221         }
222         if (!equalsDtoLists(a.getEndpointGroup(), b.getEndpointGroup())) {
223             return false;
224         }
225         return true;
226     }
227
228     private static boolean equalsRelativeLocations(RelativeLocations a, RelativeLocations b) {
229         if ((a == null && b != null) || (a != null && b == null)) {
230             return false;
231         }
232         if (a == null && b == null) {
233             return true;
234         }
235         if (!equalsDtoLists(a.getExternalLocation(), b.getExternalLocation())) {
236             return false;
237         }
238         if (!equalsDtoLists(a.getInternalLocation(), b.getInternalLocation())) {
239             return false;
240         }
241         return true;
242     }
243
244     private static boolean equalsForwardingByTenantLists(List<ForwardingByTenant> a, List<ForwardingByTenant> b) {
245         if ((a == null && b != null) || (a != null && b == null)) {
246             return false;
247         }
248         if (a == null && b == null) {
249             return true;
250         }
251         if (a.size() != b.size()) {
252             return false;
253         }
254         ImmutableMap<TenantId, ForwardingByTenant> aMap = Maps.uniqueIndex(a, FORWARDING_BY_TENANT_TO_TENANT_ID);
255         ImmutableMap<TenantId, ForwardingByTenant> bMap = Maps.uniqueIndex(b, FORWARDING_BY_TENANT_TO_TENANT_ID);
256         return equalsDtoMapsByEquivalence(aMap, bMap, FWD_BY_TENANT_EQ);
257     }
258
259     private static <K, V> boolean equalsDtoMapsByEquivalence(@Nullable Map<K, V> o1, @Nullable Map<K, V> o2,
260             Equivalence<V> eq) {
261         if ((o1 == null && o2 != null) || (o1 != null && o2 == null)) {
262             return false;
263         }
264         if (o1 == null && o2 == null) {
265             return true;
266         }
267         if (o1.size() != o2.size()) {
268             return false;
269         }
270         MapDifference<K, V> diff = Maps.difference(o1, o2, eq);
271         if (!diff.entriesOnlyOnLeft().isEmpty() || !diff.entriesOnlyOnRight().isEmpty()) {
272             return false;
273         }
274         if (!diff.entriesDiffering().isEmpty()) {
275             return false;
276         }
277         return true;
278     }
279
280     private static <T> boolean equalsDtoLists(@Nullable List<T> a, @Nullable List<T> b) {
281         if ((a == null && b != null) || (a != null && b == null)) {
282             return false;
283         }
284         if (a == null && b == null) {
285             return true;
286         }
287         return a.size() == b.size() && a.containsAll(b);
288     }
289 }