001/**
002 * Logback: the reliable, generic, fast and flexible logging framework.
003 * Copyright (C) 1999-2015, QOS.ch. All rights reserved.
004 *
005 * This program and the accompanying materials are dual-licensed under
006 * either the terms of the Eclipse Public License v1.0 as published by
007 * the Eclipse Foundation
008 *
009 *   or (per the licensee's choosing)
010 *
011 * under the terms of the GNU Lesser General Public License version 2.1
012 * as published by the Free Software Foundation.
013 */
014package ch.qos.logback.core.joran.spi;
015
016import java.util.Map;
017import java.util.Stack;
018
019import ch.qos.logback.core.Context;
020import ch.qos.logback.core.joran.action.Action;
021import ch.qos.logback.core.model.Model;
022import ch.qos.logback.core.spi.ContextAwareBase;
023import ch.qos.logback.core.spi.PropertyContainer;
024import ch.qos.logback.core.spi.ScanException;
025import ch.qos.logback.core.util.OptionHelper;
026
027/**
028 * 
029 * An InterpretationContext contains the contextual state of a Joran parsing
030 * session. {@link Action} objects depend on this context to exchange and store
031 * information.
032 * 
033 * @author Ceki Gülcü
034 */
035public class SaxEventInterpretationContext extends ContextAwareBase implements PropertyContainer {
036    // Stack<Object> xobjectStack;
037    Stack<Model> modelStack;
038    // Stack<ImplicitActionDataBase> implicitActionDataStack;
039
040    // Map<String, Object> objectMap;
041    // Map<String, String> propertiesMap;
042    // Map<String, String> importMap;
043
044//      final HashMap<Model, List<String>> dependenciesMap = new HashMap<>();
045//      final List<String> startedDependencies = new ArrayList<>();
046
047    SaxEventInterpreter saxEventInterpreter;
048//      DefaultNestedComponentRegistry defaultNestedComponentRegistry = new DefaultNestedComponentRegistry();
049//      private BeanDescriptionCache beanDescriptionCache;
050
051    public SaxEventInterpretationContext(Context context, SaxEventInterpreter saxEventInterpreter) {
052        this.context = context;
053        this.saxEventInterpreter = saxEventInterpreter;
054        // this.objectStack = new Stack<>();
055        this.modelStack = new Stack<>();
056        // this.implicitActionDataStack = new Stack<>();
057
058        // objectMap = new HashMap<>(5);
059        // propertiesMap = new HashMap<>(5);
060        // importMap = new HashMap<>(5);
061    }
062
063//      public BeanDescriptionCache getBeanDescriptionCache() {
064//              if (beanDescriptionCache == null) {
065//                      beanDescriptionCache = new BeanDescriptionCache(getContext());
066//              }
067//              return beanDescriptionCache;
068//      }
069//
070//      public DefaultNestedComponentRegistry getDefaultNestedComponentRegistry() {
071//              return defaultNestedComponentRegistry;
072//      }
073
074//      public Map<String, String> getCopyOfPropertyMap() {
075//              return new HashMap<String, String>(propertiesMap);
076//      }
077//
078//      void setPropertiesMap(Map<String, String> propertiesMap) {
079//              this.propertiesMap = propertiesMap;
080//      }
081
082//      public HashMap<Model, List<String>> getDependenciesMap() {
083//              return dependenciesMap;
084//      }
085
086//      public void addDependency(Model model, String ref) {
087//              List<String> refList = dependenciesMap.get(model);
088//              if(refList == null) {
089//                      refList = new ArrayList<>();
090//              }
091//              refList.add(ref);
092//              dependenciesMap.put(model, refList);
093//      }
094
095//      public List<String> getDependencies(Model model) {
096//              return dependenciesMap.get(model);
097//      }
098
099//      public String getLineNumber() {
100//              if(saxEventInterpreter == null) {
101//                      return "NA";
102//              }
103//              Locator locator = saxEventInterpreter.getLocator();
104//
105//              if (locator != null) {
106//                      return Integer.toString(locator.getLineNumber());
107//              } else {
108//                      return "NA";
109//              }
110//      }
111
112    public SaxEventInterpreter getSaxEventInterpreter() {
113        return saxEventInterpreter;
114    }
115
116//      public Stack<Object> getObjectStack() {
117//              return objectStack;
118//      }
119
120//      /**
121//       * @deprecated Use {@link isObjectStackEmpty isObjectStackEmpty()} method
122//       *             instead
123//       * @return
124//       */
125//      public boolean isEmpty() {
126//              return isObjectStackEmpty();
127//      }
128
129//      /**
130//       * 
131//       * @return whether the objectStack is empty or not
132//       */
133//      public boolean isObjectStackEmpty() {
134//              return objectStack.isEmpty();
135//      }
136//
137//      public Object peekObject() {
138//              return objectStack.peek();
139//      }
140//
141//      public void pushObject(Object o) {
142//              objectStack.push(o);
143//      }
144//
145//      public Object popObject() {
146//              return objectStack.pop();
147//      }
148
149    /**
150     * actionDataStack contains ActionData instances We use a stack of ActionData
151     * objects in order to support nested elements which are handled by the same
152     * NestedComplexPropertyIA instance. We push a ActionData instance in the
153     * isApplicable method (if the action is applicable) and pop it in the end()
154     * method. The XML well-formedness property will guarantee that a push will
155     * eventually be followed by a corresponding pop.
156     */
157//      public Stack<ImplicitActionDataBase> getImplcitActionDataStack() {
158//              return implicitActionDataStack;
159//      }
160//
161    /**
162     * Return the Model at the top of the model stack, may return null.
163     * 
164     * @return
165     */
166    public Model peekModel() {
167        if(modelStack.isEmpty()) {
168            return null;
169        }
170        return modelStack.peek();
171    }
172
173    public void pushModel(Model m) {
174        modelStack.push(m);
175    }
176
177    public boolean isModelStackEmpty() {
178        return modelStack.isEmpty();
179    }
180
181    public Model popModel() {
182        return modelStack.pop();
183    }
184
185    public Stack<Model> getCopyOfModelStack() {
186        Stack<Model> copy = new Stack<>();
187        copy.addAll(modelStack);
188        return copy;
189    }
190
191//      public Object getObject(int i) {
192//              return objectStack.get(i);
193//      }
194
195//      public Map<String, Object> getObjectMap() {
196//              return objectMap;
197//      }
198
199//      /**
200//       * Add a property to the properties of this execution context. If the property
201//       * exists already, it is overwritten.
202//       */
203//      public void addSubstitutionProperty(String key, String value) {
204//              if (key == null || value == null) {
205//                      return;
206//              }
207//              // values with leading or trailing spaces are bad. We remove them now.
208//              value = value.trim();
209//              propertiesMap.put(key, value);
210//      }
211
212//      public void addSubstitutionProperties(Properties props) {
213//              if (props == null) {
214//                      return;
215//              }
216//              for (Object keyObject : props.keySet()) {
217//                      String key = (String) keyObject;
218//                      String val = props.getProperty(key);
219//                      addSubstitutionProperty(key, val);
220//              }
221//      }
222
223    /**
224     * If a key is found in propertiesMap then return it. Otherwise, delegate to the
225     * context.
226     */
227    public String getProperty(String key) {
228        return context.getProperty(key);
229    }
230
231    @Override
232    public Map<String, String> getCopyOfPropertyMap() {
233        return null;
234    }
235
236    public String subst(String value) {
237        if (value == null) {
238            return null;
239        }
240
241        try {
242            return OptionHelper.substVars(value, this, context);
243        } catch (ScanException | IllegalArgumentException e) {
244            addError("Problem while parsing [" + value + "]", e);
245            return value;
246        }
247    }
248
249//      public void markStartOfNamedDependency(String name) {
250//              startedDependencies.add(name);
251//      }
252//      public boolean isNamedDependencyStarted(String name) {
253//              return startedDependencies.contains(name);
254//      }
255
256//      /**
257//       * Add an import to the importMao
258//       * @param stem the class to import
259//       * @param fqcn the fully qualified name of the class
260//       * 
261//       * @since 1.3
262//       */
263//      public void addImport(String stem, String fqcn) {
264//              importMap.put(stem, fqcn);
265//      }
266//
267//      /**
268//       * Given a stem, get the fully qualified name of the class corresponding to the stem. 
269//       * For unknown stems, returns the stem as is. If stem is null, null is returned.
270//       * 
271//       * @param stem may be null
272//       * @return fully qualified name of the class corresponding to the stem. For unknown stems, returns the stem as is. 
273//       * If stem is null, null is returned.
274//       * @since 1.3
275//       */
276//      public String getImport(String stem) {
277//              if(stem == null)
278//                      return null;
279//              
280//              String result = importMap.get(stem);
281//              if(result == null)
282//                      return stem;
283//              else 
284//                      return result;
285//      }
286
287}