Skip to content

Commit

Permalink
hints: Add non-inheritable representation hints.
Browse files Browse the repository at this point in the history
This finishes off the representation hint system, so fixes #149
  • Loading branch information
zml2008 committed Oct 4, 2020
1 parent aacef64 commit effc391
Show file tree
Hide file tree
Showing 3 changed files with 139 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -637,7 +637,7 @@ public <V> N setHint(final RepresentationHint<V> hint, final @Nullable V value)
return (V) value;
}
final @Nullable A parent = this.parent;
if (parent != null) {
if (parent != null && hint.isInheritable()) {
return parent.getHint(hint);
} else {
return hint.getDefaultValue();
Expand Down
124 changes: 114 additions & 10 deletions core/src/main/java/org/spongepowered/configurate/RepresentationHint.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,22 +32,44 @@
@AutoValue
public abstract class RepresentationHint<V> {

public static final RepresentationHint<Integer> INDENT = of("indent", Integer.class);

/**
* Create a new basic representation hint.
*
* <p>The created hint will be inheritable and have no default
* value set.</p>
*
* @param identifier hint identifier
* @param valueType type of value the hint will hold
* @param <V> value type
* @return a new hint
*/
public static <V> RepresentationHint<V> of(final String identifier, final Class<V> valueType) {
return new AutoValue_RepresentationHint<>(identifier, TypeToken.get(valueType), null);
return RepresentationHint.<V>builder().setIdentifier(identifier).setValueType(valueType).build();
}

/**
* Create a new basic representation hint.
*
* <p>The created hint will be inheritable and have no default
* value set.</p>
*
* @param identifier hint identifier
* @param valueType type of value the hint will hold
* @param <V> value type
* @return a new hint
*/
public static <V> RepresentationHint<V> of(final String identifier, final TypeToken<V> valueType) {
return new AutoValue_RepresentationHint<>(identifier, valueType, null);
}

public static <V> RepresentationHint<V> of(final String identifier, final Class<V> valueType, final V defaultValue) {
return new AutoValue_RepresentationHint<>(identifier, TypeToken.get(valueType), defaultValue);
return RepresentationHint.<V>builder().setIdentifier(identifier).setValueType(valueType).build();
}

public static <V> RepresentationHint<V> of(final String identifier, final TypeToken<V> valueType, final V defaultValue) {
return new AutoValue_RepresentationHint<>(identifier, valueType, defaultValue);
/**
* Create a builder for a new hint.
*
* @param <V> value type
* @return a new builder
*/
public static <V> Builder<V> builder() {
return new AutoValue_RepresentationHint.Builder<>();
}

RepresentationHint() { }
Expand All @@ -74,4 +96,86 @@ public static <V> RepresentationHint<V> of(final String identifier, final TypeTo
*/
public abstract @Nullable V getDefaultValue();

/**
* Get whether or not this hint can draw its value from parent nodes.
*
* @return if inheritable
*/
public abstract boolean isInheritable();

/**
* A builder for {@link RepresentationHint}s.
*
* @param <V> value type
*/
@AutoValue.Builder
public abstract static class Builder<V> {

Builder() {
this.setInheritable(true);
}

/**
* Set the identifier to refer to this hint.
*
* @param identifier hint identifier
* @return this builder
*/
public abstract Builder<V> setIdentifier(String identifier);

/**
* Set the type used for this node's value.
*
* <p>Raw types are forbidden.</p>
*
* @param valueType the value type
* @return this builder
*/
public final Builder<V> setValueType(final Class<V> valueType) {
return setValueType(TypeToken.get(valueType));
}

/**
* Set the type used for this node's value.
*
* <p>Raw types are forbidden.</p>
*
* @param valueType the value type
* @return this builder
*/
public abstract Builder<V> setValueType(TypeToken<V> valueType);

/**
* Set the default value when this hint is not present in the hierarchy.
*
* <p>This defaults to {@code null}.</p>
*
* @param defaultValue Default value
* @return this builder
*/
public abstract Builder<V> setDefaultValue(@Nullable V defaultValue);

/**
* Set whether or not the hint can be inherited.
*
* <p>Defaults to {@code true}.</p>
*
* @param inheritable if inheritable
* @return this builder
* @see #isInheritable()
*/
public abstract Builder<V> setInheritable(boolean inheritable);

/**
* Create a new hint from the provided options.
*
* <p>The {@code identifier} and {@code valueType} must have been set to
* build a complete hint.</p>
*
* @return a new representation hint
*/
public abstract RepresentationHint<V> build();

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,18 @@ void testNullOutListValue() {
*/
private static final RepresentationHint<Boolean> IS_EVIL = RepresentationHint.of("evil", Boolean.class);

/**
* A representation hint for indentation
*/
public static final RepresentationHint<Integer> INDENT = RepresentationHint.of("indent", Integer.class);

public static final RepresentationHint<String> NAME =
RepresentationHint.<String>builder()
.setIdentifier("name")
.setValueType(String.class)
.setInheritable(false)
.build();

@Test
void testHintsReadWrite() {
final ConfigurationNode node = BasicConfigurationNode.root();
Expand Down Expand Up @@ -355,6 +367,15 @@ void testGetHintInherited() {
assertEquals(false, root.getHint(IS_EVIL));
}

@Test
void testNonInheritableHints() {
final ConfigurationNode root = BasicConfigurationNode.root();
root.setHint(NAME, "secondary");

final ConfigurationNode child = root.getNode("other");
assertNull(child.getHint(NAME));
}

@Test
void testHintsCopied() {
final ConfigurationNode original = BasicConfigurationNode.root();
Expand All @@ -375,16 +396,16 @@ void testHintsMerged() {
.setHint(IS_EVIL, true);
final ConfigurationNode mergeTarget = BasicConfigurationNode.root()
.setValue('o')
.setHint(RepresentationHint.INDENT, 34);
.setHint(INDENT, 34);

mergeTarget.mergeValuesFrom(hintHolder);

assertEquals(34, mergeTarget.getHint(RepresentationHint.INDENT));
assertEquals(34, mergeTarget.getHint(INDENT));
assertEquals(true, mergeTarget.getHint(IS_EVIL));
}

@Test
void testCollectToMap() throws ObjectMappingException {
void testCollectToMap() {
final ConfigurationNode target = ImmutableMap.of("one", 3,
"two", 28,
"test", 14).entrySet().stream()
Expand Down

0 comments on commit effc391

Please sign in to comment.