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