Integrating FAAS renderer with the faas fabric mapping services. Also,
[groupbasedpolicy.git] / groupbasedpolicy / src / main / java / org / opendaylight / groupbasedpolicy / util / InheritanceUtils.java
1 /*
2  * Copyright (c) 2014 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.util;
10
11 import java.util.ArrayList;
12 import java.util.Collection;
13 import java.util.Collections;
14 import java.util.HashMap;
15 import java.util.HashSet;
16 import java.util.List;
17
18 import org.opendaylight.groupbasedpolicy.util.MatcherUtils.GetLabelName;
19 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.CapabilityMatcherName;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.CapabilityName;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ClauseName;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ConditionMatcherName;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ConditionName;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ContractId;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.EndpointGroupId;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.LabelName;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.NetworkDomainId;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.QualityMatcherName;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.QualityName;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.RequirementMatcherName;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.RequirementName;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.SelectorName;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.SubjectName;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TargetName;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.Label;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.has.capabilities.Capability;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.has.condition.matchers.ConditionMatcher;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.has.condition.matchers.ConditionMatcherBuilder;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.has.conditions.Condition;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.has.qualities.Quality;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.has.requirements.Requirement;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.target.selector.QualityMatcher;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.target.selector.QualityMatcherBuilder;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.target.selector.quality.matcher.MatcherQuality;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.Tenant;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.TenantBuilder;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.Policy;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.PolicyBuilder;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.Contract;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.ContractBuilder;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.EndpointGroup;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.EndpointGroup.IntraGroupPolicy;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.EndpointGroupBuilder;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.contract.Clause;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.contract.ClauseBuilder;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.contract.Subject;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.contract.SubjectBuilder;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.contract.Target;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.contract.TargetBuilder;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.contract.clause.ConsumerMatchers;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.contract.clause.ConsumerMatchersBuilder;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.contract.clause.ProviderMatchers;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.contract.clause.ProviderMatchersBuilder;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.contract.clause.consumer.matchers.GroupIdentificationConstraints;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.contract.clause.consumer.matchers.group.identification.constraints.GroupRequirementConstraintCase;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.contract.clause.consumer.matchers.group.identification.constraints.GroupRequirementConstraintCaseBuilder;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.contract.clause.consumer.matchers.group.identification.constraints.group.requirement.constraint._case.RequirementMatcher;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.contract.clause.consumer.matchers.group.identification.constraints.group.requirement.constraint._case.RequirementMatcherBuilder;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.contract.clause.consumer.matchers.group.identification.constraints.group.requirement.constraint._case.requirement.matcher.MatcherRequirement;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.contract.clause.provider.matchers.group.identification.constraints.GroupCapabilityConstraintCase;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.contract.clause.provider.matchers.group.identification.constraints.GroupCapabilityConstraintCaseBuilder;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.contract.clause.provider.matchers.group.identification.constraints.group.capability.constraint._case.CapabilityMatcher;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.contract.clause.provider.matchers.group.identification.constraints.group.capability.constraint._case.CapabilityMatcherBuilder;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.contract.clause.provider.matchers.group.identification.constraints.group.capability.constraint._case.capability.matcher.MatcherCapability;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.contract.subject.Rule;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.contract.subject.RuleBuilder;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.endpoint.group.ConsumerNamedSelector;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.endpoint.group.ConsumerNamedSelectorBuilder;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.endpoint.group.ConsumerTargetSelector;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.endpoint.group.ConsumerTargetSelectorBuilder;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.endpoint.group.ProviderNamedSelector;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.endpoint.group.ProviderNamedSelectorBuilder;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.endpoint.group.ProviderTargetSelector;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.endpoint.group.ProviderTargetSelectorBuilder;
85
86 import com.google.common.base.Preconditions;
87 import com.google.common.collect.ImmutableList;
88
89 /**
90  * Utilities useful for resolving the inheritance rules for the various objects
91  * in the system
92  *
93  * @author readams
94  *
95  */
96 public class InheritanceUtils {
97
98     private InheritanceUtils() {
99         throw new UnsupportedOperationException("Cannot create an instance");
100     }
101
102     /**
103      * Fully resolve the specified {@link Tenant}, returning a tenant with all
104      * items fully normalized. This means that no items will have parent/child
105      * relationships and can be interpreted simply without regard to inheritance
106      * rules
107      *
108      * @param unresolvedTenant
109      *            the {@link Tenant} unresolved tenant to resolve
110      * @return the fully-resolved {@link Tenant}
111      * @throws NullPointerException if parameter {@code unresolvedTenant} is {@code null}
112      */
113     public static Tenant resolveTenant(Tenant unresolvedTenant) {
114         Preconditions.checkNotNull(unresolvedTenant);
115         HashMap<EndpointGroupId, EndpointGroup> resolvedEgs = new HashMap<>();
116         HashMap<ContractId, Contract> resolvedContracts = new HashMap<>();
117         TenantBuilder resolvedTenantBuilder = new TenantBuilder().setId(unresolvedTenant.getId())
118                 .setName(unresolvedTenant.getName())
119                 .setDescription(unresolvedTenant.getDescription());
120
121         Policy unresolvedPolicy = unresolvedTenant.getPolicy();
122         if (unresolvedPolicy != null) {
123             if (unresolvedPolicy.getEndpointGroup() != null) {
124                 for (EndpointGroup eg : unresolvedPolicy.getEndpointGroup()) {
125                     resolveEndpointGroup(unresolvedTenant, eg, resolvedEgs);
126                 }
127             }
128             if (unresolvedPolicy.getContract() != null) {
129                 for (Contract c : unresolvedPolicy.getContract()) {
130                     resolveContract(unresolvedTenant, c, resolvedContracts);
131                 }
132             }
133             resolvedTenantBuilder
134             .setPolicy(new PolicyBuilder().setEndpointGroup(ImmutableList.copyOf(resolvedEgs.values()))
135                 .setContract(ImmutableList.copyOf(resolvedContracts.values()))
136                 .setContractRef(unresolvedPolicy.getContractRef())
137                 .setExternalImplicitGroup(unresolvedPolicy.getExternalImplicitGroup())
138                 .setSubjectFeatureInstances(unresolvedPolicy.getSubjectFeatureInstances())
139                 .build());
140         }
141
142         // XXX TODO - inherit from common tenant
143
144         resolvedTenantBuilder.setForwardingContext(unresolvedTenant.getForwardingContext());
145         return resolvedTenantBuilder.build();
146     }
147
148     // ****************
149     // Helper functions
150     // ****************
151
152     private static void resolveEndpointGroup(Tenant unresolvedTenant,
153             EndpointGroup unresolvedEg,
154             HashMap<EndpointGroupId,
155             EndpointGroup> resolvedEgs) {
156         // put the unresolved object into the data structure to avoid loops
157         resolvedEgs.put(unresolvedEg.getId(), unresolvedEg);
158
159         // resolve parent if it hasn't been resolved already
160         EndpointGroup parent = null;
161         if (unresolvedEg.getParent() != null) {
162             if (!resolvedEgs.containsKey(unresolvedEg.getParent())) {
163                 parent = TenantUtils.findEndpointGroup(unresolvedTenant,
164                         unresolvedEg.getParent());
165                 if (parent != null)
166                     resolveEndpointGroup(unresolvedTenant, parent, resolvedEgs);
167             }
168             parent = resolvedEgs.get(unresolvedEg.getParent());
169         }
170
171         HashMap<SelectorName, ConsumerTargetSelector> resolvedCts =
172                 new HashMap<>();
173         HashMap<SelectorName, ConsumerNamedSelector> resolvedCns =
174                 new HashMap<>();
175         HashMap<SelectorName, ProviderTargetSelector> resolvedPts =
176                 new HashMap<>();
177         HashMap<SelectorName, ProviderNamedSelector> resolvedPns =
178                 new HashMap<>();
179         NetworkDomainId domain = unresolvedEg.getNetworkDomain();
180         IntraGroupPolicy igp = unresolvedEg.getIntraGroupPolicy();
181
182         if (unresolvedEg.getConsumerTargetSelector() != null) {
183             for (ConsumerTargetSelector s : unresolvedEg.getConsumerTargetSelector()) {
184                 resolveCts(unresolvedTenant, unresolvedEg, s, resolvedCts);
185             }
186         }
187         if (unresolvedEg.getConsumerNamedSelector() != null) {
188             for (ConsumerNamedSelector s : unresolvedEg.getConsumerNamedSelector()) {
189                 resolveCns(unresolvedTenant, unresolvedEg, s, resolvedCns);
190             }
191         }
192         if (unresolvedEg.getProviderTargetSelector() != null) {
193             for (ProviderTargetSelector s : unresolvedEg.getProviderTargetSelector()) {
194                 resolvePts(unresolvedTenant, unresolvedEg, s, resolvedPts);
195             }
196         }
197         if (unresolvedEg.getProviderNamedSelector() != null) {
198             for (ProviderNamedSelector s : unresolvedEg.getProviderNamedSelector()) {
199                 resolvePns(unresolvedTenant, unresolvedEg, s, resolvedPns);
200             }
201         }
202
203         if (parent != null) {
204             if (parent.getConsumerTargetSelector() != null) {
205                 for (ConsumerTargetSelector cts : parent.getConsumerTargetSelector()) {
206                     if (!resolvedCts.containsKey(cts.getName()))
207                         resolvedCts.put(cts.getName(), cts);
208                 }
209             }
210             if (parent.getConsumerNamedSelector() != null) {
211                 for (ConsumerNamedSelector cns : parent.getConsumerNamedSelector()) {
212                     if (!resolvedCns.containsKey(cns.getName()))
213                         resolvedCns.put(cns.getName(), cns);
214                 }
215             }
216             if (parent.getProviderTargetSelector() != null) {
217                 for (ProviderTargetSelector pts : parent.getProviderTargetSelector()) {
218                     if (!resolvedPts.containsKey(pts.getName()))
219                         resolvedPts.put(pts.getName(), pts);
220                 }
221             }
222             if (parent.getProviderNamedSelector() != null) {
223                 for (ProviderNamedSelector pns : parent.getProviderNamedSelector()) {
224                     if (!resolvedPns.containsKey(pns.getName()))
225                         resolvedPns.put(pns.getName(), pns);
226                 }
227             }
228             if (domain == null) {
229                 domain = parent.getNetworkDomain();
230             }
231             if (igp == null) {
232                 igp = parent.getIntraGroupPolicy();
233             }
234         }
235
236         // Note: do not set parent, or any of the values that only exist
237         // for inheritance
238         EndpointGroup resolvedEg = new EndpointGroupBuilder()
239                 .setId(unresolvedEg.getId())
240                 .setDescription(unresolvedEg.getDescription())
241                 .setName(unresolvedEg.getName())
242                 .setConsumerTargetSelector(ImmutableList.copyOf(resolvedCts.values()))
243                 .setConsumerNamedSelector(ImmutableList.copyOf(resolvedCns.values()))
244                 .setProviderTargetSelector(ImmutableList.copyOf(resolvedPts.values()))
245                 .setProviderNamedSelector(ImmutableList.copyOf(resolvedPns.values()))
246                 .setNetworkDomain(domain)
247                 .setIntraGroupPolicy(igp)
248                 .build();
249         resolvedEgs.put(resolvedEg.getId(), resolvedEg);
250     }
251
252     private static void resolveCts(Tenant unresolvedTenant,
253             EndpointGroup unresolvedEg,
254             ConsumerTargetSelector unresolvedTs,
255             HashMap<SelectorName,
256             ConsumerTargetSelector> resolvedCts) {
257         HashMap<QualityMatcherName, QualityMatcher> matchers = new HashMap<>();
258         HashMap<RequirementName, Requirement> requirements = new HashMap<>();
259         HashSet<EndpointGroupId> visited = new HashSet<>();
260
261         resolveCtsAttr(unresolvedTenant, unresolvedEg, unresolvedTs.getName(),
262                 matchers, requirements, visited);
263
264         ConsumerTargetSelector resolved = new ConsumerTargetSelectorBuilder()
265                 .setName(unresolvedTs.getName())
266                 .setQualityMatcher(ImmutableList.copyOf(matchers.values()))
267                 .setRequirement(ImmutableList.copyOf(requirements.values()))
268                 .build();
269         resolvedCts.put(resolved.getName(), resolved);
270     }
271
272     private static void resolveCtsAttr(Tenant unresolvedTenant,
273             EndpointGroup unresolvedEg,
274             SelectorName name,
275             HashMap<QualityMatcherName,
276             QualityMatcher> matchers,
277             HashMap<RequirementName,
278             Requirement> requirements,
279             HashSet<EndpointGroupId> visited) {
280         if (unresolvedEg == null)
281             return;
282         if (visited.contains(unresolvedEg.getId()))
283             return;
284         visited.add(unresolvedEg.getId());
285         if (unresolvedEg.getParent() != null) {
286             resolveCtsAttr(unresolvedTenant,
287                     TenantUtils.findEndpointGroup(unresolvedTenant,
288                             unresolvedEg.getParent()),
289                     name,
290                     matchers,
291                     requirements,
292                     visited);
293         }
294         resolveLabels(unresolvedEg.getRequirement(), requirements,
295                 MatcherUtils.getRequirementName);
296         ConsumerTargetSelector unresolvedSelector =
297                 TenantUtils.findCts(unresolvedEg, name);
298         if (unresolvedSelector == null)
299             return;
300         resolveLabels(unresolvedSelector.getRequirement(), requirements,
301                 MatcherUtils.getRequirementName);
302         resolveQualityMatcher(unresolvedSelector.getQualityMatcher(), matchers);
303     }
304
305     private static void resolveCns(Tenant unresolvedTenant,
306             EndpointGroup unresolvedEg,
307             ConsumerNamedSelector unresolvedTs,
308             HashMap<SelectorName,
309             ConsumerNamedSelector> resolvedCns) {
310         HashMap<RequirementName, Requirement> requirements = new HashMap<>();
311         HashSet<ContractId> contracts = new HashSet<>();
312         HashSet<EndpointGroupId> visited = new HashSet<>();
313
314         resolveCnsAttr(unresolvedTenant, unresolvedEg, unresolvedTs.getName(),
315                 requirements, contracts, visited);
316
317         ConsumerNamedSelector resolved = new ConsumerNamedSelectorBuilder()
318                 .setName(unresolvedTs.getName())
319                 .setRequirement(ImmutableList.copyOf(requirements.values()))
320                 .setContract(ImmutableList.copyOf(contracts))
321                 .build();
322         resolvedCns.put(resolved.getName(), resolved);
323     }
324
325     private static void resolveCnsAttr(Tenant unresolvedTenant,
326             EndpointGroup unresolvedEg,
327             SelectorName name,
328             HashMap<RequirementName,
329             Requirement> requirements,
330             HashSet<ContractId> contracts,
331             HashSet<EndpointGroupId> visited) {
332         if (unresolvedEg == null)
333             return;
334         if (visited.contains(unresolvedEg.getId()))
335             return;
336         visited.add(unresolvedEg.getId());
337         if (unresolvedEg.getParent() != null) {
338             resolveCnsAttr(unresolvedTenant,
339                     TenantUtils.findEndpointGroup(unresolvedTenant,
340                             unresolvedEg.getParent()),
341                     name, requirements, contracts, visited);
342         }
343         resolveLabels(unresolvedEg.getRequirement(), requirements,
344                 MatcherUtils.getRequirementName);
345         ConsumerNamedSelector unresolvedSelector =
346                 TenantUtils.findCns(unresolvedEg, name);
347         if (unresolvedSelector == null)
348             return;
349         resolveLabels(unresolvedSelector.getRequirement(), requirements,
350                 MatcherUtils.getRequirementName);
351         if (unresolvedSelector.getContract() != null) {
352             contracts.addAll(unresolvedSelector.getContract());
353         }
354     }
355
356     private static void resolvePts(Tenant unresolvedTenant,
357             EndpointGroup unresolvedEg,
358             ProviderTargetSelector unresolvedTs,
359             HashMap<SelectorName,
360             ProviderTargetSelector> resolvedCts) {
361         HashMap<QualityMatcherName, QualityMatcher> matchers = new HashMap<>();
362         HashMap<CapabilityName, Capability> capabilities = new HashMap<>();
363         HashSet<EndpointGroupId> visited = new HashSet<>();
364
365         resolvePtsAttr(unresolvedTenant, unresolvedEg, unresolvedTs.getName(),
366                 matchers, capabilities, visited);
367
368         ProviderTargetSelector resolved = new ProviderTargetSelectorBuilder()
369                 .setName(unresolvedTs.getName())
370                 .setQualityMatcher(ImmutableList.copyOf(matchers.values()))
371                 .setCapability(ImmutableList.copyOf(capabilities.values()))
372                 .build();
373         resolvedCts.put(resolved.getName(), resolved);
374     }
375
376     private static void resolvePtsAttr(Tenant unresolvedTenant,
377             EndpointGroup unresolvedEg,
378             SelectorName name,
379             HashMap<QualityMatcherName,
380             QualityMatcher> matchers,
381             HashMap<CapabilityName,
382             Capability> capabilities,
383             HashSet<EndpointGroupId> visited) {
384         if (unresolvedEg == null)
385             return;
386         if (visited.contains(unresolvedEg.getId()))
387             return;
388         visited.add(unresolvedEg.getId());
389         if (unresolvedEg.getParent() != null) {
390             resolvePtsAttr(unresolvedTenant,
391                     TenantUtils.findEndpointGroup(unresolvedTenant,
392                             unresolvedEg.getParent()),
393                     name,
394                     matchers,
395                     capabilities, visited);
396         }
397         resolveLabels(unresolvedEg.getCapability(), capabilities,
398                 MatcherUtils.getCapabilityName);
399         ProviderTargetSelector unresolvedSelector =
400                 TenantUtils.findPts(unresolvedEg, name);
401         if (unresolvedSelector == null)
402             return;
403         resolveLabels(unresolvedSelector.getCapability(), capabilities,
404                 MatcherUtils.getCapabilityName);
405         resolveQualityMatcher(unresolvedSelector.getQualityMatcher(), matchers);
406     }
407
408     private static void resolvePns(Tenant unresolvedTenant,
409             EndpointGroup unresolvedEg,
410             ProviderNamedSelector unresolvedTs,
411             HashMap<SelectorName,
412             ProviderNamedSelector> resolvedCns) {
413         HashMap<CapabilityName, Capability> capabilities = new HashMap<>();
414         HashSet<ContractId> contracts = new HashSet<>();
415         HashSet<EndpointGroupId> visited = new HashSet<>();
416
417         resolvePnsAttr(unresolvedTenant, unresolvedEg, unresolvedTs.getName(),
418                 capabilities, contracts, visited);
419
420         ProviderNamedSelector resolved = new ProviderNamedSelectorBuilder()
421                 .setName(unresolvedTs.getName())
422                 .setCapability(ImmutableList.copyOf(capabilities.values()))
423                 .setContract(ImmutableList.copyOf(contracts))
424                 .build();
425         resolvedCns.put(resolved.getName(), resolved);
426     }
427
428     private static void resolvePnsAttr(Tenant unresolvedTenant,
429             EndpointGroup unresolvedEg,
430             SelectorName name,
431             HashMap<CapabilityName,
432             Capability> capabilities,
433             HashSet<ContractId> contracts,
434             HashSet<EndpointGroupId> visited) {
435         if (unresolvedEg == null)
436             return;
437         if (visited.contains(unresolvedEg.getId()))
438             return;
439         visited.add(unresolvedEg.getId());
440         if (unresolvedEg.getParent() != null) {
441             resolvePnsAttr(unresolvedTenant,
442                     TenantUtils.findEndpointGroup(unresolvedTenant,
443                             unresolvedEg.getParent()),
444                     name, capabilities, contracts, visited);
445         }
446         resolveLabels(unresolvedEg.getCapability(), capabilities,
447                 MatcherUtils.getCapabilityName);
448         ProviderNamedSelector unresolvedSelector =
449                 TenantUtils.findPns(unresolvedEg, name);
450         if (unresolvedSelector == null)
451             return;
452         resolveLabels(unresolvedSelector.getCapability(), capabilities,
453                 MatcherUtils.getCapabilityName);
454         if (unresolvedSelector.getContract() != null) {
455             contracts.addAll(unresolvedSelector.getContract());
456         }
457     }
458
459     private static void resolveContract(Tenant unresolvedTenant,
460             Contract unresolvedContract,
461             HashMap<ContractId,
462             Contract> resolvedContracts) {
463         // put the unresolved object into the data structure to avoid loops
464         resolvedContracts.put(unresolvedContract.getId(), unresolvedContract);
465
466         // resolve parent if it hasn't been resolved already
467         Contract parent = null;
468         if (unresolvedContract.getParent() != null) {
469             if (!resolvedContracts.containsKey(unresolvedContract.getParent())) {
470                 parent = TenantUtils.findContract(unresolvedTenant,
471                         unresolvedContract.getParent());
472                 if (parent != null)
473                     resolveContract(unresolvedTenant,
474                             parent,
475                             resolvedContracts);
476             }
477             parent = resolvedContracts.get(unresolvedContract.getParent());
478         }
479
480         HashMap<TargetName, Target> resolvedTargets = new HashMap<>();
481         HashMap<ClauseName, Clause> resolvedClauses = new HashMap<>();
482         HashMap<SubjectName, Subject> resolvedSubjects = new HashMap<>();
483
484         if (unresolvedContract.getTarget() != null) {
485             for (Target t : unresolvedContract.getTarget()) {
486                 resolveTarget(unresolvedTenant, unresolvedContract,
487                         t, resolvedTargets);
488             }
489         }
490         if (unresolvedContract.getClause() != null) {
491             for (Clause c : unresolvedContract.getClause()) {
492                 resolveClause(unresolvedTenant, unresolvedContract,
493                         c, resolvedClauses);
494             }
495         }
496         if (unresolvedContract.getSubject() != null) {
497             for (Subject s : unresolvedContract.getSubject()) {
498                 resolveSubject(unresolvedTenant, unresolvedContract,
499                         s, resolvedSubjects);
500             }
501         }
502
503         if (parent != null) {
504             if (parent.getTarget() != null) {
505                 for (Target t : parent.getTarget()) {
506                     if (!resolvedTargets.containsKey(t.getName()))
507                         resolvedTargets.put(t.getName(), t);
508                 }
509             }
510             if (parent.getClause() != null) {
511                 for (Clause c : parent.getClause()) {
512                     if (!resolvedClauses.containsKey(c.getName()))
513                         resolvedClauses.put(c.getName(), c);
514                 }
515             }
516             if (parent.getSubject() != null) {
517                 for (Subject s : parent.getSubject()) {
518                     if (!resolvedSubjects.containsKey(s.getName()))
519                         resolvedSubjects.put(s.getName(), s);
520                 }
521             }
522         }
523
524         Contract resolvedContract = new ContractBuilder()
525                 .setId(unresolvedContract.getId())
526                 .setDescription(unresolvedContract.getDescription())
527                 .setTarget(ImmutableList.copyOf(resolvedTargets.values()))
528                 .setClause(ImmutableList.copyOf(resolvedClauses.values()))
529                 .setSubject(ImmutableList.copyOf(resolvedSubjects.values()))
530                 .build();
531         resolvedContracts.put(resolvedContract.getId(), resolvedContract);
532     }
533
534     private static void resolveTarget(Tenant unresolvedTenant,
535             Contract unresolvedContract,
536             Target unresolvedTarget,
537             HashMap<TargetName, Target> resolvedTargets) {
538         HashMap<QualityName, Quality> qualities = new HashMap<>();
539         HashSet<ContractId> visited = new HashSet<>();
540
541         resolveTargetAttrs(unresolvedTenant,
542                 unresolvedContract,
543                 unresolvedTarget.getName(),
544                 qualities, visited);
545
546         Target resolved = new TargetBuilder()
547                 .setName(unresolvedTarget.getName())
548                 .setQuality(ImmutableList.copyOf(qualities.values()))
549                 .build();
550         resolvedTargets.put(resolved.getName(), resolved);
551     }
552
553     private static void resolveTargetAttrs(Tenant unresolvedTenant,
554             Contract unresolvedContract,
555             TargetName targetName,
556             HashMap<QualityName, Quality> qualities,
557             HashSet<ContractId> visited) {
558         if (unresolvedContract == null)
559             return;
560         if (visited.contains(unresolvedContract.getId()))
561             return;
562         visited.add(unresolvedContract.getId());
563         if (unresolvedContract.getParent() != null) {
564             resolveTargetAttrs(unresolvedTenant,
565                     TenantUtils.findContract(unresolvedTenant,
566                             unresolvedContract.getParent()),
567                     targetName,
568                     qualities, visited);
569         }
570         resolveLabels(unresolvedContract.getQuality(), qualities,
571                 MatcherUtils.getQualityName);
572         Target unresolvedTarget =
573                 TenantUtils.findTarget(unresolvedContract, targetName);
574         resolveLabels(unresolvedTarget.getQuality(), qualities,
575                 MatcherUtils.getQualityName);
576     }
577
578     private static void
579             resolveQualityMatcher(Collection<QualityMatcher> toResolve,
580                     HashMap<QualityMatcherName,
581                     QualityMatcher> matchers) {
582         if (toResolve == null)
583             return;
584         for (QualityMatcher qm : toResolve) {
585             if (matchers.containsKey(qm.getName())) {
586                 QualityMatcher oqm = matchers.get(qm.getName());
587                 QualityMatcherBuilder qmb = new QualityMatcherBuilder();
588                 qmb.setName(qm.getName());
589                 qmb.setMatchType(oqm.getMatchType());
590                 if (qm.getMatchType() != null)
591                     qmb.setMatchType(qm.getMatchType());
592
593                 HashMap<QualityName, MatcherQuality> qualities =
594                         new HashMap<>();
595                 resolveLabels(oqm.getMatcherQuality(), qualities,
596                         MatcherUtils.getMatcherQualityName);
597                 resolveLabels(qm.getMatcherQuality(), qualities,
598                         MatcherUtils.getMatcherQualityName);
599
600                 qmb.setMatcherQuality(ImmutableList.copyOf(qualities.values()));
601                 matchers.put(qm.getName(), qmb.build());
602             } else {
603                 matchers.put(qm.getName(), qm);
604             }
605         }
606     }
607
608     private static void
609             resolveCapabilityMatcher(Collection<CapabilityMatcher> toResolve,
610                     HashMap<CapabilityMatcherName,
611                     CapabilityMatcher> matchers) {
612         if (toResolve == null)
613             return;
614         for (CapabilityMatcher m : toResolve) {
615             if (matchers.containsKey(m.getName())) {
616                 CapabilityMatcher om = matchers.get(m.getName());
617                 CapabilityMatcherBuilder mb = new CapabilityMatcherBuilder();
618                 mb.setName(m.getName());
619                 mb.setMatchType(om.getMatchType());
620                 if (m.getMatchType() != null)
621                     mb.setMatchType(m.getMatchType());
622
623                 HashMap<CapabilityName, MatcherCapability> labels =
624                         new HashMap<>();
625                 resolveLabels(om.getMatcherCapability(), labels,
626                         MatcherUtils.getMatcherCapabilityName);
627                 resolveLabels(m.getMatcherCapability(), labels,
628                         MatcherUtils.getMatcherCapabilityName);
629
630                 mb.setMatcherCapability(ImmutableList.copyOf(labels.values()));
631                 matchers.put(m.getName(), mb.build());
632             } else {
633                 matchers.put(m.getName(), m);
634             }
635         }
636     }
637
638     private static void
639             resolveRequirementMatcher(Collection<RequirementMatcher> toResolve,
640                     HashMap<RequirementMatcherName,
641                     RequirementMatcher> matchers) {
642         if (toResolve == null)
643             return;
644         for (RequirementMatcher m : toResolve) {
645             if (matchers.containsKey(m.getName())) {
646                 RequirementMatcher om = matchers.get(m.getName());
647                 RequirementMatcherBuilder mb = new RequirementMatcherBuilder();
648                 mb.setName(m.getName());
649                 mb.setMatchType(om.getMatchType());
650                 if (m.getMatchType() != null)
651                     mb.setMatchType(m.getMatchType());
652
653                 HashMap<RequirementName, MatcherRequirement> labels =
654                         new HashMap<>();
655                 resolveLabels(om.getMatcherRequirement(), labels,
656                         MatcherUtils.getMatcherRequirementName);
657                 resolveLabels(m.getMatcherRequirement(), labels,
658                         MatcherUtils.getMatcherRequirementName);
659
660                 mb.setMatcherRequirement(ImmutableList.copyOf(labels.values()));
661                 matchers.put(m.getName(), mb.build());
662             } else {
663                 matchers.put(m.getName(), m);
664             }
665         }
666     }
667
668     private static void
669             resolveConditionMatcher(Collection<ConditionMatcher> toResolve,
670                     HashMap<ConditionMatcherName,
671                     ConditionMatcher> matchers) {
672         if (toResolve == null)
673             return;
674         for (ConditionMatcher m : toResolve) {
675             if (matchers.containsKey(m.getName())) {
676                 ConditionMatcher om = matchers.get(m.getName());
677                 ConditionMatcherBuilder mb = new ConditionMatcherBuilder();
678                 mb.setName(m.getName());
679                 mb.setMatchType(om.getMatchType());
680                 if (m.getMatchType() != null)
681                     mb.setMatchType(m.getMatchType());
682
683                 HashMap<ConditionName, Condition> labels =
684                         new HashMap<>();
685                 resolveLabels(om.getCondition(), labels,
686                         MatcherUtils.getConditionName);
687                 resolveLabels(m.getCondition(), labels,
688                         MatcherUtils.getConditionName);
689
690                 mb.setCondition(ImmutableList.copyOf(labels.values()));
691                 matchers.put(m.getName(), mb.build());
692             } else {
693                 matchers.put(m.getName(), m);
694             }
695         }
696     }
697
698     private static void resolveClause(Tenant unresolvedTenant,
699             Contract unresolvedContract,
700             Clause unresolvedClause,
701             HashMap<ClauseName, Clause> resolvedClauses) {
702         HashMap<CapabilityMatcherName, CapabilityMatcher> capMatchers = new HashMap<>();
703         HashMap<ConditionMatcherName, ConditionMatcher> provCondMatchers = new HashMap<>();
704         HashMap<RequirementMatcherName, RequirementMatcher> reqMatchers = new HashMap<>();
705         HashMap<ConditionMatcherName, ConditionMatcher> consCondMatchers = new HashMap<>();
706         HashSet<SubjectName> subjectRefs = new HashSet<>();
707         HashSet<ContractId> visited = new HashSet<>();
708
709         // TODO: Add GIC choices GroupNameConstraint and GroupAny
710         // TODO: Add Inheritance for EIC (ie L3Prefix) constraint.
711
712         resolveClauseAttr(unresolvedTenant, unresolvedContract,
713                 unresolvedClause.getName(), subjectRefs,
714                 capMatchers, provCondMatchers,
715                 reqMatchers, consCondMatchers, visited);
716
717         Clause resolved = new ClauseBuilder()
718                 .setName(unresolvedClause.getName())
719                 .setSubjectRefs(ImmutableList.copyOf(subjectRefs))
720                 .setProviderMatchers(new ProviderMatchersBuilder()
721                         .setGroupIdentificationConstraints(new GroupCapabilityConstraintCaseBuilder()
722                                 .setCapabilityMatcher(ImmutableList.copyOf(capMatchers.values())).build())
723                         .setConditionMatcher(ImmutableList.copyOf(provCondMatchers.values()))
724                         .setEndpointIdentificationConstraints(
725                                 unresolvedClause.getProviderMatchers() == null ? null :
726                                     unresolvedClause.getProviderMatchers().getEndpointIdentificationConstraints())
727                         .build())
728                 .setConsumerMatchers(new ConsumerMatchersBuilder()
729                         .setGroupIdentificationConstraints(new GroupRequirementConstraintCaseBuilder()
730                                 .setRequirementMatcher(ImmutableList.copyOf(reqMatchers.values())).build())
731                         .setConditionMatcher(ImmutableList.copyOf(consCondMatchers.values()))
732                         .setEndpointIdentificationConstraints(
733                                 unresolvedClause.getConsumerMatchers() == null ? null :
734                                     unresolvedClause.getConsumerMatchers().getEndpointIdentificationConstraints())
735                         .build())
736                 .build();
737         resolvedClauses.put(resolved.getName(), resolved);
738     }
739
740     private static void resolveClauseAttr(Tenant unresolvedTenant,
741             Contract unresolvedContract,
742             ClauseName clauseName,
743             HashSet<SubjectName> subjectRefs,
744             HashMap<CapabilityMatcherName,
745             CapabilityMatcher> capMatchers,
746             HashMap<ConditionMatcherName,
747             ConditionMatcher> provCondMatchers,
748             HashMap<RequirementMatcherName,
749             RequirementMatcher> reqMatchers,
750             HashMap<ConditionMatcherName,
751             ConditionMatcher> consCondMatchers,
752             HashSet<ContractId> visited) {
753         if (unresolvedContract == null)
754             return;
755         if (visited.contains(unresolvedContract.getId()))
756             return;
757         visited.add(unresolvedContract.getId());
758         if (unresolvedContract.getParent() != null) {
759             resolveClauseAttr(unresolvedTenant,
760                     TenantUtils.findContract(unresolvedTenant,
761                             unresolvedContract.getParent()),
762                     clauseName,
763                     subjectRefs,
764                     capMatchers,
765                     provCondMatchers,
766                     reqMatchers,
767                     consCondMatchers, visited);
768         }
769
770         Clause unresolvedClause =
771                 TenantUtils.findClause(unresolvedContract, clauseName);
772         if (unresolvedClause == null)
773             return;
774
775         if (unresolvedClause.getProviderMatchers() != null) {
776             ProviderMatchers pms = unresolvedClause.getProviderMatchers();
777             org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.contract.clause.provider.matchers.GroupIdentificationConstraints groupIdentificationConstraintsProvider = pms
778                     .getGroupIdentificationConstraints();
779             if (groupIdentificationConstraintsProvider instanceof GroupCapabilityConstraintCase) {
780                 resolveCapabilityMatcher(
781                         ((GroupCapabilityConstraintCase) groupIdentificationConstraintsProvider).getCapabilityMatcher(),
782                         capMatchers);
783             }
784             resolveConditionMatcher(pms.getConditionMatcher(), provCondMatchers);
785         }
786
787         if (unresolvedClause.getConsumerMatchers() != null) {
788             ConsumerMatchers cms = unresolvedClause.getConsumerMatchers();
789             GroupIdentificationConstraints groupIdentificiationConstrainsConsumer = cms
790                     .getGroupIdentificationConstraints();
791             if (groupIdentificiationConstrainsConsumer instanceof GroupRequirementConstraintCase) {
792                 resolveRequirementMatcher(
793                         ((GroupRequirementConstraintCase) groupIdentificiationConstrainsConsumer)
794                                 .getRequirementMatcher(),
795                         reqMatchers);
796             }
797             resolveConditionMatcher(cms.getConditionMatcher(), consCondMatchers);
798
799         }
800         if (unresolvedClause.getSubjectRefs() != null)
801             subjectRefs.addAll(unresolvedClause.getSubjectRefs());
802     }
803
804     private static class Mutable<O> {
805         O value;
806     }
807
808     private static void resolveSubject(Tenant unresolvedTenant,
809             Contract unresolvedContract,
810             Subject unresolvedSubject,
811             HashMap<SubjectName, Subject> resolvedSubjects) {
812         Mutable<Integer> order = new Mutable<>();
813         Mutable<List<Rule>> rules = new Mutable<>();
814         rules.value = Collections.emptyList();
815         HashSet<ContractId> visited = new HashSet<>();
816
817         resolveSubjectAttr(unresolvedTenant, unresolvedContract,
818                 unresolvedSubject.getName(), order, rules, visited);
819
820         Subject resolved = new SubjectBuilder()
821                 .setName(unresolvedSubject.getName())
822                 .setOrder(order.value)
823                 .setRule(rules.value)
824                 .build();
825         resolvedSubjects.put(resolved.getName(), resolved);
826     }
827
828     private static Rule makeRule(Rule r, int order) {
829         return new RuleBuilder()
830                 .setName(r.getName())
831                 .setActionRef(r.getActionRef())
832                 .setClassifierRef(r.getClassifierRef())
833                 .setOrder(order)
834                 .build();
835     }
836
837     private static void resolveSubjectAttr(Tenant unresolvedTenant,
838             Contract unresolvedContract,
839             SubjectName subjectName,
840             Mutable<Integer> order,
841             Mutable<List<Rule>> rules,
842             HashSet<ContractId> visited) {
843         if (unresolvedContract == null)
844             return;
845         if (visited.contains(unresolvedContract.getId()))
846             return;
847         visited.add(unresolvedContract.getId());
848         if (unresolvedContract.getParent() != null) {
849             resolveSubjectAttr(unresolvedTenant,
850                     TenantUtils.findContract(unresolvedTenant,
851                             unresolvedContract.getParent()),
852                     subjectName,
853                     order,
854                     rules, visited);
855         }
856
857         Subject unresolvedSubject =
858                 TenantUtils.findSubject(unresolvedContract, subjectName);
859         if (unresolvedSubject == null)
860             return;
861         if (unresolvedSubject.getOrder() != null)
862             order.value = unresolvedSubject.getOrder();
863         if (unresolvedSubject.getRule() != null) {
864             ImmutableList.Builder<Rule> rbuilder =
865                     new ImmutableList.Builder<Rule>();
866             ArrayList<Rule> nrules =
867                     new ArrayList<>(unresolvedSubject.getRule());
868             Collections.sort(nrules, TenantUtils.RULE_COMPARATOR);
869             int index = 0;
870             for (Rule r : nrules) {
871                 rbuilder.add(makeRule(r, index++));
872             }
873             for (Rule r : rules.value) {
874                 rbuilder.add(makeRule(r, index++));
875             }
876             rules.value = rbuilder.build();
877         }
878     }
879
880     /**
881      * Given a partially-resolved set of labels, add the next item in the
882      * inheritance ordering to the set of resolved labels.
883      *
884      * @param toResolve
885      *            the new set to add
886      * @param labels
887      *            the partially-resolved set
888      * @param getName
889      *            a function object to get the appropriate typed label name
890      */
891     private static <L extends Label, LN extends LabelName> void
892             resolveLabels(Collection<L> toResolve, HashMap<LN, L> labels,
893                     GetLabelName<L, LN> getName) {
894         if (toResolve == null)
895             return;
896         for (L l : toResolve) {
897             if (l.getInclusionRule() != null) {
898                 switch (l.getInclusionRule()) {
899                 case Include:
900                     // override
901                     labels.put(getName.getName(l), l);
902                     break;
903                 case Exclude:
904                     // remove
905                     labels.remove(getName.getName(l));
906                     break;
907                 }
908             } else {
909                 // default to Include
910                 labels.put(getName.getName(l), l);
911             }
912         }
913     }
914 }