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…

[code lang=”java”]

mount(new MixedParamHybridUrlCodingStrategy(“/questions”,QuestionsPage.class,false,new String[]{“cat”}));

[/code]

This will mount “/questions/stupid-category” and convert it to…

[code lang=”java”]
new PageParameters(“cat”,”stupid-category”);
[/code]

[code lang=”java”]

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(Iterator itr = 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; } } [/code]