1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.spf4j.test.log;
17
18 import com.google.common.collect.ImmutableList;
19 import java.util.ArrayList;
20 import java.util.Comparator;
21 import java.util.HashMap;
22 import java.util.List;
23 import java.util.Map;
24 import java.util.SortedMap;
25 import java.util.TreeMap;
26 import java.util.function.ToIntFunction;
27 import javax.annotation.Nullable;
28 import javax.annotation.ParametersAreNonnullByDefault;
29 import javax.annotation.concurrent.Immutable;
30 import org.spf4j.log.Level;
31
32
33
34
35 @Immutable
36 @ParametersAreNonnullByDefault
37 final class LogConfigImpl implements LogConfig {
38
39 static final Comparator<String> REV_STR_COMPARATOR = ((Comparator<String>) String::compareTo).reversed();
40
41 private static final int DEFAULT_HANDLER_COUNT = Integer.getInteger("spf4j.test.log.defaultNrOfHandlers", 4);
42
43 private final ImmutableList<LogHandler> rootHandler;
44
45 private final SortedMap<String, List<LogHandler>> logHandlers;
46
47 LogConfigImpl(final ImmutableList<LogHandler> rootHandler, final Map<String, List<LogHandler>> catHandlers) {
48 this.rootHandler = rootHandler;
49 logHandlers = new TreeMap<>(REV_STR_COMPARATOR);
50 logHandlers.putAll(catHandlers);
51 }
52
53 @Override
54 public LogConfigImpl add(final String category, final LogHandler handler,
55 final ToIntFunction<List<LogHandler>> whereTo) {
56 ImmutableList<LogHandler> rh;
57 Map<String, List<LogHandler>> ch;
58 if (category.isEmpty()) {
59 List<LogHandler> existing = rootHandler;
60 List<LogHandler> handlers = new ArrayList<>(existing.size() + 1);
61 handlers.addAll(existing);
62 handlers.add(whereTo.applyAsInt(handlers), handler);
63 rh = ImmutableList.<LogHandler>builder().addAll(handlers).build();
64 ch = logHandlers;
65 } else {
66 rh = rootHandler;
67 ch = new HashMap<>(logHandlers);
68 List<LogHandler> hndlrs = ch.get(category);
69 if (hndlrs == null) {
70 hndlrs = new ArrayList<>(2);
71 ch.put(category, hndlrs);
72 hndlrs.add(handler);
73 } else {
74 List<LogHandler> exHandlers = hndlrs;
75 hndlrs = new ArrayList<>(exHandlers.size() + 1);
76 hndlrs.addAll(exHandlers);
77 hndlrs.add(whereTo.applyAsInt(hndlrs), handler);
78 ch.put(category, hndlrs);
79 }
80 }
81 return new LogConfigImpl(rh, ch);
82 }
83
84
85 @Override
86 public LogConfigImpl remove(final String category, final LogHandler handler) {
87 ImmutableList<LogHandler> rh;
88 Map<String, List<LogHandler>> ch;
89 if (category.isEmpty()) {
90 rh = rootHandler.stream().filter((h) -> h != handler).collect(ImmutableList.toImmutableList());
91 ch = logHandlers;
92 } else {
93 rh = rootHandler;
94 ch = new HashMap<>(logHandlers);
95 List<LogHandler> hndlrs = ch.get(category);
96 if (hndlrs != null) {
97 hndlrs = new ArrayList<>(hndlrs);
98 hndlrs.remove(handler);
99 if (hndlrs.isEmpty()) {
100 ch.remove(category);
101 } else {
102 ch.put(category, hndlrs);
103 }
104 }
105 }
106 return new LogConfigImpl(rh, ch);
107 }
108
109 @Override
110 @Nullable
111 public LogConsumer getLogConsumer(final String category, final Level level) {
112 ArrayList<LogHandler> res = new ArrayList<>(DEFAULT_HANDLER_COUNT);
113 if (category.isEmpty() || logHandlers.isEmpty()) {
114 addAll(level, rootHandler, res);
115 return CompositeLogHandler.from(res);
116 }
117 for (Map.Entry<String, List<LogHandler>> entry : logHandlers.tailMap(category).entrySet()) {
118 String key = entry.getKey();
119 if (category.startsWith(key)) {
120 if (addAll(level, entry.getValue(), res)) {
121 return CompositeLogHandler.from(res);
122 }
123 } else if (key.charAt(0) != category.charAt(0)) {
124 break;
125 }
126 }
127 addAll(level, rootHandler, res);
128 return CompositeLogHandler.from(res);
129 }
130
131 private static boolean addAll(final Level level, final List<LogHandler> from, final List<LogHandler> to) {
132 for (LogHandler handler : from) {
133 LogHandler.Handling handling = handler.handles(level);
134 switch (handling) {
135 case HANDLE_CONSUME:
136 if (!(handler instanceof ConsumeAllLogs)) {
137 to.add(handler);
138 }
139 return true;
140 case HANDLE_PASS:
141 to.add(handler);
142 break;
143 case NONE:
144 break;
145 default:
146 throw new UnsupportedOperationException("Not known " + handling);
147 }
148 }
149 return false;
150 }
151
152 @Override
153 public String toString() {
154 return "LogConfigImpl{" + "rootHandler=" + rootHandler + ", logHandlers=" + logHandlers + '}';
155 }
156
157 }