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