OpenDaylight Controller functional modules.
[controller.git] / opendaylight / sal / api / src / main / java / org / opendaylight / controller / sal / match / MatchField.java
1
2 /*
3  * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
4  *
5  * This program and the accompanying materials are made available under the
6  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
7  * and is available at http://www.eclipse.org/legal/epl-v10.html
8  */
9
10 package org.opendaylight.controller.sal.match;
11
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.apache.commons.lang3.builder.EqualsBuilder;
18 import org.apache.commons.lang3.builder.HashCodeBuilder;
19 import org.opendaylight.controller.sal.utils.HexEncode;
20 import org.slf4j.Logger;
21 import org.slf4j.LoggerFactory;
22
23 /**
24  * Represents the generic matching field
25  *
26  */
27
28 @XmlRootElement
29 @XmlAccessorType(XmlAccessType.NONE)
30
31 public class MatchField implements Cloneable {
32     private static final Logger logger = LoggerFactory
33             .getLogger(MatchField.class);
34         private MatchType type; // the field we want to match
35     private Object value; // the value of the field we want to match
36     private Object mask; // the value of the mask we want to match on the specified field
37     private transient boolean isValid;
38
39     // To satisfy JAXB
40     private MatchField() {
41     }
42     /**
43      * Mask based match constructor
44      *
45      * @param type
46      * @param value
47      * @param mask   has to be of the same class type of value. A null mask means full match
48      */
49     public MatchField(MatchType type, Object value, Object mask) {
50         this.type = type;
51         this.value = value;
52         this.mask = mask;
53         this.isValid = checkValueType() && checkValues(); // Keep this logic, value checked only if type check is fine
54     }
55
56     /**
57      * Full match constructor
58      *
59      * @param type
60      * @param value
61      */
62     public MatchField(MatchType type, Object value) {
63         this.type = type;
64         this.value = value;
65         this.mask = null;
66         this.isValid = checkValueType() && checkValues(); // Keep this logic, value checked only if type check is fine
67     }
68
69     /**
70      * Returns the value set for this match field
71      *
72      * @return
73      */
74     public Object getValue() {
75         return value;
76     }
77     
78     @XmlElement(name="value")
79     private String getValueString() {
80         return type.stringify(value);
81     }
82
83     /**
84      * Returns the type field this match field object is for
85      *
86      * @return
87      */
88     public MatchType getType() {
89         return type;
90     }
91
92     @XmlElement(name="type")
93     private String getTypeString() {
94         return type.toString();
95     }
96
97     /**
98      * Returns the mask value set for this field match
99      * A null mask means this is a full match
100      * @return
101      */
102     public Object getMask() {
103         return mask;
104     }
105     
106     @XmlElement(name="mask")
107     private String getMaskString() {
108         return type.stringify(mask); 
109     }
110
111     /**
112      * Returns the bitmask set for this field match
113      *
114      * @return
115      */
116     public long getBitMask() {
117         return type.getBitMask(mask);
118     }
119
120     /**
121      * Returns whether the field match configuration is valid or not
122      *
123      * @return
124      */
125     public boolean isValid() {
126         return isValid;
127     }
128
129     private boolean checkValueType() {
130         if (type.isCongruentType(value, mask) == false) {
131             String valueClass = (value == null) ? "null" : value.getClass()
132                     .getSimpleName();
133             String maskClass = (mask == null) ? "null" : mask.getClass()
134                     .getSimpleName();
135             String error = "Invalid match field's value or mask types.For field: "
136                     + type.id()
137                     + " Expected:"
138                     + type.dataType().getSimpleName()
139                     + " or equivalent,"
140                     + " Got:(" + valueClass + "," + maskClass + ")";
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: "
152                     + type.id()
153                     + " Expected: "
154                     + type.getRange()
155                     + ", Got:(0x"
156                     + Integer.toHexString(Integer.parseInt(value.toString()))
157                     + "," + maskString + ")";
158
159             throwException(error);
160             return false;
161         }
162         return true;
163     }
164
165     private static void throwException(String error) {
166         try {
167             throw new Exception(error);
168         } catch (Exception e) {
169             logger.error(e.getMessage());
170         }
171     }
172
173     @Override
174     public MatchField clone() {
175         MatchField cloned = null;
176         try {
177             cloned = (MatchField) super.clone();
178             if (value instanceof byte[]) {
179                 cloned.value = ((byte[]) this.value).clone();
180                 if (this.mask != null) {
181                     cloned.mask = ((byte[]) this.mask).clone();
182                 }
183             }
184         } catch (CloneNotSupportedException e) {
185             e.printStackTrace();
186         }
187         return cloned;
188     }
189
190     @Override
191     public int hashCode() {
192         return HashCodeBuilder.reflectionHashCode(this);
193     }
194
195     @Override
196     public boolean equals(Object obj) {
197         return EqualsBuilder.reflectionEquals(this, obj);
198     }
199
200     @Override
201     public String toString() {
202         return type + "(" + getValueString() + "," + getMaskString() + ")";
203     }
204 }