1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.logging.log4j.message;
18
19 import java.util.Map;
20
21 import org.apache.logging.log4j.util.EnglishEnums;
22
23
24
25
26
27
28
29
30
31
32
33 public class StructuredDataMessage extends MapMessage {
34
35 private static final long serialVersionUID = 1703221292892071920L;
36 private static final int MAX_LENGTH = 32;
37 private static final int HASHVAL = 31;
38
39 private StructuredDataId id;
40
41 private String message;
42
43 private String type;
44
45
46
47
48 public enum Format {
49
50 XML,
51
52 FULL
53 }
54
55
56
57
58
59
60
61 public StructuredDataMessage(final String id, final String msg, final String type) {
62 this.id = new StructuredDataId(id, null, null);
63 this.message = msg;
64 this.type = type;
65 }
66
67
68
69
70
71
72
73 public StructuredDataMessage(final String id, final String msg, final String type,
74 final Map<String, String> data) {
75 super(data);
76 this.id = new StructuredDataId(id, null, null);
77 this.message = msg;
78 this.type = type;
79 }
80
81
82
83
84
85
86
87 public StructuredDataMessage(final StructuredDataId id, final String msg, final String type) {
88 this.id = id;
89 this.message = msg;
90 this.type = type;
91 }
92
93
94
95
96
97
98
99
100 public StructuredDataMessage(final StructuredDataId id, final String msg, final String type,
101 final Map<String, String> data) {
102 super(data);
103 this.id = id;
104 this.message = msg;
105 this.type = type;
106 }
107
108
109
110
111
112
113
114 private StructuredDataMessage(final StructuredDataMessage msg, final Map<String, String> map) {
115 super(map);
116 this.id = msg.id;
117 this.message = msg.message;
118 this.type = msg.type;
119 }
120
121
122
123
124
125 protected StructuredDataMessage() {
126
127 }
128
129
130
131
132
133 @Override
134 public String[] getFormats() {
135 final String[] formats = new String[Format.values().length];
136 int i = 0;
137 for (final Format format : Format.values()) {
138 formats[i++] = format.name();
139 }
140 return formats;
141 }
142
143
144
145
146
147 public StructuredDataId getId() {
148 return id;
149 }
150
151
152
153
154
155 protected void setId(final String id) {
156 this.id = new StructuredDataId(id, null, null);
157 }
158
159
160
161
162
163 protected void setId(final StructuredDataId id) {
164 this.id = id;
165 }
166
167
168
169
170
171 public String getType() {
172 return type;
173 }
174
175 protected void setType(final String type) {
176 if (type.length() > MAX_LENGTH) {
177 throw new IllegalArgumentException("structured data type exceeds maximum length of 32 characters: " + type);
178 }
179 this.type = type;
180 }
181
182
183
184
185
186 @Override
187 public String getFormat() {
188 return message;
189 }
190
191 protected void setMessageFormat(final String msg) {
192 this.message = msg;
193 }
194
195
196 @Override
197 protected void validate(final String key, final String value) {
198 validateKey(key);
199 }
200
201 private void validateKey(final String key) {
202 if (key.length() > MAX_LENGTH) {
203 throw new IllegalArgumentException("Structured data keys are limited to 32 characters. key: " + key);
204 }
205 final char[] chars = key.toCharArray();
206 for (final char c : chars) {
207 if (c < '!' || c > '~' || c == '=' || c == ']' || c == '"') {
208 throw new IllegalArgumentException("Structured data keys must contain printable US ASCII characters" +
209 "and may not contain a space, =, ], or \"");
210 }
211 }
212 }
213
214
215
216
217
218
219 @Override
220 public String asString() {
221 return asString(Format.FULL, null);
222 }
223
224
225
226
227
228
229
230
231 @Override
232 public String asString(final String format) {
233 try {
234 return asString(EnglishEnums.valueOf(Format.class, format), null);
235 } catch (final IllegalArgumentException ex) {
236 return asString();
237 }
238 }
239
240
241
242
243
244
245
246
247
248
249 public final String asString(final Format format, final StructuredDataId structuredDataId) {
250 final StringBuilder sb = new StringBuilder();
251 final boolean full = Format.FULL.equals(format);
252 if (full) {
253 final String type = getType();
254 if (type == null) {
255 return sb.toString();
256 }
257 sb.append(getType()).append(' ');
258 }
259 StructuredDataId id = getId();
260 if (id != null) {
261 id = id.makeId(structuredDataId);
262 } else {
263 id = structuredDataId;
264 }
265 if (id == null || id.getName() == null) {
266 return sb.toString();
267 }
268 sb.append('[');
269 sb.append(id);
270 sb.append(' ');
271 appendMap(sb);
272 sb.append(']');
273 if (full) {
274 final String msg = getFormat();
275 if (msg != null) {
276 sb.append(' ').append(msg);
277 }
278 }
279 return sb.toString();
280 }
281
282
283
284
285
286 @Override
287 public String getFormattedMessage() {
288 return asString(Format.FULL, null);
289 }
290
291
292
293
294
295
296
297
298
299
300 @Override
301 public String getFormattedMessage(final String[] formats) {
302 if (formats != null && formats.length > 0) {
303 for (final String format : formats) {
304 if (Format.XML.name().equalsIgnoreCase(format)) {
305 return asXML();
306 } else if (Format.FULL.name().equalsIgnoreCase(format)) {
307 return asString(Format.FULL, null);
308 }
309 }
310 return asString(null, null);
311 }
312 return asString(Format.FULL, null);
313 }
314
315 private String asXML() {
316 final StringBuilder sb = new StringBuilder();
317 final StructuredDataId id = getId();
318 if (id == null || id.getName() == null || type == null) {
319 return sb.toString();
320 }
321 sb.append("<StructuredData>\n");
322 sb.append("<type>").append(type).append("</type>\n");
323 sb.append("<id>").append(id).append("</id>\n");
324 super.asXml(sb);
325 sb.append("</StructuredData>\n");
326 return sb.toString();
327 }
328
329 @Override
330 public String toString() {
331 return asString(null, null);
332 }
333
334
335 @Override
336 public MapMessage newInstance(final Map<String, String> map) {
337 return new StructuredDataMessage(this, map);
338 }
339
340 @Override
341 public boolean equals(final Object o) {
342 if (this == o) {
343 return true;
344 }
345 if (o == null || getClass() != o.getClass()) {
346 return false;
347 }
348
349 final StructuredDataMessage that = (StructuredDataMessage) o;
350
351 if (!super.equals(o)) {
352 return false;
353 }
354 if (type != null ? !type.equals(that.type) : that.type != null) {
355 return false;
356 }
357 if (id != null ? !id.equals(that.id) : that.id != null) {
358 return false;
359 }
360 if (message != null ? !message.equals(that.message) : that.message != null) {
361 return false;
362 }
363
364 return true;
365 }
366
367 @Override
368 public int hashCode() {
369 int result = super.hashCode();
370 result = HASHVAL * result + (type != null ? type.hashCode() : 0);
371 result = HASHVAL * result + (id != null ? id.hashCode() : 0);
372 result = HASHVAL * result + (message != null ? message.hashCode() : 0);
373 return result;
374 }
375 }