17
17
package org .apache .logging .log4j .core .config .builder .impl ;
18
18
19
19
import java .util .ArrayList ;
20
+ import java .util .Collections ;
20
21
import java .util .LinkedHashMap ;
21
22
import java .util .List ;
22
23
import java .util .Map ;
24
+ import java .util .Objects ;
23
25
import java .util .Optional ;
24
-
25
26
import org .apache .logging .log4j .Level ;
26
27
import org .apache .logging .log4j .core .config .Configuration ;
27
28
import org .apache .logging .log4j .core .config .builder .api .Component ;
28
29
import org .apache .logging .log4j .core .config .builder .api .ComponentBuilder ;
29
30
import org .apache .logging .log4j .core .config .builder .api .ConfigurationBuilder ;
31
+ import org .jspecify .annotations .NonNull ;
32
+ import org .jspecify .annotations .Nullable ;
30
33
31
34
/**
32
35
* Generic component that captures attributes and Components in preparation for assembling the Appender's
37
40
class DefaultComponentBuilder <T extends ComponentBuilder <T >, CB extends ConfigurationBuilder <? extends Configuration >>
38
41
implements ComponentBuilder <T > {
39
42
40
- private final CB builder ;
41
- private final String type ;
43
+ private final @ NonNull CB builder ;
44
+ private final @ Nullable String name ;
45
+ private final @ NonNull String type ;
46
+ private final @ Nullable String value ;
42
47
private final Map <String , String > attributes = new LinkedHashMap <>();
43
48
private final List <Component > components = new ArrayList <>();
44
- private final String name ;
45
- private final String value ;
46
49
47
- public DefaultComponentBuilder (final CB builder , final String type ) {
50
+ /**
51
+ * Constructs a component builder with the given configuration builder and type with {@code null} name and value.
52
+ * @param builder the configuration builder
53
+ * @param type the type (plugin-type) of the component being built
54
+ * @throws NullPointerException if either {@code builder} or {@code type} argument is null
55
+ */
56
+ public DefaultComponentBuilder (final @ NonNull CB builder , final @ NonNull String type ) {
48
57
this (builder , null , type , null );
49
58
}
50
59
51
- public DefaultComponentBuilder (final CB builder , final String name , final String type ) {
60
+ /**
61
+ * Constructs a component builder with the given configuration builder, name, type, and {@code null} value.
62
+ * @param builder the configuration builder
63
+ * @param name the component name
64
+ * @param type the type (plugin-type) of the component being built
65
+ * @throws NullPointerException if either {@code builder} or {@code type} argument is null
66
+ */
67
+ public DefaultComponentBuilder (final @ NonNull CB builder , final @ Nullable String name , final @ NonNull String type ) {
52
68
this (builder , name , type , null );
53
69
}
54
70
55
- public DefaultComponentBuilder (final CB builder , final String name , final String type , final String value ) {
56
- this .type = type ;
57
- this .builder = builder ;
71
+ /**
72
+ * Constructs a component builder with the given configuration builder, name, type, and value.
73
+ * @param builder the configuration builder
74
+ * @param name the component name
75
+ * @param type the type (plugin-type) of the component being built
76
+ * @param value the component value
77
+ * @throws NullPointerException if either {@code builder} or {@code type} argument is null
78
+ */
79
+ public DefaultComponentBuilder (
80
+ final @ NonNull CB builder ,
81
+ final @ Nullable String name ,
82
+ final @ NonNull String type ,
83
+ final @ Nullable String value ) {
84
+ super ();
85
+ this .builder = Objects .requireNonNull (builder , "The 'builder' argument must not be null." );
86
+ this .type = Objects .requireNonNull (type , "The 'type' argument must not be null." );
58
87
this .name = name ;
59
88
this .value = value ;
60
89
}
61
90
62
91
/** {@inheritDoc} */
63
92
@ Override
64
- public T addAttribute (final String key , final boolean value ) {
93
+ public @ NonNull T addAttribute (final @ NonNull String key , final boolean value ) {
65
94
return put (key , Boolean .toString (value ));
66
95
}
67
96
68
97
/** {@inheritDoc} */
69
98
@ Override
70
- public T addAttribute (final String key , final Enum <?> value ) {
71
- return put (key , Optional . ofNullable (value ). map ( Enum :: name ). orElse ( null ));
99
+ public @ NonNull T addAttribute (final @ NonNull String key , final int value ) {
100
+ return put (key , Integer . toString (value ));
72
101
}
73
102
74
103
/** {@inheritDoc} */
75
104
@ Override
76
- public T addAttribute (final String key , final int value ) {
77
- return put (key , Integer . toString (value ));
105
+ public @ NonNull T addAttribute (final @ NonNull String key , final @ Nullable Enum <?> value ) {
106
+ return put (key , Optional . ofNullable (value ). map ( Enum :: name ). orElse ( null ));
78
107
}
79
108
80
109
/** {@inheritDoc} */
81
110
@ Override
82
- public T addAttribute (final String key , final Level level ) {
111
+ public @ NonNull T addAttribute (final @ NonNull String key , final @ Nullable Level level ) {
83
112
return put (key , Optional .ofNullable (level ).map (Level ::toString ).orElse (null ));
84
113
}
85
114
86
115
/** {@inheritDoc} */
87
116
@ Override
88
- public T addAttribute (final String key , final Object value ) {
117
+ public @ NonNull T addAttribute (final @ NonNull String key , final @ Nullable Object value ) {
89
118
return put (key , Optional .ofNullable (value ).map (Object ::toString ).orElse (null ));
90
119
}
91
120
92
121
/** {@inheritDoc} */
93
122
@ Override
94
- public T addAttribute (final String key , final String value ) {
123
+ public @ NonNull T addAttribute (final @ NonNull String key , final @ Nullable String value ) {
95
124
return put (key , value );
96
125
}
97
126
127
+ /**
128
+ * Gets the value of the component attribute with the given key.
129
+ *
130
+ * @param key the key
131
+ * @return the attribute value or {@code null} if not found
132
+ */
133
+ protected @ Nullable String getAttribute (final @ NonNull String key ) {
134
+
135
+ Objects .requireNonNull (key , "The 'key' argument must not be null." );
136
+
137
+ return this .attributes .get (key );
138
+ }
139
+
140
+ /**
141
+ * Gets the map of key/value component attributes.
142
+ * <p>
143
+ * The result map is guaranteed to have both non-{@code null} keys and values.
144
+ * </p>
145
+ * @return an <i>immutable</i> map of the key/value attributes
146
+ */
147
+ protected @ NonNull Map <String , String > getAttributes () {
148
+ return Collections .unmodifiableMap (attributes );
149
+ }
150
+
98
151
/** {@inheritDoc} */
99
152
@ Override
100
- @ SuppressWarnings ( "unchecked" )
101
- public T addComponent ( final ComponentBuilder <?> builder ) {
153
+ public @ NonNull T addComponent ( final @ NonNull ComponentBuilder <?> builder ) {
154
+ Objects . requireNonNull ( builder , "The ' builder' argument must not be null." );
102
155
components .add (builder .build ());
103
- return ( T ) this ;
156
+ return self () ;
104
157
}
105
158
106
159
/** {@inheritDoc} */
107
160
@ Override
108
- public Component build () {
161
+ public @ NonNull Component build () {
109
162
final Component component = new Component (type , name , value );
110
163
component .getAttributes ().putAll (attributes );
111
164
component .getComponents ().addAll (components );
@@ -114,13 +167,13 @@ public Component build() {
114
167
115
168
/** {@inheritDoc} */
116
169
@ Override
117
- public CB getBuilder () {
170
+ public @ NonNull CB getBuilder () {
118
171
return builder ;
119
172
}
120
173
121
174
/** {@inheritDoc} */
122
175
@ Override
123
- public String getName () {
176
+ public @ Nullable String getName () {
124
177
return name ;
125
178
}
126
179
@@ -133,16 +186,40 @@ public String getName() {
133
186
* @param key the key
134
187
* @param value the value
135
188
* @return this builder (for chaining)
189
+ * @throws NullPointerException if the given {@code key} argument is {@code null}
136
190
*/
137
- @ SuppressWarnings ("unchecked" )
138
- protected T put (final String key , final String value ) {
191
+ private @ NonNull T put (final @ NonNull String key , final @ Nullable String value ) {
192
+
193
+ Objects .requireNonNull (key , "The 'key' argument must not be null." );
139
194
140
195
if (value != null ) {
141
196
attributes .put (key , value );
142
197
} else {
143
198
attributes .remove (key );
144
199
}
145
200
201
+ return self ();
202
+ }
203
+
204
+ /**
205
+ * Clears the internal state removing all configured attributes and components.
206
+ * <p>
207
+ * This method is primarily intended to be used in testing.
208
+ * </p>
209
+ */
210
+ protected void clear () {
211
+ synchronized (this ) {
212
+ attributes .clear ();
213
+ components .clear ();
214
+ }
215
+ }
216
+
217
+ /**
218
+ * Returns an instance of this builder cast to its generic type.
219
+ * @return this builder
220
+ */
221
+ @ SuppressWarnings ("unchecked" )
222
+ protected @ NonNull T self () {
146
223
return (T ) this ;
147
224
}
148
225
}
0 commit comments