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