[ https://issues.apache.org/jira/browse/VELOCITY-986?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]
Patrick Barry updated VELOCITY-986: ----------------------------------- Summary: Breaking change- Map size method is called, instead of provided size property (was: Regression test failure) > Breaking change- Map size method is called, instead of provided size property > ----------------------------------------------------------------------------- > > Key: VELOCITY-986 > URL: https://issues.apache.org/jira/browse/VELOCITY-986 > Project: Velocity > Issue Type: Bug > Components: Engine > Affects Versions: 2.4, 2.4.1 > Reporter: Patrick Barry > Priority: Major > > We recently tried to upgrade to 2.4 and 2.4.1 and both had this issue, so we > had to rollback. We have a template looking like this: > [https://my.example.com?size=$|https://my.example.com/?size=$]{input.size} > > In our VelocityContext, we have have an InnerContext values that should be > used. > IE > {"size"= "1089", "name"="tyler", "age"="28"} > > In versions 2.3 and below, this would evaluate to > [https://my.example.com?size=1089|https://my.example.com/?size=1089] > With newest versions, it gives us the number of items in our map. So > [https://my.example.com?size=3|https://my.example.com/?size=1089] > > Here is a unit test of our usage. This test includes the ability to register > many different "providers", however, I kept it simple and just used one. > Providers have a prefix, so in the example above, we use a prefix provider of > "input". This allows to "scope" contexts. > > {code:java} > import org.apache.commons.collections4.map.CaseInsensitiveMap; > import org.apache.commons.lang3.NotImplementedException; > import org.apache.commons.lang3.StringUtils; > import org.apache.velocity.VelocityContext; > import org.apache.velocity.app.Velocity; > import org.apache.velocity.app.VelocityEngine; > import org.apache.velocity.context.Context; > import org.junit.Test; > import java.io.StringWriter; > import java.util.LinkedList; > import java.util.List; > import java.util.Map; > import java.util.Set; > import static org.junit.jupiter.api.Assertions.assertEquals; > public class VelocityRegressionTest { > @Test > public void testVelocityTemplate() throws Exception { > VelocityEngine velocityEngine = new VelocityEngine(); > velocityEngine.init(); > VariableProviderCaseInsensitiveMap<String> innerMap = new > VariableProviderCaseInsensitiveMap<>("input"); > innerMap.put("size", "1098"); > innerMap.put("name", "Tyler"); > innerMap.put("try", "1"); > Context innerContext = new > VariableProviderVelocityContext(List.of(innerMap)); > VelocityContext context = new VelocityContext(innerContext); > StringWriter sw = new StringWriter(); > String vt = "https://my.example.com?size=${input.size}"; > Velocity.evaluate(context, sw, "", vt); > assertEquals("https://my.example.com?size=1098", sw.toString()); > } > static class VariableProviderCaseInsensitiveMap<T> extends > CaseInsensitiveMap<String, T> { > private String providerContextPrefix = null; > public VariableProviderCaseInsensitiveMap(final String > providerContextPrefix) { > if (!StringUtils.isBlank(providerContextPrefix)) { > this.providerContextPrefix = providerContextPrefix; > } > } > public String getProviderContextPrefix() { > return providerContextPrefix; > } > public Set<String> getKeys() { > return super.keySet(); > } > public Map<String, T> getMap() {return this;} > } > static class VariableProviderVelocityContext extends VelocityContext { > protected final List<VariableProviderCaseInsensitiveMap> providers; > public VariableProviderVelocityContext( > final List<VariableProviderCaseInsensitiveMap> providers > ) { > super(); > this.providers = providers; > } > private Object lookup(String key) { > for (VariableProviderCaseInsensitiveMap provider : providers) { > final String contextPrefix = > provider.getProviderContextPrefix(); > if (contextPrefix.equalsIgnoreCase(key)) { > return provider.getMap(); > } > } > return null; > } > @Override > public Object internalGet(String var1) { > return lookup(var1); > } > @Override > public Object internalPut(String key, Object value) { > throw new NotImplementedException("internalRemove is not valid > and is not implemented"); > } > @Override > public String[] internalGetKeys() { > List<String> keys = new LinkedList<>(); > for (VariableProviderCaseInsensitiveMap provider : providers) { > String prefix = provider.getProviderContextPrefix(); > if (StringUtils.isNotBlank(prefix)) { > keys.add(prefix); > } //the prefix is the key name for a context provider. > else { > keys.addAll(provider.getKeys()); > } > } > return keys.toArray(new String[0]); > } > @Override > public boolean internalContainsKey(String var1) { > return lookup(var1) != null; > } > @Override > public Object internalRemove(String var1) { > throw new NotImplementedException("internalRemove is not valid > and is not implemented"); > } > } > } {code} -- This message was sent by Atlassian Jira (v8.20.10#820010) --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@velocity.apache.org For additional commands, e-mail: dev-h...@velocity.apache.org