1
2
3
4 package de.powerstat.validation.values;
5
6
7 import java.util.Arrays;
8 import java.util.Locale;
9 import java.util.Objects;
10 import java.util.regex.Pattern;
11
12 import de.powerstat.validation.interfaces.IValueObject;
13
14
15
16
17
18
19
20
21
22 public final class MACAddress implements Comparable<MACAddress>, IValueObject
23 {
24
25
26
27
28
29
30
31
32 private static final String H00 = "00";
33
34
35
36
37 private static final String H01 = "01";
38
39
40
41
42 private static final String H33 = "33";
43
44
45
46
47 private static final String H5E = "5e";
48
49
50
51
52 private static final String HFF = "ff";
53
54
55
56
57 private static final String SEPARATOR = ":";
58
59
60
61
62 private static final String DELIMITER = "-";
63
64
65
66
67 private static final String DELIMITER_TXT = "delimiter";
68
69
70
71
72 private static final String ILLEGAL_DELIMITER_LENGTH = "Illegal delimiter length";
73
74
75
76
77 private static final String ILLEGAL_DELIMITER_CHARACTER = "Illegal delimiter character";
78
79
80
81
82 private static final Pattern IPV6_REGEXP = Pattern.compile("^[0-9a-f]{2}([:-]?[0-9a-f]{2}){5}$");
83
84
85
86
87 private static final Pattern IPV6_SEPARATOR_REGEXP = Pattern.compile("[:-]");
88
89
90
91
92 private final String[] parts;
93
94
95
96
97
98
99
100
101
102 private MACAddress(final String address)
103 {
104 super();
105 Objects.requireNonNull(address, "address");
106 if ((address.length() != 12) && (address.length() != 17))
107 {
108 throw new IllegalArgumentException("To short or long for a mac address");
109 }
110 if (!MACAddress.IPV6_REGEXP.matcher(address.toLowerCase(Locale.getDefault())).matches())
111 {
112 throw new IllegalArgumentException("Not a mac address");
113 }
114 this.parts = MACAddress.IPV6_SEPARATOR_REGEXP.split(address.toLowerCase(Locale.getDefault()));
115 }
116
117
118
119
120
121
122
123
124 public static MACAddress of(final String address)
125 {
126
127
128
129
130
131
132
133
134
135
136
137
138
139 return new MACAddress(address);
140 }
141
142
143
144
145
146
147
148
149 public String stringValue(final String delimiter)
150 {
151 Objects.requireNonNull(delimiter, MACAddress.DELIMITER_TXT);
152 if (delimiter.length() > 1)
153 {
154 throw new IllegalArgumentException(MACAddress.ILLEGAL_DELIMITER_LENGTH);
155 }
156 if (!delimiter.isEmpty() && !MACAddress.SEPARATOR.equals(delimiter) && !MACAddress.DELIMITER.equals(delimiter))
157 {
158 throw new IllegalArgumentException(MACAddress.ILLEGAL_DELIMITER_CHARACTER);
159 }
160 return String.join(delimiter, this.parts);
161 }
162
163
164
165
166
167
168
169 @Override
170 public String stringValue()
171 {
172 return stringValue(MACAddress.SEPARATOR);
173 }
174
175
176
177
178
179
180
181 public boolean isBroadcast()
182 {
183 return MACAddress.HFF.equals(this.parts[0]) && MACAddress.HFF.equals(this.parts[1]) && MACAddress.HFF.equals(this.parts[2]) && MACAddress.HFF.equals(this.parts[3]) && MACAddress.HFF.equals(this.parts[4]) && MACAddress.HFF.equals(this.parts[5]);
184 }
185
186
187
188
189
190
191
192 public boolean isGroup()
193 {
194 return (Integer.parseInt(this.parts[0], 16) & 0x01) != 0;
195 }
196
197
198
199
200
201
202
203 public boolean isLocal()
204 {
205 return (Integer.parseInt(this.parts[0], 16) & 0x02) != 0;
206 }
207
208
209
210
211
212
213
214 public boolean isIPV4Multicast()
215 {
216 return MACAddress.H01.equals(this.parts[0]) && MACAddress.H00.equals(this.parts[1]) && MACAddress.H5E.equals(this.parts[2]) && ((Integer.parseInt(this.parts[3], 16) & 0x80) == 0);
217 }
218
219
220
221
222
223
224
225 public boolean isIPV6Multicast()
226 {
227 return MACAddress.H33.equals(this.parts[0]) && MACAddress.H33.equals(this.parts[1]);
228 }
229
230
231
232
233
234
235
236 public boolean isVRRP()
237 {
238 return MACAddress.H00.equals(this.parts[0]) && MACAddress.H00.equals(this.parts[1]) && MACAddress.H5E.equals(this.parts[2]) && MACAddress.H00.equals(this.parts[3]) && MACAddress.H01.equals(this.parts[4]);
239 }
240
241
242
243
244
245
246
247
248
249 public String getOUI()
250 {
251 return String.format("%1$02X", Integer.parseInt(this.parts[0], 16) & 0xfc) + this.parts[1].toUpperCase(Locale.getDefault()) + this.parts[2].toUpperCase(Locale.getDefault());
252 }
253
254
255
256
257
258
259
260
261 @Override
262 public int hashCode()
263 {
264 return Arrays.hashCode(this.parts);
265 }
266
267
268
269
270
271
272
273
274
275 @Override
276 public boolean equals(final Object obj)
277 {
278 if (this == obj)
279 {
280 return true;
281 }
282 if (!(obj instanceof MACAddress))
283 {
284 return false;
285 }
286 final MACAddress other = (MACAddress)obj;
287 return Arrays.equals(this.parts, other.parts);
288 }
289
290
291
292
293
294
295
296
297
298
299
300
301 @Override
302 public String toString()
303 {
304 final var builder = new StringBuilder(21);
305 builder.append("MACAddress[address=").append(String.join(MACAddress.SEPARATOR, this.parts)).append(']');
306 return builder.toString();
307 }
308
309
310
311
312
313
314
315
316
317 @Override
318 public int compareTo(final MACAddress obj)
319 {
320 Objects.requireNonNull(obj, "obj");
321 return Arrays.compare(this.parts, obj.parts);
322 }
323
324 }