Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@ public interface BuiltInFeatures {
String IGNORE_NESTED_INTERPRETATION_PARSE_ERRORS =
"IGNORE_NESTED_INTERPRETATION_PARSE_ERRORS";
String OUTPUT_UNDEFINED_VARIABLES_ERROR = "OUTPUT_UNDEFINED_VARIABLES_ERROR";
String INTEGER_SET_TO_LONG_CONVERSION = "INTEGER_SET_TO_LONG_CONVERSION";
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.hubspot.jinjava.lib.filter;

import com.hubspot.jinjava.features.BuiltInFeatures;
import com.hubspot.jinjava.interpret.JinjavaInterpreter;
import com.hubspot.jinjava.interpret.TemplateError;
import com.hubspot.jinjava.interpret.TemplateSyntaxException;
Expand Down Expand Up @@ -43,7 +44,27 @@ public Object filter(
Set<Object> varSet = objectToSet(var);
Set<Object> argSet = objectToSet(parseArgs(interpreter, args));

attachMismatchedTypesWarning(interpreter, varSet, argSet);
if (!varSet.isEmpty() && !argSet.isEmpty()) {
Object oneVar = varSet.iterator().next();
Object oneArg = argSet.iterator().next();

boolean featureActive = interpreter
.getConfig()
.getFeatures()
.isActive(
BuiltInFeatures.INTEGER_SET_TO_LONG_CONVERSION,
interpreter.getContext()
);
if (featureActive) {
if (oneVar instanceof Integer && oneArg instanceof Long) {
varSet = convertIntegersToLongs(varSet);
} else if (oneArg instanceof Integer && oneVar instanceof Long) {
argSet = convertIntegersToLongs(argSet);
}
}

attachMismatchedTypesWarning(interpreter, varSet, argSet, oneVar, oneArg);
}

return filter(varSet, argSet);
}
Expand All @@ -55,17 +76,31 @@ protected void attachMismatchedTypesWarning(
Set<Object> varSet,
Set<Object> argSet
) {
boolean hasAtLeastOneSetEmpty = varSet.isEmpty() || argSet.isEmpty();
if (hasAtLeastOneSetEmpty) {
if (varSet.isEmpty() || argSet.isEmpty()) {
return;
}
attachMismatchedTypesWarning(
interpreter,
varSet,
argSet,
varSet.iterator().next(),
argSet.iterator().next()
);
}

boolean areMatchedElementTypes = getTypeOfSetElements(varSet)
.equals(getTypeOfSetElements(argSet));
if (areMatchedElementTypes) {
private void attachMismatchedTypesWarning(
JinjavaInterpreter interpreter,
Set<Object> varSet,
Set<Object> argSet,
Object oneVarObj,
Object oneArgObj
) {
if (getTypeOfSetElements(varSet).equals(getTypeOfSetElements(argSet))) {
return;
}
if (potentiallyConvertibleNumbers(oneVarObj, oneArgObj)) {
return;
}

interpreter.addError(
new TemplateError(
TemplateError.ErrorType.WARNING,
Expand All @@ -84,6 +119,25 @@ protected void attachMismatchedTypesWarning(
);
}

private boolean potentiallyConvertibleNumbers(Object oneVarObj, Object oneArgObj) {
return (
(oneArgObj instanceof Integer && oneVarObj instanceof Long) ||
(oneVarObj instanceof Integer && oneArgObj instanceof Long)
);
}

private Set<Object> convertIntegersToLongs(Set<Object> set) {
Set<Object> result = new LinkedHashSet<>();
for (Object element : set) {
if (element instanceof Integer integer) {
result.add(integer.longValue());
} else {
result.add(element);
}
}
return result;
}

private String getTypeOfSetElements(Set<Object> set) {
return TypeFunction.type(set.iterator().next());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,16 @@
import static org.assertj.core.api.Assertions.assertThat;

import com.hubspot.jinjava.BaseJinjavaTest;
import com.hubspot.jinjava.Jinjava;
import com.hubspot.jinjava.features.BuiltInFeatures;
import com.hubspot.jinjava.features.FeatureConfig;
import com.hubspot.jinjava.features.FeatureStrategies;
import com.hubspot.jinjava.interpret.JinjavaInterpreter;
import com.hubspot.jinjava.interpret.RenderResult;
import com.hubspot.jinjava.interpret.TemplateError;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.junit.Before;
import org.junit.Test;
Expand Down Expand Up @@ -80,4 +87,53 @@ public void itThrowsWarningOnMismatchTypes() {
"Mismatched Types: input set has elements of type 'long' but arg set has elements of type 'str'. Use |map filter to convert sets to the same type for filter to work correctly."
);
}

@Test
public void itDoesNotThrowWarningOnIntegerLongMismatch() {
JinjavaInterpreter interpreter = jinjava.newInterpreter();

Set<Object> varSet = concreteSetFilter.objectToSet(new Long[] { 1L, 2L, 3L });
Set<Object> argSet = concreteSetFilter.objectToSet(new Integer[] { 1, 2, 3 });
concreteSetFilter.attachMismatchedTypesWarning(interpreter, varSet, argSet);

assertThat(interpreter.getErrors()).isEmpty();
}

@Test
public void itConvertsIntegerToLongWhenFeatureActive() {
Jinjava jinjavaWithFeature = new Jinjava(
BaseJinjavaTest
.newConfigBuilder()
.withFeatureConfig(
FeatureConfig
.newBuilder()
.add(BuiltInFeatures.INTEGER_SET_TO_LONG_CONVERSION, FeatureStrategies.ACTIVE)
.build()
)
.build()
);

Map<String, Object> vars = new HashMap<>();
vars.put("longList", new Long[] { 1L, 2L, 3L });
vars.put("intList", new Integer[] { 2, 3, 4 });

String result = jinjavaWithFeature.render("{{ longList|intersect(intList) }}", vars);

assertThat(result).isEqualTo("[2, 3]");
}

@Test
public void itDoesNotConvertWhenFeatureInactive() {
Map<String, Object> vars = new HashMap<>();
vars.put("longList", new Long[] { 1L, 2L, 3L });
vars.put("intList", new Integer[] { 2, 3, 4 });

RenderResult renderResult = jinjava.renderForResult(
"{{ longList|intersect(intList) }}",
vars
);

assertThat(renderResult.getOutput()).isEqualTo("[]");
assertThat(renderResult.getErrors()).isEmpty();
}
}
Loading