001    /**
002     * Copyright (c) 2000-2013 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.kernel.templateparser;
016    
017    import com.liferay.portal.kernel.io.unsync.UnsyncStringWriter;
018    import com.liferay.portal.kernel.mobile.device.Device;
019    import com.liferay.portal.kernel.mobile.device.UnknownDevice;
020    import com.liferay.portal.kernel.util.GetterUtil;
021    import com.liferay.portal.kernel.util.LocaleUtil;
022    import com.liferay.portal.kernel.util.StringBundler;
023    import com.liferay.portal.kernel.util.StringPool;
024    import com.liferay.portal.kernel.util.Validator;
025    import com.liferay.portal.kernel.xml.Document;
026    import com.liferay.portal.kernel.xml.DocumentException;
027    import com.liferay.portal.kernel.xml.Element;
028    import com.liferay.portal.kernel.xml.SAXReaderUtil;
029    import com.liferay.portal.model.Company;
030    import com.liferay.portal.security.permission.PermissionThreadLocal;
031    import com.liferay.portal.service.CompanyLocalServiceUtil;
032    import com.liferay.portal.theme.ThemeDisplay;
033    
034    import java.io.IOException;
035    
036    import java.util.ArrayList;
037    import java.util.HashMap;
038    import java.util.List;
039    import java.util.Locale;
040    import java.util.Map;
041    
042    /**
043     * @author Brian Wing Shun Chan
044     * @author Marcellus Tavares
045     */
046    public abstract class BaseTemplateParser implements TemplateParser {
047    
048            @Override
049            public String getLanguageId() {
050                    return _languageId;
051            }
052    
053            @Override
054            public String getScript() {
055                    return _script;
056            }
057    
058            @Override
059            public ThemeDisplay getThemeDisplay() {
060                    return _themeDisplay;
061            }
062    
063            @Override
064            public Map<String, String> getTokens() {
065                    return _tokens;
066            }
067    
068            @Override
069            public String getViewMode() {
070                    return _viewMode;
071            }
072    
073            @Override
074            public String getXML() {
075                    return _xml;
076            }
077    
078            public void setContextObjects(Map<String, Object> contextObjects) {
079                    _contextObjects = contextObjects;
080            }
081    
082            @Override
083            public void setLanguageId(String languageId) {
084                    _languageId = languageId;
085            }
086    
087            @Override
088            public void setScript(String script) {
089                    _script = script;
090            }
091    
092            @Override
093            public void setThemeDisplay(ThemeDisplay themeDisplay) {
094                    _themeDisplay = themeDisplay;
095            }
096    
097            @Override
098            public void setTokens(Map<String, String> tokens) {
099                    _tokens = tokens;
100            }
101    
102            @Override
103            public void setViewMode(String viewMode) {
104                    _viewMode = viewMode;
105            }
106    
107            @Override
108            public void setXML(String xml) {
109                    _xml = xml;
110            }
111    
112            @Override
113            public String transform() throws TransformException {
114                    UnsyncStringWriter unsyncStringWriter = new UnsyncStringWriter();
115    
116                    boolean load = false;
117    
118                    try {
119                            TemplateContext templateContext = getTemplateContext();
120    
121                            if (Validator.isNotNull(_xml)) {
122                                    Document document = SAXReaderUtil.read(_xml);
123    
124                                    Element rootElement = document.getRootElement();
125    
126                                    List<TemplateNode> templateNodes = getTemplateNodes(
127                                            rootElement);
128    
129                                    if (templateNodes != null) {
130                                            for (TemplateNode templateNode : templateNodes) {
131                                                    templateContext.put(
132                                                            templateNode.getName(), templateNode);
133                                            }
134                                    }
135    
136                                    Element requestElement = rootElement.element("request");
137    
138                                    templateContext.put(
139                                            "request", insertRequestVariables(requestElement));
140    
141                                    templateContext.put("xmlRequest", requestElement.asXML());
142                            }
143    
144                            if (_contextObjects != null) {
145                                    for (String key : _contextObjects.keySet()) {
146                                            templateContext.put(key, _contextObjects.get(key));
147                                    }
148                            }
149    
150                            populateTemplateContext(templateContext);
151    
152                            load = mergeTemplate(templateContext, unsyncStringWriter);
153                    }
154                    catch (Exception e) {
155                            if (e instanceof DocumentException) {
156                                    throw new TransformException("Unable to read XML document", e);
157                            }
158                            else if (e instanceof IOException) {
159                                    throw new TransformException("Error reading template", e);
160                            }
161                            else if (e instanceof TransformException) {
162                                    throw (TransformException)e;
163                            }
164                            else {
165                                    throw new TransformException("Unhandled exception", e);
166                            }
167                    }
168    
169                    if (!load) {
170                            throw new TransformException(
171                                    "Unable to dynamically load transform script");
172                    }
173    
174                    return unsyncStringWriter.toString();
175            }
176    
177            protected long getArticleGroupId() {
178                    return GetterUtil.getLong(_tokens.get("article_group_id"));
179            }
180    
181            protected Company getCompany() throws Exception {
182                    if (_themeDisplay != null) {
183                            return _themeDisplay.getCompany();
184                    }
185    
186                    return CompanyLocalServiceUtil.getCompany(getCompanyId());
187            }
188    
189            protected long getCompanyGroupId() {
190                    if (_themeDisplay != null) {
191                            return _themeDisplay.getCompanyGroupId();
192                    }
193    
194                    return GetterUtil.getLong(_tokens.get("company_group_id"));
195            }
196    
197            protected long getCompanyId() {
198                    if (_themeDisplay != null) {
199                            return _themeDisplay.getCompanyId();
200                    }
201    
202                    return GetterUtil.getLong(_tokens.get("company_id"));
203            }
204    
205            protected Device getDevice() {
206                    if (_themeDisplay != null) {
207                            return _themeDisplay.getDevice();
208                    }
209    
210                    return UnknownDevice.getInstance();
211            }
212    
213            protected long getGroupId() {
214                    return getArticleGroupId();
215            }
216    
217            protected long getScopeGroupId() {
218                    return GetterUtil.getLong(_tokens.get("scope_group_id"));
219            }
220    
221            protected abstract TemplateContext getTemplateContext() throws Exception;
222    
223            protected String getTemplateId() {
224                    long companyGroupId = getCompanyGroupId();
225    
226                    String templateId = null;
227    
228                    if (_tokens != null) {
229                            templateId = _tokens.get("template_id");
230                    }
231    
232                    if (Validator.isNull(templateId)) {
233                            templateId = (String.valueOf(_contextObjects.get("template_id")));
234                    }
235    
236                    StringBundler sb = new StringBundler(5);
237    
238                    sb.append(getCompanyId());
239                    sb.append(StringPool.POUND);
240    
241                    if (companyGroupId > 0) {
242                            sb.append(companyGroupId);
243                    }
244                    else {
245                            sb.append(getGroupId());
246                    }
247    
248                    sb.append(StringPool.POUND);
249                    sb.append(templateId);
250    
251                    return sb.toString();
252            }
253    
254            protected abstract List<TemplateNode> getTemplateNodes(Element element)
255                    throws Exception;
256    
257            protected Map<String, Object> insertRequestVariables(Element element) {
258                    Map<String, Object> map = new HashMap<String, Object>();
259    
260                    if (element == null) {
261                            return map;
262                    }
263    
264                    for (Element childElement : element.elements()) {
265                            String name = childElement.getName();
266    
267                            if (name.equals("attribute")) {
268                                    Element nameElement = childElement.element("name");
269                                    Element valueElement = childElement.element("value");
270    
271                                    map.put(nameElement.getText(), valueElement.getText());
272                            }
273                            else if (name.equals("parameter")) {
274                                    Element nameElement = childElement.element("name");
275    
276                                    List<Element> valueElements = childElement.elements("value");
277    
278                                    if (valueElements.size() == 1) {
279                                            Element valueElement = valueElements.get(0);
280    
281                                            map.put(nameElement.getText(), valueElement.getText());
282                                    }
283                                    else {
284                                            List<String> values = new ArrayList<String>();
285    
286                                            for (Element valueElement : valueElements) {
287                                                    values.add(valueElement.getText());
288                                            }
289    
290                                            map.put(nameElement.getText(), values);
291                                    }
292                            }
293                            else if (childElement.elements().size() > 0) {
294                                    map.put(name, insertRequestVariables(childElement));
295                            }
296                            else {
297                                    map.put(name, childElement.getText());
298                            }
299                    }
300    
301                    return map;
302            }
303    
304            protected abstract boolean mergeTemplate(
305                            TemplateContext templateContext,
306                            UnsyncStringWriter unsyncStringWriter)
307                    throws Exception;
308    
309            protected void populateTemplateContext(TemplateContext templateContext)
310                    throws Exception {
311    
312                    templateContext.put("articleGroupId", getArticleGroupId());
313                    templateContext.put("company", getCompany());
314                    templateContext.put("companyId", getCompanyId());
315                    templateContext.put("device", getDevice());
316                    templateContext.put("groupId", getGroupId());
317    
318                    Locale locale = LocaleUtil.fromLanguageId(_languageId);
319    
320                    templateContext.put("locale", locale);
321    
322                    templateContext.put(
323                            "permissionChecker", PermissionThreadLocal.getPermissionChecker());
324                    templateContext.put("scopeGroupId", getScopeGroupId());
325                    templateContext.put("viewMode", _viewMode);
326            }
327    
328            private Map<String, Object> _contextObjects = new HashMap<String, Object>();
329            private String _languageId;
330            private String _script;
331            private ThemeDisplay _themeDisplay;
332            private Map<String, String> _tokens;
333            private String _viewMode;
334            private String _xml;
335    
336    }