Skip to content

Commit

Permalink
Added mapName and mapValue methods to ParameterStream
Browse files Browse the repository at this point in the history
  • Loading branch information
robtimus committed Oct 28, 2023
1 parent d575d9a commit 0a1295e
Show file tree
Hide file tree
Showing 2 changed files with 249 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.UnaryOperator;
import java.util.stream.BaseStream;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
Expand Down Expand Up @@ -75,6 +76,34 @@ public <R> Stream<R> map(BiFunction<? super String, ? super String, ? extends R>
return stream.map(Parameter.function(mapper));
}

/**
* Returns a stream consisting of the results of applying the given function to the parameter names of this stream. The values remain unchanged.
* <p>
* This is an intermediate operation.
*
* @param mapper A function to apply to each parameter name.
* @return The new stream.
* @throws NullPointerException If the given mapper is {@code null}.
* @see Stream#map(Function)
*/
public ParameterStream mapName(Function<? super String, String> mapper) {
return new ParameterStream(stream.map(Parameter.nameFunction(mapper)));
}

/**
* Returns a stream consisting of the results of applying the given function to the parameter values of this stream. The names remain unchanged.
* <p>
* This is an intermediate operation.
*
* @param mapper A function to apply to each parameter value.
* @return The new stream.
* @throws NullPointerException If the given mapper is {@code null}.
* @see Stream#map(Function)
*/
public ParameterStream mapValue(Function<? super String, String> mapper) {
return new ParameterStream(stream.map(Parameter.valueFunction(mapper)));
}

