001package org.slf4j.helpers;
002
003import java.util.ArrayDeque;
004import java.util.Deque;
005import java.util.HashMap;
006import java.util.Map;
007
008
009/**
010 * A simple implementation of ThreadLocal backed Map containing values of type 
011 * Deque<String>.
012 * 
013 * @author Ceki Guuml;c&uuml;
014 * @since 2.0.0
015 */
016public class ThreadLocalMapOfStacks {
017
018    // BEWARE: Keys or values placed in a ThreadLocal should not be of a type/class
019    // not included in the JDK. See also https://jira.qos.ch/browse/LOGBACK-450
020
021    final ThreadLocal<Map<String, Deque<String>>> tlMapOfStacks = new ThreadLocal<>();
022
023    public void pushByKey(String key, String value) {
024        if (key == null)
025            return;
026
027        Map<String, Deque<String>> map = tlMapOfStacks.get();
028
029        if (map == null) {
030            map = new HashMap<>();
031            tlMapOfStacks.set(map);
032        }
033
034        Deque<String> deque = map.get(key);
035        if (deque == null) {
036            deque = new ArrayDeque<>();
037        }
038        deque.push(value);
039        map.put(key, deque);
040    }
041
042    public String popByKey(String key) {
043        if (key == null)
044            return null;
045
046        Map<String, Deque<String>> map = tlMapOfStacks.get();
047        if (map == null)
048            return null;
049        Deque<String> deque = map.get(key);
050        if (deque == null)
051            return null;
052        return deque.pop();
053    }
054
055    public Deque<String> getCopyOfDequeByKey(String key) {
056        if (key == null)
057            return null;
058
059        Map<String, Deque<String>> map = tlMapOfStacks.get();
060        if (map == null)
061            return null;
062        Deque<String> deque = map.get(key);
063        if (deque == null)
064            return null;
065
066        return new ArrayDeque<String>(deque);
067    }
068    
069    /**
070     * Clear the deque(stack) referenced by 'key'. 
071     * 
072     * @param key identifies the  stack
073     * 
074     * @since 2.0.0
075     */
076    public void clearDequeByKey(String key) {
077        if (key == null)
078            return;
079
080        Map<String, Deque<String>> map = tlMapOfStacks.get();
081        if (map == null)
082            return;
083        Deque<String> deque = map.get(key);
084        if (deque == null)
085            return;
086        deque.clear();
087    }
088
089}