Add yang generated packages in .gitignore
[groupbasedpolicy.git] / groupbasedpolicy / src / main / java / org / opendaylight / groupbasedpolicy / resolver / SubjectResolverUtils.java
1 package org.opendaylight.groupbasedpolicy.resolver;
2
3 import java.util.ArrayList;
4 import java.util.Collections;
5 import java.util.HashMap;
6 import java.util.HashSet;
7 import java.util.List;
8 import java.util.Map;
9 import java.util.Set;
10
11 import org.opendaylight.groupbasedpolicy.resolver.ContractResolverUtils.ContractMatch;
12 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ConditionName;
13 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.SubjectName;
14 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.Matcher.MatchType;
15 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.has.condition.matchers.ConditionMatcher;
16 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.has.conditions.Condition;
17 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.Tenant;
18 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.Contract;
19 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.Clause;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.Subject;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.clause.consumer.matchers.GroupIdentificationConstraints;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.clause.consumer.matchers.group.identification.constraints.GroupRequirementConstraintCase;
23 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;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.clause.provider.matchers.group.identification.constraints.GroupCapabilityConstraintCase;
25 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;
26
27 import com.google.common.collect.HashBasedTable;
28 import com.google.common.collect.ImmutableSet;
29 import com.google.common.collect.Table;
30 import com.google.common.collect.Table.Cell;
31
32
33 public class SubjectResolverUtils {
34
35     private SubjectResolverUtils() {
36         throw new UnsupportedOperationException("Cannot create an instance");
37     }
38
39     /**
40      * Choose the set of subjects that in scope for each possible set of
41      * endpoint conditions
42      */
43     // TODO Li msunal do we really need contractMatches to be a type Table<EgKey, EgKey, List<ContractMatch>>
44     // it should be sufficient to be just List<ContractMatch>
45     protected static Table<EgKey, EgKey, Policy> selectSubjects(
46             Table<EgKey, EgKey, List<ContractMatch>> contractMatches, Map<EgKey, Set<ConditionSet>> egConditions) {
47         // TODO: Note that it's possible to further simplify the resulting
48         // policy
49         // in the case of things like repeated rules, condition sets that
50         // cover other condition sets, etc. This would be a good thing to do
51         // at some point
52         Table<EgKey, EgKey, Policy> policy = HashBasedTable.create();
53
54         for (List<ContractMatch> matches : contractMatches.values()) {
55             for (ContractMatch match : matches) {
56                 List<Clause> clauses = match.contract.getClause();
57                 if (clauses == null)
58                     continue;
59
60                 List<Subject> subjectList = match.contract.getSubject();
61                 if (subjectList == null)
62                     continue;
63
64                 EgKey ckey = new EgKey(match.consumerTenant.getId(),
65                         match.consumer.getId());
66                 EgKey pkey = new EgKey(match.providerTenant.getId(),
67                         match.provider.getId());
68                 Policy existing = policy.get(ckey, pkey);
69
70                 HashMap<SubjectName, Subject> subjects = new HashMap<>();
71                 for (Subject s : subjectList) {
72                     subjects.put(s.getName(), s);
73                 }
74
75                 Table<EndpointConstraint, EndpointConstraint, List<Subject>> subjectMap =
76                         HashBasedTable.create();
77
78                 for (Clause clause : clauses) {
79                     if (clause.getSubjectRefs() != null &&
80                             clauseMatchesByGroupReqAndCapConstraints(clause, match)) {
81                         ConditionSet consCSet = buildConsConditionSet(clause);
82                         addConditionSet(ckey, consCSet, egConditions);
83                         EndpointConstraint consEpConstraint = new EndpointConstraint(consCSet,
84                                 clause.getConsumerMatchers() == null ? null : clause.getConsumerMatchers()
85                                     .getEndpointIdentificationConstraints());
86                         ConditionSet provCSet = buildProvConditionSet(clause);
87                         addConditionSet(pkey, provCSet, egConditions);
88                         EndpointConstraint provEpConstraint = new EndpointConstraint(provCSet,
89                                 clause.getProviderMatchers() == null ? null : clause.getProviderMatchers()
90                                     .getEndpointIdentificationConstraints());
91                         List<Subject> clauseSubjects = subjectMap.get(consEpConstraint, provEpConstraint);
92                         if (clauseSubjects == null) {
93                             clauseSubjects = new ArrayList<>();
94                             subjectMap.put(consEpConstraint, provEpConstraint, clauseSubjects);
95                         }
96                         for (SubjectName sn : clause.getSubjectRefs()) {
97                             Subject s = subjects.get(sn);
98                             if (s != null)
99                                 clauseSubjects.add(s);
100                         }
101                     }
102                 }
103
104                 policy.put(ckey, pkey,
105                         resolvePolicy(match.contractTenant,
106                                 match.contract,
107                                 existing,
108                                 subjectMap));
109             }
110         }
111
112         return policy;
113     }
114
115     private static boolean clauseMatchesByGroupReqAndCapConstraints(Clause clause, ContractMatch match) {
116         if (clause.getConsumerMatchers() != null) {
117             GroupIdentificationConstraints groupIdentificationConstraintsConsumer = clause.getConsumerMatchers()
118                     .getGroupIdentificationConstraints();
119             if (groupIdentificationConstraintsConsumer instanceof GroupRequirementConstraintCase) {
120                 List<RequirementMatcher> reqMatchers = ((GroupRequirementConstraintCase) groupIdentificationConstraintsConsumer)
121                         .getRequirementMatcher();
122                 if (reqMatchers != null) {
123                     for (RequirementMatcher reqMatcher : reqMatchers) {
124                         if (!MatcherUtils.applyReqMatcher(reqMatcher,
125                                 match.consumerRelator)) {
126                             return false;
127                         }
128                     }
129                 }
130             }
131         }
132         if (clause.getProviderMatchers() != null) {
133             org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.clause.provider.matchers.GroupIdentificationConstraints groupIdentificationConstraintsProvider = clause
134                     .getProviderMatchers().getGroupIdentificationConstraints();
135             if (groupIdentificationConstraintsProvider instanceof GroupCapabilityConstraintCase) {
136                 List<CapabilityMatcher> capMatchers = ((GroupCapabilityConstraintCase) groupIdentificationConstraintsProvider)
137                         .getCapabilityMatcher();
138
139                 if (capMatchers != null) {
140                     for (CapabilityMatcher capMatcher : capMatchers) {
141                         if (!MatcherUtils.applyCapMatcher(capMatcher,
142                                 match.providerRelator)) {
143                             return false;
144                         }
145                     }
146                 }
147             }
148         }
149         return true;
150     }
151
152     private static void addConditionSet(EgKey eg, ConditionSet cs,
153             Map<EgKey, Set<ConditionSet>> egConditions) {
154         if (egConditions == null)
155             return;
156         Set<ConditionSet> cset = egConditions.get(eg);
157         if (cset == null) {
158             egConditions.put(eg, cset = new HashSet<>());
159         }
160         cset.add(cs);
161     }
162
163     private static ConditionSet buildConsConditionSet(Clause clause) {
164         if (clause.getConsumerMatchers() != null) {
165             List<ConditionMatcher> condMatchers =
166                     clause.getConsumerMatchers().getConditionMatcher();
167             return buildConditionSet(condMatchers);
168         }
169         return ConditionSet.EMPTY;
170     }
171
172     private static ConditionSet buildProvConditionSet(Clause clause) {
173         if (clause.getProviderMatchers() != null) {
174             List<ConditionMatcher> condMatchers =
175                     clause.getProviderMatchers().getConditionMatcher();
176             return buildConditionSet(condMatchers);
177         }
178         return ConditionSet.EMPTY;
179     }
180
181     private static ConditionSet buildConditionSet(List<ConditionMatcher> condMatchers) {
182         if (condMatchers == null)
183             return ConditionSet.EMPTY;
184
185         ImmutableSet.Builder<ConditionName> allb = ImmutableSet.builder();
186         ImmutableSet.Builder<ConditionName> noneb = ImmutableSet.builder();
187         ImmutableSet.Builder<Set<ConditionName>> anyb =
188                 ImmutableSet.builder();
189         for (ConditionMatcher condMatcher : condMatchers) {
190             if (condMatcher.getCondition() == null)
191                 continue;
192             MatchType type = condMatcher.getMatchType();
193             if (type == null)
194                 type = MatchType.All;
195             if (type.equals(MatchType.Any)) {
196                 ImmutableSet.Builder<ConditionName> a =
197                         ImmutableSet.builder();
198                 for (Condition c : condMatcher.getCondition()) {
199                     a.add(c.getName());
200                 }
201                 anyb.add(a.build());
202             } else {
203                 for (Condition c : condMatcher.getCondition()) {
204                     switch (type) {
205                     case Any:
206                         break;
207                     case None:
208                         noneb.add(c.getName());
209                         break;
210                     case All:
211                     default:
212                         allb.add(c.getName());
213                         break;
214                     }
215                 }
216             }
217         }
218         return new ConditionSet(allb.build(), noneb.build(), anyb.build());
219     }
220
221     private static Policy resolvePolicy(Tenant contractTenant,
222             Contract contract,
223             Policy merge,
224             Table<EndpointConstraint, EndpointConstraint,
225             List<Subject>> subjectMap) {
226         Table<EndpointConstraint, EndpointConstraint, List<RuleGroup>> ruleMap =
227                 HashBasedTable.create();
228         if (merge != null) {
229             ruleMap.putAll(merge.getRuleMap());
230         }
231         for (Cell<EndpointConstraint, EndpointConstraint, List<Subject>> entry : subjectMap.cellSet()) {
232             List<RuleGroup> rules = new ArrayList<>();
233             EndpointConstraint consEpConstraint = entry.getRowKey();
234             EndpointConstraint provEpConstraint = entry.getColumnKey();
235             List<RuleGroup> oldrules = ruleMap.get(consEpConstraint, provEpConstraint);
236             if (oldrules != null) {
237                 rules.addAll(oldrules);
238             }
239             for (Subject s : entry.getValue()) {
240                 if (s.getRule() == null)
241                     continue;
242
243                 RuleGroup rg = new RuleGroup(s.getRule(), s.getOrder(),
244                         contractTenant, contract,
245                         s.getName());
246                 rules.add(rg);
247             }
248             Collections.sort(rules);
249             ruleMap.put(consEpConstraint, provEpConstraint, Collections.unmodifiableList(rules));
250         }
251         return new Policy(ruleMap);
252     }
253 }