001    /**
002     * Copyright (c) 2000-2012 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.journalcontent;
016    
017    import com.liferay.portal.kernel.log.Log;
018    import com.liferay.portal.kernel.log.LogFactoryUtil;
019    import com.liferay.portal.kernel.portlet.PortletLayoutListener;
020    import com.liferay.portal.kernel.portlet.PortletLayoutListenerException;
021    import com.liferay.portal.kernel.util.StringPool;
022    import com.liferay.portal.kernel.util.UniqueList;
023    import com.liferay.portal.kernel.util.Validator;
024    import com.liferay.portal.kernel.xml.Document;
025    import com.liferay.portal.kernel.xml.Element;
026    import com.liferay.portal.kernel.xml.SAXReaderUtil;
027    import com.liferay.portal.model.Group;
028    import com.liferay.portal.model.Layout;
029    import com.liferay.portal.model.PortletConstants;
030    import com.liferay.portal.service.GroupLocalServiceUtil;
031    import com.liferay.portal.service.LayoutLocalServiceUtil;
032    import com.liferay.portal.service.PortletLocalServiceUtil;
033    import com.liferay.portal.util.PortalUtil;
034    import com.liferay.portlet.PortletPreferencesFactoryUtil;
035    import com.liferay.portlet.dynamicdatamapping.model.DDMStructure;
036    import com.liferay.portlet.dynamicdatamapping.model.DDMTemplate;
037    import com.liferay.portlet.dynamicdatamapping.service.DDMTemplateLocalServiceUtil;
038    import com.liferay.portlet.journal.NoSuchArticleException;
039    import com.liferay.portlet.journal.NoSuchTemplateException;
040    import com.liferay.portlet.journal.model.JournalArticle;
041    import com.liferay.portlet.journal.service.JournalArticleLocalServiceUtil;
042    import com.liferay.portlet.journal.service.JournalContentSearchLocalServiceUtil;
043    import com.liferay.portlet.layoutconfiguration.util.xml.PortletLogic;
044    
045    import java.util.List;
046    
047    import javax.portlet.PortletPreferences;
048    
049    /**
050     * @author Brian Wing Shun Chan
051     * @author Raymond Augé
052     */
053    public class JournalContentPortletLayoutListener
054            implements PortletLayoutListener {
055    
056            public void onAddToLayout(String portletId, long plid)
057                    throws PortletLayoutListenerException {
058    
059                    if (_log.isDebugEnabled()) {
060                            _log.debug("Add " + portletId + " to layout " + plid);
061                    }
062    
063                    try {
064                            Layout layout = LayoutLocalServiceUtil.getLayout(plid);
065    
066                            PortletPreferences preferences =
067                                    PortletPreferencesFactoryUtil.getPortletSetup(
068                                            layout, portletId, StringPool.BLANK);
069    
070                            String articleId = preferences.getValue("articleId", null);
071    
072                            if (Validator.isNull(articleId)) {
073                                    return;
074                            }
075    
076                            JournalContentSearchLocalServiceUtil.updateContentSearch(
077                                    layout.getGroupId(), layout.isPrivateLayout(),
078                                    layout.getLayoutId(), portletId, articleId, true);
079                    }
080                    catch (Exception e) {
081                            throw new PortletLayoutListenerException(e);
082                    }
083            }
084    
085            public void onMoveInLayout(String portletId, long plid)
086                    throws PortletLayoutListenerException {
087    
088                    if (_log.isDebugEnabled()) {
089                            _log.debug("Move " + portletId + " from in " + plid);
090                    }
091            }
092    
093            public void onRemoveFromLayout(String portletId, long plid)
094                    throws PortletLayoutListenerException {
095    
096                    if (_log.isDebugEnabled()) {
097                            _log.debug("Remove " + portletId + " from layout " + plid);
098                    }
099    
100                    try {
101                            Layout layout = LayoutLocalServiceUtil.getLayout(plid);
102    
103                            PortletPreferences preferences =
104                                    PortletPreferencesFactoryUtil.getPortletSetup(
105                                            layout, portletId, StringPool.BLANK);
106    
107                            String articleId = preferences.getValue("articleId", null);
108    
109                            if (Validator.isNull(articleId)) {
110                                    return;
111                            }
112    
113                            JournalContentSearchLocalServiceUtil.deleteArticleContentSearch(
114                                    layout.getGroupId(), layout.isPrivateLayout(),
115                                    layout.getLayoutId(), portletId, articleId);
116    
117                            String[] runtimePortletIds = getRuntimePortletIds(
118                                    layout.getCompanyId(), layout.getGroupId(), articleId);
119    
120                            if (runtimePortletIds.length > 0) {
121                                    PortletLocalServiceUtil.deletePortlets(
122                                            layout.getCompanyId(), runtimePortletIds, layout.getPlid());
123                            }
124                    }
125                    catch (Exception e) {
126                            throw new PortletLayoutListenerException(e);
127                    }
128            }
129    
130            protected String getRuntimePortletId(String xml) throws Exception {
131                    Document document = SAXReaderUtil.read(xml);
132    
133                    Element rootElement = document.getRootElement();
134    
135                    String instanceId = rootElement.attributeValue("instance");
136                    String portletId = rootElement.attributeValue("name");
137    
138                    if (Validator.isNotNull(instanceId)) {
139                            portletId += PortletConstants.INSTANCE_SEPARATOR + instanceId;
140                    }
141    
142                    return portletId;
143            }
144    
145            protected String[] getRuntimePortletIds(
146                            long companyId, long scopeGroupId, String articleId)
147                    throws Exception {
148    
149                    Group group = GroupLocalServiceUtil.getCompanyGroup(companyId);
150    
151                    JournalArticle article = null;
152    
153                    try {
154                            article = JournalArticleLocalServiceUtil.getDisplayArticle(
155                                    scopeGroupId, articleId);
156                    }
157                    catch (NoSuchArticleException nsae) {
158                    }
159    
160                    if (article == null) {
161                            try {
162                                    article = JournalArticleLocalServiceUtil.getDisplayArticle(
163                                            group.getGroupId(), articleId);
164                            }
165                            catch (NoSuchArticleException nsae) {
166                                    return new String[0];
167                            }
168                    }
169    
170                    List<String> portletIds = getRuntimePortletIds(article.getContent());
171    
172                    if (Validator.isNotNull(article.getTemplateId())) {
173                            DDMTemplate ddmTemplate = null;
174    
175                            try {
176                                    ddmTemplate = DDMTemplateLocalServiceUtil.getTemplate(
177                                            scopeGroupId, PortalUtil.getClassNameId(DDMStructure.class),
178                                            article.getTemplateId());
179                            }
180                            catch (NoSuchTemplateException nste) {
181                                    ddmTemplate = DDMTemplateLocalServiceUtil.getTemplate(
182                                            group.getGroupId(),
183                                            PortalUtil.getClassNameId(DDMStructure.class),
184                                            article.getTemplateId());
185                            }
186    
187                            portletIds.addAll(getRuntimePortletIds(ddmTemplate.getScript()));
188                    }
189    
190                    return portletIds.toArray(new String[portletIds.size()]);
191            }
192    
193            protected List<String> getRuntimePortletIds(String content)
194                    throws Exception {
195    
196                    List<String> portletIds = new UniqueList<String>();
197    
198                    for (int index = 0;;) {
199                            index = content.indexOf(PortletLogic.OPEN_TAG, index);
200    
201                            if (index == -1) {
202                                    break;
203                            }
204    
205                            int close1 = content.indexOf(PortletLogic.CLOSE_1_TAG, index);
206                            int close2 = content.indexOf(PortletLogic.CLOSE_2_TAG, index);
207    
208                            int closeIndex = -1;
209    
210                            if ((close2 == -1) || ((close1 != -1) && (close1 < close2))) {
211                                    closeIndex = close1 + PortletLogic.CLOSE_1_TAG.length();
212                            }
213                            else {
214                                    closeIndex = close2 + PortletLogic.CLOSE_2_TAG.length();
215                            }
216    
217                            if (closeIndex == -1) {
218                                    break;
219                            }
220    
221                            portletIds.add(
222                                    getRuntimePortletId(content.substring(index, closeIndex)));
223    
224                            index = closeIndex;
225                    }
226    
227                    return portletIds;
228            }
229    
230            private static Log _log = LogFactoryUtil.getLog(
231                    JournalContentPortletLayoutListener.class);
232    
233    }