Wicket MixedParamHybridUrlCodingStrategy
May 23, 2009
I am about to run out the house for the Labor Day weekend, quickie post on my new coding url strategy.
MixedParamHybridUrlCodingStrategy lets you keep stateful multi-pagemap URLs clean while using mixed parameters.
Example…
mount(new MixedParamHybridUrlCodingStrategy("/questions",QuestionsPage.class,false,new String[]{"cat"}));
This will mount “/questions/stupid-category” and convert it to…
new PageParameters("cat","stupid-category");
package com.base.target.coding; import java.util.HashSet; import java.util.Iterator; import java.util.Map; import java.util.Set; import org.apache.wicket.IRequestTarget; import org.apache.wicket.PageParameters; import org.apache.wicket.protocol.http.request.WebRequestCodingStrategy; import org.apache.wicket.request.target.coding.HybridUrlCodingStrategy; import org.apache.wicket.util.string.AppendingStringBuffer; import org.apache.wicket.util.value.ValueMap; public class MixedParamHybridUrlCodingStrategy extends HybridUrlCodingStrategy { private final String[] parameterNames; public MixedParamHybridUrlCodingStrategy(final String mountPath, final Class pageClass) { super(mountPath, pageClass); this.parameterNames = new String[] {}; } public MixedParamHybridUrlCodingStrategy(final String mountPath, final Class pageClass,final boolean refresh) { super(mountPath,pageClass,refresh); this.parameterNames = new String[] {}; } public MixedParamHybridUrlCodingStrategy(final String mountPath, final Class pageClass,final String[] params) { super(mountPath,pageClass,false); this.parameterNames = params; } public MixedParamHybridUrlCodingStrategy(final String mountPath, final Class pageClass,final boolean refresh,final String[] params) { super(mountPath,pageClass,refresh); this.parameterNames = params; } @Override protected void appendParameters(final AppendingStringBuffer url, final Map parameters) { Set parameterNamesToAdd = new HashSet(parameters.keySet()); // Find index of last specified parameter boolean foundParameter = false; int lastSpecifiedParameter = parameterNames.length; while (lastSpecifiedParameter != 0 && !foundParameter) { foundParameter = parameters.containsKey(parameterNames[--lastSpecifiedParameter]); } if (foundParameter) { for (int i = 0; i <= lastSpecifiedParameter; i++) { String parameterName = parameterNames[i]; final Object param = parameters.get(parameterName); String value = param instanceof String[] ? ((String[])param)[0] : (String)param; if (value == null) { value = ""; } if (!url.endsWith("/")) { url.append("/"); } url.append(urlEncodePathComponent(value)); parameterNamesToAdd.remove(parameterName); } } if (!parameterNamesToAdd.isEmpty()) { boolean first = true; final Iterator iterator = parameterNamesToAdd.iterator(); while (iterator.hasNext()) { url.append(first ? '?' : '&'); String parameterName = (String)iterator.next(); final Object param = parameters.get(parameterName); String value = param instanceof String[] ? ((String[])param)[0] : (String)param; url.append(urlEncodeQueryComponent(parameterName)).append("=").append( urlEncodeQueryComponent(value)); first = false; } } String pageMap = (String)parameters.get(WebRequestCodingStrategy.PAGEMAP); if (pageMap != null) { pageMap = WebRequestCodingStrategy.encodePageMapName(pageMap); if (!url.endsWith("/")) { url.append("/"); } url.append(WebRequestCodingStrategy.PAGEMAP).append("/").append( urlEncodePathComponent(pageMap)); } } @Override public CharSequence encode(final IRequestTarget requestTarget) { String url = String.valueOf(super.encode(requestTarget)); if(url.contains(".wicket")) { // Rewrite URL from.. /foo?bar=5.wicket-xxx to /foo.wicket-xxx?bar=5 return url.replaceAll("(.*)\\?(.*)\\.(wicket-[0-9]+)$", "$1.$3?$2"); } return url; } @Override protected ValueMap decodeParameters(final String urlFragment, final Map urlParameters) { PageParameters params = new PageParameters(); if(urlFragment == null) { return params; } // Add all url parameters and normalize for(Iteratoritr = urlParameters.entrySet().iterator();itr.hasNext();) { Map.Entry e = itr.next(); if(e.getValue() != null) { String val = (e.getValue())[0]; if(val != null) { if(val.contains(".wicket")) { val = val.substring(0,val.indexOf(".wicket")); urlParameters.put(e.getKey(), val); } } } } params.putAll(urlParameters); String urlPath = urlFragment; if (urlPath.startsWith("/")) { urlPath = urlPath.substring(1); } if (urlPath.length() > 0) { String[] pathParts = urlPath.split("/"); if (pathParts.length > parameterNames.length) { throw new IllegalArgumentException( "Too many path parts, please provide sufficient number of path parameter names"); } for (int i = 0; i < pathParts.length; i++) { if(pathParts[i].contains(".wicket")) { pathParts[i].substring(0,pathParts[i].indexOf(".wicket")); } if (WebRequestCodingStrategy.PAGEMAP.equals(pathParts[i])) { params.put(WebRequestCodingStrategy.PAGEMAP, WebRequestCodingStrategy.decodePageMapName(urlDecodePathComponent(pathParts[i]))); } params.put(parameterNames[i], urlDecodePathComponent(pathParts[i])); } } return params; } }
An UrlCodingStrategy I’ve definitely missed in Wicket. Cool, thanks.
Btw, your blog software transformed “–” into “-“:
foundParameter = parameters.containsKey(parameterNames[–lastSpecifiedParameter]);
should be
foundParameter = parameters.containsKey(parameterNames[-–lastSpecifiedParameter]);