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