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