add MixedParamHybridUrlCodingStrategy
-------------------------------------

                 Key: WICKET-2395
                 URL: https://issues.apache.org/jira/browse/WICKET-2395
             Project: Wicket
          Issue Type: New Feature
    Affects Versions: 1.4-RC5
            Reporter: Vladimir Kovalyuk


/**
 * Apache 2 license.
 */

import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import org.apache.wicket.Page;
import org.apache.wicket.PageParameters;
import org.apache.wicket.RequestCycle;
import org.apache.wicket.request.target.coding.HybridUrlCodingStrategy;
import org.apache.wicket.request.target.coding.MixedParamUrlCodingStrategy;
import org.apache.wicket.util.string.AppendingStringBuffer;
import org.apache.wicket.util.value.ValueMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @see MixedParamUrlCodingStrategy
 * 
 * @author Erik van Oosten
 */
public class MixedParamHybridUrlCodingStrategy extends HybridUrlCodingStrategy {

        private static Logger logger = 
LoggerFactory.getLogger(MixedParamHybridUrlCodingStrategy.class);

        private final String[] parameterNames;
        private boolean ignoreUndeclaredParameters = true;

        /**
         * Construct.
         * 
         * @param mountPath
         *            mount path
         * @param pageClass
         *            class of mounted page
         * @param redirectOnBookmarkableRequest
         *            ?
         * @param parameterNames
         *            the parameter names (not null)
         */
        public MixedParamHybridUrlCodingStrategy(String mountPath, Class<? 
extends Page> pageClass,
                        boolean redirectOnBookmarkableRequest, String[] 
parameterNames) {

                super(mountPath, pageClass, redirectOnBookmarkableRequest);
                this.parameterNames = parameterNames;
        }

        /**
         * Construct.
         * 
         * @param mountPath
         *            mount path
         * @param pageClass
         *            class of mounted page
         * @param parameterNames
         *            the parameter names (not null)
         */
        public MixedParamHybridUrlCodingStrategy(String mountPath, Class<? 
extends Page> pageClass, String[] parameterNames) {
                super(mountPath, pageClass);
                this.parameterNames = parameterNames;
        }

        /** {...@inheritdoc} */
        @Override
        protected void appendParameters(AppendingStringBuffer url, Map<String, 
?> parameters) {
                if (!url.endsWith("/")) {
                        url.append("/");
                }

                Set<String> parameterNamesToAdd = new 
HashSet<String>(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 = "";
                                }
                                
url.append(urlEncodePathComponent(value)).append("/");
                                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;
                        }
                }
        }

        /** {...@inheritdoc} */
        @Override
        protected ValueMap decodeParameters(String urlFragment, Map<String, ?> 
urlParameters) {
                PageParameters params = new PageParameters();
                // Add all url parameters
                params.putAll(urlParameters);
                String urlPath = urlFragment;
                urlPath = removeStartSlash(urlPath);
                urlPath = removeEndSlash(urlPath);

                if (urlPath.length() > 0) {
                        String[] pathParts = urlPath.split("/");
                        if (pathParts.length > parameterNames.length) {
                                String msg = String.format(
                                                "Too many path parts, please 
provide sufficient number of path parameter names "
                                                                + " url: '%s', 
mountpath: '%s', urlPath: '%s', expected %d parameters", RequestCycle
                                                                
.get().getRequest().getURL(), getMountPath(), urlPath, parameterNames.length);
                                if (ignoreUndeclaredParameters) {
                                        logger.error(msg);
                                } else {
                                        throw new IllegalArgumentException(msg);
                                }
                        }

                        int actualParameterCount = Math.min(pathParts.length, 
parameterNames.length);
                        for (int i = 0; i < actualParameterCount; i++) {
                                params.put(parameterNames[i], 
urlDecodePathComponent(pathParts[i]));
                        }
                }

                return params;
        }

        private String removeEndSlash(String urlPath) {
                if (urlPath.endsWith("/")) {
                        urlPath = urlPath.substring(0, urlPath.length() - 1);
                }
                return urlPath;
        }

        private String removeStartSlash(String urlPath) {
                if (urlPath.startsWith("/")) {
                        urlPath = urlPath.substring(1);
                }
                return urlPath;
        }

        /**
         * @param ignoreUndeclaredParameters
         *            true to ignore undeclared parameters in the URL (still
         *            logged), false to throw an exception when this happens
         *            (default is true)
         */
        public void setIgnoreUndeclaredParameters(boolean 
ignoreUndeclaredParameters) {
                this.ignoreUndeclaredParameters = ignoreUndeclaredParameters;
        }
}

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.

Reply via email to