Bug 4724 added containers to tenant
[groupbasedpolicy.git] / groupbasedpolicy / src / main / java / org / opendaylight / groupbasedpolicy / dto / IndexedTenant.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.dto;
10
11 import java.util.Collection;
12 import java.util.HashMap;
13 import java.util.HashSet;
14 import java.util.Map;
15 import java.util.Set;
16
17 import javax.annotation.concurrent.Immutable;
18
19 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ActionName;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ClassifierName;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ContractId;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.EndpointGroupId;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.NetworkDomainId;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.SubnetId;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.NetworkDomain;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.Tenant;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.ForwardingContext;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.Policy;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.L2BridgeDomain;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.L2FloodDomain;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.L3Context;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.Subnet;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.Contract;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.EndpointGroup;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.SubjectFeatureInstances;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.subject.feature.instances.ActionInstance;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.subject.feature.instances.ClassifierInstance;
38
39 import com.google.common.base.Function;
40 import com.google.common.collect.Collections2;
41
42 /**
43  * Wrap some convenient indexes around a {@link Tenant} object
44  * @author readams
45  */
46 @Immutable
47 public class IndexedTenant {
48     private final Tenant tenant;
49     private final int hashCode;
50
51     private final Map<EndpointGroupId, EndpointGroup> endpointGroups =
52             new HashMap<>();
53     private final Map<ContractId, Contract> contracts =
54             new HashMap<>();
55     private final Map<String, NetworkDomain> networkDomains =
56             new HashMap<>();
57     private final Map<ClassifierName, ClassifierInstance> classifiers =
58             new HashMap<>();
59     private final Map<ActionName, ActionInstance> actions =
60             new HashMap<>();
61     private final Map<String, Set<SubnetId>> subnetMap = new HashMap<>();
62
63     public IndexedTenant(Tenant tenant) {
64         this.tenant = tenant;
65         this.hashCode = tenant.hashCode();
66         if (tenant.getPolicy() != null) {
67             processPolicy(tenant.getPolicy());
68         }
69         if (tenant.getForwardingContext() != null) {
70             processForwardingContext(tenant.getForwardingContext());
71         }
72     }
73
74     private void processPolicy(Policy policy) {
75         if (policy.getEndpointGroup() != null) {
76             for (EndpointGroup eg : policy.getEndpointGroup()) {
77                 endpointGroups.put(eg.getId(), eg);
78             }
79         }
80         if (policy.getContract() != null) {
81             for (Contract c : policy.getContract()) {
82                 contracts.put(c.getId(), c);
83             }
84         }
85         if (policy.getSubjectFeatureInstances() != null) {
86             SubjectFeatureInstances sfi = policy.getSubjectFeatureInstances();
87             if (sfi.getClassifierInstance() != null) {
88                 for (ClassifierInstance ci : sfi.getClassifierInstance()) {
89                     classifiers.put(ci.getName(), ci);
90                 }
91             }
92             if (sfi.getActionInstance() != null) {
93                 for (ActionInstance action : sfi.getActionInstance()) {
94                     actions.put(action.getName(), action);
95                 }
96             }
97         }
98     }
99
100     private void processForwardingContext(ForwardingContext fwCtx) {
101         if (fwCtx.getL3Context() != null) {
102             for (L3Context c : fwCtx.getL3Context()) {
103                 networkDomains.put(c.getId().getValue(), c);
104             }
105         }
106         if (fwCtx.getL2BridgeDomain() != null) {
107             for (L2BridgeDomain c : fwCtx.getL2BridgeDomain()) {
108                 networkDomains.put(c.getId().getValue(), c);
109             }
110         }
111         if (fwCtx.getL2FloodDomain() != null) {
112             for (L2FloodDomain c : fwCtx.getL2FloodDomain()) {
113                 networkDomains.put(c.getId().getValue(), c);
114             }
115         }
116         if (fwCtx.getSubnet() != null) {
117             for (Subnet s : fwCtx.getSubnet()) {
118                 networkDomains.put(s.getId().getValue(), s);
119                 Set<SubnetId> sset = subnetMap.get(s.getParent().getValue());
120                 if (sset == null) {
121                     subnetMap.put(s.getParent().getValue(), sset = new HashSet<SubnetId>());
122                 }
123                 sset.add(s.getId());
124             }
125         }
126     }
127
128     /**
129      * Get the underlying tenant object
130      * @return the {@link Tenant}
131      */
132     public Tenant getTenant() {
133         return tenant;
134     }
135     
136     /**
137      * Look up the network domain specified
138      * @param id the {@link NetworkDomainId}
139      * @return the {@link NetworkDomain} if it exists, or <code>null</code> 
140      * otherwise
141      */
142     public NetworkDomain getNetworkDomain(NetworkDomainId id) {
143         return networkDomains.get(id.getValue());
144     }
145
146     /**
147      * Look up the endpoint group specified
148      * @param id the {@link EndpointGroupId}
149      * @return the {@link EndpointGroup} if it exists, or <code>null</code> 
150      * otherwise
151      */
152     public EndpointGroup getEndpointGroup(EndpointGroupId id) {
153         return endpointGroups.get(id);
154     }
155     
156     /**
157      * Look up the contract specified
158      * @param id the {@link ContractId}
159      * @return the {@link Contract} if it exists, or <code>null</code> 
160      * otherwise
161      */
162     public Contract getContract(ContractId id) {
163         return contracts.get(id);
164     }
165     
166     /**
167      * Look up the classifier instance specified
168      * @param name the {@link ClassifierName}
169      * @return the {@link ClassifierInstance} if it exists, or <code>null</code> 
170      * otherwise
171      */
172     public ClassifierInstance getClassifier(ClassifierName name) {
173         return classifiers.get(name);
174     }
175
176     /**
177      * Look up the classifier instance specified
178      * @param name the {@link ActionName}
179      * @return the {@link ActionInstance} if it exists, or <code>null</code> 
180      * otherwise
181      */
182     public ActionInstance getAction(ActionName name) {
183         return actions.get(name);
184     }
185
186     /**
187      * Get the layer 3 context for the specified network domain by walking
188      * up the hierarchy
189      * @param id the {@link NetworkDomainId} for the network domain
190      * @return the {@link L3Context} or <code>null</code> if it does not exist
191      */
192     public L3Context resolveL3Context(NetworkDomainId id) {
193         return resolveDomain(L3Context.class, id);
194     }
195
196     /**
197      * Get the layer 2 bridge domain for the specified network domain by walking
198      * up the hierarchy
199      * @param id the {@link NetworkDomainId} for the network domain
200      * @return the {@link L2BridgeDomain} or <code>null</code> if it does
201      * not exist
202      */
203     public L2BridgeDomain resolveL2BridgeDomain(NetworkDomainId id) {
204         return resolveDomain(L2BridgeDomain.class, id);
205     }
206
207     /**
208      * Get the layer 2 flood domain for the specified network domain by walking
209      * up the hierarchy
210      * @param id the {@link NetworkDomainId} for the network domain
211      * @return the {@link L2FloodDomain} or <code>null</code> if it does
212      * not exist
213      */
214     public L2FloodDomain resolveL2FloodDomain(NetworkDomainId id) {
215         return resolveDomain(L2FloodDomain.class, id);
216     }
217
218     /**
219      * Resolve all subnets applicable to the given network domain ID
220      * @param id the {@link NetworkDomainId}
221      * @return the set of subnets.  Cannot be null, but could be empty.
222      */
223     public Collection<Subnet> resolveSubnets(NetworkDomainId id) {
224         Set<SubnetId> sset = new HashSet<>();
225         HashSet<NetworkDomainId> visited = new HashSet<>();        
226         while (id != null) {
227             if (visited.contains(id)) break;
228             visited.add(id);
229             Set<SubnetId> cursset = subnetMap.get(id.getValue());
230             if (cursset != null)
231                 sset.addAll(cursset);
232             NetworkDomain d = networkDomains.get(id.getValue());
233             if (d == null) break;
234             if (d instanceof Subnet) {
235                 id = ((Subnet)d).getParent();
236                 sset.add(((Subnet) d).getId());
237             } 
238             else if (d instanceof L2BridgeDomain)
239                 id = ((L2BridgeDomain)d).getParent();
240             else if (d instanceof L2FloodDomain)
241                 id = ((L2FloodDomain)d).getParent();
242             else
243                 id = null;
244         }
245         return Collections2.transform(sset, new Function<SubnetId, Subnet>() {
246             @Override
247             public Subnet apply(SubnetId input) {
248                 return (Subnet)networkDomains.get(input.getValue());
249             }
250         });
251     }
252
253     // ******
254     // Object
255     // ******
256     
257     @Override
258     public int hashCode() {
259         return hashCode;
260     }
261
262     @Override
263     public boolean equals(Object obj) {
264         if (this == obj)
265             return true;
266         if (obj == null)
267             return false;
268         if (getClass() != obj.getClass())
269             return false;
270         IndexedTenant other = (IndexedTenant) obj;
271         if (tenant == null) {
272             if (other.tenant != null)
273                 return false;
274         } else if (!tenant.equals(other.tenant))
275             return false;
276         return true;
277     }
278
279     // **************
280     // Implementation
281     // **************
282
283     private <C extends NetworkDomain> C resolveDomain(Class<C> domainClass,
284                                                       NetworkDomainId id) {
285         HashSet<NetworkDomainId> visited = new HashSet<>();        
286         while (id != null) {
287             if (visited.contains(id)) return null;
288             visited.add(id);
289             NetworkDomain d = networkDomains.get(id.getValue());
290             if (d == null) return null;
291             if (domainClass.isInstance(d)) return domainClass.cast(d);
292             if (d instanceof Subnet)
293                 id = ((Subnet)d).getParent();
294             else if (d instanceof L2BridgeDomain)
295                 id = ((L2BridgeDomain)d).getParent();
296             else if (d instanceof L2FloodDomain)
297                 id = ((L2FloodDomain)d).getParent();
298             else
299                 id = null;
300         }
301         return null;
302     }
303 }