Added range type to subject-feature-definition/parameter
[groupbasedpolicy.git] / renderers / opflex / src / main / java / org / opendaylight / groupbasedpolicy / renderer / opflex / Identity.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.renderer.opflex;
10
11 import java.util.ArrayList;
12 import java.util.Collections;
13 import java.util.List;
14 import java.util.Set;
15 import java.util.concurrent.ConcurrentHashMap;
16 import java.util.regex.Pattern;
17
18 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
19 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddressBuilder;
20 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.L2BridgeDomainId;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.L3ContextId;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoint.fields.L3Address;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoint.fields.L3AddressBuilder;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.Endpoint;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3;
27
28 import com.google.common.net.InetAddresses;
29
30
31 /**
32  * An Identity for OpFlex. Identities can take on many
33  * forms, so it's possible that this class may be replaced
34  * by an abstract class with different concrete types.
35  * At the moment, we're only dealing with IP and MAC
36  * addresses.
37  *
38  * This class also provides methods for getting the identity
39  * in forms by the yang model, and are therefore usable by
40  * other classes in the policy model (e.g. the objects
41  * needed by the Endpoint Registry).
42  *
43  */
44 public class Identity {
45     enum IdentityType {
46         UNKNOWN, IP_ADDRESS, MAC_ADDRESS;
47     }
48     private IdentityType type = IdentityType.UNKNOWN;
49     private L3ContextId l3Context = null;
50     private IpAddress primaryIp = null;
51     private Set<IpAddress> ips = null;
52     private L2BridgeDomainId l2Context = null;
53     private MacAddress mac = null;
54     public Identity(String id) {
55         /*
56          * Determine the ID type and populate
57          */
58         if (idIsIp(id)) {
59             type = IdentityType.IP_ADDRESS;
60             ips = Collections.newSetFromMap(new ConcurrentHashMap<IpAddress, Boolean>());
61             if (primaryIp == null) primaryIp = normalizeIpAddress(id);
62             ips.add(normalizeIpAddress(id));
63         }
64         else if (idIsMac(id)) {
65             type = IdentityType.MAC_ADDRESS;
66             mac = normalizeMacAddress(id);
67         }
68
69     }
70
71     public Identity(Endpoint ep) {
72         type = IdentityType.MAC_ADDRESS;
73         mac = ep.getMacAddress();
74         l2Context = ep.getL2Context();
75     }
76
77     public Identity(EndpointL3 ep) {
78         type = IdentityType.IP_ADDRESS;
79         ips = Collections.newSetFromMap(new ConcurrentHashMap<IpAddress, Boolean>());
80         primaryIp = ep.getIpAddress();
81         List<L3Address> l3List = ep.getL3Address();
82         for (L3Address addr: l3List) {
83             ips.add(addr.getIpAddress());
84         }
85     }
86
87     public void setContext(String context) {
88         switch (type) {
89         case MAC_ADDRESS:
90             l2Context = new L2BridgeDomainId(context);
91             break;
92         case IP_ADDRESS:
93             l3Context = new L3ContextId(context);
94             break;
95         default:
96             break;
97         }
98     }
99
100     /**
101      * Adds a new identifier to the list. Some types of
102      * identities allow for list of identifiers (e.g. L3).
103      *
104      * @param id The new identifier to add to the list
105      */
106     public void addId(String id) {
107         switch (type) {
108         case IP_ADDRESS:
109             ips.add(normalizeIpAddress(id));
110             break;
111         default:
112             break;
113         }
114     }
115
116     private boolean idIsIp(String id) {
117         return InetAddresses.isInetAddress(id);
118     }
119
120     /*
121      * Verifies MAC addresses with the following formats:
122      * 0xAA:0xBB:0xCC:0xDD:0xEE:0xFF
123      * AA:BB:CC:DD:EE:FF
124      * 0xAA:BB:CC:DD:EE:FF
125      * 0xAA-0xBB-0xCC-0xDD-0xEE-0xFF
126      */
127     private boolean idIsMac(String id) {
128         /*
129          * First check/remove separators
130          */
131         String[] sixFields = id.split(":");
132         if (sixFields.length != 6) {
133             sixFields = id.split("-");
134             if (sixFields.length != 6) {
135                 return false;
136             }
137         }
138
139         for (String field : sixFields) {
140             /* Strip '0x' if present */
141             field = field.replace("0x", "");
142             if (field.length() > 2 || field.length() <1) {
143                 return false;
144             }
145             if (!Pattern.matches("[0-9a-fA-F]{1,2}", field)) {
146                 return false;
147             }
148         }
149         return true;
150     }
151
152     /**
153      * Check if this {@link Identity} is an L3 type (Ip Address)
154      *
155      * @return true if L3, false if not
156      */
157     public boolean isL3() {
158         return (type == IdentityType.IP_ADDRESS);
159     }
160
161     /**
162      * Check if this {@link Identity} is an L2 type (MAC Address)
163      *
164      * @return true if L2, false if not
165      */
166     public boolean isL2() {
167         return (type == IdentityType.MAC_ADDRESS);
168     }
169
170     public boolean valid() {
171         switch (type) {
172         case MAC_ADDRESS:
173             if (getL2Context() != null && mac != null) {
174                 return true;
175             }
176             break;
177         case IP_ADDRESS:
178             if (getL3Context() != null && primaryIp != null) {
179                 return true;
180             }
181             default:
182                 break;
183
184         }
185         return false;
186     }
187     /**
188      * Return the context, regardless of type, as a string.
189      *
190      * @return String representing the context for this Identity
191      */
192     public String contextAsString() {
193         switch (type) {
194         case MAC_ADDRESS:
195             return l2Context.getValue().toString();
196         case IP_ADDRESS:
197             return l3Context.getValue().toString();
198         default:
199             return null;
200         }
201     }
202
203     /**
204      * Returns the identity as a string. The format
205      * of the string depends on the identity type.
206      * When the identity is a actually a list, only
207      * the first identity is returned.
208      *
209      * @return null if type is UKNOWN, otherwise String
210      */
211     public String identityAsString() {
212         switch (type) {
213         case MAC_ADDRESS:
214             return mac.getValue();
215         case IP_ADDRESS:
216             List<IpAddress> ipl = new ArrayList<IpAddress>(ips);
217             IpAddress i = ipl.get(0);
218             if (i.getIpv4Address() != null) {
219                 return i.getIpv4Address().getValue();
220             }
221             else if (i.getIpv6Address() != null) {
222                 return i.getIpv6Address().getValue();
223             }
224         default:
225         }
226         return null;
227     }
228
229     /**
230      * Get the L2 context in an Endpoint Registry
231      * compatible format
232      *
233      * @return The Layer 2 context
234      */
235     public L2BridgeDomainId getL2Context() {
236         return l2Context;
237     }
238
239     /**
240      * Get the L2 identity in an Endpoint Registry
241      * compatible format
242      *
243      * @return The Layer 2 identity
244      */
245     public MacAddress getL2Identity() {
246         return mac;
247     }
248
249     /**
250      * Get the L3 context in an Endpoint Registry
251      * compatible format
252      *
253      * @return The Layer 3 context
254      */
255     public L3ContextId getL3Context() {
256         return l3Context;
257     }
258
259     /**
260      * Get the L3 identity in an Endpoint Registry
261      * compatible format
262      *
263      * @return The Layer 3 identity
264      */
265     public IpAddress getL3Identity() {
266         return primaryIp;
267     }
268
269     public List<L3Address> getL3Addresses() {
270
271         List<L3Address> l3List= new ArrayList<L3Address>();
272         List<IpAddress> ipList = new ArrayList<IpAddress>();
273         ipList.addAll(ips);
274         for (IpAddress i: ipList){
275             L3AddressBuilder l3ab = new L3AddressBuilder();
276             l3ab.setIpAddress(i);
277             l3ab.setL3Context(l3Context);
278             l3List.add(l3ab.build());
279         }
280
281         return l3List;
282     }
283
284     private IpAddress normalizeIpAddress(String identifier) {
285         return IpAddressBuilder.getDefaultInstance(identifier);
286     }
287
288     private MacAddress normalizeMacAddress(String identifier) {
289         MacAddress m = new MacAddress(identifier);
290         return m;
291     }
292
293     @Override
294     public int hashCode() {
295         final int prime = 31;
296         int result = 1;
297         result = prime * result + ((ips == null) ? 0 : ips.hashCode());
298         result = prime * result
299                 + ((l2Context == null) ? 0 : l2Context.hashCode());
300         result = prime * result
301                 + ((l3Context == null) ? 0 : l3Context.hashCode());
302         result = prime * result + ((mac == null) ? 0 : mac.hashCode());
303         result = prime * result
304                 + ((primaryIp == null) ? 0 : primaryIp.hashCode());
305         result = prime * result + ((type == null) ? 0 : type.hashCode());
306         return result;
307     }
308
309     @Override
310     public boolean equals(Object obj) {
311         if (this == obj)
312             return true;
313         if (obj == null)
314             return false;
315         if (getClass() != obj.getClass())
316             return false;
317         Identity other = (Identity) obj;
318         if (ips == null) {
319             if (other.ips != null)
320                 return false;
321         } else if (!ips.equals(other.ips))
322             return false;
323         if (l2Context == null) {
324             if (other.l2Context != null)
325                 return false;
326         } else if (!l2Context.equals(other.l2Context))
327             return false;
328         if (l3Context == null) {
329             if (other.l3Context != null)
330                 return false;
331         } else if (!l3Context.equals(other.l3Context))
332             return false;
333         if (mac == null) {
334             if (other.mac != null)
335                 return false;
336         } else if (!mac.equals(other.mac))
337             return false;
338         if (primaryIp == null) {
339             if (other.primaryIp != null)
340                 return false;
341         } else if (!primaryIp.equals(other.primaryIp))
342             return false;
343         if (type != other.type)
344             return false;
345         return true;
346     }
347
348 }