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