    001// Copyright 2008, 2010 The Apache Software Foundation
    002//
    003// Licensed under the Apache License, Version 2.0 (the "License");
    004// you may not use this file except in compliance with the License.
    005// You may obtain a copy of the License at
    006//
    007// http://www.apache.org/licenses/LICENSE-2.0
    008//
    009// Unless required by applicable law or agreed to in writing, software
    010// distributed under the License is distributed on an "AS IS" BASIS,
    011// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    012// See the License for the specific language governing permissions and
    013// limitations under the License.
    014
    015package org.apache.tapestry5.internal.services;
    016
    017import org.apache.tapestry5.EventContext;
    018import org.apache.tapestry5.commons.services.TypeCoercer;
    019import org.apache.tapestry5.internal.EmptyEventContext;
    020import org.apache.tapestry5.internal.TapestryInternalUtils;
    021import org.apache.tapestry5.internal.URLEventContext;
    022import org.apache.tapestry5.ioc.internal.util.InternalUtils;
    023import org.apache.tapestry5.services.ContextPathEncoder;
    024import org.apache.tapestry5.services.ContextValueEncoder;
    025import org.apache.tapestry5.services.URLEncoder;
    026
    027public class ContextPathEncoderImpl implements ContextPathEncoder
    028{
    029    private static final int BUFFER_SIZE = 100;
    030
    031    private final ContextValueEncoder valueEncoder;
    032
    033    private final URLEncoder urlEncoder;
    034
    035    private final TypeCoercer typeCoercer;
    036
    037    private final EventContext EMPTY = new EmptyEventContext();
    038
    039    public ContextPathEncoderImpl(ContextValueEncoder valueEncoder, URLEncoder urlEncoder, TypeCoercer typeCoercer)
    040    {
    041        this.valueEncoder = valueEncoder;
    042        this.urlEncoder = urlEncoder;
    043        this.typeCoercer = typeCoercer;
    044    }
    045
    046    public String encodeValue(Object value)
    047    {
    048        String valueEncoded = value == null ? null : valueEncoder.toClient(value);
    049
    050        return urlEncoder.encode(valueEncoded);
    051    }
    052
    053    public String encodeIntoPath(Object[] context)
    054    {
    055        if (context == null || context.length == 0)
    056            return "";
    057
    058        return encodeIntoPath(new ArrayEventContext(typeCoercer, context));
    059    }
    060
    061    public String encodeIntoPath(EventContext context)
    062    {
    063        assert context != null;
    064        int count = context.getCount();
    065
    066        StringBuilder output = new StringBuilder(BUFFER_SIZE);
    067
    068        for (int i = 0; i < count; i++)
    069        {
    070            Object raw = context.get(Object.class, i);
    071
    072            String urlEncoded = encodeValue(raw);
    073
    074            if (i > 0)
    075                output.append('/');
    076
    077            output.append(urlEncoded);
    078        }
    079
    080        return output.toString();
    081    }
    082
    083    public EventContext decodePath(String path)
    084    {
    085        if (InternalUtils.isBlank(path))
    086            return EMPTY;
    087
    088        String[] split = TapestryInternalUtils.splitPath(path);
    089
    090        for (int i = 0; i < split.length; i++)
    091        {
    092            split[i] = urlEncoder.decode(split[i]);
    093        }
    094
    095        return new URLEventContext(valueEncoder, split);
    096    }
    097}