ccbea043948ab2efebce8769b613526c6f7aa535
[groupbasedpolicy.git] / groupbasedpolicy / src / main / java / org / opendaylight / groupbasedpolicy / resolver / ContractResolverUtils.java
1 package org.opendaylight.groupbasedpolicy.resolver;
2
3 import java.util.ArrayList;
4 import java.util.List;
5 import java.util.Set;
6
7 import javax.annotation.concurrent.Immutable;
8
9 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ContractId;
10 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
11 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.ConsumerSelectionRelator;
12 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.ProviderSelectionRelator;
13 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.target.selector.QualityMatcher;
14 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.Tenant;
15 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.Contract;
16 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.EndpointGroup;
17 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.Target;
18 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.endpoint.group.ConsumerNamedSelector;
19 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.endpoint.group.ConsumerTargetSelector;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.endpoint.group.ProviderNamedSelector;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.endpoint.group.ProviderTargetSelector;
22
23 import com.google.common.collect.HashBasedTable;
24 import com.google.common.collect.Table;
25
26
27 public class ContractResolverUtils {
28
29     private ContractResolverUtils() {
30         throw new UnsupportedOperationException("Cannot create an instance");
31     }
32
33     /**
34      * Choose the contracts that are in scope for each pair of endpoint groups,
35      * then perform subject selection for the pair
36      */
37     protected static Table<EgKey, EgKey, List<ContractMatch>> selectContracts(Set<IndexedTenant> tenants) {
38         Table<TenantId, ContractId, List<ConsumerContractMatch>> consumerMatches = HashBasedTable.create();
39         Table<EgKey, EgKey, List<ContractMatch>> contractMatches = HashBasedTable.create();
40
41         for (IndexedTenant tenant : tenants) {
42             selectContracts(consumerMatches, contractMatches, tenant.getTenant());
43         }
44         return contractMatches;
45     }
46
47     protected static void selectContracts(Table<TenantId, ContractId, List<ConsumerContractMatch>> consumerMatches,
48             Table<EgKey, EgKey, List<ContractMatch>> contractMatches, Tenant tenant) {
49         // For each endpoint group, match consumer selectors
50         // against contracts to get a set of matching consumer selectors
51         if (tenant.getEndpointGroup() == null)
52             return;
53         for (EndpointGroup group : tenant.getEndpointGroup()) {
54             List<ConsumerContractMatch> r = matchConsumerContracts(tenant, group);
55             for (ConsumerContractMatch ccm : r) {
56                 List<ConsumerContractMatch> cms = consumerMatches.get(tenant.getId(), ccm.contract.getId());
57                 if (cms == null) {
58                     cms = new ArrayList<>();
59                     consumerMatches.put(tenant.getId(), ccm.contract.getId(), cms);
60                 }
61                 cms.add(ccm);
62             }
63         }
64
65         // Match provider selectors, and check each match for a corresponding
66         // consumer selector match.
67         for (EndpointGroup group : tenant.getEndpointGroup()) {
68             List<ContractMatch> matches = matchProviderContracts(tenant, group, consumerMatches);
69             for (ContractMatch cm : matches) {
70                 EgKey consumerKey = new EgKey(cm.consumerTenant.getId(), cm.consumer.getId());
71                 EgKey providerKey = new EgKey(cm.providerTenant.getId(), cm.provider.getId());
72                 List<ContractMatch> egPairMatches = contractMatches.get(consumerKey, providerKey);
73                 if (egPairMatches == null) {
74                     egPairMatches = new ArrayList<>();
75                     contractMatches.put(consumerKey, providerKey, egPairMatches);
76                 }
77
78                 egPairMatches.add(cm);
79             }
80         }
81     }
82
83     private static List<ConsumerContractMatch> matchConsumerContracts(Tenant tenant,
84             EndpointGroup consumer) {
85         List<ConsumerContractMatch> matches = new ArrayList<>();
86         if (consumer.getConsumerNamedSelector() != null) {
87             for (ConsumerNamedSelector cns : consumer.getConsumerNamedSelector()) {
88                 if (cns.getContract() == null)
89                     continue;
90                 for (ContractId contractId : cns.getContract()) {
91                     Contract contract =
92                             TenantUtils.findContract(tenant, contractId);
93                     if (contract == null)
94                         continue;
95                     matches.add(new ConsumerContractMatch(tenant, contract,
96                             tenant, consumer,
97                             cns));
98                 }
99             }
100         }
101         if (consumer.getConsumerTargetSelector() != null) {
102             for (ConsumerTargetSelector cts : consumer.getConsumerTargetSelector()) {
103                 if (tenant.getContract() == null)
104                     continue;
105                 for (Contract contract : tenant.getContract()) {
106                     if (contract.getTarget() == null)
107                         continue;
108                     for (Target t : contract.getTarget()) {
109                         boolean match = true;
110                         if (cts.getQualityMatcher() != null) {
111                             for (QualityMatcher m : cts.getQualityMatcher()) {
112                                 if (!MatcherUtils.applyQualityMatcher(m, t)) {
113                                     match = false;
114                                     break;
115                                 }
116                             }
117                         }
118                         if (match) {
119                             matches.add(new ConsumerContractMatch(tenant,
120                                     contract,
121                                     tenant,
122                                     consumer,
123                                     cts));
124                         }
125                     }
126                 }
127             }
128         }
129         // TODO match selectors also against contract references
130         // for (ConsumerTargetSelector cts :
131         // consumer.getConsumerTargetSelector()) {
132         // if (tenant.getContractRef() == null) continue;
133         // for (ContractRef c : tenant.getContractRef()) {
134         //
135         // }
136         // }
137         return matches;
138     }
139
140     private static List<ContractMatch> matchProviderContracts(Tenant tenant, EndpointGroup provider,
141             Table<TenantId, ContractId, List<ConsumerContractMatch>> consumerMatches) {
142         List<ContractMatch> matches = new ArrayList<>();
143         if (provider.getProviderNamedSelector() != null) {
144             for (ProviderNamedSelector pns : provider.getProviderNamedSelector()) {
145                 if (pns.getContract() == null)
146                     continue;
147                 for (ContractId contractId : pns.getContract()) {
148                     Contract c = TenantUtils.findContract(tenant, contractId);
149                     if (c == null)
150                         continue;
151                     List<ConsumerContractMatch> cMatches = consumerMatches.get(tenant.getId(), c.getId());
152                     amendContractMatches(matches, cMatches, tenant, provider, pns);
153                 }
154             }
155         }
156         if (provider.getProviderTargetSelector() != null) {
157             for (ProviderTargetSelector pts : provider.getProviderTargetSelector()) {
158                 if (tenant.getContract() == null)
159                     continue;
160                 for (Contract c : tenant.getContract()) {
161                     if (c.getTarget() == null)
162                         continue;
163                     for (Target t : c.getTarget()) {
164                         boolean match = true;
165                         if (pts.getQualityMatcher() != null) {
166                             for (QualityMatcher m : pts.getQualityMatcher()) {
167                                 if (!MatcherUtils.applyQualityMatcher(m, t)) {
168                                     match = false;
169                                     break;
170                                 }
171                             }
172                         }
173                         if (match) {
174                             List<ConsumerContractMatch> cMatches = consumerMatches.get(tenant.getId(), c.getId());
175                             amendContractMatches(matches, cMatches, tenant, provider, pts);
176
177                         }
178                     }
179                 }
180             }
181         }
182         return matches;
183     }
184
185     private static void amendContractMatches(List<ContractMatch> matches,
186             List<ConsumerContractMatch> cMatches,
187             Tenant tenant, EndpointGroup provider,
188             ProviderSelectionRelator relator) {
189         if (cMatches == null)
190             return;
191         for (ConsumerContractMatch cMatch : cMatches) {
192             matches.add(new ContractMatch(cMatch, tenant, provider, relator));
193         }
194     }
195
196     /**
197      * Represents a selected contract made by endpoint groups matching it using
198      * selection relators. This is the result of the contract selection phase.
199      *
200      * @author readams
201      */
202     @Immutable
203     protected static class ContractMatch extends ConsumerContractMatch {
204
205         /**
206          * The tenant ID of the provider endpoint group
207          */
208         final Tenant providerTenant;
209
210         /**
211          * The provider endpoint group
212          */
213         final EndpointGroup provider;
214
215         /**
216          * The provider selection relator that was used to match the contract
217          */
218         final ProviderSelectionRelator providerRelator;
219
220         public ContractMatch(ConsumerContractMatch consumerMatch, Tenant providerTenant, EndpointGroup provider,
221                 ProviderSelectionRelator providerRelator) {
222             super(consumerMatch.contractTenant, consumerMatch.contract, consumerMatch.consumerTenant,
223                     consumerMatch.consumer, consumerMatch.consumerRelator);
224             this.providerTenant = providerTenant;
225             this.provider = provider;
226             this.providerRelator = providerRelator;
227         }
228     }
229
230     @Immutable
231     protected static class ConsumerContractMatch {
232
233         /**
234          * The tenant of the matching contract
235          */
236         final Tenant contractTenant;
237
238         /**
239          * The matching contract
240          */
241         final Contract contract;
242
243         /**
244          * The tenant for the endpoint group
245          */
246         final Tenant consumerTenant;
247
248         /**
249          * The consumer endpoint group
250          */
251         final EndpointGroup consumer;
252
253         /**
254          * The consumer selection relator that was used to match the contract
255          */
256         final ConsumerSelectionRelator consumerRelator;
257
258         public ConsumerContractMatch(Tenant contractTenant, Contract contract, Tenant consumerTenant,
259                 EndpointGroup consumer, ConsumerSelectionRelator consumerRelator) {
260             super();
261             this.contractTenant = contractTenant;
262             this.contract = contract;
263             this.consumerTenant = consumerTenant;
264             this.consumer = consumer;
265             this.consumerRelator = consumerRelator;
266         }
267     }
268
269 }