1 package com.github.triceo.splitlog;
2
3 import java.lang.ref.WeakReference;
4 import java.util.ArrayList;
5 import java.util.Collection;
6 import java.util.Collections;
7 import java.util.Date;
8 import java.util.List;
9
10 import com.github.triceo.splitlog.api.CommonFollower;
11 import com.github.triceo.splitlog.api.ExceptionDescriptor;
12 import com.github.triceo.splitlog.api.Message;
13 import com.github.triceo.splitlog.api.MessageSeverity;
14 import com.github.triceo.splitlog.api.MessageType;
15 import com.github.triceo.splitlog.api.TailSplitter;
16 import com.github.triceo.splitlog.splitters.SimpleTailSplitter;
17
18 final class DefaultMessage implements Message {
19
20 private static final TailSplitter DEFAULT_SPLITTER = new SimpleTailSplitter();
21
22 private final ExceptionDescriptor exceptionDescriptor;
23 private final List<String> lines;
24 private final String logger;
25 private final long millisecondsSinceJanuary1st1970;
26 private final WeakReference<Message> previousMessage;
27 private final MessageSeverity severity;
28 private final TailSplitter splitter;
29 private final MessageType type;
30 private final long uniqueId;
31
32
33
34
35
36
37
38
39
40
41
42 protected DefaultMessage(final long id, final Collection<String> raw) {
43 this(id, raw, DefaultMessage.DEFAULT_SPLITTER);
44 }
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63 protected DefaultMessage(final long id, final Collection<String> raw, final long timestamp,
64 final TailSplitter splitter, final Message previousMessage) {
65 if ((raw == null) || raw.isEmpty()) {
66 throw new IllegalArgumentException("DefaultMessage must not be null.");
67 } else if (splitter == null) {
68 throw new IllegalArgumentException("DefaultMessage requires a TailSplitter.");
69 }
70 if (previousMessage == null) {
71 this.previousMessage = null;
72 } else {
73 this.previousMessage = new WeakReference<Message>(previousMessage);
74 }
75 this.uniqueId = id;
76 this.splitter = splitter;
77 this.lines = Collections.unmodifiableList(new ArrayList<String>(raw));
78 final String logger = splitter.determineLogger(this.lines);
79 this.logger = (logger == null) ? "" : logger;
80 this.severity = splitter.determineSeverity(this.lines);
81 this.type = splitter.determineType(this.lines);
82 this.exceptionDescriptor = splitter.determineException(this.lines);
83
84 final Date d = splitter.determineDate(this.lines);
85 if (d == null) {
86 this.millisecondsSinceJanuary1st1970 = timestamp;
87 } else {
88 this.millisecondsSinceJanuary1st1970 = d.getTime();
89 }
90 }
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105 protected DefaultMessage(final long id, final Collection<String> raw, final TailSplitter splitter) {
106 this(id, raw, System.currentTimeMillis(), splitter, null);
107 }
108
109
110
111
112
113
114
115
116
117
118
119 protected DefaultMessage(final long id, final String message) {
120 if ((message == null) || (message.length() == 0)) {
121 throw new IllegalArgumentException("DefaultMessage must not be empty.");
122 }
123 this.logger = "";
124 this.uniqueId = id;
125 this.previousMessage = null;
126 this.splitter = null;
127 this.lines = Collections.singletonList(message.trim());
128 this.severity = MessageSeverity.UNKNOWN;
129 this.type = MessageType.TAG;
130 this.millisecondsSinceJanuary1st1970 = System.currentTimeMillis();
131 this.exceptionDescriptor = null;
132 }
133
134 @Override
135 public boolean equals(final Object obj) {
136 if (this == obj) {
137 return true;
138 }
139 if (obj == null) {
140 return false;
141 }
142 if (this.getClass() != obj.getClass()) {
143 return false;
144 }
145 final DefaultMessage other = (DefaultMessage) obj;
146 if (this.uniqueId != other.uniqueId) {
147 return false;
148 }
149 return true;
150 }
151
152 @Override
153 public Date getDate() {
154 return new Date(this.millisecondsSinceJanuary1st1970);
155 }
156
157 @Override
158 public ExceptionDescriptor getExceptionDescriptor() {
159 return this.exceptionDescriptor;
160 }
161
162 @Override
163 public List<String> getLines() {
164 return this.lines;
165 }
166
167 @Override
168 public List<String> getLinesWithoutMetadata() {
169 if (this.type == MessageType.TAG) {
170
171 return this.lines;
172 }
173 final List<String> stripped = new ArrayList<String>();
174 for (final String line : this.lines) {
175 stripped.add(this.splitter.stripOfMetadata(line));
176 }
177 return Collections.unmodifiableList(stripped);
178 }
179
180 @Override
181 public String getLogger() {
182 return this.logger;
183 }
184
185 @Override
186 public Message getPreviousMessage() {
187 if (this.previousMessage == null) {
188 return null;
189 }
190 return this.previousMessage.get();
191 }
192
193 @Override
194 public MessageSeverity getSeverity() {
195 return this.severity;
196 }
197
198 @Override
199 public MessageType getType() {
200 return this.type;
201 }
202
203 @Override
204 public long getUniqueId() {
205 return this.uniqueId;
206 }
207
208 @Override
209 public boolean hasException() {
210 return this.exceptionDescriptor != null;
211 }
212
213 @Override
214 public int hashCode() {
215 final int prime = 31;
216 int result = 1;
217 result = (prime * result) + (int) (this.uniqueId ^ (this.uniqueId >>> 32));
218 return result;
219 }
220
221 @Override
222 public String toString() {
223 final StringBuilder sb = new StringBuilder();
224 sb.append('#');
225 sb.append(this.getUniqueId());
226 sb.append(" ");
227 sb.append(" [");
228 sb.append(this.logger);
229 sb.append("] ");
230 sb.append(this.getDate());
231 sb.append(" (");
232 sb.append(this.type);
233 sb.append(") ");
234 sb.append(this.severity);
235 sb.append(" '");
236 sb.append(this.lines.get(0));
237 sb.append("'");
238 if (this.lines.size() > 1) {
239 sb.append(" and ");
240 sb.append(this.lines.size() - 1);
241 sb.append(" more lines...");
242 }
243 return sb.toString();
244 }
245
246 }