-
Notifications
You must be signed in to change notification settings - Fork 217
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This change implements a function of 'fn:replace', which maps to the Java "String::replace" method. Signed-off-by: Jens Reimann <jreimann@redhat.com>
- Loading branch information
Showing
5 changed files
with
278 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
191 changes: 191 additions & 0 deletions
191
...src/main/java/org/eclipse/ditto/internal/models/placeholders/PipelineFunctionReplace.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,191 @@ | ||
/* | ||
* Copyright (c) 2021 Contributors to the Eclipse Foundation | ||
* | ||
* See the NOTICE file(s) distributed with this work for additional | ||
* information regarding copyright ownership. | ||
* | ||
* This program and the accompanying materials are made available under the | ||
* terms of the Eclipse Public License 2.0 which is available at | ||
* http://www.eclipse.org/legal/epl-2.0 | ||
* | ||
* SPDX-License-Identifier: EPL-2.0 | ||
*/ | ||
package org.eclipse.ditto.internal.models.placeholders; | ||
|
||
import javax.annotation.concurrent.Immutable; | ||
import java.util.Arrays; | ||
import java.util.List; | ||
|
||
import static org.eclipse.ditto.base.model.common.ConditionChecker.checkNotNull; | ||
|
||
/** | ||
* Provides the {@code fn:replace('from', 'to')} function implementation. | ||
*/ | ||
@Immutable | ||
final class PipelineFunctionReplace implements PipelineFunction { | ||
|
||
private static final String FUNCTION_NAME = "replace"; | ||
|
||
@Override | ||
public String getName() { | ||
return FUNCTION_NAME; | ||
} | ||
|
||
@Override | ||
public Signature getSignature() { | ||
return ReplaceFunctionSignature.INSTANCE; | ||
} | ||
|
||
@Override | ||
public PipelineElement apply(final PipelineElement value, final String paramsIncludingParentheses, | ||
final ExpressionResolver expressionResolver) { | ||
|
||
final Parameters parameters = parseAndResolve(paramsIncludingParentheses, expressionResolver); | ||
|
||
return value.map(str -> str.replace(parameters.getFrom(), parameters.getTo())); | ||
} | ||
|
||
private PipelineFunctionReplace.Parameters parseAndResolve(final String paramsIncludingParentheses, | ||
final ExpressionResolver expressionResolver) { | ||
|
||
final List<PipelineElement> parameterElements = | ||
PipelineFunctionParameterResolverFactory.forDoubleOrTripleStringOrPlaceholderParameter() | ||
.apply(paramsIncludingParentheses, expressionResolver, this); | ||
|
||
final PipelineFunctionReplace.ParametersBuilder parametersBuilder = new PipelineFunctionReplace.ParametersBuilder(); | ||
|
||
final PipelineElement fromParamElement = parameterElements.get(0); | ||
final String fromParam = fromParamElement.toOptional().orElse(""); | ||
parametersBuilder.withFrom(fromParam); | ||
|
||
final PipelineElement toParamElement = parameterElements.get(1); | ||
final String toParam = toParamElement.toOptional().orElseThrow(() -> | ||
PlaceholderFunctionSignatureInvalidException.newBuilder(paramsIncludingParentheses, this) | ||
.build()); | ||
parametersBuilder.withTo(toParam); | ||
|
||
return parametersBuilder.build(); | ||
} | ||
|
||
/** | ||
* Describes the signature of the {@code replace('from', 'to')} function. | ||
*/ | ||
private static final class ReplaceFunctionSignature implements Signature { | ||
|
||
private static final ReplaceFunctionSignature INSTANCE = new ReplaceFunctionSignature(); | ||
|
||
private final ParameterDefinition<String> fromStringDescription; | ||
private final ParameterDefinition<String> toStringDescription; | ||
|
||
private ReplaceFunctionSignature() { | ||
fromStringDescription = new FromStringParam(); | ||
toStringDescription = new ToStringParam(); | ||
} | ||
|
||
@Override | ||
public List<ParameterDefinition<?>> getParameterDefinitions() { | ||
return Arrays.asList(fromStringDescription, toStringDescription); | ||
} | ||
|
||
@Override | ||
public String toString() { | ||
return renderSignature(); | ||
} | ||
|
||
} | ||
|
||
/** | ||
* Describes the from param of the {@code replace('from', 'to')} function. | ||
*/ | ||
private static final class FromStringParam implements ParameterDefinition<String> { | ||
|
||
private FromStringParam() { | ||
} | ||
|
||
@Override | ||
public String getName() { | ||
return "from"; | ||
} | ||
|
||
@Override | ||
public Class<String> getType() { | ||
return String.class; | ||
} | ||
|
||
@Override | ||
public String getDescription() { | ||
return "Specifies the string to search for and replace"; | ||
} | ||
|
||
} | ||
|
||
/** | ||
* Describes the to param of the {@code replace('from', 'to')} function. | ||
*/ | ||
private static final class ToStringParam implements ParameterDefinition<String> { | ||
|
||
private ToStringParam() { | ||
} | ||
|
||
@Override | ||
public String getName() { | ||
return "to"; | ||
} | ||
|
||
@Override | ||
public Class<String> getType() { | ||
return String.class; | ||
} | ||
|
||
@Override | ||
public String getDescription() { | ||
return "Specifies the replace string to be inserted for all matching 'from' strings"; | ||
} | ||
|
||
} | ||
|
||
|
||
@Immutable | ||
private static final class Parameters { | ||
private final String from; | ||
private final String to; | ||
|
||
private Parameters( | ||
final String from, | ||
final String to) { | ||
this.from = checkNotNull(from, "from"); | ||
this.to = checkNotNull(to, "to"); | ||
} | ||
|
||
private String getFrom() { | ||
return from; | ||
} | ||
|
||
private String getTo() { | ||
return to; | ||
} | ||
|
||
} | ||
|
||
private static final class ParametersBuilder { | ||
private String from; | ||
private String to; | ||
|
||
PipelineFunctionReplace.ParametersBuilder withFrom(final String from) { | ||
this.from = from; | ||
return this; | ||
} | ||
|
||
PipelineFunctionReplace.ParametersBuilder withTo(final String to) { | ||
this.to = to; | ||
return this; | ||
} | ||
|
||
PipelineFunctionReplace.Parameters build() { | ||
return new PipelineFunctionReplace.Parameters(from, to); | ||
} | ||
|
||
} | ||
|
||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
82 changes: 82 additions & 0 deletions
82
...test/java/org/eclipse/ditto/internal/models/placeholders/PipelineFunctionReplaceTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
/* | ||
* Copyright (c) 2021 Contributors to the Eclipse Foundation | ||
* | ||
* See the NOTICE file(s) distributed with this work for additional | ||
* information regarding copyright ownership. | ||
* | ||
* This program and the accompanying materials are made available under the | ||
* terms of the Eclipse Public License 2.0 which is available at | ||
* http://www.eclipse.org/legal/epl-2.0 | ||
* | ||
* SPDX-License-Identifier: EPL-2.0 | ||
*/ | ||
package org.eclipse.ditto.internal.models.placeholders; | ||
|
||
import org.junit.After; | ||
import org.junit.Test; | ||
import org.junit.runner.RunWith; | ||
import org.mockito.Mock; | ||
import org.mockito.junit.MockitoJUnitRunner; | ||
|
||
import static org.assertj.core.api.Assertions.assertThat; | ||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType; | ||
import static org.mockito.Mockito.verifyZeroInteractions; | ||
|
||
@RunWith(MockitoJUnitRunner.class) | ||
public class PipelineFunctionReplaceTest { | ||
|
||
private static final PipelineElement EMPTY_INPUT = PipelineElement.unresolved(); | ||
|
||
private static final PipelineElement KNOWN_INPUT = PipelineElement.resolved("eclipse-iot-test"); | ||
private static final String EXPECTED_OUTPUT = "eclipse_iot_test"; | ||
|
||
private static final PipelineElement KNOWN_INPUT_NO_MATCH = PipelineElement.resolved("eclipse"); | ||
private static final String EXPECTED_OUTPUT_NO_MATCH = "eclipse"; | ||
|
||
private final PipelineFunctionReplace function = new PipelineFunctionReplace(); | ||
|
||
@Mock | ||
private ExpressionResolver expressionResolver; | ||
|
||
@After | ||
public void verifyExpressionResolverUnused() { | ||
verifyZeroInteractions(expressionResolver); | ||
} | ||
|
||
@Test | ||
public void getName() { | ||
assertThat(function.getName()).isEqualTo("replace"); | ||
} | ||
|
||
@Test | ||
public void apply() { | ||
assertThat(function.apply(KNOWN_INPUT, "('-', '_')", expressionResolver)).contains(EXPECTED_OUTPUT); | ||
} | ||
|
||
@Test | ||
public void applyNoMatch() { | ||
assertThat(function.apply(KNOWN_INPUT_NO_MATCH, "('-', '_')", expressionResolver)).contains(EXPECTED_OUTPUT_NO_MATCH); | ||
} | ||
|
||
@Test | ||
public void returnsEmptyForEmptyInput() { | ||
assertThat(function.apply(EMPTY_INPUT, "('-', '_')", expressionResolver)).isEmpty(); | ||
} | ||
|
||
@Test | ||
public void throwsOnInvalidParameters() { | ||
// has not enough parameters | ||
assertThatExceptionOfType(PlaceholderFunctionSignatureInvalidException.class).isThrownBy(() -> | ||
function.apply(KNOWN_INPUT, "()", expressionResolver) | ||
); | ||
// has not enough parameters | ||
assertThatExceptionOfType(PlaceholderFunctionSignatureInvalidException.class).isThrownBy(() -> | ||
function.apply(KNOWN_INPUT, "('from')", expressionResolver) | ||
); | ||
// has no parameters | ||
assertThatExceptionOfType(PlaceholderFunctionSignatureInvalidException.class).isThrownBy(() -> | ||
function.apply(KNOWN_INPUT, "", expressionResolver) | ||
); | ||
} | ||
|
||
} |