| 1 | package fr.sii.ogham.core.builder.configuration; | |
| 2 | ||
| 3 | import static fr.sii.ogham.core.util.BuilderUtils.isExpression; | |
| 4 | import static java.util.Optional.empty; | |
| 5 | ||
| 6 | import java.util.ArrayList; | |
| 7 | import java.util.List; | |
| 8 | import java.util.Optional; | |
| 9 | ||
| 10 | import fr.sii.ogham.core.builder.configurer.Configurer; | |
| 11 | import fr.sii.ogham.core.builder.context.BuildContext; | |
| 12 | import fr.sii.ogham.core.fluent.AbstractParent; | |
| 13 | ||
| 14 | /** | |
| 15 | * Helper that allow registration of properties and default value but also | |
| 16 | * registers the value set by the developer. | |
| 17 | * | |
| 18 | * <p> | |
| 19 | * If a value is explicitly set by developer, it means that the value is | |
| 20 | * hard-coded in its own code. This value can't be overridden by a property or | |
| 21 | * default value so the developer value always takes precedence. | |
| 22 | * | |
| 23 | * For example, Ogham could be configured like this: | |
| 24 | * | |
| 25 | * <pre> | |
| 26 | * .port() | |
| 27 | * .properties("mail.smtp.port", "mail.port") | |
| 28 | * .devaultValue(25) | |
| 29 | * </pre> | |
| 30 | * | |
| 31 | * The developer can configure Ogham using a configuration file in the classpath | |
| 32 | * to provide values for local development environment. Example of content of | |
| 33 | * the configuration file: | |
| 34 | * | |
| 35 | * <pre> | |
| 36 | * mail.smtp.port = 557 | |
| 37 | * </pre> | |
| 38 | * | |
| 39 | * The developer may want to test its code and may need to have a different port | |
| 40 | * value in test: | |
| 41 | * | |
| 42 | * <pre> | |
| 43 | * @Test | |
| 44 | * public void testMail() { | |
| 45 | * MessagingBuilder builder = MessagingBuilder.standard(); | |
| 46 | * builder | |
| 47 | * .email().sender(JavaMailBuilder.class) | |
| 48 | * .port(10025) | |
| 49 | * ... | |
| 50 | * </pre> | |
| 51 | * | |
| 52 | * The value {@code 10025} must be the value available in the test regardless of | |
| 53 | * the value of the properties and default value. | |
| 54 | * | |
| 55 | * <p> | |
| 56 | * <strong>NOTE:</strong> This class is for internal use (or extensions for | |
| 57 | * Ogham). The developer that uses Ogham should not see | |
| 58 | * {@link #setValue(Object)} and {@link #getValue()} methods. | |
| 59 | * | |
| 60 | * | |
| 61 | * @author Aurélien Baudet | |
| 62 | * | |
| 63 | * @param <P> | |
| 64 | * the type of the parent | |
| 65 | * @param <V> | |
| 66 | * the type of the value | |
| 67 | */ | |
| 68 | public class ConfigurationValueBuilderHelper<P, V> extends AbstractParent<P> implements ConfigurationValueBuilder<P, V> { | |
| 69 | private final Class<V> valueClass; | |
| 70 | private final BuildContext buildContext; | |
| 71 | private final List<String> properties; | |
| 72 | private V defaultValue; | |
| 73 | private V value; | |
| 74 | private Optional<V> optionalValue; | |
| 75 | ||
| 76 | /** | |
| 77 | * Initializes with the parent builder and the type of the value used for | |
| 78 | * conversion. | |
| 79 | * | |
| 80 | * @param parent | |
| 81 | * the parent builder | |
| 82 | * @param valueClass | |
| 83 | * the type of the value | |
| 84 | * @param buildContext | |
| 85 | * for registering instances and property evaluation | |
| 86 | */ | |
| 87 | public ConfigurationValueBuilderHelper(P parent, Class<V> valueClass, BuildContext buildContext) { | |
| 88 | super(parent); | |
| 89 | this.valueClass = valueClass; | |
| 90 | this.buildContext = buildContext; | |
| 91 | properties = new ArrayList<>(); | |
| 92 | optionalValue = empty(); | |
| 93 | } | |
| 94 | ||
| 95 | @Override | |
| 96 | public ConfigurationValueBuilderHelper<P, V> properties(String... properties) { | |
| 97 | for (String property : properties) { | |
| 98 |
1
1. properties : negated conditional → RUN_ERROR |
if (!isExpression(property)) { |
| 99 | property = "${" + property + "}"; | |
| 100 | } | |
| 101 | this.properties.add(property); | |
| 102 | } | |
| 103 |
1
1. properties : replaced return value with null for fr/sii/ogham/core/builder/configuration/ConfigurationValueBuilderHelper::properties → RUN_ERROR |
return this; |
| 104 | } | |
| 105 | ||
| 106 | @Override | |
| 107 | public ConfigurationValueBuilderHelper<P, V> defaultValue(V value) { | |
| 108 | defaultValue = value; | |
| 109 |
1
1. defaultValue : replaced return value with null for fr/sii/ogham/core/builder/configuration/ConfigurationValueBuilderHelper::defaultValue → RUN_ERROR |
return this; |
| 110 | } | |
| 111 | ||
| 112 | @Override | |
| 113 | public ConfigurationValueBuilderHelper<P, V> defaultValue(MayOverride<V> possibleNewValue) { | |
| 114 | defaultValue = possibleNewValue.override(defaultValue); | |
| 115 |
1
1. defaultValue : replaced return value with null for fr/sii/ogham/core/builder/configuration/ConfigurationValueBuilderHelper::defaultValue → RUN_ERROR |
return this; |
| 116 | } | |
| 117 | ||
| 118 | @Override | |
| 119 | @SuppressWarnings("squid:S3553") | |
| 120 | public ConfigurationValueBuilderHelper<P, V> value(Optional<V> optionalValue) { | |
| 121 |
1
1. value : negated conditional → NO_COVERAGE |
if (optionalValue.isPresent()) { |
| 122 | this.optionalValue = optionalValue; | |
| 123 | } | |
| 124 |
1
1. value : replaced return value with null for fr/sii/ogham/core/builder/configuration/ConfigurationValueBuilderHelper::value → NO_COVERAGE |
return this; |
| 125 | } | |
| 126 | ||
| 127 | /** | |
| 128 | * If a value is explicitly set by developer, it means that the value is | |
| 129 | * hard-coded in its own code. This value can't be overridden by a property | |
| 130 | * or default value so the developer value always takes precedence. | |
| 131 | * | |
| 132 | * For example, Ogham could be configured like this: | |
| 133 | * | |
| 134 | * <pre> | |
| 135 | * .port() | |
| 136 | * .properties("mail.smtp.port", "mail.port") | |
| 137 | * .devaultValue(25) | |
| 138 | * </pre> | |
| 139 | * | |
| 140 | * The developer can configure Ogham using a configuration file in the | |
| 141 | * classpath to provide values for local development environment. Example of | |
| 142 | * content of the configuration file: | |
| 143 | * | |
| 144 | * <pre> | |
| 145 | * mail.smtp.port = 557 | |
| 146 | * </pre> | |
| 147 | * | |
| 148 | * The developer may want to test its code and may need to have a different | |
| 149 | * port value in test: | |
| 150 | * | |
| 151 | * <pre> | |
| 152 | * @Test | |
| 153 | * public void testMail() { | |
| 154 | * MessagingBuilder builder = MessagingBuilder.standard(); | |
| 155 | * builder | |
| 156 | * .email().sender(JavaMailBuilder.class) | |
| 157 | * .port(10025) | |
| 158 | * ... | |
| 159 | * </pre> | |
| 160 | * | |
| 161 | * The value {@code 10025} must be the value available in the test | |
| 162 | * regardless of the value of the properties and default value. | |
| 163 | * | |
| 164 | * <p> | |
| 165 | * <strong>IMPORTANT:</strong> {@link Configurer}s <strong>should | |
| 166 | * not</strong> use this method directly because it prevents the possibility | |
| 167 | * to override the value from external configuration. | |
| 168 | * | |
| 169 | * @param value | |
| 170 | * the value set by the developer in its own code | |
| 171 | */ | |
| 172 | public void setValue(V value) { | |
| 173 | this.value = value; | |
| 174 | } | |
| 175 | ||
| 176 | /** | |
| 177 | * Get the final value. The first non-null value is returned: | |
| 178 | * | |
| 179 | * <ol> | |
| 180 | * <li>If the a non-null value has been set using {@link #setValue(Object)}, | |
| 181 | * this value is returned</li> | |
| 182 | * <li>If an optional value has been set using {@link #value(Optional)}, and | |
| 183 | * {@link Optional#isPresent()} returns true this value is returned</li> | |
| 184 | * <li>If property keys have been registered and one has been evaluated to a | |
| 185 | * non-null value, this value is returned</li> | |
| 186 | * <li>If a default value has been registered, the default value is | |
| 187 | * returned</li> | |
| 188 | * <li>null is returned</li> | |
| 189 | * </ol> | |
| 190 | * | |
| 191 | * @return the value | |
| 192 | */ | |
| 193 | public V getValue() { | |
| 194 |
1
1. getValue : negated conditional → RUN_ERROR |
if (value != null) { |
| 195 |
1
1. getValue : replaced return value with null for fr/sii/ogham/core/builder/configuration/ConfigurationValueBuilderHelper::getValue → RUN_ERROR |
return value; |
| 196 | } | |
| 197 |
1
1. getValue : negated conditional → RUN_ERROR |
if (optionalValue.isPresent()) { |
| 198 |
1
1. getValue : replaced return value with null for fr/sii/ogham/core/builder/configuration/ConfigurationValueBuilderHelper::getValue → NO_COVERAGE |
return optionalValue.get(); |
| 199 | } | |
| 200 | V prop = buildContext.evaluate(properties, valueClass); | |
| 201 |
1
1. getValue : negated conditional → RUN_ERROR |
if (prop != null) { |
| 202 |
1
1. getValue : replaced return value with null for fr/sii/ogham/core/builder/configuration/ConfigurationValueBuilderHelper::getValue → RUN_ERROR |
return prop; |
| 203 | } | |
| 204 |
1
1. getValue : replaced return value with null for fr/sii/ogham/core/builder/configuration/ConfigurationValueBuilderHelper::getValue → RUN_ERROR |
return defaultValue; |
| 205 | } | |
| 206 | ||
| 207 | /** | |
| 208 | * Get the final value. The first non-null value is returned: | |
| 209 | * | |
| 210 | * <ol> | |
| 211 | * <li>If the a non-null value has been set using {@link #setValue(Object)}, | |
| 212 | * this value is returned</li> | |
| 213 | * <li>If an optional value has been set using {@link #value(Optional)}, and | |
| 214 | * {@link Optional#isPresent()} returns true this value is returned</li> | |
| 215 | * <li>If property keys have been registered and one has been evaluated to a | |
| 216 | * non-null value, this value is returned</li> | |
| 217 | * <li>If a default value has been registered, the default value is | |
| 218 | * returned</li> | |
| 219 | * <li>The default value provided as parameter is used</li> | |
| 220 | * </ol> | |
| 221 | * | |
| 222 | * @param defaultValue | |
| 223 | * the default value to use if there isn't a non-null value | |
| 224 | * @return the value | |
| 225 | */ | |
| 226 | public V getValue(V defaultValue) { | |
| 227 | V configuredValue = getValue(); | |
| 228 |
1
1. getValue : negated conditional → RUN_ERROR |
if (configuredValue != null) { |
| 229 |
1
1. getValue : replaced return value with null for fr/sii/ogham/core/builder/configuration/ConfigurationValueBuilderHelper::getValue → RUN_ERROR |
return configuredValue; |
| 230 | } | |
| 231 |
1
1. getValue : replaced return value with null for fr/sii/ogham/core/builder/configuration/ConfigurationValueBuilderHelper::getValue → RUN_ERROR |
return defaultValue; |
| 232 | } | |
| 233 | ||
| 234 | /** | |
| 235 | * Returns true if a value, default value or properties have been set. | |
| 236 | * | |
| 237 | * @return true if there is a value, default value or at least one property | |
| 238 | */ | |
| 239 | public boolean hasValueOrProperties() { | |
| 240 |
4
1. hasValueOrProperties : negated conditional → NO_COVERAGE 2. hasValueOrProperties : negated conditional → NO_COVERAGE 3. hasValueOrProperties : negated conditional → NO_COVERAGE 4. hasValueOrProperties : replaced boolean return with true for fr/sii/ogham/core/builder/configuration/ConfigurationValueBuilderHelper::hasValueOrProperties → NO_COVERAGE |
return value != null || !properties.isEmpty() || defaultValue != null; |
| 241 | } | |
| 242 | ||
| 243 | } | |
Mutations | ||
| 98 |
1.1 |
|
| 103 |
1.1 |
|
| 109 |
1.1 |
|
| 115 |
1.1 |
|
| 121 |
1.1 |
|
| 124 |
1.1 |
|
| 194 |
1.1 |
|
| 195 |
1.1 |
|
| 197 |
1.1 |
|
| 198 |
1.1 |
|
| 201 |
1.1 |
|
| 202 |
1.1 |
|
| 204 |
1.1 |
|
| 228 |
1.1 |
|
| 229 |
1.1 |
|
| 231 |
1.1 |
|
| 240 |
1.1 2.2 3.3 4.4 |