1 /**
2  * Logback: the reliable, generic, fast and flexible logging framework.
3  * Copyright (C) 1999-2015, QOS.ch. All rights reserved.
4  *
5  * This program and the accompanying materials are dual-licensed under
6  * either the terms of the Eclipse Public License v1.0 as published by
7  * the Eclipse Foundation
8  *
9  *   or (per the licensee's choosing)
10  *
11  * under the terms of the GNU Lesser General Public License version 2.1
12  * as published by the Free Software Foundation.
13  */

14 package ch.qos.logback.core.joran.action;
15
16 import java.util.Stack;
17
18 import ch.qos.logback.core.joran.spi.ElementPath;
19
20 import org.xml.sax.Attributes;
21
22 import ch.qos.logback.core.joran.spi.InterpretationContext;
23 import ch.qos.logback.core.joran.util.PropertySetter;
24 import ch.qos.logback.core.joran.util.beans.BeanDescriptionCache;
25 import ch.qos.logback.core.util.AggregationType;
26
27 /**
28  * This action is responsible for tying together a parent object with one of its
29  * <em>simple</em> properties specified as an element but for which there is
30  * no explicit rule.
31  *
32  * @author Ceki G&uuml;lc&uuml;
33  */

34 public class NestedBasicPropertyIA extends ImplicitAction {
35
36     // We use a stack of IADataForBasicProperty objects in order to
37     // support nested elements which are handled by the same NestedBasicPropertyIA instance.
38     // We push a IADataForBasicProperty instance in the isApplicable method (if the
39     // action is applicable) and pop it in the end() method.
40     // The XML well-formedness property will guarantee that a push will eventually
41     // be followed by the corresponding pop.
42     Stack<IADataForBasicProperty> actionDataStack = new Stack<IADataForBasicProperty>();
43
44     private final BeanDescriptionCache beanDescriptionCache;
45
46     public NestedBasicPropertyIA(BeanDescriptionCache beanDescriptionCache) {
47         this.beanDescriptionCache = beanDescriptionCache;
48     }
49
50     public boolean isApplicable(ElementPath elementPath, Attributes attributes, InterpretationContext ec) {
51         // System.out.println("in NestedSimplePropertyIA.isApplicable [" + pattern +
52         // "]");
53         String nestedElementTagName = elementPath.peekLast();
54
55         // no point in attempting if there is no parent object
56         if (ec.isEmpty()) {
57             return false;
58         }
59
60         Object o = ec.peekObject();
61         PropertySetter parentBean = new PropertySetter(beanDescriptionCache, o);
62         parentBean.setContext(context);
63
64         AggregationType aggregationType = parentBean.computeAggregationType(nestedElementTagName);
65
66         switch (aggregationType) {
67         case NOT_FOUND:
68         case AS_COMPLEX_PROPERTY:
69         case AS_COMPLEX_PROPERTY_COLLECTION:
70             return false;
71
72         case AS_BASIC_PROPERTY:
73         case AS_BASIC_PROPERTY_COLLECTION:
74             IADataForBasicProperty ad = new IADataForBasicProperty(parentBean, aggregationType, nestedElementTagName);
75             actionDataStack.push(ad);
76             // addInfo("NestedSimplePropertyIA deemed applicable [" + pattern + "]");
77             return true;
78         default:
79             addError("PropertySetter.canContainComponent returned " + aggregationType);
80             return false;
81         }
82     }
83
84     public void begin(InterpretationContext ec, String localName, Attributes attributes) {
85         // NOP
86     }
87
88     public void body(InterpretationContext ec, String body) {
89
90         String finalBody = ec.subst(body);
91         // get the action data object pushed in isApplicable() method call
92         IADataForBasicProperty actionData = (IADataForBasicProperty) actionDataStack.peek();
93         switch (actionData.aggregationType) {
94         case AS_BASIC_PROPERTY:
95             actionData.parentBean.setProperty(actionData.propertyName, finalBody);
96             break;
97         case AS_BASIC_PROPERTY_COLLECTION:
98             actionData.parentBean.addBasicProperty(actionData.propertyName, finalBody);
99             break;
100         default:
101             addError("Unexpected aggregationType " + actionData.aggregationType);
102         }
103     }
104
105     public void end(InterpretationContext ec, String tagName) {
106         // pop the action data object pushed in isApplicable() method call
107         actionDataStack.pop();
108     }
109 }
110