1 /**
2 * Logback: the reliable, fast and flexible logging library for Java.
3 *
4 * Copyright (C) 1999-2006, QOS.ch
5 *
6 * This library is free software, you can redistribute it and/or modify it under
7 * the terms of the GNU Lesser General Public License as published by the Free
8 * Software Foundation.
9 */
10
11 package chapter3.calculator;
12
13 import java.util.Stack;
14
15 import org.xml.sax.Attributes;
16
17 import ch.qos.logback.core.joran.action.Action;
18 import ch.qos.logback.core.joran.spi.InterpretationContext;
19 import ch.qos.logback.core.util.OptionHelper;
20
21
22 /**
23 * ComputationAction2 will print the result of the compuration made by
24 * children elements but only if the compuration itself is named, that is if the
25 * name attribute of the associated computation element is not null. In other
26 * words, anonymous computations will not print their result.
27 *
28 * ComputationAction2 differs from ComputationAction1 in its handling of
29 * instance variables. ComputationAction1 has a simple <Code>nameStr</code>
30 * instance variable. This variable is set when the begin() method is called
31 * and then later used within the end() method.
32 *
33 * This simple approach works properly if the begin() and end()
34 * method of a given action are expected to be called in sequence. However,
35 * there are situations where the begin() method of the same action instance is
36 * invoked multiple times before the matching end() method is invoked.
37 *
38 * When this happens, the second call to begin() overwrites values set by
39 * the first invocation to begin(). The solution is to save parameter values
40 * into a separate stack. The well-formedness of XML will guarantee that a value
41 * saved by one begin() will be consumed only by the matching end() method.
42 *
43 * Note that in the vast majority of cases there is no need to resort to a
44 * separate stack for each variable. The situation of successibe begin()
45 * invocations can only occur if:
46 *
47 * 1) the associated pattern contains a wildcard, i.e. the * character
48 *
49 * and
50 *
51 * 2) the associated element tag can contain itself as a child
52 *
53 * For example, "*/computation" pattern means that computations can contain
54 * other computation elements as children.
55 *
56 * @author Ceki Gülcü
57 */
58 public class ComputationAction2 extends Action {
59 public static String NAME_ATR = "name";
60
61 Stack<String> nameStrStack = new Stack<String>();
62
63
64 public void begin(InterpretationContext ec, String name, Attributes attributes) {
65 String nameStr = attributes.getValue(NAME_ATR);
66 // save nameStr value in a special stack. Note that the value is saved
67 // even if it is empty or null.
68 nameStrStack.push(nameStr);
69 }
70
71 public void end(InterpretationContext ec, String name) {
72 // pop nameStr value from the special stack
73 String nameStr = (String) nameStrStack.pop();
74
75 if (OptionHelper.isEmpty(nameStr)) {
76 // nothing to do
77 } else {
78 Integer i = (Integer) ec.peekObject();
79 System.out.println(
80 "The computation named [" + nameStr + "] resulted in the value " + i);
81 }
82 }
83 }