11package org .codejive .properties ;
22
3+ import static org .codejive .properties .PropertiesParser .unescape ;
4+
35import java .io .BufferedReader ;
46import java .io .IOException ;
57import java .io .Reader ;
2527import java .util .stream .Collectors ;
2628import java .util .stream .IntStream ;
2729
28- import static org .codejive .properties .PropertiesParser .unescape ;
29-
3030public class Properties extends AbstractMap <String , String > {
3131 private final LinkedHashMap <String , String > values = new LinkedHashMap <>();
3232 private final List <PropertiesParser .Token > tokens = new ArrayList <>();
@@ -85,7 +85,7 @@ public String get(Object key) {
8585
8686 public String getRaw (String rawKey ) {
8787 int idx = indexOf (unescape (rawKey ));
88- if (idx >=0 ) {
88+ if (idx >= 0 ) {
8989 return tokens .get (idx + 2 ).getRaw ();
9090 } else {
9191 return null ;
@@ -106,8 +106,9 @@ public String put(String key, String value) {
106106 }
107107
108108 /**
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+ *
111112 * @param rawKey key with which the specified value is to be associated
112113 * @param rawValue value to be associated with the specified key
113114 * @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) {
155156 }
156157
157158 /**
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+ *
162163 * @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.
165166 */
166167 public List <String > getComment (String key ) {
167168 return getComment (findCommentLines (key ));
168169 }
169170
170171 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 ()));
172176 }
173177
174178 public List <String > setComment (String key , String ... comments ) {
@@ -205,19 +209,20 @@ public List<String> setComment(String key, List<String> comments) {
205209 // Add any additional lines (when there are more new lines than old ones)
206210 int ins = idx ;
207211 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 )));
209214 tokens .add (ins ++, new PropertiesParser .Token (PropertiesParser .Type .WHITESPACE , "\n " ));
210215 }
211216
212217 return oldcs ;
213218 }
214219
215220 /**
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
220224 * `preferredPrefix`.
225+ *
221226 * @param comments list of comment lines
222227 * @param preferredPrefix the preferred prefix to use
223228 * @return list of comment lines
@@ -255,11 +260,9 @@ private List<Integer> findCommentLines(String key) {
255260 }
256261
257262 /**
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).
263266 */
264267 private List <Integer > findCommentLines (int idx ) {
265268 List <Integer > result = new ArrayList <>();
@@ -280,7 +283,8 @@ private List<Integer> findCommentLines(int idx) {
280283 }
281284
282285 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 ));
284288 }
285289
286290 private String escape (String raw , boolean forKey ) {
@@ -290,12 +294,12 @@ private String escape(String raw, boolean forKey) {
290294 raw = raw .replace ("\f " , "\\ f" );
291295 if (forKey ) {
292296 raw = raw .replace (" " , "\\ " );
293- } else {
294- if (raw .charAt (raw .length () - 1 ) == ' ' ) {
295- raw = raw .substring (0 , raw .length () - 1 ) + "\\ " ;
296- }
297297 }
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 ));
299303 return raw ;
300304 }
301305
@@ -314,6 +318,16 @@ private static String replace(String input, Pattern regex, Function<Matcher, Str
314318 return resultString .toString ();
315319 }
316320
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+
317331 public void load (Path file ) throws IOException {
318332 try (Reader br = Files .newBufferedReader (file )) {
319333 load (br );
@@ -326,8 +340,7 @@ public void load(Reader reader) throws IOException {
326340 reader instanceof BufferedReader
327341 ? (BufferedReader ) reader
328342 : 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 ());
331344 tokens .addAll (ts );
332345 String key = null ;
333346 for (PropertiesParser .Token token : tokens ) {
0 commit comments