1
1
package org .codejive .properties ;
2
2
3
+ import static org .codejive .properties .PropertiesParser .unescape ;
4
+
3
5
import java .io .BufferedReader ;
4
6
import java .io .IOException ;
5
7
import java .io .Reader ;
25
27
import java .util .stream .Collectors ;
26
28
import java .util .stream .IntStream ;
27
29
28
- import static org .codejive .properties .PropertiesParser .unescape ;
29
-
30
30
public class Properties extends AbstractMap <String , String > {
31
31
private final LinkedHashMap <String , String > values = new LinkedHashMap <>();
32
32
private final List <PropertiesParser .Token > tokens = new ArrayList <>();
@@ -85,7 +85,7 @@ public String get(Object key) {
85
85
86
86
public String getRaw (String rawKey ) {
87
87
int idx = indexOf (unescape (rawKey ));
88
- if (idx >=0 ) {
88
+ if (idx >= 0 ) {
89
89
return tokens .get (idx + 2 ).getRaw ();
90
90
} else {
91
91
return null ;
@@ -106,8 +106,9 @@ public String put(String key, String value) {
106
106
}
107
107
108
108
/**
109
- * Works like `put()` but uses raw values for keys and values.
110
- * This means these keys and values will not be escaped before being serialized.
109
+ * Works like `put()` but uses raw values for keys and values. This means these keys and values
110
+ * will not be escaped before being serialized.
111
+ *
111
112
* @param rawKey key with which the specified value is to be associated
112
113
* @param rawValue value to be associated with the specified key
113
114
* @return the previous value associated with key, or null if there was no mapping for key.
@@ -155,20 +156,23 @@ public String remove(Object key) {
155
156
}
156
157
157
158
/**
158
- * Gather all the comments directly before the given key
159
- * and return them as a list. The list will only contain
160
- * those lines that immediately follow one another, once
161
- * a non-comment line is encountered gathering will stop.
159
+ * Gather all the comments directly before the given key and return them as a list. The list
160
+ * will only contain those lines that immediately follow one another, once a non-comment line is
161
+ * encountered gathering will stop.
162
+ *
162
163
* @param key The key to look for
163
- * @return A list of comment strings or an empty list if
164
- * no comments lines were found or the key doesn't exist.
164
+ * @return A list of comment strings or an empty list if no comments lines were found or the key
165
+ * doesn't exist.
165
166
*/
166
167
public List <String > getComment (String key ) {
167
168
return getComment (findCommentLines (key ));
168
169
}
169
170
170
171
private List <String > getComment (List <Integer > indices ) {
171
- return Collections .unmodifiableList (indices .stream ().map (idx -> tokens .get (idx ).getText ()).collect (Collectors .toList ()));
172
+ return Collections .unmodifiableList (
173
+ indices .stream ()
174
+ .map (idx -> tokens .get (idx ).getText ())
175
+ .collect (Collectors .toList ()));
172
176
}
173
177
174
178
public List <String > setComment (String key , String ... comments ) {
@@ -205,19 +209,20 @@ public List<String> setComment(String key, List<String> comments) {
205
209
// Add any additional lines (when there are more new lines than old ones)
206
210
int ins = idx ;
207
211
for (int j = i ; j < newcs .size (); j ++) {
208
- tokens .add (ins ++, new PropertiesParser .Token (PropertiesParser .Type .COMMENT , newcs .get (j )));
212
+ tokens .add (
213
+ ins ++, new PropertiesParser .Token (PropertiesParser .Type .COMMENT , newcs .get (j )));
209
214
tokens .add (ins ++, new PropertiesParser .Token (PropertiesParser .Type .WHITESPACE , "\n " ));
210
215
}
211
216
212
217
return oldcs ;
213
218
}
214
219
215
220
/**
216
- * Takes a list of comments and makes sure each of them starts with
217
- * a valid comment character (either '#' or '!'). If only some lines
218
- * have missing comment prefixes it will use the ones that were used
219
- * on previous lines, if not the default will be the value passed as
221
+ * Takes a list of comments and makes sure each of them starts with a valid comment character
222
+ * (either '#' or '!'). If only some lines have missing comment prefixes it will use the ones
223
+ * that were used on previous lines, if not the default will be the value passed as
220
224
* `preferredPrefix`.
225
+ *
221
226
* @param comments list of comment lines
222
227
* @param preferredPrefix the preferred prefix to use
223
228
* @return list of comment lines
@@ -255,11 +260,9 @@ private List<Integer> findCommentLines(String key) {
255
260
}
256
261
257
262
/**
258
- * Returns a list of token indices pointing to all the comment lines
259
- * in a comment block. A list of comments is considered a block when
260
- * they are consecutive lines, without any empty lines in between,
261
- * using the same comment symbol (so they are either all `!` comments
262
- * or all `#` ones).
263
+ * Returns a list of token indices pointing to all the comment lines in a comment block. A list
264
+ * of comments is considered a block when they are consecutive lines, without any empty lines in
265
+ * between, using the same comment symbol (so they are either all `!` comments or all `#` ones).
263
266
*/
264
267
private List <Integer > findCommentLines (int idx ) {
265
268
List <Integer > result = new ArrayList <>();
@@ -280,7 +283,8 @@ private List<Integer> findCommentLines(int idx) {
280
283
}
281
284
282
285
private int indexOf (String key ) {
283
- return tokens .indexOf (new PropertiesParser .Token (PropertiesParser .Type .KEY , escape (key , true ), key ));
286
+ return tokens .indexOf (
287
+ new PropertiesParser .Token (PropertiesParser .Type .KEY , escape (key , true ), key ));
284
288
}
285
289
286
290
private String escape (String raw , boolean forKey ) {
@@ -290,12 +294,12 @@ private String escape(String raw, boolean forKey) {
290
294
raw = raw .replace ("\f " , "\\ f" );
291
295
if (forKey ) {
292
296
raw = raw .replace (" " , "\\ " );
293
- } else {
294
- if (raw .charAt (raw .length () - 1 ) == ' ' ) {
295
- raw = raw .substring (0 , raw .length () - 1 ) + "\\ " ;
296
- }
297
297
}
298
- raw = replace (raw , "[^\\ x{0000}-\\ x{00FF}]" , m -> "\\ \\ u" + Integer .toString (m .group (0 ).charAt (0 ), 16 ));
298
+ raw =
299
+ replace (
300
+ raw ,
301
+ "[^\\ x{0000}-\\ x{00FF}]" ,
302
+ m -> "\\ \\ u" + Integer .toString (m .group (0 ).charAt (0 ), 16 ));
299
303
return raw ;
300
304
}
301
305
@@ -314,6 +318,16 @@ private static String replace(String input, Pattern regex, Function<Matcher, Str
314
318
return resultString .toString ();
315
319
}
316
320
321
+ public java .util .Properties asJUProperties () {
322
+ return asJUProperties (null );
323
+ }
324
+
325
+ public java .util .Properties asJUProperties (java .util .Properties defaults ) {
326
+ java .util .Properties p = new java .util .Properties (defaults );
327
+ p .putAll (this );
328
+ return p ;
329
+ }
330
+
317
331
public void load (Path file ) throws IOException {
318
332
try (Reader br = Files .newBufferedReader (file )) {
319
333
load (br );
@@ -326,8 +340,7 @@ public void load(Reader reader) throws IOException {
326
340
reader instanceof BufferedReader
327
341
? (BufferedReader ) reader
328
342
: new BufferedReader (reader );
329
- List <PropertiesParser .Token > ts = PropertiesParser .tokens (br )
330
- .collect (Collectors .toList ());
343
+ List <PropertiesParser .Token > ts = PropertiesParser .tokens (br ).collect (Collectors .toList ());
331
344
tokens .addAll (ts );
332
345
String key = null ;
333
346
for (PropertiesParser .Token token : tokens ) {
0 commit comments