001    // Copyright 2009 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.Link;
018    import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
019    import org.apache.tapestry5.ioc.internal.util.Defense;
020    import org.apache.tapestry5.ioc.internal.util.InternalUtils;
021    import org.apache.tapestry5.services.Response;
022    
023    import java.util.List;
024    import java.util.Map;
025    
026    public class LinkImpl implements Link
027    {
028        private Map<String, String> parameters;
029    
030        private final String absoluteURI;
031    
032        private final boolean optimizable;
033    
034        private final boolean forForm;
035    
036        private final Response response;
037    
038        private final RequestPathOptimizer optimizer;
039    
040        private String anchor;
041    
042        public LinkImpl(String absoluteURI, boolean optimizable, boolean forForm, Response response,
043                         RequestPathOptimizer optimizer)
044        {
045            this.absoluteURI = absoluteURI;
046            this.optimizable = optimizable;
047            this.forForm = forForm;
048            this.response = response;
049            this.optimizer = optimizer;
050        }
051    
052        public void addParameter(String parameterName, String value)
053        {
054            Defense.notBlank(parameterName, "parameterName");
055            Defense.notBlank(value, "value");
056    
057            if (parameters == null)
058                parameters = CollectionFactory.newMap();
059    
060            parameters.put(parameterName, value);
061        }
062    
063        public String getAnchor()
064        {
065            return anchor;
066        }
067    
068        public List<String> getParameterNames()
069        {
070            return InternalUtils.sortedKeys(parameters);
071        }
072    
073        public String getParameterValue(String name)
074        {
075            return InternalUtils.get(parameters, name);
076        }
077    
078        public void setAnchor(String anchor)
079        {
080            this.anchor = anchor;
081        }
082    
083        public String toAbsoluteURI()
084        {
085            return appendAnchor(response.encodeURL(buildURI()));
086        }
087    
088        public String toRedirectURI()
089        {
090            return appendAnchor(response.encodeRedirectURL(buildURI()));
091        }
092    
093        public String toURI()
094        {
095            String path = buildURI();
096    
097            if (optimizable)
098                path = optimizer.optimizePath(path);
099    
100            return appendAnchor(response.encodeURL(path));
101        }
102    
103        private String appendAnchor(String path)
104        {
105            return InternalUtils.isBlank(anchor)
106                   ? path
107                   : path + "#" + anchor;
108        }
109    
110        /**
111         * Returns the value from {@link #toURI()}
112         */
113        @Override
114        public String toString()
115        {
116            return toURI();
117        }
118    
119    
120        /**
121         * Extends the absolute path with any query parameters. Query parameters are never added to a forForm link.
122         *
123         * @return absoluteURI appended with query parameters
124         */
125        private String buildURI()
126        {
127            if (forForm || parameters == null)
128                return absoluteURI;
129    
130            StringBuilder builder = new StringBuilder(absoluteURI.length() * 2);
131    
132            builder.append(absoluteURI);
133    
134            String sep = "?";
135    
136            for (String name : getParameterNames())
137            {
138                String value = parameters.get(name);
139    
140                builder.append(sep);
141    
142                // We assume that the name is URL safe and that the value will already have been URL
143                // encoded if it is not known to be URL safe.
144    
145                builder.append(name);
146                builder.append("=");
147                builder.append(value);
148    
149                sep = "&";
150            }
151    
152            return builder.toString();
153        }
154    }