Skip to content

Commit 6bd2b01

Browse files
committed
Merge remote-tracking branch 'origin/master' into dependencies
2 parents abf95e5 + 98a6450 commit 6bd2b01

18 files changed

Lines changed: 529 additions & 72 deletions

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
[![Build Status](https://github.com/AuthMe/ConfigMe/actions/workflows/maven_jdk8.yml/badge.svg)](https://github.com/AuthMe/ConfigMe/actions?query=branch%3Amaster)
33
[![Coverage Status](https://coveralls.io/repos/github/AuthMe/ConfigMe/badge.svg?branch=master)](https://coveralls.io/github/AuthMe/ConfigMe?branch=master)
44
[![Javadoc](https://www.javadoc.io/badge/ch.jalu/configme.svg)](https://www.javadoc.io/doc/ch.jalu/configme)
5-
[![MegaLinter](https://github.com/AuthMe/ConfigMe/workflows/MegaLinter/badge.svg?branch=master)](https://github.com/AuthMe/ConfigMe/actions?query=workflow%3AMegaLinter+branch%3Amaster)
5+
[![MegaLinter](https://github.com/AuthMe/ConfigMe/actions/workflows/mega-linter.yml/badge.svg?branch=master)](https://github.com/AuthMe/ConfigMe/actions?query=workflow%3AMegaLinter+branch%3Amaster)
66

77
A simple configuration management library with YAML support out of the box.
88

src/main/java/ch/jalu/configme/SettingsManagerBuilder.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ private SettingsManagerBuilder(@NotNull PropertyResource resource) {
9191
*/
9292
@SafeVarargs
9393
public final @NotNull SettingsManagerBuilder configurationData(
94-
@NotNull Class<? extends SettingsHolder>... classes) {
94+
@NotNull Class<? extends SettingsHolder> @NotNull ... classes) {
9595
this.configurationData = ConfigurationDataBuilder.createConfiguration(classes);
9696
return this;
9797
}

src/main/java/ch/jalu/configme/beanmapper/MapperImpl.java

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -66,9 +66,6 @@
6666
*/
6767
public class MapperImpl implements Mapper {
6868

69-
/** Marker object to signal that null is meant to be used as value. */
70-
public static final Object RETURN_NULL = new Object();
71-
7269
// ---------
7370
// Fields and general configurable methods
7471
// ---------
@@ -125,13 +122,13 @@ public MapperImpl(@NotNull BeanDefinitionService beanDefinitionService,
125122
// Step 1: attempt simple value transformation
126123
Object exportValue = leafValueHandler.toExportValue(value, exportContext);
127124
if (exportValue != null || value == null) {
128-
return unwrapReturnNull(exportValue);
125+
return LeafValueHandler.unwrapReturnNull(exportValue);
129126
}
130127

131128
// Step 2: handle special cases like Collection
132129
exportValue = createExportValueForSpecialTypes(value, exportContext);
133130
if (exportValue != null) {
134-
return unwrapReturnNull(exportValue);
131+
return LeafValueHandler.unwrapReturnNull(exportValue);
135132
}
136133

137134
// Step 3: treat as bean
@@ -159,12 +156,12 @@ public MapperImpl(@NotNull BeanDefinitionService beanDefinitionService,
159156

160157
/**
161158
* Handles values of types which need special handling (such as Optional). Null means the value is not
162-
* a special type and that the export value should be built differently. Use {@link #RETURN_NULL} to
159+
* a special type and that the export value should be built differently. Use {@link LeafValueHandler#RETURN_NULL} to
163160
* signal that null should be used as the export value of the provided value.
164161
*
165162
* @param value the value to convert
166163
* @param exportContext export context
167-
* @return the export value to use or {@link #RETURN_NULL}, or null if not applicable
164+
* @return the export value to use or {@link LeafValueHandler#RETURN_NULL}, or null if not applicable
168165
*/
169166
protected @Nullable Object createExportValueForSpecialTypes(@Nullable Object value,
170167
@NotNull ExportContext exportContext) {
@@ -192,16 +189,12 @@ public MapperImpl(@NotNull BeanDefinitionService beanDefinitionService,
192189
Optional<?> optional = (Optional<?>) value;
193190
return optional
194191
.map(v -> toExportValue(v, exportContext.createChildContext(OPTIONAL_SPECIFIER)))
195-
.orElse(RETURN_NULL);
192+
.orElse(LeafValueHandler.RETURN_NULL);
196193
}
197194

198195
return null;
199196
}
200197

201-
protected static @Nullable Object unwrapReturnNull(@Nullable Object o) {
202-
return o == RETURN_NULL ? null : o;
203-
}
204-
205198
// ---------
206199
// Bean mapping
207200
// ---------

src/main/java/ch/jalu/configme/beanmapper/leafvaluehandler/LeafValueHandler.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@
2020
*/
2121
public interface LeafValueHandler {
2222

23+
/** Marker object to signal that null is meant to be used as value. */
24+
Object RETURN_NULL = new Object();
25+
2326
/**
2427
* Converts the given value to the target type (as defined by the mapping context), if supported. Otherwise,
2528
* null is returned. If a value is returned, its type is guaranteed to match the target type.
@@ -33,11 +36,25 @@ public interface LeafValueHandler {
3336
/**
3437
* Converts the value of a property to a value suitable for exporting. This method converts the opposite
3538
* way of {@link #convert}. Null is returned if this leaf value handler does not support the object's type.
39+
* If the leaf value handler determines that {@code null} should be used as export value, then {@link #RETURN_NULL}
40+
* is returned, which the caller needs to unwrap to {@code null}.
3641
*
3742
* @param value the value to convert
3843
* @param exportContext the export context (usually not needed)
3944
* @return the value suitable for exporting, or null if not applicable
4045
*/
4146
@Nullable Object toExportValue(@Nullable Object value, @NotNull ExportContext exportContext);
4247

48+
/**
49+
* Returns null if the object is {@link #RETURN_NULL}, otherwise the given object. Used to process return values
50+
* from methods like {@link #toExportValue}, where {@code null} means the instance doesn't support the value,
51+
* while {@link #RETURN_NULL} means null should be used as export value.
52+
*
53+
* @param object the object to potentially unwrap
54+
* @param <T> the object type
55+
* @return null, or the provided object
56+
*/
57+
static <T> @Nullable T unwrapReturnNull(@Nullable T object) {
58+
return object == RETURN_NULL ? null : object;
59+
}
4360
}

src/main/java/ch/jalu/configme/beanmapper/leafvaluehandler/LeafValueHandlerImpl.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ public static final class Builder {
144144
* @param typesToAdd the leaf types to add
145145
* @return this builder
146146
*/
147-
public @NotNull Builder addTypes(@NotNull MapperLeafType... typesToAdd) {
147+
public @NotNull Builder addTypes(@NotNull MapperLeafType @NotNull ... typesToAdd) {
148148
leafTypes.addAll(Arrays.asList(typesToAdd));
149149
return this;
150150
}

src/main/java/ch/jalu/configme/beanmapper/leafvaluehandler/MapperLeafType.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ public interface MapperLeafType {
3030
* when {@link ch.jalu.configme.beanmapper.MapperImpl#toExportValue(Object)} is called.
3131
* Returns null if the leaf value handler cannot handle the value.
3232
* <p>
33-
* Return {@link ch.jalu.configme.beanmapper.MapperImpl#RETURN_NULL} to signal that null should be used
33+
* Return {@link LeafValueHandler#RETURN_NULL} to signal that null should be used
3434
* as the export value (returning {@code null} itself means this leaf value handler cannot handle it).
3535
*
3636
* @param value the value to convert to an export value, if possible

src/main/java/ch/jalu/configme/configurationdata/CommentsConfiguration.java

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ public class CommentsConfiguration {
1818

1919
private final @NotNull Map<String, List<String>> comments;
2020

21+
public static final String FOOTER_KEY = "..FOOTER";
22+
2123
/**
2224
* Constructor.
2325
*/
@@ -41,7 +43,7 @@ public CommentsConfiguration(@NotNull Map<String, List<String>> comments) {
4143
* @param path the path to register the comment lines for
4244
* @param commentLines the comment lines to set for the path
4345
*/
44-
public void setComment(@NotNull String path, @NotNull String... commentLines) {
46+
public void setComment(@NotNull String path, @NotNull String @NotNull ... commentLines) {
4547
List<String> replaced = comments.put(path, Collections.unmodifiableList(Arrays.asList(commentLines)));
4648

4749
if (replaced != null) {
@@ -59,4 +61,23 @@ public void setComment(@NotNull String path, @NotNull String... commentLines) {
5961
public @NotNull @UnmodifiableView Map<String, @UnmodifiableView List<String>> getAllComments() {
6062
return Collections.unmodifiableMap(comments);
6163
}
64+
65+
/**
66+
* Adds the given lines as footer comments. They will be written at the end of the configuration file.
67+
*
68+
* @param commentLines the comment lines to add as footer comments
69+
*/
70+
public void setFooterComments(@NotNull String... commentLines) {
71+
setComment(FOOTER_KEY, commentLines);
72+
}
73+
74+
/**
75+
* Adds the given lines as header comments. They will be written at the start of the configuration file.
76+
*
77+
* @param commentLines the comment lines to add as header comments
78+
*/
79+
public void setHeaderComments(@NotNull String... commentLines) {
80+
setComment("", commentLines);
81+
}
82+
6283
}

src/main/java/ch/jalu/configme/configurationdata/ConfigurationDataBuilder.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,8 @@ public ConfigurationDataBuilder(@NotNull PropertyListBuilder propertyListBuilder
5656
* @return collected configuration data
5757
*/
5858
@SafeVarargs
59-
public static @NotNull ConfigurationData createConfiguration(@NotNull Class<? extends SettingsHolder>... classes) {
59+
public static @NotNull ConfigurationData createConfiguration(
60+
@NotNull Class<? extends SettingsHolder> @NotNull ... classes) {
6061
return createConfiguration(Arrays.asList(classes));
6162
}
6263

src/main/java/ch/jalu/configme/migration/version/VersionMigrationService.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ public VersionMigrationService(@NotNull Property<Integer> versionProperty,
6969
* @param migrations all known migrations
7070
*/
7171
public VersionMigrationService(@NotNull Property<Integer> versionProperty,
72-
@NotNull VersionMigration... migrations) {
72+
@NotNull VersionMigration @NotNull ... migrations) {
7373
this(versionProperty, Arrays.asList(migrations));
7474
}
7575

Lines changed: 40 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,19 @@
11
package ch.jalu.configme.properties;
22

3-
import ch.jalu.configme.properties.convertresult.ConvertErrorRecorder;
3+
import ch.jalu.configme.properties.types.MapPropertyType;
44
import ch.jalu.configme.properties.types.PropertyType;
5-
import ch.jalu.configme.resource.PropertyReader;
65
import org.jetbrains.annotations.NotNull;
7-
import org.jetbrains.annotations.Nullable;
86

97
import java.util.Collections;
10-
import java.util.LinkedHashMap;
118
import java.util.Map;
12-
import java.util.Objects;
139

1410
/**
15-
* Property for an immutable map whose keys is of type String and whose values can be configured.
16-
* The map retains the order of the elements.
11+
* Property for a map with String keys and a configurable value type. The map retains the order of the elements.
12+
* Maps produced by this property are guaranteed to never have a null key or null value.
1713
*
1814
* @param <V> the value type of the map
1915
*/
20-
public class MapProperty<V> extends BaseProperty<Map<String, V>> {
21-
22-
private final PropertyType<V> valueType;
16+
public class MapProperty<V> extends TypeBasedProperty<Map<String, V>> {
2317

2418
/**
2519
* Constructor. Builds a {@link MapProperty} with an empty map as default value.
@@ -28,9 +22,7 @@ public class MapProperty<V> extends BaseProperty<Map<String, V>> {
2822
* @param valueType the property type of the values
2923
*/
3024
public MapProperty(@NotNull String path, @NotNull PropertyType<V> valueType) {
31-
super(path, Collections.emptyMap());
32-
Objects.requireNonNull(valueType, "valueType");
33-
this.valueType = valueType;
25+
super(path, new MapPropertyType<>(valueType), Collections.emptyMap());
3426
}
3527

3628
/**
@@ -41,48 +33,46 @@ public MapProperty(@NotNull String path, @NotNull PropertyType<V> valueType) {
4133
* @param defaultValue the default value of the property
4234
*/
4335
public MapProperty(@NotNull String path, @NotNull PropertyType<V> valueType, @NotNull Map<String, V> defaultValue) {
44-
super(path, Collections.unmodifiableMap(defaultValue));
45-
Objects.requireNonNull(valueType, "valueType");
46-
this.valueType = valueType;
36+
super(path, new MapPropertyType<>(valueType), defaultValue);
4737
}
4838

49-
@Override
50-
protected @Nullable Map<String, V> getFromReader(@NotNull PropertyReader reader,
51-
@NotNull ConvertErrorRecorder errorRecorder) {
52-
Object rawObject = reader.getObject(getPath());
53-
54-
if (!(rawObject instanceof Map<?, ?>)) {
55-
return null;
56-
}
57-
58-
Map<?, ?> rawMap = (Map<?, ?>) rawObject;
59-
Map<String, V> map = new LinkedHashMap<>();
60-
61-
for (Map.Entry<?, ?> entry : rawMap.entrySet()) {
62-
String path = entry.getKey().toString();
63-
V value = valueType.convert(entry.getValue(), errorRecorder);
64-
65-
if (value != null) {
66-
map.put(path, value);
67-
}
68-
}
69-
70-
return postProcessMap(map);
39+
/**
40+
* Constructor. Use {@link #withMapType}.
41+
*
42+
* @param mapType the map type
43+
* @param path the path of the property
44+
* @param defaultValue the default value of the property
45+
*/
46+
// Constructor arguments are usually (path, type, defaultValue), but this is not possible here because there
47+
// are other constructors with the same argument order.
48+
protected MapProperty(@NotNull PropertyType<Map<String, V>> mapType, @NotNull String path,
49+
@NotNull Map<String, V> defaultValue) {
50+
super(path, mapType, defaultValue);
7151
}
7252

73-
@Override
74-
public @NotNull Object toExportValue(@NotNull Map<String, V> value) {
75-
Map<String, Object> exportMap = new LinkedHashMap<>();
76-
77-
for (Map.Entry<String, V> entry : value.entrySet()) {
78-
exportMap.put(entry.getKey(), valueType.toExportValue(entry.getValue()));
79-
}
80-
81-
return exportMap;
53+
/**
54+
* Creates a new map property with the given path and type. An empty map is set as default value.
55+
*
56+
* @param path the path of the property
57+
* @param mapType the map type
58+
* @param <V> the type of the values in the map
59+
* @return a new map property
60+
*/
61+
public static <V> MapProperty<V> withMapType(@NotNull String path, @NotNull PropertyType<Map<String, V>> mapType) {
62+
return new MapProperty<>(mapType, path, Collections.emptyMap());
8263
}
8364

84-
/* Allows to modify the map once its fully built based on the values in the property reader. */
85-
protected @NotNull Map<String, V> postProcessMap(@NotNull Map<String, V> constructedMap) {
86-
return Collections.unmodifiableMap(constructedMap);
65+
/**
66+
* Creates a new map property with the given path, type and default value.
67+
*
68+
* @param path the path of the property
69+
* @param mapType the map type
70+
* @param defaultValue the default value of the property
71+
* @param <V> the type of the values in the map
72+
* @return a new map property
73+
*/
74+
public static <V> MapProperty<V> withMapType(@NotNull String path, @NotNull PropertyType<Map<String, V>> mapType,
75+
@NotNull Map<String, V> defaultValue) {
76+
return new MapProperty<>(mapType, path, defaultValue);
8777
}
8878
}

0 commit comments

Comments
 (0)