/**
* Returns a stream consisting of the distinct parameters (according to {@link String#equals(Object)} for both the name and value) of this stream.
* <p>
Expand Down Expand Up @@ -528,6 +557,28 @@ private void update(String name, String value) {
this.value = Objects.requireNonNull(value);
}

private Parameter withName(String name) {
if (isShared) {
this.name = Objects.requireNonNull(name);
return this;
}
if (this.name.equals(name)) {
return this;
}
return nonSharedParameter(name, value);
}

private Parameter withValue(String value) {
if (isShared) {
this.value = Objects.requireNonNull(value);
return this;
}
if (this.value.equals(value)) {
return this;
}
return nonSharedParameter(name, value);
}

// equals and hashCode only exist for distinct() support
// These will never be called before update will be called, and therefore a name and value will be available

Expand Down Expand Up @@ -559,6 +610,16 @@ private static <R> Function<Parameter, R> function(BiFunction<? super String, ?
return parameter -> function.apply(parameter.name, parameter.value);
}

private static UnaryOperator<Parameter> nameFunction(Function<? super String, String> function) {
Objects.requireNonNull(function);
return parameter -> parameter.withName(function.apply(parameter.name));
}

private static UnaryOperator<Parameter> valueFunction(Function<? super String, String> function) {
Objects.requireNonNull(function);
return parameter -> parameter.withValue(function.apply(parameter.value));
}

private static Consumer<Parameter> consumer(BiConsumer<? super String, ? super String> consumer) {
Objects.requireNonNull(consumer);
return parameter -> consumer.accept(parameter.name, parameter.value);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
import java.util.function.BiFunction;
import java.util.function.BiPredicate;
import java.util.function.Function;
import java.util.function.UnaryOperator;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.junit.jupiter.api.Nested;
Expand Down Expand Up @@ -111,6 +112,188 @@ void testMap() {
verifyNoMoreInteractions(mapper);
}

@Nested
class MapName {

@Test
void testWithSharedParameters() {
UnaryOperator<String> mapper = mockUnaryOperator();
when(mapper.apply(anyString())).thenAnswer(i -> i.getArgument(0, String.class).toUpperCase());

Stream<Parameter> stream = createStream()
.mapName(mapper)
.map(Parameter::new);

verify(mapper, never()).apply(anyString());

List<Parameter> expected = parameters()
.stream()
.map(p -> new Parameter(p.name.toUpperCase(), p.value))
.collect(Collectors.toList());

List<Parameter> parameters = stream.collect(Collectors.toList());

assertEquals(expected, parameters);

parameters().stream()
.map(Parameter::name)
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()))
.entrySet()
.stream()
.forEach(entry -> verify(mapper, times(entry.getValue().intValue())).apply(entry.getKey()));
verifyNoMoreInteractions(mapper);
}

@Test
void testWithNonSharedParameters() {
UnaryOperator<String> mapper = mockUnaryOperator();
when(mapper.apply(anyString())).thenAnswer(i -> i.getArgument(0, String.class).toUpperCase());

Stream<Parameter> stream = createStream()
.distinct()
.mapName(mapper)
.map(Parameter::new);

verify(mapper, never()).apply(anyString());

List<Parameter> expected = parameters()
.stream()
.distinct()
.map(p -> new Parameter(p.name.toUpperCase(), p.value))
.collect(Collectors.toList());

List<Parameter> parameters = stream.collect(Collectors.toList());

assertEquals(expected, parameters);

parameters().stream()
.distinct()
.map(Parameter::name)
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()))
.entrySet()
.stream()
.forEach(entry -> verify(mapper, times(entry.getValue().intValue())).apply(entry.getKey()));
verifyNoMoreInteractions(mapper);
}

@Test
void testWithNoChanges() {
UnaryOperator<String> mapper = mockUnaryOperator();
when(mapper.apply(anyString())).thenAnswer(i -> i.getArgument(0));

Stream<Parameter> stream = createStream()
.mapName(mapper)
.map(Parameter::new);

verify(mapper, never()).apply(anyString());

List<Parameter> expected = parameters();

List<Parameter> parameters = stream.collect(Collectors.toList());

assertEquals(expected, parameters);

parameters().stream()
.map(Parameter::name)
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()))
.entrySet()
.stream()
.forEach(entry -> verify(mapper, times(entry.getValue().intValue())).apply(entry.getKey()));
verifyNoMoreInteractions(mapper);
}
}

@Nested
class MapValue {

@Test
void testWithSharedParameters() {
UnaryOperator<String> mapper = mockUnaryOperator();
when(mapper.apply(anyString())).thenAnswer(i -> i.getArgument(0, String.class).toUpperCase());

Stream<Parameter> stream = createStream()
.mapValue(mapper)
.map(Parameter::new);

verify(mapper, never()).apply(anyString());

List<Parameter> expected = parameters()
.stream()
.map(p -> new Parameter(p.name, p.value.toUpperCase()))
.collect(Collectors.toList());

List<Parameter> parameters = stream.collect(Collectors.toList());

assertEquals(expected, parameters);

parameters().stream()
.map(Parameter::value)
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()))
.entrySet()
.stream()
.forEach(entry -> verify(mapper, times(entry.getValue().intValue())).apply(entry.getKey()));
verifyNoMoreInteractions(mapper);
}

@Test
void testWithNonSharedParameters() {
UnaryOperator<String> mapper = mockUnaryOperator();
when(mapper.apply(anyString())).thenAnswer(i -> i.getArgument(0, String.class).toUpperCase());

Stream<Parameter> stream = createStream()
.distinct()
.mapValue(mapper)
.map(Parameter::new);

verify(mapper, never()).apply(anyString());

List<Parameter> expected = parameters()
.stream()
.distinct()
.map(p -> new Parameter(p.name, p.value.toUpperCase()))
.collect(Collectors.toList());

List<Parameter> parameters = stream.collect(Collectors.toList());

assertEquals(expected, parameters);

parameters().stream()
.distinct()
.map(Parameter::value)
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()))
.entrySet()
.stream()
.forEach(entry -> verify(mapper, times(entry.getValue().intValue())).apply(entry.getKey()));
verifyNoMoreInteractions(mapper);
}

@Test
void testWithNoChanges() {
UnaryOperator<String> mapper = mockUnaryOperator();
when(mapper.apply(anyString())).thenAnswer(i -> i.getArgument(0));

Stream<Parameter> stream = createStream()
.mapValue(mapper)
.map(Parameter::new);

verify(mapper, never()).apply(anyString());

List<Parameter> expected = parameters();

List<Parameter> parameters = stream.collect(Collectors.toList());

assertEquals(expected, parameters);

parameters().stream()
.map(Parameter::value)
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()))
.entrySet()
.stream()
.forEach(entry -> verify(mapper, times(entry.getValue().intValue())).apply(entry.getKey()));
verifyNoMoreInteractions(mapper);
}
}

@Test
void testDistinct() {
Stream<Parameter> stream = createStream()
Expand Down Expand Up @@ -789,6 +972,11 @@ private <R> BiFunction<String, String, R> mockFunction() {
return mock(BiFunction.class);
}

@SuppressWarnings("unchecked")
private UnaryOperator<String> mockUnaryOperator() {
return mock(UnaryOperator.class);
}

@SuppressWarnings("unchecked")
private BiConsumer<String, String> mockConsumer() {
return mock(BiConsumer.class);
Expand Down

0 comments on commit 0a1295e

Please sign in to comment.