package org.tessell.place.tokenizer; import org.tessell.place.PlaceRequest; /** * Formats tokens from String values into PlaceRequest values and back again. * * This implementation parses the token format like so: * * <pre> * [name](;param=value)* * </pre> */ public class DefaultTokenizer implements Tokenizer { private final String paramSep; private final String valueSep; public DefaultTokenizer() { this(";", "="); } public DefaultTokenizer(final String paramSeparator, final String valueSeparator) { paramSep = paramSeparator; valueSep = valueSeparator; } public String toHistoryToken(final PlaceRequest request) { final StringBuilder out = new StringBuilder(); out.append(escape(request.getName())); for (final String name : request.getParameterNames()) { out.append(paramSep); out.append(escape(name)).append(valueSep); out.append(escape(request.getParameter(name, ""))); } return out.toString(); } public PlaceRequest toPlaceRequest(final String token) throws TokenizerException { final int paramSepIndex = token.indexOf(paramSep); if (paramSepIndex == -1) { return new PlaceRequest(unescape(token)); } else if (paramSepIndex >= 0) { PlaceRequest request = new PlaceRequest(unescape(token.substring(0, paramSepIndex))); for (final String paramToken : token.substring(paramSepIndex + 1).split(paramSep)) { final String[] param = paramToken.split(valueSep); if (param.length == 1) { request = request.with(unescape(param[0]), ""); } else if (param.length == 2) { request = request.with(unescape(param[0]), unescape(param[1])); } else { throw new TokenizerException("Parameters require a single '" + valueSep + "' between the key and value."); } } return request; } else { throw new TokenizerException("Invalid token " + token); } } protected String escape(final String value) { return Codec.encodeQueryString(value); } protected String unescape(final String value) { return Codec.decodeQueryString(value); } }