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