3b8a2952164eafb0cf463208d06cc29a182e2d6f
[controller.git] / opendaylight / sal / api / src / main / java / org / opendaylight / controller / sal / match / MatchField.java
1 /*
2  * Copyright (c) 2013 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.controller.sal.match;
10
11 import java.io.Serializable;
12 import javax.xml.bind.annotation.XmlAccessType;
13 import javax.xml.bind.annotation.XmlAccessorType;
14 import javax.xml.bind.annotation.XmlElement;
15 import javax.xml.bind.annotation.XmlRootElement;
16
17 import org.slf4j.Logger;
18 import org.slf4j.LoggerFactory;
19
20 /**
21  * Represents the generic matching field
22  *
23  */
24
25 @XmlRootElement
26 @XmlAccessorType(XmlAccessType.NONE)
27 public class MatchField implements Cloneable, Serializable {
28     private static final long serialVersionUID = 1L;
29     private static final Logger logger = LoggerFactory.getLogger(MatchField.class);
30     private MatchType type; // the field we want to match
31     private Object value; // the value of the field we want to match
32     private Object mask; // the value of the mask we want to match on the
33     // specified field
34     private transient boolean isValid;
35
36     // To satisfy JAXB
37     @SuppressWarnings("unused")
38     private MatchField() {
39     }
40
41     /**
42      * Mask based match constructor
43      *
44      * @param type
45      * @param value
46      * @param mask
47      *            has to be of the same class type of value. A null mask means
48      *            full match
49      */
50     public MatchField(MatchType type, Object value, Object mask) {
51         this.type = type;
52         this.value = value;
53         this.mask = mask;
54         // Keep this logic, value checked only if type check is fine
55         this.isValid = checkValueType() && checkValues();
56     }
57
58     /**
59      * Full match constructor
60      *
61      * @param type
62      * @param value
63      */
64     public MatchField(MatchType type, Object value) {
65         this.type = type;
66         this.value = value;
67         this.mask = null;
68         // Keep this logic, value checked only if type check is fine
69         this.isValid = checkValueType() && checkValues();
70     }
71
72     /**
73      * Returns the value set for this match field
74      *
75      * @return
76      */
77     public Object getValue() {
78         return value;
79     }
80
81     @XmlElement(name = "value")
82     private String getValueString() {
83         return type.stringify(value);
84     }
85
86     /**
87      * Returns the type field this match field object is for
88      *
89      * @return
90      */
91     public MatchType getType() {
92         return type;
93     }
94
95     @XmlElement(name = "type")
96     private String getTypeString() {
97         return type.toString();
98     }
99
100     /**
101      * Returns the mask value set for this field match A null mask means this is
102      * a full match
103      *
104      * @return
105      */
106     public Object getMask() {
107         return mask;
108     }
109
110     @XmlElement(name = "mask")
111     private String getMaskString() {
112         return type.stringify(mask);
113     }
114
115     /**
116      * Returns the bitmask set for this field match
117      *
118      * @return
119      */
120     public long getBitMask() {
121         return type.getBitMask(mask);
122     }
123
124     /**
125      * Returns whether the field match configuration is valid or not
126      *
127      * @return
128      */
129     public boolean isValid() {
130         return isValid;
131     }
132
133     private boolean checkValueType() {
134         if (type.isCongruentType(value, mask) == false) {
135             String valueClass = (value == null) ? "null" : value.getClass().getSimpleName();
136             String maskClass = (mask == null) ? "null" : mask.getClass().getSimpleName();
137             String error = "Invalid match field's value or mask types.For field: " + type.id() + " Expected:"
138                     + type.dataType().getSimpleName() + " or equivalent," + " Got:(" + valueClass + "," + maskClass
139                     + ")";
140             throwException(error);
141             return false;
142         }
143         return true;
144     }
145
146     private boolean checkValues() {
147         if (type.isValid(value, mask) == false) {
148             String maskString = (mask == null) ? "null" : ("0x" + Integer
149                     .toHexString(Integer.parseInt(mask.toString())));
150             String error = "Invalid match field's value or mask assignement.For field: " + type.id() + " Expected: "
151                     + type.getRange() + ", Got:(0x" + Integer.toHexString(Integer.parseInt(value.toString())) + ","
152                     + maskString + ")";
153
154             throwException(error);
155             return false;
156         }
157         return true;
158     }
159
160     private static void throwException(String error) {
161         try {
162             throw new Exception(error);
163         } catch (Exception e) {
164             logger.error(e.getMessage());
165         }
166     }
167
168     @Override
169     public MatchField clone() {
170         MatchField cloned = null;
171         try {
172             cloned = (MatchField) super.clone();
173             if (value instanceof byte[]) {
174                 cloned.value = ((byte[]) this.value).clone();
175                 if (this.mask != null) {
176                     cloned.mask = ((byte[]) this.mask).clone();
177                 }
178             }
179         } catch (CloneNotSupportedException e) {
180             logger.error("", e);
181         }
182         return cloned;
183     }
184
185     @Override
186     public String toString() {
187         return type + "(" + getValueString() + "," + getMaskString() + ")";
188     }
189
190     @Override
191     public int hashCode() {
192         return type.hashCode(value, mask);
193     }
194
195     @Override
196     public boolean equals(Object obj) {
197         if (this == obj) {
198             return true;
199         }
200         if (obj == null) {
201             return false;
202         }
203         if (getClass() != obj.getClass()) {
204             return false;
205         }
206         MatchField other = (MatchField) obj;
207         if (type != other.type) {
208             return false;
209         }
210         return type.equals(this.value, other.value, this.mask, other.mask);
211     }
212 }