Open brainbytes42 opened 1 year ago
Hi!
I've created #133 to track your feature request about modification tracking.
Config#copy()
is intended to be a shallow copy, in a similar way to clone()
. A deepCopy()
or deepClone()
would be useful, though. Let's track this here.
For now, you can implement it yourself by calling copy, iterating on the entries and recursively copying sub-configurations, it shouldn't be too long to implement.
I'm still wondering what the right interface is. One possibility is to add these to Config
/**
* Puts a deep copy of the given configuration to the root of this config.
* <p>
* This methods calls {@code deepCopy} on every sub-configuration,
* manually copies lists of known type (including {@code ArrayList}),
* calls {@code clone()} on {@code Cloneable} values, and simply
* copy the reference of other values.
* <p>
* For more control over the deep copy, in particular if you have
* put nested mutable objects into the config, use {@link #putDeepCopy(Function)}.
*/
void putDeepCopy(UnmodifiableConfig configToCopy);
/**
* Puts a deep copy of the given configuration to the root of this config.
* <p>
* This methods calls {@code deepCopy} on every sub-configuration
* and uses the {@code valueCopier} for other values (including lists).
*
* @param valueCopier a function that creates a deep copy of any object
*/
void putDeepCopy(UnmodifiableConfig configToCopy, Function<Object, Object> valueCopier);
But given that many options could be good to have, it may be better to have a dedicated class DeepConfigCopier
.
The Signature doesn't fit the JavaDoc's @return...
(And I'd prefer the described functionality in @return - so that I just get a new Config-Object from an existing one, without too much hassle...)
Ah that's right, I miscopied some code. The design choice here is: how do you choose the type of the new config. For simple configs that maps a HashMap and aren't thread-safe it's trivial, but for ConcurrentConfigs
it's not (for instance, a subConfig
of a SynchronizedConfig
is not the same as a new SynchronizedConfig
).
Thus, doing new MyNewConfig().putDeepCopy(config);
works well.
An alternative would be config.deepCopyTo(MyNewConfig::new);
.
Ah, I see - that makes sense...
From a usability / "discoverability" view, I'd prefer the latter, as I'd then come from an existing object and have all my methods there, with all their documentation / examples. Seems more fluent to me... But maybe that's a personal preference... :-)
hi again,
is there any (simple) way to create a deep copy of a configuration? Then one could compare the original and copied version, if one was changed later on? (
equals
seems to work properly for this case, comparing values and recursively including sub-configurations.)This is slightly related to #118, as I was evaluating workarounds to this and to the question, if the config has been changed (to then manually / optionally save the config with user interaction). (Not only for autosave, but also for changes in config, a listener would be nice.)
But it seems, that in a copy only the 'simple' values are copied; sub-configurations remain linked and will be changed in both places:
Maybe (if this behaviour isn't considered a bug), add
Config.deepCopy(UnmodifiableConfig)
?