8000 task: better document property mapping by shawkins · Pull Request #40873 · keycloak/keycloak · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

task: better document property mapping #40873

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@
*
* <p>This interceptor must execute after the {@link io.smallrye.config.ExpressionConfigSourceInterceptor} so that expressions
* are properly resolved before executing this interceptor.
*
* <p>The {@link NestedPropertyMappingInterceptor} catches property mappings that need to be performed within expressions.
*
* <p>
* The reason for the used priority is to always execute the interceptor before default Application Config Source interceptors
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,23 @@ public class PropertyMapper<T> {
this.namedProperty = namedProperty;
}

/**
* This is the heart of the property mapping logic. In preference order we are looking for:
* <ul>
* <li>the "from" value (the property is directly specified)
* <li>the mapFrom (the property is inferred from another value)
* <li>the default
* </ul>
*
* <p>
* If we did not find a value, we simply move on in the interceptor chain.
* <p>
* If we found a value, it needs to be transformed via {@link #transformValue(String, ConfigValue, ConfigSourceInterceptorContext, boolean)}. If the mapFrom value is being used or the name matches "to", the
* either the parentMapper (from {@link PropertyMapper.Builder} mapFrom methods), or the mapper (from {@link PropertyMapper.Builder} transformer methods) is applied.
* <p>
* Finally the returned {@link ConfigValue} is made to match what was requested - with the name, value, rawValue, and ordinal set appropriately.
* <p>
*/
Comment on lines +102 to +118
Copy link
Contributor
@mabartos mabartos Jul 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@shawkins Thanks for creating this PR!

Suggested change
/**
* This is the heart of the property mapping logic. In preference order we are looking for:
* <ul>
* <li>the "from" value (the property is directly specified)
* <li>the mapFrom (the property is inferred from another value)
* <li>the default
* </ul>
*
* <p>
* If we did not find a value, we simply move on in the interceptor chain.
* <p>
* If we found a value, it needs to be transformed via {@link #transformValue(String, ConfigValue, ConfigSourceInterceptorContext, boolean)}. If the mapFrom value is being used or the name matches "to", the
* either the parentMapper (from {@link PropertyMapper.Builder} mapFrom methods), or the mapper (from {@link PropertyMapper.Builder} transformer methods) is applied.
* <p>
* Finally the returned {@link ConfigValue} is made to match what was requested - with the name, value, rawValue, and ordinal set appropriately.
* <p>
*/
/**
* This is the heart of the property mapping logic. In the first step, we need to find the value of the property and then transform it into a form of our needs.
* <p>
*
* <b>1. Find value</b>
* <p>
* In preference order we are looking for:
* <pre>
* [ {@link #from} ] ---> [ {@link #mapFrom} ] ---> [ default ] ---> [try other external]
* (explicit) (derived) (fallback)
* </pre>
* <ul>
* <li>the {@link #from} value (the property is directly specified)
* <li>the {@link #mapFrom} value (the property is inferred from another value)
* <li>the default
* <li>If we did not find a value, we simply move on in the interceptor chain.
* </ul>
* <p>
*
* <b>2. Transform found value</b>
* <p>
* If we found a value for the attribute name, it needs to be transformed via {@link #transformValue} method. How to transform it?
* <pre>
* [ name = {@link #from} ? ] ---> [ name = {@link #to} ? ] ---> [ value from parent ? ]
* | y | y | y
* | | |
* value transform(value) parent.transform(value)
* </pre>
* <ul>
* <li>If the name matches {@link #to}, we use the {@link #mapper} from the {@link PropertyMapper.Builder#transformer} method.
* <li>If we found the value on the parent side ({@link #mapFrom}), we use the {@link #parentMapper} specified either via {@link PropertyMapper.Builder#mapFrom(Option, ValueMapper)} method or parent's {@link PropertyMapper.Builder#transformer} method.
* </ul>
* <p>
* Finally the returned {@link ConfigValue} is made to match what was requested - with the name, value, rawValue, and ordinal set appropriately.
*/

I took it a little bit further to provide at least some illustration of the process to make it more understandable.

Here how it looks like in my IDE with all these formatting:

image

@shawkins WDYT? And please check if the info is valid.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, but I'd say that the transformValue logic would be better described as:

if name == from || value from parent then apply applicable mapper

Alternatively it might be better to just refer to that method here and add some docs there.

ConfigValue getConfigValue(String name, ConfigSourceInterceptorContext context) {
String from = getFrom();

Expand Down Expand Up @@ -354,8 +371,7 @@ public Builder<T> to(String to) {
}

/**
* NOTE: This transformer will not apply to the mapFrom value. When using
* {@link #mapFrom} you generally need a transformer specifically for the parent
* When using {@link #mapFrom} you generally need a transformer specifically for the parent
* value, see {@link #mapFrom(Option, BiFunction)}
* <p>
* The value passed into the transformer may be null if the property has no value set, and no default
Expand All @@ -364,6 +380,12 @@ public Builder<T> transformer(BiFunction<String, ConfigSourceInterceptorContext,
return transformer((name, value, context) -> mapper.apply(value, context));
}

/**
* When using {@link #mapFrom} you generally need a transformer specifically for the parent
* value, see {@link #mapFrom(Option, BiFunction)}
* <p>
* The value passed into the transformer may be null if the property has no value set, and no default
*/
public Builder<T> transformer(ValueMapper mapper) {
this.mapper = mapper;
return this;
Expand Down
Loading
0