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.portal.layoutconfiguration.util.velocity;
016    
017    import com.liferay.portal.kernel.json.JSONFactoryUtil;
018    import com.liferay.portal.kernel.json.JSONObject;
019    import com.liferay.portal.kernel.portlet.PortletContainerUtil;
020    import com.liferay.portal.kernel.portlet.PortletJSONUtil;
021    import com.liferay.portal.kernel.servlet.BufferCacheServletResponse;
022    import com.liferay.portal.kernel.settings.ModifiableSettings;
023    import com.liferay.portal.kernel.settings.PortletInstanceSettingsLocator;
024    import com.liferay.portal.kernel.settings.Settings;
025    import com.liferay.portal.kernel.settings.SettingsFactoryUtil;
026    import com.liferay.portal.kernel.util.ClassUtil;
027    import com.liferay.portal.kernel.util.GetterUtil;
028    import com.liferay.portal.kernel.util.StringBundler;
029    import com.liferay.portal.kernel.util.StringPool;
030    import com.liferay.portal.kernel.util.Validator;
031    import com.liferay.portal.layoutconfiguration.util.PortletRenderer;
032    import com.liferay.portal.model.LayoutTypePortlet;
033    import com.liferay.portal.model.Portlet;
034    import com.liferay.portal.service.PortletLocalServiceUtil;
035    import com.liferay.portal.theme.ThemeDisplay;
036    import com.liferay.portal.util.WebKeys;
037    
038    import java.util.ArrayList;
039    import java.util.Comparator;
040    import java.util.List;
041    import java.util.Map;
042    import java.util.TreeMap;
043    
044    import javax.servlet.http.HttpServletRequest;
045    import javax.servlet.http.HttpServletResponse;
046    
047    /**
048     * @author Ivica Cardic
049     * @author Brian Wing Shun Chan
050     * @author Shuyang Zhou
051     * @author Oliver Teichmann
052     */
053    public class TemplateProcessor implements ColumnProcessor {
054    
055            public TemplateProcessor(
056                    HttpServletRequest request, HttpServletResponse response,
057                    String portletId) {
058    
059                    _request = request;
060                    _response = response;
061    
062                    if (Validator.isNotNull(portletId)) {
063                            ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
064                                    WebKeys.THEME_DISPLAY);
065    
066                            _portlet = PortletLocalServiceUtil.getPortletById(
067                                    themeDisplay.getCompanyId(), portletId);
068                    }
069                    else {
070                            _portlet = null;
071                    }
072    
073                    _portletAjaxRender = GetterUtil.getBoolean(
074                            request.getAttribute(WebKeys.PORTLET_AJAX_RENDER));
075    
076                    _portletRenderers = new TreeMap<>(_renderWeightComparator);
077            }
078    
079            public Map<Integer, List<PortletRenderer>> getPortletRenderers() {
080                    return _portletRenderers;
081            }
082    
083            public boolean isPortletAjaxRender() {
084                    return _portletAjaxRender;
085            }
086    
087            @Override
088            public String processColumn(String columnId) throws Exception {
089                    return processColumn(columnId, StringPool.BLANK);
090            }
091    
092            @Override
093            public String processColumn(String columnId, String classNames)
094                    throws Exception {
095    
096                    ThemeDisplay themeDisplay = (ThemeDisplay)_request.getAttribute(
097                            WebKeys.THEME_DISPLAY);
098    
099                    LayoutTypePortlet layoutTypePortlet =
100                            themeDisplay.getLayoutTypePortlet();
101    
102                    List<Portlet> portlets = layoutTypePortlet.getAllPortlets(columnId);
103    
104                    StringBundler sb = new StringBundler(portlets.size() + 11);
105    
106                    sb.append("<div class=\"");
107                    sb.append("portlet-dropzone");
108    
109                    if (layoutTypePortlet.isCustomizable() &&
110                            layoutTypePortlet.isColumnDisabled(columnId)) {
111    
112                            sb.append(" portlet-dropzone-disabled");
113                    }
114    
115                    if (layoutTypePortlet.isColumnCustomizable(columnId)) {
116                            sb.append(" customizable");
117                    }
118    
119                    if (portlets.isEmpty()) {
120                            sb.append(" empty");
121                    }
122    
123                    if (Validator.isNotNull(classNames)) {
124                            sb.append(" ");
125                            sb.append(classNames);
126                    }
127    
128                    sb.append("\" id=\"layout-column_");
129                    sb.append(columnId);
130                    sb.append("\">");
131    
132                    for (int i = 0; i < portlets.size(); i++) {
133                            Portlet portlet = portlets.get(i);
134    
135                            Integer columnCount = new Integer(portlets.size());
136                            Integer columnPos = new Integer(i);
137    
138                            PortletRenderer portletRenderer = new PortletRenderer(
139                                    portlet, columnId, columnCount, columnPos);
140    
141                            if (_portletAjaxRender && (portlet.getRenderWeight() < 1)) {
142                                    StringBundler renderResult = portletRenderer.renderAjax(
143                                            _request, _response);
144    
145                                    sb.append(renderResult);
146                            }
147                            else {
148                                    Integer renderWeight = portlet.getRenderWeight();
149    
150                                    List<PortletRenderer> portletRenderers = _portletRenderers.get(
151                                            renderWeight);
152    
153                                    if (portletRenderers == null) {
154                                            portletRenderers = new ArrayList<>();
155    
156                                            _portletRenderers.put(renderWeight, portletRenderers);
157                                    }
158    
159                                    portletRenderers.add(portletRenderer);
160    
161                                    sb.append("[$TEMPLATE_PORTLET_");
162                                    sb.append(portlet.getPortletId());
163                                    sb.append("$]");
164                            }
165                    }
166    
167                    sb.append("</div>");
168    
169                    return sb.toString();
170            }
171    
172            @Override
173            public String processMax() throws Exception {
174                    BufferCacheServletResponse bufferCacheServletResponse =
175                            new BufferCacheServletResponse(_response);
176    
177                    PortletContainerUtil.render(
178                            _request, bufferCacheServletResponse, _portlet);
179    
180                    return bufferCacheServletResponse.getString();
181            }
182    
183            /**
184             * @deprecated As of 6.2.0, replaced by {@link #processMax()}
185             */
186            @Deprecated
187            @Override
188            public String processMax(String classNames) throws Exception {
189                    return processMax();
190            }
191    
192            @Override
193            public String processPortlet(String portletId) throws Exception {
194                    _request.setAttribute(WebKeys.RENDER_PORTLET_RESOURCE, Boolean.TRUE);
195    
196                    BufferCacheServletResponse bufferCacheServletResponse =
197                            new BufferCacheServletResponse(_response);
198    
199                    ThemeDisplay themeDisplay = (ThemeDisplay)_request.getAttribute(
200                            WebKeys.THEME_DISPLAY);
201    
202                    Portlet portlet = PortletLocalServiceUtil.getPortletById(
203                            themeDisplay.getCompanyId(), portletId);
204    
205                    JSONObject jsonObject = JSONFactoryUtil.createJSONObject();
206    
207                    PortletJSONUtil.populatePortletJSONObject(
208                            _request, StringPool.BLANK, portlet, jsonObject);
209    
210                    try {
211                            PortletJSONUtil.writeHeaderPaths(_response, jsonObject);
212    
213                            PortletContainerUtil.render(
214                                    _request, bufferCacheServletResponse, portlet);
215    
216                            PortletJSONUtil.writeFooterPaths(_response, jsonObject);
217    
218                            return bufferCacheServletResponse.getString();
219                    }
220                    finally {
221                            _request.removeAttribute(WebKeys.RENDER_PORTLET_RESOURCE);
222                    }
223            }
224    
225            @Override
226            public String processPortlet(
227                            String portletId, Map<String, ?> defaultSettingsMap)
228                    throws Exception {
229    
230                    ThemeDisplay themeDisplay = (ThemeDisplay)_request.getAttribute(
231                            WebKeys.THEME_DISPLAY);
232    
233                    Settings settings = SettingsFactoryUtil.getSettings(
234                            new PortletInstanceSettingsLocator(
235                                    themeDisplay.getLayout(), portletId));
236    
237                    ModifiableSettings modifiableSettings =
238                            settings.getModifiableSettings();
239    
240                    for (Map.Entry<String, ?> entry : defaultSettingsMap.entrySet()) {
241                            String key = entry.getKey();
242                            Object value = entry.getValue();
243    
244                            if (value instanceof String) {
245                                    modifiableSettings.setValue(key, (String)value);
246                            }
247                            else if (value instanceof String[]) {
248                                    modifiableSettings.setValues(key, (String[])value);
249                            }
250                            else {
251                                    throw new IllegalArgumentException(
252                                            "Key " + key + " has unsupported value of type " +
253                                                    ClassUtil.getClassName(value.getClass()));
254                            }
255                    }
256    
257                    modifiableSettings.store();
258    
259                    return processPortlet(portletId);
260            }
261    
262            private static final RenderWeightComparator _renderWeightComparator =
263                    new RenderWeightComparator();
264    
265            private final Portlet _portlet;
266            private final boolean _portletAjaxRender;
267            private final Map<Integer, List<PortletRenderer>> _portletRenderers;
268            private final HttpServletRequest _request;
269            private final HttpServletResponse _response;
270    
271            private static class RenderWeightComparator implements Comparator<Integer> {
272    
273                    @Override
274                    public int compare(Integer renderWeight1, Integer renderWeight2) {
275                            return renderWeight2.intValue() - renderWeight1.intValue();
276                    }
277    
278            }
279    
280    }