Closed tfabien closed 10 years ago
This is very, very good issue/question/example.
Props
macro resolving (i.e. replacement of ${}
values) works statically and not dynamically. Which means that replacement happens based on whats available during the parsing time. When you call getValue()
with profiles, parsing is already done and macros are already resolved, so passed profile is not used for resolving macros.
When you change the active profile in the code, all resolved macros are reset, so macros get resolved on next lookup and things are working.
Thats why we have setUseActiveProfilesWhenResolvingMacros
flag, you can define should we use the active profile (which is also known prior to actual parsing) or to use current profile of a property when resolving macros.
To make example work, you would need to add:
data.path<foo>=${root}/data
(or to use profiles). This property is now defined in foo
profile, and it will be able resolve ${root}
macro from the same profile (if exist).
Why resolving macros on parsing time? One of the starting ideas was to have all property values set, so we don't need to resolve macros on every getValue()
. This would also make iteration of properties easier. We thought that profiles would be set once on start and not much during the runtime.
That being said... I must admit this is a bit... nah, not pretty. I had a problem figuring whats wrong with your example, because it's logic was simple :) Let me try to make macros resolving dynamic. It should not change the way how existing code works... much :) If we go dynamic then setUseActiveProfilesWhenResolvingMacros
would have no meaning, which is also fine :) I will let you know here the results.
Ok, seems logic looking at the code of the two methods in fact. I was just a bit confused by the results, and glad I made a unit test that revealed that side-effect of changing the way jodd-props was called in my own code :) I'll try to dig into it this too if I get some free coding-time and see if I can make a pull request
Meanwhile, maybe add a warning to the documentation, as user might expect a totally different behaviour, or even be totally unaware of the unexpected result
I made changes, in the separated branch: https://github.com/oblac/jodd/tree/props-dynamic-macros
And I like it this way much better, it is much more obvious what is the value! Like I've said, your logic above is quite strait and simple, and that is fine; moreover, one fuzzy configuration rule is out. The change was not big after all.
Need to check with other users would have a problem with this change, but afaik they will not be affected.
Very nice, just tested it and it's working great :-)
As a complementary suggestion, would it be possible, with dynamic macro resolving, to have a macro specifying/overriding the profile to be used when resolving? eg:
key1=DEFAULT
key1<foo>=FOO
# Expecting:
# - "FOO" if "foo" profile is active
# - "DEFAULT" otherwise
key2=${key1}
# Macro specifying a profile for resolve
# Expecting:
# - "FOO" whatever the active profile is
key3=${key1<foo>}
# A more complex example
# Expecting:
# - "FOO" if "foo" profile is active
# - "FOOBAR" if "bar" profile is active
# - "DEFAULT" otherwise
key4=${key1}
key4<bar>=${key1<foo>}BAR
# Copy operator specifying a resolve profile
[group1]
key=DEFAULT
key<foo>=FOO
[group2]
#: Expanded as 'group2.key=${group1.key<foo>}'
<= group1<foo>
I can see a few use-cases for this, although maybe a bit too specific :)
Why not :) Done it: https://github.com/oblac/jodd/commit/c0759bc250e69552321f15050deeb564af1f0598
Enjoy! And thank you for the excellent examples!
In fact, your latest addon with profiles in keys (${key1<foo>}
) is important for backward compatibility - if someone wants to get the previous behavior, he can just set the profile in the macro name!
Great, because this gives me a green light to merge this branch to master.
Great news then :-) Also, very impressed by your reactivity, it's a real pleasure, and I'll probably use jodd more and more on my next projects, keep up :-)
Thanx for updating the above example with COPY operator, I missed that part in initial fix :)
Meh, I am just trying to give the best code, so to help people who find it useful. Feel free to try and play with Jodd :) I have started working on documentation, so soon its gonna be updated for changes in upcoming 3.6
Following documentation example properties.
Resolving macros using active profiles works as expected when calling
setActiveProfile()
and then callinggetValue(String key)
:But resolution is incorrect when using
getValue(String key, String... profiles)
directly:Note: Present both in 3.5.2 and 3.6-RC1