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