View Javadoc
1   /*  This file is part of the aspect  project.
2    This program is free software; you can redistribute it and/or
3    modify it under the terms of the GNU Lesser General Public License
4    as published by the Free Software Foundation; version 2.1
5    of the License.
6    This program is distributed in the hope that it will be useful,
7    but WITHOUT ANY WARRANTY; without even the implied warranty of
8    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9    GNU Lesser General Public License for more details.
10   You should have received a copy of the GNU Lesser General Public License
11   along with this program; if not, write to the Free Software
12   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
13  
14   Copyright 2007-2014 Semochkin Vitaliy Evgenevich aka Yilativs
15    
16   */
17  package net.sf.aspect4log.text;
18  
19  import net.sf.aspect4log.Log;
20  import net.sf.aspect4log.aspect.LogAspect;
21  import net.sf.aspect4log.conf.LogFormatConfiguration;
22  
23  /**
24   *
25   * This class is responsible for creating {@link MessageBuilder} instances.
26   * Log decoration properties are set by {@link LogFormatConfiguration via reflection.
27   * 
28   * @author yilativs
29   *
30   */
31  public class CustomisableMessageBuilderFactory implements MessageBuilderFactory {
32  	public static final String METHOD_ENTER_SYMBOL = "↓";
33  	public static final String METHOD_SUCCESSFUL_EXIT_SYMBOL = "↑";
34  	public static final String METHOD_THROWN_EXCEPTION_EXIT_SYMBOL = "⇑";
35  	public static final String RETURNED_VALUE_SEPARATOR = " → ";
36  	public static final String THROWN_EXCEPTION_SEPARATOR = " ⇒ ";
37  
38  	private String methodEnterSymbol = METHOD_ENTER_SYMBOL;
39  	private String methodSuccessfulExitSymbol = METHOD_SUCCESSFUL_EXIT_SYMBOL;
40  	private String methodThrownExceptionExitSymbol = METHOD_THROWN_EXCEPTION_EXIT_SYMBOL;
41  	private String returnedValueSeparator = RETURNED_VALUE_SEPARATOR;
42  	private String thrownExceptionSeparator = THROWN_EXCEPTION_SEPARATOR;
43  
44  	/**
45  	 * 
46  	 * @return specifies if indent should be used for methods called inside marked method. The default value is true.
47  	 */
48  
49  	private boolean useIndent = true;
50  
51  	/**
52  	 * @return a java.lang.String that represents text of Indent. The default value is 1 tab symbol.
53  	 */
54  
55  	private String indentText = "\t";
56  
57  	public boolean isUseIndent() {
58  		return useIndent;
59  	}
60  
61  	public void setUseIndent(boolean useIndent) {
62  		this.useIndent = useIndent;
63  	}
64  
65  	public String getIndentText() {
66  		return indentText;
67  	}
68  
69  	public void setIndentText(String indentText) {
70  		this.indentText = indentText;
71  	}
72  
73  	public void setElementsDelitmiter(String elementsDelitmiter) {
74  		logFormatter.setElementsDelitmiter(elementsDelitmiter);
75  	}
76  
77  	public void setMapKeyValueDelimeter(String mapKeyValueDelimeter) {
78  		logFormatter.setMapKeyValueDelimeter(mapKeyValueDelimeter);
79  	}
80  
81  	public void setArrayBeginsBracket(String arrayBeginsBracket) {
82  		logFormatter.setArrayBeginsBracket(arrayBeginsBracket);
83  	}
84  
85  	public void setArrayEndsBracket(String arrayEndsBracket) {
86  		logFormatter.setArrayEndsBracket(arrayEndsBracket);
87  	}
88  
89  	public void setIterableBeginsBracket(String iterableBeginsBracket) {
90  		logFormatter.setIterableBeginsBracket(iterableBeginsBracket);
91  	}
92  
93  	public void setIterableEndsBracket(String iterableEndsBracket) {
94  		logFormatter.setIterableEndsBracket(iterableEndsBracket);
95  	}
96  
97  	public void setUndefindedToStringMethodSymbol(String undefindedToStringValue) {
98  		logFormatter.setUndefindedToStringMethodSymbol(undefindedToStringValue);
99  	}
100 
101 	public void setNullSymbol(String nullValue) {
102 		logFormatter.setNullSymbol(nullValue);
103 	}
104 
105 	public void setErrorEvaluatingToStringSymbol(String errorValue) {
106 		logFormatter.setErrorEvaluatingToStringSymbol(errorValue);
107 	}
108 
109 	public void setMethodEnterSymbol(String methodEnterSymbol) {
110 		this.methodEnterSymbol = methodEnterSymbol;
111 	}
112 
113 	public void setMethodSuccessfulExitSymbol(String methodSuccessfulReturnSymbol) {
114 		this.methodSuccessfulExitSymbol = methodSuccessfulReturnSymbol;
115 	}
116 
117 	public void setMethodThrownExceptionExitSymbol(String returnValueSymbol) {
118 		this.methodThrownExceptionExitSymbol = returnValueSymbol;
119 	}
120 
121 	public void setThrownExceptionSeparator(String methodExceptionReturSymbol) {
122 		this.thrownExceptionSeparator = methodExceptionReturSymbol;
123 	}
124 
125 	public void setReturnedValueSeparator(String exceptionValueSymbol) {
126 		this.returnedValueSeparator = exceptionValueSymbol;
127 	}
128 
129 	private final LogFormatter logFormatter = new LogFormatter();
130 
131 	@Override
132 	public MessageBuilder createEnterMessageBuilder(String methodName, Log log, Object[] args) {
133 		return new EnterMessageBuilder(methodName, log, args);
134 	}
135 
136 	@Override
137 	public MessageBuilder createSuccessfulReturnMessageBuilder(String methodName, Log log, Object[] args, boolean returnsNothing, Object result) {
138 		return new MethodSuccessfulExitMessageBuilder(methodName, log, args, returnsNothing, result);
139 	}
140 
141 	@Override
142 	public MessageBuilder createExceptionReturnMessageBuilder(String methodName, Log log, Object[] args, Throwable throwable, String exceptionExitTemplate) {
143 		return new ExceptionReturnMessageBuilder(methodName, log, args, throwable, exceptionExitTemplate);
144 	}
145 
146 	private final class SimpleMdcMessageBuilder implements MessageBuilder {
147 		private final Log log;
148 		private final Object[] args;
149 
150 		protected SimpleMdcMessageBuilder(Log log, Object[] args) {
151 			this.log = log;
152 			this.args = (Object[])args.clone();
153 		}
154 
155 		@Override
156 		public String build() {
157 			return logFormatter.toString(log.mdcTemplate(), args);
158 		}
159 	}
160 
161 	private class EnterMessageBuilder extends CustomisableMessageBulder {
162 
163 		public EnterMessageBuilder(String methodName, Log log, Object[] args) {
164 			super(methodName, log, args, logFormatter);
165 		}
166 
167 		@Override
168 		protected void buildDirectionSymbol(StringBuilder stringBuilder) {
169 			stringBuilder.append(methodEnterSymbol);
170 		}
171 	}
172 
173 	private class MethodSuccessfulExitMessageBuilder extends CustomisableMessageBulder {
174 
175 		private final Object result;
176 		private final boolean returnsNothing;
177 
178 		public MethodSuccessfulExitMessageBuilder(String methodName, Log log, Object[] args, boolean returnsNothing, Object result) {
179 			super(methodName, log, args, logFormatter);
180 			this.returnsNothing = returnsNothing;
181 			this.result = result;
182 		}
183 
184 		@Override
185 		protected void buildDirectionSymbol(StringBuilder stringBuilder) {
186 			stringBuilder.append(methodSuccessfulExitSymbol);
187 		}
188 
189 		@Override
190 		protected void buildResultDelimeter(StringBuilder stringBuilder) {
191 			if (isBuildingResultRequired()) {
192 				stringBuilder.append(returnedValueSeparator);
193 			}
194 		}
195 
196 		@Override
197 		protected void buildResult(StringBuilder stringBuilder) {
198 			if (isBuildingResultRequired()) {
199 				stringBuilder.append(logFormatter.toString(getLog().resultTemplate(), result));
200 			}
201 		}
202 
203 		private boolean isBuildingResultRequired() {
204 			return !getLog().resultTemplate().isEmpty() && !returnsNothing;
205 		}
206 	}
207 
208 	private class ExceptionReturnMessageBuilder extends CustomisableMessageBulder {
209 
210 		private final Throwable throwable;
211 		private final String exceptionExitTemplate;
212 
213 		public ExceptionReturnMessageBuilder(String methodName, Log log, Object[] args, Throwable throwable, String exceptionExitTemplate) {
214 			super(methodName, log, args, logFormatter);
215 			this.throwable = throwable;
216 			this.exceptionExitTemplate = exceptionExitTemplate;
217 		}
218 
219 		@Override
220 		protected void buildDirectionSymbol(StringBuilder stringBuilder) {
221 			stringBuilder.append(methodThrownExceptionExitSymbol);
222 		}
223 
224 		@Override
225 		protected void buildResultDelimeter(StringBuilder stringBuilder) {
226 			stringBuilder.append(thrownExceptionSeparator);
227 		}
228 
229 		@Override
230 		protected void buildResult(StringBuilder stringBuilder) {
231 			if (!exceptionExitTemplate.isEmpty()) {
232 				stringBuilder.append(logFormatter.toString(exceptionExitTemplate, throwable));
233 			}
234 		}
235 	}
236 
237 	@Override
238 	public MessageBuilder createMdcTemplate(final Log log, final Object[] args) {
239 		return new SimpleMdcMessageBuilder(log, args);
240 	}
241 
242 	private abstract class CustomisableMessageBulder implements MessageBuilder {
243 		private final String methodName;
244 		private final Log log;
245 		private final Object[] args;
246 		private final LogFormatter logFormatter;
247 
248 		public CustomisableMessageBulder(String methodName, Log log, Object[] args, LogFormatter logFormatter) {
249 			this.methodName = methodName;
250 			this.log = log;
251 			this.logFormatter = logFormatter;
252 			this.args = args.clone();
253 		}
254 
255 		@Override
256 		public final String build() {
257 			StringBuilder stringBuilder = new StringBuilder();
258 			buildDirectionSymbol(stringBuilder);
259 			buildIndent(stringBuilder);
260 			buildMethodName(stringBuilder);
261 			buildMethodOpenBracket(stringBuilder);
262 			buildArguments(stringBuilder);
263 			buildMethodClosedBracket(stringBuilder);
264 			buildResultDelimeter(stringBuilder);
265 			buildResult(stringBuilder);
266 			return stringBuilder.toString();
267 		}
268 
269 		protected void buildIndent(StringBuilder stringBuilder) {
270 			for (int i = 0; i < LogAspect.getThreadLocalIdent().intValue(); i++) {
271 				stringBuilder.append(indentText);
272 			}
273 		}
274 
275 		abstract protected void buildDirectionSymbol(StringBuilder stringBuilder);
276 
277 		protected void buildMethodName(StringBuilder stringBuilder) {
278 			stringBuilder.append(methodName);
279 		}
280 
281 		protected void buildMethodOpenBracket(StringBuilder stringBuilder) {
282 			stringBuilder.append("(");
283 		}
284 
285 		protected void buildArguments(StringBuilder stringBuilder) {
286 			if (!log.argumentsTemplate().isEmpty()) {
287 				if (Log.ARGUMENTS_DEFAULT_TEMPLATE.equals(log.argumentsTemplate())) {
288 					stringBuilder.append(logFormatter.toString(args));
289 				} else {
290 					stringBuilder.append(logFormatter.toString(log.argumentsTemplate(), args));
291 				}
292 			}
293 		}
294 
295 		protected void buildMethodClosedBracket(StringBuilder stringBuilder) {
296 			stringBuilder.append(")");
297 		}
298 
299 		protected void buildResultDelimeter(StringBuilder stringBuilder) {
300 			// there is no result by default
301 		}
302 
303 		protected void buildResult(StringBuilder stringBuilder) {
304 			// there is no result by default
305 		}
306 
307 		protected Log getLog() {
308 			return log;
309 		}
310 
311 	}
312 
313 	@Override
314 	public String buildIdent() {
315 		StringBuilder stringBuilder = new StringBuilder();
316 		for (int i = 0; i < LogAspect.getThreadLocalIdent().intValue(); i++) {
317 			stringBuilder.append(indentText);
318 		}
319 		return stringBuilder.toString();
320 	}
321 
322 }