001    /**
002     * Copyright (c) 2000-present Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portlet;
016    
017    import com.liferay.portal.kernel.portlet.Route;
018    import com.liferay.portal.kernel.util.InheritableMap;
019    import com.liferay.portal.kernel.util.MapUtil;
020    import com.liferay.portal.kernel.util.StringEncoder;
021    import com.liferay.portal.kernel.util.StringParser;
022    import com.liferay.portal.kernel.util.URLStringEncoder;
023    import com.liferay.portal.kernel.util.Validator;
024    
025    import java.util.Collections;
026    import java.util.HashMap;
027    import java.util.HashSet;
028    import java.util.Map;
029    import java.util.Set;
030    
031    /**
032     * @author Connor McKay
033     * @author Brian Wing Shun Chan
034     */
035    public class RouteImpl implements Route {
036    
037            public RouteImpl(String pattern) {
038                    _stringParser = StringParser.create(pattern);
039    
040                    _stringParser.setStringEncoder(_urlEncoder);
041            }
042    
043            @Override
044            public void addGeneratedParameter(String name, String pattern) {
045                    if (_generatedParameters == null) {
046                            _generatedParameters = new HashMap<>();
047                    }
048    
049                    StringParser stringParser = StringParser.create(pattern);
050    
051                    _generatedParameters.put(name, stringParser);
052            }
053    
054            @Override
055            public void addIgnoredParameter(String name) {
056                    if (_ignoredParameters == null) {
057                            _ignoredParameters = new HashSet<>();
058                    }
059    
060                    _ignoredParameters.add(name);
061            }
062    
063            @Override
064            public void addImplicitParameter(String name, String value) {
065                    if (_implicitParameters == null) {
066                            _implicitParameters = new HashMap<>();
067                    }
068    
069                    _implicitParameters.put(name, value);
070            }
071    
072            @Override
073            public void addOverriddenParameter(String name, String value) {
074                    if (_overriddenParameters == null) {
075                            _overriddenParameters = new HashMap<>();
076                    }
077    
078                    _overriddenParameters.put(name, value);
079            }
080    
081            @Override
082            public Map<String, StringParser> getGeneratedParameters() {
083                    if (_generatedParameters == null) {
084                            return Collections.emptyMap();
085                    }
086    
087                    return _generatedParameters;
088            }
089    
090            @Override
091            public Set<String> getIgnoredParameters() {
092                    if (_ignoredParameters == null) {
093                            return Collections.emptySet();
094                    }
095    
096                    return _ignoredParameters;
097            }
098    
099            @Override
100            public Map<String, String> getImplicitParameters() {
101                    if (_implicitParameters == null) {
102                            return Collections.emptyMap();
103                    }
104    
105                    return _implicitParameters;
106            }
107    
108            @Override
109            public Map<String, String> getOverriddenParameters() {
110                    if (_overriddenParameters == null) {
111                            return Collections.emptyMap();
112                    }
113    
114                    return _overriddenParameters;
115            }
116    
117            @Override
118            public String parametersToUrl(Map<String, String> parameters) {
119                    InheritableMap<String, String> allParameters = new InheritableMap<>();
120    
121                    allParameters.setParentMap(parameters);
122    
123                    // The order is important because virtual parameters may sometimes be
124                    // checked by implicit parameters
125    
126                    Map<String, StringParser> generatedParameters =
127                            getGeneratedParameters();
128    
129                    for (Map.Entry<String, StringParser> entry :
130                                    generatedParameters.entrySet()) {
131    
132                            String name = entry.getKey();
133                            StringParser stringParser = entry.getValue();
134    
135                            String value = MapUtil.getString(allParameters, name);
136    
137                            if (!stringParser.parse(value, allParameters)) {
138                                    return null;
139                            }
140                    }
141    
142                    Map<String, String> implicitParameters = getImplicitParameters();
143    
144                    for (Map.Entry<String, String> entry : implicitParameters.entrySet()) {
145                            String name = entry.getKey();
146                            String value = entry.getValue();
147    
148                            if (!value.equals(MapUtil.getString(allParameters, name))) {
149                                    return null;
150                            }
151                    }
152    
153                    String url = _stringParser.build(allParameters);
154    
155                    if (Validator.isNull(url)) {
156                            return null;
157                    }
158    
159                    for (String name : generatedParameters.keySet()) {
160    
161                            // Virtual parameters will never be placed in the query string, so
162                            // parameters is modified directly instead of allParameters
163    
164                            parameters.remove(name);
165                    }
166    
167                    for (String name : implicitParameters.keySet()) {
168                            parameters.remove(name);
169                    }
170    
171                    for (String name : getIgnoredParameters()) {
172                            parameters.remove(name);
173                    }
174    
175                    return url;
176            }
177    
178            @Override
179            public boolean urlToParameters(String url, Map<String, String> parameters) {
180                    if (!_stringParser.parse(url, parameters)) {
181                            return false;
182                    }
183    
184                    parameters.putAll(getImplicitParameters());
185                    parameters.putAll(getOverriddenParameters());
186    
187                    // The order is important because generated parameters may be dependent
188                    // on implicit parameters or overridden parameters
189    
190                    Map<String, StringParser> generatedParameters =
191                            getGeneratedParameters();
192    
193                    for (Map.Entry<String, StringParser> entry :
194                                    generatedParameters.entrySet()) {
195    
196                            String name = entry.getKey();
197                            StringParser stringParser = entry.getValue();
198    
199                            String value = stringParser.build(parameters);
200    
201                            // Generated parameters are not guaranteed to be created. The format
202                            // of the virtual parameters in the route pattern must match their
203                            // format in the generated parameter.
204    
205                            if (value != null) {
206                                    parameters.put(name, value);
207                            }
208                    }
209    
210                    return true;
211            }
212    
213            private static final StringEncoder _urlEncoder = new URLStringEncoder();
214    
215            private Map<String, StringParser> _generatedParameters;
216            private Set<String> _ignoredParameters;
217            private Map<String, String> _implicitParameters;
218            private Map<String, String> _overriddenParameters;
219            private final StringParser _stringParser;
220    
221    }