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 }