001    /**
002     * Copyright (c) 2000-2013 Liferay, Inc. All rights reserved.
003     *
004     * The contents of this file are subject to the terms of the Liferay Enterprise
005     * Subscription License ("License"). You may not use this file except in
006     * compliance with the License. You can obtain a copy of the License by
007     * contacting Liferay, Inc. See the License for the specific language governing
008     * permissions and limitations under the License, including but not limited to
009     * distribution rights of the Software.
010     *
011     *
012     *
013     */
014    
015    package com.liferay.portlet.journal.util;
016    
017    import com.liferay.portal.kernel.log.Log;
018    import com.liferay.portal.kernel.log.LogFactoryUtil;
019    import com.liferay.portal.kernel.templateparser.BaseTransformerListener;
020    import com.liferay.portal.kernel.util.GetterUtil;
021    import com.liferay.portal.kernel.util.HtmlUtil;
022    import com.liferay.portal.kernel.util.StringPool;
023    import com.liferay.portal.kernel.util.StringUtil;
024    import com.liferay.portal.kernel.util.Validator;
025    import com.liferay.portal.kernel.xml.Document;
026    import com.liferay.portal.kernel.xml.Element;
027    import com.liferay.portal.kernel.xml.Node;
028    import com.liferay.portal.kernel.xml.SAXReaderUtil;
029    import com.liferay.portlet.dynamicdatamapping.util.DDMXMLUtil;
030    import com.liferay.portlet.journal.model.JournalArticle;
031    import com.liferay.portlet.journal.service.JournalArticleLocalServiceUtil;
032    
033    import java.util.List;
034    import java.util.Map;
035    
036    /**
037     * @author Brian Wing Shun Chan
038     * @author Tina Tian
039     */
040    public class ContentTransformerListener extends BaseTransformerListener {
041    
042            @Override
043            public String onScript(
044                    String script, String xml, String languageId,
045                    Map<String, String> tokens) {
046    
047                    if (_log.isDebugEnabled()) {
048                            _log.debug("onScript");
049                    }
050    
051                    return injectEditInPlace(xml, script);
052            }
053    
054            @Override
055            public String onXml(
056                    String xml, String languageId, Map<String, String> tokens) {
057    
058                    if (_log.isDebugEnabled()) {
059                            _log.debug("onXml");
060                    }
061    
062                    return replace(xml, tokens);
063            }
064    
065            protected String getDynamicContent(String xml, String elementName) {
066                    String content = null;
067    
068                    try {
069                            Document document = SAXReaderUtil.read(xml);
070    
071                            Element rootElement = document.getRootElement();
072    
073                            for (Element element : rootElement.elements()) {
074                                    String curElementName = element.attributeValue(
075                                            "name", StringPool.BLANK);
076    
077                                    if (curElementName.equals(elementName)) {
078                                            content = element.elementText("dynamic-content");
079    
080                                            break;
081                                    }
082                            }
083                    }
084                    catch (Exception e) {
085                            _log.error(e, e);
086                    }
087    
088                    return GetterUtil.getString(content);
089            }
090    
091            protected String injectEditInPlace(String xml, String script) {
092                    try {
093                            Document document = SAXReaderUtil.read(xml);
094    
095                            List<Node> nodes = document.selectNodes("//dynamic-element");
096    
097                            for (Node node : nodes) {
098                                    Element element = (Element)node;
099    
100                                    String name = GetterUtil.getString(
101                                            element.attributeValue("name"));
102                                    String type = GetterUtil.getString(
103                                            element.attributeValue("type"));
104    
105                                    if (!name.startsWith("reserved-") &&
106                                            (type.equals("text") || type.equals("text_area") ||
107                                             type.equals("text_box"))) {
108    
109                                            script = wrapEditInPlaceField(script, name, type, "data");
110                                            script = wrapEditInPlaceField(
111                                                    script, name, type, "getData()");
112                                    }
113                            }
114                    }
115                    catch (Exception e) {
116                            if (_log.isWarnEnabled()) {
117                                    _log.warn(e.getMessage());
118                            }
119                    }
120    
121                    return script;
122            }
123    
124            protected void replace(Element root, Map<String, String> tokens)
125                    throws Exception {
126    
127                    long articleGroupId = GetterUtil.getLong(
128                            tokens.get("article_group_id"));
129    
130                    for (Element element : root.elements()) {
131                            List<Element> dynamicContentElements = element.elements(
132                                    "dynamic-content");
133    
134                            for (Element dynamicContentElement : dynamicContentElements) {
135                                    String text = dynamicContentElement.getText();
136    
137                                    text = HtmlUtil.stripComments(text);
138                                    text = HtmlUtil.stripHtml(text);
139                                    text = text.trim();
140    
141                                    // [@articleId;elementName@]
142    
143                                    if (Validator.isNotNull(text) && (text.length() >= 7) &&
144                                            text.startsWith("[@") && text.endsWith("@]")) {
145    
146                                            text = text.substring(2, text.length() - 2);
147    
148                                            int pos = text.indexOf(";");
149    
150                                            if (pos != -1) {
151                                                    String articleId = text.substring(0, pos);
152                                                    String elementName = text.substring(pos + 1);
153    
154                                                    JournalArticle article =
155                                                            JournalArticleLocalServiceUtil.getArticle(
156                                                                    articleGroupId, articleId);
157    
158                                                    dynamicContentElement.clearContent();
159                                                    dynamicContentElement.addCDATA(
160                                                            getDynamicContent(
161                                                                    article.getContent(), elementName));
162                                            }
163                                    }
164    
165                                    // Make sure to point images to the full path
166    
167                                    else if ((text != null) &&
168                                                     text.startsWith("/image/journal/article?img_id")) {
169    
170                                            dynamicContentElement.setText(
171                                                    "@cdn_host@@root_path@" + text);
172                                    }
173                            }
174    
175                            replace(element, tokens);
176                    }
177            }
178    
179            /**
180             * Fill one article with content from another approved article. See the
181             * article DOCUMENTATION-INSTALLATION-BORLAND for a sample use case.
182             *
183             * @return the processed string
184             */
185            protected String replace(String xml, Map<String, String> tokens) {
186                    try {
187                            Document document = SAXReaderUtil.read(xml);
188    
189                            Element rootElement = document.getRootElement();
190    
191                            replace(rootElement, tokens);
192    
193                            xml = DDMXMLUtil.formatXML(document);
194                    }
195                    catch (Exception e) {
196                            if (_log.isWarnEnabled()) {
197                                    _log.warn(e.getMessage());
198                            }
199                    }
200    
201                    return xml;
202            }
203    
204            protected String wrapEditInPlaceField(
205                    String script, String name, String type, String call) {
206    
207                    String field = "$" + name + "." + call;
208                    String wrappedField =
209                            "<span class=\"journal-content-eip-" + type + "\" " +
210                                    "id=\"journal-content-field-name-" + name + "\">" + field +
211                                            "</span>";
212    
213                    return StringUtil.replace(
214                            script, "$editInPlace(" + field + ")", wrappedField);
215            }
216    
217            private static Log _log = LogFactoryUtil.getLog(
218                    ContentTransformerListener.class);
219    
220    }