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