    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
    015    package org.apache.tapestry5.internal.services;
    016
    017    import org.apache.tapestry5.EventContext;
    018    import org.apache.tapestry5.internal.EmptyEventContext;
    019    import org.apache.tapestry5.internal.TapestryInternalUtils;
    020    import org.apache.tapestry5.internal.URLEventContext;
    021    import org.apache.tapestry5.ioc.internal.util.InternalUtils;
    022    import org.apache.tapestry5.ioc.services.TypeCoercer;
    023    import org.apache.tapestry5.services.ContextPathEncoder;
    024    import org.apache.tapestry5.services.ContextValueEncoder;
    025    import org.apache.tapestry5.services.URLEncoder;
    026
    027    public 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    }