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