View Javadoc
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 }