1/*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements.  See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License.  You may obtain a copy of the License at
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18package tests.util;
19
20import java.util.Stack;
21
22/**
23 * A stack to store the parameters of a call, as well as the call stack.
24 *
25 */
26public class CallVerificationStack extends Stack<Object> {
27
28	/*
29	 * --------------------------------------------------------------------
30	 * Class variables
31	 * --------------------------------------------------------------------
32	 */
33
34	private static final long serialVersionUID = 1L;
35
36	// the singleton
37	private static final CallVerificationStack _instance = new CallVerificationStack();
38
39	/*
40	 * --------------------------------------------------------------------
41	 * Instance variables
42	 * --------------------------------------------------------------------
43	 */
44
45	// the call stack, store StackTraceElement
46	private final Stack<StackTraceElement> callStack = new Stack<StackTraceElement>();
47
48	/*
49	 * -------------------------------------------------------------------
50	 * Constructors
51	 * -------------------------------------------------------------------
52	 */
53
54	/**
55	 * Can't be instantiated.
56	 */
57	private CallVerificationStack() {
58		// empty
59	}
60
61	/*
62	 * -------------------------------------------------------------------
63	 * Methods
64	 * -------------------------------------------------------------------
65	 */
66
67	/**
68	 * Gets the singleton instance.
69	 *
70	 * @return the singleton instance
71	 */
72	public static CallVerificationStack getInstance() {
73		return _instance;
74	}
75
76	/**
77	 * Pushes the call stack.
78	 */
79	private void pushCallStack() {
80		StackTraceElement[] eles = (new Throwable()).getStackTrace();
81		int i;
82		for (i = 1; i < eles.length; i++) {
83			if (!eles[i].getClassName().equals(this.getClass().getName())) {
84				break;
85			}
86		}
87		this.callStack.push(eles[i]);
88	}
89
90	/**
91	 * Gets the "current" calling class name.
92	 *
93	 * @return the "current" calling class name
94	 */
95	public String getCurrentSourceClass() {
96		return this.callStack.peek().getClassName();
97	}
98
99	/**
100	 * Gets the "current" calling method name.
101	 *
102	 * @return the "current" calling method name
103	 */
104	public String getCurrentSourceMethod() {
105		return this.callStack.peek().getMethodName();
106	}
107
108	/**
109	 * Clear the parameter stack and the call stack.
110	 *
111	 */
112	@Override
113    public void clear() {
114		this.callStack.clear();
115		super.clear();
116	}
117
118	@Override
119    public Object push(Object o) {
120		pushCallStack();
121		return super.push(o);
122	}
123
124	/**
125	 * Pushes a boolean onto the top of this stack.
126	 *
127	 * @param val
128	 *            the value to push
129	 */
130	public void push(boolean val) {
131		this.push(new BaseTypeWrapper(val));
132	}
133
134	/**
135	 * Pushes a char onto the top of this stack.
136	 *
137	 * @param val
138	 *            the value to push
139	 */
140	public void push(char val) {
141		this.push(new BaseTypeWrapper(val));
142	}
143
144	/**
145	 * Pushes a double onto the top of this stack.
146	 *
147	 * @param val
148	 *            the value to push
149	 */
150	public void push(double val) {
151		this.push(new BaseTypeWrapper(val));
152	}
153
154	/**
155	 * Pushes a float onto the top of this stack.
156	 *
157	 * @param val
158	 *            the value to push
159	 */
160	public void push(float val) {
161		this.push(new BaseTypeWrapper(val));
162	}
163
164	/**
165	 * Pushes an int onto the top of this stack.
166	 *
167	 * @param val
168	 *            the value to push
169	 */
170	public void push(int val) {
171		this.push(new BaseTypeWrapper(val));
172	}
173
174	/**
175	 * Pushes a long onto the top of this stack.
176	 *
177	 * @param val
178	 *            the value to push
179	 */
180	public void push(long val) {
181		this.push(new BaseTypeWrapper(val));
182	}
183
184	/**
185	 * Pushes a short onto the top of this stack.
186	 *
187	 * @param val
188	 *            the value to push
189	 */
190	public void push(short val) {
191		this.push(new BaseTypeWrapper(val));
192	}
193
194	/**
195	 * Pop an object.
196	 *
197	 * @return the object
198	 */
199	@Override
200    public Object pop() {
201		this.callStack.pop();
202		return super.pop();
203	}
204
205	/**
206	 * Pop a boolean.
207	 *
208	 * @return the value
209	 */
210	public boolean popBoolean() {
211		BaseTypeWrapper wrapper = (BaseTypeWrapper) this.pop();
212		Boolean value = (Boolean) wrapper.getValue();
213		return value.booleanValue();
214	}
215
216	/**
217	 * Pop a char.
218	 *
219	 * @return the value
220	 */
221	public char popChar() {
222		BaseTypeWrapper wrapper = (BaseTypeWrapper) this.pop();
223		Character value = (Character) wrapper.getValue();
224		return value.charValue();
225	}
226
227	/**
228	 * Pop a double.
229	 *
230	 * @return the value
231	 */
232	public double popDouble() {
233		BaseTypeWrapper wrapper = (BaseTypeWrapper) this.pop();
234		Double value = (Double) wrapper.getValue();
235		return value.doubleValue();
236	}
237
238	/**
239	 * Pop a float.
240	 *
241	 * @return the value
242	 */
243	public float popFloat() {
244		BaseTypeWrapper wrapper = (BaseTypeWrapper) this.pop();
245		Float value = (Float) wrapper.getValue();
246		return value.floatValue();
247	}
248
249	/**
250	 * Pop a int.
251	 *
252	 * @return the value
253	 */
254	public int popInt() {
255		BaseTypeWrapper wrapper = (BaseTypeWrapper) this.pop();
256		Integer value = (Integer) wrapper.getValue();
257		return value.intValue();
258	}
259
260	/**
261	 * Pop a long.
262	 *
263	 * @return the value
264	 */
265	public long popLong() {
266		BaseTypeWrapper wrapper = (BaseTypeWrapper) this.pop();
267		Long value = (Long) wrapper.getValue();
268		return value.longValue();
269	}
270
271	/**
272	 * Pop a short.
273	 *
274	 * @return the value
275	 */
276	public short popShort() {
277		BaseTypeWrapper wrapper = (BaseTypeWrapper) this.pop();
278		Short value = (Short) wrapper.getValue();
279		return value.shortValue();
280	}
281
282	/*
283	 * Wrapper of base types.
284	 */
285	class BaseTypeWrapper {
286
287		// the internal value
288		private Object value;
289
290		/*
291		 * Constructs a wrapper object for the base type <code> boolean </code> .
292		 */
293		public BaseTypeWrapper(boolean val) {
294			this.value = new Boolean(val);
295		}
296
297		/*
298		 * Constructs a wrapper object for the base type <code> c </code> .
299		 */
300		public BaseTypeWrapper(byte val) {
301			this.value = new Byte(val);
302		}
303
304		/*
305		 * Constructs a wrapper object for the base type <code> char </code> .
306		 */
307		public BaseTypeWrapper(char val) {
308			this.value = new Character(val);
309		}
310
311		/*
312		 * Constructs a wrapper object for the base type <code> double </code> .
313		 */
314		public BaseTypeWrapper(double val) {
315			this.value = new Double(val);
316		}
317
318		/*
319		 * Constructs a wrapper object for the base type <code> float </code> .
320		 */
321		public BaseTypeWrapper(float val) {
322			this.value = new Float(val);
323		}
324
325		/*
326		 * Constructs a wrapper object for the base type <code> int </code> .
327		 */
328		public BaseTypeWrapper(int val) {
329			this.value = new Integer(val);
330		}
331
332		/*
333		 * Constructs a wrapper object for the base type <code> long </code> .
334		 */
335		public BaseTypeWrapper(long val) {
336			this.value = new Long(val);
337		}
338
339		/*
340		 * Constructs a wrapper object for the base type <code> short </code> .
341		 */
342		public BaseTypeWrapper(short val) {
343			this.value = new Short(val);
344		}
345
346		/*
347		 * Gets the internal value.
348		 */
349		public Object getValue() {
350			return this.value;
351		}
352	}
353}
354