001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.wicket.core.request.mapper;
018
019import java.util.List;
020import org.apache.wicket.core.request.handler.ListenerRequestHandler;
021import org.apache.wicket.core.request.handler.PageAndComponentProvider;
022import org.apache.wicket.core.request.handler.PageProvider;
023import org.apache.wicket.core.request.handler.RenderPageRequestHandler;
024import org.apache.wicket.request.IRequestHandler;
025import org.apache.wicket.request.Request;
026import org.apache.wicket.request.Url;
027import org.apache.wicket.request.component.IRequestablePage;
028import org.apache.wicket.request.mapper.info.ComponentInfo;
029import org.apache.wicket.request.mapper.info.PageComponentInfo;
030import org.apache.wicket.request.mapper.info.PageInfo;
031
032/**
033 * Decodes and encodes the following URLs:
034 *
035 * <pre>
036 *  Page Instance - Render (RenderPageRequestHandler)
037 *  /wicket/page?2
038 *
039 *
040 *  Page Instance - Listener (ListenerRequestHandler)
041 *  /wicket/page?2-click-foo-bar-baz
042 *  /wicket/page?2-click.1-foo-bar-baz (1 is behavior index)
043 * </pre>
044 *
045 * @author Matej Knopp
046 */
047public class PageInstanceMapper extends AbstractComponentMapper
048{
049        /**
050         * Construct.
051         */
052        public PageInstanceMapper()
053        {
054        }
055
056        /**
057         * @see org.apache.wicket.request.IRequestMapper#mapRequest(org.apache.wicket.request.Request)
058         */
059        @Override
060        public IRequestHandler mapRequest(Request request)
061        {
062                if (matches(request))
063                {
064                        Url url = request.getUrl();
065                        PageComponentInfo info = getPageComponentInfo(url);
066                        if (info != null && info.getPageInfo().getPageId() != null)
067                        {
068                                Integer renderCount = info.getComponentInfo() != null ? info.getComponentInfo()
069                                        .getRenderCount() : null;
070
071                                if (info.getComponentInfo() == null)
072                                {
073                                        PageProvider provider = new PageProvider(info.getPageInfo().getPageId(),
074                                                renderCount);
075                                        provider.setPageSource(getContext());
076                                        // render page
077                                        return new RenderPageRequestHandler(provider);
078                                }
079                                else
080                                {
081                                        ComponentInfo componentInfo = info.getComponentInfo();
082
083                                        PageAndComponentProvider provider = new PageAndComponentProvider(
084                                                info.getPageInfo().getPageId(), renderCount,
085                                                componentInfo.getComponentPath());
086
087                                        provider.setPageSource(getContext());
088
089                                        return new ListenerRequestHandler(provider, componentInfo.getBehaviorId());
090                                }
091                        }
092                }
093                return null;
094        }
095
096        /**
097         * @see org.apache.wicket.request.IRequestMapper#mapHandler(org.apache.wicket.request.IRequestHandler)
098         */
099        @Override
100        public Url mapHandler(IRequestHandler requestHandler)
101        {
102                PageComponentInfo info = null;
103
104                if (requestHandler instanceof RenderPageRequestHandler)
105                {
106                        IRequestablePage page = ((RenderPageRequestHandler)requestHandler).getPage();
107
108                        PageInfo i = new PageInfo(page.getPageId());
109                        info = new PageComponentInfo(i, null);
110                }
111                else if (requestHandler instanceof ListenerRequestHandler)
112                {
113                        ListenerRequestHandler handler = (ListenerRequestHandler)requestHandler;
114                        IRequestablePage page = handler.getPage();
115                        String componentPath = handler.getComponentPath();
116
117                        Integer renderCount = null;
118                        if (handler.includeRenderCount())
119                        {
120                                renderCount = page.getRenderCount();
121                        }
122
123                        PageInfo pageInfo = new PageInfo(page.getPageId());
124                        ComponentInfo componentInfo = new ComponentInfo(renderCount, componentPath, handler.getBehaviorIndex());
125                        info = new PageComponentInfo(pageInfo, componentInfo);
126                }
127
128                if (info != null)
129                {
130                        Url url = new Url();
131                        url.getSegments().add(getContext().getNamespace());
132                        url.getSegments().add(getContext().getPageIdentifier());
133                        encodePageComponentInfo(url, info);
134                        return url;
135                }
136                else
137                {
138                        return null;
139                }
140        }
141
142        /**
143         * @see org.apache.wicket.request.IRequestMapper#getCompatibilityScore(org.apache.wicket.request.Request)
144         */
145        @Override
146        public int getCompatibilityScore(final Request request)
147        {
148                int score = 0;
149                if (matches(request))
150                {
151                        score = Integer.MAX_VALUE;
152                }
153                return score;
154        }
155
156        /**
157         * Matches when the request url starts with
158         * {@link org.apache.wicket.core.request.mapper.IMapperContext#getNamespace()}/{@link org.apache.wicket.core.request.mapper.IMapperContext#getPageIdentifier()}
159         * or when the base url starts with
160         * {@link org.apache.wicket.core.request.mapper.IMapperContext#getNamespace()}/{@link org.apache.wicket.core.request.mapper.IMapperContext#getPageIdentifier()}
161         * and the request url with {@link org.apache.wicket.core.request.mapper.IMapperContext#getPageIdentifier()}
162
163         * @param request
164         *      the request to check
165         * @return {@code true} if the conditions match
166         */
167        private boolean matches(final Request request)
168        {
169                boolean matches = false;
170                Url url = request.getUrl();
171                Url baseUrl = request.getClientUrl();
172                String namespace = getContext().getNamespace();
173                String pageIdentifier = getContext().getPageIdentifier();
174                List<String> segments = url.getSegments();
175                
176                if (isNotPageInstanceUrl(segments, pageIdentifier))
177                {
178                        return false;
179                }
180                
181                if (urlStartsWith(url, namespace, pageIdentifier))
182                {
183                        matches = true;
184                }
185                else if (urlStartsWith(baseUrl, namespace, pageIdentifier) && urlStartsWith(url, pageIdentifier))
186                {
187                        matches = true;
188                }
189                else if (urlStartsWith(baseUrl, pageIdentifier) && urlStartsWith(url, pageIdentifier))
190                {
191                        matches = true;
192                }
193
194                return matches;
195        }
196
197
198        private boolean isNotPageInstanceUrl(List<String> segments, String pageIdentifier) 
199        {               
200                if (segments.size() > 2 ) 
201                {
202                        return true;
203                } 
204                
205                int pageIdIndex = segments.indexOf(pageIdentifier);
206                
207                //check if we have segments after pageIdentifier
208                return pageIdIndex < 0 || segments.size() - 1 > pageIdIndex;
209        }
210}