2525import java .util .function .BiFunction ;
2626import java .util .function .Function ;
2727
28+ import static java .util .stream .Collectors .toSet ;
29+
2830/**
2931 * An unmodifiable subclass of {@link Properties}.
3032 *<p>
@@ -39,12 +41,43 @@ public final class FrozenProperties extends Properties
3941 /**
4042 * Constructs a {@code FrozenProperties} instance from an existing
4143 * {@link Properties} instance.
44+ *<p>
45+ * The instance will have a defaults list (also frozen) if <var>p</var> has
46+ * defaults that have not been superseded by later settings. Defaults are
47+ * flattened into a single default properties instance, even if <var>p</var>
48+ * had a defaults instance chaining to another or a chain of others.
4249 * @param p the instance whose entries are to be copied
4350 */
4451 public FrozenProperties (Properties p )
4552 {
46- // super(p.size()); // has no @Since but first appears in Java 10
47- super .putAll (p );
53+ super (defaults (p ));
54+ super .putAll (p ); // putAll copies only non-default entries
55+ }
56+
57+ /**
58+ * Constructor used internally to return a frozen instance with only
59+ * <var>p</var>'s defaults (entries with keys in <var>subset</var>).
60+ */
61+ private FrozenProperties (Properties p , Set <String > subset )
62+ {
63+ // super(subset.size()); // has no @Since but first appears in Java 10
64+ for ( String s : subset )
65+ super .put (s , p .get (s ));
66+ }
67+
68+ /**
69+ * Returns a {@code FrozenProperties} instance representing defaults of
70+ * <var>p</var> not superseded by later settings.
71+ * @return FrozenProperties with the defaults, or null if none
72+ */
73+ private static FrozenProperties defaults (Properties p )
74+ {
75+ Set <String > defaultedNames =
76+ p .stringPropertyNames ().stream ().filter (n -> ! p .containsKey (n ))
77+ .collect (toSet ());
78+ if ( defaultedNames .isEmpty () )
79+ return null ;
80+ return new FrozenProperties (p , defaultedNames );
4881 }
4982
5083 @ Override
0 commit comments